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
{
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()
{
return Data;
return IExpenseRepository.TestData;
}
}
}

View File

@ -23,16 +23,20 @@ namespace GameHandler
_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))
{
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 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>
<ItemGroup>
<PackageReference Include="Autofac" Version="7.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

View File

@ -70,7 +70,7 @@ namespace GameHandler.DeathGame
}
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)

View File

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

View File

@ -4,6 +4,19 @@ namespace GameModel.Contract
{
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();
}
}

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
namespace GameModel.Contracts
{
public interface IGameModel
{
{
int[] PlayerIds { get; }
}
}

View File

@ -7,5 +7,5 @@ using System.Threading.Tasks;
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 static ExpenseModel Create()
{
return new ExpenseModel(Array.Empty<MemberExpense>());
}
}
}

View File

@ -7,11 +7,11 @@ using System.Threading.Tasks;
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

@ -198,9 +198,12 @@ namespace GameModel
internal static PinPicture Create(string pindata)
{
if (!int.TryParse(pindata, out int dummy))
if (!string.IsNullOrEmpty(pindata))
{
throw new InvalidDataException($"{pindata} cannot be parsed as throw");
if (!int.TryParse(pindata, out int dummy))
{
throw new InvalidDataException($"{pindata} cannot be parsed as throw");
}
}
var states = new[] {

View File

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

View File

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

View File

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

View File

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