2 using System.Collections.Generic;
\r
3 using System.Globalization;
\r
5 using System.Diagnostics;
\r
7 using System.Drawing;
\r
8 using System.Threading;
\r
13 internal class CSongs管理
\r
17 public int nSongsDBから取得できたスコア数
\r
22 public int nSongsDBへ出力できたスコア数
\r
27 public int nスコアキャッシュから反映できたスコア数
\r
32 public int nファイルから反映できたスコア数
\r
37 public int n検索されたスコア数
\r
42 public int n検索された曲ノード数
\r
48 public List<Cスコア> listSongsDB; // songs.dbから構築されるlist
\r
49 public List<C曲リストノード> list曲ルート; // 起動時にフォルダ検索して構築されるlist
\r
50 public bool bIsSuspending // 外部スレッドから、内部スレッドのsuspendを指示する時にtrueにする
\r
51 { // 再開時は、これをfalseにしてから、次のautoReset.Set()を実行する
\r
55 public bool bIsSlowdown // #PREMOVIE再生時に曲検索を遅くする
\r
61 private AutoResetEvent autoReset;
\r
62 public AutoResetEvent AutoReset
\r
74 private int searchCount; // #PREMOVIE中は検索n回実行したら少しスリープする
\r
80 this.listSongsDB = new List<Cスコア>();
\r
81 this.list曲ルート = new List<C曲リストノード>();
\r
82 this.n検索された曲ノード数 = 0;
\r
83 this.n検索されたスコア数 = 0;
\r
84 this.bIsSuspending = false; // #27060
\r
85 this.autoReset = new AutoResetEvent( true ); // #27060
\r
86 this.searchCount = 0;
\r
92 #region [ SongsDB(songs.db) を読み込む ]
\r
94 public void tSongsDBを読み込む( string SongsDBファイル名 )
\r
96 this.nSongsDBから取得できたスコア数 = 0;
\r
97 if( File.Exists( SongsDBファイル名 ) )
\r
99 BinaryReader br = null;
\r
102 br = new BinaryReader( File.OpenRead( SongsDBファイル名 ) );
\r
103 if ( !br.ReadString().Equals( SONGSDB_VERSION ) )
\r
105 throw new InvalidDataException( "ヘッダが異なります。" );
\r
107 this.listSongsDB = new List<Cスコア>();
\r
113 Cスコア item = this.tSongsDBからスコアを1つ読み込む( br );
\r
114 this.listSongsDB.Add( item );
\r
115 this.nSongsDBから取得できたスコア数++;
\r
117 catch( EndOfStreamException )
\r
130 //-----------------
\r
133 #region [ 曲を検索してリストを作成する ]
\r
134 //-----------------
\r
135 public void t曲を検索してリストを作成する( string str基点フォルダ, bool b子BOXへ再帰する )
\r
137 this.t曲を検索してリストを作成する( str基点フォルダ, b子BOXへ再帰する, this.list曲ルート, null );
\r
139 private void t曲を検索してリストを作成する( string str基点フォルダ, bool b子BOXへ再帰する, List<C曲リストノード> listノードリスト, C曲リストノード node親 )
\r
141 if( !str基点フォルダ.EndsWith( @"\" ) )
\r
142 str基点フォルダ = str基点フォルダ + @"\";
\r
144 DirectoryInfo info = new DirectoryInfo( str基点フォルダ );
\r
146 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
147 Trace.TraceInformation( "基点フォルダ: " + str基点フォルダ );
\r
149 #region [ a.フォルダ内に set.def が存在する場合 → set.def からノード作成]
\r
150 //-----------------------------
\r
151 string path = str基点フォルダ + "set.def";
\r
152 if( File.Exists( path ) )
\r
154 CSetDef def = new CSetDef( path );
\r
155 new FileInfo( path );
\r
156 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
158 Trace.TraceInformation( "set.def検出 : {0}", path );
\r
163 SlowOrSuspendSearchTask(); // #27060 中断要求があったら、解除要求が来るまで待機, #PREMOVIE再生中は検索負荷を落とす
\r
164 for( int i = 0; i < def.blocks.Count; i++ )
\r
166 CSetDef.CBlock block = def.blocks[ i ];
\r
167 C曲リストノード item = new C曲リストノード();
\r
168 item.eノード種別 = C曲リストノード.Eノード種別.SCORE;
\r
169 item.strタイトル = block.Title;
\r
170 item.strジャンル = block.Genre;
\r
172 item.col文字色 = block.FontColor;
\r
173 item.SetDefのブロック番号 = i;
\r
174 item.pathSetDefの絶対パス = path;
\r
175 item.r親ノード = node親;
\r
177 item.strBreadcrumbs = ( item.r親ノード == null ) ?
\r
178 path + i : item.r親ノード.strBreadcrumbs + " > " + path + i;
\r
180 for( int j = 0; j < 5; j++ )
\r
182 if( !string.IsNullOrEmpty( block.File[ j ] ) )
\r
184 string str2 = str基点フォルダ + block.File[ j ];
\r
185 if( File.Exists( str2 ) )
\r
187 item.ar難易度ラベル[ j ] = block.Label[ j ];
\r
188 item.arスコア[ j ] = new Cスコア();
\r
189 item.arスコア[ j ].ファイル情報.ファイルの絶対パス = str2;
\r
190 item.arスコア[ j ].ファイル情報.フォルダの絶対パス = Path.GetFullPath( Path.GetDirectoryName( str2 ) ) + @"\";
\r
191 FileInfo info2 = new FileInfo( str2 );
\r
192 item.arスコア[ j ].ファイル情報.ファイルサイズ = info2.Length;
\r
193 item.arスコア[ j ].ファイル情報.最終更新日時 = info2.LastWriteTime;
\r
194 string str3 = str2 + ".score.ini";
\r
195 if( File.Exists( str3 ) )
\r
197 FileInfo info3 = new FileInfo( str3 );
\r
198 item.arスコア[ j ].ScoreIni情報.ファイルサイズ = info3.Length;
\r
199 item.arスコア[ j ].ScoreIni情報.最終更新日時 = info3.LastWriteTime;
\r
206 item.arスコア[ j ] = null;
\r
210 if( item.nスコア数 > 0 )
\r
212 listノードリスト.Add( item );
\r
213 this.n検索された曲ノード数++;
\r
214 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
216 StringBuilder builder = new StringBuilder( 0x200 );
\r
217 builder.Append( string.Format( "nID#{0:D3}", item.nID ) );
\r
218 if( item.r親ノード != null )
\r
220 builder.Append( string.Format( "(in#{0:D3}):", item.r親ノード.nID ) );
\r
224 builder.Append( "(onRoot):" );
\r
226 if( ( item.strタイトル != null ) && ( item.strタイトル.Length > 0 ) )
\r
228 builder.Append( " SONG, Title=" + item.strタイトル );
\r
230 if( ( item.strジャンル != null ) && ( item.strジャンル.Length > 0 ) )
\r
232 builder.Append( ", Genre=" + item.strジャンル );
\r
234 if( item.col文字色 != Color.White )
\r
236 builder.Append( ", FontColor=" + item.col文字色 );
\r
238 Trace.TraceInformation( builder.ToString() );
\r
242 for( int k = 0; k < 5; k++ )
\r
244 if( item.arスコア[ k ] != null )
\r
246 Cスコア cスコア = item.arスコア[ k ];
\r
247 builder.Remove( 0, builder.Length );
\r
248 builder.Append( string.Format( "ブロック{0}-{1}:", item.SetDefのブロック番号 + 1, k + 1 ) );
\r
249 builder.Append( " Label=" + item.ar難易度ラベル[ k ] );
\r
250 builder.Append( ", File=" + cスコア.ファイル情報.ファイルの絶対パス );
\r
251 builder.Append( ", Size=" + cスコア.ファイル情報.ファイルサイズ );
\r
252 builder.Append( ", LastUpdate=" + cスコア.ファイル情報.最終更新日時 );
\r
253 Trace.TraceInformation( builder.ToString() );
\r
267 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
273 //-----------------------------
\r
276 #region [ b.フォルダ内に set.def が存在しない場合 → 個別ファイルからノード作成 ]
\r
277 //-----------------------------
\r
280 foreach( FileInfo fileinfo in info.GetFiles() )
\r
282 SlowOrSuspendSearchTask(); // #27060 中断要求があったら、解除要求が来るまで待機, #PREMOVIE再生中は検索負荷を落とす
\r
283 string strExt = fileinfo.Extension.ToLower();
\r
284 if( ( strExt.Equals( ".dtx" ) || strExt.Equals( ".gda" ) ) || ( ( strExt.Equals( ".g2d" ) || strExt.Equals( ".bms" ) ) || strExt.Equals( ".bme" ) ) )
\r
286 C曲リストノード c曲リストノード = new C曲リストノード();
\r
287 c曲リストノード.eノード種別 = C曲リストノード.Eノード種別.SCORE;
\r
288 c曲リストノード.nスコア数 = 1;
\r
289 c曲リストノード.r親ノード = node親;
\r
291 c曲リストノード.strBreadcrumbs = ( c曲リストノード.r親ノード == null ) ?
\r
292 str基点フォルダ + fileinfo.Name : c曲リストノード.r親ノード.strBreadcrumbs + " > " + str基点フォルダ + fileinfo.Name;
\r
294 c曲リストノード.arスコア[ 0 ] = new Cスコア();
\r
295 c曲リストノード.arスコア[ 0 ].ファイル情報.ファイルの絶対パス = str基点フォルダ + fileinfo.Name;
\r
296 c曲リストノード.arスコア[ 0 ].ファイル情報.フォルダの絶対パス = str基点フォルダ;
\r
297 c曲リストノード.arスコア[ 0 ].ファイル情報.ファイルサイズ = fileinfo.Length;
\r
298 c曲リストノード.arスコア[ 0 ].ファイル情報.最終更新日時 = fileinfo.LastWriteTime;
\r
299 string strFileNameScoreIni = c曲リストノード.arスコア[ 0 ].ファイル情報.ファイルの絶対パス + ".score.ini";
\r
300 if( File.Exists( strFileNameScoreIni ) )
\r
302 FileInfo infoScoreIni = new FileInfo( strFileNameScoreIni );
\r
303 c曲リストノード.arスコア[ 0 ].ScoreIni情報.ファイルサイズ = infoScoreIni.Length;
\r
304 c曲リストノード.arスコア[ 0 ].ScoreIni情報.最終更新日時 = infoScoreIni.LastWriteTime;
\r
307 listノードリスト.Add( c曲リストノード );
\r
308 this.n検索された曲ノード数++;
\r
309 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
314 StringBuilder sb = new StringBuilder( 0x100 );
\r
315 sb.Append( string.Format( "nID#{0:D3}", c曲リストノード.nID ) );
\r
316 if( c曲リストノード.r親ノード != null )
\r
318 sb.Append( string.Format( "(in#{0:D3}):", c曲リストノード.r親ノード.nID ) );
\r
322 sb.Append( "(onRoot):" );
\r
324 sb.Append( " SONG, File=" + c曲リストノード.arスコア[ 0 ].ファイル情報.ファイルの絶対パス );
\r
325 sb.Append( ", Size=" + c曲リストノード.arスコア[ 0 ].ファイル情報.ファイルサイズ );
\r
326 sb.Append( ", LastUpdate=" + c曲リストノード.arスコア[ 0 ].ファイル情報.最終更新日時 );
\r
327 Trace.TraceInformation( sb.ToString() );
\r
335 else if( strExt.Equals( ".mid" ) || strExt.Equals( ".smf" ))
\r
341 //-----------------------------
\r
344 foreach( DirectoryInfo infoDir in info.GetDirectories() )
\r
346 SlowOrSuspendSearchTask(); // #27060 中断要求があったら、解除要求が来るまで待機, #PREMOVIE再生中は検索負荷を落とす
\r
348 #region [ a. "dtxfiles." で始まるフォルダの場合 ]
\r
349 //-----------------------------
\r
350 if( infoDir.Name.ToLower().StartsWith( "dtxfiles." ) )
\r
352 C曲リストノード c曲リストノード = new C曲リストノード();
\r
353 c曲リストノード.eノード種別 = C曲リストノード.Eノード種別.BOX;
\r
354 c曲リストノード.bDTXFilesで始まるフォルダ名のBOXである = true;
\r
355 c曲リストノード.strタイトル = infoDir.Name.Substring( 9 );
\r
356 c曲リストノード.nスコア数 = 1;
\r
357 c曲リストノード.r親ノード = node親;
\r
359 c曲リストノード.strBreadcrumbs = ( c曲リストノード.r親ノード == null ) ?
\r
360 c曲リストノード.strタイトル : c曲リストノード.r親ノード.strBreadcrumbs + " > " + c曲リストノード.strタイトル;
\r
363 c曲リストノード.list子リスト = new List<C曲リストノード>();
\r
364 c曲リストノード.arスコア[ 0 ] = new Cスコア();
\r
365 c曲リストノード.arスコア[ 0 ].ファイル情報.フォルダの絶対パス = infoDir.FullName + @"\";
\r
366 c曲リストノード.arスコア[ 0 ].譜面情報.タイトル = c曲リストノード.strタイトル;
\r
367 c曲リストノード.arスコア[ 0 ].譜面情報.コメント =
\r
368 (CultureInfo.CurrentCulture.TwoLetterISOLanguageName == "ja") ?
\r
370 "Enter into the BOX.";
\r
371 listノードリスト.Add(c曲リストノード);
\r
372 if( File.Exists( infoDir.FullName + @"\box.def" ) )
\r
374 CBoxDef boxdef = new CBoxDef( infoDir.FullName + @"\box.def" );
\r
375 if( ( boxdef.Title != null ) && ( boxdef.Title.Length > 0 ) )
\r
377 c曲リストノード.strタイトル = boxdef.Title;
\r
379 if( ( boxdef.Genre != null ) && ( boxdef.Genre.Length > 0 ) )
\r
381 c曲リストノード.strジャンル = boxdef.Genre;
\r
383 if( boxdef.Color != Color.White )
\r
385 c曲リストノード.col文字色 = boxdef.Color;
\r
387 if( ( boxdef.Artist != null ) && ( boxdef.Artist.Length > 0 ) )
\r
389 c曲リストノード.arスコア[ 0 ].譜面情報.アーティスト名 = boxdef.Artist;
\r
391 if( ( boxdef.Comment != null ) && ( boxdef.Comment.Length > 0 ) )
\r
393 c曲リストノード.arスコア[ 0 ].譜面情報.コメント = boxdef.Comment;
\r
395 if( ( boxdef.Preimage != null ) && ( boxdef.Preimage.Length > 0 ) )
\r
397 c曲リストノード.arスコア[ 0 ].譜面情報.Preimage = boxdef.Preimage;
\r
399 if( ( boxdef.Premovie != null ) && ( boxdef.Premovie.Length > 0 ) )
\r
401 c曲リストノード.arスコア[ 0 ].譜面情報.Premovie = boxdef.Premovie;
\r
403 if( ( boxdef.Presound != null ) && ( boxdef.Presound.Length > 0 ) )
\r
405 c曲リストノード.arスコア[ 0 ].譜面情報.Presound = boxdef.Presound;
\r
407 if( boxdef.PerfectRange >= 0 )
\r
409 c曲リストノード.nPerfect範囲ms = boxdef.PerfectRange;
\r
411 if( boxdef.GreatRange >= 0 )
\r
413 c曲リストノード.nGreat範囲ms = boxdef.GreatRange;
\r
415 if( boxdef.GoodRange >= 0 )
\r
417 c曲リストノード.nGood範囲ms = boxdef.GoodRange;
\r
419 if( boxdef.PoorRange >= 0 )
\r
421 c曲リストノード.nPoor範囲ms = boxdef.PoorRange;
\r
424 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
429 StringBuilder sb = new StringBuilder( 0x100 );
\r
430 sb.Append( string.Format( "nID#{0:D3}", c曲リストノード.nID ) );
\r
431 if( c曲リストノード.r親ノード != null )
\r
433 sb.Append( string.Format( "(in#{0:D3}):", c曲リストノード.r親ノード.nID ) );
\r
437 sb.Append( "(onRoot):" );
\r
439 sb.Append( " BOX, Title=" + c曲リストノード.strタイトル );
\r
440 sb.Append( ", Folder=" + c曲リストノード.arスコア[ 0 ].ファイル情報.フォルダの絶対パス );
\r
441 sb.Append( ", Comment=" + c曲リストノード.arスコア[ 0 ].譜面情報.コメント );
\r
442 Trace.TraceInformation( sb.ToString() );
\r
451 this.t曲を検索してリストを作成する( infoDir.FullName + @"\", b子BOXへ再帰する, c曲リストノード.list子リスト, c曲リストノード );
\r
454 //-----------------------------
\r
457 #region [ b.box.def を含むフォルダの場合 ]
\r
458 //-----------------------------
\r
459 else if( File.Exists( infoDir.FullName + @"\box.def" ) )
\r
461 CBoxDef boxdef = new CBoxDef( infoDir.FullName + @"\box.def" );
\r
462 C曲リストノード c曲リストノード = new C曲リストノード();
\r
463 c曲リストノード.eノード種別 = C曲リストノード.Eノード種別.BOX;
\r
464 c曲リストノード.bDTXFilesで始まるフォルダ名のBOXである = false;
\r
465 c曲リストノード.strタイトル = boxdef.Title;
\r
466 c曲リストノード.strジャンル = boxdef.Genre;
\r
467 c曲リストノード.col文字色 = boxdef.Color;
\r
468 c曲リストノード.nスコア数 = 1;
\r
469 c曲リストノード.arスコア[ 0 ] = new Cスコア();
\r
470 c曲リストノード.arスコア[ 0 ].ファイル情報.フォルダの絶対パス = infoDir.FullName + @"\";
\r
471 c曲リストノード.arスコア[ 0 ].譜面情報.タイトル = boxdef.Title;
\r
472 c曲リストノード.arスコア[ 0 ].譜面情報.ジャンル = boxdef.Genre;
\r
473 c曲リストノード.arスコア[ 0 ].譜面情報.アーティスト名 = boxdef.Artist;
\r
474 c曲リストノード.arスコア[ 0 ].譜面情報.コメント = boxdef.Comment;
\r
475 c曲リストノード.arスコア[ 0 ].譜面情報.Preimage = boxdef.Preimage;
\r
476 c曲リストノード.arスコア[ 0 ].譜面情報.Premovie = boxdef.Premovie;
\r
477 c曲リストノード.arスコア[ 0 ].譜面情報.Presound = boxdef.Presound;
\r
478 c曲リストノード.r親ノード = node親;
\r
480 c曲リストノード.strBreadcrumbs = ( c曲リストノード.r親ノード == null ) ?
\r
481 c曲リストノード.strタイトル : c曲リストノード.r親ノード.strBreadcrumbs + " > " + c曲リストノード.strタイトル;
\r
484 c曲リストノード.list子リスト = new List<C曲リストノード>();
\r
485 c曲リストノード.nPerfect範囲ms = boxdef.PerfectRange;
\r
486 c曲リストノード.nGreat範囲ms = boxdef.GreatRange;
\r
487 c曲リストノード.nGood範囲ms = boxdef.GoodRange;
\r
488 c曲リストノード.nPoor範囲ms = boxdef.PoorRange;
\r
489 listノードリスト.Add( c曲リストノード );
\r
490 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
492 Trace.TraceInformation( "box.def検出 : {0}", infoDir.FullName + @"\box.def" );
\r
496 StringBuilder sb = new StringBuilder( 0x400 );
\r
497 sb.Append( string.Format( "nID#{0:D3}", c曲リストノード.nID ) );
\r
498 if( c曲リストノード.r親ノード != null )
\r
500 sb.Append( string.Format( "(in#{0:D3}):", c曲リストノード.r親ノード.nID ) );
\r
504 sb.Append( "(onRoot):" );
\r
506 sb.Append( "BOX, Title=" + c曲リストノード.strタイトル );
\r
507 if( ( c曲リストノード.strジャンル != null ) && ( c曲リストノード.strジャンル.Length > 0 ) )
\r
509 sb.Append( ", Genre=" + c曲リストノード.strジャンル );
\r
511 if( ( c曲リストノード.arスコア[ 0 ].譜面情報.アーティスト名 != null ) && ( c曲リストノード.arスコア[ 0 ].譜面情報.アーティスト名.Length > 0 ) )
\r
513 sb.Append( ", Artist=" + c曲リストノード.arスコア[ 0 ].譜面情報.アーティスト名 );
\r
515 if( ( c曲リストノード.arスコア[ 0 ].譜面情報.コメント != null ) && ( c曲リストノード.arスコア[ 0 ].譜面情報.コメント.Length > 0 ) )
\r
517 sb.Append( ", Comment=" + c曲リストノード.arスコア[ 0 ].譜面情報.コメント );
\r
519 if( ( c曲リストノード.arスコア[ 0 ].譜面情報.Preimage != null ) && ( c曲リストノード.arスコア[ 0 ].譜面情報.Preimage.Length > 0 ) )
\r
521 sb.Append( ", Preimage=" + c曲リストノード.arスコア[ 0 ].譜面情報.Preimage );
\r
523 if( ( c曲リストノード.arスコア[ 0 ].譜面情報.Premovie != null ) && ( c曲リストノード.arスコア[ 0 ].譜面情報.Premovie.Length > 0 ) )
\r
525 sb.Append( ", Premovie=" + c曲リストノード.arスコア[ 0 ].譜面情報.Premovie );
\r
527 if( ( c曲リストノード.arスコア[ 0 ].譜面情報.Presound != null ) && ( c曲リストノード.arスコア[ 0 ].譜面情報.Presound.Length > 0 ) )
\r
529 sb.Append( ", Presound=" + c曲リストノード.arスコア[ 0 ].譜面情報.Presound );
\r
531 if( c曲リストノード.col文字色 != ColorTranslator.FromHtml( "White" ) )
\r
533 sb.Append( ", FontColor=" + c曲リストノード.col文字色 );
\r
535 if( c曲リストノード.nPerfect範囲ms != -1 )
\r
537 sb.Append( ", Perfect=" + c曲リストノード.nPerfect範囲ms + "ms" );
\r
539 if( c曲リストノード.nGreat範囲ms != -1 )
\r
541 sb.Append( ", Great=" + c曲リストノード.nGreat範囲ms + "ms" );
\r
543 if( c曲リストノード.nGood範囲ms != -1 )
\r
545 sb.Append( ", Good=" + c曲リストノード.nGood範囲ms + "ms" );
\r
547 if( c曲リストノード.nPoor範囲ms != -1 )
\r
549 sb.Append( ", Poor=" + c曲リストノード.nPoor範囲ms + "ms" );
\r
551 Trace.TraceInformation( sb.ToString() );
\r
560 this.t曲を検索してリストを作成する( infoDir.FullName + @"\", b子BOXへ再帰する, c曲リストノード.list子リスト, c曲リストノード );
\r
563 //-----------------------------
\r
566 #region [ c.通常フォルダの場合 ]
\r
567 //-----------------------------
\r
570 this.t曲を検索してリストを作成する( infoDir.FullName + @"\", b子BOXへ再帰する, listノードリスト, node親 );
\r
572 //-----------------------------
\r
576 //-----------------
\r
578 #region [ スコアキャッシュを曲リストに反映する ]
\r
579 //-----------------
\r
580 public void tスコアキャッシュを曲リストに反映する()
\r
582 this.nスコアキャッシュから反映できたスコア数 = 0;
\r
583 this.tスコアキャッシュを曲リストに反映する( this.list曲ルート );
\r
585 private void tスコアキャッシュを曲リストに反映する( List<C曲リストノード> ノードリスト )
\r
587 using( List<C曲リストノード>.Enumerator enumerator = ノードリスト.GetEnumerator() )
\r
589 while( enumerator.MoveNext() )
\r
591 SlowOrSuspendSearchTask(); // #27060 中断要求があったら、解除要求が来るまで待機, #PREMOVIE再生中は検索負荷を落とす
\r
593 C曲リストノード node = enumerator.Current;
\r
594 if( node.eノード種別 == C曲リストノード.Eノード種別.BOX )
\r
596 this.tスコアキャッシュを曲リストに反映する( node.list子リスト );
\r
598 else if( ( node.eノード種別 == C曲リストノード.Eノード種別.SCORE ) || ( node.eノード種別 == C曲リストノード.Eノード種別.SCORE_MIDI ) )
\r
600 Predicate<Cスコア> match = null;
\r
601 for( int lv = 0; lv < 5; lv++ )
\r
603 if( node.arスコア[ lv ] != null )
\r
605 if( match == null )
\r
607 match = delegate( Cスコア sc )
\r
611 ( sc.ファイル情報.ファイルの絶対パス.Equals( node.arスコア[ lv ].ファイル情報.ファイルの絶対パス )
\r
612 && sc.ファイル情報.ファイルサイズ.Equals( node.arスコア[ lv ].ファイル情報.ファイルサイズ ) )
\r
613 && ( sc.ファイル情報.最終更新日時.Equals( node.arスコア[ lv ].ファイル情報.最終更新日時 )
\r
614 && sc.ScoreIni情報.ファイルサイズ.Equals( node.arスコア[ lv ].ScoreIni情報.ファイルサイズ ) ) )
\r
615 && sc.ScoreIni情報.最終更新日時.Equals( node.arスコア[ lv ].ScoreIni情報.最終更新日時 );
\r
618 int nMatched = this.listSongsDB.FindIndex( match );
\r
619 if( nMatched == -1 )
\r
621 //Trace.TraceInformation( "songs.db に存在しません。({0})", node.arスコア[ lv ].ファイル情報.ファイルの絶対パス );
\r
622 if ( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
624 Trace.TraceInformation( "songs.db に存在しません。({0})", node.arスコア[ lv ].ファイル情報.ファイルの絶対パス );
\r
629 node.arスコア[ lv ].譜面情報 = this.listSongsDB[ nMatched ].譜面情報;
\r
630 node.arスコア[ lv ].bSongDBにキャッシュがあった = true;
\r
631 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
633 Trace.TraceInformation( "songs.db から転記しました。({0})", node.arスコア[ lv ].ファイル情報.ファイルの絶対パス );
\r
635 this.nスコアキャッシュから反映できたスコア数++;
\r
636 if( node.arスコア[ lv ].ScoreIni情報.最終更新日時 != this.listSongsDB[ nMatched ].ScoreIni情報.最終更新日時 )
\r
638 string strFileNameScoreIni = node.arスコア[ lv ].ファイル情報.ファイルの絶対パス + ".score.ini";
\r
641 CScoreIni scoreIni = new CScoreIni( strFileNameScoreIni );
\r
642 scoreIni.t全演奏記録セクションの整合性をチェックし不整合があればリセットする();
\r
643 for( int i = 0; i < 3; i++ )
\r
645 int nSectionHiSkill = ( i * 2 ) + 1;
\r
646 if( scoreIni.stセクション[ nSectionHiSkill ].b演奏にMIDI入力を使用した
\r
647 || scoreIni.stセクション[ nSectionHiSkill ].b演奏にキーボードを使用した
\r
648 || scoreIni.stセクション[ nSectionHiSkill ].b演奏にジョイパッドを使用した
\r
649 || scoreIni.stセクション[ nSectionHiSkill ].b演奏にマウスを使用した )
\r
651 node.arスコア[ lv ].譜面情報.最大ランク[ i ] =
\r
652 (scoreIni.stファイル.BestRank[i] != (int)CScoreIni.ERANK.UNKNOWN)?
\r
653 (int)scoreIni.stファイル.BestRank[i] : CScoreIni.tランク値を計算して返す( scoreIni.stセクション[ nSectionHiSkill ] );
\r
657 node.arスコア[ lv ].譜面情報.最大ランク[ i ] = (int)CScoreIni.ERANK.UNKNOWN;
\r
659 node.arスコア[ lv ].譜面情報.最大スキル[ i ] = scoreIni.stセクション[ nSectionHiSkill ].db演奏型スキル値;
\r
660 node.arスコア[ lv ].譜面情報.フルコンボ[ i ] = scoreIni.stセクション[ nSectionHiSkill ].bフルコンボである;
\r
662 node.arスコア[ lv ].譜面情報.演奏回数.Drums = scoreIni.stファイル.PlayCountDrums;
\r
663 node.arスコア[ lv ].譜面情報.演奏回数.Guitar = scoreIni.stファイル.PlayCountGuitar;
\r
664 node.arスコア[ lv ].譜面情報.演奏回数.Bass = scoreIni.stファイル.PlayCountBass;
\r
665 for( int j = 0; j < 5; j++ )
\r
667 node.arスコア[ lv ].譜面情報.演奏履歴[ j ] = scoreIni.stファイル.History[ j ];
\r
669 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
671 Trace.TraceInformation( "演奏記録ファイルから HiSkill 情報と演奏履歴を取得しました。({0})", strFileNameScoreIni );
\r
676 Trace.TraceError( "演奏記録ファイルの読み込みに失敗しました。({0})", strFileNameScoreIni );
\r
686 private Cスコア tSongsDBからスコアを1つ読み込む( BinaryReader br )
\r
688 Cスコア cスコア = new Cスコア();
\r
689 cスコア.ファイル情報.ファイルの絶対パス = br.ReadString();
\r
690 cスコア.ファイル情報.フォルダの絶対パス = br.ReadString();
\r
691 cスコア.ファイル情報.最終更新日時 = new DateTime( br.ReadInt64() );
\r
692 cスコア.ファイル情報.ファイルサイズ = br.ReadInt64();
\r
693 cスコア.ScoreIni情報.最終更新日時 = new DateTime( br.ReadInt64() );
\r
694 cスコア.ScoreIni情報.ファイルサイズ = br.ReadInt64();
\r
695 cスコア.譜面情報.タイトル = br.ReadString();
\r
696 cスコア.譜面情報.アーティスト名 = br.ReadString();
\r
697 cスコア.譜面情報.コメント = br.ReadString();
\r
698 cスコア.譜面情報.ジャンル = br.ReadString();
\r
699 cスコア.譜面情報.Preimage = br.ReadString();
\r
700 cスコア.譜面情報.Premovie = br.ReadString();
\r
701 cスコア.譜面情報.Presound = br.ReadString();
\r
702 cスコア.譜面情報.Backgound = br.ReadString();
\r
703 cスコア.譜面情報.レベル.Drums = br.ReadInt32();
\r
704 cスコア.譜面情報.レベル.Guitar = br.ReadInt32();
\r
705 cスコア.譜面情報.レベル.Bass = br.ReadInt32();
\r
706 cスコア.譜面情報.最大ランク.Drums = br.ReadInt32();
\r
707 cスコア.譜面情報.最大ランク.Guitar = br.ReadInt32();
\r
708 cスコア.譜面情報.最大ランク.Bass = br.ReadInt32();
\r
709 cスコア.譜面情報.最大スキル.Drums = br.ReadDouble();
\r
710 cスコア.譜面情報.最大スキル.Guitar = br.ReadDouble();
\r
711 cスコア.譜面情報.最大スキル.Bass = br.ReadDouble();
\r
712 cスコア.譜面情報.フルコンボ.Drums = br.ReadBoolean();
\r
713 cスコア.譜面情報.フルコンボ.Guitar = br.ReadBoolean();
\r
714 cスコア.譜面情報.フルコンボ.Bass = br.ReadBoolean();
\r
715 cスコア.譜面情報.演奏回数.Drums = br.ReadInt32();
\r
716 cスコア.譜面情報.演奏回数.Guitar = br.ReadInt32();
\r
717 cスコア.譜面情報.演奏回数.Bass = br.ReadInt32();
\r
718 cスコア.譜面情報.演奏履歴.行1 = br.ReadString();
\r
719 cスコア.譜面情報.演奏履歴.行2 = br.ReadString();
\r
720 cスコア.譜面情報.演奏履歴.行3 = br.ReadString();
\r
721 cスコア.譜面情報.演奏履歴.行4 = br.ReadString();
\r
722 cスコア.譜面情報.演奏履歴.行5 = br.ReadString();
\r
723 cスコア.譜面情報.レベルを非表示にする = br.ReadBoolean();
\r
724 cスコア.譜面情報.曲種別 = (CDTX.E種別) br.ReadInt32();
\r
725 // cスコア.譜面情報.bpm = br.ReadDouble();
\r
727 //Debug.WriteLine( "songs.db: " + cスコア.ファイル情報.ファイルの絶対パス );
\r
730 //-----------------
\r
732 #region [ SongsDBになかった曲をファイルから読み込んで反映する ]
\r
733 //-----------------
\r
734 public void tSongsDBになかった曲をファイルから読み込んで反映する()
\r
736 this.nファイルから反映できたスコア数 = 0;
\r
737 this.tSongsDBになかった曲をファイルから読み込んで反映する( this.list曲ルート );
\r
739 private void tSongsDBになかった曲をファイルから読み込んで反映する( List<C曲リストノード> ノードリスト )
\r
741 foreach( C曲リストノード c曲リストノード in ノードリスト )
\r
743 SlowOrSuspendSearchTask(); // #27060 中断要求があったら、解除要求が来るまで待機, #PREMOVIE再生中は検索負荷を落とす
\r
745 if( c曲リストノード.eノード種別 == C曲リストノード.Eノード種別.BOX )
\r
747 this.tSongsDBになかった曲をファイルから読み込んで反映する( c曲リストノード.list子リスト );
\r
749 else if( ( c曲リストノード.eノード種別 == C曲リストノード.Eノード種別.SCORE )
\r
750 || ( c曲リストノード.eノード種別 == C曲リストノード.Eノード種別.SCORE_MIDI ) )
\r
752 for( int i = 0; i < 5; i++ )
\r
754 if( ( c曲リストノード.arスコア[ i ] != null ) && !c曲リストノード.arスコア[ i ].bSongDBにキャッシュがあった )
\r
756 #region [ DTX ファイルのヘッダだけ読み込み、Cスコア.譜面情報 を設定する ]
\r
757 //-----------------
\r
758 string path = c曲リストノード.arスコア[ i ].ファイル情報.ファイルの絶対パス;
\r
759 if( File.Exists( path ) )
\r
763 CDTX cdtx = new CDTX( c曲リストノード.arスコア[ i ].ファイル情報.ファイルの絶対パス, true );
\r
764 c曲リストノード.arスコア[ i ].譜面情報.タイトル = cdtx.TITLE;
\r
765 c曲リストノード.arスコア[ i ].譜面情報.アーティスト名 = cdtx.ARTIST;
\r
766 c曲リストノード.arスコア[ i ].譜面情報.コメント = cdtx.COMMENT;
\r
767 c曲リストノード.arスコア[ i ].譜面情報.ジャンル = cdtx.GENRE;
\r
768 c曲リストノード.arスコア[ i ].譜面情報.Preimage = cdtx.PREIMAGE;
\r
769 c曲リストノード.arスコア[ i ].譜面情報.Premovie = cdtx.PREMOVIE;
\r
770 c曲リストノード.arスコア[ i ].譜面情報.Presound = cdtx.PREVIEW;
\r
771 c曲リストノード.arスコア[ i ].譜面情報.Backgound = ( ( cdtx.BACKGROUND != null ) && ( cdtx.BACKGROUND.Length > 0 ) ) ? cdtx.BACKGROUND : cdtx.BACKGROUND_GR;
\r
772 c曲リストノード.arスコア[ i ].譜面情報.レベル.Drums = cdtx.LEVEL.Drums;
\r
773 c曲リストノード.arスコア[ i ].譜面情報.レベル.Guitar = cdtx.LEVEL.Guitar;
\r
774 c曲リストノード.arスコア[ i ].譜面情報.レベル.Bass = cdtx.LEVEL.Bass;
\r
775 c曲リストノード.arスコア[ i ].譜面情報.レベルを非表示にする = cdtx.HIDDENLEVEL;
\r
776 c曲リストノード.arスコア[ i ].譜面情報.曲種別 = cdtx.e種別;
\r
777 // c曲リストノード.arスコア[ i ].譜面情報.bpm = cdtx.BPM;
\r
778 this.nファイルから反映できたスコア数++;
\r
780 //Debug.WriteLine( "★" + this.nファイルから反映できたスコア数 + " " + c曲リストノード.arスコア[ i ].譜面情報.タイトル );
\r
781 #region [ 曲検索ログ出力 ]
\r
782 //-----------------
\r
783 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
785 StringBuilder sb = new StringBuilder( 0x400 );
\r
786 sb.Append( string.Format( "曲データファイルから譜面情報を転記しました。({0})", path ) );
\r
787 sb.Append( "(title=" + c曲リストノード.arスコア[ i ].譜面情報.タイトル );
\r
788 sb.Append( ", artist=" + c曲リストノード.arスコア[ i ].譜面情報.アーティスト名 );
\r
789 sb.Append( ", comment=" + c曲リストノード.arスコア[ i ].譜面情報.コメント );
\r
790 sb.Append( ", genre=" + c曲リストノード.arスコア[ i ].譜面情報.ジャンル );
\r
791 sb.Append( ", preimage=" + c曲リストノード.arスコア[ i ].譜面情報.Preimage );
\r
792 sb.Append( ", premovie=" + c曲リストノード.arスコア[ i ].譜面情報.Premovie );
\r
793 sb.Append( ", presound=" + c曲リストノード.arスコア[ i ].譜面情報.Presound );
\r
794 sb.Append( ", background=" + c曲リストノード.arスコア[ i ].譜面情報.Backgound );
\r
795 sb.Append( ", lvDr=" + c曲リストノード.arスコア[ i ].譜面情報.レベル.Drums );
\r
796 sb.Append( ", lvGt=" + c曲リストノード.arスコア[ i ].譜面情報.レベル.Guitar );
\r
797 sb.Append( ", lvBs=" + c曲リストノード.arスコア[ i ].譜面情報.レベル.Bass );
\r
798 sb.Append( ", lvHide=" + c曲リストノード.arスコア[ i ].譜面情報.レベルを非表示にする );
\r
799 sb.Append( ", type=" + c曲リストノード.arスコア[ i ].譜面情報.曲種別 );
\r
800 // builder.Append( ", bpm=" + c曲リストノード.arスコア[ i ].譜面情報.bpm );
\r
801 Trace.TraceInformation( sb.ToString() );
\r
803 //-----------------
\r
806 catch( Exception exception )
\r
808 Trace.TraceError( exception.Message );
\r
809 c曲リストノード.arスコア[ i ] = null;
\r
812 Trace.TraceError( "曲データファイルの読み込みに失敗しました。({0})", path );
\r
815 //-----------------
\r
818 #region [ 対応する .score.ini が存在していれば読み込み、Cスコア.譜面情報 に追加設定する ]
\r
819 //-----------------
\r
820 this.tScoreIniを読み込んで譜面情報を設定する( c曲リストノード.arスコア[ i ].ファイル情報.ファイルの絶対パス + ".score.ini", ref c曲リストノード.arスコア[ i ] );
\r
821 //-----------------
\r
828 //-----------------
\r
830 #region [ 曲リストへ後処理を適用する ]
\r
831 //-----------------
\r
832 public void t曲リストへ後処理を適用する()
\r
834 this.t曲リストへ後処理を適用する( this.list曲ルート );
\r
836 private void t曲リストへ後処理を適用する( List<C曲リストノード> ノードリスト )
\r
838 #region [ リストに1つ以上の曲があるなら RANDOM BOX を入れる ]
\r
839 //-----------------------------
\r
840 if( ノードリスト.Count > 0 )
\r
842 C曲リストノード itemRandom = new C曲リストノード();
\r
843 itemRandom.eノード種別 = C曲リストノード.Eノード種別.RANDOM;
\r
844 itemRandom.strタイトル = "< RANDOM SELECT >";
\r
845 itemRandom.nスコア数 = 5;
\r
846 itemRandom.r親ノード = ノードリスト[ 0 ].r親ノード;
\r
848 itemRandom.strBreadcrumbs = ( itemRandom.r親ノード == null ) ?
\r
849 itemRandom.strタイトル : itemRandom.r親ノード.strBreadcrumbs + " > " + itemRandom.strタイトル;
\r
851 for( int i = 0; i < 5; i++ )
\r
853 itemRandom.arスコア[ i ] = new Cスコア();
\r
854 itemRandom.arスコア[ i ].譜面情報.タイトル = string.Format( "< RANDOM SELECT Lv.{0} >", i + 1 );
\r
855 itemRandom.arスコア[i].譜面情報.コメント =
\r
856 (CultureInfo.CurrentCulture.TwoLetterISOLanguageName == "ja") ?
\r
857 string.Format("難易度レベル {0} 付近の曲をランダムに選択します。難易度レベルを持たない曲も選択候補となります。", i + 1) :
\r
858 string.Format("Random select from the songs which has the level about L{0}. Non-leveled songs may also selected.", i + 1);
\r
859 itemRandom.ar難易度ラベル[ i ] = string.Format( "L{0}", i + 1 );
\r
861 ノードリスト.Add( itemRandom );
\r
864 //-----------------------------
\r
865 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
867 StringBuilder sb = new StringBuilder( 0x100 );
\r
868 sb.Append( string.Format( "nID#{0:D3}", itemRandom.nID ) );
\r
869 if( itemRandom.r親ノード != null )
\r
871 sb.Append( string.Format( "(in#{0:D3}):", itemRandom.r親ノード.nID ) );
\r
875 sb.Append( "(onRoot):" );
\r
877 sb.Append( " RANDOM" );
\r
878 Trace.TraceInformation( sb.ToString() );
\r
880 //-----------------------------
\r
883 //-----------------------------
\r
887 foreach( C曲リストノード c曲リストノード in ノードリスト )
\r
889 SlowOrSuspendSearchTask(); // #27060 中断要求があったら、解除要求が来るまで待機, #PREMOVIE再生中は検索負荷を落とす
\r
891 #region [ BOXノードなら子リストに <<BACK を入れ、子リストに後処理を適用する ]
\r
892 //-----------------------------
\r
893 if( c曲リストノード.eノード種別 == C曲リストノード.Eノード種別.BOX )
\r
895 C曲リストノード itemBack = new C曲リストノード();
\r
896 itemBack.eノード種別 = C曲リストノード.Eノード種別.BACKBOX;
\r
897 itemBack.strタイトル = "<< BACK";
\r
898 itemBack.nスコア数 = 1;
\r
899 itemBack.r親ノード = c曲リストノード;
\r
901 itemBack.strBreadcrumbs = ( itemBack.r親ノード == null ) ?
\r
902 itemBack.strタイトル : itemBack.r親ノード.strBreadcrumbs + " > " + itemBack.strタイトル;
\r
904 itemBack.arスコア[ 0 ] = new Cスコア();
\r
905 itemBack.arスコア[ 0 ].ファイル情報.フォルダの絶対パス = "";
\r
906 itemBack.arスコア[ 0 ].譜面情報.タイトル = itemBack.strタイトル;
\r
907 itemBack.arスコア[ 0 ].譜面情報.コメント =
\r
908 (CultureInfo.CurrentCulture.TwoLetterISOLanguageName == "ja") ?
\r
910 "Exit from the BOX.";
\r
911 c曲リストノード.list子リスト.Insert( 0, itemBack );
\r
914 //-----------------------------
\r
915 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
917 StringBuilder sb = new StringBuilder( 0x100 );
\r
918 sb.Append( string.Format( "nID#{0:D3}", itemBack.nID ) );
\r
919 if( itemBack.r親ノード != null )
\r
921 sb.Append( string.Format( "(in#{0:D3}):", itemBack.r親ノード.nID ) );
\r
925 sb.Append( "(onRoot):" );
\r
927 sb.Append( " BACKBOX" );
\r
928 Trace.TraceInformation( sb.ToString() );
\r
930 //-----------------------------
\r
933 this.t曲リストへ後処理を適用する( c曲リストノード.list子リスト );
\r
936 //-----------------------------
\r
939 #region [ ノードにタイトルがないなら、最初に見つけたスコアのタイトルを設定する ]
\r
940 //-----------------------------
\r
941 if( string.IsNullOrEmpty( c曲リストノード.strタイトル ) )
\r
943 for( int j = 0; j < 5; j++ )
\r
945 if( ( c曲リストノード.arスコア[ j ] != null ) && !string.IsNullOrEmpty( c曲リストノード.arスコア[ j ].譜面情報.タイトル ) )
\r
947 c曲リストノード.strタイトル = c曲リストノード.arスコア[ j ].譜面情報.タイトル;
\r
949 if( CDTXMania.ConfigIni.bLog曲検索ログ出力 )
\r
950 Trace.TraceInformation( "タイトルを設定しました。(nID#{0:D3}, title={1})", c曲リストノード.nID, c曲リストノード.strタイトル );
\r
956 //-----------------------------
\r
960 #region [ ノードをソートする ]
\r
961 //-----------------------------
\r
962 this.t曲リストのソート1_絶対パス順( ノードリスト );
\r
963 //-----------------------------
\r
966 //-----------------
\r
968 #region [ スコアキャッシュをSongsDBに出力する ]
\r
969 //-----------------
\r
970 public void tスコアキャッシュをSongsDBに出力する( string SongsDBファイル名 )
\r
972 this.nSongsDBへ出力できたスコア数 = 0;
\r
975 BinaryWriter bw = new BinaryWriter( new FileStream( SongsDBファイル名, FileMode.Create, FileAccess.Write ) );
\r
976 bw.Write( SONGSDB_VERSION );
\r
977 this.tSongsDBにリストを1つ出力する( bw, this.list曲ルート );
\r
982 Trace.TraceError( "songs.dbの出力に失敗しました。" );
\r
985 private void tSongsDBにノードを1つ出力する( BinaryWriter bw, C曲リストノード node )
\r
987 for( int i = 0; i < 5; i++ )
\r
989 // ここではsuspendに応じないようにしておく(深い意味はない。ファイルの書き込みオープン状態を長時間維持したくないだけ)
\r
990 //if ( this.bIsSuspending ) // #27060 中断要求があったら、解除要求が来るまで待機
\r
992 // autoReset.WaitOne();
\r
995 if( node.arスコア[ i ] != null )
\r
997 bw.Write( node.arスコア[ i ].ファイル情報.ファイルの絶対パス );
\r
998 bw.Write( node.arスコア[ i ].ファイル情報.フォルダの絶対パス );
\r
999 bw.Write( node.arスコア[ i ].ファイル情報.最終更新日時.Ticks );
\r
1000 bw.Write( node.arスコア[ i ].ファイル情報.ファイルサイズ );
\r
1001 bw.Write( node.arスコア[ i ].ScoreIni情報.最終更新日時.Ticks );
\r
1002 bw.Write( node.arスコア[ i ].ScoreIni情報.ファイルサイズ );
\r
1003 bw.Write( node.arスコア[ i ].譜面情報.タイトル );
\r
1004 bw.Write( node.arスコア[ i ].譜面情報.アーティスト名 );
\r
1005 bw.Write( node.arスコア[ i ].譜面情報.コメント );
\r
1006 bw.Write( node.arスコア[ i ].譜面情報.ジャンル );
\r
1007 bw.Write( node.arスコア[ i ].譜面情報.Preimage );
\r
1008 bw.Write( node.arスコア[ i ].譜面情報.Premovie );
\r
1009 bw.Write( node.arスコア[ i ].譜面情報.Presound );
\r
1010 bw.Write( node.arスコア[ i ].譜面情報.Backgound );
\r
1011 bw.Write( node.arスコア[ i ].譜面情報.レベル.Drums );
\r
1012 bw.Write( node.arスコア[ i ].譜面情報.レベル.Guitar );
\r
1013 bw.Write( node.arスコア[ i ].譜面情報.レベル.Bass );
\r
1014 bw.Write( node.arスコア[ i ].譜面情報.最大ランク.Drums );
\r
1015 bw.Write( node.arスコア[ i ].譜面情報.最大ランク.Guitar );
\r
1016 bw.Write( node.arスコア[ i ].譜面情報.最大ランク.Bass );
\r
1017 bw.Write( node.arスコア[ i ].譜面情報.最大スキル.Drums );
\r
1018 bw.Write( node.arスコア[ i ].譜面情報.最大スキル.Guitar );
\r
1019 bw.Write( node.arスコア[ i ].譜面情報.最大スキル.Bass );
\r
1020 bw.Write( node.arスコア[ i ].譜面情報.フルコンボ.Drums );
\r
1021 bw.Write( node.arスコア[ i ].譜面情報.フルコンボ.Guitar );
\r
1022 bw.Write( node.arスコア[ i ].譜面情報.フルコンボ.Bass );
\r
1023 bw.Write( node.arスコア[ i ].譜面情報.演奏回数.Drums );
\r
1024 bw.Write( node.arスコア[ i ].譜面情報.演奏回数.Guitar );
\r
1025 bw.Write( node.arスコア[ i ].譜面情報.演奏回数.Bass );
\r
1026 bw.Write( node.arスコア[ i ].譜面情報.演奏履歴.行1 );
\r
1027 bw.Write( node.arスコア[ i ].譜面情報.演奏履歴.行2 );
\r
1028 bw.Write( node.arスコア[ i ].譜面情報.演奏履歴.行3 );
\r
1029 bw.Write( node.arスコア[ i ].譜面情報.演奏履歴.行4 );
\r
1030 bw.Write( node.arスコア[ i ].譜面情報.演奏履歴.行5 );
\r
1031 bw.Write( node.arスコア[ i ].譜面情報.レベルを非表示にする );
\r
1032 bw.Write( (int) node.arスコア[ i ].譜面情報.曲種別 );
\r
1033 // bw.Write( node.arスコア[ i ].譜面情報.bpm );
\r
1034 this.nSongsDBへ出力できたスコア数++;
\r
1038 private void tSongsDBにリストを1つ出力する( BinaryWriter bw, List<C曲リストノード> list )
\r
1040 foreach( C曲リストノード c曲リストノード in list )
\r
1042 if( ( c曲リストノード.eノード種別 == C曲リストノード.Eノード種別.SCORE )
\r
1043 || ( c曲リストノード.eノード種別 == C曲リストノード.Eノード種別.SCORE_MIDI ) )
\r
1045 this.tSongsDBにノードを1つ出力する( bw, c曲リストノード );
\r
1047 if( c曲リストノード.list子リスト != null )
\r
1049 this.tSongsDBにリストを1つ出力する( bw, c曲リストノード.list子リスト );
\r
1053 //-----------------
\r
1056 #region [ 曲リストソート ]
\r
1057 //-----------------
\r
1058 public void t曲リストのソート1_絶対パス順( List<C曲リストノード> ノードリスト )
\r
1060 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1067 int num = this.t比較0_共通( n1, n2 );
\r
1072 if( ( n1.eノード種別 == C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 == C曲リストノード.Eノード種別.BOX ) )
\r
1074 return n1.arスコア[ 0 ].ファイル情報.フォルダの絶対パス.CompareTo( n2.arスコア[ 0 ].ファイル情報.フォルダの絶対パス );
\r
1078 if( string.IsNullOrEmpty( n1.pathSetDefの絶対パス ) )
\r
1080 for( int i = 0; i < 5; i++ )
\r
1082 if( n1.arスコア[ i ] != null )
\r
1084 str = n1.arスコア[ i ].ファイル情報.ファイルの絶対パス;
\r
1095 str = n1.pathSetDefの絶対パス + n1.SetDefのブロック番号.ToString( "00" );
\r
1098 if( string.IsNullOrEmpty( n2.pathSetDefの絶対パス ) )
\r
1100 for( int j = 0; j < 5; j++ )
\r
1102 if( n2.arスコア[ j ] != null )
\r
1104 strB = n2.arスコア[ j ].ファイル情報.ファイルの絶対パス;
\r
1105 if( strB == null )
\r
1115 strB = n2.pathSetDefの絶対パス + n2.SetDefのブロック番号.ToString( "00" );
\r
1117 return str.CompareTo( strB );
\r
1119 foreach( C曲リストノード c曲リストノード in ノードリスト )
\r
1121 if( ( c曲リストノード.list子リスト != null ) && ( c曲リストノード.list子リスト.Count > 1 ) )
\r
1123 this.t曲リストのソート1_絶対パス順( c曲リストノード.list子リスト );
\r
1127 public void t曲リストのソート2_タイトル順( List<C曲リストノード> ノードリスト, E楽器パート part, int order, params object[] p )
\r
1129 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1135 int num = this.t比較0_共通( n1, n2 );
\r
1138 return order * num;
\r
1140 return order * n1.strタイトル.CompareTo( n2.strタイトル );
\r
1142 // foreach( C曲リストノード c曲リストノード in ノードリスト )
\r
1144 // if( ( c曲リストノード.list子リスト != null ) && ( c曲リストノード.list子リスト.Count > 1 ) )
\r
1146 // this.t曲リストのソート2_タイトル順( c曲リストノード.list子リスト, part, order );
\r
1153 /// <param name="ノードリスト"></param>
\r
1154 /// <param name="part"></param>
\r
1155 /// <param name="order">1=Ascend -1=Descend</param>
\r
1156 public void t曲リストのソート3_演奏回数の多い順( List<C曲リストノード> ノードリスト, E楽器パート part, int order, params object[] p )
\r
1159 int nL12345 = (int) p[ 0 ];
\r
1160 if ( part != E楽器パート.UNKNOWN )
\r
1162 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1169 int num = this.t比較0_共通( n1, n2 );
\r
1172 return order * num;
\r
1174 if( ( n1.eノード種別 == C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 == C曲リストノード.Eノード種別.BOX ) )
\r
1176 return order * n1.arスコア[ 0 ].ファイル情報.フォルダの絶対パス.CompareTo( n2.arスコア[ 0 ].ファイル情報.フォルダの絶対パス );
\r
1179 int nSumPlayCountN1 = 0, nSumPlayCountN2 = 0;
\r
1180 // for( int i = 0; i < 5; i++ )
\r
1182 if( n1.arスコア[ nL12345 ] != null )
\r
1184 nSumPlayCountN1 += n1.arスコア[ nL12345 ].譜面情報.演奏回数[ (int) part ];
\r
1186 if( n2.arスコア[ nL12345 ] != null )
\r
1188 nSumPlayCountN2 += n2.arスコア[ nL12345 ].譜面情報.演奏回数[ (int) part ];
\r
1191 num = nSumPlayCountN2 - nSumPlayCountN1;
\r
1194 return order * num;
\r
1196 return order * n1.strタイトル.CompareTo( n2.strタイトル );
\r
1198 foreach ( C曲リストノード c曲リストノード in ノードリスト )
\r
1200 int nSumPlayCountN1 = 0;
\r
1201 // for ( int i = 0; i < 5; i++ )
\r
1203 if ( c曲リストノード.arスコア[ nL12345 ] != null )
\r
1205 nSumPlayCountN1 += c曲リストノード.arスコア[ nL12345 ].譜面情報.演奏回数[ (int) part ];
\r
1208 // Debug.WriteLine( nSumPlayCountN1 + ":" + c曲リストノード.strタイトル );
\r
1211 // foreach( C曲リストノード c曲リストノード in ノードリスト )
\r
1213 // if( ( c曲リストノード.list子リスト != null ) && ( c曲リストノード.list子リスト.Count > 1 ) )
\r
1215 // this.t曲リストのソート3_演奏回数の多い順( c曲リストノード.list子リスト, part );
\r
1220 public void t曲リストのソート4_LEVEL順( List<C曲リストノード> ノードリスト, E楽器パート part, int order, params object[] p )
\r
1223 int nL12345 = (int)p[ 0 ];
\r
1224 if ( part != E楽器パート.UNKNOWN )
\r
1226 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1233 int num = this.t比較0_共通( n1, n2 );
\r
1236 return order * num;
\r
1238 if ( ( n1.eノード種別 == C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 == C曲リストノード.Eノード種別.BOX ) )
\r
1240 return order * n1.arスコア[ 0 ].ファイル情報.フォルダの絶対パス.CompareTo( n2.arスコア[ 0 ].ファイル情報.フォルダの絶対パス );
\r
1243 int nSumPlayCountN1 = 0, nSumPlayCountN2 = 0;
\r
1244 if ( n1.arスコア[ nL12345 ] != null )
\r
1246 nSumPlayCountN1 = n1.arスコア[ nL12345 ].譜面情報.レベル[ (int) part ];
\r
1248 if ( n2.arスコア[ nL12345 ] != null )
\r
1250 nSumPlayCountN2 = n2.arスコア[ nL12345 ].譜面情報.レベル[ (int) part ];
\r
1252 num = nSumPlayCountN2 - nSumPlayCountN1;
\r
1255 return order * num;
\r
1257 return order * n1.strタイトル.CompareTo( n2.strタイトル );
\r
1259 foreach ( C曲リストノード c曲リストノード in ノードリスト )
\r
1261 int nSumPlayCountN1 = 0;
\r
1262 if ( c曲リストノード.arスコア[ nL12345 ] != null )
\r
1264 nSumPlayCountN1 = c曲リストノード.arスコア[ nL12345 ].譜面情報.レベル[ (int) part ];
\r
1266 // Debug.WriteLine( nSumPlayCountN1 + ":" + c曲リストノード.strタイトル );
\r
1270 public void t曲リストのソート5_BestRank順( List<C曲リストノード> ノードリスト, E楽器パート part, int order, params object[] p )
\r
1273 int nL12345 = (int) p[ 0 ];
\r
1274 if ( part != E楽器パート.UNKNOWN )
\r
1276 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1283 int num = this.t比較0_共通( n1, n2 );
\r
1286 return order * num;
\r
1288 if ( ( n1.eノード種別 == C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 == C曲リストノード.Eノード種別.BOX ) )
\r
1290 return order * n1.arスコア[ 0 ].ファイル情報.フォルダの絶対パス.CompareTo( n2.arスコア[ 0 ].ファイル情報.フォルダの絶対パス );
\r
1293 int nSumPlayCountN1 = 0, nSumPlayCountN2 = 0;
\r
1294 bool isFullCombo1 = false, isFullCombo2 = false;
\r
1295 if ( n1.arスコア[ nL12345 ] != null )
\r
1297 isFullCombo1 = n1.arスコア[ nL12345 ].譜面情報.フルコンボ[ (int) part ];
\r
1298 nSumPlayCountN1 = n1.arスコア[ nL12345 ].譜面情報.最大ランク[ (int) part ];
\r
1300 if ( n2.arスコア[ nL12345 ] != null )
\r
1302 isFullCombo2 = n2.arスコア[ nL12345 ].譜面情報.フルコンボ[ (int) part ];
\r
1303 nSumPlayCountN2 = n2.arスコア[ nL12345 ].譜面情報.最大ランク[ (int) part ];
\r
1305 if ( isFullCombo1 ^ isFullCombo2 )
\r
1307 if ( isFullCombo1 ) return order; else return -order;
\r
1309 num = nSumPlayCountN2 - nSumPlayCountN1;
\r
1312 return order * num;
\r
1314 return order * n1.strタイトル.CompareTo( n2.strタイトル );
\r
1316 foreach ( C曲リストノード c曲リストノード in ノードリスト )
\r
1318 int nSumPlayCountN1 = 0;
\r
1319 if ( c曲リストノード.arスコア[ nL12345 ] != null )
\r
1321 nSumPlayCountN1 = c曲リストノード.arスコア[ nL12345 ].譜面情報.最大ランク[ (int) part ];
\r
1323 // Debug.WriteLine( nSumPlayCountN1 + ":" + c曲リストノード.strタイトル );
\r
1327 public void t曲リストのソート6_SkillPoint順( List<C曲リストノード> ノードリスト, E楽器パート part, int order, params object[] p )
\r
1330 int nL12345 = (int) p[ 0 ];
\r
1331 if ( part != E楽器パート.UNKNOWN )
\r
1333 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1340 int num = this.t比較0_共通( n1, n2 );
\r
1343 return order * num;
\r
1345 if ( ( n1.eノード種別 == C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 == C曲リストノード.Eノード種別.BOX ) )
\r
1347 return order * n1.arスコア[ 0 ].ファイル情報.フォルダの絶対パス.CompareTo( n2.arスコア[ 0 ].ファイル情報.フォルダの絶対パス );
\r
1350 double nSumPlayCountN1 = 0, nSumPlayCountN2 = 0;
\r
1351 if ( n1.arスコア[ nL12345 ] != null )
\r
1353 nSumPlayCountN1 = n1.arスコア[ nL12345 ].譜面情報.最大スキル[ (int) part ];
\r
1355 if ( n2.arスコア[ nL12345 ] != null )
\r
1357 nSumPlayCountN2 = n2.arスコア[ nL12345 ].譜面情報.最大スキル[ (int) part ];
\r
1359 double d = nSumPlayCountN2 - nSumPlayCountN1;
\r
1362 return order * System.Math.Sign(d);
\r
1364 return order * n1.strタイトル.CompareTo( n2.strタイトル );
\r
1366 foreach ( C曲リストノード c曲リストノード in ノードリスト )
\r
1368 double nSumPlayCountN1 = 0;
\r
1369 if ( c曲リストノード.arスコア[ nL12345 ] != null )
\r
1371 nSumPlayCountN1 = c曲リストノード.arスコア[ nL12345 ].譜面情報.最大スキル[ (int) part ];
\r
1373 // Debug.WriteLine( nSumPlayCountN1 + ":" + c曲リストノード.strタイトル );
\r
1377 public void t曲リストのソート7_更新日時順( List<C曲リストノード> ノードリスト, E楽器パート part, int order, params object[] p )
\r
1379 int nL12345 = (int) p[ 0 ];
\r
1380 if ( part != E楽器パート.UNKNOWN )
\r
1382 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1389 int num = this.t比較0_共通( n1, n2 );
\r
1392 return order * num;
\r
1394 if ( ( n1.eノード種別 == C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 == C曲リストノード.Eノード種別.BOX ) )
\r
1396 return order * n1.arスコア[ 0 ].ファイル情報.フォルダの絶対パス.CompareTo( n2.arスコア[ 0 ].ファイル情報.フォルダの絶対パス );
\r
1399 DateTime nSumPlayCountN1 = DateTime.Parse("0001/01/01 12:00:01.000");
\r
1400 DateTime nSumPlayCountN2 = DateTime.Parse("0001/01/01 12:00:01.000");
\r
1401 if ( n1.arスコア[ nL12345 ] != null )
\r
1403 nSumPlayCountN1 = n1.arスコア[ nL12345 ].ファイル情報.最終更新日時;
\r
1405 if ( n2.arスコア[ nL12345 ] != null )
\r
1407 nSumPlayCountN2 = n2.arスコア[ nL12345 ].ファイル情報.最終更新日時;
\r
1409 int d = nSumPlayCountN1.CompareTo(nSumPlayCountN2);
\r
1412 return order * System.Math.Sign( d );
\r
1414 return order * n1.strタイトル.CompareTo( n2.strタイトル );
\r
1416 foreach ( C曲リストノード c曲リストノード in ノードリスト )
\r
1418 DateTime nSumPlayCountN1 = DateTime.Parse( "0001/01/01 12:00:01.000" );
\r
1419 if ( c曲リストノード.arスコア[ nL12345 ] != null )
\r
1421 nSumPlayCountN1 = c曲リストノード.arスコア[ nL12345 ].ファイル情報.最終更新日時;
\r
1423 // Debug.WriteLine( nSumPlayCountN1 + ":" + c曲リストノード.strタイトル );
\r
1427 public void t曲リストのソート8_アーティスト名順( List<C曲リストノード> ノードリスト, E楽器パート part, int order, params object[] p )
\r
1429 int nL12345 = (int) p[ 0 ];
\r
1430 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1436 int num = this.t比較0_共通( n1, n2 );
\r
1439 return order * System.Math.Sign( num );
\r
1441 string strAuthorN1 = "";
\r
1442 string strAuthorN2 = "";
\r
1443 if (n1.arスコア[ nL12345 ] != null ) {
\r
1444 strAuthorN1 = n1.arスコア[ nL12345 ].譜面情報.アーティスト名;
\r
1446 if ( n2.arスコア[ nL12345 ] != null )
\r
1448 strAuthorN2 = n2.arスコア[ nL12345 ].譜面情報.アーティスト名;
\r
1451 return order * strAuthorN1.CompareTo( strAuthorN2 );
\r
1453 foreach ( C曲リストノード c曲リストノード in ノードリスト )
\r
1456 if ( c曲リストノード.arスコア[ nL12345 ] != null )
\r
1458 s = c曲リストノード.arスコア[ nL12345 ].譜面情報.アーティスト名;
\r
1460 Debug.WriteLine( s + ":" + c曲リストノード.strタイトル );
\r
1464 public void t曲リストのソート9_BPM順( List<C曲リストノード> ノードリスト, E楽器パート part, int order, params object[] p )
\r
1467 int nL12345 = (int) p[ 0 ];
\r
1468 if ( part != E楽器パート.UNKNOWN )
\r
1470 ノードリスト.Sort( delegate( C曲リストノード n1, C曲リストノード n2 )
\r
1477 int num = this.t比較0_共通( n1, n2 );
\r
1480 return order * num;
\r
1482 if ( ( n1.eノード種別 == C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 == C曲リストノード.Eノード種別.BOX ) )
\r
1484 return order * n1.arスコア[ 0 ].ファイル情報.フォルダの絶対パス.CompareTo( n2.arスコア[ 0 ].ファイル情報.フォルダの絶対パス );
\r
1487 double dBPMn1 = 0.0, dBPMn2 = 0.0;
\r
1488 if ( n1.arスコア[ nL12345 ] != null )
\r
1490 dBPMn1 = n1.arスコア[ nL12345 ].譜面情報.bpm;
\r
1492 if ( n2.arスコア[ nL12345 ] != null )
\r
1494 dBPMn2 = n2.arスコア[ nL12345 ].譜面情報.bpm;
\r
1496 double d = dBPMn1- dBPMn2;
\r
1499 return order * System.Math.Sign( d );
\r
1501 return order * n1.strタイトル.CompareTo( n2.strタイトル );
\r
1503 foreach ( C曲リストノード c曲リストノード in ノードリスト )
\r
1506 if ( c曲リストノード.arスコア[ nL12345 ] != null )
\r
1508 dBPM = c曲リストノード.arスコア[ nL12345 ].譜面情報.bpm;
\r
1510 Debug.WriteLine( dBPM + ":" + c曲リストノード.strタイトル );
\r
1515 //-----------------
\r
1517 #region [ .score.ini を読み込んで Cスコア.譜面情報に設定する ]
\r
1518 //-----------------
\r
1519 public void tScoreIniを読み込んで譜面情報を設定する( string strScoreIniファイルパス, ref Cスコア score )
\r
1521 if( !File.Exists( strScoreIniファイルパス ) )
\r
1526 var ini = new CScoreIni( strScoreIniファイルパス );
\r
1527 ini.t全演奏記録セクションの整合性をチェックし不整合があればリセットする();
\r
1529 for( int n楽器番号 = 0; n楽器番号 < 3; n楽器番号++ )
\r
1531 int n = ( n楽器番号 * 2 ) + 1; // n = 0~5
\r
1533 #region socre.譜面情報.最大ランク[ n楽器番号 ] = ...
\r
1534 //-----------------
\r
1535 if( ini.stセクション[ n ].b演奏にMIDI入力を使用した ||
\r
1536 ini.stセクション[ n ].b演奏にキーボードを使用した ||
\r
1537 ini.stセクション[ n ].b演奏にジョイパッドを使用した ||
\r
1538 ini.stセクション[ n ].b演奏にマウスを使用した )
\r
1540 // (A) 全オートじゃないようなので、演奏結果情報を有効としてランクを算出する。
\r
1542 score.譜面情報.最大ランク[ n楽器番号 ] =
\r
1543 CScoreIni.tランク値を計算して返す(
\r
1544 ini.stセクション[ n ].n全チップ数,
\r
1545 ini.stセクション[ n ].nPerfect数,
\r
1546 ini.stセクション[ n ].nGreat数,
\r
1547 ini.stセクション[ n ].nGood数,
\r
1548 ini.stセクション[ n ].nPoor数,
\r
1549 ini.stセクション[ n ].nMiss数 );
\r
1553 // (B) 全オートらしいので、ランクは無効とする。
\r
1555 score.譜面情報.最大ランク[ n楽器番号 ] = (int) CScoreIni.ERANK.UNKNOWN;
\r
1557 //-----------------
\r
1559 score.譜面情報.最大スキル[ n楽器番号 ] = ini.stセクション[ n ].db演奏型スキル値;
\r
1560 score.譜面情報.フルコンボ[ n楽器番号 ] = ini.stセクション[ n ].bフルコンボである;
\r
1562 score.譜面情報.演奏回数.Drums = ini.stファイル.PlayCountDrums;
\r
1563 score.譜面情報.演奏回数.Guitar = ini.stファイル.PlayCountGuitar;
\r
1564 score.譜面情報.演奏回数.Bass = ini.stファイル.PlayCountBass;
\r
1565 for( int i = 0; i < 5; i++ )
\r
1566 score.譜面情報.演奏履歴[ i ] = ini.stファイル.History[ i ];
\r
1570 Trace.TraceError( "演奏記録ファイルの読み込みに失敗しました。[{0}]", strScoreIniファイルパス );
\r
1573 //-----------------
\r
1579 #region [ private ]
\r
1580 //-----------------
\r
1581 private const string SONGSDB_VERSION = "SongsDB2";
\r
1583 private int t比較0_共通( C曲リストノード n1, C曲リストノード n2 )
\r
1585 if( n1.eノード種別 == C曲リストノード.Eノード種別.BACKBOX )
\r
1589 if( n2.eノード種別 == C曲リストノード.Eノード種別.BACKBOX )
\r
1593 if( n1.eノード種別 == C曲リストノード.Eノード種別.RANDOM )
\r
1597 if( n2.eノード種別 == C曲リストノード.Eノード種別.RANDOM )
\r
1601 if( ( n1.eノード種別 == C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 != C曲リストノード.Eノード種別.BOX ) )
\r
1605 if( ( n1.eノード種別 != C曲リストノード.Eノード種別.BOX ) && ( n2.eノード種別 == C曲リストノード.Eノード種別.BOX ) )
\r
1613 /// 検索を中断・スローダウンする
\r
1615 private void SlowOrSuspendSearchTask()
\r
1617 if ( this.bIsSuspending ) // #27060 中断要求があったら、解除要求が来るまで待機
\r
1619 autoReset.WaitOne();
\r
1621 if ( this.bIsSlowdown && ++this.searchCount > 10 ) // #27060 #PREMOVIE再生中は検索負荷を下げる
\r
1623 Thread.Sleep( 100 );
\r
1624 this.searchCount = 0;
\r
1628 //-----------------
\r