OSDN Git Service

曲ツリーの構築機能を ユーザ クラスから分離。
[strokestylet/CsWin10Desktop3.git] / StrokeStyleT / ユーザ / ユーザ.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Linq;
6 using System.Xml.Linq;
7
8 namespace SST.ユーザ
9 {
10         public class ユーザ
11         {
12                 // プロパティ
13
14                 public string 名前 { get; set; } = null;
15
16                 public bool Rideは左 { get; set; } = false;
17                 public bool Chinaは左 { get; set; } = false;
18                 public bool Splashは左 { get; set; } = true;
19
20                 public class Cヒット範囲sec
21                 {
22                         public const double Perfect既定値 = 0.034;
23                         public double Perfect = Perfect既定値;
24
25                         public const double Great既定値 = 0.067;
26                         public double Great = Great既定値;
27
28                         public const double Good既定値 = 0.084;
29                         public double Good = Good既定値;
30
31                         public const double Poor既定値 = 0.117;
32                         public double Poor = Poor既定値;
33                 }
34                 public Cヒット範囲sec ヒット範囲sec { get; } = new Cヒット範囲sec();
35
36                 public class CAutoPlay
37                 {
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;
49                 }
50                 public CAutoPlay AutoPlay { get; } = new CAutoPlay();
51
52                 public double 譜面スクロール速度の倍率 { get; set; } = 1.0;
53
54                 /// <summary>
55                 /// ビュアーモードでログインしているユーザの場合、RootNode の子Nodeはゼロである。
56                 /// </summary>
57                 public SST.曲.RootNode 曲ツリーのルートノード { get; } = new 曲.RootNode();
58                 /// <summary>
59                 /// ビュアーモードでログインしているユーザの場合は空リスト。
60                 /// </summary>
61                 public List<string> 曲の検索元フォルダパスのリスト { get; } = new List<string>();
62
63                 // メソッド
64
65                 public ユーザ()
66                 {
67                 }
68                 public ユーザ( string 名前 )
69                 {
70                         this.名前 = 名前;
71                 }
72
73                 public bool チップが自動演奏である( SSTFormat.チップ種別 chipType )
74                 {
75                         switch( chipType )
76                         {
77                                 case SSTFormat.チップ種別.LeftCrash:
78                                 case SSTFormat.チップ種別.LeftCymbal_Mute:
79                                         return this.AutoPlay.LeftCrash;
80
81                                 case SSTFormat.チップ種別.Ride:
82                                 case SSTFormat.チップ種別.Ride_Cup:
83                                         return ( this.Rideは左 ) ? this.AutoPlay.LeftCrash : this.AutoPlay.RightCrash;
84
85                                 case SSTFormat.チップ種別.China:
86                                         return ( this.Chinaは左 ) ? this.AutoPlay.LeftCrash : this.AutoPlay.RightCrash;
87
88                                 case SSTFormat.チップ種別.Splash:
89                                         return ( this.Splashは左 ) ? this.AutoPlay.LeftCrash : this.AutoPlay.RightCrash;
90
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;
96
97                                 case SSTFormat.チップ種別.Snare:
98                                 case SSTFormat.チップ種別.Snare_OpenRim:
99                                 case SSTFormat.チップ種別.Snare_ClosedRim:
100                                 case SSTFormat.チップ種別.Snare_Ghost:
101                                         return this.AutoPlay.Snare;
102
103                                 case SSTFormat.チップ種別.Bass:
104                                         return this.AutoPlay.Bass;
105
106                                 case SSTFormat.チップ種別.Tom1:
107                                 case SSTFormat.チップ種別.Tom1_Rim:
108                                         return this.AutoPlay.Tom1;
109
110                                 case SSTFormat.チップ種別.Tom2:
111                                 case SSTFormat.チップ種別.Tom2_Rim:
112                                         return this.AutoPlay.Tom2;
113
114                                 case SSTFormat.チップ種別.Tom3:
115                                 case SSTFormat.チップ種別.Tom3_Rim:
116                                         return this.AutoPlay.Tom3;
117
118                                 case SSTFormat.チップ種別.RightCrash:
119                                 case SSTFormat.チップ種別.RightCymbal_Mute:
120                                         return this.AutoPlay.RightCrash;
121
122                                 case SSTFormat.チップ種別.背景動画:
123                                         return true;    // 常にAutoPlay
124                         }
125
126                         // 上記以外はみな false。
127                         return false;
128                 }
129                 public void チップの自動演奏を一括設定する( bool 設定値 )
130                 {
131                         this.AutoPlay.LeftCrash =
132                                 this.AutoPlay.Ride =
133                                 this.AutoPlay.China =
134                                 this.AutoPlay.Splash =
135                                 this.AutoPlay.HiHat =
136                                 this.AutoPlay.Snare =
137                                 this.AutoPlay.Bass =
138                                 this.AutoPlay.Tom1 =
139                                 this.AutoPlay.Tom2 =
140                                 this.AutoPlay.Tom3 =
141                                 this.AutoPlay.RightCrash = 設定値;
142                 }
143
144                 public void ユーザをXML要素で出力する( XElement 親要素 )
145                 {
146                         // <user name="..." />...</user>
147                         var user = new XElement( nameof( XML.User ), new XAttribute( nameof( XML.Name ), this.名前 ) );
148
149                         // 子要素
150                         user.Add(
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 ) ),
154
155                                 new XElement( nameof( XML.ScrollSpeedRate ), this.譜面スクロール速度の倍率 ),
156
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 ) ),
162
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 ) )
175                         );
176
177                         親要素.Add( user );
178                 }
179                 public void ユーザをXML要素から読み込む( XElement 読込対象要素 )
180                 {
181                         // 初期化する。
182                         this.名前 = null;
183
184                         // <user>
185                         if( 読込対象要素.Name.LocalName.ToLower() == nameof( XML.User ).ToLower() )
186                         {
187                                 var user要素 = 読込対象要素;
188
189                                 // name="..."
190                                 var name属性 = user要素.Attribute( nameof( XML.Name ) );
191                                 if( null == name属性 )
192                                 {
193                                         var msg = $"{nameof( XML.User )} タグに {nameof( XML.Name )} 属性が見つかりません。";
194                                         FDK.Log.ERROR( msg );
195                                         throw new SSTException( msg );
196                                 }
197                                 this.名前 = name属性.Value;
198
199                                 // 子要素。
200
201                                 #region " <RidePosition> "
202                                 //----------------
203                                 try
204                                 {
205                                         this.Rideは左 = ( user要素.Element( nameof( XML.RidePosition ) )?.Value ?? nameof( XML.Right ) ) == nameof( XML.Left ); // 規定値は Right
206                                 }
207                                 catch( Exception e )
208                                 {
209                                         FDK.Log.ERROR( $"<{XML.User}>.<{XML.RidePosition}> の読み込みに失敗しました。{e.Message}" );
210                                         this.Rideは左 = false;    // 既定値は Right
211                                 }
212                                 //----------------
213                                 #endregion
214                                 #region " <ChinaPosition> "
215                                 //----------------
216                                 try
217                                 {
218                                         this.Chinaは左 = ( user要素.Element( nameof( XML.ChinaPosition ) )?.Value ?? nameof( XML.Right ) ) == nameof( XML.Left );   // 規定値は Right
219                                 }
220                                 catch( Exception e )
221                                 {
222                                         FDK.Log.ERROR( $"<{XML.User}>.<{XML.ChinaPosition}> の読み込みに失敗しました。{e.Message}" );
223                                         this.Chinaは左 = false;    // 既定値は Right
224                                 }
225                                 //----------------
226                                 #endregion
227                                 #region " <SplashPosition> "
228                                 //----------------
229                                 try
230                                 {
231                                         this.Splashは左 = ( user要素.Element( nameof( XML.SplashPosition ) )?.Value ?? nameof( XML.Left ) ) == nameof( XML.Left );  // 規定値は Left
232                                 }
233                                 catch( Exception e )
234                                 {
235                                         FDK.Log.ERROR( $"<{XML.User}>.<{XML.SplashPosition}> の読み込みに失敗しました。{e.Message}" );
236                                         this.Splashは左 = true;    // 既定値は Left
237                                 }
238                                 //----------------
239                                 #endregion
240
241                                 #region " <Range> "
242                                 //----------------
243                                 var range要素 = user要素.Element( nameof( XML.Range ) );
244                                 if( null != range要素 )
245                                 {
246                                         #region " <Perfect> "
247                                         //----------------
248                                         try
249                                         {
250                                                 this.ヒット範囲sec.Perfect = (double) range要素.Element( nameof( XML.Perfect ) );
251                                         }
252                                         catch( Exception e )
253                                         {
254                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.Range}>.<{XML.Perfect}> の読み込みに失敗しました。{e.Message}" );
255                                                 this.ヒット範囲sec.Perfect = Cヒット範囲sec.Perfect既定値;
256                                         }
257                                         //----------------
258                                         #endregion
259                                         #region " <Great> "
260                                         //----------------
261                                         try
262                                         {
263                                                 this.ヒット範囲sec.Great = (double) range要素.Element( nameof( XML.Great ) );
264                                         }
265                                         catch( Exception e )
266                                         {
267                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.Range}>.<{XML.Great}> の読み込みに失敗しました。{e.Message}" );
268                                                 this.ヒット範囲sec.Great = Cヒット範囲sec.Great既定値;
269                                         }
270                                         //----------------
271                                         #endregion
272                                         #region " <Good> "
273                                         //----------------
274                                         try
275                                         {
276                                                 this.ヒット範囲sec.Good = (double) range要素.Element( nameof( XML.Good ) );
277                                         }
278                                         catch( Exception e )
279                                         {
280                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.Range}>.<{XML.Good}> の読み込みに失敗しました。{e.Message}" );
281                                                 this.ヒット範囲sec.Good = Cヒット範囲sec.Good既定値;
282                                         }
283                                         //----------------
284                                         #endregion
285                                         #region " <Poor> "
286                                         //----------------
287                                         try
288                                         {
289                                                 this.ヒット範囲sec.Poor = (double) range要素.Element( nameof( XML.Poor ) );
290                                         }
291                                         catch( Exception e )
292                                         {
293                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.Range}>.<{XML.Poor}> の読み込みに失敗しました。{e.Message}" );
294                                                 this.ヒット範囲sec.Poor = Cヒット範囲sec.Poor既定値;
295                                         }
296                                         //----------------
297                                         #endregion
298                                 }
299                                 //----------------
300                                 #endregion
301                                 #region " <AutoPlay> "
302                                 //----------------
303                                 var autoPlay要素 = user要素.Element( nameof( XML.AutoPlay ) );
304                                 if( null != autoPlay要素 )
305                                 {
306                                         #region " <LeftCrash> "
307                                         //----------------
308                                         try
309                                         {
310                                                 this.AutoPlay.LeftCrash = (bool) autoPlay要素.Element( nameof( XML.LeftCrash ) );
311                                         }
312                                         catch( Exception e )
313                                         {
314                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.LeftCrash}> の読み込みに失敗しました。{e.Message}" );
315                                                 this.AutoPlay.LeftCrash = false;
316                                         }
317                                         //----------------
318                                         #endregion
319                                         #region " <Ride> "
320                                         //----------------
321                                         try
322                                         {
323                                                 this.AutoPlay.Ride = (bool) autoPlay要素.Element( nameof( XML.Ride ) );
324                                         }
325                                         catch( Exception e )
326                                         {
327                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Ride}> の読み込みに失敗しました。{e.Message}" );
328                                                 this.AutoPlay.Ride = false;
329                                         }
330                                         //----------------
331                                         #endregion
332                                         #region " <China> "
333                                         //----------------
334                                         try
335                                         {
336                                                 this.AutoPlay.China = (bool) autoPlay要素.Element( nameof( XML.China ) );
337                                         }
338                                         catch( Exception e )
339                                         {
340                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.China}> の読み込みに失敗しました。{e.Message}" );
341                                                 this.AutoPlay.China = false;
342                                         }
343                                         //----------------
344                                         #endregion
345                                         #region " <Splash> "
346                                         //----------------
347                                         try
348                                         {
349                                                 this.AutoPlay.Splash = (bool) autoPlay要素.Element( nameof( XML.Splash ) );
350                                         }
351                                         catch( Exception e )
352                                         {
353                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Splash}> の読み込みに失敗しました。{e.Message}" );
354                                                 this.AutoPlay.Splash = false;
355                                         }
356                                         //----------------
357                                         #endregion
358                                         #region " <HiHat> "
359                                         //----------------
360                                         try
361                                         {
362                                                 this.AutoPlay.HiHat = (bool) autoPlay要素.Element( nameof( XML.HiHat ) );
363                                         }
364                                         catch( Exception e )
365                                         {
366                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.HiHat}> の読み込みに失敗しました。{e.Message}" );
367                                                 this.AutoPlay.HiHat = false;
368                                         }
369                                         //----------------
370                                         #endregion
371                                         #region " <Snare> "
372                                         //----------------
373                                         try
374                                         {
375                                                 this.AutoPlay.Snare = (bool) autoPlay要素.Element( nameof( XML.Snare ) );
376                                         }
377                                         catch( Exception e )
378                                         {
379                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Snare}> の読み込みに失敗しました。{e.Message}" );
380                                                 this.AutoPlay.Snare = false;
381                                         }
382                                         //----------------
383                                         #endregion
384                                         #region " <Bass> "
385                                         //----------------
386                                         try
387                                         {
388                                                 this.AutoPlay.Bass = (bool) autoPlay要素.Element( nameof( XML.Bass ) );
389                                         }
390                                         catch( Exception e )
391                                         {
392                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Bass}> の読み込みに失敗しました。{e.Message}" );
393                                                 this.AutoPlay.Bass = false;
394                                         }
395                                         //----------------
396                                         #endregion
397                                         #region " <Tom1> "
398                                         //----------------
399                                         try
400                                         {
401                                                 this.AutoPlay.Tom1 = (bool) autoPlay要素.Element( nameof( XML.Tom1 ) );
402                                         }
403                                         catch( Exception e )
404                                         {
405                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Tom1}> の読み込みに失敗しました。{e.Message}" );
406                                                 this.AutoPlay.Tom1 = false;
407                                         }
408                                         //----------------
409                                         #endregion
410                                         #region " <Tom2> "
411                                         //----------------
412                                         try
413                                         {
414                                                 this.AutoPlay.Tom2 = (bool) autoPlay要素.Element( nameof( XML.Tom2 ) );
415                                         }
416                                         catch( Exception e )
417                                         {
418                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Tom2}> の読み込みに失敗しました。{e.Message}" );
419                                                 this.AutoPlay.Tom2 = false;
420                                         }
421                                         //----------------
422                                         #endregion
423                                         #region " <Tom3> "
424                                         //----------------
425                                         try
426                                         {
427                                                 this.AutoPlay.Tom3 = (bool) autoPlay要素.Element( nameof( XML.Tom3 ) );
428                                         }
429                                         catch( Exception e )
430                                         {
431                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.Tom3}> の読み込みに失敗しました。{e.Message}" );
432                                                 this.AutoPlay.Tom3 = false;
433                                         }
434                                         //----------------
435                                         #endregion
436                                         #region " <RightCrash> "
437                                         //----------------
438                                         try
439                                         {
440                                                 this.AutoPlay.RightCrash = (bool) autoPlay要素.Element( nameof( XML.RightCrash ) );
441                                         }
442                                         catch( Exception e )
443                                         {
444                                                 FDK.Log.ERROR( $"<{XML.User}>.<{XML.AutoPlay}>.<{XML.RightCrash}> の読み込みに失敗しました。{e.Message}" );
445                                                 this.AutoPlay.RightCrash = false;
446                                         }
447                                         //----------------
448                                         #endregion
449                                 }
450                                 //----------------
451                                 #endregion
452
453                                 #region " <ScrollSpeedRate> "
454                                 //----------------
455                                 try
456                                 {
457                                         this.譜面スクロール速度の倍率 = (double) user要素.Element( nameof( XML.ScrollSpeedRate ) );
458                                 }
459                                 catch( Exception e )
460                                 {
461                                         FDK.Log.ERROR( $"<{XML.User}>.<{XML.ScrollSpeedRate}> の読み込みに失敗しました。{e.Message}" );
462                                         this.譜面スクロール速度の倍率 = 1.0;    // 既定値
463                                 }
464                                 //----------------
465                                 #endregion
466                         }
467                 }
468
469                 public void SourcesXmlを保存する()
470                 {
471                         FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
472
473                         string ユーザフォルダ名 = StrokeStyleT.フォルダ.UserFolder( this.名前 );
474
475                         // ユーザフォルダが存在しないなら作成する。
476                         if( false == Directory.Exists( ユーザフォルダ名 ) )
477                                 Directory.CreateDirectory( ユーザフォルダ名 );
478
479                         string ファイル名 = Path.Combine( ユーザフォルダ名, this.ソースXmlファイルパス );
480                         var xml文書 = new XDocument( new XDeclaration( "1.0", "utf-8", "yes" ) );
481
482                         // <Root>
483                         var Root要素 = new XElement( nameof( XML.Root ) );
484                         {
485                                 // <Sources>
486                                 var Sources要素 = new XElement( nameof( XML.Sources ) );
487                                 {
488                                         // <Path>*
489                                         foreach( var path in this.曲の検索元フォルダパスのリスト )
490                                         {
491                                                 var 変数付きフォルダパス = FDK.フォルダ.絶対パスをフォルダ変数付き絶対パスに変換して返す( path );
492                                                 Root要素.Add( new XElement( nameof( XML.Path ), 変数付きフォルダパス ) );
493                                         }
494                                 }
495                                 Root要素.Add( Sources要素 );
496                         }
497                         xml文書.Add( Root要素 );
498
499                         // ファイルに保存する。
500                         xml文書.Save( ファイル名 );
501
502                         FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
503                 }
504                 public void SourcesXmlを読み込む()
505                 {
506                         FDK.Log.BeginInfo( $"{FDK.Utilities.現在のメソッド名}" );
507
508                         // 初期化する。
509                         this.曲の検索元フォルダパスのリスト.Clear();
510
511                         string ファイル名 = Path.Combine( StrokeStyleT.フォルダ.UserFolder( this.名前 ), this.ソースXmlファイルパス );
512
513                         if( false == File.Exists( ファイル名 ) )
514                         {
515                                 FDK.Log.WARNING( $"ソースファイルが存在しません。作成します。[{this.ソースXmlファイルパス}]" );
516                                 this.SourcesXmlを保存する();    // ファイルがなかったら新規に作成。中身は空。
517                                 return;
518                         }
519
520                         try
521                         {
522                                 var xml文書 = XDocument.Load( ファイル名 );
523
524                                 // <Root>
525                                 var Root要素 = xml文書.Element( nameof( XML.Root ) );
526                                 {
527                                         // <Sources>*
528                                         foreach( var Sources要素 in Root要素.Elements( nameof( XML.Sources ) ) )
529                                         {
530                                                 foreach( var Sourcesの子要素 in Sources要素.Elements() )
531                                                 {
532                                                         switch( Sourcesの子要素.Name.LocalName )
533                                                         {
534                                                                 // <Path>
535                                                                 case nameof( XML.Path ):
536                                                                         this.曲の検索元フォルダパスのリスト.Add( FDK.フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( Sourcesの子要素.Value ) );
537                                                                         break;
538                                                         }
539                                                 }
540                                         }
541                                 }
542
543                                 // 曲の検索元フォルダパスが1つもなかったら、exe のあるフォルダを既定値として追加する。
544                                 if( 0 == this.曲の検索元フォルダパスのリスト.Count )
545                                         this.曲の検索元フォルダパスのリスト.Add( FDK.フォルダ.絶対パスに含まれるフォルダ変数を展開して返す( @"$(Static)\" ) );
546                         }
547                         catch( Exception e )
548                         {
549                                 FDK.Log.ERROR( $"ソースファイルの読み込みに失敗しました。{e.Message}[{this.ソースXmlファイルパス}]" );
550                         }
551
552                         FDK.Log.EndInfo( $"{FDK.Utilities.現在のメソッド名}" );
553                 }
554
555                 protected readonly string ソースXmlファイルパス = @"Sources.xml";
556         }
557 }