add beyond
This commit is contained in:
1 parent
49cd39297a
commit
1c362c0c1c
4 files changed
+163
-6
No files matched your search
@@ -0,0 +1,23 @@
|
|||||||
|
'61-70: 無限 INFINITY':
|
||||||
|
'61': [乞, 仄, 佇, 侶, 俄, 俯, 倣, 僻, 儚, 冴, 凄, 几, 凧, 凭, 剃, 剥, 勾, 匂, 匙, 叩, 只, 叶, 吃, 吊, 咎, 咳, 唸, 唾, 喉, 喧, 喩, 嗅, 嘘, 嘩, 嘲, 嘴, 噂, 噛, 嚇, 囀]
|
||||||
|
'62': [垢, 堆, 塞, 壺, 夥, 奢, 妬, 姑, 姪, 婉, 嫉, 嬉, 孕, 宛, 宥, 尤, 屓, 嵌, 庇, 弄, 彙, 彷, 徨, 悉, 惚, 惧, 愁, 慌, 戚, 拭, 拶, 挨, 挫, 挽, 捗, 捧, 捲, 捻, 掟, 掬]
|
||||||
|
'63': [掴, 揉, 摺, 撰, 敲, 斡, 斥, 旁, 昏, 昧, 晒, 暈, 暢, 曖, 杖, 杜, 柿, 栗, 桁, 桶, 棘, 棲, 椀, 楊, 楕, 楯, 楷, 槌, 樽, 橙, 檻, 歪, 氾, 汲, 洒, 浚, 涎, 渚, 溜, 溢]
|
||||||
|
'64': [溺, 滲, 漑, 潰, 澱, 濡, 濫, 灌, 炒, 焜, 煉, 煌, 煎, 煽, 爺, 璧, 瓦, 甥, 甦, 痒, 痣, 痩, 痺, 瘤, 癌, 皰, 眉, 眩, 碗, 禿, 稽, 窄, 窪, 窶, 竿, 箋, 簾, 籠, 籤, 絨]
|
||||||
|
'65': [綴, 綻, 緞, 縊, 縋, 縞, 縺, 繕, 罠, 罵, 羨, 耗, 耽, 聊, 肘, 股, 脛, 腫, 膝, 臆, 舅, 舐, 舵, 艶, 苛, 茸, 茣, 莫, 萎, 蒔, 蓋, 蓙, 蔓, 薩, 藁, 蛉, 蛛, 蜘, 蜻, 蝉]
|
||||||
|
'66': [蝕, 螺, 衷, 袖, 袴, 裾, 褄, 褪, 襖, 訛, 訣, 詣, 詫, 誂, 諄, 諦, 謳, 讐, 貌, 貪, 貶, 賑, 賦, 贔, 跨, 跪, 踉, 蹌, 蹲, 蹴, 躇, 躊, 躱, 躾, 輿, 辻, 辿, 迦, 這, 逞]
|
||||||
|
'67': [遡, 遽, 醒, 釘, 銜, 鋸, 錆, 錨, 閃, 閏, 隈, 雀, 雛, 霞, 靡, 鞄, 頓, 頬, 頷, 顎, 餃, 餅, 餌, 餡, 饉, 馴, 骸, 鬘, 鯛, 鯵, 鰯, 鰻, 鱈, 鹸, 麒, 麓, 麟, 黴]
|
||||||
|
'68': [冶, 繭, 但, 頒, 肢, 侯, 遵, 謄, 采, 弐, 朕, 詔, 壱, 丙, 儒, 旺, 嗣, 抄, 嫡, 畝, 虞, 痘, 爵, 墾, 塑, 吏, 附, 宵, 逐, 褐, 楼, 勅, 硝, 逓, 翁, 薫, 厘, 斤, 薪]
|
||||||
|
'69': [汎, 窟, 痕, 串, 刹, 慄, 詮, 曽, 麺, 腎, 沃, 憬, 柵, 僅, 錮, 辣, 踪, 諧, 釜, 舷, 羞, 璽, 淫, 毀, 瘍, 拉, 咽, 緻, 畏, 訃, 冥, 恣, 填, 摯, 斑, 怨, 膳, 臼, 捉, 妖, 蔽, 畿]
|
||||||
|
'70': [迄, 糞, 賜, 猪, 啜, 珈, 琲, 撫, 箒, 叛, 兜, 髭, 鼠, 兎, 稍, 丑, 寅, 卯, 辰, 巳, 酉, 戌, 亥, 蚕, 埃, 伍, 萬]
|
||||||
|
'71-75: 極度 BEYOND':
|
||||||
|
'71': [樺, 脩, 橘, 巴, 渥, 惟, 禎, 苑, 惣, 圭, 祐, 倭, 肇, 漱, 楠, 笹, 晃, 鷹, 耀, 浩, 匡, 晋, 尭, 朋, 喬, 於, 榛, 嵯, 鮎, 絢, 蕉, 巽, 啄, 槙, 彬, 椿, 磯, 怜, 淳]
|
||||||
|
'72': [毅, 彦, 弘, 鴻, 李, 亘, 佑, 鳳, 綜, 悌, 柚, 穣, 碧, 邑, 秦, 皓, 彪, 舜, 允, 偲, 黎, 伽, 朔, 汐, 凱, 甫, 惇, 禄, 皐, 稀, 桐, 琢, 翠, 欽, 慧]
|
||||||
|
'73': [馨, 芹, 孟, 魁, 暉, 毬, 稜, 琉, 槻, 峻, 巌, 洲, 亨, 桂, 玲, 茅, 欣, 郁, 洸, 紘, 稔, 鵬, 敦, 蔦, 芙, 宏, 萩, 嶺, 黛, 旭, 蘭]
|
||||||
|
'74': [眸, 麿, 銑, 鞠, 茉, 燿, 脹, 詢, 蕗, 倖, 嵩, 滉, 伶, 玖, 莞, 錘, 捺, 凜, 裟, 碩, 勺, 頌, 菫, 赳, 彗, 晟, 迪, 袈, 捷, 熙, 柾, 昂, 奎, 丞, 絃, 茄, 胤, 紬, 叡]
|
||||||
|
'75': [椋, 洵, 菖, 勁, 誼, 蓉, 亦, 燎, 瑚, 恕, 耶, 梢, 凪, 衿, 匁, 澪, 梧, 琳, 燦, 晨, 綸, 晏, 昴, 爾, 笙, 侑, 椰, 崚, 侃, 紗, 竣, 柊, 瑶]
|
||||||
|
'76+: 名人 MASTERY':
|
||||||
|
'76': [澤, 嶋, 篠, 幌, 筑, 芦, 幡, 柏, 堺, 梶, 眞, 條, 蘇, 俣, 廣, 磐, 荻, 葛, 蒲, 冨, 國, 栖, 粟, 諏, 函, 淵, 渕, 牟, 畠, 鴨, 宍, 梁, 榊, 樫, 橿, 苅, 釧, 鷲, 杵]
|
||||||
|
'77': [榎, 樋, 櫻, 珂, 砺, 箕, 舘, 苫, 奄, 峯, 廼, 播, 檜, 湘, 濱, 瀧, 瑳, 砥, 祢, 薙, 蛯, 襄, 諫, 讃, 逍, 逗, 鄭, 銚, 騨, 鵜, 齋]
|
||||||
|
'78': [喋, 屁, 繋, 檎, 蛙, 儲, 騙, 揃, 苺, 瀕, 仔, 吠, 牢, 狼, 疹, 萄, 葡, 蕎, 薇, 薔, 覗, 諺, 貰, 飩, 飴, 饂, 茹, 仇, 囁, 晰, 淋, 焚, 葦, 馳, 鮭]
|
||||||
|
'79': [劫, 厭, 呑, 喘, 嚢, 姦, 娶, 娼, 屍, 怯, 恍, 惹, 憊, 捏, 撒, 撼, 擢, 晦, 梗, 梟, 梯, 梳, 棺, 浣, 淹, 漕, 爬, 牝, 牽, 狸, 珊, 癇, 皺, 睨, 瞑, 瞼, 礫]
|
||||||
|
'80': [祷, 窺, 竪, 筏, 糊, 糠, 絆, 罹, 膏, 臥, 苔, 虔, 蛋, 蛭, 蛾, 蝸, 蟻, 蠅, 蠣, 褌, 諜, 踵, 轟, 轢, 鎧, 鞘, 餞, 駝, 駱, 髯, 鮫, 鶯]
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||||
|
|
||||||
|
import { IKanji, WaniKani } from '@/wanikani';
|
||||||
|
import yaml from 'js-yaml';
|
||||||
|
|
||||||
|
interface ILevelMap {
|
||||||
|
[category: string]: {
|
||||||
|
[levelString: string]: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function makeWaniKaniKanjiLevels(opts: { cache?: boolean } = {}) {
|
||||||
|
const FILENAME = 'cache/wanikani-kanji.yaml';
|
||||||
|
if (opts.cache && existsSync(FILENAME)) {
|
||||||
|
return yaml.load(readFileSync(FILENAME, 'utf-8')) as ILevelMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wkKanji = await new WaniKani()
|
||||||
|
.subjects()
|
||||||
|
.then((vs) => vs.filter((v) => v.object === 'kanji') as IKanji[]);
|
||||||
|
|
||||||
|
const levelMap: ILevelMap = {};
|
||||||
|
|
||||||
|
for (const k of wkKanji) {
|
||||||
|
const { level, characters } = k.data;
|
||||||
|
|
||||||
|
let category: string;
|
||||||
|
if (level < 11) {
|
||||||
|
category = '01-10: 快 PLEASANT';
|
||||||
|
} else if (level < 21) {
|
||||||
|
category = '11-21: 苦 PAINFUL';
|
||||||
|
} else if (level < 31) {
|
||||||
|
category = '21-30: 死 DEATH';
|
||||||
|
} else if (level < 41) {
|
||||||
|
category = '31-40: 地獄 HELL';
|
||||||
|
} else if (level < 51) {
|
||||||
|
category = '41-50: 天国 PARADISE';
|
||||||
|
} else {
|
||||||
|
category = '51-60: 現実 REALITY';
|
||||||
|
}
|
||||||
|
|
||||||
|
const catMap = levelMap[category] || {};
|
||||||
|
|
||||||
|
const levelString = level.toString().padStart(2, '0');
|
||||||
|
|
||||||
|
const ks = catMap[levelString] || [];
|
||||||
|
ks.push(characters);
|
||||||
|
catMap[levelString] = ks;
|
||||||
|
|
||||||
|
levelMap[category] = catMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFileSync(
|
||||||
|
FILENAME,
|
||||||
|
yaml.dump(levelMap, {
|
||||||
|
sortKeys: true,
|
||||||
|
flowLevel: 2,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return levelMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function makeKanjiLevels() {
|
||||||
|
const wk = await makeWaniKaniKanjiLevels({ cache: true });
|
||||||
|
const wkKanji = new Set(
|
||||||
|
Object.values(wk).flatMap((v) => Object.values(v).flat()),
|
||||||
|
);
|
||||||
|
|
||||||
|
const beyond = yaml.load(
|
||||||
|
readFileSync('assets/beyond.yaml', 'utf-8'),
|
||||||
|
) as ILevelMap;
|
||||||
|
|
||||||
|
for (const [cat, map] of Object.entries(beyond)) {
|
||||||
|
const catMap = wk[cat] || {};
|
||||||
|
Object.entries(map).map(([levelString, ks]) => {
|
||||||
|
catMap[levelString] = ks.filter((k) => !wkKanji.has(k));
|
||||||
|
});
|
||||||
|
wk[cat] = catMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wk;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function repairBeyond() {
|
||||||
|
const beyond = yaml.load(
|
||||||
|
readFileSync('cache/beyond.yaml', 'utf-8'),
|
||||||
|
) as Record<string, string>;
|
||||||
|
|
||||||
|
const levelMap: ILevelMap = {};
|
||||||
|
|
||||||
|
for (const [levelString, vs] of Object.entries(beyond)) {
|
||||||
|
const level = Number(levelString);
|
||||||
|
|
||||||
|
let category: string;
|
||||||
|
if (level < 71) {
|
||||||
|
category = '61-70: 無限 INFINITY';
|
||||||
|
} else if (level < 76) {
|
||||||
|
category = '71-75: 極度 BEYOND';
|
||||||
|
} else {
|
||||||
|
category = '76+: 名人 MASTERY';
|
||||||
|
}
|
||||||
|
|
||||||
|
const catMap = levelMap[category] || {};
|
||||||
|
|
||||||
|
const ks = catMap[levelString] || [];
|
||||||
|
ks.push(...vs);
|
||||||
|
catMap[levelString] = ks;
|
||||||
|
|
||||||
|
levelMap[category] = catMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFileSync(
|
||||||
|
'assets/beyond.yaml',
|
||||||
|
yaml.dump(levelMap, {
|
||||||
|
sortKeys: true,
|
||||||
|
flowLevel: 2,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
repairBeyond();
|
||||||
|
}
|
||||||
+15
-5
@@ -41,6 +41,20 @@ async function main() {
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
.then((rs) => {
|
.then((rs) => {
|
||||||
|
const cardsByTemplateName = {
|
||||||
|
data: new Map<string, number[]>(),
|
||||||
|
async get(templateName: string) {
|
||||||
|
let v = this.data.get(templateName);
|
||||||
|
if (!v) {
|
||||||
|
v = await anki.api('findCards', {
|
||||||
|
query: `deck:${DECK} card:${templateName}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.data.set(templateName, v);
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
rs
|
rs
|
||||||
.flat()
|
.flat()
|
||||||
@@ -51,11 +65,7 @@ async function main() {
|
|||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
.map(({ templateName, subdeck, cardIdsSet }) =>
|
.map(({ templateName, subdeck, cardIdsSet }) =>
|
||||||
anki
|
cardsByTemplateName.get(templateName).then((cards) =>
|
||||||
.api('findCards', {
|
|
||||||
query: `deck:${DECK} card:${templateName}`,
|
|
||||||
})
|
|
||||||
.then((cards) =>
|
|
||||||
anki.api('changeDeck', {
|
anki.api('changeDeck', {
|
||||||
cards: cards.filter((c) => cardIdsSet.has(c)),
|
cards: cards.filter((c) => cardIdsSet.has(c)),
|
||||||
deck: `${DECK}::${subdeck}::${templateName}`,
|
deck: `${DECK}::${subdeck}::${templateName}`,
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ export class WaniKani {
|
|||||||
} = {}) {
|
} = {}) {
|
||||||
const subjects = {
|
const subjects = {
|
||||||
data: [] as (IKanji | IRadical)[],
|
data: [] as (IKanji | IRadical)[],
|
||||||
filename: 'wanikani.json',
|
filename: 'cache/wanikani.json',
|
||||||
load() {
|
load() {
|
||||||
this.data = JSON.parse(fs.readFileSync(this.filename, 'utf-8'));
|
this.data = JSON.parse(fs.readFileSync(this.filename, 'utf-8'));
|
||||||
return this.data;
|
return this.data;
|
||||||
|
|||||||
Reference in new issue
Block a user