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); } } }
以上!
最初の記事はこちら。