KoogleV4/GameHandler/GameService.cs

182 lines
6.2 KiB
C#

using GameHandler.Extensions;
using GameModel;
using GameModel.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using GameHandler.GameHandler;
using GameHandler.Parser;
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 _rootContainer { get; set; }
private bool _isStarted = false;
private ILifetimeScope _scope;
private IGameHandler _gh;
private ThrowHandler _th;
private ExpenseHandler _eh;
private GameStateHandler _gameStateHandler;
private Game _game;
public GameState GameModel { get => _gameStateHandler.GameState; }
public GameService(IContainer rootContainer = null)
{
_rootContainer = rootContainer;
}
public string ThrowModeName
{
get
{
if (_gameStateHandler.GameState != null)
{
return _gameStateHandler.GameState.ThrowState.BoardState.ThrowMode == ThrowMode.Decrease ? "Abräumen" : "Volle";
}
return string.Empty;
}
}
static int[] defaultPlayerIds => new[] {1,2,3,4};
public async Task<GameState> Start(string gameName = FreeGameHandler.GAMENAME_FREETRAINING)
{
return await Start(defaultPlayerIds, new DeathGameSettings(6), gameName);
}
public async Task<GameState> Start(int[] playerIds, IGameSettings gameSettings, string gameName = FreeGameHandler.GAMENAME_FREETRAINING)
{
if (_isStarted)
{
throw new InvalidGameStateExcpetion("Game already started");
}
_isStarted = true;
InitGameServiceBehaviour(gameName);
var state = await InitGameState(playerIds, gameSettings, gameName);
await _gameStateHandler.Add(state);
await _gameStateHandler.Add(ExpenseModel.Create());
return state;
}
private async Task<GameState> InitGameState(int[] playerIds, IGameSettings gameSettings, string gameName)
{
var gm = _gh.InitGameModel(playerIds, gameSettings);
var throwState = ThrowState.Create(_gh.ThrowMode(), _gh.ThrowsPerRount());
_game = await _gameStateHandler.CreateNewGame(gameName);
return GameState.Create(_game.Id, gameName, throwState, _gh.GetCurrentPlayerId(gm), gm);
}
private void InitGameServiceBehaviour(string gameName)
{
_scope = _rootContainer?.BeginLifetimeScope();
_gh = this.GetGameHandler(gameName);
_gh.GameExpenseOccured += _gh_GameExpenseOccured;
_th = new ThrowHandler();
_eh = new ExpenseHandler(_scope.Resolve<IExpenseRepository>());
_gameStateHandler = new GameStateHandler(_scope.Resolve<IGameRepository>(), _scope.Resolve<IExpenseRepository>());
}
private void _gh_GameExpenseOccured(object? sender, EventArgs e)
{
var expenseModel = _eh.HandleGameExenseEventArgs(e as GameExenseEventArgs, _gameStateHandler.ExpenseModel).Result;
_gameStateHandler.Add(expenseModel);
//_lastState = _lastState with { ExpenseModel = expenseModel };
}
public async Task<GameState> HandleThrow(PinThrow pinThrow)
{
if (!_isStarted)
{
throw new InvalidGameStateExcpetion("Game not started");
}
var lastGameState = _gameStateHandler.GameState;
var boardStateBeforeUpdate = lastGameState.ThrowState.BoardState;
pinThrow = AutoCompletePlayerId(pinThrow);
var throwStateAfterUpdate = _th.Update(lastGameState.ThrowState, pinThrow);
var gameModel = _gh.Update(pinThrow, lastGameState.GameModel, boardStateBeforeUpdate, throwStateAfterUpdate);
var expenseModel = _eh.CheckThrow(throwStateAfterUpdate.BoardState, pinThrow, gameModel.PlayerIds, _gameStateHandler.ExpenseModel);
var newGameState = lastGameState with { ThrowState = throwStateAfterUpdate, GameModel = gameModel, NextPlayerId = _gh.GetCurrentPlayerId(gameModel) };
await _gameStateHandler.Add(expenseModel);
await _gameStateHandler.Add(newGameState);
return newGameState;
}
private PinThrow AutoCompletePlayerId(PinThrow pinThrow)
{
if (_gh.FreePlayerSelection() && pinThrow.PlayerId == 0)
{
throw new InvalidPinThrowException("PlayerId connot be 0");
}
if (_gh.FreePlayerSelection())
{
return pinThrow;
}
return pinThrow with { PlayerId = _gh.GetCurrentPlayerId(_gameStateHandler.GameState.GameModel) };
}
public void Stop()
{
if (!_isStarted)
{
throw new InvalidGameStateExcpetion("Game not started");
}
_isStarted = false;
_scope?.Dispose();
}
public ThrowCommandData ParseThrowData(string stringData)
{
return ThrowCommandParser.Parse(stringData, _gh.FreePlayerSelection(), 0);
}
public async Task<GameState> Load(Guid gameId)
{
Game game = null;
using (var scope = _rootContainer?.BeginLifetimeScope())
{
var gs = new GameStateHandler(scope.Resolve<IGameRepository>(), scope.Resolve<IExpenseRepository>());
game = await gs.LoadGame(gameId);
}
if (game == null)
{
return null;
}
_game = game;
InitGameServiceBehaviour(game.GameName);
var res = await _gameStateHandler.LoadState(game.Id);
_isStarted = res != null;
return res;
}
public bool FreePlayerSelection => _gh.FreePlayerSelection();
}
}