Skip to content

Commit 3640473

Browse files
Use generator
1 parent ba606d1 commit 3640473

File tree

4 files changed

+400
-186
lines changed

4 files changed

+400
-186
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
public enum StopwatchState
2+
{
3+
Ready,
4+
Running,
5+
Stopped
6+
}
7+
8+
public class SplitSecondStopwatch(TimeProvider time)
9+
{
10+
private List<TimeSpan> _previousLaps = [];
11+
private TimeSpan _currentLapTrackedTime = TimeSpan.Zero;
12+
private DateTimeOffset? _currentLapTrackingTimeSince;
13+
14+
private TimeSpan PreviousLapsTotal => _previousLaps.Aggregate(TimeSpan.Zero, (total, lap) => total + lap);
15+
private TimeSpan CurrentLapTrackingTime =>
16+
_currentLapTrackingTimeSince is null ? TimeSpan.Zero : time.GetUtcNow() - _currentLapTrackingTimeSince.Value;
17+
18+
public StopwatchState State { get; private set; } = StopwatchState.Ready;
19+
public TimeSpan CurrentLap => _currentLapTrackedTime + CurrentLapTrackingTime;
20+
public TimeSpan Total => CurrentLap + PreviousLapsTotal;
21+
public IReadOnlyCollection<TimeSpan> PreviousLaps => _previousLaps.AsReadOnly();
22+
23+
public void Start()
24+
{
25+
if (State == StopwatchState.Running)
26+
throw new InvalidOperationException();
27+
28+
_currentLapTrackingTimeSince = time.GetUtcNow();
29+
30+
State = StopwatchState.Running;
31+
}
32+
33+
public void Stop()
34+
{
35+
if (State != StopwatchState.Running)
36+
throw new InvalidOperationException();
37+
38+
_currentLapTrackedTime += CurrentLap;
39+
_currentLapTrackingTimeSince = null;
40+
41+
State = StopwatchState.Stopped;
42+
}
43+
44+
public void Reset()
45+
{
46+
if (State != StopwatchState.Stopped)
47+
throw new InvalidOperationException();
48+
49+
_previousLaps.Clear();
50+
_currentLapTrackingTimeSince = null;
51+
_currentLapTrackedTime = TimeSpan.Zero;
52+
53+
State = StopwatchState.Ready;
54+
}
55+
56+
public void Lap()
57+
{
58+
if (State != StopwatchState.Running)
59+
throw new InvalidOperationException();
60+
61+
_previousLaps.Add(CurrentLap);
62+
_currentLapTrackedTime = TimeSpan.Zero;
63+
_currentLapTrackingTimeSince = time.GetUtcNow();
64+
}
65+
}
Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,49 @@
1-
using Xunit;
1+
{{ func to_timespan
2+
if $0 == "00:00:00"
3+
ret "TimeSpan.Zero"
4+
end
5+
6+
parts = string.split $0 ":"
7+
hours = parts[0] | string.to_int
8+
minutes = parts[1] | string.to_int
9+
seconds = parts[2] | string.to_int
10+
$"new TimeSpan({hours},{minutes},{seconds})"
11+
end }}
12+
13+
using Microsoft.Extensions.Time.Testing;
214

315
public class {{ testClass }}
416
{
517
{{- for test in tests }}
618
[Fact{{ if !for.first }}(Skip = "Remove this Skip property to run this test"){{ end }}]
719
public void {{ test.testMethod }}()
820
{
9-
Assert.Equal({{ test.expected }}, {{ testedClass }}.{{ test.testedMethod }}({{ test.input.commands }}));
21+
{{- for command in test.input.commands }}
22+
{{- if command.command == "new" }}
23+
var timeProvider = new FakeTimeProvider();
24+
var stopwatch = new {{ testedClass }}(timeProvider);
25+
{{- else if command.command == "state" }}
26+
Assert.Equal({{ command.expected | enum "StopwatchState" }}, stopwatch.State);
27+
{{- else if command.command == "currentLap" }}
28+
Assert.Equal({{ command.expected | to_timespan }}, stopwatch.CurrentLap);
29+
{{- else if command.command == "total" }}
30+
Assert.Equal({{ command.expected | to_timespan }}, stopwatch.Total);
31+
{{- else if command.command == "previousLaps" }}
32+
{{- if command.expected.empty? }}
33+
Assert.Empty(stopwatch.PreviousLaps);
34+
{{ else }}
35+
Assert.Equal([{{- for previousLap in command.expected }}{{ previousLap | to_timespan }}{{ if !for.last }}, {{ end }}{{ end -}}], stopwatch.PreviousLaps);
36+
{{ end -}}
37+
{{- else if command.command == "advanceTime" }}
38+
timeProvider.Advance({{ command.by | to_timespan }});
39+
{{- else }}
40+
{{- if command.expected && command.expected.error }}
41+
Assert.Throws<InvalidOperationException>(() => stopwatch.{{ command.command | pascalize }}());
42+
{{ else }}
43+
stopwatch.{{ command.command | pascalize }}();
44+
{{ end -}}
45+
{{ end -}}
46+
{{ end -}}
1047
}
1148
{{ end -}}
1249
}
Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,34 @@
11
public enum StopwatchState
22
{
33
Ready,
4-
Running
4+
Running,
5+
Stopped
56
}
67

78
public class SplitSecondStopwatch(TimeProvider time)
8-
{
9-
private readonly List<TimeSpan> _splits = new();
10-
private DateTimeOffset? _splitStart;
11-
12-
private TimeSpan PreviousSplits => _splits.Aggregate(TimeSpan.Zero, (total, split) => total + split);
13-
private TimeSpan CurrentSplit => _splitStart is {} start ? time.GetUtcNow() - start : TimeSpan.Zero;
14-
15-
public StopwatchState State { get; private set; } = StopwatchState.Ready;
16-
public List<TimeSpan> PreviousLaps { get; } = new();
17-
18-
public TimeSpan CurrentLap => CurrentSplit + PreviousSplits;
19-
public TimeSpan Total => CurrentLap + PreviousLaps.Aggregate(TimeSpan.Zero, (total, split) => total + split);
9+
{
10+
public StopwatchState State { get; }
11+
public TimeSpan CurrentLap { get; }
12+
public TimeSpan Total { get; }
13+
public IReadOnlyCollection<TimeSpan> PreviousLaps { get; }
2014

2115
public void Start()
2216
{
23-
if (State != StopwatchState.Ready)
24-
throw new InvalidOperationException("Can't start a stopwatch that is not stopped.");
25-
26-
_splitStart = time.GetUtcNow();
27-
State = StopwatchState.Running;
17+
throw new NotImplementedException("You need to implement this method.");
2818
}
2919

3020
public void Stop()
3121
{
32-
if (State != StopwatchState.Running)
33-
throw new InvalidOperationException("Can't stop a stopwatch that is not started.");
34-
35-
_splits.Add(CurrentSplit);
36-
_splitStart = null;
37-
State = StopwatchState.Ready;
22+
throw new NotImplementedException("You need to implement this method.");
3823
}
39-
24+
4025
public void Reset()
4126
{
42-
if (State != StopwatchState.Ready)
43-
throw new InvalidOperationException("Can't reset a stopwatch that is not stopped.");
44-
45-
_splits.Clear();
46-
_splitStart = null;
47-
State = StopwatchState.Ready;
27+
throw new NotImplementedException("You need to implement this method.");
4828
}
49-
29+
5030
public void Lap()
5131
{
52-
if (State != StopwatchState.Running)
53-
throw new InvalidOperationException("Can't lap a stopwatch that is not started stopped.");
54-
55-
PreviousLaps.Add(CurrentLap);
56-
_splits.Clear();
57-
_splitStart = time.GetUtcNow();
32+
throw new NotImplementedException("You need to implement this method.");
5833
}
5934
}

0 commit comments

Comments
 (0)