C# (dotnetcore)で標準出力を利用して進行中のスピナーを作る (6:完)
Console用のスピナー用の部品を作ろうという連載を初めて6記事目。
Console用のスピナー用の部品の開発は、今回を持って一旦終了とします。
前回の記事
Stepの実装を修正
ProgressBar.Step プロパティ をみても、特に何もしていなさそう。このドキュメントからわかることは、 既定値は 10ということだけか。
private int step = 10; /// <summary>PerformStep() メソッドを呼び出したときに、プログレス バーの現在の位置を進める量を取得または設定します。</summary> public int Step { get { return this.step; } set { this.step = value; } }
Stepのテストを実装
デフォルト値の試験
[Fact] public void StepDefaultTest() { ConsoleProgressSpiner c = new ConsoleProgressSpiner(); Assert.Equal(10, c.Step); }
PerformStep を実装する
PerformStepでは、プロパティから値を設定せず、直接内部の値にインクリメント。
そして、minimumとmaximum の間に治るよう調整してから、updateを実行という流れ。
今回は、Reference Sourceを参考にしました。
/// <summary>プログレス バーの現在位置を Step プロパティの値の分だけ進めます。 </summary> public void PerformStep() { this.value += this.Step; if (this.value < minimum) { this.value = minimum; } if (this.value > maximum) { this.value = maximum; } update(); }
PerformStepのテストを実装
デフォルト値で0~100まで、PerformStepを実行した場合のテストケースを追加しておく。
[Fact] public void PerformStepTest() { var output = new System.IO.StringWriter(); Console.SetOut(output); ConsoleProgressSpiner c = new ConsoleProgressSpiner(); Assert.Equal("", output.ToString()); c.Value = 0; Assert.Equal("⠋ 0%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%⠋ 30%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%⠋ 30%⠋ 40%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%⠋ 30%⠋ 40%⠋ 50%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%⠋ 30%⠋ 40%⠋ 50%⠋ 60%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%⠋ 30%⠋ 40%⠋ 50%⠋ 60%⠋ 70%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%⠋ 30%⠋ 40%⠋ 50%⠋ 60%⠋ 70%⠋ 80%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%⠋ 30%⠋ 40%⠋ 50%⠋ 60%⠋ 70%⠋ 80%⠋ 90%", output.ToString()); c.PerformStep(); Assert.Equal("⠋ 0%⠋ 10%⠋ 20%⠋ 30%⠋ 40%⠋ 50%⠋ 60%⠋ 70%⠋ 80%⠋ 90%Done! \n", output.ToString()); }
ConsoleProgressSpinerクラスの実装全体
/// <summary>コンソール用のスピナー</summary> public class ConsoleProgressSpiner { //アニメーションのコマ string[] bars = { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" }; 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; } } } private int value = 0; /// <summary>プログレス バーの現在位置を取得または設定します。</summary> public int Value { get { return this.value; } set { if (value < this.Minimum) throw new ArgumentException("指定された値が Minimum プロパティの値未満です。"); if (value > this.Maximum) throw new ArgumentException("指定された値が Maximum プロパティの値を超えます。"); this.value = value; update(); } } private int step = 10; /// <summary>PerformStep() メソッドを呼び出したときに、プログレス バーの現在の位置を進める量を取得または設定します。</summary> public int Step { get { return this.step; } set { this.step = value; } } /// <summary>プログレス バーの現在位置を Step プロパティの値の分だけ進めます。 </summary> public void PerformStep() { this.value += this.Step; if (this.value < minimum) { this.value = minimum; } if (this.value > maximum) { this.value = maximum; } update(); } /// <summary>Minimum〜Maximumに対するValueの進捗率を計算して返却</summary> /// <returns>進捗率(%)</returns> private int CalcProportion() { decimal oneMeter = new decimal(100) / (this.Maximum - this.Minimum); return Decimal.ToInt32(oneMeter * (this.Value - this.Minimum)); } /// <summary>進捗終了の印字</summary> private void DoneProgressConsoleWrite() { //色を戻す Console.ResetColor(); //カーソル位置を変更 Console.SetCursorPosition(0, Console.CursorTop); //終了の表示 Console.WriteLine("Done! "); } /// <summary>進捗進行中の印字</summary> private void InProgressConsoleWrite() { //進捗率計算 int proportion = CalcProportion(); //カーソル位置を変更 Console.SetCursorPosition(0, Console.CursorTop); //色変更 Console.ForegroundColor = ConsoleColor.Green; Console.BackgroundColor = ConsoleColor.Black; //進捗率の印字 Console.Write("{0}{1, 3:d0}%", bars[proportion % bars.Length], proportion); } /// <summary>描画</summary> private void update() { if (this.Maximum == this.Value) { DoneProgressConsoleWrite(); } else { InProgressConsoleWrite(); } } }
操作方法
class Program { static void Main(string[] args) { ConsoleProgressSpiner progressSpiner = new ConsoleProgressSpiner(); progressSpiner.Step = 1; for (int i = progressSpiner.Minimum; i <= progressSpiner.Maximum-1; i++) { progressSpiner.PerformStep(); //一時停止 System.Threading.Thread.Sleep(10); } } }
以上!
最初の記事はこちら。