Skip to content

Commit 9ab1695

Browse files
committed
Removed all reactive logic, in preparation for the workshop.
1 parent f9556d7 commit 9ab1695

27 files changed

+111
-791
lines changed
Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
using System;
22
using System.Reactive.Concurrency;
3-
using System.Reactive.Linq;
4-
using System.Reactive.PlatformServices;
5-
6-
using ReduxSharp;
7-
8-
using Battleship.NET.Domain.Actions;
9-
using Battleship.NET.Domain.Models;
103

114
namespace Battleship.NET.Domain.Behaviors
125
{
@@ -16,20 +9,8 @@ public class GameClockBehavior
169
public static readonly TimeSpan UpdateInterval
1710
= TimeSpan.FromMilliseconds(1000 / 60);
1811

19-
public GameClockBehavior(
20-
IStore<GameStateModel> gameStateStore,
21-
ISystemClock systemClock)
22-
{
23-
_gameStateStore = gameStateStore;
24-
_systemClock = systemClock;
25-
}
26-
12+
// TODO: Implement this
2713
public IDisposable Start(IScheduler scheduler)
28-
=> Observable.Timer(TimeSpan.Zero, UpdateInterval, scheduler)
29-
.Do(_ => _gameStateStore.Dispatch(new UpdateRuntimeAction(_systemClock.UtcNow.UtcDateTime)))
30-
.Subscribe();
31-
32-
private readonly IStore<GameStateModel> _gameStateStore;
33-
private readonly ISystemClock _systemClock;
14+
=> throw new NotImplementedException();
3415
}
3516
}
Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,13 @@
11
using System;
2-
using System.Linq;
32
using System.Reactive.Concurrency;
4-
using System.Reactive.Linq;
5-
6-
using ReduxSharp;
7-
8-
using Battleship.NET.Domain.Actions;
9-
using Battleship.NET.Domain.Models;
103

114
namespace Battleship.NET.Domain.Behaviors
125
{
136
public class GameCompletionBehavior
147
: IBehavior
158
{
16-
public GameCompletionBehavior(
17-
IStore<GameStateModel> gameStateStore)
18-
{
19-
_gameStateStore = gameStateStore;
20-
}
21-
9+
// TODO: Implement this
2210
public IDisposable Start(IScheduler scheduler)
23-
=> _gameStateStore
24-
.ObserveOn(scheduler)
25-
.Select(gameState =>
26-
(
27-
maxHitCount: gameState.Definition.Ships.Sum(ship => ship.Segments.Count),
28-
player1HitCount: gameState.Player1.GameBoard.Hits.Count,
29-
player2HitCount: gameState.Player2.GameBoard.Hits.Count,
30-
phase: gameState.Phase
31-
))
32-
.DistinctUntilChanged()
33-
.Where(model => model.phase == GamePhase.Running)
34-
.Do(model =>
35-
{
36-
if (model.player1HitCount >= model.maxHitCount)
37-
_gameStateStore.Dispatch(new CompleteGameAction(GamePlayer.Player2));
38-
else if (model.player2HitCount >= model.maxHitCount)
39-
_gameStateStore.Dispatch(new CompleteGameAction(GamePlayer.Player1));
40-
})
41-
.Subscribe();
42-
43-
private readonly IStore<GameStateModel> _gameStateStore;
11+
=> throw new NotImplementedException();
4412
}
4513
}
Lines changed: 4 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,19 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Collections.Immutable;
42
using System.Drawing;
5-
using System.Linq;
63

74
using Battleship.NET.Domain.Models;
85

96
namespace Battleship.NET.Domain.Selectors
107
{
118
public static class BoardSelectors
129
{
13-
public static readonly SelectorSet<GameStateModel, bool, (GamePlayer player, Point position)> CanReceiveShot
14-
= SelectorSet.Create<GameStateModel, bool, (GamePlayer player, Point position)>(@params =>
15-
{
16-
Func<GameStateModel, bool> hasShooterMissedSelector;
17-
Func<GameStateModel, ImmutableHashSet<Point>> hitsSelector, missesSelector;
18-
if (@params.player == GamePlayer.Player1)
19-
{
20-
hasShooterMissedSelector = gameState => gameState.Player2.HasMissed;
21-
hitsSelector = gameState => gameState.Player1.GameBoard.Hits;
22-
missesSelector = gameState => gameState.Player1.GameBoard.Misses;
23-
}
24-
else
25-
{
26-
hasShooterMissedSelector = gameState => gameState.Player1.HasMissed;
27-
hitsSelector = gameState => gameState.Player2.GameBoard.Hits;
28-
missesSelector = gameState => gameState.Player2.GameBoard.Misses;
29-
}
30-
31-
return Selector.Create(
32-
hasShooterMissedSelector,
33-
hitsSelector,
34-
missesSelector,
35-
(hasShooterMissed, hits, misses) => !hasShooterMissed && !hits.Contains(@params.position)
36-
&& !misses.Contains(@params.position));
37-
});
38-
39-
public static readonly Func<GameStateModel, ImmutableArray<string>> ColumnHeadings
40-
= Selector.Create<GameStateModel, GameDefinitionModel, ImmutableArray<string>>(
41-
argSelector: gameState => gameState.Definition,
42-
resultSelector: definition => definition.GameBoard.Positions
43-
.Select(position => position.X)
44-
.Distinct()
45-
.OrderBy(x => x)
46-
.Select(x => x.ToString())
47-
.ToImmutableArray());
48-
4910
public static readonly SelectorSet<GameStateModel, bool, GamePlayer> IsValid
5011
= SelectorSet.Create<GameStateModel, bool, GamePlayer>(
51-
player => Selector.Create(
52-
arg1Selector: gameState => gameState.Definition,
53-
arg2Selector: ShipSelectors.AllSegmentPlacements[player],
54-
resultSelector: (definition, segmentPlacements) =>
55-
{
56-
var visitedPositions = new HashSet<Point>();
57-
58-
foreach (var position in segmentPlacements.Select(segmentPlacement => segmentPlacement.Position))
59-
{
60-
if (visitedPositions.Contains(position) || !definition.GameBoard.Positions.Contains(position))
61-
return false;
62-
visitedPositions.Add(position);
63-
}
64-
65-
return true;
66-
}));
67-
68-
public static readonly Func<GameStateModel, ImmutableArray<string>> RowHeadings
69-
= Selector.Create<GameStateModel, GameDefinitionModel, ImmutableArray<string>>(
70-
argSelector: gameState => gameState.Definition,
71-
resultSelector: definition => definition.GameBoard.Positions
72-
.Select(position => position.Y)
73-
.Distinct()
74-
.OrderBy(y => y)
75-
.Select(y => Convert.ToChar(y + 'A').ToString())
76-
.ToImmutableArray());
77-
78-
public static readonly SelectorSet<GameStateModel, ShipSegmentPlacementModel?, (GamePlayer player, Point position)> ShipSegmentPlacement
79-
= SelectorSet.Create<GameStateModel, ShipSegmentPlacementModel?, (GamePlayer player, Point position)>(
80-
@params => Selector.Create<GameStateModel, ReadOnlyValueList<ShipSegmentPlacementModel>, ShipSegmentPlacementModel?>(
81-
argSelector: ShipSelectors.AllSegmentPlacements[@params.player],
82-
resultSelector: segmentPlacements => segmentPlacements
83-
.Where(segmentPlacement => segmentPlacement.Position == @params.position)
84-
.FirstOrDefault()));
85-
86-
public static readonly SelectorSet<GameStateModel, ShotOutcome?, (GamePlayer player, Point position)> ShotOutcome
87-
= SelectorSet.Create<GameStateModel, ShotOutcome?, (GamePlayer player, Point position)>(
88-
@params => Selector.Create<GameStateModel, ImmutableHashSet<Point>, ImmutableHashSet<Point>, ShotOutcome?>(
89-
arg1Selector: (@params.player == GamePlayer.Player1)
90-
? gameState => gameState.Player1.GameBoard.Hits
91-
: gameState => gameState.Player2.GameBoard.Hits,
92-
arg2Selector: (@params.player == GamePlayer.Player1)
93-
? gameState => gameState.Player1.GameBoard.Misses
94-
: gameState => gameState.Player2.GameBoard.Misses,
95-
resultSelector: (hits, misses) => @params.position switch
96-
{
97-
_ when hits.Contains(@params.position) => Models.ShotOutcome.Hit,
98-
_ when misses.Contains(@params.position) => Models.ShotOutcome.Miss,
99-
_ => null
100-
}));
12+
// TODO: Implement this
13+
player => throw new NotImplementedException());
10114

15+
// TODO: Implement this
10216
public static readonly Func<GameStateModel, Size> Size
103-
= Selector.Create<GameStateModel, GameDefinitionModel, Size>(
104-
gameState => gameState.Definition,
105-
definition => new Size(
106-
width: definition.GameBoard.Positions.Max(position => position.X) + 1,
107-
height: definition.GameBoard.Positions.Max(position => position.Y) + 1));
17+
= _ => throw new NotImplementedException();
10818
}
10919
}

Battleship.NET.Domain/Selectors/ShipSelectors.cs

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,63 +12,17 @@ public static class ShipSelectors
1212
{
1313
public static readonly SelectorSet<GameStateModel, ReadOnlyValueList<ShipSegmentPlacementModel>, GamePlayer> AllSegmentPlacements
1414
= SelectorSet.Create<GameStateModel, ReadOnlyValueList<ShipSegmentPlacementModel>, GamePlayer>(
15-
player => Selector.Create<GameStateModel, ReadOnlyValueList<ReadOnlyValueList<ShipSegmentPlacementModel>>, ReadOnlyValueList<ShipSegmentPlacementModel>>(
16-
argSelector: gameState => Enumerable.Range(0, gameState.Definition.Ships.Length)
17-
.Select(index => SegmentPlacements![(player, index)].Invoke(gameState)) // Null-check overridden because this can only be null of SelectorSet.Create() and Selector.Create() both invoke their delegates immediately, which neither do.
18-
.ToReadOnlyValueList(),
19-
resultSelector: segmentPlacementSet => segmentPlacementSet
20-
.SelectMany(segmentPlacements => segmentPlacements)
21-
.ToReadOnlyValueList()));
22-
23-
public static readonly SelectorSet<GameStateModel, bool, (GamePlayer player, int index)> IsSunk
24-
= SelectorSet.Create<GameStateModel, bool, (GamePlayer player, int index)>(
25-
@params => Selector.Create<GameStateModel, ImmutableHashSet<Point>, ReadOnlyValueList<ShipSegmentPlacementModel>, bool>(
26-
arg1Selector: (@params.player == GamePlayer.Player1)
27-
? gameState => gameState.Player1.GameBoard.Hits
28-
: gameState => gameState.Player2.GameBoard.Hits,
29-
arg2Selector: SegmentPlacements![@params], // Null-check overridden because this can only be null of SelectorSet.Create() and Selector.Create() both invoke their delegates immediately, which neither do.
30-
resultSelector: (hits, segmentPlacements) => segmentPlacements
31-
.All(segmentPlacement => hits.Contains(segmentPlacement.Position))));
32-
33-
public static readonly SelectorSet<GameStateModel, bool, (GamePlayer player, int index)> IsValid
34-
= SelectorSet.Create<GameStateModel, bool, (GamePlayer player, int index)>(
35-
@params => Selector.Create(
36-
arg1Selector: gameState => gameState.Definition.GameBoard.Positions,
37-
arg2Selector: AllSegmentPlacements[@params.player],
38-
resultSelector: (boardPositions, segmentPlacements) =>
39-
{
40-
var thisShipPositions = new HashSet<Point>();
41-
var otherShipPositions = new HashSet<Point>();
42-
43-
foreach(var segmentPlacement in segmentPlacements)
44-
if (segmentPlacement.ShipIndex == @params.index)
45-
thisShipPositions.Add(segmentPlacement.Position);
46-
else
47-
otherShipPositions.Add(segmentPlacement.Position);
48-
49-
return thisShipPositions.All(position => boardPositions.Contains(position))
50-
&& !thisShipPositions.Intersect(otherShipPositions).Any();
51-
}));
15+
// TODO: Implement this
16+
player => throw new NotImplementedException());
5217

5318
public static readonly SelectorSet<GameStateModel, ShipSegmentPlacementModel, (GamePlayer player, int index, Point segment)> SegmentPlacement
5419
= SelectorSet.Create<GameStateModel, ShipSegmentPlacementModel, (GamePlayer player, int index, Point segment)>(
55-
@params => Selector.Create<GameStateModel, ShipStateModel, ShipSegmentPlacementModel>(
56-
argSelector: (@params.player == GamePlayer.Player1)
57-
? gameState => gameState.Player1.GameBoard.Ships[@params.index]
58-
: gameState => gameState.Player2.GameBoard.Ships[@params.index],
59-
resultSelector: state => new ShipSegmentPlacementModel(
60-
orientation: state.Orientation,
61-
position: @params.segment
62-
.RotateOrigin(state.Orientation)
63-
.Translate(state.Position),
64-
segment: @params.segment,
65-
shipIndex: @params.index)));
20+
// TODO: Implement this
21+
@params => throw new NotImplementedException());
6622

6723
public static readonly SelectorSet<GameStateModel, ReadOnlyValueList<ShipSegmentPlacementModel>, (GamePlayer player, int index)> SegmentPlacements
6824
= SelectorSet.Create<GameStateModel, ReadOnlyValueList<ShipSegmentPlacementModel>, (GamePlayer player, int index)>(
69-
@params => Selector.Create<GameStateModel, ReadOnlyValueList<ShipSegmentPlacementModel>>(
70-
resultSelector: gameState => gameState.Definition.Ships[@params.index].Segments
71-
.Select(segment => SegmentPlacement[(@params.player, @params.index, segment)].Invoke(gameState))
72-
.ToReadOnlyValueList()));
25+
// TODO: Implement this
26+
@params => throw new NotImplementedException());
7327
}
7428
}

Battleship.NET.WPF/Game/GameViewModel.cs

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,18 @@
1-
using System;
2-
using System.Reactive.Linq;
1+
using System.Reactive.Linq;
32
using System.Windows;
43

5-
using ReduxSharp;
6-
74
using Battleship.NET.Domain.Models;
8-
using Battleship.NET.WPF.Gamespace.Completed;
9-
using Battleship.NET.WPF.Gamespace.Idle;
10-
using Battleship.NET.WPF.Gamespace.Paused;
11-
using Battleship.NET.WPF.Gamespace.Ready;
12-
using Battleship.NET.WPF.Gamespace.Running;
13-
using Battleship.NET.WPF.Gamespace.Setup;
145
using Battleship.NET.WPF.Player;
156

167
namespace Battleship.NET.WPF.Game
178
{
189
public class GameViewModel
1910
{
2011
public GameViewModel(
21-
CompletedGamespaceViewModel completedGamespace,
22-
IStore<GameStateModel> gameStateStore,
23-
IdleGamespaceViewModel idleGamespace,
24-
PausedGamespaceViewModel pausedGamespace,
25-
PlayerViewModelFactory playerViewModelFactory,
26-
ReadyGamespaceViewModel readyGamespace,
27-
RunningGamespaceViewModel runningGamespace,
28-
SetupGamespaceViewModel setupGamespace)
12+
PlayerViewModelFactory playerViewModelFactory)
2913
{
30-
Gamespace = gameStateStore
31-
.Select(gameState => gameState.Phase)
32-
.DistinctUntilChanged()
33-
.Select(phase => (object)(phase switch
34-
{
35-
GamePhase.Complete => completedGamespace,
36-
GamePhase.Idle => idleGamespace,
37-
GamePhase.Paused => pausedGamespace,
38-
GamePhase.Ready => readyGamespace,
39-
GamePhase.Running => runningGamespace,
40-
GamePhase.Setup => setupGamespace,
41-
_ => throw new InvalidOperationException("Dafuq did you do to the game state?"),
42-
}))
14+
// TODO: Implement this
15+
Gamespace = Observable.Never<object>()
4316
.ToReactiveProperty();
4417

4518
Player1 = playerViewModelFactory.CreatePlayerViewModel(GamePlayer.Player1);

Battleship.NET.WPF/Gamespace/Completed/CompletedGamespaceBoardPositionViewModel.cs

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,28 @@
1-
using System.Linq;
2-
using System.Reactive.Linq;
1+
using System.Reactive.Linq;
32
using System.Windows;
43

5-
using ReduxSharp;
6-
74
using Battleship.NET.Domain.Models;
8-
using Battleship.NET.Domain.Selectors;
95
using Battleship.NET.WPF.Ship;
10-
using Battleship.NET.WPF.State.Models;
116

127
namespace Battleship.NET.WPF.Gamespace.Completed
138
{
149
public class CompletedGamespaceBoardPositionViewModel
1510
: GameBoardPositionViewModelBase
1611
{
1712
public CompletedGamespaceBoardPositionViewModel(
18-
IStore<GameStateModel> gameStateStore,
19-
System.Drawing.Point position,
20-
IStore<ViewStateModel> viewStateStore)
13+
System.Drawing.Point position)
2114
: base(position)
2215
{
23-
var activePlayer = viewStateStore
24-
.Select(viewState => viewState.ActivePlayer)
25-
.WhereNotNull()
26-
.DistinctUntilChanged()
27-
.ShareReplay(1);
28-
29-
var shipSegmentPlacement = activePlayer
30-
.Select(activePlayer => gameStateStore
31-
.Select(BoardSelectors.ShipSegmentPlacement[(activePlayer, position)]))
32-
.Switch()
33-
.DistinctUntilChanged()
34-
.ShareReplay(1);
35-
36-
IsShipSunk = shipSegmentPlacement
37-
.WithLatestFrom(
38-
activePlayer,
39-
(shipSegmentPlacement, activePlayer) => (shipSegmentPlacement is not null)
40-
? gameStateStore
41-
.Select(ShipSelectors.IsSunk[(activePlayer, shipSegmentPlacement.ShipIndex)])
42-
: Observable.Return(false))
43-
.Switch()
16+
// TODO: Implement this
17+
IsShipSunk = Observable.Never<bool>()
4418
.ToReactiveProperty();
4519

46-
ShipAsset = Observable.CombineLatest(
47-
gameStateStore
48-
.Select(gameState => gameState.Definition),
49-
shipSegmentPlacement,
50-
(definition, shipSegmentPlacement) => (shipSegmentPlacement is null)
51-
? null
52-
: new ShipSegmentAssetModel(
53-
orientation: shipSegmentPlacement.Orientation,
54-
segment: shipSegmentPlacement.Segment,
55-
shipIndex: shipSegmentPlacement.ShipIndex,
56-
shipName: definition.Ships[shipSegmentPlacement.ShipIndex].Name))
20+
// TODO: Implement this
21+
ShipAsset = Observable.Never<ShipSegmentAssetModel?>()
5722
.ToReactiveProperty();
5823

59-
ShotOutcome = activePlayer
60-
.Select(activePlayer => gameStateStore
61-
.Select(BoardSelectors.ShotOutcome[(activePlayer, position)]))
62-
.Switch()
24+
// TODO: Implement this
25+
ShotOutcome = Observable.Never<ShotOutcome?>()
6326
.ToReactiveProperty();
6427
}
6528

0 commit comments

Comments
 (0)