From a4889519e860e316534135d3485c55abf370bf61 Mon Sep 17 00:00:00 2001 From: rampaa Date: Fri, 12 Jan 2024 21:19:12 +0300 Subject: [PATCH] Add "Mine to file instead of Anki" option Add "Higher Value Means Higher Frequency" option for frequency dictionaries Add an option to change whether pitch accent info will be shown with dotted lines or with solid lines Update dependencies --- JL.Core.Tests/LookupTests.cs | 2 +- JL.Core/Anki/Mining.cs | 190 ++++++++++++++- JL.Core/Dicts/Options/AvailableDictOptions.cs | 5 + JL.Core/Dicts/Options/DictOptions.cs | 5 +- JL.Core/Freqs/FreqUtils.cs | 8 +- JL.Core/Freqs/Options/AvailableFreqOptions.cs | 7 +- JL.Core/Freqs/Options/FreqOptions.cs | 4 +- JL.Core/JL.Core.csproj | 4 +- JL.Core/Lookup/LookupFrequencyResult.cs | 5 +- JL.Core/Lookup/LookupResultUtils.cs | 157 ++++++++++++ JL.Core/Lookup/LookupUtils.cs | 118 +++------ JL.Windows/ConfigManager.cs | 5 + JL.Windows/GUI/EditDictionaryWindow.xaml.cs | 14 ++ JL.Windows/GUI/PopupWindow.xaml.cs | 27 ++- JL.Windows/GUI/PreferencesWindow.xaml | 11 + .../GUI/UserControls/DictOptionsControl.xaml | 9 + .../UserControls/DictOptionsControl.xaml.cs | 24 +- .../GUI/UserControls/FreqOptionsControl.xaml | 7 + .../UserControls/FreqOptionsControl.xaml.cs | 22 +- JL.Windows/Utilities/PopupWindowUtils.cs | 228 +----------------- 20 files changed, 518 insertions(+), 334 deletions(-) create mode 100644 JL.Core/Lookup/LookupResultUtils.cs diff --git a/JL.Core.Tests/LookupTests.cs b/JL.Core.Tests/LookupTests.cs index f3f7d2d5..e1bcd317 100644 --- a/JL.Core.Tests/LookupTests.cs +++ b/JL.Core.Tests/LookupTests.cs @@ -63,7 +63,7 @@ public void LookupText_始まる() ( matchedText: "始まる", dict: DictUtils.Dicts.Values.First(static dict => dict.Type is DictType.JMdict), - frequencies: new List { new("VN (Nazeka)", 759) }, + frequencies: new List { new("VN (Nazeka)", 759, false) }, primarySpelling: "始まる", deconjugatedMatchedText: "始まる", readings: new[] { "はじまる" }, diff --git a/JL.Core/Anki/Mining.cs b/JL.Core/Anki/Mining.cs index b70f09e3..6b5f435d 100644 --- a/JL.Core/Anki/Mining.cs +++ b/JL.Core/Anki/Mining.cs @@ -1,20 +1,196 @@ using System.Globalization; +using System.Text; using JL.Core.Audio; using JL.Core.Dicts; using JL.Core.Lookup; using JL.Core.Network; +using JL.Core.Statistics; using JL.Core.Utilities; namespace JL.Core.Anki; public static class Mining { - public static async Task Mine(Dictionary miningParams, LookupResult lookupResult) + private static Dictionary GetMiningParameters(LookupResult lookupResult, string currentText, string? selectedDefinitions, int currentCharPosition, bool replaceLineBreakWithBrTag) + { + Dictionary miningParams = new() + { + [JLField.LocalTime] = DateTime.Now.ToString("s", CultureInfo.InvariantCulture), + [JLField.SourceText] = replaceLineBreakWithBrTag ? currentText.ReplaceLineEndings("
") : currentText, + [JLField.Sentence] = JapaneseUtils.FindSentence(currentText, currentCharPosition), + [JLField.DictionaryName] = lookupResult.Dict.Name, + [JLField.MatchedText] = lookupResult.MatchedText, + [JLField.DeconjugatedMatchedText] = lookupResult.DeconjugatedMatchedText, + [JLField.PrimarySpelling] = lookupResult.PrimarySpelling, + [JLField.PrimarySpellingWithOrthographyInfo] = lookupResult.PrimarySpellingOrthographyInfoList is not null + ? string.Create(CultureInfo.InvariantCulture, $"{lookupResult.PrimarySpelling} ({string.Join(", ", lookupResult.PrimarySpellingOrthographyInfoList)})") + : lookupResult.PrimarySpelling + }; + + if (lookupResult.Readings is not null) + { + string readings = string.Join(", ", lookupResult.Readings); + miningParams[JLField.Readings] = readings; + + miningParams[JLField.ReadingsWithOrthographyInfo] = lookupResult.ReadingsOrthographyInfoList is not null + ? LookupResultUtils.ReadingsToText(lookupResult.Readings, lookupResult.ReadingsOrthographyInfoList) + : readings; + } + + if (lookupResult.AlternativeSpellings is not null) + { + string alternativeSpellings = string.Join(", ", lookupResult.AlternativeSpellings); + miningParams[JLField.AlternativeSpellings] = alternativeSpellings; + + miningParams[JLField.AlternativeSpellingsWithOrthographyInfo] = lookupResult.AlternativeSpellingsOrthographyInfoList is not null + ? LookupResultUtils.ReadingsToText(lookupResult.AlternativeSpellings, lookupResult.AlternativeSpellingsOrthographyInfoList) + : alternativeSpellings; + } + + if (lookupResult.Frequencies is not null) + { + string? formattedFreq = LookupResultUtils.FrequenciesToText(lookupResult.Frequencies, true); + if (formattedFreq is not null) + { + miningParams[JLField.Frequencies] = formattedFreq; + miningParams[JLField.RawFrequencies] = string.Join(", ", lookupResult.Frequencies + .Where(static f => f.Freq is > 0 and < int.MaxValue) + .Select(static f => f.Freq)); + } + } + + if (lookupResult.FormattedDefinitions is not null) + { + string formattedDefinitions = replaceLineBreakWithBrTag + ? lookupResult.FormattedDefinitions.ReplaceLineEndings("
") + : lookupResult.FormattedDefinitions; + + miningParams[JLField.Definitions] = formattedDefinitions; + + if (selectedDefinitions is null) + { + miningParams[JLField.SelectedDefinitions] = formattedDefinitions; + } + } + + if (selectedDefinitions is not null) + { + miningParams[JLField.SelectedDefinitions] = replaceLineBreakWithBrTag + ? selectedDefinitions.ReplaceLineEndings("
") + : selectedDefinitions; + } + + if (lookupResult.EdictId > 0) + { + miningParams[JLField.EdictId] = lookupResult.EdictId.ToString(CultureInfo.InvariantCulture); + } + + if (lookupResult.DeconjugationProcess is not null) + { + miningParams[JLField.DeconjugationProcess] = lookupResult.DeconjugationProcess; + } + + if (lookupResult.KanjiComposition is not null) + { + miningParams[JLField.KanjiComposition] = lookupResult.KanjiComposition; + } + + if (lookupResult.KanjiStats is not null) + { + miningParams[JLField.KanjiStats] = lookupResult.KanjiStats; + } + + if (lookupResult.StrokeCount > 0) + { + miningParams[JLField.StrokeCount] = lookupResult.StrokeCount.ToString(CultureInfo.InvariantCulture); + } + + if (lookupResult.KanjiGrade > -1) + { + miningParams[JLField.KanjiGrade] = lookupResult.KanjiGrade.ToString(CultureInfo.InvariantCulture); + } + + if (lookupResult.OnReadings is not null) + { + miningParams[JLField.OnReadings] = string.Join(", ", lookupResult.OnReadings); + } + + if (lookupResult.KunReadings is not null) + { + miningParams[JLField.KunReadings] = string.Join(", ", lookupResult.KunReadings); + } + + if (lookupResult.NanoriReadings is not null) + { + miningParams[JLField.NanoriReadings] = string.Join(", ", lookupResult.NanoriReadings); + } + + if (lookupResult.RadicalNames is not null) + { + miningParams[JLField.RadicalNames] = string.Join(", ", lookupResult.RadicalNames); + } + + return miningParams; + } + + public static async Task MineToFile(LookupResult lookupResult, string currentText, string? selectedDefinitions, int currentCharPosition) + { + string filePath; + JLField[] jlFields; + if (DictUtils.s_wordDictTypes.Contains(lookupResult.Dict.Type)) + { + filePath = Path.Join(Utils.ResourcesPath, "mined_words.txt"); + jlFields = JLFieldUtils.JLFieldsForWordDicts; + } + else if (DictUtils.s_nameDictTypes.Contains(lookupResult.Dict.Type)) + { + filePath = Path.Join(Utils.ResourcesPath, "mined_names.txt"); + jlFields = JLFieldUtils.JLFieldsForNameDicts; + } + else if (DictUtils.s_kanjiDictTypes.Contains(lookupResult.Dict.Type)) + { + filePath = Path.Join(Utils.ResourcesPath, "mined_kanjis.txt"); + jlFields = JLFieldUtils.JLFieldsForKanjiDicts; + } + else + { + filePath = Path.Join(Utils.ResourcesPath, "mined_others.txt"); + jlFields = JLFieldUtils.JLFieldsForWordDicts; + } + + Dictionary miningParameters = GetMiningParameters(lookupResult, currentText, selectedDefinitions, currentCharPosition, false); + StringBuilder lineToMine = new(); + for (int i = 1; i < jlFields.Length; i++) + { + JLField jlField = jlFields[i]; + if (jlField is JLField.Audio or JLField.Image) + { + continue; + } + + string? jlFieldContent = miningParameters.GetValueOrDefault(jlField)?.ReplaceLineEndings("\\n").Replace("\t", " ", StringComparison.Ordinal).Trim(); + if (!string.IsNullOrEmpty(jlFieldContent)) + { + _ = lineToMine.Append(CultureInfo.InvariantCulture, $"{jlField.GetDescription()}: ") + .Append(jlFieldContent) + .Append(i < jlFields.Length - 1 ? '\t' : '\n'); + } + } + + await File.AppendAllTextAsync(filePath, lineToMine.ToString(), Encoding.UTF8).ConfigureAwait(false); + + Stats.IncrementStat(StatType.CardsMined); + + Utils.Frontend.Alert(AlertLevel.Success, string.Create(CultureInfo.InvariantCulture, $"Mined {lookupResult.PrimarySpelling}")); + Utils.Logger.Information("Mined {FoundSpelling}", lookupResult.PrimarySpelling); + } + + public static async Task Mine(LookupResult lookupResult, string currentText, string? selectedDefinitions, int currentCharPosition) { if (!CoreConfig.AnkiIntegration) { Utils.Frontend.Alert(AlertLevel.Error, "Please setup mining first in the preferences"); - return false; + return; } Dictionary? ankiConfigDict = await AnkiConfig.ReadAnkiConfig().ConfigureAwait(false); @@ -22,7 +198,7 @@ public static async Task Mine(Dictionary miningParams, Lo if (ankiConfigDict is null) { Utils.Frontend.Alert(AlertLevel.Error, "Please setup mining first in the preferences"); - return false; + return; } AnkiConfig? ankiConfig; @@ -49,7 +225,7 @@ public static async Task Mine(Dictionary miningParams, Lo if (ankiConfig is null) { Utils.Frontend.Alert(AlertLevel.Error, "Please setup mining first in the preferences"); - return false; + return; } Dictionary userFields = ankiConfig.Fields; @@ -102,6 +278,8 @@ public static async Task Mine(Dictionary miningParams, Lo { "allowDuplicate", CoreConfig.AllowDuplicateCards } }; + Dictionary miningParams = GetMiningParameters(lookupResult, currentText, selectedDefinitions, currentCharPosition, true); + Dictionary fields = ConvertFields(userFields, miningParams); Note note = new(ankiConfig.DeckName, ankiConfig.ModelName, fields, options, ankiConfig.Tags, audio, null, image); @@ -111,7 +289,7 @@ public static async Task Mine(Dictionary miningParams, Lo { Utils.Frontend.Alert(AlertLevel.Error, string.Create(CultureInfo.InvariantCulture, $"Mining failed for {lookupResult.PrimarySpelling}")); Utils.Logger.Error("Mining failed for {FoundSpelling}", lookupResult.PrimarySpelling); - return false; + return; } if (needsAudio && (audioData is null || Utils.GetMd5String(audioData) is Networking.Jpod101NoAudioMd5Hash)) @@ -131,7 +309,7 @@ public static async Task Mine(Dictionary miningParams, Lo await AnkiConnect.Sync().ConfigureAwait(false); } - return true; + Stats.IncrementStat(StatType.CardsMined); } /// diff --git a/JL.Core/Dicts/Options/AvailableDictOptions.cs b/JL.Core/Dicts/Options/AvailableDictOptions.cs index 407008ef..00d53659 100644 --- a/JL.Core/Dicts/Options/AvailableDictOptions.cs +++ b/JL.Core/Dicts/Options/AvailableDictOptions.cs @@ -108,3 +108,8 @@ public readonly record struct UseDBOption(bool Value) { [JsonIgnore] public static readonly DictType[] ValidDictTypes = DictUtils.s_dictTypesWithDBSupport; } + +public readonly record struct ShowPitchAccentWithDottedLines(bool Value) +{ + [JsonIgnore] public static readonly DictType[] ValidDictTypes = { DictType.PitchAccentYomichan }; +} diff --git a/JL.Core/Dicts/Options/DictOptions.cs b/JL.Core/Dicts/Options/DictOptions.cs index 85bc0d4d..7a02c81f 100644 --- a/JL.Core/Dicts/Options/DictOptions.cs +++ b/JL.Core/Dicts/Options/DictOptions.cs @@ -21,6 +21,7 @@ public sealed class DictOptions public AntonymOption? Antonym { get; } public LoanwordEtymologyOption? LoanwordEtymology { get; } public UseDBOption? UseDB { get; } + public ShowPitchAccentWithDottedLines? ShowPitchAccentWithDottedLines { get; } public DictOptions ( @@ -42,7 +43,8 @@ public DictOptions LoanwordEtymologyOption? loanwordEtymology = null, RelatedTermOption? relatedTerm = null, AntonymOption? antonym = null, - UseDBOption? useDB = null + UseDBOption? useDB = null, + ShowPitchAccentWithDottedLines? showPitchAccentWithDottedLines = null ) { NewlineBetweenDefinitions = newlineBetweenDefinitions; @@ -64,5 +66,6 @@ public DictOptions RelatedTerm = relatedTerm; Antonym = antonym; UseDB = useDB; + ShowPitchAccentWithDottedLines = showPitchAccentWithDottedLines; } } diff --git a/JL.Core/Freqs/FreqUtils.cs b/JL.Core/Freqs/FreqUtils.cs index 94bfaa92..58ab2fc8 100644 --- a/JL.Core/Freqs/FreqUtils.cs +++ b/JL.Core/Freqs/FreqUtils.cs @@ -20,25 +20,25 @@ public static class FreqUtils "VN (Nazeka)", new Freq(FreqType.Nazeka, "VN (Nazeka)", Path.Join(Utils.ResourcesPath, "freqlist_vns.json"), - true, 1, 57273, false, new FreqOptions(new UseDBOption(false))) + true, 1, 57273, false, new FreqOptions(new UseDBOption(false), new HigherValueMeansHigherFrequencyOption(false))) }, { "Narou (Nazeka)", new Freq(FreqType.Nazeka, "Narou (Nazeka)", Path.Join(Utils.ResourcesPath, "freqlist_narou.json"), - false, 2, 75588, false, new FreqOptions(new UseDBOption(false))) + false, 2, 75588, false, new FreqOptions(new UseDBOption(false), new HigherValueMeansHigherFrequencyOption(false))) }, { "Novel (Nazeka)", new Freq(FreqType.Nazeka, "Novel (Nazeka)", Path.Join(Utils.ResourcesPath, "freqlist_novels.json"), - false, 3, 114348, false, new FreqOptions(new UseDBOption(false))) + false, 3, 114348, false, new FreqOptions(new UseDBOption(false), new HigherValueMeansHigherFrequencyOption(false))) } }; - internal static readonly FreqType[] s_freqTypesWithDBSupport = { + internal static readonly FreqType[] s_allFreqDicts = { FreqType.Nazeka, FreqType.Yomichan, FreqType.YomichanKanji diff --git a/JL.Core/Freqs/Options/AvailableFreqOptions.cs b/JL.Core/Freqs/Options/AvailableFreqOptions.cs index b95710ab..f799f292 100644 --- a/JL.Core/Freqs/Options/AvailableFreqOptions.cs +++ b/JL.Core/Freqs/Options/AvailableFreqOptions.cs @@ -3,5 +3,10 @@ namespace JL.Core.Freqs.Options; public readonly record struct UseDBOption(bool Value) { - [JsonIgnore] public static readonly FreqType[] ValidFreqTypes = FreqUtils.s_freqTypesWithDBSupport; + [JsonIgnore] public static readonly FreqType[] ValidFreqTypes = FreqUtils.s_allFreqDicts; +} + +public readonly record struct HigherValueMeansHigherFrequencyOption(bool Value) +{ + [JsonIgnore] public static readonly FreqType[] ValidFreqTypes = FreqUtils.s_allFreqDicts; } diff --git a/JL.Core/Freqs/Options/FreqOptions.cs b/JL.Core/Freqs/Options/FreqOptions.cs index 71c42a4e..96654495 100644 --- a/JL.Core/Freqs/Options/FreqOptions.cs +++ b/JL.Core/Freqs/Options/FreqOptions.cs @@ -2,9 +2,11 @@ namespace JL.Core.Freqs.Options; public sealed class FreqOptions { public UseDBOption? UseDB { get; } + public HigherValueMeansHigherFrequencyOption? HigherValueMeansHigherFrequency { get; } - public FreqOptions(UseDBOption? useDB = null) + public FreqOptions(UseDBOption? useDB = null,HigherValueMeansHigherFrequencyOption? higherValueMeansHigherFrequency = null) { UseDB = useDB; + HigherValueMeansHigherFrequency = higherValueMeansHigherFrequency; } } diff --git a/JL.Core/JL.Core.csproj b/JL.Core/JL.Core.csproj index 55afd99a..e24f4478 100644 --- a/JL.Core/JL.Core.csproj +++ b/JL.Core/JL.Core.csproj @@ -11,9 +11,9 @@ - + - + diff --git a/JL.Core/Lookup/LookupFrequencyResult.cs b/JL.Core/Lookup/LookupFrequencyResult.cs index 707fc346..64902bbb 100644 --- a/JL.Core/Lookup/LookupFrequencyResult.cs +++ b/JL.Core/Lookup/LookupFrequencyResult.cs @@ -5,9 +5,12 @@ public sealed class LookupFrequencyResult public string Name { get; } public int Freq { get; } - internal LookupFrequencyResult(string name, int freq) + public bool HigherValueMeansHigherFrequency { get; } + + internal LookupFrequencyResult(string name, int freq, bool higherValueMeansHigherFrequency) { Name = name; Freq = freq; + HigherValueMeansHigherFrequency = higherValueMeansHigherFrequency; } } diff --git a/JL.Core/Lookup/LookupResultUtils.cs b/JL.Core/Lookup/LookupResultUtils.cs new file mode 100644 index 00000000..11995040 --- /dev/null +++ b/JL.Core/Lookup/LookupResultUtils.cs @@ -0,0 +1,157 @@ +using System.Globalization; +using System.Text; + +namespace JL.Core.Lookup; +public class LookupResultUtils +{ + internal static string? ProcessDeconjugationProcess(List>? processList) + { + if (processList is null) + { + return null; + } + + StringBuilder deconjugation = new(); + bool first = true; + + for (int i = 0; i < processList.Count; i++) + { + List form = processList[i]; + + StringBuilder formText = new(); + int added = 0; + + for (int j = form.Count - 1; j >= 0; j--) + { + string info = form[j]; + + if (info is "") + { + continue; + } + + if (info.StartsWith('(') && info.EndsWith(')') && j is not 0) + { + continue; + } + + if (added > 0) + { + _ = formText.Append('→'); + } + + ++added; + _ = formText.Append(info); + } + + if (formText.Length is not 0) + { + _ = first + ? deconjugation.Append(CultureInfo.InvariantCulture, $"~{formText}") + : deconjugation.Append(CultureInfo.InvariantCulture, $"; {formText}"); + } + + first = false; + } + + return deconjugation.Length is 0 ? null : deconjugation.ToString(); + } + + public static string GradeToText(int grade) + { + string gradeText = grade switch + { + >= 1 and <= 6 => string.Create(CultureInfo.InvariantCulture, $"{grade} (Kyouiku)"), + 8 => string.Create(CultureInfo.InvariantCulture, $"{grade} (Jouyou)"), + <= 10 => string.Create(CultureInfo.InvariantCulture, $"{grade} (Jinmeiyou)"), + _ => "Hyougai" + }; + + return gradeText; + } + + public static string? FrequenciesToText(List frequencies, bool forMining) + { + if (!forMining && frequencies.Count is 1 && frequencies[0].Freq is > 0 and < int.MaxValue) + { + return string.Create(CultureInfo.InvariantCulture, $"#{frequencies[0].Freq}"); + } + + if (frequencies.Count > 0) + { + int freqResultCount = 0; + StringBuilder sb = new(); + foreach (LookupFrequencyResult lookupFreqResult in frequencies) + { + if (lookupFreqResult.Freq is > 0 and < int.MaxValue) + { + _ = sb.Append(CultureInfo.InvariantCulture, $"{lookupFreqResult.Name}: {lookupFreqResult.Freq}, "); + ++freqResultCount; + } + } + + if (freqResultCount > 0) + { + return sb.Remove(sb.Length - 2, 2).ToString(); + } + } + + return null; + } + + public static string ReadingsToText(string[] readings, string[]?[] rOrthographyInfoList) + { + StringBuilder sb = new(); + + for (int index = 0; index < readings.Length; index++) + { + _ = sb.Append(readings[index]); + + if (index < rOrthographyInfoList.Length) + { + string[]? rOrthographyInfo = rOrthographyInfoList[index]; + if (rOrthographyInfo is not null) + { + _ = sb.Append(CultureInfo.InvariantCulture, $" ({string.Join(", ", rOrthographyInfo)})"); + } + } + + if (index != readings.Length - 1) + { + _ = sb.Append(", "); + } + } + + return sb.ToString(); + } + + public static string AlternativeSpellingsToText(string[] alternativeSpellings, string[]?[] aOrthographyInfoList) + { + StringBuilder sb = new(); + + _ = sb.Append('('); + + for (int index = 0; index < alternativeSpellings.Length; index++) + { + _ = sb.Append(alternativeSpellings[index]); + + if (index < aOrthographyInfoList.Length) + { + string[]? aOrthographyInfo = aOrthographyInfoList[index]; + if (aOrthographyInfo is not null) + { + _ = sb.Append(CultureInfo.InvariantCulture, $" ({string.Join(", ", aOrthographyInfo)})"); + } + } + + if (index != alternativeSpellings.Length - 1) + { + _ = sb.Append(", "); + } + } + + _ = sb.Append(')'); + + return sb.ToString(); + } +} diff --git a/JL.Core/Lookup/LookupUtils.cs b/JL.Core/Lookup/LookupUtils.cs index d1fb2f46..6f7b0d07 100644 --- a/JL.Core/Lookup/LookupUtils.cs +++ b/JL.Core/Lookup/LookupUtils.cs @@ -1,7 +1,5 @@ using System.Collections.Concurrent; using System.Diagnostics; -using System.Globalization; -using System.Text; using JL.Core.Deconjugation; using JL.Core.Dicts; using JL.Core.Dicts.CustomNameDict; @@ -36,14 +34,14 @@ public static class LookupUtils s_lastLookupTime = preciseTimeNow; - ConcurrentBag lookupResults = new(); - List dbFreqs = FreqUtils.FreqDicts.Values.Where(static f => f is { Active: true, Type: not FreqType.YomichanKanji } && (f.Options?.UseDB?.Value ?? false) && f.Ready).ToList(); _ = DictUtils.SingleDictTypeDicts.TryGetValue(DictType.PitchAccentYomichan, out Dict? pitchDict); bool pitchDictIsActive = pitchDict?.Active ?? false; bool useDBForPitchDict = pitchDictIsActive && (pitchDict!.Options?.UseDB?.Value ?? false) && pitchDict.Ready; + ConcurrentBag lookupResults = new(); + if (CoreConfig.KanjiMode) { _ = Parallel.ForEach(DictUtils.Dicts.Values.ToList(), dict => @@ -355,7 +353,20 @@ private static List SortLookupResults(IEnumerable lo return 1; }) - .ThenBy(static lookupResult => lookupResult.Frequencies?.Count > 0 ? lookupResult.Frequencies[0].Freq : int.MaxValue) + .ThenBy(static lookupResult => + { + if (lookupResult.Frequencies?.Count > 0) + { + LookupFrequencyResult freqResult = lookupResult.Frequencies[0]; + return !freqResult.HigherValueMeansHigherFrequency + ? freqResult.Freq + : freqResult.Freq is int.MaxValue + ? int.MaxValue + : int.MaxValue - freqResult.Freq; + } + + return int.MaxValue; + }) //.ThenBy(static lookupResult => //{ // int index = lookupResult.Readings is not null @@ -443,8 +454,6 @@ private static (bool tryLongVowelConversion, int succAttempt) GetWordResultsHelp private static Dictionary GetWordResults(List textList, List textInHiraganaList, List> deconjugationResultsList, Dict dict, bool useDB, GetRecordsFromDB? getRecordsFromDB) { - Dictionary results = new(); - Dictionary>? dbWordDict = null; Dictionary>? dbVerbDict = null; @@ -456,6 +465,7 @@ private static Dictionary GetWordResults(List results = new(); int succAttempt = 0; for (int i = 0; i < textList.Count; i++) { @@ -495,13 +505,11 @@ private static Dictionary GetWordResults(List GetValidDeconjugatedResults(Dict dict, Form deconjugationResult, IList dictResults) { - List resultsList = new(); + string? lastTag = deconjugationResult.Tags.Count > 0 + ? deconjugationResult.Tags[^1] + : null; - string lastTag = ""; - if (deconjugationResult.Tags.Count > 0) - { - lastTag = deconjugationResult.Tags.Last(); - } + List resultsList = new(); switch (dict.Type) { @@ -512,8 +520,7 @@ private static List GetValidDeconjugatedResults(Dict dict, Form dec { JmdictRecord dictResult = (JmdictRecord)dictResults[i]; - if (deconjugationResult.Tags.Count is 0 - || dictResult.WordClasses.SelectMany(static pos => pos).Contains(lastTag)) + if (lastTag is null || dictResult.WordClasses.SelectMany(static pos => pos).Contains(lastTag)) { resultsList.Add(dictResult); } @@ -529,8 +536,7 @@ private static List GetValidDeconjugatedResults(Dict dict, Form dec { CustomWordRecord dictResult = (CustomWordRecord)dictResults[i]; - if (deconjugationResult.Tags.Count is 0 - || dictResult.WordClasses.Contains(lastTag)) + if (lastTag is null || dictResult.WordClasses.Contains(lastTag)) { resultsList.Add(dictResult); } @@ -568,8 +574,7 @@ private static List GetValidDeconjugatedResults(Dict dict, Form dec { EpwingYomichanRecord dictResult = (EpwingYomichanRecord)dictResults[i]; - if (deconjugationResult.Tags.Count is 0 || - (dictResult.WordClasses?.Contains(lastTag) ?? false)) + if (lastTag is null || (dictResult.WordClasses?.Contains(lastTag) ?? false)) { resultsList.Add(dictResult); } @@ -585,7 +590,7 @@ private static List GetValidDeconjugatedResults(Dict dict, Form dec && (jmdictWordClassResult.Readings?.Contains(dictResult.Reading ?? string.Empty) ?? string.IsNullOrEmpty(dictResult.Reading))) { - if (jmdictWordClassResult.WordClasses.Contains(lastTag)) + if (lastTag is not null && jmdictWordClassResult.WordClasses.Contains(lastTag)) { resultsList.Add(dictResult); break; @@ -626,7 +631,7 @@ private static List GetValidDeconjugatedResults(Dict dict, Form dec && (jmdictWordClassResult.Readings?.Contains(dictResult.Reading ?? "") ?? string.IsNullOrEmpty(dictResult.Reading))) { - if (jmdictWordClassResult.WordClasses.Contains(lastTag)) + if (lastTag is not null && jmdictWordClassResult.WordClasses.Contains(lastTag)) { resultsList.Add(dictResult); break; @@ -905,7 +910,7 @@ private static List BuildJmdictResult( deconjugatedMatchedText: wordResult.DeconjugatedMatchedText, edictId: jmdictResult.Id, alternativeSpellings: jmdictResult.AlternativeSpellings, - deconjugationProcess: ProcessDeconjugationProcess(wordResult.Processes?[i]), + deconjugationProcess: LookupResultUtils.ProcessDeconjugationProcess(wordResult.Processes?[i]), frequencies: GetWordFrequencies(jmdictResult, frequencyDicts), primarySpellingOrthographyInfoList: jmdictResult.PrimarySpellingOrthographyInfo, readingsOrthographyInfoList: jmdictResult.ReadingsOrthographyInfo, @@ -1094,7 +1099,7 @@ private static List BuildEpwingYomichanResult( primarySpelling: epwingResult.PrimarySpelling, matchedText: wordResult.MatchedText, deconjugatedMatchedText: wordResult.DeconjugatedMatchedText, - deconjugationProcess: ProcessDeconjugationProcess(wordResult.Processes?[i]), + deconjugationProcess: LookupResultUtils.ProcessDeconjugationProcess(wordResult.Processes?[i]), frequencies: GetWordFrequencies(epwingResult, frequencyDicts), dict: wordResult.Dict, readings: epwingResult.Reading is not null @@ -1152,7 +1157,7 @@ private static ConcurrentBag BuildEpwingNazekaResult( alternativeSpellings: epwingResult.AlternativeSpellings, matchedText: wordResult.MatchedText, deconjugatedMatchedText: wordResult.DeconjugatedMatchedText, - deconjugationProcess: ProcessDeconjugationProcess(wordResult.Processes?[i]), + deconjugationProcess: LookupResultUtils.ProcessDeconjugationProcess(wordResult.Processes?[i]), frequencies: GetWordFrequencies(epwingResult, frequencyDicts), dict: wordResult.Dict, readings: epwingResult.Reading is not null @@ -1211,7 +1216,7 @@ private static ConcurrentBag BuildCustomWordResult( matchedText: wordResult.MatchedText, deconjugatedMatchedText: wordResult.DeconjugatedMatchedText, deconjugationProcess: customWordDictResult.HasUserDefinedWordClass - ? ProcessDeconjugationProcess(wordResult.Processes?[i]) + ? LookupResultUtils.ProcessDeconjugationProcess(wordResult.Processes?[i]) : null, dict: wordResult.Dict, readings: customWordDictResult.Readings, @@ -1256,7 +1261,7 @@ private static ConcurrentBag BuildCustomNameResult( primarySpelling: customNameDictResult.PrimarySpelling, matchedText: customNameResult.Value.MatchedText, deconjugatedMatchedText: customNameResult.Value.DeconjugatedMatchedText, - frequencies: new List { new(customNameResult.Value.Dict.Name, -freq) }, + frequencies: new List { new(customNameResult.Value.Dict.Name, -freq, false) }, dict: customNameResult.Value.Dict, readings: customNameDictResult.Reading is not null ? new[] { customNameDictResult.Reading } @@ -1288,13 +1293,13 @@ private static List GetWordFrequencies(IGetFrequency reco { if (freqDictsFromDB?.TryGetValue(freq.Name, out Dictionary>? freqDict) ?? false) { - freqsList.Add(new LookupFrequencyResult(freq.Name, record.GetFrequencyFromDB(freqDict))); + freqsList.Add(new LookupFrequencyResult(freq.Name, record.GetFrequencyFromDB(freqDict), freq.Options?.HigherValueMeansHigherFrequency?.Value ?? false)); } } else { - freqsList.Add(new LookupFrequencyResult(freq.Name, record.GetFrequency(freq))); + freqsList.Add(new LookupFrequencyResult(freq.Name, record.GetFrequency(freq), freq.Options?.HigherValueMeansHigherFrequency?.Value ?? false)); } } @@ -1325,7 +1330,7 @@ private static List GetYomichanKanjiFrequencies(string ka int frequency = freqResultList.FirstOrDefault().Frequency; if (frequency is not 0) { - freqsList.Add(new LookupFrequencyResult(kanjiFreq.Name, frequency)); + freqsList.Add(new LookupFrequencyResult(kanjiFreq.Name, frequency, false)); } } } @@ -1339,63 +1344,10 @@ private static List GetKanjidicFrequencies(string kanji, if (frequency is not 0) { - freqsList.Add(new LookupFrequencyResult("KANJIDIC2", frequency)); + freqsList.Add(new LookupFrequencyResult("KANJIDIC2", frequency, false)); } freqsList.AddRange(GetYomichanKanjiFrequencies(kanji)); return freqsList; } - - private static string? ProcessDeconjugationProcess(List>? processList) - { - if (processList is null) - { - return null; - } - - StringBuilder deconjugation = new(); - bool first = true; - - for (int i = 0; i < processList.Count; i++) - { - List form = processList[i]; - - StringBuilder formText = new(); - int added = 0; - - for (int j = form.Count - 1; j >= 0; j--) - { - string info = form[j]; - - if (info is "") - { - continue; - } - - if (info.StartsWith('(') && info.EndsWith(')') && j is not 0) - { - continue; - } - - if (added > 0) - { - _ = formText.Append('→'); - } - - ++added; - _ = formText.Append(info); - } - - if (formText.Length is not 0) - { - _ = first - ? deconjugation.Append(CultureInfo.InvariantCulture, $"~{formText}") - : deconjugation.Append(CultureInfo.InvariantCulture, $"; {formText}"); - } - - first = false; - } - - return deconjugation.Length is 0 ? null : deconjugation.ToString(); - } } diff --git a/JL.Windows/ConfigManager.cs b/JL.Windows/ConfigManager.cs index 6c2d75dd..a7e1ec9f 100644 --- a/JL.Windows/ConfigManager.cs +++ b/JL.Windows/ConfigManager.cs @@ -170,6 +170,7 @@ internal static class ConfigManager public static bool GlobalHotKeys { get; private set; } = false; public static bool StopIncreasingTimeStatWhenMinimized { get; private set; } = true; public static bool StripPunctuationBeforeCalculatingCharacterCount { get; private set; } = true; + public static bool MineToFileInsteadOfAnki { get; private set; } = true; #endregion @@ -256,6 +257,7 @@ public static void ApplyPreferences() GlobalHotKeys = GetValueFromConfig(config, GlobalHotKeys, nameof(GlobalHotKeys), bool.TryParse); StopIncreasingTimeStatWhenMinimized = GetValueFromConfig(config, StopIncreasingTimeStatWhenMinimized, nameof(StopIncreasingTimeStatWhenMinimized), bool.TryParse); StripPunctuationBeforeCalculatingCharacterCount = GetValueFromConfig(config, StripPunctuationBeforeCalculatingCharacterCount, nameof(StripPunctuationBeforeCalculatingCharacterCount), bool.TryParse); + MineToFileInsteadOfAnki = GetValueFromConfig(config, MineToFileInsteadOfAnki, nameof(MineToFileInsteadOfAnki), bool.TryParse); CheckForJLUpdatesOnStartUp = GetValueFromConfig(config, CheckForJLUpdatesOnStartUp, nameof(CheckForJLUpdatesOnStartUp), bool.TryParse); AlwaysOnTop = GetValueFromConfig(config, AlwaysOnTop, nameof(AlwaysOnTop), bool.TryParse); mainWindow.Topmost = AlwaysOnTop; @@ -825,6 +827,7 @@ public static void LoadPreferences(PreferencesWindow preferenceWindow) preferenceWindow.GlobalHotKeysCheckBox.IsChecked = GlobalHotKeys; preferenceWindow.StopIncreasingTimeStatWhenMinimizedCheckBox.IsChecked = StopIncreasingTimeStatWhenMinimized; preferenceWindow.StripPunctuationBeforeCalculatingCharacterCountCheckBox.IsChecked = StripPunctuationBeforeCalculatingCharacterCount; + preferenceWindow.MineToFileInsteadOfAnkiCheckBox.IsChecked = MineToFileInsteadOfAnki; preferenceWindow.AlwaysOnTopCheckBox.IsChecked = AlwaysOnTop; preferenceWindow.RequireLookupKeyPressCheckBox.IsChecked = RequireLookupKeyPress; preferenceWindow.DisableHotkeysCheckBox.IsChecked = DisableHotkeys; @@ -1121,6 +1124,8 @@ public static async Task SavePreferences(PreferencesWindow preferenceWindow) preferenceWindow.StopIncreasingTimeStatWhenMinimizedCheckBox.IsChecked.ToString(); settings[nameof(StripPunctuationBeforeCalculatingCharacterCount)].Value = preferenceWindow.StripPunctuationBeforeCalculatingCharacterCountCheckBox.IsChecked.ToString(); + settings[nameof(MineToFileInsteadOfAnki)].Value = + preferenceWindow.MineToFileInsteadOfAnkiCheckBox.IsChecked.ToString(); settings[nameof(CheckForJLUpdatesOnStartUp)].Value = preferenceWindow.CheckForJLUpdatesOnStartUpCheckBox.IsChecked.ToString(); diff --git a/JL.Windows/GUI/EditDictionaryWindow.xaml.cs b/JL.Windows/GUI/EditDictionaryWindow.xaml.cs index e28204b4..b0d6ad46 100644 --- a/JL.Windows/GUI/EditDictionaryWindow.xaml.cs +++ b/JL.Windows/GUI/EditDictionaryWindow.xaml.cs @@ -5,6 +5,7 @@ using JL.Core.Dicts.Options; using JL.Core.Utilities; using JL.Windows.GUI.UserControls; +using JL.Windows.Utilities; using Microsoft.Data.Sqlite; using OpenFileDialog = Microsoft.Win32.OpenFileDialog; using Path = System.IO.Path; @@ -85,6 +86,19 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) DictOptions options = _dictOptionsControl.GetDictOptions(_dict.Type); + if (_dict.Type is DictType.PitchAccentYomichan) + { + bool oldDottedLinesOption = _dict.Options?.ShowPitchAccentWithDottedLines?.Value ?? true; + bool newDottedLinesOption = options.ShowPitchAccentWithDottedLines?.Value ?? true; + + if (oldDottedLinesOption != newDottedLinesOption) + { + PopupWindowUtils.StrokeDashArray = newDottedLinesOption + ? new DoubleCollection() { 1, 1 } + : new DoubleCollection() { 1, 0 }; + } + } + if (_dict.Options?.Examples?.Value != options.Examples?.Value) { _dict.Contents.Clear(); diff --git a/JL.Windows/GUI/PopupWindow.xaml.cs b/JL.Windows/GUI/PopupWindow.xaml.cs index e72a6078..1397e87d 100644 --- a/JL.Windows/GUI/PopupWindow.xaml.cs +++ b/JL.Windows/GUI/PopupWindow.xaml.cs @@ -6,6 +6,7 @@ using System.Windows.Media; using Caching; using JL.Core; +using JL.Core.Anki; using JL.Core.Audio; using JL.Core.Dicts; using JL.Core.Lookup; @@ -549,7 +550,7 @@ public StackPanel PrepareResultStackPanel(LookupResult result, int index, int re && (pitchDictIsActive || (result.KunReadings is null && result.OnReadings is null))) { string readingsText = showROrthographyInfo && result.ReadingsOrthographyInfoList is not null - ? PopupWindowUtils.ReadingsToText(result.Readings, result.ReadingsOrthographyInfoList) + ? LookupResultUtils.ReadingsToText(result.Readings, result.ReadingsOrthographyInfoList) : string.Join(", ", result.Readings); if (MiningMode) @@ -656,7 +657,7 @@ public StackPanel PrepareResultStackPanel(LookupResult result, int index, int re if (result.AlternativeSpellings is not null) { string alternativeSpellingsText = showAOrthographyInfo && result.AlternativeSpellingsOrthographyInfoList is not null - ? PopupWindowUtils.AlternativeSpellingsToText(result.AlternativeSpellings, result.AlternativeSpellingsOrthographyInfoList) + ? LookupResultUtils.AlternativeSpellingsToText(result.AlternativeSpellings, result.AlternativeSpellingsOrthographyInfoList) : string.Create(CultureInfo.InvariantCulture, $"({string.Join(", ", result.AlternativeSpellings)})"); if (MiningMode) @@ -726,7 +727,7 @@ public StackPanel PrepareResultStackPanel(LookupResult result, int index, int re if (result.Frequencies is not null) { - string? freqText = PopupWindowUtils.FrequenciesToText(result.Frequencies, false); + string? freqText = LookupResultUtils.FrequenciesToText(result.Frequencies, false); if (freqText is not null) { @@ -1027,7 +1028,7 @@ public StackPanel PrepareResultStackPanel(LookupResult result, int index, int re TextBlock gradeTextBlock = new() { Name = nameof(result.KanjiGrade), - Text = string.Create(CultureInfo.InvariantCulture, $"Grade: {PopupWindowUtils.GradeToText(result.KanjiGrade)}"), + Text = string.Create(CultureInfo.InvariantCulture, $"Grade: {LookupResultUtils.GradeToText(result.KanjiGrade)}"), Foreground = ConfigManager.DefinitionsColor, FontSize = ConfigManager.DefinitionsFontSize, Margin = new Thickness(2, 2, 2, 2), @@ -1239,7 +1240,14 @@ private async void PrimarySpelling_PreviewMouseUp(object sender, MouseButtonEven HidePopup(); - await PopupWindowUtils.Mine(LastLookupResults[listViewItemIndex], _currentText, selectedDefinitions, _currentCharPosition).ConfigureAwait(false); + if (ConfigManager.MineToFileInsteadOfAnki) + { + await Mining.MineToFile(LastLookupResults[listViewItemIndex], _currentText, selectedDefinitions, _currentCharPosition).ConfigureAwait(false); + } + else + { + await Mining.Mine(LastLookupResults[listViewItemIndex], _currentText, selectedDefinitions, _currentCharPosition).ConfigureAwait(false); + } } private void ShowAddNameWindow() @@ -1621,7 +1629,14 @@ public async Task HandleHotKey(KeyGesture keyGesture) HidePopup(); - await PopupWindowUtils.Mine(LastLookupResults[index], _currentText, selectedDefinitions, _currentCharPosition).ConfigureAwait(false); + if (ConfigManager.MineToFileInsteadOfAnki) + { + await Mining.MineToFile(LastLookupResults[index], _currentText, selectedDefinitions, _currentCharPosition).ConfigureAwait(false); + } + else + { + await Mining.Mine(LastLookupResults[index], _currentText, selectedDefinitions, _currentCharPosition).ConfigureAwait(false); + } } } diff --git a/JL.Windows/GUI/PreferencesWindow.xaml b/JL.Windows/GUI/PreferencesWindow.xaml index 04e012fd..d7c9c3b5 100644 --- a/JL.Windows/GUI/PreferencesWindow.xaml +++ b/JL.Windows/GUI/PreferencesWindow.xaml @@ -1477,6 +1477,17 @@ + + + + + + + + + diff --git a/JL.Windows/GUI/UserControls/DictOptionsControl.xaml.cs b/JL.Windows/GUI/UserControls/DictOptionsControl.xaml.cs index 377b14b8..ec651751 100644 --- a/JL.Windows/GUI/UserControls/DictOptionsControl.xaml.cs +++ b/JL.Windows/GUI/UserControls/DictOptionsControl.xaml.cs @@ -145,6 +145,12 @@ public DictOptions GetDictOptions(DictType type) useDBOption = new UseDBOption(UseDBCheckBox.IsChecked!.Value); } + ShowPitchAccentWithDottedLines? showPitchAccentWithDottedLines = null; + if (ShowPitchAccentWithDottedLines.ValidDictTypes.Contains(type)) + { + showPitchAccentWithDottedLines = new ShowPitchAccentWithDottedLines(ShowPitchAccentWithDottedLinesCheckBox.IsChecked!.Value); + } + DictOptions options = new( newlineOption, examplesOption, @@ -164,7 +170,8 @@ public DictOptions GetDictOptions(DictType type) loanwordEtymology, relatedTermOption, antonymOption, - useDBOption); + useDBOption, + showPitchAccentWithDottedLines); return options; } @@ -306,6 +313,14 @@ public void GenerateDictOptionsElements(DictType dictType) showDictOptions = true; } + ShowPitchAccentWithDottedLines? showPitchAccentWithDottedLines = null; + if (ShowPitchAccentWithDottedLines.ValidDictTypes.Contains(dictType)) + { + ShowPitchAccentWithDottedLinesCheckBox.IsChecked = true; + ShowPitchAccentWithDottedLinesCheckBox.Visibility = Visibility.Visible; + showDictOptions = true; + } + if (showDictOptions) { OptionsTextBlock.Visibility = Visibility.Visible; @@ -450,6 +465,13 @@ public void GenerateDictOptionsElements(Dict dict) showDictOptions = true; } + if (ShowPitchAccentWithDottedLines.ValidDictTypes.Contains(dict.Type)) + { + ShowPitchAccentWithDottedLinesCheckBox.IsChecked = dict.Options?.ShowPitchAccentWithDottedLines?.Value ?? true; + ShowPitchAccentWithDottedLinesCheckBox.Visibility = Visibility.Visible; + showDictOptions = true; + } + if (showDictOptions) { OptionsTextBlock.Visibility = Visibility.Visible; diff --git a/JL.Windows/GUI/UserControls/FreqOptionsControl.xaml b/JL.Windows/GUI/UserControls/FreqOptionsControl.xaml index d179e940..9914a154 100644 --- a/JL.Windows/GUI/UserControls/FreqOptionsControl.xaml +++ b/JL.Windows/GUI/UserControls/FreqOptionsControl.xaml @@ -18,6 +18,13 @@ HorizontalAlignment="Left" Style="{StaticResource TextBlockDefault}" /> + + + + diff --git a/JL.Windows/GUI/UserControls/FreqOptionsControl.xaml.cs b/JL.Windows/GUI/UserControls/FreqOptionsControl.xaml.cs index 1602b5c6..0b898382 100644 --- a/JL.Windows/GUI/UserControls/FreqOptionsControl.xaml.cs +++ b/JL.Windows/GUI/UserControls/FreqOptionsControl.xaml.cs @@ -20,7 +20,13 @@ public FreqOptions GetFreqOptions(FreqType type) useDBOption = new UseDBOption(UseDBCheckBox.IsChecked!.Value); } - FreqOptions options = new(useDBOption); + HigherValueMeansHigherFrequencyOption? higherValueMeansHigherFrequencyOption = null; + if (HigherValueMeansHigherFrequencyOption.ValidFreqTypes.Contains(type)) + { + higherValueMeansHigherFrequencyOption = new HigherValueMeansHigherFrequencyOption(HigherValueMeansHigherFrequencyCheckBox.IsChecked!.Value); + } + + FreqOptions options = new(useDBOption, higherValueMeansHigherFrequencyOption); return options; } @@ -35,6 +41,13 @@ public void GenerateFreqOptionsElements(FreqType freqType) showFreqOptions = true; } + if (HigherValueMeansHigherFrequencyOption.ValidFreqTypes.Contains(freqType)) + { + HigherValueMeansHigherFrequencyCheckBox.IsChecked = false; + HigherValueMeansHigherFrequencyCheckBox.Visibility = Visibility.Visible; + showFreqOptions = true; + } + if (showFreqOptions) { OptionsTextBlock.Visibility = Visibility.Visible; @@ -52,6 +65,13 @@ public void GenerateFreqOptionsElements(Freq freq) showFreqOptions = true; } + if (HigherValueMeansHigherFrequencyOption.ValidFreqTypes.Contains(freq.Type)) + { + HigherValueMeansHigherFrequencyCheckBox.IsChecked = freq.Options?.HigherValueMeansHigherFrequency?.Value ?? false; + HigherValueMeansHigherFrequencyCheckBox.Visibility = Visibility.Visible; + showFreqOptions = true; + } + if (showFreqOptions) { OptionsTextBlock.Visibility = Visibility.Visible; diff --git a/JL.Windows/Utilities/PopupWindowUtils.cs b/JL.Windows/Utilities/PopupWindowUtils.cs index 9a2b56c6..46492eec 100644 --- a/JL.Windows/Utilities/PopupWindowUtils.cs +++ b/JL.Windows/Utilities/PopupWindowUtils.cs @@ -1,15 +1,11 @@ using System.Globalization; -using System.Text; using System.Timers; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; -using JL.Core.Anki; using JL.Core.Dicts; using JL.Core.Dicts.PitchAccent; -using JL.Core.Lookup; -using JL.Core.Statistics; using JL.Core.Utilities; using JL.Windows.GUI; @@ -17,105 +13,7 @@ namespace JL.Windows.Utilities; internal static class PopupWindowUtils { - private static readonly DoubleCollection s_strokeDashArray = new() { 1, 1 }; - - public static string GradeToText(int grade) - { - string gradeText = grade switch - { - >= 1 and <= 6 => string.Create(CultureInfo.InvariantCulture, $"{grade} (Kyouiku)"), - 8 => string.Create(CultureInfo.InvariantCulture, $"{grade} (Jouyou)"), - <= 10 => string.Create(CultureInfo.InvariantCulture, $"{grade} (Jinmeiyou)"), - _ => "Hyougai" - }; - - return gradeText; - } - - public static string? FrequenciesToText(List frequencies, bool forMining) - { - if (!forMining && frequencies.Count is 1 && frequencies[0].Freq is > 0 and < int.MaxValue) - { - return string.Create(CultureInfo.InvariantCulture, $"#{frequencies[0].Freq}"); - } - - if (frequencies.Count > 0) - { - int freqResultCount = 0; - StringBuilder sb = new(); - foreach (LookupFrequencyResult lookupFreqResult in frequencies) - { - if (lookupFreqResult.Freq is > 0 and < int.MaxValue) - { - _ = sb.Append(CultureInfo.InvariantCulture, $"{lookupFreqResult.Name}: {lookupFreqResult.Freq}, "); - ++freqResultCount; - } - } - - if (freqResultCount > 0) - { - return sb.Remove(sb.Length - 2, 2).ToString(); - } - } - - return null; - } - - public static string ReadingsToText(string[] readings, string[]?[] rOrthographyInfoList) - { - StringBuilder sb = new(); - - for (int index = 0; index < readings.Length; index++) - { - _ = sb.Append(readings[index]); - - if (index < rOrthographyInfoList.Length) - { - string[]? rOrthographyInfo = rOrthographyInfoList[index]; - if (rOrthographyInfo is not null) - { - _ = sb.Append(CultureInfo.InvariantCulture, $" ({string.Join(", ", rOrthographyInfo)})"); - } - } - - if (index != readings.Length - 1) - { - _ = sb.Append(", "); - } - } - - return sb.ToString(); - } - - public static string AlternativeSpellingsToText(string[] alternativeSpellings, string[]?[] aOrthographyInfoList) - { - StringBuilder sb = new(); - - _ = sb.Append('('); - - for (int index = 0; index < alternativeSpellings.Length; index++) - { - _ = sb.Append(alternativeSpellings[index]); - - if (index < aOrthographyInfoList.Length) - { - string[]? aOrthographyInfo = aOrthographyInfoList[index]; - if (aOrthographyInfo is not null) - { - _ = sb.Append(CultureInfo.InvariantCulture, $" ({string.Join(", ", aOrthographyInfo)})"); - } - } - - if (index != alternativeSpellings.Length - 1) - { - _ = sb.Append(", "); - } - } - - _ = sb.Append(')'); - - return sb.ToString(); - } + public static DoubleCollection StrokeDashArray { get; set; } = new() { 1, 1 }; public static Grid CreatePitchAccentGrid(string primarySpelling, string[]? alternativeSpellings, string[]? readings, string[] splitReadingsWithRInfo, double leftMargin, Dict dict, Dictionary>? pitchRecordDict) @@ -177,7 +75,7 @@ public static Grid CreatePitchAccentGrid(string primarySpelling, string[]? alter { StrokeThickness = 2, Stroke = DictOptionManager.PitchAccentMarkerColor, - StrokeDashArray = s_strokeDashArray + StrokeDashArray = StrokeDashArray }; bool lowPitch = false; @@ -305,126 +203,4 @@ public static void ShowMiningModeResults(PopupWindow popupWindow) SetPopupAutoHideTimer(); } } - - public static async Task Mine(LookupResult lookupResult, string currentText, string? selectedDefinitions, int currentCharPosition) - { - Dictionary miningParams = new() - { - [JLField.LocalTime] = DateTime.Now.ToString("s", CultureInfo.InvariantCulture), - [JLField.SourceText] = currentText, - [JLField.Sentence] = JapaneseUtils.FindSentence(currentText, currentCharPosition), - [JLField.DictionaryName] = lookupResult.Dict.Name, - [JLField.MatchedText] = lookupResult.MatchedText, - [JLField.DeconjugatedMatchedText] = lookupResult.DeconjugatedMatchedText, - [JLField.PrimarySpelling] = lookupResult.PrimarySpelling, - [JLField.PrimarySpellingWithOrthographyInfo] = lookupResult.PrimarySpellingOrthographyInfoList is not null - ? string.Create(CultureInfo.InvariantCulture, $"{lookupResult.PrimarySpelling} ({string.Join(", ", lookupResult.PrimarySpellingOrthographyInfoList)})") - : lookupResult.PrimarySpelling - }; - - if (lookupResult.Readings is not null) - { - string readings = string.Join(", ", lookupResult.Readings); - miningParams[JLField.Readings] = readings; - - miningParams[JLField.ReadingsWithOrthographyInfo] = lookupResult.ReadingsOrthographyInfoList is not null - ? ReadingsToText(lookupResult.Readings, lookupResult.ReadingsOrthographyInfoList) - : readings; - } - - if (lookupResult.AlternativeSpellings is not null) - { - string alternativeSpellings = string.Join(", ", lookupResult.AlternativeSpellings); - miningParams[JLField.AlternativeSpellings] = alternativeSpellings; - - miningParams[JLField.AlternativeSpellingsWithOrthographyInfo] = lookupResult.AlternativeSpellingsOrthographyInfoList is not null - ? ReadingsToText(lookupResult.AlternativeSpellings, lookupResult.AlternativeSpellingsOrthographyInfoList) - : alternativeSpellings; - } - - if (lookupResult.Frequencies is not null) - { - string? formattedFreq = FrequenciesToText(lookupResult.Frequencies, true); - if (formattedFreq is not null) - { - miningParams[JLField.Frequencies] = formattedFreq; - miningParams[JLField.RawFrequencies] = string.Join(", ", lookupResult.Frequencies - .Where(static f => f.Freq is > 0 and < int.MaxValue) - .Select(static f => f.Freq)); - } - } - - if (lookupResult.FormattedDefinitions is not null) - { - string formattedDefinitions = lookupResult.FormattedDefinitions.Replace("\n", "
", StringComparison.Ordinal); - miningParams[JLField.Definitions] = formattedDefinitions; - - if (selectedDefinitions is null) - { - miningParams[JLField.SelectedDefinitions] = formattedDefinitions; - } - } - - if (selectedDefinitions is not null) - { - miningParams[JLField.SelectedDefinitions] = selectedDefinitions.Replace("\n", "
", StringComparison.Ordinal); - } - - if (lookupResult.EdictId > 0) - { - miningParams[JLField.EdictId] = lookupResult.EdictId.ToString(CultureInfo.InvariantCulture); - } - - if (lookupResult.DeconjugationProcess is not null) - { - miningParams[JLField.DeconjugationProcess] = lookupResult.DeconjugationProcess; - } - - if (lookupResult.KanjiComposition is not null) - { - miningParams[JLField.KanjiComposition] = lookupResult.KanjiComposition; - } - - if (lookupResult.KanjiStats is not null) - { - miningParams[JLField.KanjiStats] = lookupResult.KanjiStats; - } - - if (lookupResult.StrokeCount > 0) - { - miningParams[JLField.StrokeCount] = lookupResult.StrokeCount.ToString(CultureInfo.InvariantCulture); - } - - if (lookupResult.KanjiGrade > -1) - { - miningParams[JLField.KanjiGrade] = lookupResult.KanjiGrade.ToString(CultureInfo.InvariantCulture); - } - - if (lookupResult.OnReadings is not null) - { - miningParams[JLField.OnReadings] = string.Join(", ", lookupResult.OnReadings); - } - - if (lookupResult.KunReadings is not null) - { - miningParams[JLField.KunReadings] = string.Join(", ", lookupResult.KunReadings); - } - - if (lookupResult.NanoriReadings is not null) - { - miningParams[JLField.NanoriReadings] = string.Join(", ", lookupResult.NanoriReadings); - } - - if (lookupResult.RadicalNames is not null) - { - miningParams[JLField.RadicalNames] = string.Join(", ", lookupResult.RadicalNames); - } - - bool mined = await Mining.Mine(miningParams, lookupResult).ConfigureAwait(false); - - if (mined) - { - Stats.IncrementStat(StatType.CardsMined); - } - } }