private void _現行化を開始する(ユーザ設定 userConfig) { this._タスク終了通知.Reset(); this._現行化タスク = Task.Run(() => { //Log.現在のスレッドに名前をつける( "現行化" ); --> await 後にワーカスレッドが変わることがある Log.Info("現行化タスクを開始しました。"); while (!this._タスク終了通知.IsSet) { if (this._タスク一時停止通知.IsSet) { this._タスク再開通知.Wait(); } if (this._現行化待ちスタック.TryPop(out var node)) { this._現行化中.Set(); this._ノードを現行化する(node, userConfig); } else { // スタックが空だったら少し待機。 this._現行化中.Reset(); Thread.Sleep(100); } } Log.Info("現行化タスクを終了しました。"); }); }
/// <summary> /// 指定されたツリーの全譜面のユーザ依存の現行化フラグをリセットする。 /// </summary> public void リセットする(IEnumerable <RootNode> roots, ユーザ設定 userConfig) { foreach (var root in roots) { foreach (var node in root.Traverse()) { if (node is SongNode snode) { snode.現行化済み = false; foreach (var score in snode.曲.譜面リスト) { if (score is null) { continue; } //score.譜面と画像を現行化済み = false; --> ユーザに依存しないので現状維持 score.最高記録 = null; score.最高記録を現行化済み = false; score.譜面の属性 = null; score.譜面の属性を現行化済み = false; } } } } }
private int _総ノーツ数を算出して返す(SSTFormatCurrent.スコア score, ユーザ設定 options) { int 総ノーツ数 = 0; foreach (var chip in score.チップリスト) { var チップの対応表 = options.ドラムとチップと入力の対応表[chip.チップ種別]; // AutoPlay ON のチップは、 if (options.AutoPlay[チップの対応表.AutoPlay種別]) { if (!(options.AutoPlayがすべてONである)) { continue; // すべてがONである場合を除いて、カウントしない。 } } // AutoPlay OFF 時でもユーザヒットの対象にならないチップはカウントしない。 if (!(チップの対応表.AutoPlayOFF.ユーザヒット)) { continue; } 総ノーツ数++; } return(総ノーツ数); }
private void _現行化を開始する(ユーザ設定 userConfig) { this._タスク終了通知.Reset(); this._現行化タスク = Task.Run(async() => { Log.現在のスレッドに名前をつける("現行化"); Log.Info("現行化タスクを開始しました。"); while (!this._タスク終了通知.IsSet) { if (this._タスク一時停止通知.IsSet) { this._タスク再開通知.Wait(); } if (this._現行化待ちスタック.TryPop(out var node)) { this._現行化中.Set(); this._ノードを現行化する(node, userConfig); } else { // スタックが空だったら少し待機。 this._現行化中.Reset(); await Task.Delay(1000); } } Log.Info("現行化タスクを終了しました。"); }); }
// 開始と終了 /// <summary> /// 指定された曲ツリーの現行化を開始する。 /// </summary> /// <param name="root">曲ツリーのルートノードのリスト。</param> public void 開始する(IEnumerable <RootNode> roots, ユーザ設定 userConfig) { using var _ = new LogBlock(Log.現在のメソッド名); // 全ノードをスタックに投入。 this._現行化待ちスタック.Clear(); foreach (var root in roots) { foreach (var node in root.Traverse()) { this._現行化待ちスタック.Push(node); } } this._現行化を開始する(userConfig); }
private int _総ノーツ数を算出して返す(SSTFormatCurrent.スコア score, ユーザ設定 options) { int 総ノーツ数 = 0; foreach (var chip in score.チップリスト) { var ドラムチッププロパティ = options.ドラムチッププロパティ管理[chip.チップ種別]; // AutoPlay ON のチップは、すべての AutoPlay が ON である場合を除いて、カウントしない。 //if( options.AutoPlay[ ドラムチッププロパティ.AutoPlay種別 ] && // !( options.AutoPlayがすべてONである ) ) // continue; // AutoPlay OFF 時でもユーザヒットの対象にならないチップはカウントしない。 //if( !( ドラムチッププロパティ.AutoPlayOFF_ユーザヒット ) ) // continue; bool 判定対象である = true; bool チップのAutoPlayはONである = options.AutoPlay[ドラムチッププロパティ.AutoPlay種別]; if (チップのAutoPlayはONである) { if (options.AutoPlayがすべてONである) { 判定対象である = ドラムチッププロパティ.AutoPlayON_自動ヒット_判定; } else { 判定対象である = false; } } else { 判定対象である = ドラムチッププロパティ.AutoPlayOFF_ユーザヒット_判定; } if (判定対象である) { 総ノーツ数++; } } return(総ノーツ数); }
// 開始と終了 /// <summary> /// 指定された曲ツリーの現行化を開始する。 /// </summary> /// <param name="root">曲ツリーのルートノード。</param> public void 開始する(RootNode root, ユーザ設定 userConfig) { using var _ = new LogBlock(Log.現在のメソッド名); Task.Run(() => { this.終了する(); this._現行化待ちスタック.Clear(); // 全ノード投入 foreach (var node in root.Traverse()) { this._現行化待ちスタック.Push(node); } this._現行化を開始する(userConfig); }); }
public void スコアと設定を反映する(SSTFormatCurrent.スコア 譜面, ユーザ設定 設定) { this.総ノーツ数 = (null != 譜面 && null != 設定) ? this._総ノーツ数を算出して返す(譜面, 設定) : 0; this._譜面レベル = 譜面?.難易度 ?? 0.5; }
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 }