This commit is contained in:
Christian Kauer 2023-12-24 12:49:13 +01:00
parent fb5ac3c4b3
commit 477bb12965
17 changed files with 107 additions and 37 deletions

View File

@ -0,0 +1,13 @@
using GameModel;
using GameModel.Contract;
namespace GameData
{
public class DummyExpenseRepository : IExpenseRepository
{
public IEnumerable<Expense> GetAll()
{
return IExpenseRepository.TestData;
}
}
}

13
GameData/GameData.csproj Normal file
View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\GameModel\GameModel.csproj" />
</ItemGroup>
</Project>

View File

@ -9,22 +9,11 @@ namespace GameModel.Mocks
{ {
public class FakeExpenseRepository : IExpenseRepository public class FakeExpenseRepository : IExpenseRepository
{ {
Expense[] Data = new[] {
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Sink }, "Gosse", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Sink }, "Gosse2", 1.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.FullSink }, "Gosse bei Anwurf", 1m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Circle }, "Kranz", 1m, true),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.NinePins }, "alle Neune", 1m, true),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Eliminated }, "Ausgeschieden", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.NoWood }, "kein Holz", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Bell }, "Klingel", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.FirstThrowFail }, "Anwurffehler", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.ExpensePoint }, "Strafpunkt, z.B. im \"Scheißspiel\"", 0.5m, false),
};
public IEnumerable<Expense> GetAll() public IEnumerable<Expense> GetAll()
{ {
return Data; return IExpenseRepository.TestData;
} }
} }
} }

View File

@ -23,16 +23,20 @@ namespace GameHandler
_expenseRepository = expenseRepository; _expenseRepository = expenseRepository;
} }
private ExpenseModel _expenseModel = new ExpenseModel(Array.Empty<MemberExpense>()); //private ExpenseModel _expenseModel = new ExpenseModel(Array.Empty<MemberExpense>());
public ExpenseModel CheckThrow(BoardState currentState, PinThrow pinThrow, int[] PlayerIds) public ExpenseModel CheckThrow(BoardState currentState, PinThrow pinThrow, int[] PlayerIds, ExpenseModel expenseModelToAppend = null)
{ {
if (!PlayerIds.Any(_ => _ == pinThrow.PlayerId)) if (!PlayerIds.Any(_ => _ == pinThrow.PlayerId))
{ {
throw new InvalidPinThrowException($"Player {pinThrow.PlayerId} not found"); throw new InvalidPinThrowException($"Player {pinThrow.PlayerId} not found");
} }
var memberExpenses = new List<MemberExpense>(_expenseModel.MemberExpenses); if (expenseModelToAppend == null)
{
expenseModelToAppend = new ExpenseModel(Array.Empty<MemberExpense>());
}
var memberExpenses = new List<MemberExpense>(expenseModelToAppend.MemberExpenses);
var triggers = pinThrow.GetExpenseTriggers(currentState); var triggers = pinThrow.GetExpenseTriggers(currentState);
var destExpenses = _expenseRepository.GetAll().Where(_ => _.ExpenseTriggers.Any(et => triggers.Any(et2 => et2 == et))); var destExpenses = _expenseRepository.GetAll().Where(_ => _.ExpenseTriggers.Any(et => triggers.Any(et2 => et2 == et)));
@ -53,7 +57,7 @@ namespace GameHandler
} }
} }
return _expenseModel with { MemberExpenses = memberExpenses.ToArray() }; return expenseModelToAppend with { MemberExpenses = memberExpenses.ToArray() };
} }
} }
} }

View File

@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac" Version="7.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>

View File

@ -70,7 +70,7 @@ namespace GameHandler.DeathGame
} }
coffins.Add(new Coffin(playerId,0,0)); coffins.Add(new Coffin(playerId,0,0));
} }
return new DeathGameModel(1, coffins.OrderBy(_ => random.Next()).ToList().ToArray(), deathGameSettings); return new DeathGameModel(1, coffins.OrderBy(_ => random.Next()).ToList().ToArray(), deathGameSettings, playerIds);
} }
public IGameModel Update(PinThrow pinThrow, IGameModel gameModel, BoardState boardStateBeforeUpdate) public IGameModel Update(PinThrow pinThrow, IGameModel gameModel, BoardState boardStateBeforeUpdate)

View File

@ -13,21 +13,28 @@ using GameModel.Contract;
using GameModel.DeathGame; using GameModel.DeathGame;
using GameModel.Contracts; using GameModel.Contracts;
using System.Data; using System.Data;
using Autofac.Core;
using Autofac;
using static System.Formats.Asn1.AsnWriter;
namespace GameHandler namespace GameHandler
{ {
public class GameService public class GameService
{ {
private IContainer? _container { get; set; }
private bool _isStarted = false; private bool _isStarted = false;
private ILifetimeScope? _scope;
private IGameHandler _gh; private IGameHandler _gh;
private ThrowHandler _th; private ThrowHandler _th;
private ExpenseHandler _eh; private ExpenseHandler _eh;
private GameState _lastState; private GameState _lastState;
public GameState GameModel { get { return _lastState; } } public GameState GameModel { get => _lastState; }
public GameService() private IExpenseRepository? _expenseRepository { get => _scope?.Resolve<IExpenseRepository>(); }
public GameService(IContainer? container =null)
{ {
_container = container;
} }
public string ThrowModeName public string ThrowModeName
@ -57,14 +64,16 @@ namespace GameHandler
} }
_isStarted = true; _isStarted = true;
_scope = _container?.BeginLifetimeScope();
_gh = this.GetGameHandler(gameName); _gh = this.GetGameHandler(gameName);
var gm = _gh.InitGameModel(playerIds, gameSettings); var gm = _gh.InitGameModel(playerIds, gameSettings);
_th = new ThrowHandler(); _th = new ThrowHandler();
_eh = new ExpenseHandler(); _eh = new ExpenseHandler(_expenseRepository);
var throwState = ThrowState.Create(_gh.ThrowMode(), _gh.ThrowsPerRount()); var throwState = ThrowState.Create(_gh.ThrowMode(), _gh.ThrowsPerRount());
_lastState = GameState.Create(throwState, _gh.GetCurrentPlayerId(gm), gm); _lastState = GameState.Create(throwState, _gh.GetCurrentPlayerId(gm), gm, ExpenseModel.Create());
return _lastState; return _lastState;
} }
@ -82,10 +91,9 @@ namespace GameHandler
var throwState = _th.Update(_lastState.ThrowState, pinThrow); var throwState = _th.Update(_lastState.ThrowState, pinThrow);
var gameModel = _gh.Update(pinThrow, _lastState.GameModel, boardStateBeforeUpdate); var gameModel = _gh.Update(pinThrow, _lastState.GameModel, boardStateBeforeUpdate);
// todo: update expense model var expenseModel = _eh.CheckThrow(throwState.BoardState, pinThrow, gameModel.PlayerIds, _lastState.ExpenseModel);
_lastState = _lastState with { ThrowState = throwState, GameModel = gameModel, NextPlayerId = _gh.GetCurrentPlayerId(gameModel), ExpenseModel = expenseModel };
_lastState = _lastState with { ThrowState = throwState, GameModel = gameModel, NextPlayerId = _gh.GetCurrentPlayerId(gameModel) };
return _lastState ; return _lastState ;
} }
@ -111,6 +119,8 @@ namespace GameHandler
throw new InvalidGameStateExcpetion("Game not started"); throw new InvalidGameStateExcpetion("Game not started");
} }
_isStarted = false; _isStarted = false;
_scope?.Dispose();
} }
public ThrowCommandData ParseThrowData(string stringData) public ThrowCommandData ParseThrowData(string stringData)

View File

@ -4,6 +4,19 @@ namespace GameModel.Contract
{ {
public interface IExpenseRepository public interface IExpenseRepository
{ {
static Expense[] TestData = new[] {
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Sink }, "Gosse", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Sink }, "Gosse2", 1.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.FullSink }, "Gosse bei Anwurf", 1m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Circle }, "Kranz", 1m, true),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.NinePins }, "alle Neune", 1m, true),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Eliminated }, "Ausgeschieden", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.NoWood }, "kein Holz", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.Bell }, "Klingel", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.FirstThrowFail }, "Anwurffehler", 0.5m, false),
Expense.Create(ExpenseType.Monetary,new[] { ExpenseTrigger.ExpensePoint }, "Strafpunkt, z.B. im \"Scheißspiel\"", 0.5m, false),
};
IEnumerable<Expense> GetAll(); IEnumerable<Expense> GetAll();
} }
} }

View File

@ -8,5 +8,6 @@ namespace GameModel.Contracts
{ {
public interface IGameModel public interface IGameModel
{ {
int[] PlayerIds { get; }
} }
} }

View File

@ -7,5 +7,5 @@ using System.Threading.Tasks;
namespace GameModel.DeathGame namespace GameModel.DeathGame
{ {
public record DeathGameModel(int Id, Coffin[] Coffins, DeathGameSettings deathGameSettings) : IGameModel; public record DeathGameModel(int Id, Coffin[] Coffins, DeathGameSettings deathGameSettings, int[] PlayerIds) : IGameModel;
} }

View File

@ -8,5 +8,9 @@ namespace GameModel
{ {
public record ExpenseModel(MemberExpense[] MemberExpenses) public record ExpenseModel(MemberExpense[] MemberExpenses)
{ {
public static ExpenseModel Create()
{
return new ExpenseModel(Array.Empty<MemberExpense>());
}
} }
} }

View File

@ -7,11 +7,11 @@ using System.Threading.Tasks;
namespace GameModel namespace GameModel
{ {
public record GameState(ThrowState ThrowState, int NextPlayerId, IGameModel GameModel) public record GameState(ThrowState ThrowState, int NextPlayerId, IGameModel GameModel, ExpenseModel ExpenseModel)
{ {
public static GameState Create(ThrowState throwState, int nextPlayerId, IGameModel gm) public static GameState Create(ThrowState throwState, int nextPlayerId, IGameModel gameModel, ExpenseModel expenseModel)
{ {
return new GameState(throwState, nextPlayerId, gm); return new GameState(throwState, nextPlayerId, gameModel, expenseModel);
} }
} }
} }

View File

@ -197,11 +197,14 @@ namespace GameModel
} }
internal static PinPicture Create(string pindata) internal static PinPicture Create(string pindata)
{
if (!string.IsNullOrEmpty(pindata))
{ {
if (!int.TryParse(pindata, out int dummy)) if (!int.TryParse(pindata, out int dummy))
{ {
throw new InvalidDataException($"{pindata} cannot be parsed as throw"); throw new InvalidDataException($"{pindata} cannot be parsed as throw");
} }
}
var states = new[] { var states = new[] {
pindata.Contains("1") ? PinState.Down : PinState.Up, pindata.Contains("1") ? PinState.Down : PinState.Up,

View File

@ -33,11 +33,14 @@ namespace GameModel
} }
public static PinThrow Create(string pindata, bool isBell, bool isSink, int playerId) public static PinThrow Create(string pindata, bool isBell, bool isSink, int playerId)
{
if (!string.IsNullOrEmpty(pindata))
{ {
if (!int.TryParse(pindata, out int dummy)) if (!int.TryParse(pindata, out int dummy))
{ {
throw new InvalidDataException($"{pindata} cannot be parsed as throw"); throw new InvalidDataException($"{pindata} cannot be parsed as throw");
} }
}
var pic = PinPicture.Create(pindata); var pic = PinPicture.Create(pindata);
return PinThrow.Create(playerId, pic, isBell, isSink); return PinThrow.Create(playerId, pic, isBell, isSink);

View File

@ -14,6 +14,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\GameData\GameData.csproj" />
<ProjectReference Include="..\GameHandler\GameHandler.csproj" /> <ProjectReference Include="..\GameHandler\GameHandler.csproj" />
<ProjectReference Include="..\GameModel\GameModel.csproj" /> <ProjectReference Include="..\GameModel\GameModel.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -1,5 +1,7 @@
// See https://aka.ms/new-console-template for more information // See https://aka.ms/new-console-template for more information
using Autofac;
using CommandLine; using CommandLine;
using GameData;
using GameHandler; using GameHandler;
using GameHandler.DeathGame; using GameHandler.DeathGame;
using GameHandler.Extensions; using GameHandler.Extensions;
@ -48,7 +50,7 @@ void NewGameAction()
var option = string.Empty; var option = string.Empty;
//do //do
//{ //{
var games = new GameService().GetGameHandler().Keys.Order().ToList(); var games = new GameService(null).GetGameHandler().Keys.Order().ToList();
games.Add("Abbreche"); games.Add("Abbreche");
option = AnsiConsole.Prompt( option = AnsiConsole.Prompt(
@ -76,7 +78,7 @@ void NewGameAction()
void StartGameAction(string gameName) void StartGameAction(string gameName)
{ {
_gs = new GameService(); _gs = new GameService(GetContainer());
var bs = _gs.Start(new[] { 1,2,3,4}, GetGameSettings(gameName), gameName ); var bs = _gs.Start(new[] { 1,2,3,4}, GetGameSettings(gameName), gameName );
@ -118,6 +120,13 @@ void StartGameAction(string gameName)
ShowMainMenu(); ShowMainMenu();
} }
IContainer GetContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<DummyExpenseRepository>().As<IExpenseRepository>();
return builder.Build();
}
IGameSettings GetGameSettings(string gameName) IGameSettings GetGameSettings(string gameName)
{ {
if (gameName == DeathGameHandler.GAMENAME_DEATHBOX) if (gameName == DeathGameHandler.GAMENAME_DEATHBOX)

View File

@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameModel.UnitTests", "Game
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KoogleCli", "KoogleCli\KoogleCli.csproj", "{3FF45A02-42F9-4E75-993B-6582DD2A22BF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KoogleCli", "KoogleCli\KoogleCli.csproj", "{3FF45A02-42F9-4E75-993B-6582DD2A22BF}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameData", "GameData\GameData.csproj", "{D026F84B-06F5-4BA4-8AB7-D1D385F0611C}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -39,6 +41,10 @@ Global
{3FF45A02-42F9-4E75-993B-6582DD2A22BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {3FF45A02-42F9-4E75-993B-6582DD2A22BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FF45A02-42F9-4E75-993B-6582DD2A22BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {3FF45A02-42F9-4E75-993B-6582DD2A22BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FF45A02-42F9-4E75-993B-6582DD2A22BF}.Release|Any CPU.Build.0 = Release|Any CPU {3FF45A02-42F9-4E75-993B-6582DD2A22BF}.Release|Any CPU.Build.0 = Release|Any CPU
{D026F84B-06F5-4BA4-8AB7-D1D385F0611C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D026F84B-06F5-4BA4-8AB7-D1D385F0611C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D026F84B-06F5-4BA4-8AB7-D1D385F0611C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D026F84B-06F5-4BA4-8AB7-D1D385F0611C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE