Пример #1
0
    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"],
                ),
            ],
        )
Пример #2
0
    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)
Пример #3
0
    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,
        )
Пример #4
0
 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")
             ],
         )
Пример #5
0
    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")
            ],
        )
Пример #6
0
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)
Пример #7
0
    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}",
                ),
            ],
        )
Пример #8
0
    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"],
                ),
            ],
        )
Пример #9
0
    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")
            ],
        )
Пример #10
0
 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",
     )
Пример #11
0
    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,
        )
Пример #12
0
 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)],
     )
Пример #13
0
 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}"
     )
Пример #14
0
    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,
        )
Пример #15
0
    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",
        )
Пример #16
0
    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")
            ],
        )
Пример #17
0
 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,
         )
     )
Пример #18
0
    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"],
                ),
            ],
        )
Пример #19
0
    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,
        )
Пример #20
0
    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}"))
Пример #21
0
    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,
        )
Пример #22
0
    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,
        )
Пример #23
0
    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,
        )
Пример #24
0
    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,
        )
Пример #25
0
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,
    )
Пример #26
0
 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"],
             ),
         ],
     )
Пример #27
0
    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,
        )
Пример #28
0
    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,
        )
Пример #29
0
    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"],
                ),
            ],
        )
Пример #30
0
    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)