From a09b5676f6f2291567dc5e6b3a3a42fbc22b7f0f Mon Sep 17 00:00:00 2001 From: Wessel Tip Date: Tue, 18 Mar 2025 12:12:33 +0000 Subject: [PATCH] feat: Clean up set checking, add load spinner --- backend/backend/Models/Game.cs | 103 ++++++++++-------- .../app/game-list/game-list.component.html | 49 +++++---- .../src/app/game-list/game-list.component.ts | 6 +- frontend/src/app/game/game.component.html | 6 + .../src/service/user/user-data.service.ts | 2 +- 5 files changed, 91 insertions(+), 75 deletions(-) diff --git a/backend/backend/Models/Game.cs b/backend/backend/Models/Game.cs index 22770fd..03ccde0 100755 --- a/backend/backend/Models/Game.cs +++ b/backend/backend/Models/Game.cs @@ -56,7 +56,7 @@ public class Game { public bool GameIsFinished() { if (Deck == null || Hand == null) return false; - var finished = Deck.Length == 0 && Hand.Length < 12; + var finished = Deck.Length < 1 && Hand.Length < 12; // Check if no sets can be made with the remaining cards if (!finished && GetIndicesOfSet().Count == 0) { @@ -71,75 +71,74 @@ public class Game { return finished; } -// todo: refactor` - public SetCheckResult? IsSet(ushort[] indices, bool remove = true) { - if (remove) { - if (GameIsFinished()) { - FinishedAt = DateTime.UtcNow; - - return new SetCheckResult { IsFinished = true, NewState = this }; - } - } - - if (indices.Length != 3 || Hand == null) { - return null; - } - - if (indices.Any(index => Hand[index] == 0)) { - return null; + public bool SetResult(ushort[] indices) { + if (Hand == null || indices.Length != 3 || indices.Any(index => Hand[index] == 0)) { + return false; } + var cards = indices .Select(index => Card.ToCard(Hand[index])) .ToList(); - if (!( + return ( AllSameOrDifferent(cards[0].Shape, cards[1].Shape, cards[2].Shape) && AllSameOrDifferent(cards[0].Color, cards[1].Color, cards[2].Color) && AllSameOrDifferent(cards[0].Shade, cards[1].Shade, cards[2].Shade) && AllSameOrDifferent(cards[0].Count, cards[1].Count, cards[2].Count) - )) { - // todo(wessel): Split up for checking algorithm to game data + ); + } + + public SetCheckResult? IsSet(ushort[] indices) { + // Also check if finished before anything else, to prevent the board getting stuck + if (GameIsFinished()) { + FinishedAt = DateTime.UtcNow; + + return new SetCheckResult { IsFinished = true, NewState = this }; + } + + if (indices.Length != 3 || Hand == null || indices.Any(index => Hand[index] == 0)) { + return null; + } + + if (!SetResult(indices)) { Fails += 1; return new SetCheckResult { IsSet = false, NewState = this }; } // Order by Descending to make sure the correct card is removed // (From the top may cause the indices to be off by one) - if (remove) { - foreach (var index in indices.OrderByDescending(i => i)) { - var foundList = Found.ToList(); - foundList.Add(Hand[index]); - Found = foundList.ToArray(); + foreach (var index in indices.OrderByDescending(i => i)) { + var foundList = Found.ToList(); + foundList.Add(Hand[index]); + Found = foundList.ToArray(); - if (Hand.Length < 13) - { - ReplaceCardInHand(index); - } - else - { - var handList = Hand.ToList(); - handList.RemoveAt(index); - Hand = handList.ToArray(); - } + if (Hand.Length < 13) + { + ReplaceCardInHand(index); } - - while (GetIndicesOfSet().Count < 1 && Deck?.Length > 0) { - DealHand(Hand.Length + 1); + else + { + var handList = Hand.ToList(); + handList.RemoveAt(index); + Hand = handList.ToArray(); } } + while (GetIndicesOfSet().Count < 1 && Deck?.Length > 0) { + DealHand(Hand.Length + 1); + } + + // Check if finished after removing the set + if (GameIsFinished()) { + FinishedAt = DateTime.UtcNow; + + return new SetCheckResult { IsFinished = true, NewState = this }; + } + return new SetCheckResult { IsSet = true, NewState = this }; } - private static bool AllSameOrDifferent(T a, T b, T c) where T : Enum { - int ai = Convert.ToInt32(a); - int bi = Convert.ToInt32(b); - int ci = Convert.ToInt32(c); - - return (ai == bi && bi == ci) || (ai != bi && bi != ci && ai != ci); - } - public List GetIndicesOfSet() { if (Hand == null) return new List(); List res = new List(); @@ -147,9 +146,9 @@ public class Game { for (int i = 0; i < Hand.Length; i++) { for (int j = i + 1; j < Hand.Length; j++) { for (int k = j + 1; k < Hand.Length; k++) { - var result = IsSet([(ushort)i, (ushort)j, (ushort)k], false); + var result = SetResult([(ushort)i, (ushort)j, (ushort)k]); - if (result?.IsSet == true) { + if (result == true) { Console.WriteLine($"Found set at {i}, {j}, {k}"); res.Add([i, j, k]); } @@ -159,4 +158,12 @@ public class Game { return res; } + + private static bool AllSameOrDifferent(T a, T b, T c) where T : Enum { + int ai = Convert.ToInt32(a); + int bi = Convert.ToInt32(b); + int ci = Convert.ToInt32(c); + + return (ai == bi && bi == ci) || (ai != bi && bi != ci && ai != ci); + } } diff --git a/frontend/src/app/game-list/game-list.component.html b/frontend/src/app/game-list/game-list.component.html index 4e7900b..90f2dc0 100644 --- a/frontend/src/app/game-list/game-list.component.html +++ b/frontend/src/app/game-list/game-list.component.html @@ -1,24 +1,31 @@
- - - - - - - - - - - - @for(game of games; track game.id) { - - - - - - + @if (games) { +
Game IDStarted AtStatusFailsCards Remaining
{{ game.id }}{{ game.startedAt | date: 'dd-MM-YYYY HH:mm' }}{{ game.finishedAt ? 'Completed' : 'In Progress' }}{{ game.fails }}{{ game.deck.length + game.hand.length }}
+ + + + + + + - } - -
Game IDStarted AtStatusFailsCards Remaining
+ + + @for(game of games; track game.id) { + + {{ game.id }} + {{ game.startedAt | date: 'dd-MM-YYYY HH:mm' }} + {{ game.finishedAt ? 'Completed' : 'In Progress' }} + {{ game.fails }} + {{ game.deck.length + game.hand.length }} + + } + + + } @else { +
+
+

Loading games...

+
+ }
\ No newline at end of file diff --git a/frontend/src/app/game-list/game-list.component.ts b/frontend/src/app/game-list/game-list.component.ts index e1fff6c..ffc49e6 100644 --- a/frontend/src/app/game-list/game-list.component.ts +++ b/frontend/src/app/game-list/game-list.component.ts @@ -10,15 +10,11 @@ import { CommonModule } from '@angular/common'; styleUrl: './game-list.component.scss' }) export class GameListComponent { - games: { id: number, startedAt: Date, finishedAt: Date | null, fails: number, hand: any[], deck: any[] }[] = []; + games: { id: number, startedAt: Date, finishedAt: Date | null, fails: number, hand: any[], deck: any[] }[] | undefined; constructor(public userService: UserDataService, private router: Router) { this.getGames() } async getGames() { this.games = await this.userService.getGames(); - console.log('gamesfromservice ' + this.userService.getGames()) - - console.log('games' + this.games); - // return this.userService.getGames(); } enterGame(game: number) { diff --git a/frontend/src/app/game/game.component.html b/frontend/src/app/game/game.component.html index d6779d1..655ff16 100755 --- a/frontend/src/app/game/game.component.html +++ b/frontend/src/app/game/game.component.html @@ -39,6 +39,12 @@ (click)="selectCard(card)" /> } + @empty() { +
+
+

Loading cards...

+
+ }
diff --git a/frontend/src/service/user/user-data.service.ts b/frontend/src/service/user/user-data.service.ts index bf28360..e833ffe 100644 --- a/frontend/src/service/user/user-data.service.ts +++ b/frontend/src/service/user/user-data.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import axios from 'axios'; +import axios, { AxiosError } from 'axios'; @Injectable({ providedIn: 'root'