# coding: utf-8 import typing from _elementtree import Element from lxml import etree from synergine2.config import Config from synergine2.log import get_logger from opencombat.simulation.base import TileStrategySimulation from opencombat.simulation.subject import TileSubject from opencombat.strategy.team.model import TeamModel from opencombat.strategy.team.stash import TeamStash from opencombat.strategy.unit.stash import UnitStash from opencombat.util import get_class_from_string_path, pretty_xml from opencombat.xml import XmlValidator class Troop(object): def __init__( self, config: Config, state_root: Element, simulation: TileStrategySimulation, ) -> None: self._config = config self._state_root = state_root self._subjects = None # type: typing.List[TileSubject] self._simulation = simulation self._builder = TroopClassBuilder(config) @property def subjects(self) -> typing.List[TileSubject]: if self._subjects is None: self._subjects = self._get_computed_subjects() return self._subjects def _get_computed_subjects(self) -> typing.List[TileSubject]: units_file_path = self._config.get( 'global.units', 'opencombat/strategy/units.xml', ) teams_file_path = self._config.get( 'global.teams', 'opencombat/strategy/teams.xml', ) team_stash = self._builder.get_team_stash( units_file_path, teams_file_path, ) # Parse team, build Subjects subjects = [] # type: typing.List[TileSubject] for troop in self._state_root.findall('troop'): country = troop.attrib['country'] team_id = troop.attrib['team_id'] team = team_stash.get_team(team_id, country) for unit in team.units: subject = unit.class_(self._config, self._simulation) properties = \ self._simulation.get_default_properties_for_country( country, ) subject.properties.update(properties) subjects.append(subject) return subjects class TroopDumper(object): def __init__( self, config: Config, ) -> None: self._config = config self._logger = get_logger('TroopDumper', config) def get_troop_dump( self, countries_troops: typing.Dict[str, typing.List[TeamModel]], ) -> str: troops_template = self._config.resolve( 'global.troops_template', 'opencombat/strategy/troops_template.xml', ) with open(troops_template, 'r') as xml_file: template_str = xml_file.read() parser = etree.XMLParser(remove_blank_text=True) state_root = etree.fromstring( template_str.encode('utf-8'), parser, ) for country, teams in countries_troops.items(): for team in teams: troop_element = etree.SubElement(state_root, 'troop') troop_element.attrib['country'] = country troop_element.attrib['team_id'] = team.id return pretty_xml( etree.tostring( state_root, ).decode('utf-8'), ) class TroopClassBuilder(object): def __init__( self, config: Config, ) -> None: self._logger = get_logger('TroopManagerBuilder', config) self._config = config def get_unit_stash( self, units_file_path: str, ) -> UnitStash: class_address = self._config.resolve( 'global.unit_stash', 'opencombat.strategy.unit.stash.UnitStash', ) class_ = get_class_from_string_path( self._config, class_address, ) return class_( self._config, units_file_path, ) def get_team_stash( self, units_file_path: str, teams_file_path: str, ) -> TeamStash: class_address = self._config.resolve( 'global.team_stash', 'opencombat.strategy.team.stash.TeamStash', ) class_ = get_class_from_string_path( self._config, class_address, ) unit_stash = self.get_unit_stash(units_file_path) return class_( self._config, teams_file_path, unit_stash=unit_stash, ) def get_troop_dumper(self) -> TroopDumper: class_address = self._config.resolve( 'global.troop_dumper', 'opencombat.strategy.troops.TroopDumper', ) class_ = get_class_from_string_path( self._config, class_address, ) return class_( self._config, ) class TroopLoader(object): def __init__( self, config: Config, simulation: TileStrategySimulation, ) -> None: self._logger = get_logger('TroopLoader', config) self._config = config self._simulation = simulation schema_file_path = self._config.get( 'global.troop_schema', 'opencombat/strategy/troops.xsd', ) self._xml_validator = XmlValidator( config, schema_file_path, ) def get_troop( self, troop_file_path: str, ) -> Troop: return Troop( self._config, self._validate_and_return_state_element(troop_file_path), self._simulation, ) def _validate_and_return_state_element( self, troop_file_path: str, ) -> Element: return self._xml_validator.validate_and_return(troop_file_path) class TroopConstructorBuilder(object): def __init__( self, config: Config, simulation: TileStrategySimulation, ) -> None: self._logger = get_logger('TroopConstructorBuilder', config) self._config = config self._simulation = simulation def get_troop_loader( self, ) -> TroopLoader: class_address = self._config.resolve( 'global.troop_loader', 'opencombat.strategy.troops.TroopLoader', ) troop_loader_class = get_class_from_string_path( self._config, class_address, ) return troop_loader_class( self._config, self._simulation, )