Skip to content

Commit

Permalink
Add "Mine to file instead of Anki" option
Browse files Browse the repository at this point in the history
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
  • Loading branch information
rampaa committed Jan 12, 2024
1 parent b7b02ff commit a488951
Show file tree
Hide file tree
Showing 20 changed files with 518 additions and 334 deletions.
2 changes: 1 addition & 1 deletion JL.Core.Tests/LookupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void LookupText_始まる()
(
matchedText: "始まる",
dict: DictUtils.Dicts.Values.First(static dict => dict.Type is DictType.JMdict),
frequencies: new List<LookupFrequencyResult> { new("VN (Nazeka)", 759) },
frequencies: new List<LookupFrequencyResult> { new("VN (Nazeka)", 759, false) },
primarySpelling: "始まる",
deconjugatedMatchedText: "始まる",
readings: new[] { "はじまる" },
Expand Down
190 changes: 184 additions & 6 deletions JL.Core/Anki/Mining.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,204 @@
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<bool> Mine(Dictionary<JLField, string> miningParams, LookupResult lookupResult)
private static Dictionary<JLField, string> GetMiningParameters(LookupResult lookupResult, string currentText, string? selectedDefinitions, int currentCharPosition, bool replaceLineBreakWithBrTag)
{
Dictionary<JLField, string> miningParams = new()
{
[JLField.LocalTime] = DateTime.Now.ToString("s", CultureInfo.InvariantCulture),
[JLField.SourceText] = replaceLineBreakWithBrTag ? currentText.ReplaceLineEndings("<br/>") : 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("<br/>")
: 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("<br/>")
: 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<JLField, string> 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<MineType, AnkiConfig>? ankiConfigDict = await AnkiConfig.ReadAnkiConfig().ConfigureAwait(false);

if (ankiConfigDict is null)
{
Utils.Frontend.Alert(AlertLevel.Error, "Please setup mining first in the preferences");
return false;
return;
}

AnkiConfig? ankiConfig;
Expand All @@ -49,7 +225,7 @@ public static async Task<bool> Mine(Dictionary<JLField, string> miningParams, Lo
if (ankiConfig is null)
{
Utils.Frontend.Alert(AlertLevel.Error, "Please setup mining first in the preferences");
return false;
return;
}

Dictionary<string, JLField> userFields = ankiConfig.Fields;
Expand Down Expand Up @@ -102,6 +278,8 @@ public static async Task<bool> Mine(Dictionary<JLField, string> miningParams, Lo
{ "allowDuplicate", CoreConfig.AllowDuplicateCards }
};

Dictionary<JLField, string> miningParams = GetMiningParameters(lookupResult, currentText, selectedDefinitions, currentCharPosition, true);

Dictionary<string, object> fields = ConvertFields(userFields, miningParams);

Note note = new(ankiConfig.DeckName, ankiConfig.ModelName, fields, options, ankiConfig.Tags, audio, null, image);
Expand All @@ -111,7 +289,7 @@ public static async Task<bool> Mine(Dictionary<JLField, string> 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))
Expand All @@ -131,7 +309,7 @@ public static async Task<bool> Mine(Dictionary<JLField, string> miningParams, Lo
await AnkiConnect.Sync().ConfigureAwait(false);
}

return true;
Stats.IncrementStat(StatType.CardsMined);
}

/// <summary>
Expand Down
5 changes: 5 additions & 0 deletions JL.Core/Dicts/Options/AvailableDictOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
}
5 changes: 4 additions & 1 deletion JL.Core/Dicts/Options/DictOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
(
Expand All @@ -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;
Expand All @@ -64,5 +66,6 @@ public DictOptions
RelatedTerm = relatedTerm;
Antonym = antonym;
UseDB = useDB;
ShowPitchAccentWithDottedLines = showPitchAccentWithDottedLines;
}
}
8 changes: 4 additions & 4 deletions JL.Core/Freqs/FreqUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion JL.Core/Freqs/Options/AvailableFreqOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
4 changes: 3 additions & 1 deletion JL.Core/Freqs/Options/FreqOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
4 changes: 2 additions & 2 deletions JL.Core/JL.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Caching" Version="3.0.1" />
<PackageReference Include="Caching" Version="3.1.1" />
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.2.2" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>

Expand Down
5 changes: 4 additions & 1 deletion JL.Core/Lookup/LookupFrequencyResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Loading

0 comments on commit a488951

Please sign in to comment.