Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Codebreaker.ViewModels/Codebreaker.ViewModels.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.1" />
<PackageReference Include="CNinnovation.Codebreaker.GamesClient" Version="3.5.0-beta.13" />
<PackageReference Include="CNinnovation.Codebreaker.GamesClient" Version="3.5.0-beta.16" />
</ItemGroup>

<ItemGroup>
Expand Down
11 changes: 3 additions & 8 deletions src/Codebreaker.ViewModels/Components/GameViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
namespace Codebreaker.ViewModels.Components;

public class GameViewModel
public class GameViewModel(Game game)
{
private readonly Game _game;

public GameViewModel(Game game)
{
_game = game;
}
private readonly Game _game = game;

public Guid GameId => _game.GameId;

Expand All @@ -23,5 +18,5 @@ public GameViewModel(Game game)

public DateTime StartTime => _game.StartTime;

public ObservableCollection<MoveViewModel> Moves { get; } = new ObservableCollection<MoveViewModel>();
public ObservableCollection<MoveViewModel> Moves { get; } = [];
}
7 changes: 2 additions & 5 deletions src/Codebreaker.ViewModels/Components/MoveViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
namespace Codebreaker.ViewModels.Components;

public class MoveViewModel
public class MoveViewModel(Move move)
{
private readonly Move _move;

public MoveViewModel(Move move) =>
_move = move;
private readonly Move _move = move;

public int MoveNumber => _move.MoveNumber;

Expand Down
4 changes: 2 additions & 2 deletions src/Codebreaker.ViewModels/Models/Move.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ public partial class Move(Guid moveId, int moveNumber) : ObservableObject
/// <summary>
/// The guess pegs from the user for this move.
/// </summary>
public ObservableCollection<string> GuessPegs { get; } = new();
public ObservableCollection<string> GuessPegs { get; } = [];

/// <summary>
/// The result from the analyer for this move based on the associated game that contains the move.
/// </summary>
public ObservableCollection<string> KeyPegs { get; } = new();
public ObservableCollection<string> KeyPegs { get; } = [];

public override string ToString() => $"{MoveNumber}. " +
$"{string.Join('#', GuessPegs)} : " +
Expand Down
46 changes: 44 additions & 2 deletions src/Codebreaker.ViewModels/Pages/GamePageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public enum GameMoveValue
Completed
}

/// <summary>
/// Configure to enable dialogs (via <see cref="IDialogService"/>), or use the <see cref="InfoBarMessageService"/>.
/// </summary>
public class GamePageViewModelOptions
{
public bool EnableDialogs { get; set; } = false;
Expand Down Expand Up @@ -46,9 +49,15 @@ public GamePageViewModel(
};
}

/// <summary>
/// Information on the game - messages, errors, etc. See <see cref="InfoBarMessageService"/>.
/// </summary>
public InfoBarMessageService InfoBarMessageService { get; } = new();

private Models.Game? _game;
/// <summary>
/// <see cref="Models.Game"/> instance."/>
/// </summary>
public Models.Game? Game
{
get => _game;
Expand Down Expand Up @@ -79,22 +88,39 @@ public Models.Game? Game
[ObservableProperty]
private bool _isNamePredefined = false;

public ObservableCollection<SelectedFieldViewModel> Fields { get; } = new();
public ObservableCollection<SelectedFieldViewModel> Fields { get; } = [];

public ObservableCollection<SelectionAndKeyPegs> GameMoves { get; } = new();
public ObservableCollection<SelectionAndKeyPegs> GameMoves { get; } = [];

/// <summary>
/// Status of the game. See <see cref="GameMode"/>.
/// </summary>
[ObservableProperty]
private GameMode _gameStatus = GameMode.NotRunning;

/// <summary>
/// An API call to the games-API is in-progress. Use to display progress indicators.
/// </summary>
[NotifyPropertyChangedFor(nameof(IsNameEnterable))]
[ObservableProperty]
private bool _inProgress = false;

[ObservableProperty]
private bool _isCancelling = false;

/// <summary>
/// The player name can be entered.
/// </summary>
public bool IsNameEnterable => !InProgress && !IsNamePredefined;

/// <summary>
/// Starts a new game using <see cref="IGamesClient"/>.
/// Updates the <see cref="GameStatus"/> property.
/// Initializes <see cref="Game"/>).
/// Increments the move number.
/// Shows <see cref="IDialogService"/> messages or <see cref="InfoBarMessageService"/> messages with errors.
/// </summary>
/// <returns>A task</returns>
[RelayCommand(AllowConcurrentExecutions = false, FlowExceptionsToTaskScheduler = true)]
private async Task StartGameAsync()
{
Expand Down Expand Up @@ -159,6 +185,11 @@ private async Task StartGameAsync()
// }
// }

/// <summary>
///
/// </summary>
/// <returns>A task</returns>
/// <exception cref="InvalidOperationException"></exception>
[RelayCommand(CanExecute = nameof(CanSetMove), AllowConcurrentExecutions = false, FlowExceptionsToTaskScheduler = true)]
private async Task SetMoveAsync()
{
Expand Down Expand Up @@ -235,8 +266,19 @@ private void InitializeValues()
}
}

/// <summary>
///
/// </summary>
/// <param name="GuessPegs">String representation of guesses</param>
/// <param name="KeyPegs">String representation of results</param>
/// <param name="MoveNumber">The move number</param>
public record SelectionAndKeyPegs(string[] GuessPegs, string[] KeyPegs, int MoveNumber);

public record class GameStateChangedMessage(GameMode GameMode);

/// <summary>
/// Messages sent when the games starts, or a move is set.
/// </summary>
/// <param name="GameMoveValue"><see cref="GameMoveValue"/></param>
/// <param name="SelectionAndKeyPegs"><see cref="SelectionAndKeyPegs"/></param>
public record class GameMoveMessage(GameMoveValue GameMoveValue, SelectionAndKeyPegs? SelectionAndKeyPegs = null);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public class InfoBarMessageService
{
public ObservableCollection<InfoMessageViewModel> Messages { get; } = new();
public ObservableCollection<InfoMessageViewModel> Messages { get; } = [];

public void ShowMessage(InfoMessageViewModel message)
{
Expand Down
33 changes: 17 additions & 16 deletions src/Codebreaker.ViewModels/docs/readme.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
# CNinnovation.Codebreaker.ViewModels

This library contains the `GamesClient` class to communicate with the Codebreaker service, and model types that are used for the communication.
This library contains view-model types for XAML-based applications (WinUI, WPF, .NET MAUI...) to create Codebreaker games.

See https://github.com/codebreakerapp for more information on the complete solution.
It is part of the Codebreaker solution.

See https://github.com/codebreakerapp for more information on the complete solution.

## The ViewModels

TODO

| Class | Description |
|-------|-------------|
| GamePageViewModel | TODO |
| GameViewModel | TODO |
| MoveViewModel | TODO |
| InfoMessageViewModel | TODO |

| GamePageViewModel | The GamePageViewModel is the view-model type for the game page with commands to start games, set moves. |
| GameViewModel | The GameViewModel is the view-model type for game information. |
| MoveViewModel | The MoveViewModel is the view-model type for a game move. |
| InfoMessageViewModel | Alternative option of IDialogService |

The `GamesClient` class is the main class to use for communication. It contains the following methods:
The `GamePageViewModel` is the main view-model type to communicate with the application.

| Method | Description |
| Members | Description |
|------------|--------------------|
| StartGameAsync | Start a new game |
| SetMoveAsync | Set guesses for a game move |
| GetGameAsync | Get a game by id with all details and moves |
| GetGamesAsync | Get a list of games with all details and moves (use the `GamesQuery` class to define the filter) |
| ctor | Needs `IGamesClient` (communication with the games-service API), `IOptions<GamePageViewModelOptions>`, `IDialogService` |

### Supporting types

| Class | Description |
|-------|-------------|
| GameMode | An enumeration - is the game not running, started, are moves set, lost, won? |

In the constructor, inject the `HttpClient` class. You can use `Microsoft.Extensions.Http` to configure the `HttpClient` class.

Expand All @@ -35,4 +36,4 @@ The following model types are used to return information about the game.
| Model type | Description |
|------------|-------------|
| Game | Contains the game id, the game status, the game moves and the game result |
| Move | Contains the move number, the guess and the result of the guess |
| Move | Contains the move number, the guess (`GuessPegs`) and the result of the guess (`KeyPegs`) |