Skip to content

Commit ad6b3fc

Browse files
committed
Closes #4: Change order of options in "main menu".
1 parent 7d73140 commit ad6b3fc

File tree

7 files changed

+224
-65
lines changed

7 files changed

+224
-65
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
3+
namespace XmrStakBootstrap.Common.Helper
4+
{
5+
public class Closure : IDisposable
6+
{
7+
private readonly Action _postAction;
8+
private bool _disposed;
9+
10+
public Closure(Action preAction, Action postAction)
11+
{
12+
_postAction = postAction;
13+
14+
preAction?.Invoke();
15+
}
16+
17+
public void Dispose()
18+
{
19+
if (_disposed) return;
20+
21+
_postAction?.Invoke();
22+
_disposed = true;
23+
}
24+
}
25+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
3+
namespace XmrStakBootstrap.Common.Helper
4+
{
5+
public static class ConsoleColorClosure
6+
{
7+
public static IDisposable ForegroundColor(ConsoleColor color)
8+
{
9+
var original = Console.ForegroundColor;
10+
return new Closure(() => Console.ForegroundColor = color, () => Console.ForegroundColor = original);
11+
}
12+
}
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace XmrStakBootstrap.Common.Menu
4+
{
5+
public interface IMenuBuilder<T>
6+
{
7+
Func<T> DefaultAction { get; set; }
8+
void AddOption(string text, bool enabled, Func<T> action);
9+
T Execute();
10+
}
11+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using XmrStakBootstrap.Common.Helper;
4+
5+
namespace XmrStakBootstrap.Common.Menu
6+
{
7+
public static class MenuBuilder
8+
{
9+
public static IMenuBuilder<T> Create<T>(Func<T> defaultAction = null)
10+
{
11+
return new MenuBuilder<T>
12+
{
13+
DefaultAction = defaultAction
14+
};
15+
}
16+
17+
public static IMenuBuilder<string> CreateTextListMenu(IEnumerable<string> values, string defaultValue = null)
18+
{
19+
var menu = new MenuBuilder<string>
20+
{
21+
DefaultAction = () => defaultValue
22+
};
23+
24+
foreach (var option in values)
25+
{
26+
menu.AddEnabledOption(option, () => option);
27+
}
28+
29+
return menu;
30+
}
31+
}
32+
33+
public class MenuBuilder<T> : IMenuBuilder<T>
34+
{
35+
public Func<T> DefaultAction { get; set; }
36+
private readonly IList<Option> _options = new List<Option>();
37+
38+
public void AddOption(string text, bool enabled, Func<T> action)
39+
{
40+
_options.Add(new Option
41+
{
42+
Action = action,
43+
IsEnabled = enabled,
44+
Text = text
45+
});
46+
}
47+
48+
public T Execute()
49+
{
50+
if (_options.Count == 0) return ExecuteDefault();
51+
52+
RenderOptions();
53+
var input = GetInput();
54+
55+
if (!IsInputValid(input)) return ExecuteDefault();
56+
57+
var option = _options[input - 1];
58+
return option.IsEnabled ? ExecuteAction(option.Action) : ExecuteDefault();
59+
}
60+
61+
private T ExecuteDefault()
62+
{
63+
return ExecuteAction(null);
64+
}
65+
66+
private T ExecuteAction(Func<T> action)
67+
{
68+
return (action ?? DefaultAction ?? (() => default(T)))();
69+
}
70+
71+
private bool IsInputValid(int input)
72+
{
73+
return input >= 1 && input <= _options.Count;
74+
}
75+
76+
private static int GetInput()
77+
{
78+
Console.Write(@"Select: ");
79+
int index;
80+
if (!int.TryParse(Console.ReadLine(), out index)) return -1;
81+
return index;
82+
}
83+
84+
private void RenderOptions()
85+
{
86+
var index = 1;
87+
foreach (var option in _options)
88+
{
89+
RenderOption(index++, option);
90+
}
91+
}
92+
93+
private static void RenderOption(int index, Option option)
94+
{
95+
using (ConsoleColorClosure.ForegroundColor(GetOptionColor(option)))
96+
{
97+
Console.WriteLine(@"{0,3}: {1}", index, option.Text);
98+
}
99+
}
100+
101+
private static ConsoleColor GetOptionColor(Option option)
102+
{
103+
return option.IsEnabled ? ConsoleColor.White : ConsoleColor.DarkGray;
104+
}
105+
106+
private class Option
107+
{
108+
public string Text { get; set; }
109+
public bool IsEnabled { get; set; }
110+
public Func<T> Action { get; set; }
111+
}
112+
}
113+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
3+
namespace XmrStakBootstrap.Common.Menu
4+
{
5+
public static class MenuBuilderExtensions
6+
{
7+
public static IMenuBuilder<T> AddDisabledOption<T>(this IMenuBuilder<T> menuBuilder, string text)
8+
{
9+
return menuBuilder.AddConditionalOption(text, false, null);
10+
}
11+
12+
public static IMenuBuilder<T> AddEnabledOption<T>(this IMenuBuilder<T> menuBuilder, string text, Func<T> action)
13+
{
14+
return menuBuilder.AddConditionalOption(text, true, action);
15+
}
16+
17+
public static IMenuBuilder<T> AddConditionalOption<T>(this IMenuBuilder<T> menuBuilder, string text, bool enabled, Func<T> action)
18+
{
19+
menuBuilder.AddOption(text, enabled, action);
20+
return menuBuilder;
21+
}
22+
}
23+
}

xmr-stak-bootstrap/Core/Runner/Miner/MinerRunner.cs

Lines changed: 34 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Newtonsoft.Json;
77
using Unity.Attributes;
88
using XmrStakBootstrap.Common;
9+
using XmrStakBootstrap.Common.Menu;
910
using XmrStakBootstrap.MasterConfiguration.Model;
1011
using XmrStakBootstrap.RunConfiguration.Model;
1112

@@ -42,59 +43,47 @@ public void Run()
4243
return;
4344
}
4445

45-
//TODO: refactor
46-
while (true)
46+
var @continue = true;
47+
while (@continue)
4748
{
4849
Console.Clear();
4950
Console.WriteLine(@"Active solution: {0}", HasSolution ? RunConfigurationModel.ActiveSolutionConfiguration : "<UNKNOWN>");
5051
Console.WriteLine(@"Active workload: {0}", HasWorkload ? RunConfigurationModel.ActiveWorkloadConfiguration : "<UNKNOWN>");
5152
Console.WriteLine();
5253
Console.WriteLine(@"What would you like to do?");
53-
if (CanRun) Console.WriteLine(@"0. Run/restart miners");
54-
Console.WriteLine(@"1. Exit");
55-
Console.WriteLine(@"2. Exit & terminate miners");
56-
Console.WriteLine(@"3. Change solution");
57-
Console.WriteLine(@"4. Change workload");
58-
Console.WriteLine();
59-
60-
Console.Write(@"Select: ");
61-
int index;
62-
if (!int.TryParse(Console.ReadLine(), out index) || index < (CanRun ? 0 : 1) || index > 5) continue;
6354

64-
Console.Clear();
65-
switch ((UserAction)index)
66-
{
67-
case UserAction.Run:
55+
@continue = MenuBuilder
56+
.Create(() => true)
57+
.AddConditionalOption(@"Start/restart miners", CanRun, () =>
58+
{
6859
DoRun();
69-
return;
70-
case UserAction.Exit:
60+
return false;
61+
})
62+
.AddEnabledOption(@"Change solution", () =>
63+
{
64+
SelectSolution();
65+
return true;
66+
})
67+
.AddEnabledOption(@"Change workload", () =>
68+
{
69+
SelectWorkload();
70+
return true;
71+
})
72+
.AddEnabledOption(@"Exit", () =>
73+
{
7174
Environment.Exit(0);
72-
break;
73-
case UserAction.ExitTerminate:
75+
return false;
76+
})
77+
.AddEnabledOption(@"Exit & terminate miners", () =>
78+
{
7479
KillMiners();
7580
Environment.Exit(0);
76-
break;
77-
case UserAction.ChangeSolution:
78-
SelectSolution();
79-
break;
80-
case UserAction.ChangeWorkload:
81-
SelectWorkload();
82-
break;
83-
default:
84-
throw new ArgumentOutOfRangeException();
85-
}
81+
return false;
82+
})
83+
.Execute();
8684
}
8785
}
8886

89-
private enum UserAction
90-
{
91-
Run,
92-
Exit,
93-
ExitTerminate,
94-
ChangeSolution,
95-
ChangeWorkload
96-
}
97-
9887
private class UtilizedHardware
9988
{
10089
public HardwareEntry Hardware { get; set; }
@@ -138,37 +127,17 @@ private void DoRun()
138127
private void SelectSolution()
139128
{
140129
Console.WriteLine(@"Available solutions: ");
141-
var keys = MasterConfigurationModel.SolutionProfiles.Keys.ToList();
142-
var i = 0;
143-
foreach (var key in keys)
144-
{
145-
Console.WriteLine(@"{0,3}: {1}", i, key);
146-
i++;
147-
}
148-
Console.Write(@"Select: ");
149-
int index;
150-
if (int.TryParse(Console.ReadLine(), out index) && index >= 0 && index < keys.Count)
151-
{
152-
RunConfigurationModel.ActiveSolutionConfiguration = keys[index];
153-
}
130+
RunConfigurationModel.ActiveSolutionConfiguration =
131+
MenuBuilder.CreateTextListMenu(MasterConfigurationModel.SolutionProfiles.Keys)
132+
.Execute();
154133
}
155134

156135
private void SelectWorkload()
157136
{
158137
Console.WriteLine(@"Available workloads: ");
159-
var keys = MasterConfigurationModel.WorkloadProfiles.Keys.ToList();
160-
var i = 0;
161-
foreach (var key in keys)
162-
{
163-
Console.WriteLine(@"{0,3}: {1}", i, key);
164-
i++;
165-
}
166-
Console.Write(@"Select: ");
167-
int index;
168-
if (int.TryParse(Console.ReadLine(), out index) && index >= 0 && index < keys.Count)
169-
{
170-
RunConfigurationModel.ActiveWorkloadConfiguration = keys[index];
171-
}
138+
RunConfigurationModel.ActiveWorkloadConfiguration =
139+
MenuBuilder.CreateTextListMenu(MasterConfigurationModel.WorkloadProfiles.Keys)
140+
.Execute();
172141
}
173142

174143
private List<PrioritizedPoolEntry> GetOutputPools(IEnumerable<string> pools)

xmr-stak-bootstrap/xmr-stak-bootstrap.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@
8585
</ItemGroup>
8686
<ItemGroup>
8787
<Compile Include="Core\Runner\Generator\ConfigurationGeneratorRunner.cs" />
88+
<Compile Include="Common\Helper\Closure.cs" />
89+
<Compile Include="Common\Helper\ConsoleColorClosure.cs" />
90+
<Compile Include="Common\Menu\IMenuBuilder.cs" />
91+
<Compile Include="Common\Menu\MenuBuilder.cs" />
92+
<Compile Include="Common\Menu\MenuBuilderExtensions.cs" />
8893
<Compile Include="MasterConfiguration\IMasterConfigurationParser.cs" />
8994
<Compile Include="Core\Runner\IRunnerContext.cs" />
9095
<Compile Include="MasterConfiguration\MasterConfigurationParser.cs" />

0 commit comments

Comments
 (0)