def get_full_description(self, kernel: "Kernel") -> str: weight = display_g_or_kg(self.weight) quantity_str = quantity_to_str(self.quantity, self.unit, kernel=kernel) return ( f"{self.name} " f"({quantity_str}, {weight}, {round(self.clutter, 3)} d'encombrement)" )
def get_name(self, kernel: "Kernel", quantity: bool = False) -> str: quantity_str = "" if self.resource_id: resource_properties = kernel.game.config.resources[ self.resource_id] if quantity: quantity_str = quantity_to_str(self.quantity, resource_properties.unit, kernel) quantity_str = f" ({quantity_str})" return f"{resource_properties.name}{quantity_str}" stuff_properties = kernel.game.stuff_manager.get_stuff_properties_by_id( self.stuff_id) if quantity: quantity_str = f" ({round(self.quantity)})" return f"{stuff_properties.name}{quantity_str}"
async def _describe(self, request: Request, hapic_data: HapicData) -> Description: # TODO BS 2019-09-30: check current char and near this build character = self._kernel.character_lib.get( hapic_data.path.character_id) build_doc = self._kernel.build_lib.get_build_doc( hapic_data.path.build_id) build_description = self._kernel.game.config.builds[build_doc.build_id] character_actions = self._kernel.build_lib.get_on_build_actions( character, hapic_data.path.build_id) on_construction = "" if build_doc.under_construction: on_construction = " (en construction)" carried_resources = self._kernel.resource_lib.get_stored_in_build( hapic_data.path.build_id) carried_in = [] for carried_resource in carried_resources: resource_description = self._kernel.game.config.resources[ carried_resource.id] quantity_str = quantity_to_str(carried_resource.quantity, unit=resource_description.unit, kernel=self._kernel) carried_in.append( Part(text=f"- {resource_description.name} ({quantity_str})")) if carried_in: carried_in.insert(0, Part(text="Contient des resources:")) carried_in.insert(1, Part(text="")) carried_in.append(Part(text=" ")) parts = carried_in parts.extend([ Part( text=action.get_as_str(), form_action=action.link, is_link=True, link_group_name=action.group_name, ) for action in character_actions ]) return Description(title=f"{build_description.name}{on_construction}", items=parts, can_be_back_url=True)
def check_request_is_possible( self, character: "CharacterModel", input_: BeginStuffModel ) -> None: self.check_is_possible(character) check_common_is_possible(self._kernel, description=self._description, character=character) cost = self.get_cost(character) if character.action_points < cost: raise ImpossibleAction( f"{character.name} no possède pas assez de points d'actions " f"({round(cost, 2)} nécessaires)" ) for consume in self._description.properties["consume"]: if "resource" in consume: resource_id = consume["resource"] resource_description = self._kernel.game.config.resources[resource_id] quantity = consume["quantity"] quantity_str = quantity_to_str(quantity, resource_description.unit, self._kernel) if not self._kernel.resource_lib.have_resource( character.id, resource_id=resource_id, quantity=quantity ): resource_description = self._kernel.game.config.resources[resource_id] raise ImpossibleAction( f"Vous ne possédez pas assez de {resource_description.name}: {quantity_str} nécessaire(s)" ) elif "stuff" in consume: stuff_id = consume["stuff"] quantity = consume["quantity"] if ( self._kernel.stuff_lib.have_stuff_count(character.id, stuff_id=stuff_id) < quantity ): stuff_properties = self._kernel.game.stuff_manager.get_stuff_properties_by_id( stuff_id ) raise ImpossibleAction( f"Vous ne possédez pas assez de {stuff_properties.name}: {quantity} nécessaire(s)" )
def check_request_is_possible(self, character: "CharacterModel", input_: BuildModel) -> None: check_common_is_possible( kernel=self._kernel, description=self._description, character=character ) build_id = self._description.properties["build_id"] build_description = self._kernel.game.config.builds[build_id] if character.action_points < self.get_cost(character, input_): raise ImpossibleAction("Pas assez de points d'actions") for require in build_description.build_require_resources: if not self._kernel.resource_lib.have_resource( character.id, resource_id=require.resource_id, quantity=require.quantity ): resource_properties = self._kernel.game.config.resources[require.resource_id] required_quantity_str = quantity_to_str( require.quantity, resource_properties.unit, self._kernel ) raise ImpossibleAction( f"Vous ne possedez pas assez de {resource_properties.name} " f"({required_quantity_str} requis)" )
def get_character_actions( self, character: "CharacterModel", build_id: int ) -> typing.List[CharacterActionLink]: actions: typing.List[CharacterActionLink] = [] build_doc = self._kernel.build_lib.get_build_doc(build_id) build_description = self._kernel.game.config.builds[build_doc.build_id] for required_resource in build_description.build_require_resources: resource_description, left, left_percent = self.get_resource_infos( self._kernel, required_resource, build_doc=build_doc ) if left <= 0: continue left_str = quantity_to_str(left, resource_description.unit, kernel=self._kernel) query_params = BringResourcesOnBuild.input_model_serializer.dump( BringResourcesOnBuild.input_model(resource_id=required_resource.resource_id) ) name = ( f"Apporter {resource_description.name} pour la construction " f"(manque {left_str} soit {round(left_percent)}%)" ) actions.append( CharacterActionLink( name=name, link=get_with_build_action_url( character_id=character.id, build_id=build_id, action_type=ActionType.BRING_RESOURCE_ON_BUILD, action_description_id=self._description.id, query_params=query_params, ), cost=None, ) ) return actions
def perform( self, character: "CharacterModel", build_id: int, input_: typing.Any ) -> Description: build_doc = self._kernel.build_lib.get_build_doc(build_id) if input_.quantity is None: build_description = self._kernel.game.config.builds[build_doc.build_id] required_resource = next( ( brr for brr in build_description.build_require_resources if brr.resource_id == input_.resource_id ) ) resource_description, left, left_percent = self.get_resource_infos( self._kernel, required_resource, build_doc=build_doc ) left_str = quantity_to_str(left, resource_description.unit, kernel=self._kernel) unit_str = self._kernel.translation.get(resource_description.unit) return Description( title=f"Cette construction nécessite encore {left_str} " f"de {resource_description.name} (soit {round(left_percent)}%)", can_be_back_url=True, items=[ Part( is_form=True, form_values_in_query=True, form_action=get_with_build_action_url( character_id=character.id, build_id=build_id, action_type=ActionType.BRING_RESOURCE_ON_BUILD, action_description_id=self._description.id, query_params=self.input_model_serializer.dump(input_), ), items=[ Part( label=f"Quantité ({unit_str}) ?", type_=Type.NUMBER, name="quantity" ) ], ) ], ) resource_description = self._kernel.game.config.resources[input_.resource_id] try: self._kernel.resource_lib.reduce_carried_by( character.id, resource_id=input_.resource_id, quantity=input_.quantity, commit=False ) except (NotEnoughResource, NoCarriedResource): raise ImpossibleAction( f"{character.name} ne possède pas assez de {resource_description.name}" ) self._kernel.resource_lib.add_resource_to( build_id=build_doc.id, resource_id=input_.resource_id, quantity=input_.quantity, commit=False, ) self._kernel.server_db_session.commit() build_description = self._kernel.game.config.builds[build_doc.build_id] quantity_str = quantity_to_str( input_.quantity, resource_description.unit, kernel=self._kernel ) return Description( title=f"{quantity_str} {resource_description.name} déposé pour {build_description.name}", items=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( label="Voir le batiment", is_link=True, form_action=DESCRIBE_BUILD.format( build_id=build_doc.id, character_id=character.id ), ), ], force_back_url=f"/_describe/character/{character.id}/build_actions", )
def _perform( self, character: "CharacterModel", description: ActionDescriptionModel, input_: CraftInput, cost: float, dry_run: bool = True, ) -> None: if character.action_points < cost: raise ImpossibleAction( f"{character.name} no possède pas assez de points d'actions " f"({round(cost, 2)} nécessaires)" ) carried_resources = self._kernel.resource_lib.get_carried_by(character.id) carried_stuffs = self._kernel.stuff_lib.get_carried_by(character.id) for require in description.properties["require"]: if "stuff" in require: required_quantity = input_.quantity * int(require["quantity"]) stuff_id = require["stuff"] stuff_properties = self._kernel.game.stuff_manager.get_stuff_properties_by_id( stuff_id ) carried_stuffs = [c for c in carried_stuffs if c.stuff_id == stuff_id] owned_quantity = len(carried_stuffs) if owned_quantity < required_quantity: raise ImpossibleAction( f"Vous ne possédez pas assez de {stuff_properties.name}: {required_quantity} nécessaire(s)" ) if not dry_run: for i in range(required_quantity): stuff_to_destroy = carried_stuffs[i] self._kernel.stuff_lib.destroy(stuff_to_destroy.id) elif "resource" in require: required_quantity = input_.quantity * require["quantity"] resource_id = require["resource"] resource_properties = self._kernel.game.config.resources[resource_id] try: carried_resource = next((c for c in carried_resources if c.id == resource_id)) except StopIteration: raise ImpossibleAction(f"Vous ne possédez pas de {resource_properties.name}") if carried_resource.quantity < required_quantity: missing_quantity_str = quantity_to_str( kernel=self._kernel, quantity=(required_quantity - carried_resource.quantity), unit=carried_resource.unit, ) raise ImpossibleAction( f"Vous ne possédez pas assez de {carried_resource.name}: {missing_quantity_str} nécessaire(s)" ) if not dry_run: self._kernel.resource_lib.reduce_carried_by( character_id=character.id, resource_id=resource_id, quantity=required_quantity, ) if dry_run: return for produce in description.properties["produce"]: stuff_id = produce["stuff"] quantity = produce["quantity"] stuff_properties = self._kernel.game.stuff_manager.get_stuff_properties_by_id(stuff_id) for i in range(int(quantity)): stuff_doc = self._kernel.stuff_lib.create_document_from_stuff_properties( properties=stuff_properties, world_row_i=character.world_row_i, world_col_i=character.world_col_i, zone_row_i=character.zone_row_i, zone_col_i=character.zone_col_i, ) self._kernel.stuff_lib.add_stuff(stuff_doc, commit=False) self._kernel.stuff_lib.set_carried_by__from_doc( stuff_doc, character_id=character.id, commit=False ) self._kernel.character_lib.reduce_action_points( character_id=character.id, cost=cost, commit=False ) self._kernel.server_db_session.commit()
def perform(self, character: "CharacterModel", input_: BeginStuffModel) -> Description: if not input_.description: require_txts = [] for consume in self._description.properties["consume"]: if "resource" in consume: resource_id = consume["resource"] resource_description = self._kernel.game.config.resources[resource_id] quantity_str = quantity_to_str( consume["quantity"], resource_description.unit, self._kernel ) require_txts.append(f"{quantity_str} de {resource_description.name}") elif "stuff" in consume: stuff_id = consume["stuff"] stuff_properties = self._kernel.game.stuff_manager.get_stuff_properties_by_id( stuff_id ) require_txts.append(f"{consume['quantity']} de {stuff_properties.name}") return Description( title=f"Commencer {self._description.name}", items=[ Part( is_form=True, form_values_in_query=True, form_action=get_character_action_url( character_id=character.id, action_type=ActionType.BEGIN_STUFF_CONSTRUCTION, query_params={}, action_description_id=self._description.id, ), items=[Part(text="Consommera :")] + [Part(text=txt) for txt in require_txts] + [ Part( label=f"Vous pouvez fournir une description de l'objet", type_=Type.STRING, name="description", default_value=self._description.properties["default_description"], ) ], ) ], ) for consume in self._description.properties["consume"]: if "resource" in consume: resource_id = consume["resource"] self._kernel.resource_lib.reduce_carried_by( character.id, resource_id=resource_id, quantity=consume["quantity"], commit=False, ) elif "stuff" in consume: stuff_id = consume["stuff"] carried_stuffs = self._kernel.stuff_lib.get_carried_by( character.id, stuff_id=stuff_id ) for i in range(consume["quantity"]): self._kernel.stuff_lib.destroy(carried_stuffs[i].id, commit=False) stuff_id = self._description.properties["produce_stuff_id"] stuff_properties = self._kernel.game.stuff_manager.get_stuff_properties_by_id(stuff_id) stuff_doc = self._kernel.stuff_lib.create_document_from_stuff_properties( properties=stuff_properties, world_row_i=character.world_row_i, world_col_i=character.world_col_i, zone_row_i=character.zone_row_i, zone_col_i=character.zone_col_i, ) stuff_doc.description = input_.description or "" stuff_doc.carried_by_id = character.id stuff_doc.ap_spent = 0.0 stuff_doc.ap_required = self._description.properties["craft_ap"] stuff_doc.under_construction = True self._kernel.stuff_lib.add_stuff(stuff_doc, commit=False) self._kernel.character_lib.reduce_action_points( character.id, cost=self.get_cost(character), commit=False ) self._kernel.server_db_session.commit() return Description( title=f"{stuff_properties.name} commencé", footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Voir l'objet commencé", form_action=DESCRIBE_LOOK_AT_STUFF_URL.format( character_id=character.id, stuff_id=stuff_doc.id ), classes=["primary"], ), ], force_back_url=f"/_describe/character/{character.id}/on_place_actions", )