ScrapboxでAnkiの問題を作る手法検討
とりあえず作業場を作成。中身は後ほど書きます

Ankiの元になった
SuperMemoの作者は「文章を読みながら抜書きして行って最終的にクイズに変える」というやり方をしている

これをAnkiに放り込めばいい
まあそう単純にはいかないけど
2024-10-15 scrapbox上で
SRSを作る方針に変更している
apkgの構造を解析して、同じものを作るコードを書こうとするのが非常に煩雑
メディア埋め込みをうまく処理できない
AnkiにScrapboxのデータを入力するのではなく、scrapbox上でAnkiする
UIにもめどがついた
scrapboxの画面をそのまま問題解答画面にすればいい
わざわざ解説などをAnki向けに書き直さずに済むのが大きい
解答中は問題だけ表示し、解答後に周囲の文章も表示すれば、それがそのまま問題の解説になる
ネーミングセンスのなさ()
jsrにpublishする予定なので @takker/
がついている
ScrapXXX
は今後使わない予定です
cosenseに付随する名前にする
でもScrapAnkiもよさそうだなあ
学習側のplatform
Scrapboxで問題データを作り、Ankiにimportする
このページではこの方法を検討する
これはパス
理論上は可能
区切り文字は何でもいい
利点
UserScriptなしでAnkiデータを作れる
限界
凝ったことはしにくい
(UserScriptなしだと)HTMLで凝った問題を作りにくい
HTMLを書いたコードブロックと、圧縮してtableに入れ込んだものを同時に管理している

例
ankiPC-2022F-小テスト2 | <table><caption>セメント化学で使われる記法</caption><thead><tr><th>化合物名</th><th>化学式</th><th>略記法</th></tr></thead><tbody><tr><td>{{c1::Calcium Oxide}}</td><td>{{c1::\(\rm CaO\)}}</td><td>{{c2::\(\rm C\)}}</td></tr><tr><td>{{c1::Silicon Dioxide}}</td><td>{{c1::\(\rm SiO_2\)}}</td><td>{{c2::\(\rm S\)}}</td></tr><tr><td>{{c1::Aluminium(III) Oxide}}</td><td>{{c1::\(\rm {Al}_2O_3\)}}</td><td>{{c2::\(\rm A\)}}</td></tr><tr><td>{{c1::Iron(III) Oxide}}</td><td>{{c1::\(\rm {Fe}_2O_3\)}}</td><td>{{c2::\(\rm F\)}}</td></tr><tr><td>{{c1::Water}}</td><td>{{c1::\(\rm H_2O\)}}</td><td>{{c2::\(\rm H\)}}</td></tr></tbody></table> |
PC-2022F-小テスト2 | <table><caption>クリンカ鉱物の記法</caption><thead><tr><th>鉱物名</th><th>化学式</th><th>略記法</th></tr></thead><tbody><tr><td>{{c1::Alite}}</td><td>{{c1::\(\rm 3CaO\cdot SiO_2\)}}</td><td>{{c2::\(\rm C_3S\)}}</td></tr><tr><td>{{c1::Belite}}</td><td>{{c1::\(\rm 2CaO\cdot SiO_2\)}}</td><td>{{c2::\(\rm C_2S\)}}</td></tr><tr><td>{{c1::Aluminate}}</td><td>{{c1::\(\rm 3CaO\cdot{Al}_2O_3\)}}</td><td>{{c2::\(\rm C_3A\)}}</td></tr><tr><td>{{c1::Ferrite}}</td><td>{{c1::\(\rm 4CaO\cdot{Al}_2O_3\cdot{Fe}_2O_3\)}}</td><td>{{c2::\(\rm C_4AF\)}}</td></tr></tbody></table> |
1.html<table>
<caption>セメント化学で使われる記法</caption>
<thead>
<tr>
<th>化合物名</th>
<th>化学式</th>
<th>略記法</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{c1::Calcium Oxide}}</td>
<td>{{c1::\(\rm CaO\)}}</td>
<td>{{c2::\(\rm C\)}}</td>
</tr>
<tr>
<td>{{c1::Silicon Dioxide}}</td>
<td>{{c1::\(\rm SiO_2\)}}</td>
<td>{{c2::\(\rm S\)}}</td>
</tr>
<tr>
<td>{{c1::Aluminium(III) Oxide}}</td>
<td>{{c1::\(\rm {Al}_2O_3\)}}</td>
<td>{{c2::\(\rm A\)}}</td>
</tr>
<tr>
<td>{{c1::Iron(III) Oxide}}</td>
<td>{{c1::\(\rm {Fe}_2O_3\)}}</td>
<td>{{c2::\(\rm F\)}}</td>
</tr>
<tr>
<td>{{c1::Water}}</td>
<td>{{c1::\(\rm H_2O\)}}</td>
<td>{{c2::\(\rm H\)}}</td>
</tr>
</tbody>
</table>
2.html<table>
<caption>クリンカ鉱物の記法</caption>
<thead>
<tr>
<th>鉱物名</th>
<th>化学式</th>
<th>略記法</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{c1::Alite}}</td>
<td>{{c1::\(\rm 3CaO\cdot SiO_2\)}}</td>
<td>{{c2::\(\rm C_3S\)}}</td>
</tr>
<tr>
<td>{{c1::Belite}}</td>
<td>{{c1::\(\rm 2CaO\cdot SiO_2\)}}</td>
<td>{{c2::\(\rm C_2S\)}}</td>
</tr>
<tr>
<td>{{c1::Aluminate}}</td>
<td>{{c1::\(\rm 3CaO\cdot{Al}_2O_3\)}}</td>
<td>{{c2::\(\rm C_3A\)}}</td>
</tr>
<tr>
<td>{{c1::Ferrite}}</td>
<td>{{c1::\(\rm 4CaO\cdot{Al}_2O_3\cdot{Fe}_2O_3\)}}</td>
<td>{{c2::\(\rm C_4AF\)}}</td>
</tr>
</tbody>
</table>
非常に管理がめんどくさい
HTMLを圧縮するのがめんどくさい
script使えば楽にはなるが……
手動で同期させるのがめんどくさい
タグ付けが面倒
問題の同一性を担保しにくい
何らかのIDを問題ごとに割り振るのが現実的だが、そのIDを作るのが面倒
インポート方法がややこしい
deck, card type, 列と対応させるfield、上書き設定などをすべてインポートするユーザが設定しなければならない
問題作成者側で設定できない
学習記録を含めて記録できるAnkiのデータ形式
学習記録を削ったものが
共有デッキとして公開されている
利点
deckやcard typeの設定まで含めてexportできる
限界
apkg形式にデータを変換するprogramが存在しない
技術的には可能なので作りたい
sql.jsを使えばscrapboxのUserScript上でsqlite DBを操作できる すでに動作確認済み
javascript port anki
で検索して見つけた

の調査不足だった……
ま、まあ、実装前に発見できたからいいか
実装は、

が考えたのとほぼ同じ
dbを調査する手間が省けた
server向けに設定されていて使いづらそうなので、refactoringする
明日書き換える
データ作成方針
UserScript無し(現行)
上述した限界があるのでやめたい
UserScript併用
Scrapbox projectをまるごとexportして、そのまま一つのapkgファイルに変換する、なんて使い方ができる
変換処理をbookmarkletにしておけば、ボタンひとつでいつでも最新の問題データを取得できて便利
RSS pluginの仕組みを組み合わせれば、自動更新も可能かもしれない
ほしいもの
簡単に問題をCRUDする
Dはいらんかも
CとUが楽にできればいい
HTMLは書きたくない
やること
どの方法を使うにしても決める必要のあること
scrapbox上でのAnkiデータの表現方法
どの塊を一つの問題とみなす?
card typeは単一にする?カスタムできるようにする?
取り組む問題を絞り込むため、最初はcloze問題に固定することにする

問題の同一性を担保する方法
scriptで適当なIDを振るのが現実的
IDの
桁数
見やすくしたいので、短いIDにしたい
/[0-9a-zA-Z]/
を使えば、14桁くらいでも衝突しないか?
Math.random()
でIDを作っているだけ
/[0-9a-zA-Z]{14}/
で1回/秒 生成すると、生成開始から16000年目以降に1%の確率で1回衝突が起きる
これだけ確率が低ければ、衝突しないと考えていいだろう
生成に利用する情報
完全ランダムでもあまり衝突しなさそう
↑より衝突確率は無視できるほど小さいので、このままで行く
行IDは使わない
編集で容易に書き換わってしまうから
どの時点で振る?
apkgへexportするとき
idのない問題に新しいidを降り、websocket経由で書き込む
ユーザー側からみると楽だが、書き込み位置の調整などをまじめに組もうとするとかなり面倒
idのない問題を無視し、IDを振るようユーザーに警告を出す
ユーザーは別途IDを作るUserScriptを使って、手作業で振っていく
問題データに必要な情報
穴埋め箇所が指定された文章
例: {{c1::Aluminate}}は,水和熱が{{c2::大::大/中/小}}、短期強度への貢献は{{c2::大::大/中/小}}、長期強度への貢献は{{c2::小::大/中/小}}である
穴埋め問題の作成支援scriptはもう作ってある

タグ
カスタム学習しやすくするために作る
どういうルールでタグ付けするかが難しい
ID
問題データ更新用
同じIDの問題を上書きさせる
この3つで十分そうだな

問題数とページ数の関係
1ページ1問題
利点
問題の範囲が明確
1ページ全てを一つの問題として変換すればいい
限界
ページが細かくなって使いづらくなりそう

1ページn問題
これが妥当そう
問題の境界を何で分けるか
先行研究では、どれも特定の文字列で分割している
まあこの方法で分ければいいだろう
nページ1問題
これは問題を大きく作りすぎ
別のページのデータを参照して問題を作る場合がある?
そのうちやる
cad typeを記述するページを作る
表、裏、CSSをそれぞれ指定した名前のコードブロックに書き込んでおく
問題を記述した箇所に、特定の書式でそのページへの
リンクを貼ると、そのcard typeを適用するよう設定する
アイコン記法で書けばいいだろう

これ以上は、目に見えるものを作りながら考えたほうがいいな
とりあえずなんかscript組むか。
問題の作り方