メモ
- スケジュール学習機能の追加は保留。Googleカレンダーで他のスケジュールと一緒に管理した方が全体の学習ボリュームを把握できるので
機能
メイン機能
- (✔︎) 暗記したいカテゴリーが選べる。その中で暗記したいカード束(bunch)も選べる
- (✔︎) スタートするとカードがランダムに表示される。答えるチャンスは3回。約30分で終わる
- (✔︎) 出題中に「q」を押すとにカード束(bunch)選択画面に戻れる
- (✔︎) 3回で思い出せなかったカードは正しい答えを入力後、復習ブロックに戻され再び出題される
- (✔︎) 1つのカード束は6回復習する。周回ごとに間違えたカードにはmarkに「1」が加算される
- (✔︎) bunch の学習が終了すると、学習日時と次回の復習タイミング日時(計6つ)が記録される
- 起動すると、復習タイミング日時を過ぎているカード束の一覧が表示される
- (✔︎) 特定の bunch に新しいカードを追加できる機能がある
- bunch を追加したり、修正できる機能がある
サブ機能
- (✔︎) 間違えたカードにはmarkが加算される。カードに付いているmark量をリスト表示できる
- (✔︎) mark量が多いカードを指定してまとめて重点的に復習できる。スケジュールに関係なく遊べる
- (✔︎) 復習イテレータを回している時に間違えるとmarkは増え、正解するとmarkは減る
動員クラス
System・String・Scanner・Integer・Connection・DriverManager・Statement・PreparedStatement・ResultSet・ArrayList・HashMap・Iterator・Exception・Collections・LocalDateTime・Thread
自作クラス
Host
- String table - プレイするカテゴリ
- List<Map<String, String>> correct - 正解したカード束
- prepareGame() - メニューを表示。選択されたカテゴリのタイトルを表示
- askBunchs(String tb) - カード束を表示して、選択されたカード束を取得
- play(String f1, String f2, String tb, String bunch) - playモードでquestionを実行
- retry(List<Map<String, String>> extra) - retryモードでquestionを実行
- iterate(String tb, int above) - sub(復習)モードでquestionを実行
- question(String type, int size, Iterator<Map<String, String>> itr, List<Map<String, String>> extra) - 出題ロジック
DAO
- String URL - DB:URL
- String USER - DBユーザ名
- String PASSWD - DBパスワード
- getCats() - データベース内のカテゴリを数字付きのマップで返す
- getBunchs(String tb) - カテゴリ内にあるカード束をリストで返す
- getCards(String f1, String f2, String tb, String bunch) - カテゴリとカード束を指定してカードを取得
- recordDates(String tb, String bunch) - 学習日時と将来のスケジュールを記録
- recordMark(String tb, List<Map<String, String>> list, boolean incorrect) - カードの正誤を記録
- listMarked(String tb) - マークされているカード一覧を表示。aboveを返す
- get MarkedCards(String tb, int above) - マークのあるカードをそのマーク数に応じて取得
Manager
- manage() - 管理メニューを表示
DAOm
- String field1 - 新規カードのfield1部分
- String field2 - 新規カードのfield2部分
- showBunchs() - カードを追加できるカード束(と枚数)を表示。追加希望のカテゴリとカード束を取得
- addCards(Map<String, String> tableBunch) - 新規カードの登録ロジック
- inputFields() - 新規カード(表:field1,裏: field2)の登録フォーム
Text
- type(String text, int speed) - タイピング演出
学んだこと/感じたこと
- 「カテゴリ」よりもDBでも使われている「テーブル」に統一した方が良い
- 仕様によると ResultSet は値指定よりもインデックス指定の方が効率的。getInt(1);
- 何を取得しようとしているのかは直前のSQL文を見れば分かる
- 無理に、Map<Integer, Map<String, String>> としなくても +連結で数字を入れても良い
- Mapのキーは、同じだと上書きされる
- DB直接操作する場合はトランザクション利用か、アプリの方の編集機能を通して操作する
- そうしないと、ふとした瞬間にデータ400件が一瞬で消える可能性が0にはならない
- まず、メインメソッド内でやりたい事の脚本をじっくり述語的に練り上げてから始めても良い
- メインを綺麗にまとめようとしたら結局、やりたい事のシンプルな脚本みたいになった
- 脚本のように書くと非常に分かりやすい。そもそも、それがプログラミング(=脚本)だから当然か
- static にするかどうかの判断基準はメソッドスコープを越えるローカル変数を使いたいかどうか
- フィールドとはそのクラス内で使い回したい汎用的なローカル変数、インスタンス変数の事
- ローカル変数を利用するには new でインスタンス変数化の後、this指定して利用する
- このようにすればスコープの外で欲しい値が取り出せる。言語設計で分割強制してる感じか
- 同じ Iterator を複数回ほど利用するときは next と previous を使ってデータを取得する
- 後になってからの変数名の変更はとても面倒なので、一番最初で「永久に決まるもの」とする
- DBでは必要最低限のデータセットVIEWをアプリ用バッファとして作成。データはそこから取得
- SQL文を作成するとき、変数でパラメータを指定している場合は「'」で括る
- エラーがないのに変更が反映されない場合は、該当ソースのコンパイルも忘れない
- toString で節目節目の流れを確認しながら進めていけばエラーの原因は特定できる
- ロジックを1文ずつしっかり読み、流れ全体を完全に理解していればエラーは必ず直せる
- 「break」1つが1時間の問題の解決策だったりする
- ListArrayからはindex指定だけでなく、要素指定でもremoveできる
- ListIterator は、要素を追加できるけど、追加できる場所が「直前」だけなので微妙
- for ですでに回しに入っている要素リストに新しく要素を追加することはできなさそう
- なので、別のコレクションをもう1つ用意してそちらで再度回すことができる
- Git が必要。大きな改善を試みる時ファイルコピーは厳しい。気軽にフォークして試したい
- Git が必要。「DBカテゴリフィールド修正.ver」と「Iterator使わない.ver」が欲しい
- Iteratorで自動的に順次で取り出す方法と、逐一リストからremoveする方法がある
- newを使うのはインスタンスにフィールドを持たせたい時。それまではstaticで十分
- PreparedStatement の「?」はフィールド名ではなくパラメータを指定するもの
- フィールド名を変数で指定したい場合は「+」を使って SQL文を連結させる
- PreparedStatement と通常SQL文を組み合わせて実行
- List<Map<String, String>> とするには Mapを毎回作ってListにaddする
- List型に対する Collections.shuffle による要素シャッフル
- Iteratorによる入れ子構造の要素の取り出し。それぞれの型の指定がポイント
- モニターがもう1台あると便利そう