C# (dotnetcore)で標準出力を利用して進行中のスピナーを作る (3)
前回の記事
前回見つけた矛盾を修正する
前回見つけた矛盾、 Value設定後に、Maximum、Minimumに値を設定すると不整合になる可能性を潰す。
- Maximumを設定した際に、Maximum < Valueの場合、ValueにMaximumを設定
- Minimumを設定した際に、Minimum > Valueの場合、ValueにMinimumを設定
プロパティのセッターを修正
private int minimum = 0; /// <summary>コントロールの範囲の最小値を取得または設定します。</summary> public int Minimum { get { return minimum; } set { if (value < 0) throw new ArgumentException("プロパティに対して指定された値が 0 未満です。"); minimum = value; if (this.minimum > this.value) { this.value = this.minimum; } } } private int maximum = 100; /// <summary>コントロールの範囲の最大値を取得または設定します。</summary> public int Maximum { get { return maximum; } set { if (value < 0) throw new ArgumentException("プロパティに対して指定された値が 0 未満です。"); maximum = value; if (this.maximum < this.value) { this.value = this.maximum; } } }
テスト追加
[Fact] public void MinimumSetTest() { ConsoleProgressSpiner c = new ConsoleProgressSpiner(); c.Value = 10; Assert.Equal(10, c.Value); c.Minimum = 20; Assert.Equal(20, c.Minimum); Assert.Equal(20, c.Value); } [Fact] public void MaximumSetTest() { ConsoleProgressSpiner c = new ConsoleProgressSpiner(); c.Value = 90; Assert.Equal(90, c.Value); c.Maximum = 80; Assert.Equal(80, c.Maximum); Assert.Equal(80, c.Value); }
スピナーの出力部分の実装
少しいまいち感が拭えないが、第1回のソースを元に、エイヤーで移植。
/// <summary>描画</summary> private void update() { if (this.Maximum == this.Value) { //色を戻す Console.ResetColor(); //カーソル位置を変更 Console.SetCursorPosition(0, Console.CursorTop); //終了の表示 Console.WriteLine("Done! "); } else { decimal oneMeter = new decimal(100) / (this.Maximum - this.Minimum); int nowIndex = Decimal.ToInt32(oneMeter * (this.Value - this.Minimum)); //色変更 Console.ForegroundColor = ConsoleColor.Green; Console.BackgroundColor = ConsoleColor.Black; //アニメーションの表示 Console.Write(bars[nowIndex % bars.Length]); //進捗率の表示 Console.Write("{0, 3:d0}%", nowIndex); //カーソル位置を変更 Console.SetCursorPosition(0, Console.CursorTop); //色を戻す Console.ResetColor(); } }
この部品を利用する箇所の実装
class Program { static void Main(string[] args) { ConsoleProgressSpiner progressSpiner = new ConsoleProgressSpiner(); progressSpiner.Minimum = 0; progressSpiner.Maximum = 1000; progressSpiner.Value = 0; for(int i = progressSpiner.Minimum; i <= progressSpiner.Maximum; i++) { progressSpiner.Value = i; //一時停止 System.Threading.Thread.Sleep(10); } } }
課題
- Consoleへの操作部分のテストをどうするか。(Moqの利用? DIの利用?)
- updateメソッドの分解(メソッドが長い)
ひとまず。ここまで。続きは次回。