PRODUCT NOTE / PRD
場面(シーン)で、話せるように。
この文書は「何ができるか」ではなく、中止したプロダクトを、どこをどう変えて作り直したかを記録した開発ノートです。
| ステータス | App Store で配信中(2026-09-09 配信開始・無料・アカウント登録なし・日本のストアのみ)/ Android β は nzw.jp から直配布 |
|---|---|
| 現行バージョン | v1.3.0(Android β build 51 を nzw.jp から直配布 / ブラウザ版あり / iOS 1.3.0 build 51 は App Store への提出前。配信中は 1.1.1 build 47) |
| プラットフォーム | iOS / Android / ブラウザ版(動作確認用。録音・聞き取りは端末アプリのみ) |
| 対象ユーザー | 読み書きはできるが、その場になると英語が組み立てられない日本語話者 |
| 出自 | Grizzlingo(v0.5 で開発中止)の後継。同じリポジトリを土台に作り直した |
| 最終更新 | 2026-10-14 |
| 関連リンク | プロダクトページ ・ ブラウザで試す ・ Grizzlingo(中止の記録) ・ Engly ・ プロダクトの系譜 ・ 開発ノート一覧 |
Bearise は、場面(シーン)を単位に「その場面を英語で切り抜ける」を積み上げる英語学習アプリです。状況画像・前提・一人称ロールを提示し、理解 → 認識 → 産出 → 発話 → 定着の 5 段階を順に踏ませます。
教材は事前に作って端末に持つため、通信なしで練習できます。
前身 Grizzlingo は「興味テキストから AI が都度生成する」設計で、v0.5 で開発を中止しました。Bearise はその2 つの死因を、機能追加ではなく構造の置き換えで潰すことだけを目的に作り直したものです。
ターゲットの症状はひとつに定義している。
言いたいことが、その場で英語で組み立てられない。
原因は 2 つあり、どちらも同じ症状として現れる。材料がない(会話の型・語彙・その場の文法が出てこない=スキル)と、怖くて出せない(完璧主義・恥=心理)。
この 2 つを別々に解こうとすると機能が膨らむため、「組み立てられない」という症状を直接解くことに一本化している。
Grizzlingo の中止理由は「作れなかった」ではなく「作れても学習方法として成立しにくい」だった(詳細は Grizzlingo の開発ノート)。Bearise はこの 2 点にだけ答えている。
いきなり「話してみましょう」とは言わない。低リスクな認識課題から始めて、産出・発話まで運ぶ。
| ① 理解 | 状況画像+前提条件+一人称ロール(「あなたは搭乗客」)を提示。母語補助で意味とゴールを掴む |
|---|---|
| ② 認識 | 正しい英文を選ぶ/並べ替える。まだ自分で作らなくていい(足場) |
| ③ 産出 | キーワードだけを手がかりに、自分で英文を組み立てる |
| ④ 発話 | シャドーイング+音声認識で、実際に言えたかを判定する |
| ⑤ 定着 | 結果を SRS に登録。克服デルタ(前回 ✗ → 今回 ○ の数)を可視化する |
「シンプルに・細かく・深く」の両立は漸進的開示で解く。1 周目は対象英文が言えればクリア。周回するごとに文法ポイント・語彙・言い換えを開いていく。1 シーンで全部を出さない。
| やる | 場面単位のカリキュラム、5 段階ループ、地図状の進行、事前生成音声によるオフライン練習、文法スライドとパターン別ドリル、SRS と当日復習レーン |
|---|---|
| やらない | TOEIC 等の網羅的な試験対策(本モードは「場面で使う文法」に限定)、教師添削、学習者コミュニティ、英語以外の言語(LangBridge が担当) |
| 保留 | シーン内の完全自由 AI 会話。構造化シーンを「入口」、自由会話を「卒業後の応用」として棲み分ける案が有力だが未決 |
2026-08-16 時点。実機(iPhone シミュレータ)を通して撮ったもので、 下の意思決定ログがどう形になっているかの現物。
ホームで塗りつぶしの主役を「今日の 1 場面」だけにした。12 問・約 5 分の「今日の練習」は、その下の「もっとやるなら」に置いた。初めて開いた日は、3 セリフ・約 1 分の「はじめの一言」だけを出す。通知とホーム画面のウィジェットも、同じ関数が選んだ同じ 1 場面を指す。
きっかけは、作っている本人が「教科書もアプリもあるのに、起動する気にならない」と言ったことだった。開いた画面に始める手段が 3 つ並ぶと、始める前に選ぶ手間が要る。重い日はそこで止まる。始めるまでの負担を、1 分で終わる物 1 つまで下げれば開く、という仮説を立てた。
画面の構成は変えたが、効いたかはまだ分からない。匿名計測(下の決定)を既定オフで出すので、再訪も通知経由の起動も数えていない。数字が取れるのは次の版からだ。
起動した日・練習を終えたこと・通知やウィジェット経由の起動だけを、匿名の ID で送る仕組みを入れた。場面の ID・解答・端末固有の ID は許可リストで落とす。ただしビルドフラグ USAGE_DEFAULT_ON を付けたビルドだけを既定オンにする。この版は付けていない。
プライバシーポリシーには「解析ツールは使用していません」「収集の範囲を広げるときはアプリ内でお知らせします」と書いてある。ポリシーと App Store の申告を直す前に既定オンで配ると、書いていない通信になる。付け忘れても壊れず、集計が空になるだけだ。安全側に倒した。
計測を始めたことを知らせる一度きりのカードと、お知らせより先に送らない印も入れた。サーバー側の許可リストへの追加とポリシーの更新は、別の PR に分けてある。
下タブの並びは、ホーム・教科書・ドリル・シーン・分析の勉強の順のままにした。
戦略では、体系的な文法の積み上げを越えてはいけない線にしている。教科書を読む物から、詰まったときに引く物へ下げるつもりで、タブをホーム・シーン・ドリル・教科書・分析に並べ替え、ホームの案内も同じ順にした。本人から「元の並びにしてほしい」と言われ、半日で戻した。
並びを替えるのは簡単だったが、案内の文言・テスト・見取り図まで同じ順で持っているので、戻す作業も同じ数の場所に及んだ。教科書の位置づけは、タブの並びでは表さない。ホームで押す物(今日の 1 場面)で表す。
v1.1.1 で入れた「話しかけの声を持たない発話には、日本語の課題文を読み上げる」をやめた。シーン練習で声が出るのは、相手と声を交わした英語の話しかけだけにする。
ヒント・相手のセリフ・教科書プレビューの下から出るシートは、固定の高さをやめて中身の量に応じて伸び縮みさせ、長押しで裏の場面の絵を覗けるようにした。
日本語の読み上げは端末のデフォルトシステム音声(flutter_tts)で鳴る一方、英語の話しかけは AI 音声(Gemini Kore)で鳴っている。同じ場面の中で声色が入れ替わるのが気持ち悪いという指摘があった。声を消して無音にする案もあったが、無音より「別人の機械声」のほうが場面への浸り方を壊すと判断した。
シートは中身が長い設問だと画面の 7〜8 割を固定で覆い、下の場面の絵が見えず、どの場面を練習しているか分からなくなるという指摘があった。
シーン練習の _introLine から日本語課題文の自動再生を外し、heard を持つ発話の英語だけが AI 音声で鳴るようにした。
シートは Column(mainAxisSize: min) で中身の量に合わせて高さが決まるようにし、外側を長押しすると場面の絵がうっすら見える操作を足した(フッターは長押し中も消さない)。
作業の途中で 2 つ壊れ方を見つけて直した。長押しの検出がジェスチャーのアリーナに参加しておらず、単語チップを覗くつもりで長押しすると、離した瞬間にそのチップも誤タップされるバグがあった(ウィジェットテストで再現・回帰テストを追加)。フッターと本文の境目に線を足した際も、最初の実装(DecoratedBox の上に Material を重ねる形)は描画順のせいで線が完全に隠れて見えなかった。Material.shape に線を持たせる形に置き換えて解決した。
場面の背景でクマが口を動かすなら、必ず声を付ける。相手の話しかけが無い問題では日本語の課題文を読み上げ、読み終わったらクマを止める。
逆に、話し相手のいない文法ドリルでは相づちを一切返さない(中立の相づちを「表が無いときの受け皿」にするのをやめた)。
数えると、場面の 149 発話のうち話しかけの声を持つのは 56 だけで、残る 93 発話は無音のまま口だけ動いていた。
動画は読み上げと無関係に 1 回流すだけなので、声が 2 秒で終わっても口は 5 秒動き続けた。
ドリル側は逆の壊れ方で、正解して「次へ」を押すたびに 「No problem.(大丈夫ですよ)」「Okay.」が鳴り、正解したのに慰められているように聞こえた。
どちらも「相手が話している」という見た目と、実際に起きていることが食い違っている。
手ごたえは正解した瞬間のフラッシュと触覚がすでに返しているので、ドリルで足りないのは声ではなく、何をする画面なのかの一言だと見た(ブリーフィングが無く、日本文と空の枠だけが出ていた)。
話しかけの声を持たない 93 発話に、課題文の読み上げを付けた。空港の場面では、10 秒の動画に対して課題文の読み上げが 4.5 秒で、そこで止まる。
ドリルの相づちは 0 本になり、空の枠に「日本語に合うように、下の語を押して並べよう」を出した(高さは足さず、1 語置くと消える)。
同じ版で、ホームの週の記録で「今日やり終えたマス」を浮かせた。クリアしても隣の日と同じ色に茶の枠が付くだけで、手ごたえが無いと言われたため。
最初は白へ寄せたグラデーションにしたが、色あせて逆に沈んだ。過去の日を淡色にして今日だけ目立たせる案も、暗いテーマで濁り「OK の日」と「やらなかった日」が紛れるので捨てた。
色相は変えず、上を明るく鮮やかにして光とチェックを足す形に落ち着いた。
配信開始日を 2026-09-09 に置き、価格は無料・アカウント登録なしで出す。解放の鍵(unlock())はローカルの旗を立てるだけの状態のまま据え置き、課金の接続は次の版へ回した。
Android は今までどおり nzw.jp からの APK 直配布を続け、Google Play には出さない。
直配布の β はURL を知っている人にしか届かない。8/23 に配り始めてから機能はいくつも足したが、足したところで届く先は増えない。
判断材料が欲しいのに、材料の出どころが増えない状態だった。
もう 1 つは順序の問題で、Grizzlingo は「完成と課金を揃えてから出す」側の順序を踏んで止めている。
同じ順序をもう一度やらないために、課金の設計より先に「人が触る」を取った。誰でも解放を押せる状態のまま出すことになるが、そこで失うのはまだ取れていない売上だけだと見た。
出す形は決まった。
無料・アカウント登録なし・収集なしで、App Store のプライバシー欄は「データを収集しない」を選べる(アナリティクスは DebugAnalytics のままで送信先が無く、学習記録は SharedPreferences =端末内のみ、Firebase も入っていない)。
中身は 27 場面・50 レッスン・4択 675 問・例文 1,088・音声 1,384 文。出したあとに何が起きたかは 9/9 以降にここへ足す。
解放の対象を「トーク(自分の話をする)」1 つから、旅の後半 4 つ+教科書 5〜8 章+ドリル 5〜8 章へ広げた。そのうえで鍵は 1 つだけにして、どれか 1 つを解放すると全部開くようにした。
境目は定数 1 行ずつ(kFirstLockedJourney / kFirstLockedChapter)で、旅の並びを入れ替えれば境目もついてくる。
もとの線引きは「AI 判定が要るから有料」という原価の理屈だった。作る側には筋が通っているが、買う側からは「なぜトークだけ?」としか見えない。
範囲を広げるとき、素直にやるなら「場面の鍵」「教科書の鍵」と分けたくなるが、組み合わせの数だけ状態が増え、買った人が自分の権利を言えなくなる。
取りうる収益より、説明できることを取った。
もう 1 つ、入口が 5 つある(章の行・「次に読む」・教科書のマス目・ドリルのマス目・定番チップ)ことが分かっていた。
片方だけ塞いだ入口が 1 つでも残れば鍵は無いのと同じなので、判定を 1 ファイルに寄せて、素通りできないことをテストで見張る形にした。
無料は手前の 3 つの旅と 1〜4 章。解放はいまのところ無料で押せる(unlock() がローカルの旗を立てるだけ)。
課金を繋ぐときはこのメソッドの中で購入成立を待つだけで済み、呼び出し側は触らない。このまま出すと誰でも開けることは承知のうえで、課金の設計を後回しにする代わりに導線だけ先に置いた。
分析タブに折れ線「進み具合の推移」を足した。数えるのはその日までに一度でも答えた文の累計で、既存の棒グラフ(その日の練習回数)とは別の軸にしてある。
縦軸は 0 から描かず、動いた範囲に合わせて引き伸ばす。
棒グラフは休むと 0 に落ちるので、続けているかは読めても、積み上がったかは読めない。かといって「いま言える文」を線にすると、忘却で上下してやったのに下がる日が出る。
折れ線に載せたいのは戻らない量なので、到達済みの集合の大きさを積むことにした。
縦軸を 0〜100% にしなかったのは、教材が 1,100 本あって数十本の進みが平らな線にしか見えないから。
数字は見出しが出すので、線は傾きが読めればいい。
右上がりが止まっていれば「進んでいない」と一目で分かる形になった。ただし履歴は直近 2,000 件で打ち切られるので、長く使った人ほど左端が実際より低く出る。
傾きは正しいが絶対値は下振れしうる、という性質を抱えたまま出している。
alloy から marin へ変え、1,384 本すべてを作り直した。選ぶ画面を AI ワークスペースの中に作り(声くらべ)、13 声を同じ 3 文・同じ条件で鳴らして並べた。アプリは文ごとに「2.7 ÷ 素材の音節毎秒」を倍率にして速さを揃えている。つまり素材がばらつくほど強い倍率がかかり、短い弱母音が崩れる——「冠詞の a がエーに聞こえる」はこれが原因だった。
だから選ぶ基準は声の速さではなくばらつきの小ささになる。実測すると alloy は 3 文の幅が ±0.48 とばらつく側で、marin は ±0.16、中央 2.69 も基準 2.7 にほぼ乗っていた。
やり直しの効かない選択(声を変えると全文作り直し)なのに、それまで決め手が「なんとなく」だったので、聴いて数字で決める場所を先に作った。
切れ疑い(5.0 音節/秒 以上)が 6 → 0、上位 5% が 3.77 → 3.45 に締まった。
ただし 3 文の見本では見えないことがあった:marin は短い相づちを引き伸ばして読む体質で、Sure. は 1 音節に 2.30 秒かかっていた。
3 音節以下の 71 本は中央 2.08 音節/秒(全体は 2.62)。見本で選び、全文で検算する——この 2 段構えが要るという学び。
倍率の上限は 2.8(これ以上は音が壊れる)なので、素材が 1.93 音節/秒 より遅いと 2 倍速にしても狙いに届かない。
marin では最初 125 本(9.0%)がこれに当たった。引き直せば直る個体があるので回したが、巡ごとの改善が 67 → 16 → 11 → 8 と落ちた。
残りは全部 Nice. のような短い相づちで、個体差ではなく声の体質だった。
上げ切りが 125 → 23 本(1.7%)。alloy のときも 18 本あったので、ほぼ同等まで戻した。
上げ切れない文は遅く鳴るだけで壊れはしないので、これ以上は追わないと決めた。
ついでに見つかった 2 つのずれも直している:レビュー画面が 1.0/1.4/1.8 というもう存在しない段で鳴らしていた(=実機と違う速さで OK/NG を付けていた)のと、ダンプ用スクリプトに制御文字が生で埋まっていてgrep から一切見えなくなっていた件。
事前生成の読み上げを gemini-2.5-flash-preview-tts から gpt-4o-mini-tts に移し、引き直し対象の 847 本ではなく 1,384 本すべてを作り直した。
声が変わるので、1 つの教材の中で話者が混ざるほうが悪いと判断した。
Gemini 側は preview モデルで、無料枠が1 日 100 リクエスト(プロジェクト単位)。847 本に 9 日かかる見積もりだった。
それだけなら待てばよいが、2026-08-24〜08-28 に同じ引き直しを「完了」させたのに直っていなかった実績がある。
9 日待ってまた直っていない可能性を許容できなかった。OpenAI は Tier 1 で 500 RPM。
実測で 1,384 本が 4 分 36 秒、費用は数ドル。
ぶつ切り率 34.4% → 0.7%(457 本 → 10 本)。切れ疑い 25 → 6、遅すぎ 27 → 6、音声の欠品 3 → 0。
21.84 秒の別音声が鳴っていた "Here it is." は 1.94 秒に。移す前に気づいたこと:OpenAI 版のスクリプトにも "enunciating each word" が書いてあった。
Gemini でぶつ切りを生んだ当の文言で、直した学習が別プロバイダ側に移っていなかった。実測では OpenAI で再現しなかったが、同じ地雷を残す理由がないので外した。
speed で作るのをやめ、1 本ずつ測って目標から外れたものだけ、その文用の速度で作り直すようにした。まず速さは指示文では動かないと分かった(4 文で実測:そのまま 4.95・「ゆっくり」と指示 5.00・speed=0.75 3.62・speed=0.60 2.62 音節/秒)。
ならばと speed=0.6 で全文を作ったが、短い文が間延びして「遅すぎ」が 27 → 137 本に増えた。一律の速度は、文の長さで結果がばらける。
揃えたいのは入力ではなく出来上がりの音節/秒なのだから、測って当て直すのが素直だった。
外れた 258 本を文ごとの速度で作り直し、目標 2.7 の ±25% に収まる割合が 65.9%(Gemini)→ 70.7%(一律 0.6)→ 83.3%(文ごと)。
遅すぎは 137 → 9 本。作り直しが 1 本 0.2 秒で終わるので、測る → 外れを撃ち直す、を 2 周回すのが一番安上がりだった(ぶつ切りも 52 → 18 → 10 本に落ちた)。
事前生成した読み上げ音声の作り直し対象を、波形から「ぶつ切り」を検出して選ぶ方式から、生成日で丸ごと選ぶ方式に変えた。
2026-08-02〜08-20 に作った 806 本を、聴かずに全部対象にした(431 本 → 806 本)。
きっかけは「全体的に音声が滑らかじゃない」という申告。人が付けた OK/NG 361 件を生成日で割ると、壊れているのは 2026-08-02〜08-20 に作ったものだけだった(NG 率 77〜100%。その前後は 10〜30%)。
この窓は合成プロンプトが "enunciating each word"(1 語ずつはっきり読ませる)だった期間で、サーバー上のスクリプトの更新日 2026-08-23 と一致する。
プロンプトは 2 週間前に直っていて、音を作り直していなかっただけだった。決め手は検出もれの数字で、古いプロンプト期のうち波形では拾えなかった 71 件の NG 率が 57.7%(フラグ無しの基準値は 10.0%)。
波形は半分しか当てられないが、生成日は外さない。
対象は教材 1,384 本の 58%。1 日 100 本の上限で約 9 日で一巡する。
副産物として「a を『エー』と読む」という申告 2 件がどちらも 08-19 生成だと確認でき、プロンプト修正時に書いた「単独で浮いた冠詞が文字読みに転ぶ」という読みが実測で裏付けられた。
かけ直した検出では、新プロンプトで作った 55 本から 1 本も出ていない。
短文を外していたのは「1 回の間でも割合が跳ねて、破裂音の閉鎖と区別が付かない」から。人が付けた 185 件と突き合わせたら、跳ねるのは割合であって回数は跳ねないと分かった。
2〜3 語の文は、間 1 回なら NG 率 16.7%(フラグ無しの 15.2% と同じ=当てずっぽう)、間 2 回なら 100%(10/10)。
一度は下限を 2 語に下げただけで通そうとして失敗している(適合率が 95.5% → 85.4% に落ちた)。人の判定と突き合わせるまで、下げ方が粗いことに気づけなかった。
適合率 96.1% / 再現率 85.1%(もとのルールは 95.5% / 73.6%)。精度を落とさずに取りこぼしを 11.5 ポイント減らした。
取り残していた "He ran." "You are kind." "It is perfect." が拾えるようになった。
レビュー画面の NG 理由を「音声」1 個から 4 個(ぶつ切り/遅い/速い/音が変)に割ったとき、受け取る側の振り分け表も同時に直すことにした。
過去の判定を読むために旧キー audio は残し、両方のコメントに「キーは画面の定義と揃える」と明記した。
画面だけ新しくなり、振り分け側が audio しか知らない状態で判定が 188 件たまっていた。このまま流すと音声の NG が丸ごと「文面の直し」に振り分けられ、1 本も引き直されない。
この壊れ方はエラーにも件数にも出ない(振り分け先が変わるだけで、合計は合う)。気づけたのは、書き出しに見慣れないキー(noise / cut)が混ざっていたのを見て画面を確かめに行ったからで、数字を見ていたら見逃していた。
同じ時に、リポジトリ側の画面ファイルが公開中より古い(32KB / 40KB)ことも見つかった。そのままデプロイすれば新しい画面を上書きして消していた。
「正はリポジトリ側」と決めていても、直接いじられた分は戻ってこない。デプロイ前に公開中と突き合わせる手順を挟むことにした。
「問題の画面が下に寄りすぎている」という申告に対し、下寄せそのものは残した。中身を画面の下端まで伸ばすのをやめ、フッターとの間に息をつくぶんの余白(画面の高さの 12%・最大 64pt)を空ける形にした。
あわせて語ボタンの列を 32% → 28%、4択を 60% → 45% に抑えた。
下寄せには理由がある。中身を画面の真ん中に置くと、背景の絵の相手の顔をちょうど隠す。
中央寄せに戻すと以前の問題が再発する。実際に詰まっていたのは位置ではなく間隔で、本文とフッターの隙間は 24pt しかなく、語ボタンの列と地続きに見えて「どこまでが問題か」が読み取れない状態だった。
「教科書で読む」の行き先を、構文の名前から引く表(1件 → 14件)と5文型の「かたち」の1枚で埋めた。そのうえでどれも引けない文には、どんな文にも当てはまる1枚(S と V の見つけ方)を最後の行き先として用意した。
「行き先の無いボタンは置かない」というそれまでの方針を、ここだけ曲げている。
ボタンは v0.12.0 で入れてあったのに「無い」と言われた。調べると、行き先の表は 1 件しか無く、大半は5文型レッスンを「前回読みかけの位置」から開くだけで、押すと解いた文と無関係なページが出ていた。
さらに型が引けない文ではボタンごと消えていた。出ないボタンは「この問題には解説が無い」と読まれるので、消えるより粗くても出るほうがましだと判断した。
場面の全発話・教科書の全例文で行き先が引ける。ただし最後の受け皿が増えると黙って粗くなるので、そこへ落ちる割合が 5% を超えたら失敗するテストを同時に置いた(現状 1% 弱)。
ボタン自体も解説タブの外へ出した——タブは中身が無いと丸ごと消えるので、導線まで道連れになっていた。
解説を書き足す前に、すでに作ってあるのに解いた瞬間に消えていたものを戻した。ヒント(型・つまずきポイント・日本語・キーワード)はふり返りに入口が無く、`_revealed` も次の問題で消えていた。
4択の誤答の理由は、解答中に一瞬出るだけだった。
「解いたあとの解説に役割やヒントも」と言われて調べたところ、文の型が出ていたのは 1,097 件中 705 件(64%)だった。
ふり返りが手書きの `Question.pattern`(125問中12問しか無い)だけを見ていて、同じ画面のヒント側は機械推論できていたのに渡していなかった。
「教科書へ誘導する」の土台がそこで塞がっていた。
5文型に収まらない文(疑問文・命令文・Here is 〜)は語順の骨組みを見出しにして 99.9% に。役割タグ自体も、疑問文と倒置を読めるようにして 77% → 94.8%。
途中で There is 〜 の主語の読み方が教科書と逆だったことも見つかった。
深い解説(倒置とエンド・フォーカス)は構文ごとに1枚書き、`explainWordOrder` が付ける構文名から教科書のページへ写す表を1つ置いた。
あわせて「後で読む」を足し、練習を中断せずに解説を積めるようにした。
`Here is my passport.` の解説を1本もらったが、これを1,179件ぶん書くのは現実的でない。
`explainWordOrder` はすでに `Here is 〜` を倒置として見分けていたので、名前を付けて行き先を表にすれば、その構文を使う文はすべて同じ1枚につながる。
教科書へ飛ぶと練習が切れるので、積んでおける口を別に用意した。
「英文の解説が足りない」を新しく書いて埋めるのをやめ、すでにある 4 択 665 問を配り直すことにした。つまずき集の 1 件を押すと解説が開き、そこから該当スライドへ直接飛べる。
あわせて理解度テストを足したが、4 択は「いま言える文 n / N」の分母には入れない——あれは口から出る文の数で、読んで選ぶ設問ではない。
作者本人から「蓄積した問題を解説と共に確認したい」と言われて数えたところ、手書きの解説は教科書の例文 1,054 本に 0 件、場面の発話 125 本に 1 件しか無かった。
一方で 4 択の選択肢 2,660 個には誤答も含めて全部に理由が書いてあった。書く材料が無いのではなく、いちばん厚い在庫がレッスンのスライドを開いた人にしか届いていなかった。
つまずき集の実装には「押して解説へ戻れるように添える」というコメントだけが先に書かれ、押す先が用意されていなかった。
解説の到達経路が 1 本から 3 本(つまずき集・理解度テスト・レッスン)に増えた。語順の説明は `explainWordOrder` が任意の英文に効くので、コンテンツを 1 文字も書き足さずに全出題へ付いた。
例文からスライドの逆引きは実データ 1,054 本すべてで通ることをテストで固定した。
理解度テストはやったことのある物だけから 10 問出し、期限(次に出る日)を見ない。「今日の練習」は期限が来た物しか出さないので、両者は同じ教材を使っても役割が重ならない。
テストは採点するが、ベストも勲章も出さない。
「過去に解いた問題からランダムに出す」はすでに「今日の練習」がやっていたので、そのまま作ると入口が 2 つに割れるだけだった。
測るために必要なのは無作為な標本で、期限切れだけを集めると「苦手ばかりのテスト」になって理解度にならない。ベストを出さないのは、理解度がいまの値であって過去最高ではないから——忘れた日に自分の最高記録を突きつけることになる。
採点そのものは、strategy の「採点をデフォルトにしない」に対して自分で押したときだけという形で折り合いを付けた。
実機で通したところ、出題が前に通した物ばかりなので10 問すべてに「クリア済み・とばす」が付いていた。
測っている最中に「やらなくていい」を勧めることになるので、点の付く回では出さないようにした(レッスンの問題でも同じ理屈で、とばすと本人が思うより点が下がっていた)。
文と言い回しの 1 つずつに記憶の状態(段・最後に出した日・忘れた回数)を持たせ、期限が来たら出し直すようにした。数字の主役を「連続日数・練習回数」から 「いま自力で言える文 n / N」へ差し替えた。
あわせて、場面を一本道で順に解放し、教科書は「次に読む」1 冊+畳んだ 8 章にした。
作者自身が「このアプリで英語が覚えられる気がしない」と言い出したのがきっかけ。本人の見立ては「グラフが足りない」「単語帳が無い」だったが、コードを読むとどちらも外れだった。
グラフは既にあり、語彙データも 82 語あって表示もされていた。実際の穴は 3 つ。
① 出題スコアに時間の項が無く、great を取った文は永久に最下位=二度と出てこない。② 保存していたのは自己ベストだけで、忘れても下がらないので覚えたかを確かめる手立てが無い。
③ 復習は場面にしか掛かっておらず、教科書 49 レッスン・例文 1,054 本・クイズ 665 問(分量の 9 割)は一度やったきりだった。
人は 1 回では覚えない。1 回で終わる設計なら、覚えられる気がしないのが正しい反応。ここで Duolingo 式のストリーク強化に逃げないのは、Grizzlingo の時点で「効力感で戻す設計にする」と決めているため。
作業中に、画面に出ている数字そのものが壊れていたことが分かった。
分析の「声の一致」は一致率を計算した直後に捨てていて常に「—」、「練習 N 回」は履歴が発話ごと 1 行なのを件数で数えていて 10 問のレッスン 1 回が「10 回」になっていた。
おすすめの「時間がかかった」も、渡す値を誰も測っていないので一度も発火していない。唯一の上達指標が死んだまま、努力量だけが水増しされて表示されていたことになる。
新機能より先にここを直した。あわせて Scene.prerequisites を削除した ― 11 場面に値が入っていたが全部「直前の 1 つ」を指す線形チェーンで旅の並び順と同じ情報、しかも 5 か月間どこからも読まれていなかった。
真実を 2 つ持たないほうを選んだ。
Android の APK を nzw.jp から直接配る β を切った。番号は 1.0.0 ではなく 0.9.0 にして、ストア公開版に 1.0.0 を空けたまま残す。
あわせて、他アプリ(Engly / DayGrid / MyDictly)と同じ update.json 方式のアプリ内アップデーターを載せた。
審査を待つ間、誰にも触られない状態が続く。作り直してから一度も外に出していないので、審査に通るかより先に、人が触って続くかを知りたい。
番号を分けたのは、β とストア版に同じ 1.0.0 を振ると「ストアの 1.0.0」と「配った APK」が後から見分けられなくなるため。
ストアと違い直配布は更新を配ってくれないので、アプリ自身が新版を見に行く仕組みを同時に入れないと、次の版を出しても誰も気づけない。
作業中に、リリースビルドが debug 鍵で署名されたままだったことが分かった(Flutter の雛形の signingConfig = signingConfigs.getByName("debug") が残っていた)。
そのまま配ると、後で正式な鍵に変えたときに署名不一致で上書き更新ができなくなる ― Engly が実際に踏んで「パッケージの解析中に問題が発生しました」になった穴。
nzw 共通の鍵を使う設定に変え、鍵が無い状態で release を叩いたら黙って debug 署名に落ちずビルドを失敗させるようにした。
更新チェックは --dart-define=APK_BUILD=true のときだけ動くので、ストア版と iOS では経路が二重にならない。
音を聞かないと答えが決まらない出題形式を足した。英文を画面に一切出さない。
聞き直しには上限(2〜3 回)を置き、残りをボタンに数字で出す。使い切ってもボタンは消さず落とすだけにして、「文字で見る」は必ず生かす。
これまでも相手のセリフは音声だけで流していたが、聞き取れなくても日本語の指示を読めば答えられた。だから「聞く」は練習にならず、通じなかった原因が語彙なのか耳なのか切り分けられない。
読める逃げ道を塞ぐ代わりに、行き止まりも作らない。聞き直しを無制限にすると「分かるまで聞く」になるが、実際の会話で要るのは 1〜2 回で掴む力。
「文字で見る」の重みだけ聞き取り問題では最上位(お手本を見た)に上げた。産出の発話では聞いた文を読んでも答えは漏れないが、ここは問題そのものを読むことになるため。
据え置くと「足場ゼロで解けた」扱いになり、次に出てくるのが遅れる。採点そのものは 1 行も変えずに済むデータの形にした。
1 レッスンは 12〜20 枚あるのに、進捗はレッスン単位の「覚えた」しか無かった。20 枚を 12 枚まで読んだ人が、一覧では 0 のまま見える。
どちらか一方から他方を導かないのは、一括「覚えた」が「覚えた=true / 0 枚理解」という嘘の状態を作るため。未着手に枠を描かないのは、手つかずの並びが「0%」を突きつける帯になるから。
スライドの鍵は見出しから作った。添字で持つと 1 枚差し込んだ瞬間に以降の記録がずれて別のスライドを指す ―「読んでいない枚が理解済みになっている」という壊れ方は、記録が消えるより気づきにくい。
ついでに一括操作の取り消しが「全部外す」になっていた穴も塞いだ(前から自分で付けていたぶんまで消えていた)。
全画面のヘッダーから同じ横断検索(教科書+場面)を開く。シートを重ねるだけで画面は切り替えない。
教科書の上には目次を置き、章名のリンクから同じ画面の中で送る。ヘッダーからは、しおり・覚えた・メモのアイコンを ⋮ に畳んだ。
検索は教科書タブにしかなく、しかも教科書の中だけを探すものだった。「あの言い方、どこで見たっけ」を場面から引けない。
画面ごとに違う検索があると、押すまでどこを探しているのか分からない。目次を別画面に分けなかったのも同じ理由で、行き来のたびに読んでいた場所を見失う。
目次は最初 8 行を縦に並べたが、それだけで画面の 4 割を占め、開いた直後にレッスンが 1 枚も見えなくなったので折り返して 3 行に畳んだ。
検索は当たったスライドへ直接開く(14 枚のレッスンの 1 枚目に落とすと結局そこから探すことになる)。実機の画面を見て、聞き取り問題の設問が背景の写真に埋もれて読めないことにも気づき、既存の「絵の上で読める面」に載せ替えた。
「問題を解いても褒められた気がしない」という申告から中を見たら、4 択は構造上、絶対に最上位にならない作りだった。
「話していないのに『よく言えた』とは言えない」という発話練習のための判断が、声を出す余地のない 4 択にもそのまま掛かっていたため。
教科書の問題は 10 問中 3 問が 4 択なので、全問 1 回で正解しても「完璧!」に一生届かない。
4 択の正解時に手ごたえ(画面フラッシュ・触覚)が返っていなかった穴も同時に塞いだ。
元の設計原則は壊していない:判定を純関数に切り出し、「並べ替えは 1 回で正解でも ok 止まり」をテストで固定して、場面練習の契約が崩れないようにした。
素朴に「正解した数」を数えると意味を成さない。問題は正解するまで先へ進めない作り(外すと理由が出て選び直す)なので、とばしたぶん以外は全員が満点になり、勲章が何も区別しなくなる。
すでに内部にあった「1 回で正解/やり直して正解/とばした」の区別を成績に昇格させた。
画面には「1 回で正解 8 / 10」と書き、何を数えたのかを隠さない。ベストだけ残す(下がらない)ので、2 周目にクリア済みをとばしても勲章は剥がれない ―「解くほど損」を作らないため。
出題は毎回違う 10 問なので、「全問クリア=レッスン制覇」と誤読されないよう読み上げと副文に「1 回分のベスト」と明記した。
このアプリはアンチペルソナに「ストリークやバッジを集めるのが目的の層」を置いている。集計を並べた瞬間に一覧が収集ゲームの計器盤になり、狙っていない層に最適化してしまう。
銅の文言は一覧に居座り続けるので、見るたび責められる形にはしない(数字は併記するので情報は落ちない)。
カード内の並びを「上ほど次にやること、下ほどこれまでの記録」に統一した。読む前から点数の話が目に入らない。
学習状態(読んだか)と勲章(解けたか)は別の軸として並べ、統合しなかった ― 読まずに問題だけ解く人を表現できなくなるため。
jp.nzw.bearise)に変更。リポジトリ名は grizzlingo のまま残置し、旧版は archive/v0.5-grizzlingo ブランチに保存した。upgradeToPremium() をクライアントから Firestore に書いていて改ざん可能だった。課金を載せる前に塞がないと、公開直後に原価を持っていかれる。ディスカッション・ラリー(定型 120 フレーズを高速に聞き流す。英語→日本語 / 日本語→英語、英語だけ、切り替えの間を秒で設定、中断から再開)/毎日のお知らせとホーム画面のウィジェット、初回は「はじめの一言」/新しいアイコンと緑のテーマカラー、学習の記録のコピーと復元
日本語課題文の機械音声読み上げをやめ、AI音声の英語だけ鳴るようにする/下から出るシートを内容量に応じた高さにし、長押しで場面の絵を覗けるようにする/再生スピードの初期値を「ふつう」に
問題文を読み上げてから始め、声の無い口パク 93 発話を解消/文法ドリルで相手のいない相づちを鳴らさず、空の枠でやることを言う/今日やり終えたマスを光とチェックで浮かせる
App Store 配信開始(無料・アカウント登録なし・収集なし)/iOS は 1.1.0 build 46/Android β は nzw.jp からの直配布を継続、Google Play には出さない
解放を 1 つの鍵にまとめ、旅の後半と教科書・ドリルの 5 章以降へ拡大/分析に「進み具合の推移」の折れ線/教科書とドリルに全 50 項目のマス目/成績 3 色を暖色に作り直し/書き終わりの途中で画面が外れると、しおりの削除から先が飛ぶバグを修正
声を alloy から marin へ(13 声を聴き比べる画面を AI ワークスペースに新設)/読み上げに 2倍速 の段を追加/遅すぎる素材を 4 巡引き直し 125 → 23 本
読み上げを Gemini から OpenAI へ移し 1,384 本を全作り直し(ぶつ切り 34.4%→0.7%)/速さは測って文ごとに当て直す/音声の欠品 3→0
読み上げ音声の作り直し対象を「生成日」で選ぶ方式へ(431 → 806 本)/ぶつ切り検出を語数ではなく間の回数で止める/レビュー画面に「作り直し待ち」を表示
「仕事の英語」に会議と電話/問題の画面の下寄せをゆるめ、フッターとの間に余白/解いた文の形から教科書の該当ページへ直接/学習カレンダーで前の月へ/教科書の「理解した」を成績の緑からブランドの茶へ
解いたあとに文の型・ヒント・語順の解説を1行にまとめて画面下に固定/文の型を 64% → ほぼ全問へ/4択は外した選択肢の理由も/構文から教科書の深い解説へ/「後で読む」と一覧
つまずき集から解説と該当スライドへ抜けられるように/4 択 665 問を蓄積の対象に(誤答の理由も表示)/やった物だけから 10 問の理解度テストと推移/ブラウザ版を公開
文・語ごとの間隔反復(覚えた文が期限で戻る)/ホームに「今日の練習」1 ボタン/主数字を「いま言える文 n / N」へ/つまずき集/場面を一本道のノード解放マップに/教科書は「次に読む」1 枚+章を畳む/壊れていた「声の一致」と「練習 N 回」を是正
Android β を nzw.jp から直配布/アプリ内アップデーター(update.json)を搭載/リリース署名を debug 鍵から nzw 共通鍵へ是正
教科書を 40 → 49 レッスンに拡張(自分を説明する・聞き取る・掘り下げる質問)/場面に無料ジャーニー「自己紹介と質問」5 本/音を聞かないと解けない出題形式/スライド 1 枚ごとの「理解した」/全画面からの横断検索と教科書の目次
教科書を 27 → 40 レッスンに拡張(代名詞・接続詞・仮定法ほか)/全レッスンの例文を並べ替え可能な完全文に統一/問題クリア時の演出と一覧の勲章を追加
Bearise として再出発/シーン 20 本と文法スライド図書館を実装/下タブを 教科書・ホーム・ドリル に再編
Scene Mode の PRD を策定/「採点しない足場」路線から段階カリキュラム路線へ変更
バックエンド API を Firebase 認証+日次上限で保護/TTS のブロッキングを解消