Browse Source

update cloze maker

main
parent
commit
5cc5272f77
3 changed files with 114 additions and 10 deletions
  1. +1
    -0
      scripts/populate-from-wanikani.ts
  2. +86
    -2
      scripts/query-anki.ts
  3. +27
    -8
      src/wanikani.ts

+ 1
- 0
scripts/populate-from-wanikani.ts View File

@ -16,6 +16,7 @@ async function main() {
sentenceJa: 'Sentence',
sentenceAudio: 'SentenceAudio',
sentenceEn: 'SentenceMeaning',
sentenceCloze: 'MeaningQuiz',
},
{ overwrite: true },
);

+ 86
- 2
scripts/query-anki.ts View File

@ -1,5 +1,5 @@
import { soundTag } from '@/anki';
import { AnkiConnect } from '@/ankiconnect';
import { AnkiConnect, IAnkiConnectActions } from '@/ankiconnect';
export async function listTags(
query = 'deck:Takoboto -Takoboto: tag:common -tag:reading-challenge -tag:favorites -tag:death-note -tag:ハピネス -tag:https://www.bunka.go.jp/seisaku/bunkashingikai/kokugo/hokoku/pdf/ijidokun_140221.pdf',
@ -63,6 +63,90 @@ export async function addSoundTag(query: string, fieldNames: string[]) {
});
}
export async function fixCloze(
query: string,
fields: { vocabJa: string; sentenceCloze: string },
) {
const anki = new AnkiConnect();
anki
.api('findNotes', {
query,
})
.then((notes) => anki.api('notesInfo', { notes }))
.then(async (notes) => {
const notesToUpdate: IAnkiConnectActions['updateNoteFields']['params']['note'][] =
[];
const badJa: string[] = [];
for (const n of notes) {
const { value: ja } = n.fields[fields.vocabJa] || {};
const { value: sent } = n.fields[fields.sentenceCloze] || {};
if (ja && sent) {
const clozeChar = '__';
if (
sent
.split('<br>')
.filter((_, i) => i % 2 === 0)
.every((s) => s.includes(clozeChar))
) {
continue;
}
const cleanJa = ja.replace(/\[.+?\]/g, '').replace(/ /g, '');
let newSent = sent.replace(cleanJa, clozeChar);
const jaNoOkuri = cleanJa.replace(/[\p{sc=Hiragana}]/gu, '');
if (cleanJa !== jaNoOkuri && newSent.includes(jaNoOkuri)) {
const s2 = newSent.replace(jaNoOkuri, clozeChar);
if (s2 !== newSent) {
newSent = s2;
} else {
badJa.push(ja);
}
}
if (!sent.includes(clozeChar) && sent !== newSent) {
notesToUpdate.push({
id: n.noteId,
fields: {
[fields.sentenceCloze]: newSent,
},
});
}
}
}
while (badJa.length) {
console.log(
query +
' tag:wanikani card:EJ (' +
badJa
.splice(0, 20)
.map((ja) => `${fields.vocabJa}:${ja}`)
.join(' OR ') +
')',
);
}
if (!notesToUpdate.length) return;
await anki.multi<'updateNoteFields'[]>({
actions: notesToUpdate.map((note) => ({
action: 'updateNoteFields',
params: {
note,
},
})),
});
});
}
if (require.main === module) {
addSoundTag('note:jp.takoboto', ['SentenceAudio', 'JapaneseAudio']);
// addSoundTag('note:jp.takoboto', ['SentenceAudio', 'JapaneseAudio']);
fixCloze('deck:Takoboto', {
vocabJa: 'Japanese',
sentenceCloze: 'MeaningQuiz',
});
}

+ 27
- 8
src/wanikani.ts View File

@ -413,6 +413,7 @@ export class WaniKani {
sentenceJa: string;
sentenceAudio?: string;
sentenceEn: string;
sentenceCloze?: string;
},
opts: {
overwrite?: boolean;
@ -428,13 +429,20 @@ export class WaniKani {
{
ja: string;
en: string;
sentences: {
ja: string;
en: string;
}[];
}
>();
vocabularies.map((v) => {
if (sentenceMap.has(v.data.characters)) return;
const sent = v.data.context_sentences[0];
if (!sent || !sent.ja.trim()) return;
sentenceMap.set(v.data.characters, sent);
sentenceMap.set(v.data.characters, {
...sent,
sentences: v.data.context_sentences,
});
});
if (!sentenceMap.size) return;
@ -459,16 +467,27 @@ export class WaniKani {
for (const n of notes) {
const { value: ja } = n.fields[fields.vocabJa] || {};
if (ja) {
const sent = sentenceMap.get(
ja.replace(/\[.+?\]/g, '').replace(/ /g, ''),
);
const cleanJa = ja.replace(/\[.+?\]/g, '').replace(/ /g, '');
const sent = sentenceMap.get(cleanJa);
if (sent) {
const fieldUpdate = {
[fields.sentenceJa]: sent.ja,
[fields.sentenceEn]: sent.en,
};
if (
fields.sentenceCloze &&
!n.fields[fields.sentenceCloze]?.value
) {
fieldUpdate[fields.sentenceCloze] = sent.sentences
.map(({ ja, en }) => `${ja}<br/>${en}`)
.join('<br/>')
.replace(cleanJa, '__');
}
notesToUpdate.push({
id: n.noteId,
fields: {
[fields.sentenceJa]: sent.ja,
[fields.sentenceEn]: sent.en,
},
fields: fieldUpdate,
});
}
}

Loading…
Cancel
Save