プロジェクトへ戻る

pub.dev公開・製品へ導入済み

unicode_typing_grader

実アプリで必要になった採点ロジックを、Dart単体で動くUnicode対応OSSとして独立させました。

個人アプリで必要になったタイピング採点をDart単体で動くパッケージへ分離し、pub.devへ公開しました。NFC正規化、書記素単位の編集距離、バージョン付きポリシーと適合性フィクスチャで同じ入力が同じ結果になる境界を定義し、実際のアプリにも適用しました。

期間
2026.08.24 - 現在
担当範囲
パッケージ設計・実装・テスト・公開・製品への再導入
チーム
個人OSS
リポジトリ
公開リポジトリ

製品内の採点規則を、公開契約へ変える

個人アプリの採点機能を作る過程で、NFC正規化、書記素単位の比較、空白・終端記号のポリシー、有効入力時間を使うCPMは画面固有の責任ではないと判断しました。

計算部分をDart単体へ分離し、英語・韓国語・日本語の文書、ブラウザ版サンプル、適合性フィクスチャとともにpub.devへ公開しました。公開後は実際のアプリにも適用し、パッケージの外に残す責任を確認しました。

製品からOSSを使う境界

製品契約は保ちながら、採点計算を公開エンジンへ一元化する

  1. 01

    練習画面

    コミット済みの入力を渡す

  2. 02

    製品ポリシー

    既存の保存・表示形式

  3. 03

    薄いアダプター

    バージョンとフィールド名を変換

  4. 04

    公開OSSエンジン

    NFC・書記素・編集経路

  5. 05

    製品結果

    固定小数点指標を保存

見える一文字を、文字列の長さと同じにしない

韓国語の完成形・分解形、日本語の結合文字、ZWJでつながる絵文字は、表示が同じでも内部表現やコードポイント数が異なります。String.lengthや単純な一致判定では、正しい入力を誤答にしたり、一つの絵文字を複数文字として数える可能性がありました。

エンジンはFlutterウィジェットやIMEライフサイクルへ依存せず、同じ文字列・ポリシー・時間なら実行環境が変わっても同じ結果を返す必要がありました。短い学習文を対象とするため、編集経路を説明できることを優先し、O(n×m)の時間・メモリ境界をREADMEに明記しました。

NFC正規化後に拡張書記素クラスタへ分割し、レーベンシュタイン距離を計算しました。同点の編集経路には固定した優先順位を置き、空白と終端記号はバージョン付きポリシーで扱い、正確度と総CPMは1000倍の整数で返します。

  • 韓国語の完成形・分解形、日本語の仮名、結合文字、ZWJ絵文字をテストケースへ追加しました。
  • ポリシーJSONを厳格に解析し、未知バージョン・値・フィールドを拒否しました。
  • 共通入力と期待結果を適合性/v1フィクスチャとして公開しました。

フォーマット・静的解析・39件のテスト・公開前ドライランを通過し、Dart 3.8と安定版を確認するCIを公開リポジトリで実行しています。

Unicode対応では、正規化を加えるだけでなく、何を一文字と数え、同点の誤りをどう説明するかまで契約に固定する必要がありました。

切り出したエンジンを、元の製品へ戻す

パッケージ公開後も適用先が内部コピーを使い続ければ、修正先が二つに分かれ、Unicodeのルールや指標の丸め方が徐々にずれる可能性があります。再利用可能という説明も、実際の利用先がなければ設計上の主張に留まります。

公開パッケージのモデルをそのまま適用すると、既存アプリのモデルと保存データの互換性を壊す可能性がありました。OSSの境界を保ちながら、適用先固有の表現も維持する必要がありました。

適用先はpub.devの0.1.2を直接利用し、既存モデルとパッケージモデルを変換する小さなアダプターだけを残しました。共通の計算はパッケージへ集約し、アプリ固有の表示・保存形式は変換点で分離しました。

  • 重複していた比較・指標計算を削除しました。
  • ローカルフォークなしでpub.dev 0.1.2を利用しました。
  • 既存モデルとの変換を小さなアダプターへ限定しました。

実際の個人アプリへ公開パッケージを適用し、既存データを維持したまま重複していた比較・指標計算を削除しました。

共通エンジンと製品契約を同じものとして扱わず、変換点を小さく残すことで、再利用と既存互換性を同時に守れると確認しました。

適用先で採点結果を確認した日本語UI

unicode_typing_grader 0.1.2はpub.devとGitHubで公開中です。39件のテストとCIを備え、実際のアプリでも公開パッケージを利用しています。

再利用できそうなコードを別リポジトリへ移すだけではOSSにならないと考えるようになりました。公開API、バージョン付き契約、境界事例のテスト、ライセンス、利用先への再導入まで閉じて初めて、製品の外でも変更を説明できる技術資産になります。

2026年8月に公開した0.1.xパッケージであり、外部利用者数・長期互換性・代表的な入力長でのベンチマークはまだ確認していません。

  • 実利用プロンプト長で時間・メモリベンチマークを追加する
  • 外部利用先のフィードバックを集め、1.0.0で固定するAPI境界を決める
  • パッケージ更新時にDart・Goのフィクスチャ検証を必須検査へする