def perform(self, character: "CharacterModel", resource_id: str, input_: input_model) -> Description: # TODO BS 2019-09-09: perfs carried_resources = self._kernel.resource_lib.get_carried_by( character.id) carried_resource = next( (r for r in carried_resources if r.id == resource_id)) if input_.quantity is None: unit_trans = self._kernel.translation.get(carried_resource.unit) return Description( title=carried_resource.get_full_description(self._kernel), items=[ Part( is_form=True, form_values_in_query=True, form_action=get_with_resource_action_url( character_id=character.id, action_type=ActionType.DROP_RESOURCE, resource_id=resource_id, query_params={}, action_description_id=self._description.id, ), items=[ Part( label= f"Quantité à laisser ici ({unit_trans}) ?", type_=Type.NUMBER, name="quantity", default_value=str(carried_resource.quantity), ) ], ) ], ) self._kernel.resource_lib.drop( character.id, resource_id, quantity=input_.quantity, 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, ) return Description( title=f"Action effectué", footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Voir l'inventaire", form_action= f"/_describe/character/{character.id}/inventory", classes=["primary"], ), ], )
def perform(self, character: "CharacterModel", stuff: "StuffModel", input_: input_model) -> Description: footer_links = [ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Voir l'inventaire", form_action=f"/_describe/character/{character.id}/inventory", ), Part( is_link=True, label="Voir l'objet", form_action=DESCRIBE_LOOK_AT_STUFF_URL.format( character_id=character.id, stuff_id=stuff.id), classes=["primary"], ), ] try: self._kernel.stuff_lib.empty_stuff(stuff) except CantEmpty as exc: return Description(title=str(exc), footer_links=footer_links) return Description(title=f"{stuff.name} vidé(e)", footer_links=footer_links)
def perform(self, character: "CharacterModel", stuff: "StuffModel", input_: input_model) -> Description: footer_links = [ Part( is_link=True, label="Voir l'inventaire", form_action=f"/_describe/character/{character.id}/inventory", ), Part( is_link=True, label="Voir l'objet", form_action=DESCRIBE_LOOK_AT_STUFF_URL.format( character_id=character.id, stuff_id=stuff.id), classes=["primary"], ), Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), ] try: self._kernel.stuff_lib.fill_stuff_with_resource( stuff, input_.resource_id) except CantFill as exc: return Description(title=str(exc), footer_links=footer_links) resource_description = self._kernel.game.config.resources[ input_.resource_id] return Description( title=f"{stuff.name} rempli(e) avec {resource_description.name}", footer_links=footer_links, )
def perform(self, character: "CharacterModel", input_: CheatsModel) -> Description: if input_.cheat_id == "increase_ap": character_doc = self._kernel.character_lib.get_document( character.id) character_doc.action_points = 24.0 self._kernel.server_db_session.add(character_doc) self._kernel.server_db_session.commit() return Description( title="Points d'actions rechargés", footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements") ], ) if input_.cheat_id == "reduce_tiredness": self._kernel.character_lib.reduce_tiredness(character.id, 100) return Description( title="Plus de fatigue", footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements") ], )
def perform(self, character: "CharacterModel", input_: input_model) -> Description: character_doc = self._character_lib.get_document(character.id) resource, resource_extraction_description, cost_per_unit = self._get_resource_and_cost( character_doc, input_) if input_.quantity is None: unit_name = self._kernel.translation.get(resource.unit) return Description( title=f"Récupérer du {resource.name}", items=[ Part( is_form=True, form_values_in_query=True, form_action=get_character_action_url( character_id=character.id, action_type=ActionType.COLLECT_RESOURCE, action_description_id=self._description.id, query_params=self.input_model_serializer.dump( input_), ), items=[ Part( label= f"Quantité (coût: {cost_per_unit} par {unit_name}) ?", type_=Type.NUMBER, name="quantity", ) ], ) ], ) self._kernel.resource_lib.add_resource_to( character_id=character_doc.id, resource_id=input_.resource_id, quantity=input_.quantity, commit=False, ) cost = self.get_cost(character, input_=input_) if cost is None: raise RollingError("Cost compute should not be None !") self._kernel.character_lib.reduce_action_points(character.id, cost, commit=False) self._kernel.server_db_session.commit() return Description( title= f"{input_.quantity} {self._kernel.translation.get(resource.unit)} récupéré", footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements") ], )
def with_multiple_carried_stuffs( action: "WithStuffAction", kernel: "Kernel", character: "CharacterModel", stuff: "StuffModel", input_: typing.Any, action_type: "ActionType", do_for_one_func: typing.Callable[ ["CharacterModel", "StuffModel", typing.Any], typing.List["Part"]], title: str, success_parts: typing.List["Part"], ) -> Description: all_carried = kernel.stuff_lib.get_carried_by(character.id, stuff_id=stuff.stuff_id) if len(all_carried) > 1 and input_.quantity is None: return Description( title=title, items=[ Part( text= f"Vous possedez {len(all_carried)} {stuff.name}, éxécuter cette action sur combien ?" ), Part( is_form=True, form_action=get_with_stuff_action_url( character_id=character.id, action_type=action_type, stuff_id=stuff.id, query_params=action.input_model_serializer.dump( input_), action_description_id=action.description.id, ), submit_label="Continuer", form_values_in_query=True, items=[ Part(label="Quantité", name="quantity", type_=Type.NUMBER, default_value="1") ], ), Part(is_link=True, label=f"Faire ça avec les {len(all_carried)}"), ], ) if input_.quantity is not None: do_it_count = input_.quantity else: do_it_count = 1 parts = [] for i in range(do_it_count): parts.extend(do_for_one_func(character, all_carried[i], input_)) return Description(title=title, items=parts + success_parts)
async def create(self, request: Request, hapic_data: HapicData) -> Description: if hapic_data.query.with_character_id: # FIXME BS NOW: code it with_character = self._kernel.character_lib.get( hapic_data.query.with_character_id) title = f"Faire une offre à {with_character.name}" form_action = ( f"/business/{hapic_data.path.character_id}/offers-create" f"?with_character_id={with_character.id}") else: title = "Créer une offre" form_action = f"/business/{hapic_data.path.character_id}/offers-create?permanent=1" if hapic_data.body.title: offer = self._kernel.business_lib.create_draft( hapic_data.path.character_id, hapic_data.body.title, permanent=hapic_data.query.permanent, with_character_id=hapic_data.query.with_character_id, ) return Description( redirect= f"/business/{hapic_data.path.character_id}/offers/{offer.id}") return Description( title=title, items=[ Part( is_form=True, form_action=form_action, items=[ Part( label="Veuillez choisir un nom pour cette offre", name="title", type_=Type.STRING, ) ], ) ], footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Retourner sur la page Commerce", form_action=f"/business/{hapic_data.path.character_id}", ), ], )
def perform(self, character: "CharacterModel", stuff: "StuffModel", input_: input_model) -> Description: character_doc = self._character_lib.get_document(character.id) effects: typing.List[ CharacterEffectDescriptionModel] = self._description.properties[ "effects"] self._kernel.stuff_lib.destroy(stuff.id, commit=False) for effect in effects: self._effect_manager.enable_effect(character_doc, effect) self._kernel.server_db_session.add(character_doc) self._kernel.server_db_session.commit() return Description( title="Action effectué", footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Voir l'inventaire", form_action= f"/_describe/character/{character.id}/inventory", classes=["primary"], ), ], )
def perform( self, character: "CharacterModel", with_character: "CharacterModel", input_: TeachKnowledgeModel, ) -> Description: knowledge_description = self._kernel.game.config.knowledge[ input_.knowledge_id] if self._kernel.character_lib.increase_knowledge_progress( with_character.id, input_.knowledge_id, ap=int(input_.ap * knowledge_description.instructor_coeff), ): title = "Connaissance acquise !" else: title = "Apprentissage effectué" self._kernel.character_lib.reduce_action_points(character.id, cost=input_.ap) self._kernel.character_lib.reduce_action_points(with_character.id, cost=input_.ap) return Description( title=title, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements") ], )
def perform(self, character: "CharacterModel", input_: typing.Any) -> Description: build_id = self._description.properties["build_id"] build_description = self._kernel.game.config.builds[build_id] build_doc = self._kernel.build_lib.place_build( 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, build_id=build_description.id, under_construction=True, ) self._kernel.character_lib.reduce_action_points( character_id=character.id, cost=self.get_cost(character, input_) ) return Description( title=f"{build_description.name} commencé", 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", )
async def main_page(self, request: Request, hapic_data: HapicData) -> Description: offer_count = self._kernel.business_lib.get_offers_query( hapic_data.path.character_id, statuses=[OfferStatus.OPEN, OfferStatus.DRAFT, OfferStatus.CLOSED], ).count() transaction_count = self._kernel.business_lib.get_transactions_query( hapic_data.path.character_id).count() transaction_label = f"Voir les transactions en attente ({transaction_count} en cours)" if (self._kernel.business_lib.get_incoming_transactions_query( hapic_data.path.character_id).filter( OfferDocument.read == False).count()): transaction_label = f"*{transaction_label}" return Description( title="Commerce", items=[ Part( label= f"Voir les offres que vous proposez ({offer_count} en cours)", is_link=True, form_action= f"/business/{hapic_data.path.character_id}/offers", ), Part( label=transaction_label, is_link=True, form_action= f"/business/{hapic_data.path.character_id}/transactions", ), ], can_be_back_url=True, )
def perform(self, character: "CharacterModel", with_character: "CharacterModel", input_: typing.Any) -> Description: self._kernel.character_lib.kill(with_character.id) return Description( title=f"Vous avez tué {with_character.name}", footer_links=[Part(is_link=True, go_back_zone=True)], )
async def remove_item(self, request: Request, hapic_data: HapicData) -> Description: # TODO: check is owner self._kernel.business_lib.get_offer_item_query( hapic_data.path.item_id).delete() return Description( redirect= f"/business/{hapic_data.path.character_id}/offers/{hapic_data.path.offer_id}" )
async def see(self, request: Request, hapic_data: HapicData) -> Description: # TODO: check can see offer (same zone) offer: OfferDocument = self._kernel.business_lib.get_offer_query( hapic_data.path.offer_id).one() offer_owner = self._kernel.character_lib.get_document( offer.character_id) if hapic_data.query.mark_as_read: self._kernel.business_lib.mark_as_read(offer.id) parts = self._produce_offer_parts(offer.character_id, hapic_data.path.character_id, offer, editing=False) if not self._kernel.business_lib.owner_can_deal(offer.id): parts.append( Part( label= f"{offer_owner.name} ne peut pas assurer cette opération")) if self._kernel.business_lib.character_can_deal( hapic_data.path.character_id, offer.id): parts.append( Part( is_link=True, label="Effectuer une transaction", form_action=(f"/business/{hapic_data.path.character_id}" f"/see-offer/{offer.id}/{offer.id}/deal"), )) else: parts.append( Part(label="Vous ne possédez pas de quoi faire un marché")) with_str = "" if offer.to_character: with_str = f" ({offer.to_character.name})" title = f"{offer.title}{with_str}" return Description( title=title, items=parts, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Retourner sur la page Commerce", form_action=f"/business/{hapic_data.path.character_id}", classes=["primary"], ), ], can_be_back_url=True, )
def perform( self, character: "CharacterModel", stuff: "StuffModel", input_: CraftInput ) -> Description: if input_.quantity is None: return Description( title=self._description.name, items=[ Part( is_form=True, form_values_in_query=True, form_action=get_with_stuff_action_url( character_id=character.id, action_type=ActionType.CRAFT_STUFF_WITH_STUFF, stuff_id=stuff.id, query_params=self.input_model_serializer.dump(input_), action_description_id=self._description.id, ), items=[ Part(label=f"Quelle quantité ?", type_=Type.NUMBER, name="quantity") ], ) ], ) cost = self.get_cost(character, stuff=stuff, input_=input_) self._perform( character, description=self._description, input_=input_, cost=cost, dry_run=True ) self._perform( character, description=self._description, input_=input_, cost=cost, dry_run=False ) return Description( title="Action effectué avec succès", footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Voir l'inventaire", form_action=f"/_describe/character/{character.id}/inventory", classes=["primary"], ), ], force_back_url=f"/_describe/character/{character.id}/on_place_actions", )
def perform(self, character: "CharacterModel", input_: LearnKnowledgeModel) -> Description: knowledge_description = self._kernel.game.config.knowledge[ input_.knowledge_id] current_progress = self._kernel.character_lib.get_knowledge_progress( character.id, input_.knowledge_id) left = knowledge_description.ap_required - current_progress if input_.ap is None: return Description( title=f"Apprendre {knowledge_description.name}", items=[ Part(text=( f"Il reste {left} points d'actions à " f"dépenser pour apprendre {knowledge_description.name}" )), Part( is_form=True, form_values_in_query=True, form_action=self._get_url(character, input_), items=[ Part(label=f"Points d'actions à dépenser ?", type_=Type.NUMBER, name="ap") ], ), ], ) if self._kernel.character_lib.increase_knowledge_progress( character.id, input_.knowledge_id, input_.ap): title = "Connaissance acquise !" else: title = "Apprentissage effectué" self._kernel.character_lib.reduce_action_points(character.id, cost=input_.ap) return Description( title=title, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements") ], )
def perform(self, character: "CharacterModel", input_: BuildModel) -> Description: build_id = self._description.properties["build_id"] build_description = self._kernel.game.config.builds[build_id] return Description( request_clicks=RequestClicks( base_url=self.get_base_url(character), cursor_classes=build_description.classes, many=build_description.many, ) )
def _perform_attack_as_affinity(self, character: "CharacterModel", with_character: "CharacterModel", as_affinity_id: int) -> Description: as_affinity = self._kernel.affinity_lib.get_affinity(as_affinity_id) title = f"Attaquer {with_character.name} en tant que {as_affinity.name}" attack_description, defense_description = self._get_attack_defense_pair( target=with_character, as_affinity=as_affinity, world_row_i=character.world_row_i, world_col_i=character.world_col_i, ) resp = self._check_attack_as_affinity( character=character, with_character=with_character, as_affinity=as_affinity, attack_description=attack_description, defense_description=defense_description, ) if resp: return resp story = self._kernel.fight_lib.fight(attack=attack_description, defense=defense_description) parts = [Part(text=p) for p in story] self._proceed_events( attacker_title="Vous avez participé à une attaque", attacked_title="Vous avez subit une attaque", characters=attack_description.all_fighters + defense_description.all_fighters, author=character, story=story, ) self._kill_deads(attack_description.all_fighters + defense_description.all_fighters) return Description( title=title, items=parts, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Retourner à la fiche personnage", form_action=DESCRIBE_LOOK_AT_CHARACTER_URL.format( character_id=character.id, with_character_id=with_character.id), classes=["primary"], ), ], )
async def read(self, request: Request, hapic_data: HapicData) -> Description: messages = self._kernel.message_lib.get_conversation_messages( character_id=hapic_data.path.character_id, conversation_id=hapic_data.path.conversation_id, ) concerned_ids = set() for message in messages: concerned_ids |= set(message.concerned) concerned_names = [ r[0] for r in self._kernel.server_db_session.query(CharacterDocument.name) .filter(CharacterDocument.id.in_(concerned_ids)) .all() ] message_parts = [] for message in messages: text = ( f"{message.author_name}: {message.text}" if not message.is_outzone_message else message.text ) message_parts.append(Part(text=text)) self._kernel.message_lib.mark_character_conversation_messages_as_read( character_id=hapic_data.path.character_id, conversation_id=hapic_data.path.conversation_id, ) self._kernel.server_db_session.commit() return Description( title=messages[-1].subject, items=[ Part(text="Cette conversation concerne les personnages suivants"), Part(text=", ".join(concerned_names)), Part( is_form=True, form_action=f"/conversation/{hapic_data.path.character_id}/add/{hapic_data.path.conversation_id}", items=[Part(label="Ajouter un message", type_=Type.STRING, name="message")], ), Part(text="Conversation (message le plus récente en haut):"), ] + message_parts, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Retourner aux conversations", form_action=f"/conversation/{hapic_data.path.character_id}", classes=["primary"], ), ], can_be_back_url=True, )
async def add_message(self, request: Request, hapic_data: HapicData) -> Description: post_content = await request.json() self._kernel.message_lib.add_zone_message( hapic_data.query.character_id, message=post_content["message"], zone_row_i=hapic_data.path.row_i, zone_col_i=hapic_data.path.col_i, ) return Description(redirect=( f"/zones/{hapic_data.path.row_i}/{hapic_data.path.col_i}" f"/messages?character_id={hapic_data.query.character_id}"))
def _get_take_something_description(self, character: "CharacterModel", with_character: "CharacterModel", input_: TakeFromModel) -> Description: parts = [] carried_stuffs = self._kernel.stuff_lib.get_carried_by( with_character.id, exclude_crafting=False) carried_resources = self._kernel.resource_lib.get_carried_by( with_character.id) displayed_stuff_ids: typing.List[str] = [] for carried_stuff in carried_stuffs: if carried_stuff.stuff_id not in displayed_stuff_ids: parts.append( Part( is_link=True, label=f"Prendre {carried_stuff.name}", form_action=self._get_url( character, with_character, TakeFromModel(take_stuff_id=carried_stuff.id)), )) displayed_stuff_ids.append(carried_stuff.stuff_id) for carried_resource in carried_resources: parts.append( Part( is_link=True, label=f"Prendre {carried_resource.name}", form_action=self._get_url( character, with_character, TakeFromModel(take_resource_id=carried_resource.id), ), )) return Description( title=f"Prendre sur {with_character.name}", items=parts, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Retourner à la fiche personnage", form_action=DESCRIBE_LOOK_AT_CHARACTER_URL.format( character_id=character.id, with_character_id=with_character.id), ), ], can_be_back_url=True, )
async def manage_relations(self, request: Request, hapic_data: HapicData) -> Description: # TODO BS: only chief (or ability) can display this affinity = self._kernel.affinity_lib.get_affinity( hapic_data.path.affinity_id) relation = self._kernel.affinity_lib.get_character_relation( affinity_id=hapic_data.path.affinity_id, character_id=hapic_data.path.character_id) parts = [] for character_id, character_name, status_id in ( self._kernel.server_db_session.query( CharacterDocument.id, CharacterDocument.name, AffinityRelationDocument.status_id).filter( AffinityRelationDocument.affinity_id == affinity.id, AffinityRelationDocument.accepted == True, ).join(AffinityRelationDocument.user).all()): status_str = dict(json.loads(affinity.statuses))[status_id] parts.append( Part( is_link=True, label=f"{character_name} ({status_str})", form_action=( f"/affinity/{hapic_data.path.character_id}" f"/manage-relations/{affinity.id}/{character_id}"), )) return Description( title=f"Membre(s) de {affinity.name}", items=parts, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label=f"Voir la fiche de {affinity.name}", form_action= f"/affinity/{hapic_data.path.character_id}/see/{affinity.id}", classes=["primary"], ), Part( is_link=True, label="Voir les affinités", form_action=f"/affinity/{hapic_data.path.character_id}", ), ], can_be_back_url=True, )
async def transactions(self, request: Request, hapic_data: HapicData) -> Description: transactions: typing.List[ OfferDocument] = self._kernel.business_lib.get_transactions_query( hapic_data.path.character_id).all() parts: typing.List[Part] = [] for offer in transactions: form_action = f"/business/{hapic_data.path.character_id}/offers/{offer.id}" state = " (X)" is_new = "" with_info = f" (avec {offer.to_character.name})" if offer.status == OfferStatus.OPEN.value: state = " (V)" if offer.with_character_id == hapic_data.path.character_id: state = "" form_action = ( f"/business/{hapic_data.path.character_id}" f"/see-offer/{offer.character_id}/{offer.id}?mark_as_read=1" ) with_info = f" (de {offer.from_character.name})" if not offer.read and offer.with_character_id == hapic_data.path.character_id: is_new = "*" parts.append( Part( label=f"{is_new}{offer.title}{state}{with_info}", is_link=True, form_action=form_action, )) return Description( title="Commerce: vos transaction avec des personnes", items=parts, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Retourner sur la page Commerce", form_action=f"/business/{hapic_data.path.character_id}", classes=["primary"], ), ], can_be_back_url=True, )
async def messages(self, request: Request, hapic_data: HapicData) -> Description: # FIXME BS: manage pagination # FIXME BS: secured character_id messages = self._kernel.message_lib.get_character_zone_messages( character_id=hapic_data.query.character_id) self._kernel.message_lib.mark_character_zone_messages_as_read( character_id=hapic_data.query.character_id) message_parts: typing.List[Part] = [] for message in messages: if message.is_outzone_message: message_parts.append( Part(text=message.text or "Vous avez quitté la zone")) else: message_parts.append( Part(text=f"{message.author_name}: {message.text}")) return Description( title="Messagerie de zone", items=[ Part( text= f"Cette messagerie regroupe les conversations que votre personnage à tenu " f"avec tous les personnages se trouvant dans la même zone que lui. " f"Lorsque vous vous exprimez ici, tous les personnages se trouvant sur la " f"même zone écoutent."), Part( is_form=True, form_action= f"/zones/{hapic_data.path.row_i}/{hapic_data.path.col_i}" f"/messages/add?character_id={hapic_data.query.character_id}", items=[ Part( label=f"Parler aux personnes presentes ?", type_=Type.STRING, name="message", ) ], ), Part(label=""), ] + message_parts, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements") ], can_be_back_url=True, )
def get_description_for_not_enough_ap( character: "CharacterModel", cost: float, can_be_back_url: bool = False) -> Description: return Description( title="Action impossible", items=[ Part(text= f"{character.name} ne possède plus assez de points d'actions " f"({character.action_points} restant et {cost} nécessaires)"), Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), ], can_be_back_url=can_be_back_url, )
def perform( self, character: "CharacterModel", stuff: "StuffModel", input_: typing.Any ) -> Description: self._kernel.stuff_lib.unset_as_used_as_bag(character.id, stuff.id) return Description( title="Action effectué", footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Voir l'inventaire", form_action=f"/_describe/character/{character.id}/inventory", classes=["primary"], ), ], )
async def main_page(self, request: Request, hapic_data: HapicData) -> Description: messages = self._kernel.message_lib.get_conversation_first_messages( hapic_data.path.character_id, hapic_data.query.with_character_id, # FIXME BS NOW: test it ) conversation_parts = [] for message in messages: unread = "" if ( self._kernel.server_db_session.query(MessageDocument.id) .filter( MessageDocument.first_message == message.first_message, MessageDocument.read == False, MessageDocument.character_id == hapic_data.path.character_id, ) .count() ): unread = "*" conversation_parts.append( Part( is_link=True, form_action=f"/conversation/{hapic_data.path.character_id}/read/{message.first_message}", label=f"{unread}{message.subject}", align="left", ) ) return Description( title="Conversations", items=[ Part( text=( "Les conversations sont les échanges de paroles" " tenus avec d'autres personnages" ) ), Part( is_link=True, label="Démarrer une nouvelle conversation", form_action=f"/conversation/{hapic_data.path.character_id}/start", ), Part(text="Ci-dessous les conversations précédentes ou en cours"), ] + conversation_parts, can_be_back_url=True, )
async def offers(self, request: Request, hapic_data: HapicData) -> Description: offers: typing.List[ OfferDocument] = self._kernel.business_lib.get_offers_query( hapic_data.path.character_id, statuses=[ OfferStatus.OPEN, OfferStatus.DRAFT, OfferStatus.CLOSED ], ).all() parts: typing.List[Part] = [ Part( label="Créer une nouvelle offre", is_link=True, form_action= f"/business/{hapic_data.path.character_id}/offers-create?permanent=1", ), Part( text= "Ci-dessous les les offres existantes (X: innactive, V: active)" ), ] for offer in offers: state = "X" if offer.status == OfferStatus.OPEN.value: state = "V" parts.append( Part( label=f"({state}) {offer.title}", is_link=True, form_action= f"/business/{hapic_data.path.character_id}/offers/{offer.id}", )) return Description( title="Commerce: vos offres", items=parts, footer_links=[ Part( is_link=True, label="Retourner sur la page Commerce", form_action=f"/business/{hapic_data.path.character_id}", ) ], can_be_back_url=True, )
def _perform_attack_lonely( self, character: "CharacterModel", with_character: "CharacterModel") -> Description: defense_description: DefendDescription = self._kernel.fight_lib.get_defense_description( origin_target=with_character, world_row_i=character.world_row_i, world_col_i=character.world_col_i, ) aff = ", ".join([a.name for a in defense_description.affinities]) self._check_attack_lonely(character, defense_description, aff) story = self._kernel.fight_lib.fight( attack=AttackDescription(all_fighters=[character], ready_fighters=[character]), defense=defense_description, ) parts = [Part(text=p) for p in story] self._proceed_events( attacker_title="Vous avez participé à un combat", attacked_title="Vous avez subit une attaque", characters=[character] + defense_description.all_fighters, author=character, story=story, ) self._kill_deads([character] + defense_description.all_fighters) return Description( title=f"Attaquer {with_character.name} seul", items=parts, footer_links=[ Part(is_link=True, go_back_zone=True, label="Retourner à l'écran de déplacements"), Part( is_link=True, label="Retourner à la fiche personnage", form_action=DESCRIBE_LOOK_AT_CHARACTER_URL.format( character_id=character.id, with_character_id=with_character.id), classes=["primary"], ), ], )
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)