2 using System.Collections.Generic;
3 using System.Diagnostics;
14 public string 名前 { get; set; } = null;
16 public bool Rideは左 { get; set; } = false;
17 public bool Chinaは左 { get; set; } = false;
18 public bool Splashは左 { get; set; } = true;
20 public class Cヒット範囲sec
22 public const double Perfect既定値 = 0.034;
23 public double Perfect = Perfect既定値;
25 public const double Great既定値 = 0.067;
26 public double Great = Great既定値;
28 public const double Good既定値 = 0.084;
29 public double Good = Good既定値;
31 public const double Poor既定値 = 0.117;
32 public double Poor = Poor既定値;
34 public Cヒット範囲sec ヒット範囲sec { get; } = new Cヒット範囲sec();
36 public class CAutoPlay
38 public bool LeftCrash = false;
39 public bool Ride = false;
40 public bool China = false;
41 public bool Splash = false;
42 public bool HiHat = false;
43 public bool Snare = false;
44 public bool Bass = false;
45 public bool Tom1 = false;
46 public bool Tom2 = false;
47 public bool Tom3 = false;
48 public bool RightCrash = false;
50 public CAutoPlay AutoPlay { get; } = new CAutoPlay();
52 public double 譜面スクロール速度の倍率 { get; set; } = 1.0;
55 /// ビュアーモードでログインしているユーザの場合、RootNode の子Nodeはゼロである。
57 public SST.曲.RootNode 曲ツリーのルートノード { get; } = new 曲.RootNode();
59 /// ビュアーモードでログインしているユーザの場合は空リスト。
61 public List<string> 曲の検索元フォルダパスのリスト { get; } = new List<string>();
68 public ユーザ( string 名前 )
73 public bool チップが自動演奏である( SSTFormat.チップ種別 chipType )
77 case SSTFormat.チップ種別.LeftCrash:
78 case SSTFormat.チップ種別.LeftCymbal_Mute:
79 return this.AutoPlay.LeftCrash;
81 case SSTFormat.チップ種別.Ride:
82 case SSTFormat.チップ種別.Ride_Cup:
83 return ( this.Rideは左 ) ? this.AutoPlay.LeftCrash : this.AutoPlay.RightCrash;
85 case SSTFormat.チップ種別.China:
86 return ( this.Chinaは左 ) ? this.AutoPlay.LeftCrash : this.AutoPlay.RightCrash;
88 case SSTFormat.チップ種別.Splash:
89 return ( this.Splashは左 ) ? this.AutoPlay.LeftCrash : this.AutoPlay.RightCrash;
91 case SSTFormat.チップ種別.HiHat_Open:
92 case SSTFormat.チップ種別.HiHat_HalfOpen:
93 case SSTFormat.チップ種別.HiHat_Close:
94 case SSTFormat.チップ種別.HiHat_Foot:
95 return this.AutoPlay.HiHat;
97 case SSTFormat.チップ種別.Snare:
98 case SSTFormat.チップ種別.Snare_OpenRim:
99 case SSTFormat.チップ種別.Snare_ClosedRim:
100 case SSTFormat.チップ種別.Snare_Ghost:
101 return this.AutoPlay.Snare;
103 case SSTFormat.チップ種別.Bass:
104 return this.AutoPlay.Bass;
106 case SSTFormat.チップ種別.Tom1:
107 case SSTFormat.チップ種別.Tom1_Rim:
108 return this.AutoPlay.Tom1;
110 case SSTFormat.チップ種別.Tom2:
111 case SSTFormat.チップ種別.Tom2_Rim:
112 return this.AutoPlay.Tom2;
114 case SSTFormat.チップ種別.Tom3:
115 case SSTFormat.チップ種別.Tom3_Rim:
116 return this.AutoPlay.Tom3;
118 case SSTFormat.チップ種別.RightCrash:
119 case SSTFormat.チップ種別.RightCymbal_Mute:
120 return this.AutoPlay.RightCrash;
122 case SSTFormat.チップ種別.背景動画:
123 return true; // 常にAutoPlay
129 public void チップの自動演奏を一括設定する( bool 設定値 )
131 this.AutoPlay.LeftCrash =
133 this.AutoPlay.China =
134 this.AutoPlay.Splash =
135 this.AutoPlay.HiHat =
136 this.AutoPlay.Snare =
141 this.AutoPlay.RightCrash = 設定値;
144 public void ユーザをXML要素で出力する( XElement 親要素 )
146 // <user name="..." />...</user>
147 var user = new XElement( nameof( XML.User ), new XAttribute( nameof( XML.Name ), this.名前 ) );
151 new XElement( nameof( XML.RidePosition ), this.Rideは左 ? nameof( XML.Left ) : nameof( XML.Right ) ),
152 new XElement( nameof( XML.ChinaPosition ), this.Chinaは左 ? nameof( XML.Left ) : nameof( XML.Right ) ),
153 new XElement( nameof( XML.SplashPosition ), this.Splashは左 ? nameof( XML.Left ) : nameof( XML.Right ) ),
155 new XElement( nameof( XML.ScrollSpeedRate ), this.譜面スクロール速度の倍率 ),
157 new XElement( nameof( XML.Range ),
158 new XElement( nameof( XML.Perfect ), this.ヒット範囲sec.Perfect ),
159 new XElement( nameof( XML.Great ), this.ヒット範囲sec.Great ),
160 new XElement( nameof( XML.Good ), this.ヒット範囲sec.Good ),
161 new XElement( nameof( XML.Poor ), this.ヒット範囲sec.Poor ) ),
163 new XElement( nameof( XML.AutoPlay ),
164 new XElement( nameof( XML.LeftCrash ), this.AutoPlay.LeftCrash ),
165 new XElement( nameof( XML.Ride ), this.AutoPlay.Ride ),
166 new XElement( nameof( XML.China ), this.AutoPlay.China ),
167 new XElement( nameof( XML.Splash ), this.AutoPlay.Splash ),
168 new XElement( nameof( XML.HiHat ), this.AutoPlay.HiHat ),
169 new XElement( nameof( XML.Snare ), this.AutoPlay.Snare ),
170 new XElement( nameof( XML.Bass ), this.AutoPlay.Bass ),
171 new XElement( nameof( XML.Tom1 ), this.AutoPlay.Tom1 ),
172 new XElement( nameof( XML.Tom2 ), this.AutoPlay.Tom2 ),
173 new XElement( nameof( XML.Tom3 ), this.AutoPlay.Tom3 ),
174 new XElement( nameof( XML.RightCrash ), this.AutoPlay.RightCrash ) )
179 public void ユーザをXML要素から読み込む( XElement 読込対象要素 )
185 if( 読込対象要素.Name.LocalName.ToLower() == nameof( XML.User ).ToLower() )
190 var name属性 = user要素.Attribute( nameof( XML.Name ) );
193 var msg = $"{nameof( XML.User )} タグに {nameof( XML.Name )} 属性が見つかりません。";
194 FDK.Log.ERROR( msg );
195 throw new SSTException( msg );
197 this.名前 = name属性.Value;
201 #region " <RidePosition> "
205 this.Rideは左 = ( user要素.Element( nameof( XML.RidePosition ) )?.Value ?? nameof( XML.Right ) ) == nameof( XML.Left ); // 規定値は Right
209 FDK.Log.ERROR( $"<{XML.User}>.<{XML.RidePosition}> の読み込みに失敗しました。{e.Message}" );
210 this.Rideは左 = false; // 既定値は Right
214 #region " <ChinaPosition> "
218 this.Chinaは左 = ( user要素.Element( nameof( XML.ChinaPosition ) )?.Value ?? nameof( XML.Right ) ) == nameof( XML.Left ); // 規定値は Right
222 FDK.Log.ERROR( $"<{XML.User}>.<{XML.ChinaPosition}> の読み込みに失敗しました。{e.Message}" );
223 this.Chinaは左 = false; // 既定値は Right
227 #region " <SplashPosition> "
231 this.Splashは左 = ( user要素.Element( nameof( XML.SplashPosition ) )?.Value ?? nameof( XML.Left ) ) == nameof( XML.Left ); // 規定値は Left
235 FDK.Log.ERROR( $"<{XML.User}>.<{XML.SplashPosition}> の読み込みに失敗しました。{e.Message}" );
236 this.Splashは左 = true; // 既定値は Left
243 var range要素 = user要素.Element( nameof( XML.Range ) );
244 if( null != range要素 )
246 #region " <Perfect> "
250 this.ヒット範囲sec.Perfect = (double) range要素.Element( nameof( XML.Perfect ) );
254 FDK.Log.ERROR( $"<{XML.User}>.<{XML.Range}>.<{XML.Perfect}> の読み込みに失敗しました。{e.Message}" );
255 this.ヒット範囲sec.Perfect = Cヒット範囲sec.Perfect既定値;
263 this.ヒット範囲sec.Great = (double) range要素.Element( nameof( XML.Great ) );
267 FDK.Log.ERROR( $"<{XML.User}>.<{XML.Range}>.<{XML.Great}> の読み込みに失敗しました。{e.Message}" );
268 this.ヒット範囲sec.Great = Cヒット範囲sec.Great既定値;
276 this.ヒット範囲sec.Good = (double) range要素.Element( nameof( XML.Good ) );
280 FDK.Log.ERROR( $"<{XML.User}>.<{XML.Range}>.<{XML.Good}> の読み込みに失敗しました。{e.Message}" );
281 this.ヒット範囲sec.Good = Cヒット範囲sec.Good既定値;
289 this.ヒット範囲sec.Poor = (double) range要素.Element( nameof( XML.Poor ) );
293 FDK.Log.ERROR( $"<{XML.User}>.<{XML.Range}>.<{XML.Poor}> の読み込みに失敗しました。{e.Message}" );
294 this.ヒット範囲sec.Poor = Cヒット範囲sec.Poor既定値;
301 #region " <AutoPlay> "
303 var autoPlay要素 = user要素.Element( nameof( XML.AutoPlay ) );
304 if( null != autoPlay要素 )
306 #region " <LeftCrash> "
310 this.AutoPlay.LeftCrash = (bool) autoPlay要素.Element( nameof( XML.LeftCrash ) );
314 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.LeftCrash}> の読み込みに失敗しました。{e.Message}" );
315 this.AutoPlay.LeftCrash = false;
323 this.AutoPlay.Ride = (bool) autoPlay要素.Element( nameof( XML.Ride ) );
327 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Ride}> の読み込みに失敗しました。{e.Message}" );
328 this.AutoPlay.Ride = false;
336 this.AutoPlay.China = (bool) autoPlay要素.Element( nameof( XML.China ) );
340 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.China}> の読み込みに失敗しました。{e.Message}" );
341 this.AutoPlay.China = false;
349 this.AutoPlay.Splash = (bool) autoPlay要素.Element( nameof( XML.Splash ) );
353 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Splash}> の読み込みに失敗しました。{e.Message}" );
354 this.AutoPlay.Splash = false;
362 this.AutoPlay.HiHat = (bool) autoPlay要素.Element( nameof( XML.HiHat ) );
366 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.HiHat}> の読み込みに失敗しました。{e.Message}" );
367 this.AutoPlay.HiHat = false;
375 this.AutoPlay.Snare = (bool) autoPlay要素.Element( nameof( XML.Snare ) );
379 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Snare}> の読み込みに失敗しました。{e.Message}" );
380 this.AutoPlay.Snare = false;
388 this.AutoPlay.Bass = (bool) autoPlay要素.Element( nameof( XML.Bass ) );
392 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Bass}> の読み込みに失敗しました。{e.Message}" );
393 this.AutoPlay.Bass = false;
401 this.AutoPlay.Tom1 = (bool) autoPlay要素.Element( nameof( XML.Tom1 ) );
405 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Tom1}> の読み込みに失敗しました。{e.Message}" );
406 this.AutoPlay.Tom1 = false;
414 this.AutoPlay.Tom2 = (bool) autoPlay要素.Element( nameof( XML.Tom2 ) );
418 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Tom2}> の読み込みに失敗しました。{e.Message}" );
419 this.AutoPlay.Tom2 = false;
427 this.AutoPlay.Tom3 = (bool) autoPlay要素.Element( nameof( XML.Tom3 ) );
431 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Tom3}> の読み込みに失敗しました。{e.Message}" );
432 this.AutoPlay.Tom3 = false;
436 #region " <RightCrash> "
440 this.AutoPlay.RightCrash = (bool) autoPlay要素.Element( nameof( XML.RightCrash ) );
444 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.RightCrash}> の読み込みに失敗しました。{e.Message}" );
445 this.AutoPlay.RightCrash = false;
453 #region " <ScrollSpeedRate> "
457 this.譜面スクロール速度の倍率 = (double) user要素.Element( nameof( XML.ScrollSpeedRate ) );
461 FDK.Log.ERROR( $"<{XML.User}>.<{XML.ScrollSpeedRate}> の読み込みに失敗しました。{e.Message}" );
462 this.譜面スクロール速度の倍率 = 1.0; // 既定値
469 public void SourcesXmlを保存する()
471 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
473 string ユーザフォルダ名 = StrokeStyleT.フォルダ.UserFolder( this.名前 );
475 // ユーザフォルダが存在しないなら作成する。
476 if( false == Directory.Exists( ユーザフォルダ名 ) )
477 Directory.CreateDirectory( ユーザフォルダ名 );
479 string ファイル名 = Path.Combine( ユーザフォルダ名, this.ソースXmlファイルパス );
480 var xml文書 = new XDocument( new XDeclaration( "1.0", "utf-8", "yes" ) );
483 var Root要素 = new XElement( nameof( XML.Root ) );
486 var Sources要素 = new XElement( nameof( XML.Sources ) );
489 foreach( var path in this.曲の検索元フォルダパスのリスト )
491 var 変数付きフォルダパス = FDK.フォルダ.絶対パスをフォルダ変数付き絶対パスに変換して返す( path );
492 Root要素.Add( new XElement( nameof( XML.Path ), 変数付きフォルダパス ) );
495 Root要素.Add( Sources要素 );
502 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
504 public void SourcesXmlを読み込む()
506 FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
509 this.曲の検索元フォルダパスのリスト.Clear();
511 string ファイル名 = Path.Combine( StrokeStyleT.フォルダ.UserFolder( this.名前 ), this.ソースXmlファイルパス );
513 if( false == File.Exists( ファイル名 ) )
515 FDK.Log.WARNING( $"ソースファイルが存在しません。作成します。[{this.ソースXmlファイルパス}]" );
516 this.SourcesXmlを保存する(); // ファイルがなかったら新規に作成。中身は空。
522 var xml文書 = XDocument.Load( ファイル名 );
525 var Root要素 = xml文書.Element( nameof( XML.Root ) );
528 foreach( var Sources要素 in Root要素.Elements( nameof( XML.Sources ) ) )
530 foreach( var Sourcesの子要素 in Sources要素.Elements() )
532 switch( Sourcesの子要素.Name.LocalName )
535 case nameof( XML.Path ):
536 this.曲の検索元フォルダパスのリスト.Add( FDK.フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( Sourcesの子要素.Value ) );
543 // 曲の検索元フォルダパスが1つもなかったら、exe のあるフォルダを既定値として追加する。
544 if( 0 == this.曲の検索元フォルダパスのリスト.Count )
545 this.曲の検索元フォルダパスのリスト.Add( FDK.フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( @"$(Static)\" ) );
549 FDK.Log.ERROR( $"ソースファイルの読み込みに失敗しました。{e.Message}[{this.ソースXmlファイルパス}]" );
552 FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
555 protected readonly string ソースXmlファイルパス = @"Sources.xml";