Backend für "Slip It In" mit ASP.NET Core erstellt

- Neues Backend-Projekt mit Entity Framework Core (PostgreSQL) und geteilten Modellen/DTOs angelegt
- Datenbankstruktur und Migrations implementiert (User, Game, Player, Phrase, PlayerCard, GameRound, SlipChallenge)
- SignalR-Hub für Spielkommunikation (Lobby, Spielstart, Kartenvergabe, Slip/Challenge) hinzugefügt
- Spiellogik und DB-Zugriffe im GameService gekapselt
- JWT-Authentifizierung und CORS für Entwicklung konfiguriert
- Projektdateien, NuGet-Abhängigkeiten und .gitignore aktualisiert
- Startkonfiguration und Umgebungsdateien angepasst
This commit is contained in:
Tim Krampitz
2026-07-23 21:39:15 +02:00
parent c1c6c9cb94
commit d29bff17a1
28 changed files with 2379 additions and 9 deletions

View File

@@ -0,0 +1,47 @@
namespace SlipItIn.Shared.DTOs;
public class GameStateDto
{
public int GameId { get; set; }
public string LobbyCode { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public List<PlayerInfoDto> Players { get; set; } = [];
public int CurrentRound { get; set; }
public int RoundTimeRemaining { get; set; }
}
public class PlayerInfoDto
{
// Öffentliche Daten (für alle sichtbar)
public int PlayerId { get; set; }
public string Username { get; set; } = string.Empty;
public int Score { get; set; }
public bool IsReady { get; set; }
public int CardCount { get; set; } // Anzahl der Karten (nicht die Karten selbst!)
}
public class PlayerHandDto
{
// Private Daten (nur für den Spieler selbst)
public int PlayerId { get; set; }
public List<PlayerCardDto> Cards { get; set; } = [];
}
public class PlayerCardDto
{
public int CardId { get; set; }
public int PhraseId { get; set; }
public string Text { get; set; } = string.Empty;
public bool IsUsed { get; set; }
}
public class SlipChallengeDto
{
public int ChallengeId { get; set; }
public int ChallengingPlayerId { get; set; }
public string ChallengingPlayerName { get; set; } = string.Empty;
public int TargetPlayerId { get; set; }
public int TargetCardId { get; set; }
public string Status { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
}

View File

@@ -0,0 +1,27 @@
namespace SlipItIn.Shared.Models;
public enum GameStatus
{
Lobby,
InProgress,
Completed,
Cancelled
}
public class Game
{
public int Id { get; set; }
public string LobbyCode { get; set; } = string.Empty; // 4-6 stelliger Code
public int HostId { get; set; }
public GameStatus Status { get; set; } = GameStatus.Lobby;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? StartedAt { get; set; }
public DateTime? EndedAt { get; set; }
public int MaxPlayers { get; set; } = 8;
public int RoundDurationSeconds { get; set; } = 45;
// Navigation
public User Host { get; set; } = null!;
public ICollection<Player> Players { get; set; } = [];
public ICollection<GameRound> Rounds { get; set; } = [];
}

View File

@@ -0,0 +1,24 @@
namespace SlipItIn.Shared.Models;
public enum RoundStatus
{
Waiting,
Active,
Resolving,
Completed
}
public class GameRound
{
public int Id { get; set; }
public int GameId { get; set; }
public int RoundNumber { get; set; }
public RoundStatus Status { get; set; } = RoundStatus.Waiting;
public DateTime StartedAt { get; set; } = DateTime.UtcNow;
public DateTime? EndedAt { get; set; }
// Navigation
public Game Game { get; set; } = null!;
public ICollection<PlayerCard> ActiveCards { get; set; } = [];
public ICollection<SlipChallenge> Challenges { get; set; } = [];
}

View File

@@ -0,0 +1,14 @@
namespace SlipItIn.Shared.Models;
public class Phrase
{
public int Id { get; set; }
public string Text { get; set; } = string.Empty;
public int CreatorId { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public bool IsActive { get; set; } = true;
// Navigation
public User Creator { get; set; } = null!;
public ICollection<PlayerCard> PlayerCards { get; set; } = [];
}

View File

@@ -0,0 +1,19 @@
namespace SlipItIn.Shared.Models;
public class Player
{
public int Id { get; set; }
public int UserId { get; set; }
public int GameId { get; set; }
public int Score { get; set; } = 0;
public int SuccessfulSlips { get; set; } = 0;
public int FailedSlips { get; set; } = 0;
public DateTime JoinedAt { get; set; } = DateTime.UtcNow;
public bool IsReady { get; set; } = false;
public string? ConnectionId { get; set; } // SignalR-Verbindungs-ID
// Navigation
public User User { get; set; } = null!;
public Game Game { get; set; } = null!;
public ICollection<PlayerCard> Cards { get; set; } = [];
}

View File

@@ -0,0 +1,16 @@
namespace SlipItIn.Shared.Models;
public class PlayerCard
{
public int Id { get; set; }
public int PlayerId { get; set; }
public int PhraseId { get; set; }
public int GameRoundId { get; set; }
public bool IsUsed { get; set; } = false;
public DateTime AssignedAt { get; set; } = DateTime.UtcNow;
// Navigation
public Player Player { get; set; } = null!;
public Phrase Phrase { get; set; } = null!;
public GameRound GameRound { get; set; } = null!;
}

View File

@@ -0,0 +1,26 @@
namespace SlipItIn.Shared.Models;
public enum ChallengeStatus
{
Pending, // Beschuldigung eingegangen, wartet auf Bestätigung/Ablehnung
Approved, // Beschuldigung war berechtigt → Phrase bleibt beim Beschuldiger
Rejected // Beschuldigung falsch → Beschuldiger erhält die Phrase
}
public class SlipChallenge
{
public int Id { get; set; }
public int GameRoundId { get; set; }
public int ChallengingPlayerId { get; set; } // Wer beschuldigt
public int TargetPlayerId { get; set; } // Wer beschuldigt wird
public int TargetCardId { get; set; } // Welche Phrase wird als falsch behauptet
public ChallengeStatus Status { get; set; } = ChallengeStatus.Pending;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? ResolvedAt { get; set; }
// Navigation
public GameRound GameRound { get; set; } = null!;
public Player ChallengingPlayer { get; set; } = null!; // Der Beschuldiger
public Player TargetPlayer { get; set; } = null!; // Der Beschuldigte
public PlayerCard TargetCard { get; set; } = null!; // Die angefochtene Phrase
}

View File

@@ -0,0 +1,15 @@
namespace SlipItIn.Shared.Models;
public class User
{
public int Id { get; set; }
public string Username { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string PasswordHash { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedAt { get; set; }
public bool IsActive { get; set; } = true;
// Navigation
public ICollection<Player> Players { get; set; } = [];
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.10" />
</ItemGroup>
</Project>