Added full VCV support + seseo + substitutes

In long:
* Full VCV support:
** Automatic "ny" instead of "nh";
** Automatic "s" instead of "z" (seseo);
** Automatic "i" instead of "y";
** Automatic "u" instead of "w";
* "n" for substitute-"ny" now works for CC-transitions between syllables;
* Necessary consonant clusters now always work, even with "i" and "u" (not tested yet with VCV due to a lack of voicebanks that support it);
* Made code more concise and cut the bloat.

Now the phonemizer should be mostly fully functioning as it should. Still, feedback is welcome.

--- OpenUtau.Plugin.Builtin/SpanishSyllableBasedPhonemizer.cs
+++ OpenUtau.Plugin.Builtin/SpanishSyllableBasedPhonemizer.cs
@@ -6,7 +6,7 @@
 using Serilog;

 namespace OpenUtau.Plugin.Builtin {
-  [Phonemizer("Spanish Syllable-Based Phonemizer", "ES SYL", "Lotte V")]
+    [Phonemizer("Spanish Syllable-Based Phonemizer", "ES SYL", "Lotte V")]
     public class SpanishSyllableBasedPhonemizer : SyllableBasedPhonemizer {

         /// <summary>
@@ -14,12 +14,10 @@
         /// Based on Teren000's reclist, but with some adjustments.
         /// (To be precise, it's based on Hoshino Hanami "Mariposa" Spanish.)
         /// Supports both CVVC and VCV if the voicebank has it.
-        /// There's some ValidateAlias support in this phonemizer, but it's not complete yet.
-        /// For now, typing ex. [n i n y o] (in the brackets) after the lyric "niño" should work.
-        /// (This currently does work automatically with ValidateAlias, but only for CVVC, not VCV.)
-        /// Same with typing [s] instead of [z] for voicebanks with "seseo" (Latin-American) accents.
-        /// I also want to add using "u" instead of "w" and "i" instead of "y" depending on the voicebank.
-        /// Ex. "kua" instead of "kwa".
+        /// Supports seseo ("s" instead of "z" if the voicebank doesn't have the latter).
+        /// It also substitutes "nh" for "ny" if the voicebank doesn't have the first.
+        /// Ít now also uses "i" instead of "y" and "u" instead of "w" depending on what the voicebank supports.
+        /// Now with full VCV support, including "consonant VCV" if the voicebank has either of them (ex. "l ba", "n da" but also "m bra" etc.).
         ///</summary>

         private readonly string[] vowels = "a,e,i,o,u".Split(',');
@@ -33,6 +31,8 @@

         private readonly string[] longConsonants = "ch,dz,s,sh,k,p,t,ts,z,l,m,n".Split(',');
         private readonly string[] burstConsonants = "ch,dz,j,k,p,r,t,ts".Split(',');
+        private readonly string[] notClusters = "dz,hh,ll,nh,sh,zz,zh".Split(',');
+        private readonly string[] specialClusters = "by,dy,fy,gy,hy,jy,ky,ly,my,py,ry,rry,sy,ty,vy,zy,bw,chw,dw,fw,gw,hw,jw,kw,lw,llw,mw,nw,pw,rw,rrw,sw,tw,vw,zw,bl,fl,gl,kl,pl,br,dr,fr,gr,kr,pr,tr".Split(',');

         protected override string[] GetVowels() => vowels;
         protected override string[] GetConsonants() => consonants;
@@ -62,20 +62,36 @@
             } else if (syllable.IsStartingCVWithOneConsonant) {
                 // TODO: move to config -CV or -C CV
                 var rc = $"- {cc[0]}{v}";
+                var src = $"- s{v}";
                 if (HasOto(rc, syllable.vowelTone)) {
                     basePhoneme = rc;
+                } else if (cc[0] == "z"
+                    && !HasOto(cc[0], syllable.vowelTone)
+                    && HasOto(src, syllable.vowelTone)
+                    && syllable.IsStartingCVWithOneConsonant) {
+                    basePhoneme = src;
                 } else {
                     basePhoneme = $"{cc[0]}{v}";
-                    if (consonants.Contains(cc[0])) {
-                    }
                 }
             } else if (syllable.IsStartingCVWithMoreThanOneConsonant) {
                 // try RCCV
                 var rvvc = $"- {string.Join("", cc)}{v}";
+                var syrvvc = $"- sy{v}";
+                var swrvvc = $"- sw{v}";
                 if (HasOto(rvvc, syllable.vowelTone)) {
                     basePhoneme = rvvc;
+                } else if (string.Join("", cc) == "zy"
+                    && !HasOto(string.Join("", cc), syllable.vowelTone)
+                    && HasOto(syrvvc, syllable.vowelTone)
+                    && syllable.IsStartingCVWithMoreThanOneConsonant) {
+                    basePhoneme = syrvvc;
+                } else if (string.Join("", cc) == "zw"
+                    && !HasOto(string.Join("", cc), syllable.vowelTone)
+                    && HasOto(syrvvc, syllable.vowelTone)
+                    && syllable.IsStartingCVWithMoreThanOneConsonant) {
+                    basePhoneme = swrvvc;
                 } else {
-                    basePhoneme = $"{cc.Last()}{v}";
+                    basePhoneme = $"{string.Join("", cc)}{v}";
                     // try RCC
                     // for (var i = cc.Length; i > 1; i--) {
                     // if (TryAddPhoneme(phonemes, syllable.tone, $"- {string.Join("", cc.Take(i))}")) {
@@ -99,16 +115,37 @@
             } else { // VCV
                 var vcv = $"{prevV} {cc[0]}{v}";
                 var vccv = $"{prevV} {string.Join("", cc)}{v}";
+                var nyvcv = $"{prevV} ny{v}";
+                var svcv = $"{prevV} s{v}";
+                var syvccv = $"{prevV} sy{v}";
+                var swvccv = $"{prevV} sw{v}";
+                var nvc = $"{prevV} n";
                 if (HasOto(vcv, syllable.vowelTone)
                     && (syllable.IsVCVWithOneConsonant)) {
                     basePhoneme = vcv;
+                } else if (cc[0] == "nh"
+                    && !HasOto(cc[0], syllable.vowelTone)
+                    && HasOto(nyvcv, syllable.vowelTone)
+                    && syllable.IsVCVWithOneConsonant) {
+                    basePhoneme = nyvcv;
+                } else if (cc[0] == "z"
+                    && !HasOto(cc[0], syllable.vowelTone)
+                    && HasOto(svcv, syllable.vowelTone)
+                    && syllable.IsVCVWithOneConsonant) {
+                    basePhoneme = svcv;
+                } else if (string.Join("", cc) == "zy"
+                    && !HasOto(string.Join("", cc), syllable.vowelTone)
+                    && HasOto(syvccv, syllable.vowelTone)
+                    && syllable.IsVCVWithMoreThanOneConsonant) {
+                    basePhoneme = syvccv;
+                } else if (string.Join("", cc) == "zw"
+                    && !HasOto(string.Join("", cc), syllable.vowelTone)
+                    && HasOto(swvccv, syllable.vowelTone)
+                    && syllable.IsVCVWithMoreThanOneConsonant) {
+                    basePhoneme = swvccv;
                 } else if (HasOto(vccv, syllable.vowelTone)
-                    && (syllable.IsVCVWithMoreThanOneConsonant)
-                    && string.Join("", cc) != "dz"
-                    && string.Join("", cc) != "nh"
-                    && string.Join("", cc) != "sh"
-                    && string.Join("", cc) != "zh"
-                    && string.Join("", cc) != "zz") {
+                    && syllable.IsVCVWithMoreThanOneConsonant
+                    && !notClusters.Contains(string.Join("", cc))) {
                     basePhoneme = vccv;
                 } else {
                     // try vcc
@@ -118,12 +155,7 @@
                             break;
                         }
                         var vcc = $"{prevV} {string.Join("", cc.Take(i))}";
-                        if (HasOto(vcc, syllable.tone)
-                            && string.Join("", cc.Take(i)) != "dz"
-                            && string.Join("", cc.Take(i)) != "nh"
-                            && string.Join("", cc.Take(i)) != "sh"
-                            && string.Join("", cc.Take(i)) != "zh"
-                            && string.Join("", cc.Take(i)) != "zz") {
+                        if (HasOto(vcc, syllable.tone) && !(notClusters.Contains(string.Join("", cc.Take(i))))) {
                             phonemes.Add(vcc);
                             firstC = i - 1;
                             break;
@@ -136,12 +168,7 @@
                             var ccv = $"{string.Join("", cc.Skip(i))}{v}";
                             var ccv2 = $"{string.Join(" ", cc.Skip(i))}{v}";
                             var ccv3 = $"{cc[0]} {string.Join("", cc.Skip(i))}{v}";
-                            if (HasOto(ccv, syllable.vowelTone)
-                                && string.Join("", cc.Skip(i)) != "dz"
-                                && string.Join("", cc.Skip(i)) != "nh"
-                                && string.Join("", cc.Skip(i)) != "sh"
-                                && string.Join("", cc.Skip(i)) != "zh"
-                                && string.Join("", cc.Skip(i)) != "zz") {
+                            if (HasOto(ccv, syllable.vowelTone) && !(notClusters.Contains(string.Join("", cc.Skip(i))))) {
                                 lastC = i;
                                 basePhoneme = ccv;
                                 break;
@@ -149,30 +176,49 @@
                                 lastC = i;
                                 basePhoneme = ccv2;
                                 break;
-                            } else if (HasOto(ccv3, syllable.vowelTone)
-                                && string.Join("", cc.Skip(i)) != "dz"
-                                && string.Join("", cc.Skip(i)) != "nh"
-                                && string.Join("", cc.Skip(i)) != "sh"
-                                && string.Join("", cc.Skip(i)) != "zh"
-                                && string.Join("", cc.Skip(i)) != "zz") {
+                            } else if (HasOto(ccv3, syllable.vowelTone) && !(notClusters.Contains(string.Join("", cc.Skip(i))))) {
                                 lastC = i;
                                 basePhoneme = ccv3;
                                 break;
                             }
                         }
                     }
+                    for (var i = firstC; i < cc.Length; i++) {
+                        var spccv = $"{string.Join("", cc.Skip(i))}{v}";
+                        var ccv3 = $"{cc[0]} {string.Join("", cc.Skip(i))}{v}";
+                        var syccv = $"{cc[0]} sy{v}";
+                        var swccv = $"{cc[0]} sw{v}";
+                        if (specialClusters.Contains(string.Join("", cc.Skip(i)))) {
+                            basePhoneme = spccv;
+                        }
+                        if (specialClusters.Contains(string.Join("", cc.Skip(i))) && HasOto(ccv3, syllable.vowelTone)) {
+                            basePhoneme = ccv3;
+                        }
+                        if (string.Join("", cc) == "zy"
+                            && !HasOto(string.Join("", cc), syllable.vowelTone)
+                            && HasOto(syccv, syllable.vowelTone)) {
+                            basePhoneme = syccv;
+                        }
+                        if (string.Join("", cc) == "zw"
+                            && !HasOto(string.Join("", cc), syllable.vowelTone)
+                            && HasOto(swccv, syllable.vowelTone)) {
+                            basePhoneme = swccv;
+                        }
+                    }
                 }
             }
             for (var i = firstC; i < lastC; i++) {
                 // we could use some CCV, so lastC is used
                 // we could use -CC so firstC is used
                 var cc1 = $"{cc[i]} {cc[i + 1]}";
+                var ncc1 = $"{cc[i]} n";
                 // if (!HasOto(cc1, syllable.tone))
                 // {
                 // cc1 = $"{cc[i]}{cc[i + 1]}";
                 // }
                 if (i + 1 < lastC) {
                     var cc2 = $"{cc[i + 1]} {cc[i + 2]}";
+                    var ncc2 = $"{cc[i + 1]} n";
                     // if (!HasOto(cc2, syllable.tone))
                     // {
                     // cc2 = $"{cc[i + 1]}{cc[i + 2]}";
@@ -185,15 +231,17 @@
                         i++;
                     } else if (TryAddPhoneme(phonemes, syllable.tone, cc1)) {
                         // like [V C1] [C1 C2] [C2 ..]
-                    } else {
+                    } else if (burstConsonants.Contains(cc[i]) && !specialClusters.Contains(string.Join("", cc.Skip(i)))) {
                         // like [V C1] [C1] [C2 ..]
                         TryAddPhoneme(phonemes, syllable.tone, cc[i], $"{cc[i]} -");
                     }
-                } else // if (!syllable.IsStartingCVWithMoreThanOneConsonant)
-                    {
+                } else {
                     // like [V C1] [C1 C2]  [C2 ..] or like [V C1] [C1 -] [C3 ..]
                     TryAddPhoneme(phonemes, syllable.tone, cc1);
-                    if (burstConsonants.Contains(cc[i]) && (!syllable.IsStartingCVWithMoreThanOneConsonant)) {
+                    if (cc[i + 1] == "nh" && !HasOto(cc[i + 1], syllable.tone)) {
+                        TryAddPhoneme(phonemes, syllable.tone, ncc1); ;
+                    }
+                    if (burstConsonants.Contains(cc[i]) && !syllable.IsStartingCVWithMoreThanOneConsonant && !specialClusters.Contains(string.Join("", cc.Skip(i)))) {
                         TryAddPhoneme(phonemes, syllable.tone, cc[i], $"{cc[i]} -");
                     }
                 }
@@ -203,83 +251,58 @@
             return phonemes;
         }

-        protected override List<string> ProcessEnding(Ending ending)
-        {
+        protected override List<string> ProcessEnding(Ending ending) {
             string[] cc = ending.cc;
             string v = ending.prevV;

             var phonemes = new List<string>();
             var vr = $"{v} -";
-            if (ending.IsEndingV && HasOto(vr, ending.tone))
-            {   // ending V
+            if (ending.IsEndingV && HasOto(vr, ending.tone)) {   // ending V
                 phonemes.Add(vr);
-            } else if (ending.IsEndingVCWithOneConsonant)
-            {   // ending VC
+            } else if (ending.IsEndingVCWithOneConsonant) {   // ending VC
                 var vcr = $"{v} {cc[0]}-";
-                if (HasOto(vcr, ending.tone))
-                {   // applies ending VC
+                if (HasOto(vcr, ending.tone)) {   // applies ending VC
                     phonemes.Add(vcr);
-                } else
-                {   // if no ending VC, then regular VC
+                } else {   // if no ending VC, then regular VC
                     phonemes.Add($"{v} {cc[0]}");
                 }
-            } else if (ending.IsEndingVCWithMoreThanOneConsonant)
-            {   // ending VCC (very rare, usually only occurs in words ending with "x")
+            } else if (ending.IsEndingVCWithMoreThanOneConsonant) {   // ending VCC (very rare, usually only occurs in words ending with "x")
                 var vccr = $"{v} {string.Join("", cc)}";
-                if (HasOto(vccr, ending.tone))
-                {   // applies ending VCC
+                if (HasOto(vccr, ending.tone)) {   // applies ending VCC
                     phonemes.Add(vccr);
-                } else if (!HasOto(vccr, ending.tone))
-                {   // if no ending VCC, then CC transitions
+                } else if (!HasOto(vccr, ending.tone)) {   // if no ending VCC, then CC transitions
                     phonemes.Add($"{v} {cc[0]}");
                     // all CCs except the first one are /C1C2/, the last one is /C1 C2-/
                     // but if there is no /C1C2/, we try /C1 C2-/, vise versa for the last one
-                    for (var i = 0; i < cc.Length - 1; i++)
-                    {
+                    for (var i = 0; i < cc.Length - 1; i++) {
                         var cc1 = $"{cc[i]} {cc[i + 1]}";
-                        if (i < cc.Length - 2)
-                        {
+                        if (i < cc.Length - 2) {
                             var cc2 = $"{cc[i + 1]} {cc[i + 2]}";
-                            if (HasOto(cc1, ending.tone) && HasOto(cc2, ending.tone))
-                            {
+                            if (HasOto(cc1, ending.tone) && HasOto(cc2, ending.tone)) {
                                 // like [C1 C2][C2 ...]
                                 phonemes.Add(cc1);
-                            } else if (TryAddPhoneme(phonemes, ending.tone, $"{cc[i + 1]} {cc[i + 2]}"))
-                            {
+                            } else if (TryAddPhoneme(phonemes, ending.tone, $"{cc[i + 1]} {cc[i + 2]}")) {
                                 // like [C1 C2][C2 ...]
-                            }
-                            else if (TryAddPhoneme(phonemes, ending.tone, $"{cc[i + 1]} {cc[i + 2]}-"))
-                            {
+                            } else if (TryAddPhoneme(phonemes, ending.tone, $"{cc[i + 1]} {cc[i + 2]}-")) {
                                 // like [C1 C2-][C3 ...]
                                 i++;
-                            }
-                            else
-                            {
+                            } else {
                                 // like [C1][C2 ...]
                                 TryAddPhoneme(phonemes, ending.tone, cc[i], $"{cc[i]} -");
                             }
-                        }
-                        else
-                        {
-                            if (TryAddPhoneme(phonemes, ending.tone, $"{cc[i]} {cc[i + 1]}-"))
-                            {
+                        } else {
+                            if (TryAddPhoneme(phonemes, ending.tone, $"{cc[i]} {cc[i + 1]}-")) {
                                 // like [C1 C2-]
                                 i++;
-                            }
-                            else if (TryAddPhoneme(phonemes, ending.tone, $"{cc[i]} {cc[i + 1]}"))
-                            {
+                            } else if (TryAddPhoneme(phonemes, ending.tone, $"{cc[i]} {cc[i + 1]}")) {
                                 // like [C1 C2][C2 -]
                                 TryAddPhoneme(phonemes, ending.tone, $"{cc[i + 1]} -", cc[i + 1]);
                                 i++;
-                            }
-                            else if (TryAddPhoneme(phonemes, ending.tone, cc1))
-                            {
+                            } else if (TryAddPhoneme(phonemes, ending.tone, cc1)) {
                                 // like [C1 C2][C2 -]
                                 TryAddPhoneme(phonemes, ending.tone, $"{cc[i + 1]} -", cc[i + 1]);
                                 i++;
-                            }
-                            else
-                            {
+                            } else {
                                 // like [C1][C2 -]
                                 TryAddPhoneme(phonemes, ending.tone, cc[i], $"{cc[i]} -");
                                 TryAddPhoneme(phonemes, ending.tone, $"{cc[i + 1]} -", cc[i + 1]);
@@ -293,23 +316,42 @@
         }

         protected override string ValidateAlias(string alias) {
+            foreach (var consonant in new[] { "j" }) {
+                alias = alias.Replace(consonant, "ll");
+            }
+            foreach (var consonant in specialClusters) {
+                alias = alias.Replace("w", "u");
+            }
+            foreach (var consonant in new[] { "z" }) {
+                alias = alias.Replace(consonant, "s");
+            }
+            foreach (var consonant in specialClusters) {
+                alias = alias.Replace("y", "i");
+            }
             foreach (var consonant in new[] { "nh" }) {
-                foreach (var vowel in vowels) {
-                    alias = alias.Replace(consonant + vowel, "ny" + vowel);
-                }
-            }
-            if (alias == "a nh" ||
-                alias == "e nh" ||
-                alias == "i nh" ||
-                alias == "o nh" ||
-                alias == "u nh" ||
-                alias == "l nh" ||
-                alias == "m nh") {
-                return alias.Replace("nh", "n");
-            }
-            foreach (var consonant in new[] { "z" }) {
-                foreach (var vowel in vowels) {
-                    alias = alias.Replace(consonant + vowel, "s" + vowel);
+                alias = alias.Replace(consonant, "ny");
+            }
+            foreach (var consonant in new[] { " nh" }) {
+                alias = alias.Replace(consonant, " n");
+            }
+            foreach (var vowel in vowels) {
+                foreach (var consonant in new[] { " ny" }) {
+                    return alias.Replace(vowel + consonant, vowel + " n");
+                }
+            }
+            foreach (var consonant1 in consonants) {
+                foreach (var consonant2 in new[] { " ny" }) {
+                    return alias.Replace(consonant1 + consonant2, consonant1 + " n");
+                }
+            }
+            foreach (var vowel in vowels) {
+                foreach (var consonant in new[] { " nh" }) {
+                    return alias.Replace(vowel + consonant, vowel + " n");
+                }
+            }
+            foreach (var consonant1 in consonants) {
+                foreach (var consonant2 in new[] { " nh" }) {
+                    return alias.Replace(consonant1 + consonant2, consonant1 + " n");
                 }
             }
             return alias;


removed Bridge access via AssetManager

removed Bridge access via AssetManager

--- PlayerProfilingAsset/PlayerProfilingAssetFunctionality.cs
+++ PlayerProfilingAsset/PlayerProfilingAssetFunctionality.cs
@@ -91,7 +91,7 @@
         /// <param name="fileId"> String containing the file identification. </param>
         internal void writeQuestionnaireDataToHTMLFile(QuestionnaireData qd, String fileId)
         {
-            IDataStorage ids = (IDataStorage)AssetManager.Instance.Bridge;
+            IDataStorage ids = PlayerProfilingAsset.Instance.getInterfaceFromAsset<IDataStorage>();
             if (ids != null)
             {
                 loggingPPA("Storing Questionnaire data to HTML File.");
@@ -109,8 +109,8 @@
         internal QuestionnaireData getQuestionnaireData()
         {
             string fileId = ((PlayerProfilingAssetSettings) getPPA().Settings).QuestionnaireDataXMLFileId;
-
-            IDataStorage ids = (IDataStorage)AssetManager.Instance.Bridge;
+
+            IDataStorage ids = PlayerProfilingAsset.Instance.getInterfaceFromAsset<IDataStorage>();
             if (ids != null)
             {
                 if (!ids.Exists(fileId))


Got print from sd card cancel to work.

Got print from sd card cancel to work.

--- PrinterCommunication/PrinterConnectionAndCommunication.cs
+++ PrinterCommunication/PrinterConnectionAndCommunication.cs
@@ -2045,19 +2045,23 @@
         {
             switch (CommunicationState)
             {
-                case CommunicationStates.PrintingToSd:
+                case CommunicationStates.PrintingFromSd:
                     using (TimedLock.Lock(this, "CancelingPrint"))
                     {
                         // get rid of all the gcode we have left to print
                         ClearQueuedGCode();
                         // let the process know we canceled not ended normaly.
-                        printWasCanceled = true;
+                        CommunicationState = CommunicationStates.Connected;
                         SendLineToPrinterNow("M25"); // : Pause SD print
                         SendLineToPrinterNow("M26"); // : Set SD position
+                        // never leave the extruder and the bed hot
+                        ReleaseMotors();
+                        TargetExtruderTemperature = 0;
+                        TargetBedTemperature = 0;
                     }
                     break;

-                case CommunicationStates.PrintingFromSd:
+                case CommunicationStates.PrintingToSd:
                     CommunicationState = CommunicationStates.Connected;
                     printWasCanceled = true;
                     break;


Added serial port radio buttons to scrollable widgets(did not implement right the first time)

--- PrinterControls/PrinterConnections/AddConnectionWidget.cs
+++ PrinterControls/PrinterConnections/AddConnectionWidget.cs
@@ -216,7 +216,7 @@
                 ConnectionControlContainer.AddChild(printerMakeContainer);
                 ConnectionControlContainer.AddChild(printerModelContainer);
                 ConnectionControlContainer.AddChild(comPortLabelWidget);
-                ConnectionControlContainer.AddChild(comPortContainer);
+				ConnectionControlContainer.AddChild(serialPortScroll);
                 ConnectionControlContainer.AddChild(baudRateLabel);
                 ConnectionControlContainer.AddChild(baudRateWidget);
                 ConnectionControlContainer.AddChild(enableAutoconnect);


Dispose of any stream, etc., that we have open

--- IndicoInterface.NET/AgendaLoader.cs
+++ IndicoInterface.NET/AgendaLoader.cs
@@ -51,13 +51,10 @@
         /// <returns>The parsed XML data. Throws an exception if it can't find what it needs</returns>
         public async Task<IndicoDataModel.iconf> GetFullConferenceData(AgendaInfo info)
         {
-            // Fetch the data
-
-            var data = await _fetcher.GetDataFromURL(GetAgendaFullXMLURL(info));
-
-            // Decode it
-
-            return _loader.Value.Deserialize(data) as IndicoDataModel.iconf;
+            using (var data = await _fetcher.GetDataFromURL(GetAgendaFullXMLURL(info)))
+            {
+                return _loader.Value.Deserialize(data) as IndicoDataModel.iconf;
+            }
         }

         /// <summary>


Web - Deprecate Lines ShowFieldDiv property

--- Signum.Web.Extensions/Files/FileLineHelper.cs
+++ Signum.Web.Extensions/Files/FileLineHelper.cs
@@ -29,7 +29,7 @@

             HtmlStringBuilder sb = new HtmlStringBuilder();

-            using (fileLine.ShowFieldDiv ? sb.Surround(new HtmlTag("div").Class("sf-field")) : null)
+            using (sb.Surround(new HtmlTag("div").Id(fileLine.ControlID).Class("sf-field")))
             using (fileLine.ValueFirst ? sb.Surround(new HtmlTag("div").Class("sf-value-first")) : null)
             {
                 sb.AddLine(new HtmlTag("link").Attrs(new { rel = "stylesheet", type = "text/css", href = RouteHelper.New().Content("~/Files/Content/SF_Files.css") }).ToHtmlSelf());


Stopped HttpRequest from using keep alives. fixes #5

--- SiteWarmer/SiteWarmer.Core/Comms/Requester.cs
+++ SiteWarmer/SiteWarmer.Core/Comms/Requester.cs
@@ -15,6 +15,7 @@
 		{
 			var request = (HttpWebRequest) WebRequest.Create(check.Url);
 			request.Timeout = 10000;
+			request.KeepAlive = false;
 			HttpWebResponse response = null;
 			try
 			{


Lehti

Lehti


fix EmailMessageBuilder

fix EmailMessageBuilder

--- Signum.Engine.Extensions/Mailing/EmailTemplateRenderer.cs
+++ Signum.Engine.Extensions/Mailing/EmailTemplateRenderer.cs
@@ -27,7 +27,7 @@
         {
             this.template = template;
             this.entity = entity;
-            this.model = model;
+            this.model = systemEmail;

             this.queryName = QueryLogic.ToQueryName(template.Query.Key);
             this.qd = QueryLogic.Queries.QueryDescription(queryName);


#112 - Implemented divorce

#112 - Implemented divorce

--- SoraBot/SoraBot.Bot/Modules/MarriageModule.cs
+++ SoraBot/SoraBot.Bot/Modules/MarriageModule.cs
@@ -23,6 +23,31 @@
             _marriageRepo = marriageRepo;
             _userService = userService;
             _interactiveService = interactiveService;
+        }
+
+        [Command("divorce")]
+        [Summary("Divorce a user by his UserId in case you cannot @ them anymore")]
+        public async Task DivorceId(ulong id)
+        {
+            await this.Divorce(id);
+        }
+
+        [Command("divorce")]
+        [Summary("Divorce a user by @mentioning them")]
+        public async Task DivorceMention(DiscordGuildUser user)
+        {
+            await this.Divorce(user.GuildUser.Id);
+        }
+
+        private async Task Divorce(ulong id)
+        {
+            if (!await _marriageRepo.TryDivorce(Context.User.Id, id))
+            {
+                await ReplyFailureEmbed("You are not married to that user");
+                return;
+            }
+
+            await ReplySuccessEmbed("You have been successfully divorced");
         }

         [Command("marry")]


Minor refactoring for TypeDiscovery.

Minor refactoring for TypeDiscovery.

--- BGC.Utilities/TypeDiscovery.cs
+++ BGC.Utilities/TypeDiscovery.cs
@@ -35,14 +35,17 @@

         private static IEnumerable<Type> GetTypeDiscoveryQuery(IEnumerable<Assembly> assembliesToSearch, Type consumingType, TypeDiscoveryMode mode)
         {
-            var query = from type in assembliesToSearch.SelectMany(a => TryGetExportedTypes(a)).ToList()
+            var query = from type in (from assembly in assembliesToSearch
+                                      from exportedTypes in TryGetExportedTypes(assembly)
+                                      where !assembly.IsDynamic
+                                      select exportedTypes)
                         let discoverableAttributes = type.GetCustomAttributes<TypeDiscoveryAttribute>()
                         let matchesConsumingType = (from typeDiscoveryAttribute in discoverableAttributes ?? Enumerable.Empty<TypeDiscoveryAttribute>()
-                                                    from declaredConsumingType in typeDiscoveryAttribute?.ConsumingTypes
+                                                    from declaredConsumingType in typeDiscoveryAttribute.ConsumingTypes
                                                     where declaredConsumingType.IsAssignableFrom(consumingType)
                                                     select declaredConsumingType).Any()
                         let isNonRestrictedType = discoverableAttributes?.Any(t => t.IsFreelyDiscoverable) ?? false
-                        where matchesConsumingType || (isNonRestrictedType && mode.HasFlag(TypeDiscoveryMode.Loose))
+                        where matchesConsumingType || (mode.HasFlag(TypeDiscoveryMode.Loose) && isNonRestrictedType)
                         select type;
             return query;
         }


Update IncrementProgram

Update IncrementProgram

--- Benchmarks/IncrementProgram.cs
+++ Benchmarks/IncrementProgram.cs
@@ -7,8 +7,8 @@
         public void Run()
         {
             var competition = new BenchmarkCompetition();
-            competition.AddTask("After", () => After());
-            competition.AddTask("Before", () => Before());
+            competition.AddTask("i++", () => After());
+            competition.AddTask("++i", () => Before());
             competition.Run();
         }


Add Torrent.PiecesAsHexString property

Add Torrent.PiecesAsHexString property

--- BencodeNET/Torrents/Torrent.cs
+++ BencodeNET/Torrents/Torrent.cs
@@ -4,6 +4,7 @@
 using System.IO;
 using System.Linq;
 using System.Text;
+using System.Text.RegularExpressions;
 using BencodeNET.Exceptions;
 using BencodeNET.IO;

@@ -128,8 +129,38 @@
         // TODO: Split into list of 20-byte hashes and rename to something appropriate?
         /// <summary>
         /// A concatenation of all 20-byte SHA1 hash values (one for each piece).
+        /// Use <see cref="PiecesAsHexString"/> to get/set this value as a hex string instead.
         /// </summary>
         public virtual byte[] Pieces { get; set; }
+
+        /// <summary>
+        /// Gets or sets <see cref="Pieces"/> from/to a hex string (without dashes), e.g. 1C115D26444AEF2A5E936133DCF8789A552BBE9F[...].
+        /// The length of the string must be a multiple of 40.
+        /// </summary>
+        public virtual string PiecesAsHexString
+        {
+            get
+            {
+                return BitConverter.ToString(Pieces).Replace("-", "");
+            }
+            set
+            {
+                if (value?.Length % 40 != 0)
+                    throw new ArgumentException("Value length must be a multiple of 40 (20 bytes as hex).");
+
+                if (Regex.IsMatch(value, "[^0-9A-F]"))
+                    throw new ArgumentException("Value must only contain hex characters (0-9 and A-F) and only uppercase.");
+
+                var bytes = new byte[value.Length/2];
+                for (var i = 0; i < bytes.Length; i++)
+                {
+                    var str = $"{value[i*2]}{value[i*2+1]}";
+                    bytes[i] = Convert.ToByte(str, 16);
+                }
+
+                Pieces = bytes;
+            }
+        }

         /// <summary>
         /// [optional] If set to true clients must only publish it's presence to the defined trackers.
@@ -209,7 +240,7 @@
             if (PieceSize > 0)
                 info[TorrentInfoFields.PieceLength] = (BNumber) PieceSize;

-            if (Pieces != null)
+            if (Pieces?.Length > 0)
                 info[TorrentInfoFields.Pieces] = new BString(Pieces, encoding);

             if (IsPrivate)


Cleanup

Cleanup

--- Source/EventFlow/Aggregates/AggregateStore.cs
+++ Source/EventFlow/Aggregates/AggregateStore.cs
@@ -93,18 +93,16 @@
             return aggregateUpdateResult.DomainEvents;
         }

-        public async Task<IAggregateUpdateResult<TResult>> UpdateAsync<TAggregate, TIdentity, TResult>(
+        public async Task<IAggregateUpdateResult<TExecutionResult>> UpdateAsync<TAggregate, TIdentity, TExecutionResult>(
             TIdentity id,
             ISourceId sourceId,
-            Func<TAggregate, CancellationToken, Task<TResult>> updateAggregate,
+            Func<TAggregate, CancellationToken, Task<TExecutionResult>> updateAggregate,
             CancellationToken cancellationToken)
             where TAggregate : IAggregateRoot<TIdentity>
             where TIdentity : IIdentity
-            where TResult : IExecutionResult
+            where TExecutionResult : IExecutionResult
         {
-            var result = default(TResult);
-
-            var domainEvents = await _transientFaultHandler.TryAsync(
+            var aggregateUpdateResult = await _transientFaultHandler.TryAsync(
                 async c =>
                 {
                     var aggregate = await LoadAsync<TAggregate, TIdentity>(id, c).ConfigureAwait(false);
@@ -116,31 +114,32 @@
                             $"Aggregate '{typeof(TAggregate).PrettyPrint()}' has already had operation '{sourceId}' performed");
                     }

-                    result = await updateAggregate(aggregate, c).ConfigureAwait(false);
-
-                    return await aggregate.CommitAsync(
+                    var result = await updateAggregate(aggregate, c).ConfigureAwait(false);
+                    var domainEvents = await aggregate.CommitAsync(
                         _eventStore,
                         _snapshotStore,
                         sourceId,
                         cancellationToken)
                         .ConfigureAwait(false);
+
+                    return new AggregateUpdateResult<TExecutionResult>(
+                        result,
+                        domainEvents);
                 },
                 Label.Named("aggregate-update"),
                 cancellationToken)
                 .ConfigureAwait(false);

-            if (domainEvents.Any())
+            if (aggregateUpdateResult.DomainEvents.Any())
             {
                 var domainEventPublisher = _resolver.Resolve<IDomainEventPublisher>();
                 await domainEventPublisher.PublishAsync(
-                    domainEvents,
+                    aggregateUpdateResult.DomainEvents,
                     cancellationToken)
                     .ConfigureAwait(false);
             }

-            return new AggregateUpdateResult<TResult>(
-                result,
-                domainEvents);
+            return aggregateUpdateResult;
         }

         public async Task<IReadOnlyCollection<IDomainEvent>> StoreAsync<TAggregate, TIdentity>(


Implement UnitTest for EditReport properties.

--- client/BlueMonkey/BlueMonkey.Model.Tests/EditReportTest.cs
+++ client/BlueMonkey/BlueMonkey.Model.Tests/EditReportTest.cs
@@ -25,6 +25,29 @@

             Assert.NotNull(actual.SelectableExpenses);
             Assert.False(actual.SelectableExpenses.Any());
+        }
+
+        [Fact]
+        public void NameProperty()
+        {
+            var expenseService = new Mock<IExpenseService>();
+            var actual = new EditReport(expenseService.Object);
+
+            Assert.PropertyChanged(actual, "Name", () => { actual.Name = "NewName"; });
+
+            Assert.Equal("NewName", actual.Name);
+        }
+
+        [Fact]
+        public void DateProperty()
+        {
+            var expenseService = new Mock<IExpenseService>();
+            var actual = new EditReport(expenseService.Object);
+
+            DateTime newDateTime = DateTime.Today + TimeSpan.FromDays(1);
+            Assert.PropertyChanged(actual, "Date", () => { actual.Date = newDateTime; });
+
+            Assert.Equal(newDateTime, actual.Date);
         }

         [Fact]


GSF.Core: Fixed issue in StringExtensions.ParseKeyValuePairs where certain character encodings would be decoded automatically by the parser.

git-tfs-id: [https://tfs.codeplex.com/tfs/TFS07]$/gsf/Main;C95286

--- Source/Libraries/GSF.Core/StringExtensions.cs
+++ Source/Libraries/GSF.Core/StringExtensions.cs
@@ -343,6 +343,7 @@
             string escapedKeyValueDelimiter = keyValueDelimiter.RegexEncode();
             string escapedStartValueDelimiter = startValueDelimiter.RegexEncode();
             string escapedEndValueDelimiter = endValueDelimiter.RegexEncode();
+            string backslashDelimiter = '\\'.RegexEncode();
             string[] elements;
             string key, unescapedValue;
             bool valueEscaped = false;
@@ -402,12 +403,17 @@
                         escapedValue.Append(escapedStartValueDelimiter);
                     else if (character == endValueDelimiter)
                         escapedValue.Append(escapedEndValueDelimiter);
+                    else if (character == '\\')
+                        escapedValue.Append(backslashDelimiter);
                     else
                         escapedValue.Append(character);
                 }
                 else
                 {
-                    escapedValue.Append(character);
+                    if (character == '\\')
+                        escapedValue.Append(backslashDelimiter);
+                    else
+                        escapedValue.Append(character);
                 }
             }

@@ -436,7 +442,8 @@
                         Replace(escapedParameterDelimiter, parameterDelimiter.ToString()).
                         Replace(escapedKeyValueDelimiter, keyValueDelimiter.ToString()).
                         Replace(escapedStartValueDelimiter, startValueDelimiter.ToString()).
-                        Replace(escapedEndValueDelimiter, endValueDelimiter.ToString());
+                        Replace(escapedEndValueDelimiter, endValueDelimiter.ToString()).
+                        Replace(backslashDelimiter, "\\");

                     // Add key/value pair to dictionary
                     if (ignoreDuplicateKeys)


Use Assert instead of null check because this class is internal.

--- Source/Magick.NET/Core/Drawables/PointInfo.cs
+++ Source/Magick.NET/Core/Drawables/PointInfo.cs
@@ -13,6 +13,7 @@
 //=================================================================================================

 using System.Collections.Generic;
+using System.Diagnostics;

 namespace ImageMagick
 {
@@ -42,8 +43,8 @@

     public void Dispose()
     {
-      if (_NativeInstance != null)
-        _NativeInstance.Dispose();
+      Debug.Assert(_NativeInstance != null);
+      _NativeInstance.Dispose();
     }
   }
 }


DataGrid support for Key.ImeProcessed #69

--- Source/PropertyTools.Wpf/DataGrid/DataGrid.cs
+++ Source/PropertyTools.Wpf/DataGrid/DataGrid.cs
@@ -1345,6 +1345,23 @@
         }

         /// <summary>
+        /// Invoked when an unhandled <see cref="E:System.Windows.Input.Keyboard.PreviewKeyDown" /> attached event reaches an element in its route that is derived from this class. Implement this method to add class handling for this event.
+        /// </summary>
+        /// <param name="e">The <see cref="T:System.Windows.Input.KeyEventArgs" /> that contains the event data.</param>
+        protected override void OnPreviewKeyDown(KeyEventArgs e)
+        {
+            base.OnPreviewKeyDown(e);
+            if (e.Key == Key.ImeProcessed)
+            {
+                var textEditor = this.currentEditor as TextBox;
+                if (textEditor != null && !textEditor.IsFocused)
+                {
+                    this.ShowTextBoxEditControl();
+                }
+            }
+        }
+
+        /// <summary>
         /// Handles mouse left button down events.
         /// </summary>
         /// <param name="e">The event arguments.</param>


Update index.cshtml

Update index.cshtml

--- site/index.cshtml
+++ site/index.cshtml
@@ -85,7 +85,7 @@
 	</form>
 	@if (show_chart)
 	{
-

+

 	}
 	else
 	{


Refresh collection view in DataGrid when the ItemsSource is not implementing notify collection changed events #135

--- Source/PropertyTools.Wpf/DataGrid/DataGrid.cs
+++ Source/PropertyTools.Wpf/DataGrid/DataGrid.cs
@@ -1759,8 +1759,7 @@
                 }
             }

-            // The collection view may need to be refreshed
-            this.CollectionView.Refresh();
+            this.RefreshIfRequired();

             return actualIndex;
         }
@@ -3190,7 +3189,7 @@
             var from = Math.Min(this.CurrentCell.Column, this.SelectionCell.Column);
             var to = Math.Max(this.CurrentCell.Column, this.SelectionCell.Column);
             this.Operator.DeleteColumns(this, from, to - from + 1);
-            this.UpdateGridContent();
+            this.RefreshIfRequired();

             var maxColumn = this.Columns > 0 ? this.Columns - 1 : 0;
             if (this.CurrentCell.Column > maxColumn)
@@ -3214,7 +3213,7 @@
             var from = Math.Min(this.CurrentCell.Row, this.SelectionCell.Row);
             var to = Math.Max(this.CurrentCell.Row, this.SelectionCell.Row);
             this.Operator.DeleteRows(this, from, to - from + 1);
-            this.UpdateGridContent();
+            this.RefreshIfRequired();

             var maxRow = this.Rows > 0 ? this.Rows - 1 : 0;
             if (this.CurrentCell.Row > maxRow)
@@ -3592,7 +3591,7 @@
             var to = Math.Max(this.CurrentCell.Column, this.SelectionCell.Column);

             this.Operator.InsertColumns(this, from, to - from + 1);
-            this.UpdateGridContent();
+            this.RefreshIfRequired();
         }

         /// <summary>
@@ -3603,7 +3602,18 @@
             var from = Math.Min(this.CurrentCell.Row, this.SelectionCell.Row);
             var to = Math.Max(this.CurrentCell.Row, this.SelectionCell.Row);
             this.Operator.InsertRows(this, from, to - from + 1);
-            this.UpdateGridContent();
+            this.RefreshIfRequired();
+        }
+
+        /// <summary>
+        /// Refreshes the collection view and updates the grid content, if the ItemsSource is not implementing INotifyCollectionChanged.
+        /// </summary>
+        private void RefreshIfRequired()
+        {
+            if (!(this.ItemsSource is INotifyCollectionChanged))
+            {
+                this.CollectionView.Refresh();
+            }
         }

         /// <summary>


mainline: fixed a bug in BroadcastService sample project

--- mainline/QuickStart/BroadcastService/BroadcastSession.cs
+++ mainline/QuickStart/BroadcastService/BroadcastSession.cs
@@ -17,7 +17,7 @@

         public new BroadcastServer AppServer
         {
-            get { return (BroadcastServer)this.AppServer; }
+            get { return (BroadcastServer)base.AppServer; }
         }

         public override void HandleExceptionalError(Exception e)


- Updated Mono update tool

- Updated Mono update tool

--- Source/Tools/Mono/UpdateProject/Transform2.cs
+++ Source/Tools/Mono/UpdateProject/Transform2.cs
@@ -174,6 +174,8 @@

 			// Create partial file
 			if (methodNodes.Count != 0) {
+				File.Copy(Path.Combine(root, file), Path.Combine(root, Path.GetFileNameWithoutExtension(file) + ".Original.cs"));
+
 				string partialMosaFile = Path.Combine(root, file.Insert(file.Length - 2, "Mosa.Partial."));
 				Console.WriteLine(">" + Path.GetFileName(partialMosaFile));
 				CreatePartialFileForMosa(lines, rootNode, usings, namespaces, partialMosaFile);
@@ -181,10 +183,10 @@
 				string partialMonoFile = Path.Combine(root, file.Insert(file.Length - 2, "Partial."));
 				Console.WriteLine(">" + Path.GetFileName(partialMonoFile));
 				CreatePartialFileForMono(lines, rootNode, usings, namespaces, partialMonoFile);
-			}
-
-			// Modify source file
-			CreateModifiedFile(lines, classNodes, methodNodes, Path.Combine(root, file));
+
+				// Modify source file
+				CreateModifiedFile(lines, classNodes, methodNodes, Path.Combine(root, file));
+			}
 		}

 		/// <summary>


BSD credentials support (disabled by default)

--- src/UnixNativeTransport.cs
+++ src/UnixNativeTransport.cs
@@ -42,6 +42,12 @@
 		[DllImport ("libc", SetLastError=true)]
 			protected static extern int setsockopt (int s, int optname, IntPtr optval, uint optlen);

+		[DllImport ("libc", SetLastError=true)]
+			public static extern int recvmsg (int s, IntPtr msg, int flags);
+
+		[DllImport ("libc", SetLastError=true)]
+			public static extern int sendmsg (int s, IntPtr msg, int flags);
+
 		public int Handle;

 		public UnixSocket (int handle)
@@ -98,6 +104,12 @@
 		}
 	}

+	public struct IOVector
+	{
+		public IntPtr Base;
+		public int Length;
+	}
+
 	public class UnixNativeTransport : Transport, IAuthenticator
 	{
 		protected UnixSocket socket;
@@ -117,11 +129,37 @@
 			Stream = new UnixStream ((int)socket.Handle);
 		}

-		//send peer credentials null byte. note that this might not be portable
-		//there are also selinux, BSD etc. considerations
-		public override void WriteCred ()
-		{
+		//send peer credentials null byte
+		//different platforms do this in different ways
+		unsafe public override void WriteCred ()
+		{
+#if HAVE_CMSGCRED
+			//null credentials byte
+			byte[] buf = new byte[] { 0 };
+
+			IOVector iov = new IOVector ();
+			fixed (byte *bufPtr = buf)
+				iov.Base = (IntPtr)bufPtr;
+			iov.Length = buf.Length;
+
+			msghdr msg = new msghdr ();
+			msg.msg_iov = &iov;
+			msg.msg_iovlen = 1;
+
+			cmsg cm = new cmsg ();
+			msg.msg_control = (IntPtr)(&cm);
+			msg.msg_controllen = (uint)sizeof (cmsg);
+			cm.hdr.cmsg_len = (uint)sizeof (cmsg);
+			cm.hdr.cmsg_level = 0xffff; //SOL_SOCKET
+			cm.hdr.cmsg_type = 0x03; //SCM_CREDS
+
+			int written = UnixSocket.sendmsg (socket.Handle, (IntPtr)(&msg), 0);
+			UnixMarshal.ThrowExceptionForLastErrorIf (written);
+			if (written != buf.Length)
+				throw new Exception ("Failed to write credentials");
+#else
 			Stream.WriteByte (0);
+#endif
 		}

 		public override string AuthString ()
@@ -173,4 +211,51 @@
 			return client;
 		}
 	}
+
+#if HAVE_CMSGCRED
+	/*
+	public struct msg
+	{
+		public IntPtr msg_next;
+		public long msg_type;
+		public ushort msg_ts;
+		short msg_spot;
+		IntPtr label;
+	}
+	*/
+
+	unsafe public struct msghdr
+	{
+		public IntPtr msg_name; //optional address
+		public uint msg_namelen; //size of address
+		public IOVector *msg_iov; //scatter/gather array
+		public int msg_iovlen; //# elements in msg_iov
+		public IntPtr msg_control; //ancillary data, see below
+		public uint msg_controllen; //ancillary data buffer len
+		public int msg_flags; //flags on received message
+	}
+
+	public struct cmsghdr
+	{
+		public uint cmsg_len; //data byte count, including header
+		public int cmsg_level; //originating protocol
+		public int cmsg_type; //protocol-specific type
+	}
+
+	unsafe public struct cmsgcred
+	{
+		public int cmcred_pid; //PID of sending process
+		public uint cmcred_uid; //real UID of sending process
+		public uint cmcred_euid; //effective UID of sending process
+		public uint cmcred_gid; //real GID of sending process
+		public short cmcred_ngroups; //number or groups
+		public fixed uint cmcred_groups[16]; //groups, CMGROUP_MAX
+	}
+
+	public struct cmsg
+	{
+		public cmsghdr hdr;
+		public cmsgcred cred;
+	}
+#endif
 }


Consolidate link functions

Consolidate link functions

--- SorasNerdDen/Services/HtmlHelpers/HtmlHelperExtensions.cs
+++ SorasNerdDen/Services/HtmlHelpers/HtmlHelperExtensions.cs
@@ -87,33 +87,17 @@
         /// <param name="helper">The HTML helper being used to render the text</param>
         /// <param name="url">The path to the page being linked to</param>
         /// <param name="text">The text to display in the link</param>
+        /// <param name="cssClass">The css class to apply to the link (null if not applicable)</param>
         /// <returns>A link to the specified location</returns>
-        public static IHtmlContent Link(this IHtmlHelper helper, string url, string text)
+        public static IHtmlContent Link(this IHtmlHelper helper, string url, string text, string cssClass = null)
         {
             bool external = url.StartsWith("http", StringComparison.InvariantCultureIgnoreCase);
             string currentUrl = helper.ViewContext.HttpContext.Request.Path.Value;
             bool isCurrentUrl = url == currentUrl;
             string relString = external ? " rel=\"noopener external\"" : null;
-            string aria = isCurrentUrl ? " area-current=\"page\"" : null;
-            return new HtmlString($"{text}");
-        }
-
-        ///
-        /// Places a link to another website (or the current website) on the page
-        ///
-        /// <param name="helper">The HTML helper being used to render the text</param>
-        /// <param name="url">The path to the page being linked to</param>
-        /// <param name="text">The text to display in the link</param>
-        /// <param name="cssClass">The css class to apply to the link (null if not applicable)</param>
-        /// <returns>A link to the specified location</returns>
-        public static IHtmlContent Link(this IHtmlHelper helper, string url, string text, string cssClass)
-        {
-            bool external = url.StartsWith("http", StringComparison.InvariantCultureIgnoreCase);
-            string currentUrl = helper.ViewContext.HttpContext.Request.Path.Value;
-            bool isCurrentUrl = url == currentUrl;
-            string relString = external ? " rel=\"noopener external\"" : null;
-            string aria = isCurrentUrl ? " area-current=\"page\"" : null;
-            return new HtmlString($"{text}");
+            string aria = isCurrentUrl ? " aria-current=\"page\"" : null;
+            string cssClassString = !string.IsNullOrWhiteSpace(cssClass) ? $" class=\"{cssClass}\"" : null;
+            return new HtmlString($"{text}");
         }

         ///
@@ -129,7 +113,7 @@
             string currentUrl = helper.ViewContext.HttpContext.Request.Path.Value;
             bool isCurrentUrl = url == currentUrl;
             string relString = external ? " rel=\"noopener external nofollow\"" : null;
-            string aria = isCurrentUrl ? " area-current=\"page\"" : null;
+            string aria = isCurrentUrl ? " aria-current=\"page\"" : null;
             return new HtmlString($"{helper.Encode(text)}");
         }


Revert change keeping invalid scripts. These are permitted.

--- Sensus.Shared/UI/PendingScriptsPage.cs
+++ Sensus.Shared/UI/PendingScriptsPage.cs
@@ -136,7 +136,7 @@

                 selectedScript.Submitting = false;

-                if (canceled || selectedScript.Valid == false)
+                if (canceled)
                 {
                     scriptList.SelectedItem = null;
                 }


* ShapeSerializer -- Use ReadField to read ShapeType

--- ShapefileSharp/Spec/ShapeSerializer.cs
+++ ShapefileSharp/Spec/ShapeSerializer.cs
@@ -17,8 +17,8 @@
             {
                 using (var reader = new BinaryReader(ms))
                 {
-                    reader.BaseStream.Position = ShpSpec.Record.Contents.ShapeType.Offset.Bytes; //TODO: Capture in spec class...
-                    ShapeType shapeType = (ShapeType)reader.ReadInt32();
+                    //TODO: Create ShapeType field?
+                    ShapeType shapeType = (ShapeType)reader.ReadField(ShpSpec.Record.Contents.ShapeType);

                     switch (shapeType)
                     {


testing factory

testing factory

Signed-off-by: Facundo Guini <099f2f72eab5268bf0323bc02ea1bf92ea56aa8e@chazki.com>

--- Shared/Framework/Db/DatabaseFactory.cs
+++ Shared/Framework/Db/DatabaseFactory.cs
@@ -11,14 +11,21 @@
         public static Database CreateDatabase(string name, string connectionString)
         {
             if(name.Length == 0)
-                throw new Exception("Database name not defined in DatabaseFactoryConfiguration section of web.config.");
+                throw new Exception("Database name not defined in the environment");
             try
             {
-                Type database = Type.GetType(name);
-                ConstructorInfo constructor = database.GetConstructor(new Type[] { });
-                Database dbInstance = (Database)constructor.Invoke(null);
-                dbInstance.connectionString = connectionString;
-                return dbInstance;
+                MSSQLServer db = new MSSQLServer();
+                // Type database = Type.GetType(name);
+                // Console.WriteLine("1");
+                // ConstructorInfo constructor = database.GetConstructor(new Type[] { });
+                // Console.WriteLine("2");
+                // Database dbInstance = (Database)constructor.Invoke(null);
+                // Console.WriteLine("3");
+                // dbInstance.connectionString = connectionString;
+                // Console.WriteLine("4");
+                db.connectionString = connectionString;
+                Console.WriteLine(connectionString);
+                return db;
             }
             catch(Exception ex)
             {


more dynamics in chain explosions

more dynamics in chain explosions

--- SimpleScene/Extra/SExplosionManager.cs
+++ SimpleScene/Extra/SExplosionManager.cs
@@ -170,6 +170,7 @@
             protected Vector3 _position;
             protected int _explosionsRemaining;
             protected int _explosionsActive = 0;
+            protected float _timeElapsedTotal = 0f;

             public ExplosionChainInfo(SExplosionManager em, SChainExplosionParameters cep,
                 Vector3 position, Vector3 velocity)
@@ -192,6 +193,7 @@
             public void update(float timeElapsed)
             {
                 _position += _velocity * timeElapsed;
+                _timeElapsedTotal += timeElapsed;
                 for (int i = 0; i < _delaysRemaining.Length; ++i) {
                     if (_explosionsRemaining > 0 && _delaysRemaining [i] <= 0f) {
                         float intensity = _chainParams.minIntensity
@@ -211,9 +213,12 @@
                                 + rand.NextDouble() * (_chainParams.spreadVelocityMax - _chainParams.spreadVelocityMin);
                         Vector3 vel = _velocity;
                         if (radialOffset.LengthFast > 0f) {
-                            vel += (float)spreadVelScale * radialOffset.Normalized();
+                            var radialDir = radialOffset.Normalized();
+                            var radialVelOffset = (float)spreadVelScale * radialDir;
+                            pos += radialVelOffset * _timeElapsedTotal;
+                            vel += radialVelOffset ;
                         }
-                        _em.showExplosion(_chainParams, intensity, pos, vel);
+                        _em.showExplosion(_chainParams, intensity, pos,  vel);

                         _delaysRemaining [i] = _chainParams.minDelay
                             + (float)rand.NextDouble() * (_chainParams.maxDelay - _chainParams.minDelay);


Add support for focusing intermediate slider-textbox component

--- osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs
+++ osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs
@@ -7,6 +7,7 @@
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.UserInterface;
+using osu.Framework.Input.Events;
 using osu.Framework.Localisation;
 using osu.Game.Graphics.UserInterfaceV2;
 using osu.Game.Overlays.Settings;
@@ -107,6 +108,14 @@
             Current.BindValueChanged(_ => updateState(), true);
         }

+        public override bool AcceptsFocus => true;
+
+        protected override void OnFocus(FocusEvent e)
+        {
+            base.OnFocus(e);
+            GetContainingInputManager().ChangeFocus(textBox);
+        }
+
         private void updateState()
         {
             if (Current.Value is T nonNullValue)


when checking status, give an until when the room is busy

--- Bot/Dialogs/CheckRoomDialog.cs
+++ Bot/Dialogs/CheckRoomDialog.cs
@@ -80,7 +80,7 @@
                         ? new { busy = false, room = room, Until = (DateTime?)null }
                         : (firstMeeting.Start > (_criteria.EndTime ?? now) && !firstMeeting.IsStarted)
                             ? new { busy = false, room = room, Until = (DateTime?)TimeZoneInfo.ConvertTime(firstMeeting.Start, tz)}
-                            : new { busy = true, room = room, Until = (DateTime?)null };
+                            : new { busy = true, room = room, Until = (DateTime?)TimeZoneInfo.ConvertTime(GetNextFree(meetings), tz) };

                 var until = result.Until.HasValue ? $"{result.Until:h:mm tt}" : "";
                 if (result.Until.HasValue)
@@ -127,5 +127,17 @@
             }
             context.Done(string.Empty);
         }
+
+        private DateTime GetNextFree(IEnumerable<RoomsService.RoomStatusResult.MeetingResult> meetings)
+        {
+            var time = meetings.First().End;
+            foreach (var meeting in meetings)
+            {
+                if (time < meeting.Start)
+                    return time;
+                time = meeting.End;
+            }
+            return time;
+        }
     }
 }


Fixing issue #2. Circular references are now detected correctly.

--- Sources/LightJson/Serialization/JsonWriter.cs
+++ Sources/LightJson/Serialization/JsonWriter.cs
@@ -12,7 +12,7 @@
 		private int indent;
 		private bool isNewLine;
 		private TextWriter writer;
-		private HashSet<JsonValue> renderedValues;
+		private HashSet<JsonValue> RenderingValues;

 		public string IndentString { get; set; }
 		public string SpacingString { get; set; }
@@ -33,7 +33,7 @@
 			this.indent = 0;
 			this.isNewLine = true;
 			this.writer = new StringWriter();
-			this.renderedValues = new HashSet<JsonValue>();
+			this.RenderingValues = new HashSet<JsonValue>();
 		}

 		private void Write(string text)
@@ -77,16 +77,21 @@
 			WriteLine();
 		}

-		private void AddRenderedValue(JsonValue value)
-		{
-			if (renderedValues.Contains(value))
+		private void AddRenderingValue(JsonValue value)
+		{
+			if (RenderingValues.Contains(value))
 			{
 				throw new CircularReferenceException();
 			}
 			else
 			{
-				renderedValues.Add(value);
-			}
+				RenderingValues.Add(value);
+			}
+		}
+
+		private void RemoveRenderingValue(JsonValue value)
+		{
+			RenderingValues.Remove(value);
 		}

 		private void Render(JsonValue value)
@@ -128,7 +133,7 @@

 		private void Render(JsonArray value)
 		{
-			AddRenderedValue(value);
+			AddRenderingValue(value);

 			WriteLine("[");

@@ -155,11 +160,13 @@

 			WriteLine();
 			Write("]");
+
+			RemoveRenderingValue(value);
 		}

 		private void Render(JsonObject value)
 		{
-			AddRenderedValue(value);
+			AddRenderingValue(value);

 			WriteLine("{");

@@ -189,6 +196,8 @@

 			WriteLine();
 			Write("}");
+
+			RemoveRenderingValue(value);
 		}

 		public string Serialize(JsonValue jsonValue)


Adds a call to RefreshSearch at the end of the Go button's click handler.

Closes headhunter45/BulkRenamer#2

--- BulkRenamer/MainWindow.xaml.cs
+++ BulkRenamer/MainWindow.xaml.cs
@@ -166,6 +166,8 @@
                     }
                 }
             }
+
+            RefreshSearch();
         }

         private void btnExport_Click(object sender, RoutedEventArgs e)


idk what

idk what

--- CSharpMath.Apple/Typesetting/AppleGlyphFinder.cs
+++ CSharpMath.Apple/Typesetting/AppleGlyphFinder.cs
@@ -30,6 +30,8 @@
           break;
         }
       }
+      var nsString = new NSString(str.Substring(start, end - start));
+
       var encoding = new UnicodeEncoding();
       var substring = str.Substring(start, end - start);
       var encodeSubstring = encoding.GetBytes(substring);


Weaken couplings between Th125Converter subclasses

--- ThScoreFileConverter/Models/Th125Converter.cs
+++ ThScoreFileConverter/Models/Th125Converter.cs
@@ -31,8 +31,7 @@
         private AllScoreData allScoreData = null;

         private Dictionary<
-            Chara,
-            Dictionary<(Th125.Level Level, int Scene), (string Path, IBestShotHeader Header)>> bestshots = null;
+            (Chara, Th125.Level Level, int Scene), (string Path, IBestShotHeader Header)> bestshots = null;

         public override string SupportedVersions
         {
@@ -76,12 +75,12 @@
         {
             return new List<IStringReplaceable>
             {
-                new ScoreReplacer(this),
-                new ScoreTotalReplacer(this),
-                new CardReplacer(this, hideUntriedCards),
-                new TimeReplacer(this),
-                new ShotReplacer(this, outputFilePath),
-                new ShotExReplacer(this, outputFilePath),
+                new ScoreReplacer(this.allScoreData.Scores),
+                new ScoreTotalReplacer(this.allScoreData.Scores),
+                new CardReplacer(this.allScoreData.Scores, hideUntriedCards),
+                new TimeReplacer(this.allScoreData.Status),
+                new ShotReplacer(this.bestshots, outputFilePath),
+                new ShotExReplacer(this.bestshots, this.allScoreData.Scores, outputFilePath),
             };
         }

@@ -110,20 +109,13 @@
                     if (this.bestshots == null)
                     {
                         this.bestshots =
-                            new Dictionary<Chara, Dictionary<(Th125.Level, int), (string, IBestShotHeader)>>(
-                                Enum.GetValues(typeof(Chara)).Length);
-                    }
-
-                    if (!this.bestshots.ContainsKey(chara))
-                    {
-                        this.bestshots.Add(
-                            chara,
-                            new Dictionary<(Th125.Level, int), (string, IBestShotHeader)>(Definitions.SpellCards.Count));
-                    }
-
-                    var key = (header.Level, header.Scene);
-                    if (!this.bestshots[chara].ContainsKey(key))
-                        this.bestshots[chara].Add(key, (outputFile.Name, header));
+                            new Dictionary<(Chara, Th125.Level, int), (string, IBestShotHeader)>(
+                                Enum.GetValues(typeof(Chara)).Length * Definitions.SpellCards.Count);
+                    }
+
+                    var key = (chara, header.Level, header.Scene);
+                    if (!this.bestshots.ContainsKey(key))
+                        this.bestshots.Add(key, (outputFile.Name, header));

                     Lzss.Extract(input, decoded);

@@ -273,7 +265,7 @@

             private readonly MatchEvaluator evaluator;

-            public ScoreReplacer(Th125Converter parent)
+            public ScoreReplacer(IReadOnlyList<IScore> scores)
             {
                 this.evaluator = new MatchEvaluator(match =>
                 {
@@ -286,7 +278,7 @@
                     if (!Definitions.SpellCards.ContainsKey(key))
                         return match.ToString();

-                    var score = parent.allScoreData.Scores.FirstOrDefault(elem =>
+                    var score = scores.FirstOrDefault(elem =>
                         (elem != null) && (elem.Chara == chara) && elem.LevelScene.Equals(key));

                     switch (type)
@@ -358,7 +350,7 @@
             private readonly MatchEvaluator evaluator;

             [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1119:StatementMustNotUseUnnecessaryParenthesis", Justification = "Reviewed.")]
-            public ScoreTotalReplacer(Th125Converter parent)
+            public ScoreTotalReplacer(IReadOnlyList<IScore> scores)
             {
                 this.evaluator = new MatchEvaluator(match =>
                 {
@@ -374,24 +366,18 @@
                     {
                         case 1:     // total score
                             return Utils.ToNumberString(
-                                parent.allScoreData.Scores.Sum(
-                                    score => triedAndSucceeded(score) ? (long)score.HighScore : 0L));
+                                scores.Sum(score => triedAndSucceeded(score) ? score.HighScore : 0L));
                         case 2:     // total of bestshot scores
                             return Utils.ToNumberString(
-                                parent.allScoreData.Scores.Sum(
-                                    score => isTarget(score) ? (long)score.BestshotScore : 0L));
+                                scores.Sum(score => isTarget(score) ? score.BestshotScore : 0L));
                         case 3:     // total of num of shots
                             return Utils.ToNumberString(
-                                parent.allScoreData.Scores.Sum(
-                                    score => isTarget(score) ? score.TrialCount : 0));
+                                scores.Sum(score => isTarget(score) ? score.TrialCount : 0));
                         case 4:     // total of num of shots for the first success
                             return Utils.ToNumberString(
-                                parent.allScoreData.Scores.Sum(
-                                    score => triedAndSucceeded(score) ? (long)score.FirstSuccess : 0L));
+                                scores.Sum(score => triedAndSucceeded(score) ? score.FirstSuccess : 0L));
                         case 5:     // num of succeeded scenes
-                            return parent.allScoreData.Scores
-                                .Count(triedAndSucceeded)
-                                .ToString(CultureInfo.CurrentCulture);
+                            return scores.Count(triedAndSucceeded).ToString(CultureInfo.CurrentCulture);
                         default:    // unreachable
                             return match.ToString();
                     }
@@ -412,7 +398,7 @@

             private readonly MatchEvaluator evaluator;

-            public CardReplacer(Th125Converter parent, bool hideUntriedCards)
+            public CardReplacer(IReadOnlyList<IScore> scores, bool hideUntriedCards)
             {
                 this.evaluator = new MatchEvaluator(match =>
                 {
@@ -426,8 +412,7 @@

                     if (hideUntriedCards)
                     {
-                        var score = parent.allScoreData.Scores.FirstOrDefault(
-                            elem => (elem != null) && elem.LevelScene.Equals(key));
+                        var score = scores.FirstOrDefault(elem => (elem != null) && elem.LevelScene.Equals(key));
                         if (score == null)
                             return "??????????";
                     }
@@ -450,11 +435,11 @@

             private readonly MatchEvaluator evaluator;

-            public TimeReplacer(Th125Converter parent)
+            public TimeReplacer(IStatus status)
             {
                 this.evaluator = new MatchEvaluator(match =>
                 {
-                    return new Time(parent.allScoreData.Status.TotalPlayTime * 10, false).ToLongString();
+                    return new Time(status.TotalPlayTime * 10, false).ToLongString();
                 });
             }

@@ -472,7 +457,9 @@

             private readonly MatchEvaluator evaluator;

-            public ShotReplacer(Th125Converter parent, string outputFilePath)
+            public ShotReplacer(
+                IReadOnlyDictionary<(Chara, Th125.Level, int), (string Path, IBestShotHeader Header)> bestshots,
+                string outputFilePath)
             {
                 this.evaluator = new MatchEvaluator(match =>
                 {
@@ -480,13 +467,11 @@
                     var level = Parsers.LevelParser.Parse(match.Groups[2].Value);
                     var scene = int.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture);

-                    var key = (level, scene);
-                    if (!Definitions.SpellCards.ContainsKey(key))
+                    if (!Definitions.SpellCards.ContainsKey((level, scene)))
                         return match.ToString();

                     if (!string.IsNullOrEmpty(outputFilePath) &&
-                        parent.bestshots.TryGetValue(chara, out var bestshots) &&
-                        bestshots.TryGetValue(key, out var bestshot))
+                        bestshots.TryGetValue((chara, level, scene), out var bestshot))
                     {
                         var relativePath = new Uri(outputFilePath)
                             .MakeRelativeUri(new Uri(bestshot.Path)).OriginalString;
@@ -552,7 +537,10 @@

             private readonly MatchEvaluator evaluator;

-            public ShotExReplacer(Th125Converter parent, string outputFilePath)
+            public ShotExReplacer(
+                IReadOnlyDictionary<(Chara, Th125.Level, int), (string Path, IBestShotHeader Header)> bestshots,
+                IReadOnlyList<IScore> scores,
+                string outputFilePath)
             {
                 this.evaluator = new MatchEvaluator(match =>
                 {
@@ -566,8 +554,7 @@
                         return match.ToString();

                     if (!string.IsNullOrEmpty(outputFilePath) &&
-                        parent.bestshots.TryGetValue(chara, out var bestshots) &&
-                        bestshots.TryGetValue(key, out var bestshot))
+                        bestshots.TryGetValue((chara, level, scene), out var bestshot))
                     {
                         IScore score;
                         IEnumerable<string> detailStrings;
@@ -585,10 +572,8 @@
                             case 5:     // slow rate
                                 return Utils.Format("{0:F6}%", bestshot.Header.SlowRate);
                             case 6:     // date & time
-                                score = parent.allScoreData.Scores.FirstOrDefault(elem =>
-                                    (elem != null) &&
-                                    (elem.Chara == chara) &&
-                                    elem.LevelScene.Equals(key));
+                                score = scores.FirstOrDefault(elem =>
+                                    (elem != null) && (elem.Chara == chara) && elem.LevelScene.Equals(key));
                                 if (score == null)
                                     return "----/--/-- --:--:--";
                                 return new DateTime(1970, 1, 1)


And now for all commands, not just adds

And now for all commands, not just adds

--- Sitecore.Courier/FileCommandsFilter.cs
+++ Sitecore.Courier/FileCommandsFilter.cs
@@ -36,6 +36,14 @@
     /// <returns>The filtered command.</returns>
     public ICommand FilterCommand(ICommand command)
     {
+      if (command == null)
+        return null;
+
+      if (ForceOverwrites)
+      {
+          command.CollisionBehavior = CollisionBehavior.Force;
+      }
+
       if (!(command is AddFolderCommand) && !(command is AddFileCommand))
       {
         return command;
@@ -44,11 +52,6 @@
       if (this.excludedFolders.Any(folder => command.EntityPath.Replace("\\", string.Empty).StartsWith(folder)))
       {
         return null;
-      }
-
-      if (ForceOverwrites)
-      {
-          command.CollisionBehavior = CollisionBehavior.Force;
       }

       return command;


Fix broken test

Fix broken test


Additional test, serialize/deserialize two persons

--- Src/Aktores.Core.Tests/Communication/InputChannelTests.cs
+++ Src/Aktores.Core.Tests/Communication/InputChannelTests.cs
@@ -169,6 +169,60 @@
         }

         [TestMethod]
+        public void WriteAndReadTwoPersonObjects()
+        {
+            var person = new Person()
+            {
+                Id = 1,
+                FirstName = "John",
+                LastName = "Smith"
+            };
+
+            var person2 = new Person()
+            {
+                Id = 2,
+                FirstName = "Adam",
+                LastName = "Pearson"
+            };
+
+            MemoryStream stream = new MemoryStream();
+            OutputChannel output = new OutputChannel(new BinaryWriter(stream));
+            output.Write(person);
+            output.Write(person2);
+
+            stream.Seek(0, SeekOrigin.Begin);
+
+            InputChannel channel = new InputChannel(new BinaryReader(stream));
+
+            var ts = channel.Read();
+
+            Assert.IsNotNull(ts);
+            Assert.IsInstanceOfType(ts, typeof(TypeSerializer));
+
+            var result = channel.Read();
+
+            Assert.IsNotNull(result);
+            Assert.IsInstanceOfType(result, typeof(Person));
+
+            var newperson = (Person)result;
+
+            Assert.AreEqual(person.Id, newperson.Id);
+            Assert.AreEqual(person.FirstName, newperson.FirstName);
+            Assert.AreEqual(person.LastName, newperson.LastName);
+
+            result = channel.Read();
+
+            Assert.IsNotNull(result);
+            Assert.IsInstanceOfType(result, typeof(Person));
+
+            var newperson2 = (Person)result;
+
+            Assert.AreEqual(person2.Id, newperson2.Id);
+            Assert.AreEqual(person2.FirstName, newperson2.FirstName);
+            Assert.AreEqual(person2.LastName, newperson2.LastName);
+        }
+
+        [TestMethod]
         public void ReadInvalidData()
         {
             MemoryStream stream = new MemoryStream();


There are two possible root causes to this test failure.

1. File IO error.
2. Incorrect options given.

#2 will have some explainatory output, while #1 will not.

Adding logging to determine which case is present.
 (changeset 1346801)

--- Src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs
+++ Src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs
@@ -6525,11 +6525,13 @@
             var csc = new MockCSharpCompiler(null, sourceDir.Path, args);
             var outWriter = new StringWriter(CultureInfo.InvariantCulture);
             var exitCode = csc.Run(outWriter);
+            var output = outWriter.ToString();

             var expectedExitCode = expectedErrorCount > 0 ? 1 : 0;
-            Assert.Equal(expectedExitCode, exitCode);
-
-            var output = outWriter.ToString();
+            Assert.True(
+                expectedExitCode == exitCode,
+                string.Format("Expected exit code to be '{0}' was '{1}'.\nOutput:\n{2}", expectedExitCode, exitCode, output));
+
             Assert.DoesNotContain("hidden", output);

             if (expectedInfoCount == 0)


add GetItem

add GetItem

--- DapCore/registry/Registry.cs
+++ DapCore/registry/Registry.cs
@@ -23,6 +23,10 @@
             Factory = Factory.NewBuiltinFactory();
         }

+        public Item GetItem(string path) {
+            return Get<Item>(path);
+        }
+
         public Item AddItem(string path, string type) {
             if (!Has(path)) {
                 Aspect aspect = Factory.FactoryAspect(this, path, type);


Add implementation for app resizing in basicPage.cs

--- wallabag/wallabag.Shared/Common/basicPage.cs
+++ wallabag/wallabag.Shared/Common/basicPage.cs
@@ -1,5 +1,7 @@
-using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
 using Windows.UI.Xaml.Navigation;
+using Windows.UI.Core;

 namespace wallabag.Common
 {
@@ -10,10 +12,22 @@

         public basicPage()
         {
+            this.Loaded += basicPage_Loaded;
+            this.Unloaded += basicPage_Unloaded;
             this.navigationHelper = new NavigationHelper(this);
             this.navigationHelper.LoadState += navigationHelper_LoadState;
             this.navigationHelper.SaveState += navigationHelper_SaveState;
         }
+
+        void basicPage_Loaded(object sender, RoutedEventArgs e) { Window.Current.SizeChanged += Window_SizeChanged; }
+        void basicPage_Unloaded(object sender, RoutedEventArgs e) { Window.Current.SizeChanged -= Window_SizeChanged; }
+
+        void Window_SizeChanged(object sender, WindowSizeChangedEventArgs e)
+        {
+            ChangedSize(e);
+        }
+
+        protected virtual void ChangedSize(WindowSizeChangedEventArgs e) { }

         void navigationHelper_SaveState(object sender, SaveStateEventArgs e)
         {


Fixed simulation speed mismatch between C and S

--- UnityProject/Assets/Scripts/Shuttles/ShuttleController.cs
+++ UnityProject/Assets/Scripts/Shuttles/ShuttleController.cs
@@ -77,8 +77,11 @@
 	public MatrixState ClientState => clientState;
 	///client's transform, can get dirty/predictive
 	private MatrixState clientState;
+	/// Is only present to match server's flight routines
+	private MatrixState clientTargetState;
 	private bool isMovingClient => clientState.IsMoving && clientState.Speed > 0f;
 	private bool isRotatingClient => transform.rotation.eulerAngles.z != clientState.Orientation.degree;
+	private bool ClientPositionsMatch => clientTargetState.Position == clientState.Position;

 	//editor (global) values
 	/// Initial flying direction from editor
@@ -183,7 +186,7 @@
 		} else {
 			serverTargetState.Speed = absoluteValue;
 		}
-		//todo: to send or not to send speed updates when not moving? I think not
+		//do not send speed updates when not moving
 		if ( isMovingServer ) {
 			RequestNotify();
 		}
@@ -208,6 +211,7 @@

 		//Lerp
 		if ( clientState.Position != transform.position ) {
+			//todo: is that extra lerp really needed?
 			float distance = Vector3.Distance( clientState.Position, transform.position );
 			//Activate warp speed if object gets too far away or have to rotate
 			bool shouldWarp = distance > 2 || isRotatingClient;
@@ -216,7 +220,6 @@
 		}
 	}

-//FIXME: server speed issues!
 	[Server]
 	private void CheckMovementServer()
 	{
@@ -263,13 +266,30 @@
 	public void UpdateClientState( MatrixState newState )
 	{
 		clientState = newState;
+		clientTargetState = newState;
 	}

 	///predictive perpetual flying
 	private void SimulateStateMovement()
 	{
-		clientState.Position +=
-			(Vector3) clientState.Direction * clientState.Speed * Time.deltaTime;
+//		clientState.Position +=
+//			(Vector3) clientState.Direction * clientState.Speed * Time.deltaTime;
+		//<<too easy, ends up being faster than server
+		//ClientState lerping to its target tile
+		if ( !ClientPositionsMatch ) {
+			clientState.Position =
+				Vector3.MoveTowards( clientState.Position,
+					clientTargetState.Position,
+					clientState.Speed * Time.deltaTime );
+			TryNotifyPlayers();
+		}
+		if ( isMovingClient && !isRotatingClient ) {
+			Vector3Int goal = Vector3Int.RoundToInt( clientState.Position + ( Vector3 ) clientTargetState.Direction );
+				//keep moving
+				if ( ClientPositionsMatch ) {
+					clientTargetState.Position = goal;
+				}
+		}
 	}

 	/// Schedule notification for the next ServerPositionsMatch


Null check player alerts

Null check player alerts


fixed bug with highlighting of terms with brackets '(' and ').

--- VS/CSHARP/asm-dude-vsix/SyntaxHighlighting/AsmTokenTag.cs
+++ VS/CSHARP/asm-dude-vsix/SyntaxHighlighting/AsmTokenTag.cs
@@ -45,7 +45,7 @@
         [Import]
         private AsmDudeTools _asmDudeTools = null;

-        static char[] splitChars = { ' ', ',', '\t', '+', '-', '*', '[', ']' }; //TODO remove this to AsmDudeTools
+        static char[] splitChars = { ' ', ',', '\t', '+', '-', '*', '[', ']', '(', ')' }; //TODO remove this to AsmDudeTools

         internal AsmTokenTagger(ITextBuffer buffer) {
             this._buffer = buffer;


Extended <MockBuilder> allowing construction with arguments.

--- Source/Core.Testing/Moq/MockBuilder.cs
+++ Source/Core.Testing/Moq/MockBuilder.cs
@@ -32,16 +32,16 @@
 {
     public class MockBuilder
     {
-        public static Mock<T> CreateMock<T>()
+        public static Mock<T> CreateMock<T>(params object[] args)
             where T : class
         {
-            return new Mock<T>();
+            return new Mock<T>(args);
         }

-        public static Mock<T> CreateStub<T>()
+        public static Mock<T> CreateStub<T>(params object[] args)
             where T : class
         {
-            return new Mock<T>
+            return new Mock<T>(args)
             {
                 CallBase = true
             };


set user id of telemetry services at startup

--- src/CSharpClient/Bit.CSharpClient.Rest/ViewModel/Extensions/ContainerBuilderExtensions.cs
+++ src/CSharpClient/Bit.CSharpClient.Rest/ViewModel/Extensions/ContainerBuilderExtensions.cs
@@ -30,7 +30,7 @@
             containerBuilder.Register(context => new RefitSettings
             {
                 ContentSerializer = context.Resolve<IContentSerializer>()
-            });
+            }).PreserveExistingDefaults();

             return containerBuilder;
         }
@@ -40,7 +40,7 @@
             if (containerBuilder == null)
                 throw new ArgumentNullException(nameof(containerBuilder));

-            containerBuilder.Register(c => RestService.For<TService>(c.Resolve<HttpClient>(), c.Resolve<RefitSettings>()));
+            containerBuilder.Register(c => RestService.For<TService>(c.Resolve<HttpClient>(), c.Resolve<RefitSettings>())).PreserveExistingDefaults();

             return containerBuilder;
         }
@@ -59,6 +59,23 @@
                 throw new ArgumentNullException(nameof(containerBuilder));

             containerBuilder.RegisterType<TSecurityService>().As<ISecurityService>().SingleInstance().PropertiesAutowired(PropertyWiringOptions.PreserveSetValues).PreserveExistingDefaults();
+
+            containerBuilder.RegisterBuildCallback(async scope =>
+            {
+                try
+                {
+                    ISecurityService securityService = scope.Resolve<ISecurityService>();
+                    if (await securityService.IsLoggedInAsync().ConfigureAwait(false))
+                    {
+                        ITelemetryService allTelemetryServices = scope.Resolve<IEnumerable<ITelemetryService>>().All();
+                        allTelemetryServices.SetUserId((await securityService.GetBitJwtToken(default).ConfigureAwait(false)).UserId);
+                    }
+                }
+                catch (Exception exp)
+                {
+                    scope.Resolve<IExceptionHandler>().OnExceptionReceived(exp);
+                }
+            });

             return containerBuilder;
         }
@@ -81,7 +98,7 @@
             containerBuilder.Register(c => c.Resolve<IHttpClientFactory>().CreateClient(ContractKeys.DefaultHttpClientName))
                 .PreserveExistingDefaults();

-            containerBuilder.Register(context => new IPollyHttpResponseMessagePolicyFactory(request => DefaultRestFactories.BuildHttpPollyPolicy(request)));
+            containerBuilder.Register(context => new IPollyHttpResponseMessagePolicyFactory(request => DefaultRestFactories.BuildHttpPollyPolicy(request))).PreserveExistingDefaults();

             return services.AddHttpClient(ContractKeys.DefaultHttpClientName)
                 .ConfigureHttpClient((serviceProvider, httpClient) =>


Don't make changes that cause def assignment problems.

--- src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCodeRefactoringProvider.cs
+++ src/Features/CSharp/Portable/UsePatternMatching/CSharpIsAndCastCodeRefactoringProvider.cs
@@ -11,10 +11,8 @@
 using Microsoft.CodeAnalysis.CSharp.Extensions;
 using Microsoft.CodeAnalysis.CSharp.Syntax;
 using Microsoft.CodeAnalysis.Editing;
-using Microsoft.CodeAnalysis.PooledObjects;
 using Microsoft.CodeAnalysis.Shared.Extensions;
 using Microsoft.CodeAnalysis.Shared.Utilities;
-using Roslyn.Utilities;

 namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching
 {
@@ -22,6 +20,7 @@
     internal class CSharpIsAndCastCodeRefactoringProvider : CodeRefactoringProvider
     {
         private const string CS0165 = nameof(CS0165); // Use of unassigned local variable 's'
+        private static readonly SyntaxAnnotation s_referenceAnnotation = new SyntaxAnnotation();

         public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
         {
@@ -71,15 +70,15 @@
             var matches = new HashSet<CastExpressionSyntax>();
             AddMatches(container, expr, type, matches);

-            if (container is StatementSyntax containingStatement &&
-                containingStatement.Parent is BlockSyntax block)
-            {
-                var statementIndex = block.Statements.IndexOf(containingStatement);
-                for (int i = statementIndex + 1, n = block.Statements.Count; i < n; i++)
-                {
-                    AddMatches(block.Statements[i], expr, type, matches);
-                }
-            }
+            //if (container is StatementSyntax containingStatement &&
+            //    containingStatement.Parent is BlockSyntax block)
+            //{
+            //    var statementIndex = block.Statements.IndexOf(containingStatement);
+            //    for (int i = statementIndex + 1, n = block.Statements.Count; i < n; i++)
+            //    {
+            //        AddMatches(block.Statements[i], expr, type, matches);
+            //    }
+            //}

             if (matches.Count == 0)
             {
@@ -95,14 +94,20 @@

             // Now, go and actually try to make the change.  This will allow us to see all the
             // locations that we updated to see if that caused an error.
-            var annotationToCastExpression = new Dictionary<SyntaxAnnotation, CastExpressionSyntax>();
-            var updatedDocument = await ReplaceMatchesAsync(
-                document, root, isExpression, localName,
-                matches, annotationToCastExpression, cancellationToken).ConfigureAwait(false);
-
-            // Remove any replacements that caused problems.
-            await RemoveMatchesThatCauseDefiniteAssignmentErrorsAsync(
-                updatedDocument, matches, annotationToCastExpression, cancellationToken).ConfigureAwait(false);
+            var tempMatches = new HashSet<CastExpressionSyntax>();
+            foreach (var castExpression in matches.ToArray())
+            {
+                tempMatches.Add(castExpression);
+                var updatedDocument = await ReplaceMatchesAsync(
+                    document, root, isExpression, localName, tempMatches, cancellationToken).ConfigureAwait(false);
+                tempMatches.Clear();
+
+                var causesError = await ReplacementCausesErrorAsync(updatedDocument, cancellationToken).ConfigureAwait(false);
+                if (causesError)
+                {
+                    matches.Remove(castExpression);
+                }
+            }

             if (matches.Count == 0)
             {
@@ -111,51 +116,24 @@

             context.RegisterRefactoring(new MyCodeAction(
                 c => ReplaceMatchesAsync(
-                    document, root, isExpression, localName, matches,
-                    annotationToCastExpressionOpt: null, cancellationToken: c)));
-        }
-
-        private async Task RemoveMatchesThatCauseDefiniteAssignmentErrorsAsync(
-            Document updatedDocument, HashSet<CastExpressionSyntax> matches,
-            Dictionary<SyntaxAnnotation, CastExpressionSyntax> annotationToCastExpression,
-            CancellationToken cancellationToken)
+                    document, root, isExpression, localName, matches, c)));
+        }
+
+        private async Task<bool> ReplacementCausesErrorAsync(
+            Document updatedDocument, CancellationToken cancellationToken)
         {
             var semanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
             var root = await updatedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

-            foreach (var (annotation, castExpression) in annotationToCastExpression)
-            {
-                var currentNode = root.GetAnnotatedNodes(annotation).Single();
-                var diagnostics = semanticModel.GetDiagnostics(currentNode.Span, cancellationToken);
-
-                if (diagnostics.Any(d => d.Id == CS0165))
-                {
-                    matches.Remove(castExpression);
-                }
-            }
-        }
-
-        //private async Task<bool> ReplacementCausesDefiniteAssignmentErrorAsync(
-        //    Document document, SyntaxNode root, BinaryExpressionSyntax isExpression,
-        //    string localName, CastExpressionSyntax castExpression, CancellationToken cancellationToken)
-        //{
-        //    var matches = new HashSet<CastExpressionSyntax> { castExpression };
-
-        //    var updatedDocument = await ReplaceMatchesAsync(
-        //        document, root, isExpression, localName, matches, cancellationToken).ConfigureAwait(false);
-
-        //    var updatedSemanticModel = await updatedDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
-        //    var updatedRoot = await updatedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
-        //    var updatedReference = updatedRoot.GetAnnotatedNodes(s_referenceAnnotation).Single();
-
-        //    var diagnostics = updatedSemanticModel.GetDiagnostics(updatedReference.Span);
-        //    return diagnostics.Any(d => d.Id == CS0165);
-        //}
+            var currentNode = root.GetAnnotatedNodes(s_referenceAnnotation).Single();
+            var diagnostics = semanticModel.GetDiagnostics(currentNode.Span, cancellationToken);
+
+            return diagnostics.Any(d => d.Id == CS0165);
+        }

         private Task<Document> ReplaceMatchesAsync(
             Document document, SyntaxNode root, BinaryExpressionSyntax isExpression,
             string localName, HashSet<CastExpressionSyntax> matches,
-            Dictionary<SyntaxAnnotation, CastExpressionSyntax> annotationToCastExpressionOpt,
             CancellationToken cancellationToken)
         {
             var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
@@ -175,13 +153,10 @@
             var localReference = SyntaxFactory.IdentifierName(localName);
             foreach (var castExpression in matches)
             {
-                var annotation = new SyntaxAnnotation();
-                annotationToCastExpressionOpt?.Add(annotation, castExpression);
-
                 editor.ReplaceNode(
                     castExpression.WalkUpParentheses(),
                     localReference.WithTriviaFrom(castExpression)
-                                  .WithAdditionalAnnotations(annotation));
+                                  .WithAdditionalAnnotations(s_referenceAnnotation));
             }

             var changedRoot = editor.GetChangedRoot();


Brace matching for json constructors.

Brace matching for json constructors.

--- src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService_Json.cs
+++ src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService_Json.cs
@@ -79,13 +79,13 @@
             var ch = virtualChar.Value;
             if (caretOnLeft)
             {
-                return ch == '{' || ch == '['
+                return ch == '{' || ch == '[' || ch == '('
                     ? FindBraceHighlights(document, tree, ch)
                     : ImmutableArray<DocumentHighlights>.Empty;
             }
             else
             {
-                return ch == '}' || ch == ']'
+                return ch == '}' || ch == ']' || ch == ')'
                     ? FindBraceHighlights(document, tree, ch)
                     : ImmutableArray<DocumentHighlights>.Empty;
             }
@@ -99,6 +99,7 @@
             {
                 case JsonObjectNode obj: return Create(document, obj.OpenBraceToken, obj.CloseBraceToken);
                 case JsonArrayNode array: return Create(document, array.OpenBracketToken, array.CloseBracketToken);
+                case JsonConstructorNode cons: return Create(document, cons.OpenParenToken, cons.CloseParenToken);
             }

             return default;
@@ -121,13 +122,14 @@
         {
             switch (node)
             {
-                case JsonArrayNode array when
-                    array.OpenBracketToken.VirtualChars.Contains(ch) || array.CloseBracketToken.VirtualChars.Contains(ch):
+                case JsonArrayNode array when Matches(array.OpenBracketToken, array.CloseBracketToken, ch):
                     return array;
-
-                case JsonObjectNode obj when
-                    obj.OpenBraceToken.VirtualChars.Contains(ch) || obj.CloseBraceToken.VirtualChars.Contains(ch):
+
+                case JsonObjectNode obj when Matches(obj.OpenBraceToken, obj.CloseBraceToken, ch):
                     return obj;
+
+                case JsonConstructorNode cons when Matches(cons.OpenParenToken, cons.CloseParenToken, ch):
+                    return cons;
             }

             foreach (var child in node)
@@ -144,5 +146,8 @@

             return null;
         }
+
+        private bool Matches(JsonToken openToken, JsonToken closeToken, VirtualChar ch)
+            => openToken.VirtualChars.Contains(ch) || closeToken.VirtualChars.Contains(ch);
     }
 }


Assert basePaths was not null

Assert basePaths was not null

--- src/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext/CoreCLR/CorePsAssemblyLoadContext.cs
+++ src/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext/CoreCLR/CorePsAssemblyLoadContext.cs
@@ -57,6 +57,11 @@
         internal PowerShellAssemblyLoadContext(string basePaths)
         {
             #region Validation
+            if (string.IsNullOrEmpty(basePaths))
+            {
+                throw new ArgumentNullException("basePaths");
+            }
+
             this.basePaths = basePaths.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
             for (int i = 0; i < this.basePaths.Length; i++)
             {
@@ -606,6 +611,11 @@
         /// </summary>
         public static void SetPowerShellAssemblyLoadContext([MarshalAs(stringType)]string basePaths)
         {
+            if (string.IsNullOrEmpty(basePaths))
+            {
+                throw new ArgumentNullException("basePaths");
+            }
+
             if (PSAsmLoadContext == null)
             {
                 PSAsmLoadContext = new PowerShellAssemblyLoadContext(basePaths);


redirect to V2 API in case book marked page

--- src/SFA.DAS.ProviderApprenticeshipsService.Web/Controllers/ManageApprenticesController.cs
+++ src/SFA.DAS.ProviderApprenticeshipsService.Web/Controllers/ManageApprenticesController.cs
@@ -49,11 +49,9 @@
         [Route("{hashedApprenticeshipId}/edit", Name = "EditApprovedApprentice")]
         [RoleAuthorize(Roles = nameof(RoleNames.HasAccountOwnerPermission))]
         [OutputCache(CacheProfile = "NoCache")]
-        public async Task<ActionResult> Edit(long providerid, string hashedApprenticeshipId)
-        {
-            var model = await _orchestrator.GetApprenticeshipForEdit(providerid, hashedApprenticeshipId);
-            ViewBag.ApprenticeshipProgrammes = model.ApprenticeshipProgrammes;
-            return View(model.Apprenticeship);
+        public ActionResult Edit(long providerid, string hashedApprenticeshipId)
+        {
+            return Redirect(_providerUrlHelper.ProviderCommitmentsLink($"{providerid}/apprentices/{hashedApprenticeshipId}/edit"));
         }

         [HttpPost]


Delete TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs