# Path: modules/game/Colour.py

# 
# Path: modules/game/Player.py
# class Player(NamedTuple('Player', [
#     ('id', 'PlayerID'),
#     ('titled', bool),
#     ('engine', bool),
#     ('gamesPlayed', int)])):
# class PlayerBSONHandler:
# class PlayerDB(NamedTuple('PlayerDB', [
#         ('playerColl', 'Collection')
#     ])):
#     def fromJson(userData: Dict):
#     def reads(bson: Dict) -> Player:
#     def writes(player: Player) -> Dict:
#     def byId(self, playerId: PlayerID) -> Opt[Player]:
#     def byPlayerId(self, playerId: PlayerID) -> Opt[Player]:
#     def unmarkedByUserIds(self, playerIds: List[PlayerID]) -> List[Player]:
#     def engineSample(self, engine: bool, size: int) -> List[Player]:
#     def oldestNonEngine(self) -> Opt[Player]:
#     def byEngine(self, engine: bool = True) -> List[Player]:
#     def all(self) -> List[Player]:
#     def write(self, player: Player):
# 
# Path: modules/game/EngineEval.py
# class EngineEval(NamedTuple('EngineEval', [
#         ('cp', Opt[Number]),
#         ('mate', Opt[int])
#     ])):
#     @staticmethod
#     def fromDict(d: Dict):
#         return EngineEval(d.get('cp', None), d.get('mate', None))
# 
#     def asdict(self) -> Dict:
#         return {'cp': self.cp} if self.cp is not None else {'mate': self.mate}
# 
#     def inverse(self):
#         return EngineEval(-self.cp if self.cp is not None else None,
#             -self.mate if self.mate is not None else None)
# 
#     def winningChances(self, colour: Colour) -> Number:
#         if self.mate is not None:
#             base = (1 if self.mate > 0 else 0)
#         else:
#             base = 1 / (1 + exp(-0.004 * self.cp))
#         return 100*(base if colour else (1-base))
# 
# class EngineEvalBSONHandler:
#     @staticmethod
#     def reads(bson: Dict) -> List[EngineEval]:
#         return EngineEval.fromDict(bson)
# 
#     def writes(engineEval: EngineEval) -> Dict:
#         return engineEval.asdict()


from default_imports import *
from modules.game.Colour import Colour
from modules.game.Player import PlayerID
from modules.game.EngineEval import EngineEval, EngineEvalBSONHandler
from pymongo.collection import Collection
from multiprocessing import Pool
from chess.pgn import read_game
            from StringIO import StringIO
            from io import StringIO
import math
import chess
import numpy as np





GameID = NewType('GameID', str)
Emt = NewType('Emt', int)
Analysis = NewType('Analysis', Opt[List[EngineEval]])

MoveTensor = NewType('MoveTensor', List[Number])
GameTensor = NewType('GameTensor', List[MoveTensor])

class Game(NamedTuple('Game', [
        ('id', GameID),
        ('white', PlayerID),
        ('black', PlayerID),
        ('pgn', List[str]),
        ('emts', Opt[List[Emt]]),
        ('analysis', Analysis)
    ])):
    @staticmethod
    def fromDict(d: Dict):
        return Game(
            id=d['id'],
            white=d['white'],
            black=d['black'],
            pgn=d['pgn'].split(' '),
            emts=d['emts'],

# Path: modules/game/Colour.py

# 
# Path: modules/game/Player.py
# class Player(NamedTuple('Player', [
#     ('id', 'PlayerID'),
#     ('titled', bool),
#     ('engine', bool),
#     ('gamesPlayed', int)])):
# class PlayerBSONHandler:
# class PlayerDB(NamedTuple('PlayerDB', [
#         ('playerColl', 'Collection')
#     ])):
#     def fromJson(userData: Dict):
#     def reads(bson: Dict) -> Player:
#     def writes(player: Player) -> Dict:
#     def byId(self, playerId: PlayerID) -> Opt[Player]:
#     def byPlayerId(self, playerId: PlayerID) -> Opt[Player]:
#     def unmarkedByUserIds(self, playerIds: List[PlayerID]) -> List[Player]:
#     def engineSample(self, engine: bool, size: int) -> List[Player]:
#     def oldestNonEngine(self) -> Opt[Player]:
#     def byEngine(self, engine: bool = True) -> List[Player]:
#     def all(self) -> List[Player]:
#     def write(self, player: Player):
# 
# Path: modules/game/EngineEval.py
# class EngineEval(NamedTuple('EngineEval', [
#         ('cp', Opt[Number]),
#         ('mate', Opt[int])
#     ])):
#     @staticmethod
#     def fromDict(d: Dict):
#         return EngineEval(d.get('cp', None), d.get('mate', None))
# 
#     def asdict(self) -> Dict:
#         return {'cp': self.cp} if self.cp is not None else {'mate': self.mate}
# 
#     def inverse(self):
#         return EngineEval(-self.cp if self.cp is not None else None,
#             -self.mate if self.mate is not None else None)
# 
#     def winningChances(self, colour: Colour) -> Number:
#         if self.mate is not None:
#             base = (1 if self.mate > 0 else 0)
#         else:
#             base = 1 / (1 + exp(-0.004 * self.cp))
#         return 100*(base if colour else (1-base))
# 
# class EngineEvalBSONHandler:
#     @staticmethod
#     def reads(bson: Dict) -> List[EngineEval]:
#         return EngineEval.fromDict(bson)
# 
#     def writes(engineEval: EngineEval) -> Dict:
#         return engineEval.asdict()


# Path: modules/game/Game.py
from default_imports import *
from modules.game.Colour import Colour
from modules.game.Player import PlayerID
from modules.game.EngineEval import EngineEval, EngineEvalBSONHandler
from pymongo.collection import Collection
from multiprocessing import Pool
from chess.pgn import read_game
            from StringIO import StringIO
            from io import StringIO
import math
import chess
import numpy as np






GameID = NewType('GameID', str)
Emt = NewType('Emt', int)
Analysis = NewType('Analysis', Opt[List[EngineEval]])

MoveTensor = NewType('MoveTensor', List[Number])
GameTensor = NewType('GameTensor', List[MoveTensor])

class Game(NamedTuple('Game', [
        ('id', GameID),
        ('white', PlayerID),
        ('black', PlayerID),
        ('pgn', List[str]),
        ('emts', Opt[List[Emt]]),
        ('analysis', Analysis)
    ])):
    @staticmethod
    def fromDict(d: Dict):
        return Game(
            id=d['id'],
            white=d['white'],
            black=d['black'],
            pgn=d['pgn'].split(' '),
            emts=d['emts'],

            analysis=None if d.get('analysis') is None else [EngineEval.fromDict(a) for a in d['analysis']]