public static IEnumerable <R> JoinSimilar <T, S, R>(this List <T> outer, List <S> inner, Func <T, string> outerKeySelector, Func <S, string> innerKeySelector, Func <T, S, int, R> resultSelector) where T : notnull where S : notnull { StringDistance sd = new StringDistance(); Dictionary <Tuple <T, S>, int> distances = (from o in outer from i in inner select KeyValuePair.Create(Tuple.Create(o, i), sd.LevenshteinDistance(outerKeySelector(o), innerKeySelector(i)))).ToDictionary(); while (distances.Count > 0) { var kvp = distances.WithMin(a => a.Value); var tuple = kvp.Key; distances.RemoveRange(distances.Keys.Where(a => a.Item1.Equals(tuple.Item1) || a.Item2.Equals(tuple.Item2)).ToList()); outer.Remove(tuple.Item1); inner.Remove(tuple.Item2); yield return(resultSelector(tuple.Item1, tuple.Item2, kvp.Value)); } }
WithDescription <V>?TryGetValue(string input) { var exact = dictionary.TryGetC(input); if (exact != null) { return(exact); } var sd = new StringDistance(); var best = dictionary.Keys.WithMin(a => sd.LevenshteinDistance(input.ToLowerInvariant(), a.ToLowerInvariant())); if (sd.LevenshteinDistance(input.ToLowerInvariant(), best.ToLowerInvariant()) <= 2) { if (SafeConsole.Ask($"Did you mean '{best}'?")) { return(dictionary.GetOrThrow(best)); } } return(null); }
public DiffLogResult GetOperationDiffLog(string id) { var operationLog = Database.Retrieve<OperationLogEntity>(PrimaryKey.Parse(id, typeof(OperationLogEntity))); var logs = DiffLogLogic.OperationLogNextPrev(operationLog); StringDistance sd = new StringDistance(); var prevFinal = logs.Min?.Mixin<DiffLogMixin>().FinalState; string nextInitial = logs.Max != null ? logs.Max.Mixin<DiffLogMixin>().InitialState : operationLog.Target.Exists() ? GetDump(operationLog.Target) : null; return new DiffLogResult { prev = logs.Min?.ToLite(), diffPrev = prevFinal == null ? null : sd.DiffText(prevFinal, operationLog.Mixin<DiffLogMixin>().InitialState), diff = sd.DiffText(operationLog.Mixin<DiffLogMixin>().InitialState, operationLog.Mixin<DiffLogMixin>().FinalState), diffNext = nextInitial == null ? null : sd.DiffText(operationLog.Mixin<DiffLogMixin>().FinalState, nextInitial), next = logs.Max?.ToLite(), }; }
public static T MostSimilar <T>(this IEnumerable <T> collection, Func <T, string> stringSelector, string pattern) { StringDistance sd = new StringDistance(); return(collection.WithMin(item => sd.LevenshteinDistance(stringSelector(item), pattern))); }
internal static SqlPreCommand SynchronizeWordTemplate(Replacements replacements, WordTemplateEntity template, StringDistance sd) { try { if (template.Template == null) return null; var queryName = QueryLogic.ToQueryName(template.Query.Key); QueryDescription qd = DynamicQueryManager.Current.QueryDescription(queryName); Console.Clear(); SafeConsole.WriteLineColor(ConsoleColor.White, "WordTemplate: " + template.Name); Console.WriteLine(" Query: " + template.Query.Key); var file = template.Template.Retrieve(); try { using (var memory = new MemoryStream()) { memory.WriteAllBytes(file.BinaryFile); using (WordprocessingDocument document = WordprocessingDocument.Open(memory, true)) { Dump(document, "0.Original.txt"); var parser = new WordTemplateParser(document, qd, template.SystemWordTemplate.ToType()); parser.ParseDocument(); Dump(document, "1.Match.txt"); parser.CreateNodes(); Dump(document, "2.BaseNode.txt"); parser.AssertClean(); SyncronizationContext sc = new SyncronizationContext { ModelType = template.SystemWordTemplate.ToType(), QueryDescription = qd, Replacements = replacements, StringDistance = sd, HasChanges = false, Variables = new ScopedDictionary<string, ValueProviderBase>(null), }; foreach (var root in document.RecursivePartsRootElements()) { foreach (var node in root.Descendants<BaseNode>().ToList()) { node.Synchronize(sc); } } if (!sc.HasChanges) return null; Dump(document, "3.Synchronized.txt"); var variables = new ScopedDictionary<string, ValueProviderBase>(null); foreach (var root in document.RecursivePartsRootElements()) { foreach (var node in root.Descendants<BaseNode>().ToList()) { node.RenderTemplate(variables); } } Dump(document, "4.Rendered.txt"); } file.AllowChange = true; file.BinaryFile = memory.ToArray(); using (replacements.WithReplacedDatabaseName()) return Schema.Current.Table<FileEntity>().UpdateSqlSync(file, comment: "WordTemplate: " + template.Name); } } catch (TemplateSyncException ex) { if (ex.Result == FixTokenResult.SkipEntity) return null; if (ex.Result == FixTokenResult.DeleteEntity) return SqlPreCommandConcat.Combine(Spacing.Simple, Schema.Current.Table<WordTemplateEntity>().DeleteSqlSync(template), Schema.Current.Table<FileEntity>().DeleteSqlSync(file)); if (ex.Result == FixTokenResult.ReGenerateEntity) return Regenerate(template, replacements); throw new InvalidOperationException("Unexcpected {0}".FormatWith(ex.Result)); } finally { Console.Clear(); } } catch (Exception e) { return new SqlPreCommandSimple("-- Exception in {0}: {1}".FormatWith(template.BaseToString(), e.Message)); } }
static SqlPreCommand Schema_Synchronize_Tokens(Replacements replacements) { if (AvoidSynchronize) return null; StringDistance sd = new StringDistance(); var emailTemplates = Database.Query<WordTemplateEntity>().ToList(); SqlPreCommand cmd = emailTemplates.Select(uq => SynchronizeWordTemplate(replacements, uq, sd)).Combine(Spacing.Double); return cmd; }
public List <DiffPair <List <DiffPair <string> > > > DiffText(string?textOld, string?textNew, bool lineEndingDifferences = true) { textOld = textOld ?? ""; textNew = textNew ?? ""; var linesOld = lineEndingDifferences ? textOld.Split('\n') : textOld.Lines(); var linesNew = lineEndingDifferences ? textNew.Split('\n') : textNew.Lines(); List <DiffPair <string> > diff = this.Diff(linesOld, linesNew); List <IGrouping <bool, DiffPair <string> > > groups = diff.GroupWhenChange(a => a.Action == DiffAction.Equal).ToList(); StringDistance sd = new StringDistance(); return(groups.SelectMany(g => { if (g.Key) { return g.Select(dp => new DiffPair <List <DiffPair <string> > >(DiffAction.Equal, new List <DiffPair <string> > { dp })); } var removed = g.Where(a => a.Action == DiffAction.Removed).Select(a => a.Value).ToArray(); var added = g.Where(a => a.Action == DiffAction.Added).Select(a => a.Value).ToArray(); var choices = this.LevenshteinChoices <string>(removed, added, weight: c => { if (c.Type == ChoiceType.Add) { return c.Added.Length; } if (c.Type == ChoiceType.Remove) { return c.Removed.Length; } var distance = sd.LevenshteinDistance(c.Added, c.Removed); return distance * 2; }); return choices.Select(c => { if (c.Type == ChoiceType.Add) { return new DiffPair <List <DiffPair <string> > >(DiffAction.Added, new List <DiffPair <string> > { new DiffPair <string>(DiffAction.Added, c.Added) }); } if (c.Type == ChoiceType.Remove) { return new DiffPair <List <DiffPair <string> > >(DiffAction.Removed, new List <DiffPair <string> > { new DiffPair <string>(DiffAction.Removed, c.Removed) }); } var diffWords = sd.DiffWords(c.Removed, c.Added); return new DiffPair <List <DiffPair <string> > >(DiffAction.Equal, diffWords); }); }).ToList()); }
public static string GetDefaultModuleName(Type[] selected, string solutionName) { StringDistance sd = new StringDistance(); string name = null; foreach (var item in selected) { if (name == null) name = item.FullName.RemovePrefix(solutionName + ".Entities"); else { int startName, rubbish; int length = sd.LongestCommonSubstring(name, item.FullName, out startName, out rubbish); name = name.Substring(startName, length); if (name.IsEmpty()) return null; } } return name.Trim('.'); }
internal static SqlPreCommand ProcessEmailTemplate( Replacements replacements, Table table, EmailTemplateEntity et, StringDistance sd) { try { var queryName = QueryLogic.ToQueryName(et.Query.Key); QueryDescription qd = DynamicQueryManager.Current.QueryDescription(queryName); Console.Clear(); SafeConsole.WriteLineColor(ConsoleColor.White, "EmailTemplate: " + et.Name); Console.WriteLine(" Query: " + et.Query.Key); if (et.From != null && et.From.Token != null) { QueryTokenEntity token = et.From.Token; switch (QueryTokenSynchronizer.FixToken(replacements, ref token, qd, SubTokensOptions.CanElement, " From", allowRemoveToken: false, allowReCreate: et.SystemEmail != null)) { case FixTokenResult.Nothing: break; case FixTokenResult.DeleteEntity: return table.DeleteSqlSync(et); case FixTokenResult.SkipEntity: return null; case FixTokenResult.Fix: et.From.Token = token; break; case FixTokenResult.ReGenerateEntity: return Regenerate(et, replacements, table); default: break; } } if (et.Recipients.Any(a=>a.Token != null)) { Console.WriteLine(" Recipients:"); foreach (var item in et.Recipients.Where(a => a.Token != null).ToList()) { QueryTokenEntity token = item.Token; switch (QueryTokenSynchronizer.FixToken(replacements, ref token, qd, SubTokensOptions.CanElement, " Recipient", allowRemoveToken: false, allowReCreate: et.SystemEmail != null)) { case FixTokenResult.Nothing: break; case FixTokenResult.DeleteEntity: return table.DeleteSqlSync(et); case FixTokenResult.RemoveToken: et.Recipients.Remove(item); break; case FixTokenResult.SkipEntity: return null; case FixTokenResult.Fix: item.Token = token; break; case FixTokenResult.ReGenerateEntity: return Regenerate(et, replacements, table); default: break; } } } try { foreach (var item in et.Messages) { SyncronizationContext sc = new SyncronizationContext { ModelType = et.SystemEmail.ToType(), QueryDescription = qd, Replacements = replacements, StringDistance = sd, Variables = new ScopedDictionary<string, ValueProviderBase>(null) }; item.Subject = Synchronize(item.Subject, sc); item.Text = Synchronize(item.Text, sc); } using (replacements.WithReplacedDatabaseName()) return table.UpdateSqlSync(et, includeCollections: true, comment: "EmailTemplate: " + et.Name); } catch (TemplateSyncException ex) { if (ex.Result == FixTokenResult.SkipEntity) return null; if (ex.Result == FixTokenResult.DeleteEntity) return table.DeleteSqlSync(et); if (ex.Result == FixTokenResult.ReGenerateEntity) return Regenerate(et, replacements, table); throw new InvalidOperationException("Unexcpected {0}".FormatWith(ex.Result)); } finally { Console.Clear(); } } catch (Exception e) { return new SqlPreCommandSimple("-- Exception in {0}: {1}".FormatWith(et.BaseToString(), e.Message)); } }
static string AskTypeReplacement(Replacements replacements, string type) { return replacements.GetOrCreate("cleanNames").GetOrCreate(type, () => { if (Replacements.AutoReplacement != null) { Replacements.Selection? sel = Replacements.AutoReplacement(type, null); if (sel != null && sel.Value.NewValue != null) return sel.Value.NewValue; } Console.WriteLine("Type {0} has been renamed?".FormatWith(type)); int startingIndex = 0; StringDistance sd = new StringDistance(); var list = TypeLogic.NameToType.Keys.OrderBy(t => sd.LevenshteinDistance(t, type)).ToList(); retry: int maxElements = Console.LargestWindowHeight - 11; list.Skip(startingIndex).Take(maxElements) .Select((s, i) => "- {1,2}: {2} ".FormatWith(i + startingIndex == 0 ? ">" : " ", i + startingIndex, s)).ToConsole(); Console.WriteLine(); SafeConsole.WriteLineColor(ConsoleColor.White, "- n: None"); int remaining = list.Count - startingIndex - maxElements; if (remaining > 0) SafeConsole.WriteLineColor(ConsoleColor.White, "- +: Show more values ({0} remaining)", remaining); while (true) { string answer = Console.ReadLine(); if (answer == null) throw new InvalidOperationException("Impossible to synchronize interactively without Console"); answer = answer.ToLower(); if (answer == "+" && remaining > 0) { startingIndex += maxElements; goto retry; } if (answer == "n") return null; int option = 0; if (int.TryParse(answer, out option)) { return list[option]; } Console.WriteLine("Error"); } }); }
public static TextBlock Diff(string oldStr, string newStr) { StringDistance sd = new StringDistance(); var dif = sd.DiffText(oldStr, newStr); TextBlock tb = new TextBlock { FontFamily = font }; foreach (var line in dif) { if (line.Action == StringDistance.DiffAction.Removed) { tb.Inlines.Add(DiffLine(line.Value, lightRed)); } if (line.Action == StringDistance.DiffAction.Added) { tb.Inlines.Add(DiffLine(line.Value, lightGreen)); } else if (line.Action == StringDistance.DiffAction.Equal) { if (line.Value.Count == 1) { tb.Inlines.Add(DiffLine(line.Value, null)); } else { tb.Inlines.Add(DiffLine(line.Value.Where(a => a.Action == StringDistance.DiffAction.Removed || a.Action == StringDistance.DiffAction.Equal), lightRed)); tb.Inlines.Add(DiffLine(line.Value.Where(a => a.Action == StringDistance.DiffAction.Added || a.Action == StringDistance.DiffAction.Equal), lightGreen)); } } } return tb; }