/// <summary> /// 現状の ScoreDB と ScorePropertiesDB(ともに現行化前)を読み込んで反映する。 /// </summary> public async Task ノードにDBを反映するAsync() { //using var _ = new LogBlock( Log.現在のメソッド名 ); this._進捗カウンタ = 0; await Task.Run(() => { // 全レコード抽出 using var scoredb = new ScoreDB(); using var scorePropertiesdb = new ScorePropertiesDB(); using var query = new SqliteCommand("SELECT * FROM Scores", scoredb.Connection); var result = query.ExecuteReader(); while (result.Read()) { Interlocked.Increment(ref this._進捗カウンタ); var record = new ScoreDBRecord(result); // レコードに記載されているパスが全譜面リストに存在していれば、レコードの内容で更新する。 foreach (var score in Global.App.全譜面リスト.Where((s) => s.譜面.ScorePath == record.ScorePath)) { score.譜面.UpdateFrom(record); } } }); }
// ツリーと全譜面リストの構築 /// <summary> /// 標準の曲ツリーを構築する。 /// </summary> /// <remarks> /// 曲ツリーは、曲検索フォルダを検索した結果に、現状の(現行前の)ScoreDB の内容を反映したものとなる。 /// 曲ツリーを構築すると同時に、全譜面リストも構築する。 /// </remarks> public void 構築する(IEnumerable <VariablePath> 曲検索フォルダパスリスト, Dictionary <string, Score> 全譜面リスト) { using var _ = new LogBlock(Log.現在のメソッド名); // (1) 曲検索フォルダパスをスキャンして、曲ツリー(と全譜面リスト)を構築する。 // ルートノードの子ノードリストの先頭に「ランダムセレクト」を追加する。 this.ルートノード.子ノードリスト.Add(new RandomSelectNode() { 親ノード = this.ルートノード }); // 曲検索パスに従って構築する。 foreach (var path in 曲検索フォルダパスリスト) { this._構築する(path, this.ルートノード); } // (2) 現状の(まだ現行化されていない)ScoreDB を読み込んで全譜面リストに反映する。 using var scoredb = new ScoreDB(); using var query = new SqliteCommand("SELECT * FROM Scores", scoredb.Connection); var result = query.ExecuteReader(); while (result.Read()) { var record = new ScoreDBRecord(result); if (全譜面リスト.ContainsKey(record.ScorePath)) { 全譜面リスト[record.ScorePath].譜面.UpdateFrom(record); // 上書き } } // (3) 文字列画像のみ生成する。 foreach (var score in 全譜面リスト.Values) { score.タイトル文字列画像 = 現行化.タイトル文字列画像を生成する(score.譜面.Title); score.サブタイトル文字列画像 = 現行化.サブタイトル文字列画像を生成する(score.譜面.Artist); } // (4) 最初の子ノードをフォーカスする。 this.フォーカスリスト.SelectFirst(); }
private void _ノードを現行化する(Node node, ユーザ設定 userConfig) { #region " 1. ノードが持つ譜面の現行化 " //---------------- if (node is SongNode snode) { using var scoredb = new ScoreDB(); using (var cmd = new SqliteCommand("BEGIN", scoredb.Connection)) cmd.ExecuteNonQuery(); // すべての譜面について…… for (int i = 0; i < 5; i++) { var score = snode.曲.譜面リスト[i]; if (score is null) { continue; } if (!File.Exists(score.譜面.ScorePath)) { Log.ERROR($"ファイルが存在しません。[{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( score.譜面.ScorePath )}]"); snode.曲.譜面リスト[i] !.Dispose(); snode.曲.譜面リスト[i] = null; continue; } // 1.1. 譜面と画像 の現行化 if (!score.譜面と画像を現行化済み) { #region " ファイルの更新を確認し、ScoreDB と score を現行化する。" //---------------- try { using var query = new SqliteCommand("SELECT * FROM Scores WHERE ScorePath = @ScorePath", scoredb.Connection); query.Parameters.Add(new SqliteParameter("@ScorePath", score.譜面.ScorePath)); var result = query.ExecuteReader(); if (!result.Read()) { // (A) ScoreDB に既存のレコードがない場合 #region " ScoreDBの レコードを新規追加し score を更新する。" //---------------- var レコード = new ScoreDBRecord(score.譜面.ScorePath, userConfig); // レコードを ScoreDB に新規追加する。 レコード.ReplaceTo(scoredb); // score にも反映する。 score.譜面.UpdateFrom(レコード); // 完了。 Log.Info($"ScoreDBに曲を追加しました。{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( score.譜面.ScorePath )}"); //---------------- #endregion } else { // (B) ScoreDB に既存のレコードがある場合 var レコード = new ScoreDBRecord(result); string 譜面ファイルの最終更新日時 = File.GetLastWriteTime(score.譜面.ScorePath).ToString("G"); if (レコード.LastWriteTime != 譜面ファイルの最終更新日時) { #region " (B-a) 譜面ファイルの最終更新日時が更新されている → ScoreDB のレコードと score を更新する。" //---------------- レコード = new ScoreDBRecord(score.譜面.ScorePath, userConfig); // ScoreDB のレコードを置換する。 レコード.ReplaceTo(scoredb); // score にも反映する。 score.譜面.UpdateFrom(レコード); // 完了。 Log.Info($"最終更新日時が変更されているため、曲の情報を更新しました。{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( score.譜面.ScorePath )}"); //---------------- #endregion } else { #region " (B-b) それ以外 → 何もしない " //---------------- //---------------- #endregion } } } catch (Exception e) { Log.ERROR($"譜面の現行化に失敗しました。[{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( e.Message )}][{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( score.譜面.ScorePath )}]"); // 続行 } //---------------- #endregion #region " 画像を現行化する。" //---------------- try { if (score.タイトル文字列画像 is null || score.タイトル文字列画像.表示文字列 != score.譜面.Title) { score.タイトル文字列画像?.Dispose(); score.タイトル文字列画像 = タイトル文字列画像を生成する(score.譜面.Title); } if (score.サブタイトル文字列画像 is null || score.サブタイトル文字列画像.表示文字列 != score.譜面.Artist) { score.サブタイトル文字列画像?.Dispose(); score.サブタイトル文字列画像 = サブタイトル文字列画像を生成する(string.IsNullOrEmpty(score.譜面.Artist) ? null : score.譜面.Artist); } score.プレビュー画像?.Dispose(); score.プレビュー画像 = ノード画像を生成する( string.IsNullOrEmpty(score.譜面.PreImage) ? null : new VariablePath(Path.Combine(Path.GetDirectoryName(score.譜面.ScorePath) ?? @"\", score.譜面.PreImage))); } catch (Exception e) { Log.ERROR($"譜面画像の現行化に失敗しました。[{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( e.Message )}][{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す(score.譜面.ScorePath)}]"); // 続行 } //---------------- #endregion // 現行化の成否によらず完了。 score.譜面と画像を現行化済み = true; } // 1.2. 属性 の現行化 if (!score.譜面の属性を現行化済み) { #region " 譜面の属性を現行化する。" //---------------- try { using var scorepropdb = new ScorePropertiesDB(); using var cmd = new SqliteCommand("SELECT * FROM ScoreProperties WHERE ScorePath = @ScorePath AND UserId = @UserId", scorepropdb.Connection); cmd.Parameters.AddRange(new[] { new SqliteParameter("@ScorePath", score.譜面.ScorePath), new SqliteParameter("@UserId", userConfig.ID), }); var result = cmd.ExecuteReader(); if (result.Read()) { score.譜面の属性 = new ScorePropertiesDBRecord(result); Log.Info($"譜面の属性を現行化しました。[{score.譜面.ScorePath}]"); } } catch (Exception e) { Log.ERROR($"譜面の属性の現行化に失敗しました。[{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( e.Message )}][{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( score.譜面.ScorePath )}]"); // 続行 } // 現行化の成否によらず完了。 score.譜面の属性を現行化済み = true; //---------------- #endregion } // 1.3. 最高記録 の現行化 if (!score.最高記録を現行化済み) { #region " 最高記録を現行化する。" //---------------- try { using var recorddb = new RecordDB(); using var cmd = new SqliteCommand("SELECT * FROM Records WHERE ScorePath = @ScorePath AND UserId = @UserId", recorddb.Connection); cmd.Parameters.AddRange(new[] { new SqliteParameter("@ScorePath", score.譜面.ScorePath), new SqliteParameter("@UserId", userConfig.ID), }); var result = cmd.ExecuteReader(); if (result.Read()) { score.最高記録 = new RecordDBRecord(result); Log.Info($"最高記録を現行化しました。[{score.譜面.ScorePath}]"); } } catch (Exception e) { Log.ERROR($"最高記録の現行化に失敗しました。[{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( e.Message )}][{Folder.絶対パスをフォルダ変数付き絶対パスに変換して返す( score.譜面.ScorePath )}]"); // 続行 } // 現行化の成否によらず完了。 score.最高記録を現行化済み = true; //---------------- #endregion } } using (var cmd = new SqliteCommand("END", scoredb.Connection)) cmd.ExecuteNonQuery(); } //---------------- #endregion #region " 2. ノードの現行化 " //---------------- if (!node.現行化済み) { if (node is SongNode) { // SongNode は生成不要。 // → App.全譜面リスト の構築時に、タイトル文字列画像とサブタイトル文字列画像だけ先に生成済み。 } else { // SongNode 以外は生成する。 node.タイトル文字列画像 = タイトル文字列画像を生成する(node.タイトル); node.サブタイトル文字列画像 = サブタイトル文字列画像を生成する(node.サブタイトル); node.ノード画像 = ノード画像を生成する(node.ノード画像ファイルの絶対パス); } // 生成の成否によらず完了。 node.現行化済み = true; } //---------------- #endregion }