diff --git a/BetterGenshinImpact/App.xaml b/BetterGenshinImpact/App.xaml index 5dd96ec7..3aedc8a1 100644 --- a/BetterGenshinImpact/App.xaml +++ b/BetterGenshinImpact/App.xaml @@ -20,6 +20,7 @@ + diff --git a/BetterGenshinImpact/App.xaml.cs b/BetterGenshinImpact/App.xaml.cs index 3f7acf19..abf1b719 100644 --- a/BetterGenshinImpact/App.xaml.cs +++ b/BetterGenshinImpact/App.xaml.cs @@ -73,6 +73,8 @@ public partial class App : Application Log.Logger = loggerConfiguration.CreateLogger(); services.AddLogging(c => c.AddSerilog()); + services.AddLocalization(); + services.AddNavigationViewPageProvider(); // App Host services.AddHostedService(); diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/._inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/._inference.pdmodel deleted file mode 100644 index 87503bfd..00000000 Binary files a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/._inference.pdmodel and /dev/null differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams b/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams deleted file mode 100644 index 3449efb5..00000000 Binary files a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams and /dev/null differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams.info b/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams.info deleted file mode 100644 index f31a1575..00000000 Binary files a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams.info and /dev/null differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdmodel deleted file mode 100644 index b90c1550..00000000 Binary files a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdmodel and /dev/null differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams new file mode 100644 index 00000000..1b1ea1a9 Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams.info b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams.info new file mode 100644 index 00000000..1cdccfce Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams.info differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdmodel new file mode 100644 index 00000000..95acc925 Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdmodel differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_dict.txt b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_dict.txt new file mode 100644 index 00000000..cc1aa472 --- /dev/null +++ b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_dict.txt @@ -0,0 +1,8421 @@ +! +" +# +$ +% +& +' +( +) +* ++ +, +- +. +/ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +: +; +< += +> +? +@ +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z +[ +\ +] +^ +_ +` +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +{ +| +} +~ +¥ +® +° +± +² +´ +· +» +É +Ë +Ó +× +Ü +à +á +ä +è +é +ì +í +ò +ó +÷ +ú +ü +ā +ē +ī +ō +ū +ǐ +ǒ +ɔ +ɡ +ʌ +ˋ +Λ +Ο +Φ +Ω +α +β +ε +θ +μ +π +З +И +Й +П +Я +г +— +‖ +‘ +’ +“ +” +• +… +‧ +′ +″ +※ +℃ +№ +™ +Ⅱ +Ⅲ +Ⅳ +← +↑ +→ +↓ +⇋ +∈ +∑ +√ +∞ +∣ +∧ +∩ +∫ +∶ +≈ +≠ +≤ +≥ +⊙ +⊥ +① +② +③ +④ +⑧ +⑴ +⑵ +⑶ +─ +│ +┅ +┌ +├ +█ +▎ +▏ +▕ +■ +□ +▪ +▲ +△ +▼ +◆ +◇ +○ +◎ +● +◥ +★ +☆ +❋ +❤ +  +、 +。 +〇 +〉 +《 +》 +「 +」 +『 +』 +【 +】 +〔 +〕 +〖 +〗 +の +サ +シ +ジ +マ +ㄱ +ㆍ +㎏ +㎡ +㐂 +㐱 +㙟 +㴪 +㸃 +䖝 +䝉 +䰾 +䲁 +一 +丁 +七 +丄 +丈 +三 +上 +下 +丌 +不 +与 +丏 +丐 +丑 +且 +丕 +世 +丘 +丙 +丞 +丟 +両 +並 +丨 +丫 +中 +丰 +串 +丶 +丸 +丹 +主 +丼 +丿 +乂 +乃 +久 +么 +之 +乍 +乎 +乏 +乒 +乓 +乖 +乗 +乘 +乙 +乚 +乜 +九 +乞 +也 +乩 +乭 +乳 +乸 +乹 +乾 +亀 +亂 +亅 +了 +予 +亊 +事 +二 +亍 +云 +互 +亓 +五 +井 +亘 +些 +亜 +亞 +亟 +亠 +亡 +亢 +交 +亥 +亦 +亨 +享 +京 +亭 +亮 +亰 +亳 +亶 +亹 +人 +亻 +什 +仁 +仂 +仃 +仄 +仇 +仉 +今 +介 +仍 +仏 +仔 +仕 +他 +仗 +付 +仙 +仛 +仝 +仞 +仟 +仡 +代 +令 +以 +仨 +仫 +仮 +仰 +仲 +仳 +仵 +件 +仺 +任 +仼 +份 +仿 +企 +伃 +伈 +伉 +伊 +伋 +伍 +伎 +伏 +伐 +休 +伕 +伙 +伝 +伢 +伯 +估 +伱 +伴 +伶 +伷 +伸 +伺 +似 +伽 +伾 +佀 +佁 +佃 +但 +佇 +佈 +佉 +佋 +位 +低 +住 +佐 +佑 +体 +佔 +何 +佗 +佘 +余 +佚 +佛 +作 +佝 +佞 +佟 +你 +佣 +佤 +佧 +佩 +佬 +佯 +佰 +佳 +併 +佶 +佹 +佺 +佼 +佾 +使 +侁 +侃 +侄 +侅 +來 +侈 +侊 +例 +侍 +侏 +侑 +侖 +侗 +侘 +侚 +供 +依 +侞 +価 +侮 +侯 +侵 +侶 +侷 +侹 +便 +俁 +係 +促 +俄 +俅 +俊 +俋 +俌 +俍 +俎 +俏 +俐 +俑 +俗 +俘 +俚 +俛 +保 +俞 +俟 +俠 +信 +俬 +修 +俯 +俱 +俳 +俴 +俵 +俶 +俸 +俺 +俽 +俾 +倆 +倈 +倉 +個 +倌 +倍 +們 +倒 +倓 +倔 +倖 +倗 +倘 +候 +倚 +倜 +倞 +借 +倡 +倢 +倣 +値 +倦 +倧 +倩 +倪 +倫 +倬 +倭 +倮 +倻 +值 +偁 +偃 +假 +偈 +偉 +偊 +偌 +偍 +偎 +偏 +偓 +偕 +做 +停 +健 +偪 +偲 +側 +偵 +偶 +偷 +偸 +偽 +傀 +傃 +傅 +傈 +傉 +傍 +傑 +傒 +傕 +傖 +傘 +備 +傜 +傢 +傣 +催 +傭 +傲 +傳 +債 +傷 +傻 +傾 +僅 +僉 +僊 +働 +像 +僑 +僔 +僕 +僖 +僙 +僚 +僜 +僡 +僧 +僩 +僭 +僮 +僰 +僱 +僳 +僴 +僵 +價 +僻 +儀 +儁 +儂 +億 +儆 +儇 +儈 +儉 +儋 +儐 +儒 +儔 +儕 +儘 +儚 +儞 +償 +儡 +儥 +儦 +優 +儫 +儱 +儲 +儷 +儺 +儻 +儼 +兀 +允 +元 +兄 +充 +兆 +先 +光 +克 +兌 +免 +児 +兒 +兔 +兕 +兗 +兜 +入 +內 +全 +兩 +兪 +八 +公 +六 +兮 +共 +兵 +其 +具 +典 +兼 +兿 +冀 +冂 +円 +冇 +冉 +冊 +再 +冏 +冑 +冒 +冕 +冖 +冗 +冚 +冠 +冢 +冤 +冥 +冧 +冨 +冪 +冫 +冬 +冮 +冰 +冴 +冶 +冷 +冼 +冽 +凃 +凄 +准 +凈 +凋 +凌 +凍 +凖 +凜 +凝 +凞 +几 +凡 +処 +凪 +凬 +凰 +凱 +凳 +凵 +凶 +凸 +凹 +出 +函 +刀 +刁 +刂 +刃 +刄 +分 +切 +刈 +刊 +刎 +刑 +划 +列 +初 +判 +別 +刦 +刧 +刨 +利 +刪 +刮 +到 +制 +刷 +券 +刺 +刻 +刼 +剁 +剃 +則 +削 +剋 +剌 +前 +剎 +剏 +剔 +剖 +剛 +剝 +剡 +剣 +剩 +剪 +剮 +副 +割 +創 +剿 +劃 +劄 +劇 +劈 +劉 +劊 +劌 +劍 +劑 +劔 +力 +功 +加 +劣 +助 +努 +劫 +劬 +劭 +劵 +効 +劼 +劾 +勁 +勃 +勅 +勇 +勉 +勐 +勑 +勒 +勔 +動 +勖 +勗 +勘 +務 +勛 +勝 +勞 +募 +勢 +勣 +勤 +勦 +勰 +勱 +勲 +勳 +勵 +勷 +勸 +勺 +勻 +勾 +勿 +匂 +匄 +包 +匆 +匈 +匋 +匍 +匏 +匐 +匕 +化 +北 +匙 +匚 +匝 +匠 +匡 +匣 +匪 +匯 +匱 +匸 +匹 +匾 +匿 +區 +十 +千 +卅 +升 +午 +卉 +半 +卋 +卍 +卐 +卑 +卒 +卓 +協 +南 +博 +卜 +卞 +卟 +占 +卡 +卣 +卦 +卧 +卩 +卬 +卮 +卯 +印 +危 +卲 +即 +卵 +卷 +卸 +卹 +卺 +卻 +卽 +卿 +厄 +厓 +厔 +厙 +厚 +厝 +原 +厥 +厭 +厰 +厲 +厴 +厶 +去 +參 +叄 +又 +叉 +及 +友 +反 +収 +叔 +叕 +取 +受 +叛 +叟 +叡 +叢 +口 +古 +句 +另 +叨 +叩 +只 +叫 +召 +叭 +叮 +可 +台 +叱 +史 +右 +叵 +司 +叻 +叼 +吁 +吃 +各 +吆 +合 +吉 +吊 +吋 +同 +名 +后 +吏 +吐 +向 +吒 +吔 +吖 +君 +吝 +吞 +吟 +吠 +吡 +吥 +否 +吧 +吩 +含 +吮 +吱 +吲 +吳 +吵 +吶 +吸 +吹 +吻 +吼 +吾 +呀 +呂 +呃 +呈 +呉 +告 +呋 +呎 +呢 +呤 +呦 +周 +呱 +味 +呵 +呷 +呸 +呼 +命 +呾 +咀 +咁 +咂 +咄 +咅 +咆 +咋 +和 +咎 +咑 +咒 +咔 +咕 +咖 +咗 +咘 +咚 +咟 +咤 +咥 +咧 +咨 +咩 +咪 +咫 +咬 +咭 +咯 +咱 +咲 +咳 +咸 +咻 +咼 +咽 +咾 +咿 +哀 +品 +哂 +哄 +哆 +哇 +哈 +哉 +哌 +哎 +哏 +哐 +哖 +哚 +哞 +員 +哥 +哦 +哨 +哩 +哪 +哭 +哮 +哱 +哲 +哺 +哼 +唃 +唄 +唆 +唇 +唉 +唏 +唐 +唑 +唔 +唘 +唧 +唫 +唬 +唭 +售 +唯 +唱 +唳 +唵 +唷 +唸 +唻 +唾 +啁 +啃 +啄 +商 +啉 +啊 +啍 +問 +啓 +啖 +啚 +啜 +啞 +啟 +啡 +啣 +啤 +啥 +啦 +啪 +啫 +啯 +啰 +啱 +啲 +啵 +啶 +啷 +啻 +啼 +啾 +喀 +喂 +喃 +善 +喆 +喇 +喈 +喉 +喊 +喋 +喏 +喔 +喘 +喙 +喚 +喜 +喝 +喢 +喦 +喧 +喪 +喫 +喬 +單 +喰 +喱 +喲 +喳 +喵 +喹 +喻 +喼 +嗄 +嗅 +嗆 +嗇 +嗊 +嗎 +嗑 +嗒 +嗓 +嗔 +嗖 +嗚 +嗜 +嗝 +嗞 +嗡 +嗢 +嗣 +嗦 +嗨 +嗩 +嗪 +嗮 +嗯 +嗲 +嗶 +嗹 +嗽 +嘀 +嘅 +嘆 +嘉 +嘌 +嘍 +嘎 +嘏 +嘔 +嘗 +嘚 +嘛 +嘜 +嘞 +嘟 +嘢 +嘣 +嘥 +嘧 +嘩 +嘬 +嘮 +嘯 +嘰 +嘲 +嘴 +嘶 +嘸 +嘹 +嘻 +嘿 +噁 +噌 +噍 +噏 +噓 +噗 +噝 +噠 +噢 +噤 +噥 +噦 +器 +噩 +噪 +噬 +噯 +噰 +噲 +噴 +噶 +噸 +噹 +噻 +嚇 +嚈 +嚎 +嚏 +嚐 +嚒 +嚓 +嚕 +嚗 +嚙 +嚞 +嚟 +嚤 +嚦 +嚧 +嚨 +嚩 +嚮 +嚳 +嚴 +嚶 +嚷 +嚼 +嚿 +囀 +囂 +囃 +囉 +囊 +囍 +囑 +囒 +囓 +囗 +囚 +四 +囝 +回 +因 +囡 +団 +囤 +囧 +囪 +囮 +囯 +困 +囲 +図 +囶 +囷 +囹 +固 +囿 +圂 +圃 +圄 +圈 +圉 +國 +圍 +圏 +園 +圓 +圖 +圗 +團 +圜 +土 +圧 +在 +圩 +圪 +圭 +圯 +地 +圳 +圻 +圾 +址 +均 +坊 +坋 +坌 +坍 +坎 +坐 +坑 +坖 +坡 +坣 +坤 +坦 +坨 +坩 +坪 +坫 +坬 +坭 +坮 +坯 +坳 +坵 +坶 +坷 +坻 +垂 +垃 +垈 +型 +垍 +垓 +垕 +垚 +垛 +垞 +垟 +垠 +垢 +垣 +垮 +垯 +垰 +垵 +垸 +垻 +垿 +埃 +埅 +埇 +埈 +埋 +埌 +城 +埏 +埒 +埔 +埕 +埗 +埜 +域 +埠 +埡 +埤 +埧 +埨 +埪 +埭 +埮 +埴 +埵 +執 +培 +基 +埻 +埼 +堀 +堂 +堃 +堅 +堆 +堇 +堈 +堉 +堊 +堍 +堖 +堝 +堡 +堤 +堦 +堪 +堮 +堯 +堰 +報 +場 +堵 +堷 +堺 +塀 +塅 +塆 +塊 +塋 +塌 +塍 +塏 +塑 +塔 +塗 +塘 +塙 +塜 +塞 +塡 +塢 +塤 +塨 +塩 +填 +塬 +塭 +塰 +塱 +塲 +塵 +塹 +塽 +塾 +墀 +境 +墅 +墉 +墊 +墎 +墓 +増 +墘 +墜 +增 +墟 +墡 +墣 +墨 +墩 +墫 +墬 +墮 +墱 +墳 +墺 +墼 +墾 +壁 +壄 +壆 +壇 +壋 +壌 +壎 +壐 +壑 +壓 +壔 +壕 +壘 +壙 +壞 +壟 +壠 +壢 +壤 +壩 +士 +壬 +壯 +壱 +壴 +壹 +壺 +壽 +夀 +夆 +変 +夊 +夋 +夌 +夏 +夔 +夕 +外 +夙 +多 +夜 +夠 +夢 +夤 +夥 +大 +天 +太 +夫 +夬 +夭 +央 +夯 +失 +夷 +夾 +奀 +奄 +奇 +奈 +奉 +奎 +奏 +奐 +契 +奓 +奔 +奕 +套 +奘 +奚 +奠 +奢 +奣 +奧 +奩 +奪 +奫 +奭 +奮 +女 +奴 +奶 +她 +好 +妀 +妁 +如 +妃 +妄 +妊 +妍 +妏 +妑 +妒 +妓 +妖 +妙 +妝 +妞 +妠 +妤 +妥 +妧 +妨 +妭 +妮 +妯 +妲 +妳 +妸 +妹 +妺 +妻 +妾 +姀 +姁 +姃 +姆 +姈 +姉 +姊 +始 +姌 +姍 +姐 +姑 +姒 +姓 +委 +姚 +姜 +姝 +姣 +姥 +姦 +姨 +姪 +姫 +姬 +姮 +姵 +姶 +姸 +姻 +姿 +威 +娃 +娉 +娋 +娌 +娍 +娎 +娑 +娖 +娘 +娛 +娜 +娟 +娠 +娣 +娥 +娩 +娫 +娳 +娶 +娸 +娼 +娽 +婀 +婁 +婆 +婉 +婊 +婑 +婕 +婚 +婢 +婦 +婧 +婪 +婭 +婯 +婷 +婺 +婻 +婼 +婿 +媃 +媄 +媊 +媐 +媒 +媓 +媖 +媗 +媚 +媛 +媜 +媞 +媧 +媭 +媯 +媲 +媳 +媺 +媼 +媽 +媾 +媿 +嫁 +嫂 +嫄 +嫈 +嫉 +嫌 +嫖 +嫘 +嫚 +嫡 +嫣 +嫦 +嫩 +嫪 +嫲 +嫳 +嫵 +嫺 +嫻 +嬅 +嬈 +嬉 +嬋 +嬌 +嬗 +嬛 +嬝 +嬡 +嬤 +嬨 +嬪 +嬬 +嬭 +嬰 +嬴 +嬸 +嬾 +嬿 +孀 +孃 +孆 +孋 +孌 +子 +孑 +孔 +孕 +孖 +字 +存 +孚 +孛 +孜 +孝 +孟 +孢 +季 +孤 +孩 +孫 +孬 +孮 +孰 +孳 +孵 +學 +孺 +孻 +孽 +孿 +宀 +它 +宅 +宇 +守 +安 +宋 +完 +宍 +宏 +宓 +宕 +宗 +官 +宙 +定 +宛 +宜 +実 +客 +宣 +室 +宥 +宦 +宧 +宮 +宰 +害 +宴 +宵 +家 +宸 +容 +宿 +寀 +寁 +寂 +寄 +寅 +密 +寇 +寈 +寊 +富 +寐 +寒 +寓 +寔 +寕 +寖 +寗 +寘 +寛 +寜 +寞 +察 +寡 +寢 +寤 +寥 +實 +寧 +寨 +審 +寫 +寬 +寮 +寯 +寰 +寳 +寵 +寶 +寸 +寺 +対 +封 +専 +尃 +射 +將 +專 +尉 +尊 +尋 +對 +導 +小 +尐 +少 +尓 +尕 +尖 +尗 +尙 +尚 +尢 +尤 +尨 +尪 +尬 +就 +尷 +尹 +尺 +尻 +尼 +尾 +尿 +局 +屁 +屄 +居 +屆 +屇 +屈 +屋 +屌 +屍 +屎 +屏 +屐 +屑 +屓 +展 +屚 +屜 +屠 +屢 +層 +履 +屬 +屭 +屯 +山 +屹 +屺 +屻 +岀 +岈 +岌 +岐 +岑 +岔 +岡 +岢 +岣 +岧 +岩 +岪 +岫 +岬 +岰 +岱 +岳 +岵 +岷 +岸 +岻 +峁 +峅 +峇 +峋 +峍 +峒 +峘 +峙 +峚 +峠 +峨 +峩 +峪 +峭 +峯 +峰 +峴 +島 +峻 +峼 +峽 +崁 +崆 +崇 +崈 +崋 +崍 +崎 +崐 +崑 +崒 +崔 +崖 +崗 +崘 +崙 +崚 +崛 +崞 +崟 +崠 +崢 +崤 +崧 +崩 +崬 +崮 +崱 +崴 +崵 +崶 +崽 +嵇 +嵊 +嵋 +嵌 +嵎 +嵐 +嵒 +嵕 +嵖 +嵗 +嵙 +嵛 +嵜 +嵨 +嵩 +嵬 +嵮 +嵯 +嵰 +嵴 +嵻 +嵿 +嶁 +嶂 +嶃 +嶄 +嶇 +嶋 +嶌 +嶍 +嶒 +嶔 +嶗 +嶝 +嶠 +嶢 +嶦 +嶧 +嶪 +嶬 +嶰 +嶲 +嶴 +嶷 +嶸 +嶺 +嶼 +嶽 +巂 +巄 +巆 +巋 +巌 +巍 +巎 +巑 +巒 +巔 +巖 +巘 +巛 +川 +州 +巡 +巢 +工 +左 +巧 +巨 +巫 +差 +巰 +己 +已 +巳 +巴 +巶 +巷 +巻 +巽 +巾 +巿 +市 +布 +帆 +希 +帑 +帔 +帕 +帖 +帘 +帙 +帚 +帛 +帝 +帡 +帢 +帥 +師 +席 +帯 +帰 +帳 +帶 +帷 +常 +帽 +幀 +幃 +幄 +幅 +幌 +幔 +幕 +幗 +幚 +幛 +幟 +幡 +幢 +幣 +幪 +幫 +干 +平 +年 +幵 +幷 +幸 +幹 +幺 +幻 +幼 +幽 +幾 +庀 +庁 +広 +庇 +床 +序 +底 +庖 +店 +庚 +府 +庠 +庢 +庥 +度 +座 +庫 +庭 +庲 +庵 +庶 +康 +庸 +庹 +庼 +庾 +廁 +廂 +廄 +廆 +廈 +廉 +廊 +廋 +廌 +廍 +廑 +廓 +廔 +廕 +廖 +廙 +廚 +廝 +廞 +廟 +廠 +廡 +廢 +廣 +廧 +廨 +廩 +廬 +廰 +廱 +廳 +延 +廷 +廸 +建 +廻 +廼 +廿 +弁 +弄 +弅 +弇 +弈 +弉 +弊 +弋 +弍 +式 +弐 +弒 +弓 +弔 +引 +弖 +弗 +弘 +弛 +弟 +弢 +弦 +弧 +弨 +弩 +弭 +弱 +張 +強 +弸 +弼 +弾 +彀 +彄 +彅 +彆 +彈 +彊 +彌 +彎 +彐 +彔 +彖 +彗 +彘 +彙 +彜 +彞 +彠 +彡 +形 +彣 +彤 +彥 +彧 +彩 +彪 +彫 +彬 +彭 +彰 +影 +彳 +彷 +役 +彼 +彿 +往 +征 +徂 +待 +徇 +很 +徉 +徊 +律 +後 +徐 +徑 +徒 +得 +徘 +徙 +徜 +從 +徠 +御 +徧 +徨 +復 +循 +徫 +徬 +徭 +微 +徳 +徴 +徵 +德 +徸 +徹 +徽 +心 +忄 +必 +忉 +忌 +忍 +忐 +忑 +忒 +志 +忘 +忙 +応 +忝 +忞 +忠 +快 +忬 +忯 +忱 +忳 +念 +忻 +忽 +忿 +怍 +怎 +怒 +怕 +怖 +怙 +怛 +思 +怠 +怡 +急 +怦 +性 +怨 +怪 +怯 +怵 +恁 +恂 +恃 +恆 +恊 +恍 +恐 +恕 +恙 +恢 +恣 +恤 +恥 +恨 +恩 +恪 +恬 +恭 +息 +恰 +恵 +恿 +悄 +悅 +悆 +悉 +悌 +悍 +悔 +悖 +悚 +悛 +悝 +悞 +悟 +悠 +患 +悧 +您 +悪 +悰 +悲 +悳 +悵 +悶 +悸 +悼 +情 +惆 +惇 +惑 +惔 +惕 +惘 +惚 +惜 +惟 +惠 +惡 +惣 +惦 +惰 +惱 +惲 +想 +惶 +惹 +惺 +愁 +愃 +愆 +愈 +愉 +愍 +意 +愐 +愒 +愔 +愕 +愚 +愛 +愜 +感 +愣 +愧 +愨 +愫 +愭 +愴 +愷 +愼 +愾 +愿 +慄 +慈 +態 +慌 +慎 +慕 +慘 +慚 +慜 +慟 +慢 +慣 +慥 +慧 +慨 +慮 +慰 +慳 +慵 +慶 +慷 +慾 +憂 +憊 +憋 +憍 +憎 +憐 +憑 +憓 +憕 +憙 +憚 +憤 +憧 +憨 +憩 +憫 +憬 +憲 +憶 +憺 +憻 +憾 +懂 +懃 +懇 +懈 +應 +懋 +懌 +懍 +懐 +懣 +懦 +懮 +懲 +懵 +懶 +懷 +懸 +懺 +懼 +懽 +懾 +懿 +戀 +戇 +戈 +戊 +戌 +戍 +戎 +成 +我 +戒 +戔 +戕 +或 +戙 +戚 +戛 +戟 +戡 +戢 +戥 +戦 +戩 +截 +戮 +戰 +戱 +戲 +戳 +戴 +戶 +戸 +戻 +戽 +戾 +房 +所 +扁 +扆 +扇 +扈 +扉 +手 +扌 +才 +扎 +扒 +打 +扔 +托 +扙 +扛 +扞 +扣 +扥 +扦 +扭 +扮 +扯 +扳 +扶 +批 +扼 +找 +承 +技 +抃 +抄 +抇 +抉 +把 +抑 +抒 +抓 +投 +抖 +抗 +折 +抦 +披 +抬 +抱 +抵 +抹 +抻 +押 +抽 +抿 +拂 +拆 +拇 +拈 +拉 +拋 +拌 +拍 +拎 +拏 +拐 +拒 +拓 +拔 +拖 +拗 +拘 +拙 +拚 +招 +拜 +拝 +拡 +括 +拭 +拮 +拯 +拱 +拳 +拴 +拷 +拺 +拼 +拽 +拾 +拿 +持 +指 +按 +挎 +挑 +挖 +挙 +挨 +挪 +挫 +振 +挲 +挵 +挹 +挺 +挻 +挾 +捂 +捆 +捉 +捌 +捍 +捎 +捏 +捐 +捒 +捕 +捜 +捦 +捧 +捨 +捩 +捫 +捭 +捱 +捲 +捶 +捷 +捺 +捻 +掀 +掂 +掃 +掄 +掇 +授 +掉 +掌 +掏 +掐 +排 +掖 +掘 +掙 +掛 +掞 +掟 +掠 +採 +探 +掣 +接 +控 +推 +掩 +措 +掬 +掰 +掾 +揀 +揄 +揆 +揉 +揍 +描 +提 +插 +揔 +揖 +揚 +換 +握 +揪 +揭 +揮 +援 +揸 +揺 +損 +搏 +搐 +搓 +搔 +搖 +搗 +搜 +搞 +搠 +搢 +搪 +搬 +搭 +搳 +搴 +搵 +搶 +搽 +搾 +摂 +摒 +摔 +摘 +摜 +摞 +摟 +摠 +摧 +摩 +摭 +摯 +摳 +摴 +摵 +摶 +摸 +摹 +摺 +摻 +摽 +撃 +撇 +撈 +撐 +撒 +撓 +撕 +撖 +撙 +撚 +撞 +撣 +撤 +撥 +撩 +撫 +撬 +播 +撮 +撰 +撲 +撳 +撻 +撼 +撾 +撿 +擀 +擁 +擂 +擅 +擇 +擊 +擋 +操 +擎 +擒 +擔 +擘 +據 +擠 +擢 +擥 +擦 +擬 +擯 +擰 +擱 +擲 +擴 +擷 +擺 +擼 +擾 +攀 +攏 +攔 +攖 +攘 +攜 +攝 +攞 +攢 +攣 +攤 +攪 +攫 +攬 +支 +攴 +攵 +收 +攷 +攸 +改 +攻 +攽 +放 +政 +故 +效 +敍 +敎 +敏 +救 +敔 +敕 +敖 +敗 +敘 +教 +敝 +敞 +敟 +敢 +散 +敦 +敫 +敬 +敭 +敲 +整 +敵 +敷 +數 +敻 +敾 +斂 +斃 +文 +斌 +斎 +斐 +斑 +斕 +斖 +斗 +料 +斛 +斜 +斝 +斟 +斡 +斤 +斥 +斧 +斬 +斯 +新 +斷 +方 +於 +施 +斿 +旁 +旂 +旃 +旄 +旅 +旉 +旋 +旌 +旎 +族 +旖 +旗 +旙 +旛 +旡 +既 +日 +旦 +旨 +早 +旬 +旭 +旱 +旲 +旳 +旺 +旻 +旼 +旽 +旾 +旿 +昀 +昂 +昃 +昆 +昇 +昉 +昊 +昌 +昍 +明 +昏 +昐 +易 +昔 +昕 +昚 +昛 +昜 +昝 +昞 +星 +映 +昡 +昣 +昤 +春 +昧 +昨 +昪 +昫 +昭 +是 +昰 +昱 +昴 +昵 +昶 +昺 +晁 +時 +晃 +晈 +晉 +晊 +晏 +晗 +晙 +晚 +晛 +晝 +晞 +晟 +晤 +晦 +晧 +晨 +晩 +晪 +晫 +晭 +普 +景 +晰 +晳 +晴 +晶 +晷 +晸 +智 +晾 +暃 +暄 +暅 +暇 +暈 +暉 +暊 +暌 +暎 +暏 +暐 +暑 +暕 +暖 +暗 +暘 +暝 +暟 +暠 +暢 +暦 +暨 +暫 +暮 +暱 +暲 +暴 +暸 +暹 +暻 +暾 +曄 +曅 +曆 +曇 +曉 +曌 +曔 +曖 +曙 +曜 +曝 +曠 +曦 +曧 +曨 +曩 +曬 +曮 +曰 +曲 +曳 +更 +曶 +曷 +書 +曹 +曺 +曼 +曽 +曾 +替 +最 +會 +月 +有 +朊 +朋 +服 +朏 +朐 +朓 +朔 +朕 +朖 +朗 +望 +朝 +期 +朦 +朧 +木 +未 +末 +本 +札 +朱 +朴 +朵 +朶 +朽 +朿 +杁 +杉 +杋 +杌 +李 +杏 +材 +村 +杓 +杖 +杙 +杜 +杞 +束 +杠 +杣 +杤 +杧 +杬 +杭 +杯 +東 +杲 +杳 +杴 +杵 +杷 +杻 +杼 +松 +板 +极 +枇 +枉 +枋 +枏 +析 +枕 +枖 +林 +枚 +枛 +果 +枝 +枠 +枡 +枯 +枰 +枱 +枲 +枳 +架 +枷 +枸 +枹 +枼 +柁 +柃 +柄 +柉 +柊 +柎 +柏 +某 +柑 +柒 +染 +柔 +柘 +柚 +柜 +柝 +柞 +柟 +查 +柩 +柬 +柯 +柰 +柱 +柳 +柴 +柵 +柶 +柷 +査 +柾 +柿 +栃 +栄 +栐 +栒 +栓 +栜 +栝 +栞 +校 +栢 +栨 +栩 +株 +栲 +栴 +核 +根 +栻 +格 +栽 +桀 +桁 +桂 +桃 +桄 +桅 +框 +案 +桉 +桌 +桎 +桐 +桑 +桓 +桔 +桕 +桖 +桙 +桜 +桝 +桫 +桱 +桲 +桴 +桶 +桷 +桼 +桿 +梀 +梁 +梂 +梃 +梅 +梆 +梉 +梏 +梓 +梔 +梗 +梘 +條 +梟 +梠 +梢 +梣 +梧 +梨 +梫 +梭 +梯 +械 +梱 +梳 +梵 +梶 +梽 +棄 +棆 +棉 +棋 +棍 +棐 +棒 +棓 +棕 +棖 +棗 +棘 +棚 +棛 +棟 +棠 +棡 +棣 +棧 +棨 +棩 +棪 +棫 +森 +棱 +棲 +棵 +棶 +棹 +棺 +棻 +棼 +棽 +椅 +椆 +椇 +椋 +植 +椎 +椏 +椒 +椙 +椥 +椪 +椰 +椲 +椴 +椵 +椹 +椽 +椿 +楂 +楊 +楓 +楔 +楗 +楙 +楚 +楝 +楞 +楠 +楡 +楢 +楣 +楤 +楦 +楧 +楨 +楫 +業 +楮 +楯 +楳 +極 +楷 +楸 +楹 +楽 +楿 +概 +榆 +榊 +榍 +榎 +榑 +榔 +榕 +榖 +榗 +榘 +榛 +榜 +榞 +榢 +榣 +榤 +榦 +榧 +榨 +榫 +榭 +榮 +榲 +榴 +榷 +榻 +榿 +槀 +槁 +槃 +槊 +構 +槌 +槍 +槎 +槐 +槓 +槔 +槗 +様 +槙 +槤 +槩 +槭 +槰 +槱 +槲 +槳 +槺 +槻 +槼 +槽 +槿 +樀 +樁 +樂 +樅 +樆 +樊 +樋 +樑 +樓 +樗 +樘 +標 +樞 +樟 +模 +樣 +樨 +権 +樫 +樵 +樸 +樹 +樺 +樻 +樽 +樾 +橄 +橇 +橈 +橋 +橐 +橒 +橓 +橘 +橙 +橚 +機 +橡 +橢 +橪 +橫 +橿 +檀 +檄 +檇 +檉 +檊 +檎 +檐 +檔 +檗 +檜 +檞 +檠 +檡 +檢 +檣 +檦 +檨 +檫 +檬 +檯 +檳 +檵 +檸 +檻 +檽 +櫂 +櫃 +櫆 +櫈 +櫓 +櫚 +櫛 +櫞 +櫟 +櫥 +櫨 +櫪 +櫱 +櫸 +櫻 +櫾 +櫿 +欄 +欉 +權 +欏 +欒 +欖 +欞 +欠 +次 +欣 +欥 +欲 +欸 +欹 +欺 +欽 +款 +歆 +歇 +歉 +歊 +歌 +歎 +歐 +歓 +歙 +歛 +歡 +止 +正 +此 +步 +武 +歧 +歩 +歪 +歲 +歳 +歴 +歷 +歸 +歹 +死 +歿 +殂 +殃 +殄 +殆 +殉 +殊 +殑 +殖 +殘 +殛 +殞 +殟 +殤 +殭 +殮 +殯 +殲 +殳 +段 +殷 +殺 +殻 +殼 +殿 +毀 +毅 +毆 +毉 +毋 +毌 +母 +毎 +每 +毐 +毒 +毓 +比 +毖 +毗 +毘 +毛 +毫 +毬 +毯 +毴 +毸 +毽 +毿 +氂 +氈 +氍 +氏 +氐 +民 +氓 +氖 +気 +氘 +氙 +氚 +氛 +氟 +氣 +氦 +氧 +氨 +氪 +氫 +氬 +氮 +氯 +氰 +水 +氵 +氷 +永 +氹 +氻 +氽 +氾 +汀 +汁 +求 +汊 +汎 +汐 +汕 +汗 +汛 +汜 +汝 +汞 +江 +池 +污 +汧 +汨 +汩 +汪 +汭 +汰 +汲 +汴 +汶 +決 +汽 +汾 +沁 +沂 +沃 +沄 +沅 +沆 +沇 +沈 +沉 +沌 +沍 +沏 +沐 +沒 +沓 +沔 +沖 +沘 +沙 +沚 +沛 +沜 +沢 +沨 +沫 +沭 +沮 +沯 +沱 +河 +沸 +油 +沺 +治 +沼 +沽 +沾 +沿 +況 +泂 +泄 +泆 +泇 +泉 +泊 +泌 +泐 +泓 +泔 +法 +泖 +泗 +泚 +泛 +泠 +泡 +波 +泣 +泥 +泩 +泫 +泮 +泯 +泰 +泱 +泳 +泵 +洄 +洋 +洌 +洎 +洗 +洙 +洛 +洞 +洢 +洣 +洤 +津 +洨 +洩 +洪 +洮 +洱 +洲 +洳 +洵 +洸 +洹 +洺 +活 +洽 +派 +流 +浄 +浙 +浚 +浛 +浜 +浞 +浟 +浠 +浡 +浣 +浤 +浥 +浦 +浩 +浪 +浮 +浯 +浴 +浵 +海 +浸 +浹 +涅 +涇 +消 +涉 +涌 +涎 +涑 +涓 +涔 +涕 +涙 +涪 +涫 +涮 +涯 +液 +涵 +涸 +涼 +涿 +淄 +淅 +淆 +淇 +淋 +淌 +淍 +淎 +淏 +淑 +淓 +淖 +淘 +淙 +淚 +淛 +淝 +淞 +淠 +淡 +淤 +淥 +淦 +淨 +淩 +淪 +淫 +淬 +淮 +淯 +淰 +深 +淳 +淵 +淶 +混 +淸 +淹 +淺 +添 +淼 +淽 +渃 +清 +済 +渉 +渋 +渕 +渙 +渚 +減 +渝 +渟 +渠 +渡 +渣 +渤 +渥 +渦 +渫 +測 +渭 +港 +渲 +渴 +游 +渺 +渼 +渽 +渾 +湃 +湄 +湉 +湊 +湍 +湓 +湔 +湖 +湘 +湛 +湜 +湞 +湟 +湣 +湥 +湧 +湫 +湮 +湯 +湳 +湴 +湼 +満 +溁 +溇 +溈 +溉 +溋 +溎 +溏 +源 +準 +溙 +溜 +溝 +溟 +溢 +溥 +溦 +溧 +溪 +溫 +溯 +溱 +溲 +溴 +溵 +溶 +溺 +溼 +滀 +滁 +滂 +滄 +滅 +滇 +滈 +滉 +滋 +滌 +滎 +滏 +滑 +滓 +滔 +滕 +滘 +滙 +滝 +滬 +滯 +滲 +滴 +滷 +滸 +滹 +滻 +滽 +滾 +滿 +漁 +漂 +漆 +漇 +漈 +漎 +漏 +漓 +演 +漕 +漚 +漠 +漢 +漣 +漩 +漪 +漫 +漬 +漯 +漱 +漲 +漳 +漴 +漵 +漷 +漸 +漼 +漾 +漿 +潁 +潑 +潔 +潘 +潛 +潞 +潟 +潢 +潤 +潭 +潮 +潯 +潰 +潲 +潺 +潼 +潽 +潾 +潿 +澀 +澁 +澂 +澄 +澆 +澇 +澈 +澉 +澋 +澌 +澍 +澎 +澔 +澗 +澠 +澡 +澣 +澤 +澥 +澧 +澪 +澮 +澯 +澱 +澳 +澶 +澹 +澻 +激 +濁 +濂 +濃 +濉 +濊 +濋 +濕 +濘 +濙 +濛 +濞 +濟 +濠 +濡 +濤 +濫 +濬 +濮 +濯 +濰 +濱 +濲 +濶 +濺 +濼 +濾 +瀁 +瀅 +瀆 +瀉 +瀍 +瀏 +瀑 +瀔 +瀕 +瀘 +瀚 +瀛 +瀝 +瀞 +瀟 +瀠 +瀣 +瀦 +瀧 +瀨 +瀬 +瀰 +瀲 +瀴 +瀶 +瀹 +瀾 +灃 +灊 +灌 +灑 +灘 +灝 +灞 +灡 +灣 +灤 +灧 +火 +灰 +灴 +灸 +灼 +災 +炁 +炅 +炆 +炊 +炎 +炒 +炔 +炕 +炘 +炙 +炟 +炣 +炤 +炫 +炬 +炭 +炮 +炯 +炱 +炲 +炳 +炷 +炸 +為 +炻 +烈 +烉 +烊 +烋 +烏 +烒 +烔 +烘 +烙 +烜 +烝 +烤 +烯 +烱 +烴 +烷 +烹 +烺 +烽 +焃 +焄 +焉 +焊 +焌 +焓 +焗 +焙 +焚 +焜 +焞 +無 +焦 +焯 +焰 +焱 +焴 +然 +焻 +焼 +焿 +煇 +煉 +煊 +煌 +煎 +煐 +煒 +煔 +煕 +煖 +煙 +煚 +煜 +煞 +煠 +煤 +煥 +煦 +照 +煨 +煩 +煬 +煮 +煲 +煳 +煵 +煶 +煸 +煽 +熄 +熅 +熇 +熈 +熊 +熏 +熒 +熔 +熖 +熗 +熘 +熙 +熜 +熟 +熠 +熤 +熥 +熨 +熬 +熯 +熱 +熲 +熳 +熵 +熹 +熺 +熼 +熾 +熿 +燁 +燃 +燄 +燈 +燉 +燊 +燎 +燏 +燐 +燒 +燔 +燕 +燘 +燙 +燚 +燜 +燝 +營 +燥 +燦 +燧 +燫 +燬 +燭 +燮 +燴 +燹 +燻 +燼 +燾 +燿 +爀 +爆 +爌 +爍 +爐 +爔 +爚 +爛 +爝 +爨 +爪 +爬 +爭 +爯 +爰 +爲 +爵 +父 +爸 +爹 +爺 +爻 +爽 +爾 +爿 +牁 +牂 +牆 +片 +版 +牌 +牒 +牕 +牖 +牘 +牙 +牛 +牝 +牟 +牠 +牡 +牢 +牧 +物 +牯 +牲 +特 +牻 +牼 +牽 +犀 +犁 +犂 +犇 +犍 +犎 +犖 +犛 +犢 +犧 +犨 +犬 +犯 +犰 +犴 +犽 +狀 +狂 +狄 +狍 +狎 +狐 +狒 +狓 +狗 +狙 +狛 +狟 +狠 +狡 +狦 +狨 +狩 +狳 +狶 +狷 +狸 +狹 +狻 +狼 +猁 +猄 +猇 +猊 +猗 +猙 +猛 +猜 +猝 +猞 +猢 +猥 +猨 +猩 +猳 +猴 +猶 +猷 +猺 +猻 +猾 +猿 +獁 +獃 +獄 +獅 +獇 +獎 +獏 +獐 +獒 +獠 +獢 +獣 +獨 +獬 +獮 +獯 +獰 +獲 +獴 +獵 +獷 +獸 +獺 +獻 +獼 +獾 +玀 +玄 +玆 +率 +玉 +王 +玎 +玏 +玓 +玕 +玖 +玗 +玘 +玙 +玟 +玠 +玡 +玢 +玥 +玧 +玨 +玩 +玫 +玭 +玲 +玳 +玶 +玷 +玹 +玻 +玾 +珀 +珂 +珅 +珈 +珉 +珊 +珌 +珍 +珎 +珏 +珖 +珙 +珝 +珞 +珠 +珡 +珣 +珤 +珥 +珦 +珧 +珩 +珪 +班 +珮 +珵 +珹 +珺 +珽 +現 +琁 +球 +琄 +琅 +理 +琇 +琉 +琊 +琍 +琎 +琚 +琛 +琡 +琢 +琤 +琥 +琦 +琨 +琪 +琬 +琮 +琯 +琰 +琱 +琳 +琴 +琵 +琶 +琹 +琺 +琿 +瑀 +瑁 +瑂 +瑄 +瑅 +瑆 +瑈 +瑊 +瑋 +瑑 +瑒 +瑕 +瑗 +瑙 +瑚 +瑛 +瑜 +瑝 +瑞 +瑟 +瑠 +瑢 +瑣 +瑤 +瑥 +瑧 +瑨 +瑩 +瑪 +瑭 +瑯 +瑰 +瑱 +瑳 +瑴 +瑺 +瑾 +璀 +璁 +璃 +璄 +璆 +璇 +璈 +璉 +璋 +璌 +璐 +璕 +璘 +璙 +璚 +璜 +璞 +璟 +璠 +璡 +璣 +璥 +璦 +璧 +璨 +璩 +璪 +璫 +璬 +璮 +環 +璱 +璵 +璸 +璹 +璽 +璿 +瓈 +瓊 +瓌 +瓏 +瓑 +瓔 +瓖 +瓘 +瓚 +瓛 +瓜 +瓞 +瓠 +瓢 +瓣 +瓤 +瓦 +瓮 +瓴 +瓶 +瓷 +瓿 +甂 +甄 +甌 +甍 +甑 +甕 +甘 +甙 +甚 +甜 +生 +甡 +產 +産 +甥 +甦 +用 +甩 +甪 +甫 +甬 +甯 +田 +由 +甲 +申 +男 +甸 +甹 +町 +甾 +畀 +畇 +畈 +畊 +畋 +界 +畎 +畏 +畐 +畑 +畔 +留 +畜 +畝 +畠 +畢 +略 +畦 +畧 +番 +畫 +畬 +畯 +異 +畲 +畳 +畵 +當 +畷 +畸 +畹 +畿 +疃 +疆 +疇 +疊 +疋 +疌 +疍 +疏 +疑 +疒 +疕 +疙 +疚 +疝 +疣 +疤 +疥 +疫 +疲 +疳 +疵 +疸 +疹 +疼 +疽 +疾 +痂 +病 +症 +痊 +痍 +痔 +痕 +痘 +痙 +痛 +痞 +痟 +痠 +痢 +痣 +痤 +痧 +痩 +痰 +痱 +痲 +痴 +痹 +痺 +痿 +瘀 +瘁 +瘊 +瘋 +瘍 +瘓 +瘙 +瘜 +瘞 +瘟 +瘠 +瘡 +瘢 +瘤 +瘦 +瘧 +瘩 +瘰 +瘴 +瘺 +癀 +療 +癆 +癇 +癌 +癒 +癖 +癘 +癜 +癟 +癡 +癢 +癤 +癥 +癩 +癬 +癭 +癮 +癯 +癰 +癱 +癲 +癸 +発 +登 +發 +白 +百 +皂 +的 +皆 +皇 +皈 +皋 +皎 +皐 +皓 +皖 +皙 +皚 +皛 +皝 +皞 +皮 +皰 +皴 +皷 +皸 +皺 +皿 +盂 +盃 +盅 +盆 +盈 +益 +盋 +盌 +盎 +盒 +盔 +盛 +盜 +盞 +盟 +盡 +監 +盤 +盥 +盦 +盧 +盨 +盩 +盪 +盫 +目 +盯 +盱 +盲 +直 +盷 +相 +盹 +盺 +盼 +盾 +眀 +省 +眉 +看 +県 +眙 +眛 +眜 +眞 +真 +眠 +眥 +眨 +眩 +眭 +眯 +眵 +眶 +眷 +眸 +眺 +眼 +眾 +着 +睇 +睛 +睜 +睞 +睡 +睢 +督 +睥 +睦 +睨 +睪 +睫 +睭 +睹 +睺 +睽 +睾 +睿 +瞄 +瞅 +瞋 +瞌 +瞎 +瞑 +瞓 +瞞 +瞢 +瞥 +瞧 +瞪 +瞫 +瞬 +瞭 +瞰 +瞳 +瞻 +瞼 +瞽 +瞿 +矇 +矍 +矗 +矚 +矛 +矜 +矞 +矢 +矣 +知 +矧 +矩 +短 +矮 +矯 +石 +矸 +矽 +砂 +砋 +砌 +砍 +砒 +研 +砝 +砢 +砥 +砦 +砧 +砩 +砫 +砭 +砮 +砯 +砰 +砲 +砳 +破 +砵 +砷 +砸 +砼 +硂 +硃 +硅 +硇 +硏 +硐 +硒 +硓 +硚 +硜 +硝 +硤 +硨 +硫 +硬 +硭 +硯 +硼 +碁 +碇 +碉 +碌 +碎 +碑 +碓 +碕 +碗 +碘 +碚 +碟 +碡 +碣 +碧 +碩 +碪 +碭 +碰 +碲 +碳 +碴 +碶 +碸 +確 +碻 +碼 +碽 +碾 +磁 +磅 +磊 +磋 +磐 +磔 +磕 +磘 +磙 +磚 +磜 +磡 +磨 +磪 +磬 +磯 +磱 +磲 +磵 +磷 +磺 +磻 +磾 +礁 +礄 +礎 +礐 +礑 +礒 +礙 +礠 +礦 +礪 +礫 +礬 +礮 +礱 +礴 +示 +礻 +礽 +社 +祀 +祁 +祂 +祆 +祇 +祈 +祉 +祋 +祏 +祐 +祓 +祕 +祖 +祗 +祙 +祚 +祛 +祜 +祝 +神 +祟 +祠 +祥 +祧 +票 +祭 +祹 +祺 +祼 +祿 +禁 +禃 +禇 +禍 +禎 +福 +禑 +禓 +禔 +禕 +禘 +禛 +禟 +禠 +禤 +禦 +禧 +禨 +禩 +禪 +禮 +禰 +禱 +禵 +禹 +禺 +禼 +禽 +禾 +禿 +秀 +私 +秈 +秉 +秋 +科 +秒 +秕 +秘 +租 +秠 +秣 +秤 +秦 +秧 +秩 +秭 +秳 +秸 +移 +稀 +稅 +稈 +稉 +程 +稍 +稑 +稔 +稗 +稘 +稙 +稚 +稜 +稞 +稟 +稠 +種 +稱 +稲 +稷 +稹 +稺 +稻 +稼 +稽 +稾 +稿 +穀 +穂 +穆 +穈 +穉 +穌 +積 +穎 +穗 +穟 +穠 +穡 +穢 +穣 +穩 +穫 +穰 +穴 +穵 +究 +穹 +空 +穿 +突 +窄 +窅 +窈 +窋 +窒 +窕 +窖 +窗 +窘 +窟 +窠 +窣 +窨 +窩 +窪 +窮 +窯 +窰 +窶 +窺 +窿 +竄 +竅 +竇 +竈 +竊 +立 +竑 +站 +竜 +竟 +章 +竣 +童 +竦 +竩 +竭 +端 +競 +竹 +竺 +竻 +竿 +笄 +笆 +笈 +笏 +笑 +笘 +笙 +笛 +笞 +笠 +笥 +符 +笨 +笩 +笪 +第 +笭 +笮 +笯 +笱 +笳 +笹 +筅 +筆 +等 +筊 +筋 +筌 +筍 +筏 +筐 +筒 +答 +策 +筘 +筠 +筥 +筦 +筧 +筬 +筭 +筱 +筲 +筳 +筵 +筶 +筷 +筻 +箆 +箇 +箋 +箍 +箏 +箐 +箑 +箒 +箔 +箕 +算 +箜 +管 +箬 +箭 +箱 +箴 +箸 +節 +篁 +範 +篆 +篇 +築 +篊 +篋 +篌 +篔 +篙 +篝 +篠 +篡 +篤 +篥 +篦 +篩 +篪 +篭 +篯 +篳 +篷 +簀 +簃 +簇 +簉 +簋 +簍 +簑 +簕 +簗 +簞 +簠 +簡 +簧 +簪 +簫 +簷 +簸 +簹 +簺 +簽 +簾 +簿 +籀 +籃 +籌 +籍 +籐 +籙 +籛 +籜 +籝 +籟 +籠 +籣 +籤 +籥 +籪 +籬 +籮 +籲 +米 +籽 +籾 +粄 +粉 +粍 +粑 +粒 +粕 +粗 +粘 +粟 +粢 +粥 +粦 +粧 +粩 +粱 +粲 +粳 +粵 +粹 +粼 +粽 +精 +粿 +糀 +糅 +糊 +糌 +糍 +糎 +糕 +糖 +糙 +糜 +糝 +糞 +糟 +糠 +糢 +糧 +糬 +糯 +糰 +糴 +糶 +糸 +糹 +糺 +系 +糾 +紀 +紂 +約 +紅 +紆 +紇 +紈 +紉 +紊 +紋 +納 +紐 +紑 +紓 +純 +紕 +紗 +紘 +紙 +級 +紛 +紜 +紝 +紞 +素 +紡 +索 +紫 +紮 +累 +細 +紱 +紲 +紳 +紵 +紹 +紺 +紿 +終 +絃 +組 +絆 +経 +絎 +結 +絕 +絛 +絜 +絞 +絡 +絢 +給 +絨 +絪 +絮 +統 +絲 +絳 +絵 +絶 +絹 +絺 +綁 +綃 +綈 +綉 +綎 +綏 +經 +綖 +継 +続 +綜 +綝 +綞 +綠 +綢 +綣 +綦 +綧 +綫 +綬 +維 +綮 +綰 +綱 +網 +綳 +綴 +綸 +綺 +綻 +綽 +綾 +綿 +緁 +緃 +緄 +緈 +緊 +緋 +総 +緑 +緒 +緖 +緘 +線 +緜 +緝 +緞 +締 +緡 +緣 +緤 +編 +緩 +緬 +緯 +緱 +緲 +練 +緹 +緻 +縂 +縄 +縈 +縉 +縊 +縕 +縛 +縝 +縞 +縠 +縡 +縣 +縤 +縫 +縮 +縯 +縱 +縴 +縵 +縷 +縹 +縻 +總 +績 +繁 +繃 +繆 +繇 +繒 +織 +繕 +繖 +繙 +繚 +繞 +繡 +繩 +繪 +繫 +繭 +繰 +繳 +繹 +繻 +繼 +繽 +繾 +纁 +纂 +纈 +續 +纍 +纏 +纓 +纔 +纕 +纖 +纘 +纛 +纜 +缐 +缶 +缸 +缺 +缽 +罃 +罄 +罅 +罈 +罉 +罌 +罍 +罐 +罔 +罕 +罘 +罟 +罡 +罨 +罩 +罪 +置 +罰 +罱 +署 +罳 +罵 +罶 +罷 +罹 +罽 +羂 +羅 +羆 +羈 +羊 +羋 +羌 +美 +羔 +羕 +羗 +羙 +羚 +羞 +羡 +羣 +群 +羥 +羧 +羨 +義 +羯 +羰 +羱 +羲 +羸 +羹 +羽 +羿 +翀 +翁 +翂 +翃 +翅 +翊 +翌 +翎 +翏 +習 +翔 +翕 +翙 +翜 +翟 +翠 +翡 +翥 +翦 +翩 +翬 +翮 +翰 +翱 +翳 +翹 +翻 +翼 +耀 +老 +考 +耄 +者 +耆 +而 +耍 +耎 +耐 +耑 +耒 +耔 +耕 +耗 +耘 +耙 +耜 +耦 +耨 +耬 +耳 +耵 +耶 +耷 +耽 +耿 +聃 +聆 +聊 +聒 +聖 +聘 +聚 +聞 +聟 +聨 +聯 +聰 +聱 +聲 +聳 +聴 +聶 +職 +聽 +聾 +聿 +肄 +肅 +肆 +肇 +肉 +肋 +肌 +肏 +肖 +肘 +肚 +肛 +肜 +肝 +肟 +股 +肢 +肥 +肩 +肪 +肫 +肯 +肱 +育 +肸 +肹 +肺 +肼 +肽 +胂 +胃 +胄 +胅 +胇 +胊 +背 +胍 +胎 +胖 +胗 +胙 +胚 +胛 +胝 +胞 +胡 +胤 +胥 +胬 +胭 +胰 +胱 +胳 +胴 +胸 +胺 +胼 +能 +脂 +脅 +脆 +脇 +脈 +脊 +脒 +脖 +脘 +脛 +脣 +脩 +脫 +脬 +脭 +脯 +脲 +脳 +脷 +脹 +脾 +腆 +腈 +腊 +腋 +腌 +腎 +腐 +腑 +腓 +腔 +腕 +腥 +腦 +腧 +腩 +腫 +腮 +腰 +腱 +腳 +腴 +腸 +腹 +腺 +腿 +膀 +膂 +膈 +膊 +膏 +膚 +膛 +膜 +膝 +膠 +膣 +膥 +膦 +膨 +膩 +膮 +膳 +膺 +膽 +膾 +膿 +臀 +臂 +臃 +臆 +臉 +臊 +臍 +臏 +臘 +臚 +臞 +臟 +臠 +臣 +臧 +臨 +自 +臭 +臯 +至 +致 +臺 +臻 +臼 +臾 +舂 +舅 +與 +興 +舉 +舊 +舌 +舍 +舎 +舒 +舔 +舖 +舘 +舛 +舜 +舞 +舟 +舢 +舥 +舨 +舩 +航 +舫 +般 +舲 +舵 +舶 +舷 +舸 +船 +舺 +艅 +艇 +艉 +艋 +艎 +艏 +艔 +艘 +艙 +艚 +艦 +艮 +良 +艱 +色 +艶 +艷 +艸 +艽 +艾 +艿 +芃 +芊 +芋 +芍 +芎 +芑 +芒 +芘 +芙 +芛 +芝 +芡 +芥 +芨 +芩 +芪 +芫 +芬 +芭 +芮 +芯 +花 +芳 +芴 +芷 +芸 +芹 +芻 +芽 +芾 +苄 +苅 +苑 +苒 +苓 +苔 +苕 +苗 +苛 +苜 +苝 +苞 +苟 +苡 +苣 +苤 +若 +苦 +苧 +苪 +苫 +苯 +英 +苳 +苴 +苷 +苺 +苻 +苼 +苾 +茀 +茁 +茂 +范 +茄 +茅 +茆 +茇 +茈 +茉 +茌 +茗 +茘 +茚 +茛 +茜 +茝 +茨 +茫 +茬 +茭 +茮 +茯 +茱 +茲 +茴 +茵 +茶 +茷 +茸 +茹 +茺 +茼 +荀 +荃 +荅 +荇 +草 +荊 +荎 +荏 +荒 +荔 +荖 +荘 +荳 +荷 +荸 +荻 +荼 +荽 +莆 +莉 +莊 +莎 +莒 +莓 +莕 +莖 +莘 +莙 +莛 +莜 +莞 +莠 +莢 +莧 +莨 +莩 +莪 +莫 +莽 +莿 +菀 +菁 +菅 +菇 +菈 +菉 +菊 +菌 +菍 +菏 +菑 +菓 +菔 +菖 +菘 +菜 +菝 +菟 +菠 +菡 +菥 +菩 +菪 +菫 +華 +菰 +菱 +菲 +菴 +菶 +菸 +菹 +菺 +菼 +菽 +菾 +萁 +萃 +萄 +萇 +萊 +萌 +萍 +萎 +萐 +萘 +萜 +萠 +萡 +萣 +萩 +萬 +萭 +萱 +萵 +萸 +萹 +萼 +落 +葃 +葆 +葉 +葊 +葎 +葑 +葒 +著 +葙 +葚 +葛 +葜 +葝 +葡 +董 +葦 +葩 +葫 +葬 +葭 +葯 +葰 +葳 +葵 +葶 +葷 +葺 +蒂 +蒄 +蒍 +蒎 +蒐 +蒓 +蒔 +蒗 +蒙 +蒜 +蒞 +蒟 +蒡 +蒢 +蒤 +蒧 +蒨 +蒭 +蒯 +蒲 +蒴 +蒸 +蒹 +蒺 +蒻 +蒼 +蒽 +蒾 +蒿 +蓀 +蓁 +蓂 +蓄 +蓆 +蓉 +蓋 +蓍 +蓑 +蓓 +蓖 +蓘 +蓚 +蓧 +蓨 +蓪 +蓬 +蓭 +蓮 +蓯 +蓳 +蓼 +蓽 +蓿 +蔆 +蔎 +蔑 +蔓 +蔔 +蔕 +蔗 +蔘 +蔚 +蔝 +蔞 +蔡 +蔣 +蔥 +蔦 +蔬 +蔭 +蔴 +蔵 +蔻 +蔽 +蕁 +蕃 +蕅 +蕈 +蕉 +蕊 +蕎 +蕑 +蕒 +蕖 +蕘 +蕙 +蕚 +蕟 +蕡 +蕢 +蕤 +蕨 +蕩 +蕪 +蕭 +蕷 +蕹 +蕺 +蕻 +蕾 +薀 +薄 +薆 +薇 +薈 +薊 +薌 +薏 +薐 +薑 +薔 +薗 +薘 +薙 +薛 +薜 +薞 +薟 +薡 +薦 +薨 +薩 +薪 +薫 +薬 +薯 +薰 +薲 +薷 +薸 +薹 +薺 +薾 +薿 +藁 +藉 +藍 +藎 +藏 +藐 +藔 +藕 +藜 +藝 +藟 +藤 +藥 +藦 +藨 +藩 +藪 +藶 +藸 +藹 +藺 +藻 +藿 +蘂 +蘄 +蘅 +蘆 +蘇 +蘊 +蘋 +蘐 +蘑 +蘓 +蘗 +蘘 +蘚 +蘞 +蘢 +蘧 +蘩 +蘭 +蘵 +蘶 +蘸 +蘼 +蘿 +虉 +虎 +虐 +虓 +虔 +處 +虖 +虛 +虜 +虞 +號 +虢 +虧 +虨 +虯 +虱 +虵 +虹 +虺 +虻 +蚆 +蚊 +蚋 +蚌 +蚍 +蚓 +蚖 +蚜 +蚝 +蚡 +蚢 +蚣 +蚤 +蚧 +蚨 +蚩 +蚪 +蚯 +蚱 +蚴 +蚵 +蚶 +蚺 +蚼 +蛀 +蛄 +蛇 +蛉 +蛋 +蛍 +蛐 +蛑 +蛔 +蛙 +蛛 +蛞 +蛟 +蛤 +蛭 +蛯 +蛸 +蛹 +蛺 +蛻 +蛾 +蜀 +蜂 +蜃 +蜆 +蜇 +蜈 +蜉 +蜊 +蜍 +蜑 +蜒 +蜓 +蜘 +蜚 +蜛 +蜜 +蜞 +蜢 +蜣 +蜥 +蜨 +蜮 +蜯 +蜱 +蜴 +蜷 +蜻 +蜾 +蜿 +蝀 +蝌 +蝍 +蝎 +蝓 +蝕 +蝗 +蝘 +蝙 +蝚 +蝟 +蝠 +蝣 +蝤 +蝦 +蝨 +蝮 +蝯 +蝰 +蝲 +蝴 +蝶 +蝸 +蝽 +螂 +螃 +螄 +螅 +螈 +螋 +融 +螐 +螔 +螞 +螟 +螠 +螢 +螣 +螥 +螫 +螭 +螯 +螳 +螶 +螺 +螻 +螽 +螾 +蟀 +蟄 +蟅 +蟆 +蟊 +蟋 +蟌 +蟎 +蟑 +蟒 +蟜 +蟠 +蟥 +蟪 +蟫 +蟬 +蟯 +蟲 +蟳 +蟴 +蟶 +蟹 +蟻 +蟾 +蠂 +蠃 +蠄 +蠅 +蠆 +蠊 +蠋 +蠍 +蠐 +蠑 +蠓 +蠔 +蠕 +蠖 +蠘 +蠙 +蠟 +蠡 +蠢 +蠣 +蠱 +蠲 +蠵 +蠶 +蠷 +蠹 +蠻 +血 +衂 +衆 +行 +衍 +衎 +術 +衕 +衖 +街 +衙 +衚 +衛 +衜 +衝 +衞 +衡 +衢 +衣 +表 +衩 +衫 +衰 +衲 +衷 +衽 +衾 +衿 +袁 +袂 +袈 +袋 +袍 +袓 +袖 +袛 +袞 +袤 +袪 +被 +袱 +袴 +袾 +裁 +裂 +裊 +裎 +裒 +裔 +裕 +裖 +裘 +裙 +補 +裝 +裟 +裡 +裨 +裬 +裱 +裳 +裴 +裵 +裸 +裹 +製 +裾 +裿 +褀 +褂 +複 +褌 +褍 +褎 +褐 +褒 +褓 +褔 +褘 +褙 +褚 +褞 +褥 +褧 +褪 +褫 +褭 +褲 +褶 +褸 +褻 +襄 +襌 +襖 +襞 +襟 +襠 +襤 +襦 +襪 +襯 +襲 +襴 +襶 +襻 +襾 +西 +要 +覃 +覆 +覇 +覈 +見 +覌 +規 +覓 +視 +覚 +覡 +覦 +覧 +親 +覬 +覲 +観 +覺 +覽 +覿 +觀 +角 +觔 +觙 +觚 +觜 +解 +觭 +觱 +觴 +觶 +觸 +觿 +言 +訁 +訂 +訃 +訇 +計 +訊 +訌 +討 +訏 +訐 +訒 +訓 +訔 +訕 +訖 +託 +記 +訛 +訝 +訟 +訣 +訥 +訪 +設 +許 +訴 +訶 +診 +註 +証 +訾 +詁 +詆 +詈 +詐 +詒 +詔 +評 +詛 +詞 +詠 +詡 +詢 +詣 +詥 +試 +詧 +詩 +詫 +詭 +詮 +詰 +話 +該 +詳 +詵 +詹 +詼 +誄 +誅 +誇 +誌 +認 +誒 +誓 +誕 +誘 +語 +誠 +誡 +誣 +誤 +誥 +誦 +誨 +說 +説 +読 +誰 +課 +誴 +誹 +誼 +誾 +調 +談 +請 +諍 +諏 +諒 +論 +諗 +諜 +諟 +諠 +諡 +諤 +諦 +諧 +諪 +諫 +諭 +諮 +諱 +諲 +諳 +諴 +諶 +諷 +諸 +諺 +諼 +諾 +謀 +謁 +謂 +謄 +謇 +謊 +謌 +謎 +謏 +謐 +謔 +謖 +謗 +謙 +謚 +講 +謜 +謝 +謠 +謢 +謤 +謨 +謩 +謫 +謬 +謳 +謹 +謾 +證 +譏 +譓 +譔 +識 +譙 +譚 +譜 +譞 +警 +譫 +譬 +譭 +譯 +議 +譲 +譳 +譴 +護 +譽 +譿 +讀 +讃 +變 +讌 +讎 +讓 +讖 +讙 +讚 +讜 +讞 +谷 +谿 +豁 +豆 +豇 +豈 +豉 +豊 +豌 +豎 +豐 +豔 +豕 +豚 +象 +豢 +豨 +豪 +豫 +豬 +豳 +豸 +豹 +豺 +豿 +貂 +貅 +貉 +貊 +貌 +貐 +貒 +貓 +貔 +貘 +貝 +貞 +負 +財 +貢 +貤 +貧 +貨 +販 +貪 +貫 +責 +貭 +貮 +貯 +貲 +貳 +貴 +貶 +買 +貸 +貺 +費 +貼 +貽 +貿 +賀 +賁 +賂 +賃 +賄 +資 +賈 +賊 +賑 +賒 +賓 +賔 +賕 +賚 +賜 +賞 +賠 +賡 +賢 +賣 +賤 +賦 +賨 +質 +賬 +賭 +賴 +賹 +賺 +賻 +購 +賽 +賾 +贄 +贅 +贇 +贈 +贊 +贌 +贍 +贏 +贓 +贔 +贖 +贛 +赤 +赦 +赧 +赫 +赬 +赭 +走 +赳 +赴 +起 +趁 +超 +越 +趐 +趕 +趖 +趙 +趟 +趣 +趨 +足 +趴 +趵 +趺 +趼 +趾 +跅 +跆 +跋 +跌 +跏 +跑 +跖 +跗 +跛 +距 +跟 +跡 +跣 +跤 +跨 +跩 +跪 +路 +跳 +踎 +踏 +踐 +踝 +踞 +踢 +踩 +踰 +踴 +踹 +踺 +蹂 +蹄 +蹇 +蹈 +蹉 +蹊 +蹋 +蹕 +蹙 +蹟 +蹠 +蹤 +蹦 +蹬 +蹭 +蹯 +蹲 +蹴 +蹶 +蹺 +蹻 +蹼 +躁 +躂 +躄 +躉 +躋 +躍 +躑 +躒 +躔 +躝 +躪 +身 +躬 +躰 +躲 +躺 +軀 +車 +軋 +軌 +軍 +軎 +軒 +軔 +軛 +軟 +転 +軫 +軲 +軸 +軹 +軺 +軻 +軼 +軽 +軾 +較 +輄 +輅 +載 +輋 +輒 +輓 +輔 +輕 +輛 +輝 +輞 +輟 +輥 +輦 +輩 +輪 +輬 +輭 +輯 +輶 +輸 +輻 +輾 +輿 +轀 +轂 +轄 +轅 +轆 +轉 +轍 +轎 +轘 +轝 +轟 +轤 +辛 +辜 +辟 +辣 +辦 +辧 +辨 +辭 +辮 +辯 +辰 +辱 +農 +辵 +辺 +辻 +込 +迂 +迄 +迅 +迎 +近 +返 +迢 +迤 +迥 +迦 +迪 +迫 +迭 +迮 +述 +迴 +迵 +迷 +迸 +迺 +追 +退 +送 +逃 +逄 +逅 +逆 +逈 +逋 +逌 +逍 +逎 +透 +逐 +逑 +途 +逕 +逖 +逗 +這 +通 +逛 +逝 +逞 +速 +造 +逢 +連 +逤 +逨 +逮 +逯 +進 +逴 +逵 +逸 +逹 +逺 +逼 +逾 +遁 +遂 +遄 +遇 +遊 +運 +遍 +過 +遏 +遐 +遒 +道 +達 +違 +遘 +遙 +遛 +遜 +遞 +遠 +遢 +遣 +遨 +適 +遭 +遮 +遯 +遲 +遴 +遵 +遶 +遷 +選 +遹 +遺 +遼 +避 +邀 +邁 +邂 +邃 +還 +邇 +邈 +邉 +邊 +邋 +邏 +邑 +邕 +邗 +邙 +邛 +邠 +邡 +邢 +那 +邦 +邨 +邪 +邯 +邰 +邱 +邲 +邳 +邴 +邵 +邸 +邽 +邾 +郁 +郃 +郄 +郅 +郇 +郊 +郋 +郎 +郗 +郛 +郜 +郝 +郞 +郟 +郡 +郢 +郤 +部 +郪 +郫 +郭 +郯 +郳 +郴 +郵 +郷 +都 +郾 +郿 +鄂 +鄃 +鄄 +鄆 +鄉 +鄋 +鄑 +鄒 +鄔 +鄖 +鄗 +鄘 +鄙 +鄚 +鄜 +鄞 +鄠 +鄢 +鄣 +鄤 +鄧 +鄩 +鄫 +鄭 +鄯 +鄰 +鄱 +鄲 +鄳 +鄴 +鄺 +酃 +酆 +酈 +酉 +酊 +酋 +酌 +配 +酎 +酏 +酐 +酒 +酔 +酗 +酚 +酞 +酡 +酢 +酣 +酥 +酩 +酪 +酬 +酮 +酯 +酰 +酴 +酵 +酶 +酷 +酸 +酺 +酼 +醁 +醂 +醃 +醅 +醇 +醉 +醋 +醌 +醍 +醐 +醒 +醚 +醛 +醜 +醞 +醢 +醣 +醪 +醫 +醬 +醮 +醯 +醴 +醺 +醾 +醿 +釀 +釁 +釆 +采 +釉 +釋 +里 +重 +野 +量 +釐 +金 +釒 +釓 +釔 +釕 +釗 +釘 +釙 +釚 +釜 +針 +釣 +釤 +釦 +釧 +釩 +釪 +釭 +釴 +釵 +釷 +釹 +釺 +鈀 +鈁 +鈄 +鈇 +鈈 +鈉 +鈊 +鈍 +鈏 +鈐 +鈑 +鈔 +鈕 +鈖 +鈞 +鈢 +鈣 +鈥 +鈦 +鈫 +鈮 +鈰 +鈳 +鈴 +鈷 +鈸 +鈹 +鈺 +鈾 +鈿 +鉀 +鉄 +鉅 +鉆 +鉈 +鉉 +鉋 +鉌 +鉍 +鉏 +鉑 +鉓 +鉗 +鉚 +鉛 +鉞 +鉟 +鉤 +鉦 +鉬 +鉭 +鉲 +鉶 +鉷 +鉸 +鉻 +鉾 +鉿 +銀 +銂 +銃 +銅 +銋 +銍 +銑 +銓 +銕 +銖 +銘 +銚 +銜 +銠 +銣 +銥 +銦 +銨 +銩 +銪 +銫 +銬 +銭 +銱 +銲 +銳 +銶 +銷 +銹 +銻 +銼 +銾 +鋁 +鋅 +鋆 +鋇 +鋌 +鋏 +鋐 +鋒 +鋕 +鋗 +鋙 +鋡 +鋤 +鋥 +鋦 +鋨 +鋪 +鋮 +鋯 +鋰 +鋱 +鋳 +鋶 +鋸 +鋹 +鋼 +錀 +錄 +錏 +錐 +錒 +錕 +錘 +錚 +錞 +錟 +錠 +錡 +錢 +錦 +錨 +錫 +錬 +錮 +錯 +錳 +錶 +錸 +錻 +鍀 +鍇 +鍈 +鍉 +鍊 +鍋 +鍍 +鍏 +鍔 +鍘 +鍛 +鍝 +鍟 +鍠 +鍥 +鍩 +鍬 +鍱 +鍳 +鍵 +鍶 +鍷 +鍺 +鍼 +鍾 +鎂 +鎅 +鎊 +鎌 +鎏 +鎓 +鎔 +鎖 +鎗 +鎘 +鎚 +鎛 +鎢 +鎣 +鎦 +鎧 +鎪 +鎬 +鎭 +鎮 +鎰 +鎳 +鎵 +鎻 +鏃 +鏇 +鏈 +鏊 +鏌 +鏐 +鏑 +鏓 +鏖 +鏗 +鏘 +鏜 +鏝 +鏞 +鏟 +鏡 +鏢 +鏤 +鏦 +鏳 +鏴 +鏵 +鏷 +鏻 +鏽 +鐃 +鐇 +鐈 +鐓 +鐔 +鐘 +鐙 +鐠 +鐡 +鐤 +鐦 +鐧 +鐫 +鐬 +鐭 +鐮 +鐲 +鐳 +鐵 +鐸 +鐺 +鐽 +鐿 +鑀 +鑁 +鑂 +鑄 +鑅 +鑊 +鑌 +鑑 +鑒 +鑛 +鑠 +鑣 +鑨 +鑪 +鑫 +鑭 +鑰 +鑲 +鑴 +鑷 +鑼 +鑽 +鑾 +鑿 +長 +門 +閂 +閃 +閆 +閉 +開 +閎 +閏 +閑 +閒 +間 +閔 +閘 +閜 +閞 +閟 +関 +閣 +閥 +閦 +閨 +閩 +閬 +閭 +閰 +閱 +閶 +閹 +閻 +閼 +閾 +閿 +闆 +闇 +闈 +闊 +闋 +闌 +闍 +闐 +闓 +闔 +闕 +闖 +闘 +關 +闞 +闡 +闢 +闥 +阜 +阝 +阡 +阪 +阭 +阮 +阯 +阱 +防 +阻 +阿 +陀 +陁 +陂 +附 +陋 +陌 +降 +限 +陔 +陘 +陛 +陜 +陝 +陞 +陟 +陡 +院 +陣 +除 +陪 +陬 +陰 +陲 +陳 +陵 +陶 +陷 +陸 +険 +陽 +隄 +隅 +隆 +隈 +隊 +隋 +隍 +階 +隔 +隕 +隗 +隘 +隙 +際 +障 +隣 +隧 +隨 +險 +隰 +隱 +隲 +隳 +隴 +隷 +隸 +隹 +隻 +隼 +雀 +雁 +雄 +雅 +集 +雇 +雉 +雋 +雌 +雍 +雎 +雑 +雒 +雕 +雖 +雙 +雛 +雜 +雝 +雞 +離 +難 +雨 +雩 +雪 +雫 +雯 +雱 +雲 +零 +雷 +雹 +電 +需 +霄 +霅 +霆 +震 +霈 +霉 +霊 +霍 +霎 +霏 +霑 +霓 +霖 +霙 +霜 +霞 +霤 +霧 +霨 +霰 +露 +霶 +霸 +霹 +霽 +霾 +靁 +靂 +靄 +靈 +靉 +靑 +青 +靖 +靚 +靛 +靜 +非 +靠 +靡 +面 +革 +靫 +靬 +靭 +靳 +靴 +靶 +靺 +靼 +鞅 +鞆 +鞋 +鞍 +鞏 +鞘 +鞞 +鞠 +鞣 +鞥 +鞦 +鞨 +鞭 +鞮 +鞴 +韁 +韃 +韆 +韋 +韌 +韑 +韓 +韙 +韜 +韞 +韠 +韡 +韭 +韮 +音 +韶 +韺 +韻 +韾 +響 +頁 +頂 +頃 +項 +順 +須 +頊 +頌 +頍 +頎 +頏 +預 +頑 +頒 +頓 +頔 +頗 +領 +頜 +頠 +頡 +頤 +頦 +頫 +頭 +頰 +頴 +頵 +頷 +頸 +頹 +頻 +頼 +顆 +題 +額 +顎 +顏 +顒 +顓 +顔 +顕 +顗 +願 +顙 +顛 +類 +顥 +顧 +顫 +顯 +顰 +顱 +顳 +顴 +風 +颮 +颯 +颱 +颶 +颺 +颼 +飄 +飆 +飈 +飛 +食 +飠 +飡 +飢 +飥 +飩 +飪 +飫 +飬 +飭 +飮 +飯 +飲 +飴 +飼 +飽 +飾 +餃 +餄 +餅 +餉 +養 +餌 +餎 +餐 +餒 +餓 +餗 +餘 +餚 +餛 +餞 +餠 +餡 +館 +餮 +餵 +餺 +餾 +餿 +饃 +饅 +饋 +饌 +饑 +饒 +饕 +饗 +饞 +饟 +饢 +首 +馗 +馘 +香 +馛 +馥 +馦 +馨 +馬 +馭 +馮 +馯 +馱 +馳 +馴 +馼 +駁 +駄 +駅 +駆 +駐 +駑 +駒 +駔 +駕 +駘 +駙 +駛 +駝 +駟 +駢 +駭 +駰 +駱 +駿 +騁 +騂 +騄 +騅 +騋 +騎 +騏 +験 +騖 +騙 +騤 +騨 +騫 +騭 +騮 +騰 +騶 +騷 +騾 +驁 +驃 +驄 +驅 +驊 +驌 +驍 +驎 +驒 +驕 +驗 +驚 +驛 +驟 +驢 +驤 +驥 +驩 +驪 +骨 +骯 +骰 +骶 +骷 +骸 +骼 +髀 +髂 +髎 +髏 +髑 +髒 +髓 +體 +高 +髙 +髡 +髦 +髪 +髭 +髮 +髯 +髲 +髷 +髹 +髻 +鬃 +鬄 +鬅 +鬆 +鬍 +鬚 +鬟 +鬢 +鬣 +鬥 +鬧 +鬨 +鬩 +鬪 +鬬 +鬮 +鬯 +鬱 +鬲 +鬹 +鬻 +鬼 +魁 +魂 +魃 +魄 +魅 +魈 +魋 +魍 +魎 +魏 +魔 +魕 +魘 +魚 +魛 +魞 +魟 +魣 +魨 +魩 +魮 +魯 +魴 +魷 +鮀 +鮁 +鮃 +鮄 +鮊 +鮋 +鮍 +鮐 +鮑 +鮒 +鮓 +鮗 +鮜 +鮟 +鮠 +鮡 +鮣 +鮨 +鮪 +鮫 +鮭 +鮮 +鮰 +鮸 +鮹 +鮻 +鯀 +鯁 +鯃 +鯇 +鯉 +鯊 +鯏 +鯒 +鯓 +鯔 +鯕 +鯖 +鯗 +鯙 +鯛 +鯡 +鯢 +鯤 +鯧 +鯨 +鯪 +鯭 +鯮 +鯰 +鯶 +鯷 +鯻 +鯽 +鯿 +鰂 +鰃 +鰆 +鰈 +鰉 +鰍 +鰏 +鰒 +鰓 +鰕 +鰗 +鰛 +鰜 +鰟 +鰣 +鰤 +鰧 +鰨 +鰩 +鰭 +鰮 +鰱 +鰲 +鰳 +鰶 +鰷 +鰹 +鰺 +鰻 +鰼 +鰾 +鱀 +鱂 +鱅 +鱇 +鱈 +鱉 +鱊 +鱒 +鱓 +鱔 +鱖 +鱗 +鱘 +鱚 +鱝 +鱟 +鱠 +鱣 +鱥 +鱧 +鱨 +鱬 +鱮 +鱰 +鱲 +鱵 +鱷 +鱸 +鱺 +鱻 +鳥 +鳧 +鳩 +鳯 +鳰 +鳳 +鳴 +鳶 +鳽 +鴆 +鴇 +鴉 +鴒 +鴓 +鴕 +鴗 +鴛 +鴝 +鴞 +鴟 +鴡 +鴣 +鴦 +鴨 +鴫 +鴯 +鴰 +鴴 +鴻 +鴿 +鵂 +鵄 +鵎 +鵐 +鵑 +鵒 +鵓 +鵙 +鵜 +鵝 +鵞 +鵟 +鵠 +鵡 +鵪 +鵬 +鵯 +鵰 +鵲 +鵵 +鵼 +鵾 +鶆 +鶇 +鶉 +鶏 +鶒 +鶓 +鶘 +鶚 +鶡 +鶥 +鶩 +鶬 +鶯 +鶲 +鶴 +鶹 +鶺 +鶻 +鶼 +鶿 +鷂 +鷄 +鷉 +鷎 +鷓 +鷗 +鷙 +鷚 +鷟 +鷥 +鷦 +鷫 +鷯 +鷲 +鷳 +鷸 +鷹 +鷺 +鸊 +鸌 +鸐 +鸑 +鸕 +鸘 +鸚 +鸛 +鸜 +鸝 +鸞 +鹮 +鹵 +鹹 +鹼 +鹽 +鹿 +麂 +麅 +麇 +麈 +麊 +麋 +麐 +麒 +麓 +麗 +麝 +麞 +麟 +麥 +麩 +麪 +麯 +麴 +麵 +麹 +麺 +麻 +麼 +麽 +麾 +麿 +黁 +黃 +黇 +黌 +黍 +黎 +黏 +黐 +黑 +黒 +黔 +默 +黙 +黛 +黜 +黝 +點 +黟 +黥 +黧 +黨 +黯 +黴 +黶 +黻 +黼 +黽 +黿 +鼂 +鼇 +鼈 +鼉 +鼎 +鼐 +鼒 +鼓 +鼕 +鼙 +鼠 +鼢 +鼩 +鼬 +鼯 +鼱 +鼴 +鼷 +鼻 +鼽 +鼾 +齊 +齋 +齒 +齕 +齡 +齣 +齦 +齧 +齲 +齶 +龍 +龎 +龐 +龑 +龔 +龕 +龜 +龝 +龠 +龢 +郎 +凉 +﹑ +﹗ +﹝ +﹞ +﹢ +! +" +# +$ +% +& +' +( +) +* ++ +, +- +. +/ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +: +; +< += +> +? +A +B +C +D +E +F +G +H +I +K +L +M +N +O +P +R +S +T +U +V +W +Y +Z +[ +] +` +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +r +s +t +u +z +{ +| +} +~ +¥ +𣇉 + diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams new file mode 100644 index 00000000..2efedca1 Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams.info b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams.info new file mode 100644 index 00000000..622d87ba Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams.info differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdmodel new file mode 100644 index 00000000..0a6bf1e4 Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdmodel differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams new file mode 100644 index 00000000..6a7305b7 Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams.info b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams.info new file mode 100644 index 00000000..1cdccfce Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams.info differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdmodel new file mode 100644 index 00000000..144978c1 Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdmodel differ diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_dict.txt b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_dict.txt new file mode 100644 index 00000000..e166bf33 --- /dev/null +++ b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_dict.txt @@ -0,0 +1,185 @@ + +! +" +# +$ +% +& +' +( +) +* ++ +, +- +. +/ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +: +; +< += +> +? +@ +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z +[ +] +_ +` +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +{ +} +¡ +£ +§ +ª +« +­ +° +² +³ +´ +µ +· +º +» +¿ +À +Á + +Ä +Å +Ç +È +É +Ê +Ë +Ì +Í +Î +Ï +Ò +Ó +Ô +Õ +Ö +Ú +Ü +Ý +ß +à +á +â +ã +ä +å +æ +ç +è +é +ê +ë +ì +í +î +ï +ñ +ò +ó +ô +õ +ö +ø +ù +ú +û +ü +ý +ą +Ć +ć +Č +č +Đ +đ +ę +ı +Ł +ł +ō +Œ +œ +Š +š +Ÿ +Ž +ž +ʒ +β +δ +ε +з +Ṡ +‘ +€ +™ diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj index a7ad8e12..f5d6c7a2 100644 --- a/BetterGenshinImpact/BetterGenshinImpact.csproj +++ b/BetterGenshinImpact/BetterGenshinImpact.csproj @@ -49,6 +49,7 @@ + @@ -63,10 +64,8 @@ - - @@ -172,5 +171,5 @@ WelcomeDialog.xaml - + \ No newline at end of file diff --git a/BetterGenshinImpact/Core/Config/OtherConfig.cs b/BetterGenshinImpact/Core/Config/OtherConfig.cs index 4255e03e..803afe97 100644 --- a/BetterGenshinImpact/Core/Config/OtherConfig.cs +++ b/BetterGenshinImpact/Core/Config/OtherConfig.cs @@ -10,5 +10,16 @@ public partial class OtherConfig : ObservableObject //调度器任务和部分独立任务,失去焦点,自动激活游戏窗口 [ObservableProperty] private bool _restoreFocusOnLostEnabled = false; - + + /// + /// 游戏语言名称 + /// + [ObservableProperty] + private string _gameCultureInfoName = "zh-Hans"; + + /// + /// BGI界面语言名称 + /// + [ObservableProperty] + private string _uiCultureInfoName = "zh-Hans"; } \ No newline at end of file diff --git a/BetterGenshinImpact/Core/Recognition/OCR/OcrFactory.cs b/BetterGenshinImpact/Core/Recognition/OCR/OcrFactory.cs index 14ca362b..0338a2bc 100644 --- a/BetterGenshinImpact/Core/Recognition/OCR/OcrFactory.cs +++ b/BetterGenshinImpact/Core/Recognition/OCR/OcrFactory.cs @@ -1,18 +1,33 @@ using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; namespace BetterGenshinImpact.Core.Recognition.OCR; public class OcrFactory { // public static IOcrService Media = Create(OcrEngineTypes.Media); - public static IOcrService Paddle { get; } = Create(OcrEngineTypes.Paddle); + public static IOcrService Paddle { get; private set; } = Create(OcrEngineTypes.Paddle); - public static IOcrService Create(OcrEngineTypes type) + public static IOcrService Create(OcrEngineTypes type, string? cultureInfoName = null) { return type switch { - OcrEngineTypes.Paddle => new PaddleOcrService(), + OcrEngineTypes.Paddle => new PaddleOcrService(cultureInfoName), _ => throw new ArgumentOutOfRangeException(nameof(type), type, null), }; } + + public static async Task ChangeCulture(string cultrueInfoName) + { + await Task.Run(() => + { + lock (Paddle) + { + Paddle = Create(OcrEngineTypes.Paddle, cultrueInfoName); + GC.Collect(); + } + }); + } } diff --git a/BetterGenshinImpact/Core/Recognition/OCR/PaddleOcrService.cs b/BetterGenshinImpact/Core/Recognition/OCR/PaddleOcrService.cs index 5d6c9b1c..1d084d3c 100644 --- a/BetterGenshinImpact/Core/Recognition/OCR/PaddleOcrService.cs +++ b/BetterGenshinImpact/Core/Recognition/OCR/PaddleOcrService.cs @@ -21,13 +21,30 @@ public class PaddleOcrService : IOcrService /// private readonly PaddleOcrAll _paddleOcrAll; - public PaddleOcrService() + public PaddleOcrService(string? cultureInfoName = null) { var path = Global.Absolute(@"Assets\Model\PaddleOcr"); - var localDetModel = DetectionModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_det"), ModelVersion.V4); - var localClsModel = ClassificationModel.FromDirectory(Path.Combine(path, "ch_ppocr_mobile_v2.0_cls")); - var localRecModel = RecognizationModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_rec"), Path.Combine(path, "ppocr_keys_v1.txt"), ModelVersion.V4); - var model = new FullOcrModel(localDetModel, localClsModel, localRecModel); + DetectionModel localDetModel; + RecognizationModel localRecModel; + FullOcrModel model; + switch (cultureInfoName) + { + case "zh-Hant": + localDetModel = DetectionModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_det"), ModelVersion.V4); // 和简中共用一下det + localRecModel = RecognizationModel.FromDirectory(Path.Combine(path, "chinese_cht_PP-OCRv3_rec_infer"), Path.Combine(path, "chinese_cht_dict.txt"), ModelVersion.V3); + //model = OnlineFullModels.TraditionalChineseV3.DownloadAsync().Result; + break; + case "fr": + localDetModel = DetectionModel.FromDirectory(Path.Combine(path, "en_PP-OCRv3_det_infer"), ModelVersion.V3); + localRecModel = RecognizationModel.FromDirectory(Path.Combine(path, "latin_PP-OCRv3_rec_infer"), Path.Combine(path, "latin_dict.txt"), ModelVersion.V3); + break; + default: + localDetModel = DetectionModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_det"), ModelVersion.V4); + localRecModel = RecognizationModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_rec"), Path.Combine(path, "ppocr_keys_v1.txt"), ModelVersion.V4); + + break; + } + model = new FullOcrModel(localDetModel, localRecModel); // Action device = TaskContext.Instance().Config.InferenceDevice switch // { // "CPU" => PaddleDevice.Onnx(), diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs index 1c808d93..d6dcf46f 100644 --- a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs +++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs @@ -36,6 +36,9 @@ using Vanara.PInvoke; using static BetterGenshinImpact.GameTask.Common.TaskControl; using static Vanara.PInvoke.Kernel32; using static Vanara.PInvoke.User32; +using Microsoft.Extensions.Localization; +using System.Globalization; +using System.Text.RegularExpressions; namespace BetterGenshinImpact.GameTask.AutoDomain; @@ -53,6 +56,10 @@ public class AutoDomainTask : ISoloTask private CancellationToken _ct; + private readonly string challengeCompletedLocalizedString; + private readonly string autoLeavingLocalizedString; + private readonly string skipLocalizedString; + public AutoDomainTask(AutoDomainParam taskParam) { AutoFightAssets.DestroyInstance(); @@ -65,6 +72,12 @@ public class AutoDomainTask : ISoloTask _config = TaskContext.Instance().Config.AutoDomainConfig; _combatScriptBag = CombatScriptParser.ReadAndParse(_taskParam.CombatStrategyPath); + + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); + CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); + this.challengeCompletedLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "挑战达成"); + this.autoLeavingLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "自动退出"); + this.skipLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "跳过"); } public async Task Start(CancellationToken ct) @@ -541,7 +554,7 @@ public class AutoDomainTask : ISoloTask var endTipsRect = ra.DeriveCrop(AutoFightAssets.Instance.EndTipsUpperRect); var text = OcrFactory.Paddle.Ocr(endTipsRect.SrcGreyMat); - if (text.Contains("挑战") || text.Contains("达成")) + if (Regex.IsMatch(text, this.challengeCompletedLocalizedString)) { Logger.LogInformation("检测到秘境结束提示(挑战达成),结束秘境"); return true; @@ -549,7 +562,7 @@ public class AutoDomainTask : ISoloTask endTipsRect = ra.DeriveCrop(AutoFightAssets.Instance.EndTipsRect); text = OcrFactory.Paddle.Ocr(endTipsRect.SrcGreyMat); - if (text.Contains("自动") || text.Contains("退出")) + if (Regex.IsMatch(text, this.autoLeavingLocalizedString)) { Logger.LogInformation("检测到秘境结束提示(xxx秒后自动退出),结束秘境"); return true; @@ -926,7 +939,7 @@ public class AutoDomainTask : ISoloTask // OCR识别是否有跳过 var ocrList = ra.FindMulti(RecognitionObject.Ocr(captureArea.Width - 230 * assetScale, 0, 230 * assetScale - 5, 80 * assetScale)); - var skipTextRa = ocrList.FirstOrDefault(t => t.Text.Contains("跳过")); + var skipTextRa = ocrList.FirstOrDefault(t => Regex.IsMatch(t.Text, this.skipLocalizedString)); if (skipTextRa != null) { hasSkip = true; diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.en.resx b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.en.resx new file mode 100644 index 00000000..64720193 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.en.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + [Challenge,Completed] + + + Leaving + + + Skip + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.fr.resx b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.fr.resx new file mode 100644 index 00000000..2b0b6840 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.fr.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + [Défi,terminé] + + + Sortie + + + Passer + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hans.resx new file mode 100644 index 00000000..4b01df9c --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hans.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + [挑战,达成] + + + [自动,退出] + + + 跳过 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hant.resx new file mode 100644 index 00000000..e2b4f460 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hant.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + [挑戰,達成] + + + [自動,退出] + + + 跳過 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoFight/Assets/AutoFightAssets.cs b/BetterGenshinImpact/GameTask/AutoFight/Assets/AutoFightAssets.cs index e48bcb4f..4690cafa 100644 --- a/BetterGenshinImpact/GameTask/AutoFight/Assets/AutoFightAssets.cs +++ b/BetterGenshinImpact/GameTask/AutoFight/Assets/AutoFightAssets.cs @@ -163,7 +163,7 @@ public class AutoFightAssets : BaseAssets Name = "P", RecognitionType = RecognitionTypes.TemplateMatch, TemplateImageMat = GameTaskManager.LoadAssetImage("AutoFight", "p.png"), - RegionOfInterest = new Rect(CaptureRect.Width - CaptureRect.Width / 7, CaptureRect.Height / 5, CaptureRect.Width / 7, CaptureRect.Height / 2 - CaptureRect.Width / 7), + RegionOfInterest = new Rect(CaptureRect.Width - (int)(CaptureRect.Width / 12.5), CaptureRect.Height / 5, (int)(CaptureRect.Width / 12.5), CaptureRect.Height / 2 - CaptureRect.Width / 7), DrawOnWindow = false }.InitTemplate(); diff --git a/BetterGenshinImpact/GameTask/AutoFight/Assets/combat_avatar.json b/BetterGenshinImpact/GameTask/AutoFight/Assets/combat_avatar.json index 1e2a05dc..bf10ff6a 100644 --- a/BetterGenshinImpact/GameTask/AutoFight/Assets/combat_avatar.json +++ b/BetterGenshinImpact/GameTask/AutoFight/Assets/combat_avatar.json @@ -1804,7 +1804,6 @@ "瓦雷沙", "牛头人", "牛战士", - "牛牛", "奶牛", "奶牛妹" ], diff --git a/BetterGenshinImpact/GameTask/AutoFight/Config/DefaultAutoFightConfig.cs b/BetterGenshinImpact/GameTask/AutoFight/Config/DefaultAutoFightConfig.cs index 7f8d6f21..928f0c5e 100644 --- a/BetterGenshinImpact/GameTask/AutoFight/Config/DefaultAutoFightConfig.cs +++ b/BetterGenshinImpact/GameTask/AutoFight/Config/DefaultAutoFightConfig.cs @@ -1,6 +1,6 @@ using BetterGenshinImpact.Core.Config; -using BetterGenshinImpact.Service; using System; +using System.Collections.Frozen; using System.Collections.Generic; using System.IO; using System.Linq; @@ -10,24 +10,31 @@ namespace BetterGenshinImpact.GameTask.AutoFight.Config; public class DefaultAutoFightConfig { - public static List CombatAvatars { get; set; } + //public static List CombatAvatars { get; set; } public static List CombatAvatarNames { get; set; } public static Dictionary CombatAvatarMap { get; set; } public static Dictionary CombatAvatarNameEnMap { get; set; } + public static FrozenDictionary CombatAvatarAliasToNameMap { get; set; } static DefaultAutoFightConfig() { var json = File.ReadAllText(Global.Absolute(@"GameTask\AutoFight\Assets\combat_avatar.json")); - var config = Newtonsoft.Json.JsonConvert.DeserializeObject>(json); - CombatAvatars = config ?? throw new Exception("combat_avatar.json deserialize failed"); + var config = Newtonsoft.Json.JsonConvert.DeserializeObject>(json) ?? throw new Exception("combat_avatar.json deserialize failed"); + //CombatAvatars = config; CombatAvatarNames = config.Select(x => x.Name).ToList(); CombatAvatarMap = config.ToDictionary(x => x.Name); CombatAvatarNameEnMap = config.ToDictionary(x => x.NameEn); + CombatAvatarAliasToNameMap = config.SelectMany(c => c.Alias.Select(a => new KeyValuePair(a, c.Name))).ToFrozenDictionary(); } public static string AvatarAliasToStandardName(string alias) { - var avatar = CombatAvatars.Find(x => x.Alias.Contains(alias)) ?? throw new Exception($"角色名称校验失败:{alias}"); - return avatar.Name; + if (CombatAvatarAliasToNameMap.TryGetValue(alias, out string? name) && name != null) + { + return name; + } + throw new Exception($"角色名称校验失败:{alias}"); + + // return CombatAvatars.Find(x => x.Alias.Contains(alias))?.Name ?? throw new Exception($"角色名称校验失败:{alias}"); } } diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.en.resx b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.en.resx new file mode 100644 index 00000000..627959b6 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.en.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + bite + + + Fishing + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.fr.resx b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.fr.resx new file mode 100644 index 00000000..e81752ca --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.fr.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + mordu + + + P[ê|é]cher + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hans.resx b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hans.resx new file mode 100644 index 00000000..80880314 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hans.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 上钩 + + + 钓鱼 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hant.resx b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hant.resx new file mode 100644 index 00000000..30a47577 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hant.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 上鉤 + + + 釣魚 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTask.cs b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTask.cs index 86c38fc7..6ca5b765 100644 --- a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTask.cs +++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTask.cs @@ -25,6 +25,10 @@ using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.Core.Recognition.ONNX; using static Vanara.PInvoke.User32; using BetterGenshinImpact.GameTask.AutoFight.Assets; +using System.Globalization; +using Microsoft.Extensions.Localization; +using BetterGenshinImpact.Helpers; +using BetterGenshinImpact.Core.Recognition.OCR; namespace BetterGenshinImpact.GameTask.AutoFishing { @@ -47,6 +51,10 @@ namespace BetterGenshinImpact.GameTask.AutoFishing { this._ct = ct; + IOcrService ocrService = OcrFactory.Paddle; + + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer)); + var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).WithSessionOptions(BgiSessionOption.Instance.Options).Build(); Blackboard blackboard = new Blackboard(predictor, this.Sleep, AutoFishingAssets.Instance); @@ -60,7 +68,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing .PushLeaf(() => new TurnAround("转圈圈调整视角", blackboard, _logger, param.SaveScreenshotOnKeyTick, input)) .PushLeaf(() => new FindFishTimeout("找到鱼", 20, blackboard, _logger, param.SaveScreenshotOnKeyTick)) .End() - .PushLeaf(() => new EnterFishingMode("进入钓鱼模式", blackboard, _logger, param.SaveScreenshotOnKeyTick, input)) + .PushLeaf(() => new EnterFishingMode("进入钓鱼模式", blackboard, _logger, param.SaveScreenshotOnKeyTick, input, cultureInfo: param.GameCultureInfo)) .UntilFailed(@"\") .Sequence("一直钓鱼直到没鱼") .AlwaysSucceed(@"\") @@ -80,17 +88,17 @@ namespace BetterGenshinImpact.GameTask.AutoFishing .UntilSuccess("重复抛竿") .Sequence("-") .PushLeaf(() => new MoveViewpointDown("调整视角至俯视", blackboard, _logger, param.SaveScreenshotOnKeyTick, input)) - //.MySimpleParallel("举起鱼竿并抛竿", policy: SimpleParallelPolicy.OnlyOneMustSucceed) - // .PushLeaf(() => new LiftAndHold("举起鱼竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input)) + //.MySimpleParallel("举起鱼竿并抛竿", policy: SimpleParallelPolicy.OnlyOneMustSucceed) + // .PushLeaf(() => new LiftAndHold("举起鱼竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input)) .PushLeaf(() => new ThrowRod("抛竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input)) - //.End() + //.End() .End() .End() .Do("抛竿检查", _ => (blackboard.abort || blackboard.throwRodNoTarget || blackboard.throwRodNoBaitFish) ? BehaviourStatus.Failed : BehaviourStatus.Running) .End() .MySimpleParallel("下杆中", SimpleParallelPolicy.OnlyOneMustSucceed) .PushLeaf(() => new CheckThrowRod("检查抛竿结果", blackboard, _logger, param.SaveScreenshotOnKeyTick)) // todo 后面串联一个召回率高的下杆中检测方法 - .PushLeaf(() => new FishBite("自动提竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input)) + .PushLeaf(() => new FishBite("自动提竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input, ocrService, cultureInfo: param.GameCultureInfo, stringLocalizer: stringLocalizer)) .PushLeaf(() => new FishBiteTimeout("下杆超时检查", param.ThrowRodTimeOutTimeoutSeconds, _logger, param.SaveScreenshotOnKeyTick, input)) .End() .MySimpleParallel("拉条中", policy: SimpleParallelPolicy.OnlyOneMustSucceed) @@ -108,13 +116,13 @@ namespace BetterGenshinImpact.GameTask.AutoFishing .End() .PushLeaf(() => new WholeProcessTimeout("检查整体超时", param.WholeProcessTimeoutSeconds, _logger, param.SaveScreenshotOnKeyTick)) .End() - .PushLeaf(() => new QuitFishingMode("退出钓鱼模式", blackboard, _logger, param.SaveScreenshotOnKeyTick, input)) + .PushLeaf(() => new QuitFishingMode("退出钓鱼模式", blackboard, _logger, param.SaveScreenshotOnKeyTick, input, param.GameCultureInfo)) .End() .Build(); // @formatter:on _logger.LogInformation("→ {Text}", "自动钓鱼,启动!"); _logger.LogWarning("请不要携带任何{Msg},极有可能会误识别导致无法结束自动钓鱼!", "跟宠"); - _logger.LogInformation($"当前参数:{param.WholeProcessTimeoutSeconds},{param.ThrowRodTimeOutTimeoutSeconds},{param.FishingTimePolicy}, {param.SaveScreenshotOnKeyTick}"); + _logger.LogInformation($"当前参数:{param.WholeProcessTimeoutSeconds},{param.ThrowRodTimeOutTimeoutSeconds},{param.FishingTimePolicy}, {param.SaveScreenshotOnKeyTick}, {param.GameCultureInfo}"); TaskContext.Instance().Config.AutoFishingConfig.Enabled = false; _logger.LogInformation("全自动运行时,自动切换实时任务中的半自动钓鱼功能为关闭状态"); @@ -340,12 +348,15 @@ namespace BetterGenshinImpact.GameTask.AutoFishing private DateTimeOffset? pressFWaitEndTime; private DateTimeOffset? clickWhiteConfirmButtonWaitEndTime; private DateTimeOffset? overallWaitEndTime; + private readonly string fishingLocalizedString; - public EnterFishingMode(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminate, IInputSimulator input, TimeProvider? timeProvider = null) : base(name, logger, saveScreenshotOnTerminate) + public EnterFishingMode(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminate, IInputSimulator input, TimeProvider? timeProvider = null, CultureInfo? cultureInfo = null) : base(name, logger, saveScreenshotOnTerminate) { this.blackboard = blackboard; this.input = input; this.timeProvider = timeProvider ?? TimeProvider.System; + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer)); + this.fishingLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "钓鱼"); } protected override BehaviourStatus Update(ImageRegion imageRegion) @@ -356,7 +367,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing return BehaviourStatus.Running; } - if ((pressFWaitEndTime == null || pressFWaitEndTime < timeProvider.GetLocalNow()) && Bv.FindFAndPress(imageRegion, input.Keyboard, "钓鱼")) + if ((pressFWaitEndTime == null || pressFWaitEndTime < timeProvider.GetLocalNow()) && Bv.FindFAndPress(imageRegion, input.Keyboard, this.fishingLocalizedString)) { logger.LogInformation("按下钓鱼键"); pressFWaitEndTime = timeProvider.GetLocalNow().AddSeconds(3); @@ -397,11 +408,14 @@ namespace BetterGenshinImpact.GameTask.AutoFishing { private readonly IInputSimulator input; private readonly Blackboard blackboard; + private readonly string fishingLocalizedString; - public QuitFishingMode(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminate, IInputSimulator input) : base(name, logger, saveScreenshotOnTerminate) + public QuitFishingMode(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminate, IInputSimulator input, CultureInfo? cultureInfo = null) : base(name, logger, saveScreenshotOnTerminate) { this.blackboard = blackboard; this.input = input; + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer)); + this.fishingLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "钓鱼"); } protected override BehaviourStatus Update(ImageRegion imageRegion) @@ -411,7 +425,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing return BehaviourStatus.Running; } - if (Bv.FindF(imageRegion, "钓鱼")) + if (Bv.FindF(imageRegion, this.fishingLocalizedString)) { logger.LogInformation("退出完成"); return BehaviourStatus.Succeeded; diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTaskParam.cs b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTaskParam.cs index 6b3567fa..44252a3d 100644 --- a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTaskParam.cs +++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTaskParam.cs @@ -4,12 +4,13 @@ using System.Collections.Generic; using System.Text; using BetterGenshinImpact.Helpers; using Microsoft.ClearScript; +using System.Globalization; namespace BetterGenshinImpact.GameTask.AutoFishing { public class AutoFishingTaskParam : BaseTaskParam { - public AutoFishingTaskParam(int wholeProcessTimeoutSeconds, int throwRodTimeOutTimeoutSeconds, FishingTimePolicy fishingTimePolicy, bool saveScreenshotOnKeyTick) + public AutoFishingTaskParam(int wholeProcessTimeoutSeconds, int throwRodTimeOutTimeoutSeconds, FishingTimePolicy fishingTimePolicy, bool saveScreenshotOnKeyTick, CultureInfo? cultureInfo) : base(cultureInfo) { WholeProcessTimeoutSeconds = wholeProcessTimeoutSeconds; ThrowRodTimeOutTimeoutSeconds = throwRodTimeOutTimeoutSeconds; @@ -43,7 +44,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing var fishingTimePolicy = (FishingTimePolicy)ScriptObjectConverter.GetValue(jsObject, "fishingTimePolicy", (int)autoFishingConfig.FishingTimePolicy); var saveScreenshotOnKeyTick = ScriptObjectConverter.GetValue(jsObject, "saveScreenshotOnKeyTick", false); - return new AutoFishingTaskParam(wholeProcessTimeoutSeconds, throwRodTimeOutTimeoutSeconds, fishingTimePolicy, saveScreenshotOnKeyTick); + return new AutoFishingTaskParam(wholeProcessTimeoutSeconds, throwRodTimeOutTimeoutSeconds, fishingTimePolicy, saveScreenshotOnKeyTick, null); } /// @@ -54,7 +55,8 @@ namespace BetterGenshinImpact.GameTask.AutoFishing /// public static AutoFishingTaskParam BuildFromConfig(AutoFishingConfig config, bool saveScreenshotOnKeyTick = false) { - return new AutoFishingTaskParam(config.WholeProcessTimeoutSeconds, config.AutoThrowRodTimeOut, config.FishingTimePolicy, saveScreenshotOnKeyTick); + CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); + return new AutoFishingTaskParam(config.WholeProcessTimeoutSeconds, config.AutoThrowRodTimeOut, config.FishingTimePolicy, saveScreenshotOnKeyTick, cultureInfo); } } } \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTrigger.cs b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTrigger.cs index 8d6c8999..a6621459 100644 --- a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTrigger.cs +++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTrigger.cs @@ -17,6 +17,8 @@ using BetterGenshinImpact.GameTask.Model.Area; using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.Core.Recognition.ONNX; using Compunet.YoloV8; +using Microsoft.Extensions.Localization; +using BetterGenshinImpact.Core.Recognition.OCR; namespace BetterGenshinImpact.GameTask.AutoFishing { @@ -45,6 +47,10 @@ namespace BetterGenshinImpact.GameTask.AutoFishing public AutoFishingTrigger() { + AutoFishingTaskParam autoFishingTaskParam = AutoFishingTaskParam.BuildFromConfig(TaskContext.Instance().Config.AutoFishingConfig); + IOcrService ocrService = OcrFactory.Paddle; + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer)); + var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).WithSessionOptions(BgiSessionOption.Instance.Options).Build(); this.blackboard = new Blackboard(predictor, this.Sleep, AutoFishingAssets.Instance); @@ -53,7 +59,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing .Do("检查是否在钓鱼界面", CheckFishingUserInterface) .UntilSuccess("拉条循环") .Sequence("拉条") - .PushLeaf(() => new FishBite("自动提竿", blackboard, _logger, false, input)) + .PushLeaf(() => new FishBite("自动提竿", blackboard, _logger, false, input, ocrService, cultureInfo: autoFishingTaskParam.GameCultureInfo, stringLocalizer: stringLocalizer)) .PushLeaf(() => new GetFishBoxArea("等待拉条出现", blackboard, _logger, false)) .PushLeaf(() => new Fishing("钓鱼拉条", blackboard, _logger, false, input)) .End() diff --git a/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs b/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs index dfe461a9..42f703b2 100644 --- a/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs +++ b/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs @@ -21,6 +21,8 @@ using Fischless.WindowsInput; using BetterGenshinImpact.Core.Recognition.OpenCv; using BetterGenshinImpact.Core.Simulator; using BetterGenshinImpact.GameTask.Model; +using System.Globalization; +using Microsoft.Extensions.Localization; namespace BetterGenshinImpact.GameTask.AutoFishing { @@ -684,12 +686,15 @@ namespace BetterGenshinImpact.GameTask.AutoFishing private readonly Blackboard blackboard; private readonly IInputSimulator input; private readonly DrawContent drawContent; - private readonly IOcrService ocrService = OcrFactory.Paddle; - public FishBite(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminat, IInputSimulator input, DrawContent? drawContent = null) : base(name, logger, saveScreenshotOnTerminat) + private readonly IOcrService ocrService; + private readonly string getABiteLocalizedString; + public FishBite(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminat, IInputSimulator input, IOcrService ocrService, DrawContent? drawContent = null, CultureInfo? cultureInfo = null, IStringLocalizer? stringLocalizer = null) : base(name, logger, saveScreenshotOnTerminat) { this.blackboard = blackboard; this.input = input; + this.ocrService = ocrService; this.drawContent = drawContent ?? VisionContext.Instance().DrawContent; + this.getABiteLocalizedString = stringLocalizer == null ? "上钩" : stringLocalizer.WithCultureGet(cultureInfo, "上钩"); } protected override void OnInitialize() @@ -702,11 +707,11 @@ namespace BetterGenshinImpact.GameTask.AutoFishing // 自动识别的钓鱼框向下延伸到屏幕中间 //var liftingWordsAreaRect = new Rect(fishBoxRect.X, fishBoxRect.Y + fishBoxRect.Height * 2, // fishBoxRect.Width, imageRegion.CaptureRectArea.SrcMat.Height / 2 - fishBoxRect.Y - fishBoxRect.Height * 5); - // 上半屏幕和中间1/3的区域 + // 上半屏幕和中间1/2的区域 var liftingWordsAreaRect = new Rect(imageRegion.SrcMat.Width / 3, 0, imageRegion.SrcMat.Width / 3, imageRegion.SrcMat.Height / 2); //VisionContext.Instance().DrawContent.PutRect("liftingWordsAreaRect", liftingWordsAreaRect.ToRectDrawable(new Pen(Color.Cyan, 2))); - var wordCaptureMat = new Mat(imageRegion.SrcMat, liftingWordsAreaRect); + using var wordCaptureMat = new Mat(imageRegion.SrcMat, liftingWordsAreaRect); var currentBiteWordsTips = AutoFishingImageRecognition.MatchFishBiteWords(wordCaptureMat, liftingWordsAreaRect); if (currentBiteWordsTips != Rect.Empty) { @@ -717,40 +722,36 @@ namespace BetterGenshinImpact.GameTask.AutoFishing using var tipsRa = imageRegion.Derive(currentBiteWordsTips + liftingWordsAreaRect.Location); tipsRa.DrawSelf("FishBiteTips"); - // 图像提竿判断 - using var liftRodButtonRa = imageRegion.Find(blackboard.AutoFishingAssets.LiftRodButtonRo); - if (!liftRodButtonRa.IsEmpty()) - { - input.Mouse.LeftButtonClick(); - logger.LogInformation(@"┌------------------------┐"); - logger.LogInformation(" 自动提竿(图像识别)"); - drawContent.RemoveRect("FishBiteTips"); - return BehaviourStatus.Succeeded; - } + return RaiseRod("文字块"); + } - // OCR 提竿判断 - var text = ocrService.Ocr(new Mat(imageRegion.SrcGreyMat, - new Rect(currentBiteWordsTips.X + liftingWordsAreaRect.X, - currentBiteWordsTips.Y + liftingWordsAreaRect.Y, - currentBiteWordsTips.Width, currentBiteWordsTips.Height))); - if (!string.IsNullOrEmpty(text) && StringUtils.RemoveAllSpace(text).Contains("上钩")) - { - input.Mouse.LeftButtonClick(); - logger.LogInformation(@"┌------------------------┐"); - logger.LogInformation(" 自动提竿(OCR)"); - drawContent.RemoveRect("FishBiteTips"); - return BehaviourStatus.Succeeded; - } + // 图像提竿判断 + using var liftRodButtonRa = imageRegion.Find(blackboard.AutoFishingAssets.LiftRodButtonRo); + if (!liftRodButtonRa.IsEmpty()) + { + return RaiseRod("图像识别"); + } - input.Mouse.LeftButtonClick(); - logger.LogInformation(@"┌------------------------┐"); - logger.LogInformation(" 自动提竿(文字块)"); - drawContent.RemoveRect("FishBiteTips"); - return BehaviourStatus.Succeeded; + // OCR 提竿判断 + using Mat wordCaptureGreyMat = new Mat(imageRegion.SrcGreyMat, liftingWordsAreaRect); + var text = ocrService.Ocr(wordCaptureGreyMat); + + if (!string.IsNullOrEmpty(text) && StringUtils.RemoveAllSpace(text).Contains(this.getABiteLocalizedString)) + { + return RaiseRod("OCR"); } return BehaviourStatus.Running; } + + private BehaviourStatus RaiseRod(string method) + { + input.Mouse.LeftButtonClick(); + logger.LogInformation(@"┌------------------------┐"); + logger.LogInformation(" 自动提竿({m})", method); + drawContent.RemoveRect("FishBiteTips"); + return BehaviourStatus.Succeeded; + } } /// diff --git a/BetterGenshinImpact/GameTask/AutoFishing/RodNet.cs b/BetterGenshinImpact/GameTask/AutoFishing/RodNet.cs index c4a09342..a923b2a0 100644 --- a/BetterGenshinImpact/GameTask/AutoFishing/RodNet.cs +++ b/BetterGenshinImpact/GameTask/AutoFishing/RodNet.cs @@ -6,6 +6,33 @@ namespace BetterGenshinImpact.GameTask.AutoFishing; /// /// copy from https://github.com/myHuTao-qwq/HutaoFisher/blob/master/src/rodnet.cpp +/// +/// 以下是hutaofisher的访谈: +/// +/// 修改我的qq昵称: 03-20 00:22:48 +/// 有任何问题可以问我 只要我在工位而不是在实验室里跟XXXX斗智斗勇就回答你 +/// +/// 额 我的算法有几个感觉挺符合直觉的假设 +/// +/// 就是 你抛竿的时候鱼是否会咬钩取决于鱼饵落点到鱼的距离 +/// +/// 这里的距离是鱼饵落点的(x, y, z)坐标与鱼的(x, y, z)坐标之差在xy平面(水平面)上的投影 +/// +/// 现在问题转化成了如何估计这两个坐标 +/// +/// 这里我们先约定x轴就是水平面上与屏幕长边平行的线 y轴就是屏幕短边的对于 剩下一个z就是游戏里面往天上的方向 +/// +/// 然后经验告诉我鱼饵落点环的x几乎为0 +/// +/// 剩下我们可以用鱼饵落点环的长和宽算出y和z +/// +/// 再近似鱼的bouding box的中心就是鱼计算咬钩的那个点 同时近似一个大类里面的所有鱼的z是相同的(这个参数可学习) 于是我们也可以计算出鱼的xyz +/// +/// 最后一步就是把对应的投影距离算出来 然后线性回归一下得到太近 刚好 太远三个类 +/// +/// tmd 今天我意识到 XXXX可不就是XXXX +/// +/// 哦 到这一步以后剩下的就很弱智了 远了挪近一点 近了挪远一点 调调参差不多得了 /// public class RodNet { diff --git a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs index 145961e7..44572a35 100644 --- a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs +++ b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -22,7 +23,9 @@ using BetterGenshinImpact.GameTask.Common.Job; using BetterGenshinImpact.GameTask.Common.Map; using BetterGenshinImpact.GameTask.Model.Area; using BetterGenshinImpact.GameTask.QuickTeleport.Assets; +using BetterGenshinImpact.Helpers; using BetterGenshinImpact.Helpers.Extensions; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using OpenCvSharp; using Vanara.PInvoke; @@ -48,7 +51,7 @@ public class TpTask(CancellationToken ct) /// 直接通过缩放比例按钮计算缩小按钮的Y坐标 /// private readonly int _zoomOutButtonY = TaskContext.Instance().Config.TpConfig.ZoomEndY + 24; // y-coordinate for zoom-out button = _zoomEndY + 24 - + private const double DisplayTpPointZoomLevel = 4.4; // 传送点显示的时候的地图比例 /// @@ -57,7 +60,7 @@ public class TpTask(CancellationToken ct) public async Task TpToStatueOfTheSeven() { await CheckInBigMapUi(); - + // 提前调整至恰当的缩放以更快的传送 if (_tpConfig.MapZoomEnabled) { @@ -103,7 +106,7 @@ public class TpTask(CancellationToken ct) await new PathExecutor(ct).MoveTo(waypointForTrack); Simulation.SendInput.SimulateAction(GIActions.Drop); } - + await Delay((int)(_tpConfig.HpRestoreDuration * 1000), ct); } @@ -153,9 +156,9 @@ public class TpTask(CancellationToken ct) } } // 获取最近的神像位置 - return nearestGiTpPosition ?? throw new InvalidOperationException("没找到最近的七天神像");; + return nearestGiTpPosition ?? throw new InvalidOperationException("没找到最近的七天神像"); } - + /// /// 通过大地图传送到指定坐标最近的传送点,然后移动到指定坐标 /// @@ -275,7 +278,7 @@ public class TpTask(CancellationToken ct) Logger.LogWarning("传送等待超时,换台电脑吧"); } - + /// /// 传送点是否在大地图窗口内 /// @@ -423,13 +426,13 @@ public class TpTask(CancellationToken ct) ++exceptionTimes; mapCenterPoint = new Point2f(0f, 0f); // 其他恰当的初始值? } - + var (xOffset, yOffset) = (x - mapCenterPoint.X, y - mapCenterPoint.Y); double totalMoveMouseX = _tpConfig.MapScaleFactor * Math.Abs(xOffset) / currentZoomLevel; double totalMoveMouseY = _tpConfig.MapScaleFactor * Math.Abs(yOffset) / currentZoomLevel; double mouseDistance = Math.Sqrt(totalMoveMouseX * totalMoveMouseX + totalMoveMouseY * totalMoveMouseY); // 缩小地图到恰当的缩放 - if (_tpConfig.MapZoomEnabled) + if (_tpConfig.MapZoomEnabled) { if (mouseDistance > _tpConfig.MapZoomOutDistance) { @@ -443,7 +446,7 @@ public class TpTask(CancellationToken ct) currentZoomLevel = nextZoomLevel; } } - + // 开始移动并放大地图 for (var iteration = 0; iteration < _tpConfig.MaxIterations; iteration++) { @@ -476,7 +479,7 @@ public class TpTask(CancellationToken ct) int moveMouseY = (int)Math.Min(totalMoveMouseY, _tpConfig.MaxMouseMove * totalMoveMouseY / mouseDistance) * Math.Sign(yOffset); double moveMouseLength = Math.Sqrt(moveMouseX * moveMouseX + moveMouseY * moveMouseY); int moveSteps = Math.Max((int)moveMouseLength / 10, 3); // 每次移动的步数最小为 3,避免除 0 错误 - + await MouseMoveMap(moveMouseX, moveMouseY, moveSteps); try { @@ -526,7 +529,7 @@ public class TpTask(CancellationToken ct) /// 调整地图缩放级别以加速移动 /// /// 是否放大地图 - [Obsolete] + [Obsolete] private async Task AdjustMapZoomLevel(bool zoomIn) { if (zoomIn) @@ -598,33 +601,37 @@ public class TpTask(CancellationToken ct) Simulation.SendInput.Mouse.LeftButtonUp(); } - private int[] GenerateSteps(int delta, int steps) { + private int[] GenerateSteps(int delta, int steps) + { double[] factors = new double[steps]; double sum = 0; - for (int i = 0; i < steps; i++) { + for (int i = 0; i < steps; i++) + { factors[i] = Math.Cos(i * Math.PI / (2 * steps)); sum += factors[i]; } int[] stepsArr = new int[steps]; int remaining = delta; - + // 两阶段分配:基础值 + 余数补偿 - for (int i = 0; i < steps; i++) { + for (int i = 0; i < steps; i++) + { double ratio = factors[i] / sum; stepsArr[i] = (int)(delta * ratio); // 基础值 remaining -= stepsArr[i]; } int center = steps / 2; - for (int r = 0; r < Math.Abs(remaining); r++) { + for (int r = 0; r < Math.Abs(remaining); r++) + { int target = (center + r) % steps; // 从中点开始螺旋分配 stepsArr[target] += remaining > 0 ? 1 : -1; } return stepsArr; } - + public Point2f GetPositionFromBigMap() { return GetBigMapCenterPoint(); @@ -796,14 +803,26 @@ public class TpTask(CancellationToken ct) GameCaptureRegion.GameRegionClick((rect, scale) => (rect.Width - 160 * scale, rect.Height - 60 * scale)); await Delay(300, ct); - var ra = CaptureToRectArea(); + using var ra = CaptureToRectArea(); var list = ra.FindMulti(new RecognitionObject { RecognitionType = RecognitionTypes.Ocr, RegionOfInterest = new Rect(ra.Width / 2, 0, ra.Width / 2, ra.Height) }); - list.FirstOrDefault(r => r.Text.Length == minCountry.Length && !r.Text.Contains("委托") && r.Text.Contains(minCountry))?.Click(); - Logger.LogInformation("切换到区域:{Country}", minCountry); + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer)); + CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); + string minCountryLocalized = stringLocalizer.WithCultureGet(cultureInfo, minCountry); + string commissionLocalized = stringLocalizer.WithCultureGet(cultureInfo, "委托"); + Region? matchRect = list.FirstOrDefault(r => r.Text.Length == minCountryLocalized.Length && !r.Text.Contains(commissionLocalized) && r.Text.Contains(minCountryLocalized)); + if (matchRect == null) + { + Logger.LogWarning("切换区域失败:{Country}", minCountry); + } + else + { + matchRect.Click(); + Logger.LogInformation("切换到区域:{Country}", minCountry); + } await Delay(500, ct); return true; } diff --git a/BetterGenshinImpact/GameTask/Common/BgiVision/BvSimpleOperation.cs b/BetterGenshinImpact/GameTask/Common/BgiVision/BvSimpleOperation.cs index 419fe8fa..1907cf9a 100644 --- a/BetterGenshinImpact/GameTask/Common/BgiVision/BvSimpleOperation.cs +++ b/BetterGenshinImpact/GameTask/Common/BgiVision/BvSimpleOperation.cs @@ -1,12 +1,11 @@ -using System.Windows.Documents; -using BetterGenshinImpact.Core.Recognition; +using BetterGenshinImpact.Core.Recognition; using BetterGenshinImpact.Core.Simulator; using BetterGenshinImpact.GameTask.AutoPick.Assets; -using BetterGenshinImpact.GameTask.AutoSkip.Assets; using BetterGenshinImpact.GameTask.Common.Element.Assets; using BetterGenshinImpact.GameTask.Model.Area; using Fischless.WindowsInput; using OpenCvSharp; +using System.Text.RegularExpressions; namespace BetterGenshinImpact.GameTask.Common.BgiVision; @@ -170,7 +169,7 @@ public static partial class Bv var success = true; foreach (var t in text) { - if (!item.Text.Contains(t)) + if (!Regex.IsMatch(item.Text, t)) { success = false; } diff --git a/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs b/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs index 8c4570a8..16d879e4 100644 --- a/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs +++ b/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs @@ -6,9 +6,6 @@ using System; using System.Linq; using System.Threading.Tasks; using BetterGenshinImpact.Core.Recognition; -using BetterGenshinImpact.Core.Simulator; -using BetterGenshinImpact.GameTask.AutoFight; -using Vanara.PInvoke; using System.Threading; using BetterGenshinImpact.GameTask.AutoFight.Assets; using BetterGenshinImpact.GameTask.AutoSkip.Assets; diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.en.resx b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.en.resx new file mode 100644 index 00000000..da0f2d6b --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.en.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Commission + + + Fontaine + + + Liyue + + + Inazuma + + + Natlan + + + Mondstadt + + + Sumeru + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.fr.resx b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.fr.resx new file mode 100644 index 00000000..3b4d5fc7 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.fr.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Mission + + + Fontaine + + + Liyue + + + Inazuma + + + Natlan + + + Mondstadt + + + Sumeru + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hans.resx new file mode 100644 index 00000000..36052e90 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hans.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 委托 + + + 枫丹 + + + 璃月 + + + 稻妻 + + + 纳塔 + + + 蒙德 + + + 须弥 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hant.resx new file mode 100644 index 00000000..e49b43e1 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hant.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 委[託,話] + + + 楓丹 + + + 璃月 + + + 稻妻 + + + 納塔 + + + 蒙德 + + + 須彌 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.cs b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.cs index 33b33b78..7de64c5f 100644 --- a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.cs +++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.cs @@ -1,12 +1,16 @@ using System; +using System.Globalization; using System.Linq; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BetterGenshinImpact.Core.Recognition; using BetterGenshinImpact.Core.Simulator; using BetterGenshinImpact.Core.Simulator.Extensions; +using BetterGenshinImpact.Helpers; using BetterGenshinImpact.Service.Notification; using BetterGenshinImpact.Service.Notification.Model.Enum; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using static BetterGenshinImpact.GameTask.Common.TaskControl; @@ -20,6 +24,15 @@ public class CheckRewardsTask { private readonly ILogger _logger = App.GetLogger(); + private readonly string dailyRewardsClaimedLocalizedString; + + public CheckRewardsTask() + { + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); + CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); + this.dailyRewardsClaimedLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "今日奖励已领取"); + } + public string Name => "检查奖励并通知的任务"; public async Task Start(CancellationToken ct) @@ -33,7 +46,7 @@ public class CheckRewardsTask var assetScale = TaskContext.Instance().SystemInfo.AssetScale; using var ra = CaptureToRectArea(); var ocrList = ra.FindMulti(RecognitionObject.Ocr(0, ra.Height - ra.Height / 3.0, 730 * assetScale, ra.Height / 3.0)); - var done = ocrList.FirstOrDefault(txt => txt.Text.Contains("今日奖励已领取")); + var done = ocrList.FirstOrDefault(txt => Regex.IsMatch(txt.Text, this.dailyRewardsClaimedLocalizedString)); if (done != null) { Logger.LogInformation("检查每日奖励结果:{Msg}", "今日奖励已领取"); diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.en.resx new file mode 100644 index 00000000..63cf9bf9 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.en.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + claimed + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.fr.resx new file mode 100644 index 00000000..d32af2bf --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.fr.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + récupérées + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hans.resx new file mode 100644 index 00000000..8a900032 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hans.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 今日奖励已领取 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hant.resx new file mode 100644 index 00000000..fd780202 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hant.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 今日獎勵已領取 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.cs b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.cs index e06df9a7..2aac397b 100644 --- a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.cs +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.cs @@ -1,12 +1,16 @@ using System; +using System.Globalization; using System.Linq; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BetterGenshinImpact.Core.Recognition; using BetterGenshinImpact.Core.Simulator.Extensions; using BetterGenshinImpact.GameTask.Common.Element.Assets; using BetterGenshinImpact.GameTask.Model.Area; +using BetterGenshinImpact.Helpers; using BetterGenshinImpact.Helpers.Extensions; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Vanara.PInvoke; using static BetterGenshinImpact.GameTask.Common.TaskControl; @@ -20,6 +24,15 @@ public class ClaimBattlePassRewardsTask { private readonly ReturnMainUiTask _returnMainUiTask = new(); + private readonly string claimAllLocalizedString; + + public ClaimBattlePassRewardsTask() + { + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); + CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); + this.claimAllLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "一键"); + } + public async Task Start(CancellationToken ct) { try @@ -74,7 +87,7 @@ public class ClaimBattlePassRewardsTask { using var ra = CaptureToRectArea(); var ocrList = ra.FindMulti(RecognitionObject.Ocr(ra.ToRect().CutRightBottom(0.3, 0.18))); - var wt = ocrList.FirstOrDefault(txt => txt.Text.Contains("一键")); + var wt = ocrList.FirstOrDefault(txt => Regex.IsMatch(txt.Text, this.claimAllLocalizedString)); if (wt != null) { wt.Click(); diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.en.resx new file mode 100644 index 00000000..fb941363 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.en.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + All + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.fr.resx new file mode 100644 index 00000000..d57ecdfa --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.fr.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Tout + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hans.resx new file mode 100644 index 00000000..4c89b85f --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hans.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 一键 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hant.resx new file mode 100644 index 00000000..ce0c0e49 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hant.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 一鍵 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.cs b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.cs index 94df7cd7..5387ba45 100644 --- a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.cs +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.cs @@ -1,5 +1,7 @@ using System; +using System.Globalization; using System.Linq; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BetterGenshinImpact.Core.Recognition; @@ -7,6 +9,8 @@ using BetterGenshinImpact.Core.Simulator; using BetterGenshinImpact.Core.Simulator.Extensions; using BetterGenshinImpact.GameTask.Common.Element.Assets; using BetterGenshinImpact.GameTask.Model.Area; +using BetterGenshinImpact.Helpers; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Vanara.PInvoke; using static BetterGenshinImpact.GameTask.Common.TaskControl; @@ -20,6 +24,15 @@ public class ClaimEncounterPointsRewardsTask { private readonly ReturnMainUiTask _returnMainUiTask = new(); + private readonly string commissionsLocalizedString; + + public ClaimEncounterPointsRewardsTask() + { + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); + CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); + this.commissionsLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "委托"); + } + public async Task Start(CancellationToken ct) { try @@ -51,9 +64,9 @@ public class ClaimEncounterPointsRewardsTask { using var ra = CaptureToRectArea(); - var ocrList = ra.FindMulti(RecognitionObject.Ocr(0, 0, 360 * assetScale, ra.Height)); + var ocrList = ra.FindMulti(RecognitionObject.Ocr(0, 0, 380 * assetScale, ra.Height)); - var wt = ocrList.FirstOrDefault(txt => txt.Text.Contains("委托")); + var wt = ocrList.FirstOrDefault(txt => Regex.IsMatch(txt.Text, this.commissionsLocalizedString)); if (wt != null) { diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.en.resx new file mode 100644 index 00000000..6a96b443 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.en.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Commissions + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.fr.resx new file mode 100644 index 00000000..f6f62ef4 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.fr.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Missions + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hans.resx new file mode 100644 index 00000000..6a6efcc2 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hans.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 委托 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hant.resx new file mode 100644 index 00000000..a97a24e7 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hant.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 委[託,話] + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.cs b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.cs index 3def90d1..d1825583 100644 --- a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.cs +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.cs @@ -13,6 +13,9 @@ using BetterGenshinImpact.GameTask.AutoPick.Assets; using BetterGenshinImpact.GameTask.Common.Element.Assets; using Vanara.PInvoke; using static BetterGenshinImpact.GameTask.Common.TaskControl; +using Microsoft.Extensions.Localization; +using BetterGenshinImpact.Helpers; +using System.Globalization; namespace BetterGenshinImpact.GameTask.Common.Job; @@ -24,6 +27,19 @@ public class GoToAdventurersGuildTask private readonly ChooseTalkOptionTask _chooseTalkOptionTask = new(); + private readonly string dailyLocalizedString; + private readonly string catherineLocalizedString; + private readonly string expeditionLocalizedString; + + public GoToAdventurersGuildTask() + { + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); + CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); + this.dailyLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "每日"); + this.catherineLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "凯瑟琳"); + this.expeditionLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "探索"); + } + public async Task Start(string country, CancellationToken ct, string? dailyRewardPartyName = null) { Logger.LogInformation("→ {Name} 开始", Name); @@ -36,7 +52,7 @@ public class GoToAdventurersGuildTask { await new SwitchPartyTask().Start(dailyRewardPartyName, ct); } - + // F1领取奖励 await new ClaimEncounterPointsRewardsTask().Start(ct); @@ -68,7 +84,7 @@ public class GoToAdventurersGuildTask await GoToAdventurersGuild(country, ct); // 每日 - var res = await _chooseTalkOptionTask.SingleSelectText("每日", ct, 10, true); + var res = await _chooseTalkOptionTask.SingleSelectText(this.dailyLocalizedString, ct, 10, true); if (res == TalkOptionRes.FoundAndClick) { Logger.LogInformation("▶ {Text}", "领取『每日委托』奖励!"); @@ -82,7 +98,7 @@ public class GoToAdventurersGuildTask // 结束后重新打开 await Delay(1200, ct); var ra = CaptureToRectArea(); - if (!Bv.FindFAndPress(ra, "凯瑟琳")) + if (!Bv.FindFAndPress(ra, text: this.catherineLocalizedString)) { throw new Exception("未找与凯瑟琳对话交互按钮"); } @@ -97,7 +113,7 @@ public class GoToAdventurersGuildTask } // 探索 - res = await _chooseTalkOptionTask.SingleSelectText("探索", ct, 10, true); + res = await _chooseTalkOptionTask.SingleSelectText(this.expeditionLocalizedString, ct, 10, true); if (res == TalkOptionRes.FoundAndClick) { await Delay(500, ct); @@ -136,7 +152,7 @@ public class GoToAdventurersGuildTask Enabled = true, AutoSkipEnabled = true }, - EndAction = region => Bv.FindFAndPress(region, "凯瑟琳") + EndAction = region => Bv.FindFAndPress(region, text: this.catherineLocalizedString) }; await pathingTask.Pathing(task); diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.en.resx new file mode 100644 index 00000000..dbf7b3c3 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.en.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Katheryne + + + Expedition + + + Daily + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.fr.resx new file mode 100644 index 00000000..a98e8632 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.fr.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Catherine + + + Expédition + + + quotidien + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hans.resx new file mode 100644 index 00000000..08228755 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hans.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 凯瑟琳 + + + 探索 + + + 每日 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hant.resx new file mode 100644 index 00000000..6c36454a --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hant.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 凱瑟琳 + + + 探索 + + + 每日 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.cs b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.cs index d590c4f9..805cc4ec 100644 --- a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.cs +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.cs @@ -11,6 +11,9 @@ using System.Threading.Tasks; using BetterGenshinImpact.Core.Simulator.Extensions; using Vanara.PInvoke; using static BetterGenshinImpact.GameTask.Common.TaskControl; +using Microsoft.Extensions.Localization; +using System.Globalization; +using BetterGenshinImpact.Helpers; namespace BetterGenshinImpact.GameTask.Common.Job; @@ -22,6 +25,15 @@ public class GoToCraftingBenchTask private readonly ChooseTalkOptionTask _chooseTalkOptionTask = new(); + private readonly string craftLocalizedString; + + public GoToCraftingBenchTask() + { + IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); + CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); + this.craftLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "合成"); + } + public async Task Start(string country, CancellationToken ct) { Logger.LogInformation("→ {Name} 开始", Name); @@ -102,7 +114,7 @@ public class GoToCraftingBenchTask AutoSkipEnabled = true, AutoRunEnabled = country != "枫丹", }, - EndAction = region => Bv.FindFAndPress(region, "合成") + EndAction = region => Bv.FindFAndPress(region, text: this.craftLocalizedString) }; await pathingTask.Pathing(task); @@ -144,7 +156,7 @@ public class GoToCraftingBenchTask private async Task TryPressCrafting( CancellationToken ct) { using var ra1 = CaptureToRectArea(); - var res = Bv.FindFAndPress(ra1, "合成"); + var res = Bv.FindFAndPress(ra1, text: this.craftLocalizedString); if (res) { await Delay(1000, ct); diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.en.resx new file mode 100644 index 00000000..a1606c56 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.en.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Craft + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.fr.resx new file mode 100644 index 00000000..164dd0e9 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.fr.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Synth[è|é]se + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hans.resx new file mode 100644 index 00000000..b2fd29a9 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hans.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 合成 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hant.resx new file mode 100644 index 00000000..b2fd29a9 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hant.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 合成 + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Model/BaseTaskParam.cs b/BetterGenshinImpact/GameTask/Model/BaseTaskParam.cs index 527f1a96..40b53621 100644 --- a/BetterGenshinImpact/GameTask/Model/BaseTaskParam.cs +++ b/BetterGenshinImpact/GameTask/Model/BaseTaskParam.cs @@ -1,4 +1,6 @@  +using BetterGenshinImpact.GameTask.AutoFishing; +using System.Globalization; using System.Threading; namespace BetterGenshinImpact.GameTask.Model; @@ -8,4 +10,12 @@ namespace BetterGenshinImpact.GameTask.Model; /// public class BaseTaskParam { + public CultureInfo? GameCultureInfo { get; set; } + public BaseTaskParam() + { + } + public BaseTaskParam(CultureInfo? gameCultureInfo) + { + GameCultureInfo = gameCultureInfo; + } } diff --git a/BetterGenshinImpact/Helpers/CultureHelper.cs b/BetterGenshinImpact/Helpers/CultureHelper.cs new file mode 100644 index 00000000..a0b24f59 --- /dev/null +++ b/BetterGenshinImpact/Helpers/CultureHelper.cs @@ -0,0 +1,84 @@ +using BetterGenshinImpact.GameTask.Common.BgiVision; +using Microsoft.Extensions.Localization; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Text; +using System.Text.RegularExpressions; + +namespace BetterGenshinImpact.Helpers; +public static class CultureHelper +{ + public static string WithCultureGet(this IStringLocalizer stringLocalizer, CultureInfo? culture, string text) + { + if (culture == null) + { + return text; + } + else + { + using var _ = Use(culture); + return stringLocalizer[text]; + } + } + + public static IDisposable Use([NotNull] string culture, string? uiCulture = null) + { + ArgumentNullException.ThrowIfNull(culture, nameof(culture)); + + return Use( + new CultureInfo(culture), + uiCulture == null + ? null + : new CultureInfo(uiCulture) + ); + } + + /// + /// WithCulture被微软移除了,这是个替代方法,用于临时切换到某个CurrentCulture、CurrentUICulture + /// + /// + /// + /// + public static IDisposable Use([NotNull] CultureInfo culture, CultureInfo? uiCulture = null) + { + ArgumentNullException.ThrowIfNull(culture, nameof(culture)); + + var currentCulture = CultureInfo.CurrentCulture; + var currentUiCulture = CultureInfo.CurrentUICulture; + + CultureInfo.CurrentCulture = culture; + CultureInfo.CurrentUICulture = uiCulture ?? culture; + + return new DisposeAction>(static (state) => + { + var (currentCulture, currentUiCulture) = state; + CultureInfo.CurrentCulture = currentCulture; + CultureInfo.CurrentUICulture = currentUiCulture; + }, (currentCulture, currentUiCulture)); + } + + public class DisposeAction : IDisposable + { + private readonly Action _action; + + private readonly T? _parameter; + + public DisposeAction(Action action, T parameter) + { + ArgumentNullException.ThrowIfNull(action, nameof(action)); + + _action = action; + _parameter = parameter; + } + + public void Dispose() + { + if (_parameter != null) + { + _action(_parameter); + } + } + } +} diff --git a/BetterGenshinImpact/Model/ConditionDefinition.cs b/BetterGenshinImpact/Model/ConditionDefinition.cs index f2c8dcdc..67d0feb1 100644 --- a/BetterGenshinImpact/Model/ConditionDefinition.cs +++ b/BetterGenshinImpact/Model/ConditionDefinition.cs @@ -13,7 +13,7 @@ public class ConditionDefinition // 谓语选项 public List PredicateOptions { get; set; } = ["包含"]; - public List? ObjectOptions { get; set; } // 宾语选项 + public IEnumerable? ObjectOptions { get; set; } // 宾语选项 public List? ResultOptions { get; set; } // 结果选项 为空使用文本框 } diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.cs b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.cs new file mode 100644 index 00000000..31403d09 --- /dev/null +++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.cs @@ -0,0 +1,43 @@ +using BetterGenshinImpact.Helpers; +using Microsoft.Extensions.Localization; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Windows.Data; + +namespace BetterGenshinImpact.View.Converters; + +[ValueConversion(typeof(KeyValuePair), typeof(string))] +class CultureInfoNameToKVPConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value == null) + { + return null; + } + + string? cultureInfoName = value as string; + if (cultureInfoName is null) + { + throw new ArgumentException("Value must be a CultureInfoName"); + } + + var stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); + var description = stringLocalizer.WithCultureGet(new CultureInfo(cultureInfoName), "简体中文"); + + return new KeyValuePair(cultureInfoName, description); + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + if (value == null) + { + return null; + } + + var kvp = (KeyValuePair)value; + return kvp.Key; + } +} diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.en.resx b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.en.resx new file mode 100644 index 00000000..4332c376 --- /dev/null +++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.en.resx @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + English + + \ No newline at end of file diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.fr.resx b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.fr.resx new file mode 100644 index 00000000..170ffb37 --- /dev/null +++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.fr.resx @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Français + + \ No newline at end of file diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hans.resx b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hans.resx new file mode 100644 index 00000000..7451e481 --- /dev/null +++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hans.resx @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 简体中文 + + \ No newline at end of file diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hant.resx b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hant.resx new file mode 100644 index 00000000..d35382fa --- /dev/null +++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hant.resx @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 繁體中文 + + \ No newline at end of file diff --git a/BetterGenshinImpact/View/Converters/EnumToKVPConverter.cs b/BetterGenshinImpact/View/Converters/EnumToKVPConverter.cs index b71110a9..977671c2 100644 --- a/BetterGenshinImpact/View/Converters/EnumToKVPConverter.cs +++ b/BetterGenshinImpact/View/Converters/EnumToKVPConverter.cs @@ -5,10 +5,7 @@ using System.Windows.Data; using System.Windows; using System.ComponentModel; using System.Globalization; -using BetterGenshinImpact.GameTask.AutoFishing; -using BetterGenshinImpact.GameTask.AutoFight.Script; using System.Reflection; -using Vanara.Extensions.Reflection; namespace BetterGenshinImpact.View.Converters; @@ -28,7 +25,7 @@ public class EnumToKVPConverter : IValueConverter throw new ArgumentException("Value must be an enum"); } - var name = Enum.GetName(enumType, value); + var name = Enum.GetName(enumType, value) ?? throw new NullReferenceException(); var field = enumType.GetField(name); var descriptionAttribute = field?.GetCustomAttribute(); diff --git a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml index 81010529..1ccf786d 100644 --- a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml @@ -1569,13 +1569,79 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs index 7b4fbc4a..60c4a016 100644 --- a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs +++ b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs @@ -132,7 +132,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel ModifyFolderSecurity(); Config.CommonConfig.RunForVersion = Global.Version; } - + OnceRun(); // 检查更新 @@ -218,10 +218,12 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel { try { - await Task.Run(() => + await Task.Run(async () => { try { + string gameCultureInfoName = TaskContext.Instance().Config.OtherConfig.GameCultureInfoName; + await OcrFactory.ChangeCulture(gameCultureInfoName); var s = OcrFactory.Paddle.Ocr(new Mat(Global.Absolute(@"Assets\Model\PaddleOCR\test_ocr.png"), ImreadModes.Grayscale)); Debug.WriteLine("PaddleOcr预热结果:" + s); } @@ -265,7 +267,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel { _logger.LogDebug("获取设备ID异常:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); } - + // 每个设备只运行一次 if (!Config.CommonConfig.OnceHadRunDeviceIdList.Contains(deviceId)) { @@ -275,7 +277,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel }; prompt.ShowDialog(); prompt.Focus(); - + Config.CommonConfig.OnceHadRunDeviceIdList.Add(deviceId); _configService.Save(); } diff --git a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs index 1b6aed2c..312e80cb 100644 --- a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs @@ -29,7 +29,6 @@ using BetterGenshinImpact.ViewModel.Pages.View; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.Extensions.Logging; -using SharpCompress; using Wpf.Ui; using Wpf.Ui.Controls; using Wpf.Ui.Violeta.Controls; @@ -997,7 +996,14 @@ public partial class ScriptControlViewModel : ViewModel return; } - SelectedScriptGroup?.Projects.ToList().Where(item2 => item2.FolderName == item.FolderName).ForEach(OnDeleteScript); + var toBeDeletedProjects = SelectedScriptGroup?.Projects.ToList().Where(item2 => item2.FolderName == item.FolderName); + if (toBeDeletedProjects != null) + { + foreach (var project in toBeDeletedProjects) + { + OnDeleteScript(project); + } + } } [RelayCommand] diff --git a/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs index f91db6a4..2b4336f3 100644 --- a/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs @@ -32,6 +32,11 @@ using BetterGenshinImpact.ViewModel.Pages.View; using System.Linq; using System.Reflection; using Vanara.Extensions; +using System.Collections.Frozen; +using System.Globalization; +using Microsoft.Extensions.Localization; +using BetterGenshinImpact.View.Converters; +using BetterGenshinImpact.Core.Recognition.OCR; namespace BetterGenshinImpact.ViewModel.Pages; @@ -120,15 +125,27 @@ public partial class TaskSettingsPageViewModel : ViewModel private string _switchAutoFishingButtonText = "启动"; [ObservableProperty] - private Dictionary _fishingTimePolicyDict = Enum.GetValues(typeof(FishingTimePolicy)) + private FrozenDictionary _fishingTimePolicyDict = Enum.GetValues(typeof(FishingTimePolicy)) .Cast() - .ToDictionary( + .ToFrozenDictionary( e => (Enum)e, e => e.GetType() .GetField(e.ToString())? .GetCustomAttribute()? .Description ?? e.ToString()); - + + [ObservableProperty] + private FrozenDictionary _languageDict = new string[] { "zh-Hans", "zh-Hant", "en", "fr" } + .ToFrozenDictionary( + c => c, + c => + { + CultureInfo.CurrentUICulture = new CultureInfo(c); + var stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); + return stringLocalizer["简体中文"].ToString(); + } + ); + private bool saveScreenshotOnKeyTick; public bool SaveScreenshotOnKeyTick { @@ -417,4 +434,10 @@ public partial class TaskSettingsPageViewModel : ViewModel { _autoFightViewModel.OnOpenLocalScriptRepo(); } + + [RelayCommand] + private async Task OnGameLangSelectionChanged(KeyValuePair type) + { + await OcrFactory.ChangeCulture(type.Key); + } } \ No newline at end of file diff --git a/Test/BetterGenshinImpact.UnitTest/CoreTests/RecognitionTests/OCRTests/PaddleOcrServiceTests.cs b/Test/BetterGenshinImpact.UnitTest/CoreTests/RecognitionTests/OCRTests/PaddleOcrServiceTests.cs new file mode 100644 index 00000000..e68f0a97 --- /dev/null +++ b/Test/BetterGenshinImpact.UnitTest/CoreTests/RecognitionTests/OCRTests/PaddleOcrServiceTests.cs @@ -0,0 +1,67 @@ +using OpenCvSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BetterGenshinImpact.Core.Recognition.OCR; +using System.Drawing; +using OpenCvSharp.Extensions; +using System.Text.RegularExpressions; +using System.Collections.Concurrent; + +namespace BetterGenshinImpact.UnitTest.CoreTests.RecognitionTests.OCRTests +{ + public partial class PaddleOcrServiceTests + { + private static readonly ConcurrentDictionary paddleOcrServices = new ConcurrentDictionary(); + + [Theory] + [InlineData("zh-Hans", "挑战,达成", "[挑战,达成]")] + [InlineData("zh-Hans", "凯瑟琳")] + [InlineData("en", "Daily")] + [InlineData("en", "Katheryne")] + [InlineData("zh-Hant", "凱瑟琳")] + [InlineData("zh-Hant", "委託", "委[託,話]")] + [InlineData("zh-Hant", "挑戰,達成", "[挑戰,達成]")] + [InlineData("zh-Hant", "自動,退出", "[自動,退出]")] + [InlineData("zh-Hant", "跳過")] + [InlineData("fr", "quotidien")] + [InlineData("fr", "Expédition")] + [InlineData("fr", "Pêcher", "P[ê|é]cher")] + [InlineData("fr", "Synthèse", "Synth[è|é]se")] + [InlineData("fr", "Défi, terminé", "[Défi,terminé]")] + [InlineData("fr", "Sortie")] + [InlineData("fr", "Passer")] + /// + /// 测试识别各种文字,结果为成功 + /// + public void PaddleOcrService_VariousLangWords_ShouldEqualOrMatch(string cultureInfoName, string word, string? pattern = null) + { + // + using Bitmap bitmap = new Bitmap(word.Length * 50, 100); + + using Graphics g = Graphics.FromImage(bitmap); + g.Clear(Color.White); + using Font font = new Font("Arial", 12); + using Brush brush = new SolidBrush(Color.Black); + g.DrawString(word, font, brush, 0, 50); + using Mat mat4 = bitmap.ToMat(); + using Mat mat = mat4.CvtColor(ColorConversionCodes.RGBA2RGB); + + // + PaddleOcrService sut = paddleOcrServices.GetOrAdd(cultureInfoName, name => { lock (paddleOcrServices) { return new PaddleOcrService(name); } }); + string actual = sut.Ocr(mat).Replace(" ", ""); + + // + if (pattern == null) + { + Assert.Equal(word, actual); + } + else + { + Assert.Matches(pattern, actual); + } + } + } +} diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFightTests/DefaultAutoFightConfigTests.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFightTests/DefaultAutoFightConfigTests.cs new file mode 100644 index 00000000..b69f6626 --- /dev/null +++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFightTests/DefaultAutoFightConfigTests.cs @@ -0,0 +1,28 @@ +using BetterGenshinImpact.GameTask.AutoFight.Config; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFightTests +{ + public partial class DefaultAutoFightConfigTests + { + /// + /// 测试默认战斗配置初始化,获取所有别名,结果应成功 + /// + [Fact] + public void DefaultAutoFightConfig_Init_AllAliasShouldSuccess() + { + // + // Do nothing + + // + var sut = DefaultAutoFightConfig.CombatAvatarAliasToNameMap; + + // + Assert.All(sut.Keys, alias => DefaultAutoFightConfig.AvatarAliasToStandardName(alias)); // 顺便测试一下查询别名方法的速度 + } + } +} diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.CheckRaiseHook.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.CheckRaiseHook.cs index 63120538..a23f9e5f 100644 --- a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.CheckRaiseHook.cs +++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.CheckRaiseHook.cs @@ -45,7 +45,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests var sut = FluentBuilder.Create() .MySimpleParallel("下杆中", SimpleParallelPolicy.OnlyOneMustSucceed) .PushLeaf(() => new CheckThrowRod("检查抛竿结果", blackboard, logger, false, timeProvider)) // todo 后面串联一个召回率高的下杆中检测方法 - .PushLeaf(() => new FishBite("自动提竿", blackboard, logger, false, input, drawContent)) + .PushLeaf(() => new FishBite("自动提竿", blackboard, logger, false, input, ocrService, drawContent)) .PushLeaf(() => new FishBiteTimeout("下杆超时检查", 15, logger, false, input, timeProvider)) .End() .Build(); diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.FishBite.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.FishBite.cs index 64fe24ec..d6296348 100644 --- a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.FishBite.cs +++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.FishBite.cs @@ -29,7 +29,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests Blackboard blackboard = new Blackboard(autoFishingAssets: autoFishingAssets); // - FishBite sut = new FishBite("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), drawContent: new FakeDrawContent()); + FishBite sut = new FishBite("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), ocrService, drawContent: new FakeDrawContent()); BehaviourStatus actual = sut.Tick(imageRegion); // @@ -60,7 +60,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests var sut = FluentBuilder.Create() .MySimpleParallel("-", SimpleParallelPolicy.OnlyOneMustSucceed) //.PushLeaf(() => new CheckThrowRod("-", logger, false, fakeTimeProvider)) // todo - .PushLeaf(() => new FishBite("-", blackboard, logger, false, input, drawContent: new FakeDrawContent())) + .PushLeaf(() => new FishBite("-", blackboard, logger, false, input, ocrService, drawContent: new FakeDrawContent())) .PushLeaf(() => fishBiteTimeoutBehaviour) .End() .Build(); @@ -92,5 +92,28 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests Assert.Equal(BehaviourStatus.Succeeded, actual); Assert.True(fishBiteTimeoutBehaviour.leftButtonClicked); } + + [Theory] + [InlineData(@"202503230049406101_en.png", "en")] // 一张移除了右下角按钮的咬钩截图 + /// + /// 测试外语鱼咬钩,结果为成功 + /// + public void FishBite_English_ShouldSuccess(string screenshot1080p, string cultureName) + { + // + Mat mat = new Mat(@$"..\..\..\Assets\AutoFishing\{screenshot1080p}"); + var imageRegion = new GameCaptureRegion(mat, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d), drawContent: new FakeDrawContent()); + + FakeSystemInfo systemInfo = new FakeSystemInfo(new Vanara.PInvoke.RECT(0, 0, mat.Width, mat.Height), 1); + AutoFishingAssets autoFishingAssets = new AutoFishingAssets(systemInfo); + Blackboard blackboard = new Blackboard(autoFishingAssets: autoFishingAssets); + + // + FishBite sut = new FishBite("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), ocrService, drawContent: new FakeDrawContent(), new System.Globalization.CultureInfo(cultureName), this.autoFishingImageRecognitionStringLocalizer); + BehaviourStatus actual = sut.Tick(imageRegion); + + // + Assert.Equal(BehaviourStatus.Succeeded, actual); + } } } diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.cs new file mode 100644 index 00000000..b57989e0 --- /dev/null +++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.cs @@ -0,0 +1,29 @@ +using BetterGenshinImpact.Core.Recognition.OCR; +using BetterGenshinImpact.GameTask.AutoFishing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests +{ + public partial class BehavioursTests + { + private readonly IStringLocalizer? autoFishingImageRecognitionStringLocalizer; +#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑添加 "required" 修饰符或声明为可为 null。 + private static IOcrService ocrService; +#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑添加 "required" 修饰符或声明为可为 null。 + public BehavioursTests() + { + ServiceCollection services = new ServiceCollection(); + services.AddLogging().AddLocalization(); + using ServiceProvider sp = services.BuildServiceProvider(); + this.autoFishingImageRecognitionStringLocalizer = sp.GetRequiredService>(); + + LazyInitializer.EnsureInitialized(ref ocrService, () => new PaddleOcrService()); + } + } +}