Source code for tibiapy.models.guild

"""Models for guilds and members."""
import datetime
from collections import OrderedDict, defaultdict
from typing import Optional

from pydantic import computed_field

from tibiapy.enums import Vocation
from tibiapy.models import BaseCharacter, BaseGuild, BaseHouse, BaseModel
from tibiapy.urls import get_guild_url, get_guild_wars_url, get_world_guilds_url

__all__ = (
    "GuildHouse",
    "GuildMember",
    "GuildInvite",
    "Guild",
    "GuildEntry",
    "GuildsSection",
    "GuildWarEntry",
    "GuildWars",
)

from tibiapy.utils import take_while


[docs] class GuildMember(BaseCharacter): """Represents a guild member.""" rank: str """The rank the member belongs to""" title: Optional[str] = None """The member's title.""" level: int """The member's level.""" vocation: Vocation """The member's vocation.""" joined_on: datetime.date """The day the member joined the guild.""" is_online: bool """Whether the member is online or not."""
[docs] class GuildInvite(BaseCharacter): """Represents an invited character.""" invited_on: datetime.date """The day when the character was invited."""
[docs] class GuildHouse(BaseHouse): """A guildhall owned by a guild. By limitation of Tibia.com, the ID of the guildhall is not available. """ paid_until: datetime.date """The date the last paid rent is due."""
[docs] class Guild(BaseGuild): """A Tibia guild, viewed from its guild's page.""" logo_url: str """The URL to the guild's logo.""" description: Optional[str] = None """The description of the guild.""" world: str """The world this guild belongs to.""" founded: datetime.date """The day the guild was founded.""" active: bool """Whether the guild is active or still in formation.""" guildhall: Optional[GuildHouse] = None """The guild's guildhall if any.""" open_applications: bool = False """Whether applications are open or not.""" active_war: bool """Whether the guild is currently in an active war or not.""" disband_date: Optional[datetime.date] = None """The date when the guild will be disbanded if the condition hasn't been meet.""" disband_condition: Optional[str] = None """The reason why the guild will get disbanded.""" homepage: Optional[str] = None """The guild's homepage, if any.""" members: list[GuildMember] """List of guild members.""" invites: list[GuildInvite] """List of invited characters.""" @computed_field @property def member_count(self) -> int: """The number of members in the guild.""" return len(self.members) @computed_field @property def online_count(self) -> int: """The number of online members in the guild.""" return len(self.online_members) @property def online_members(self) -> list[GuildMember]: """List of currently online members.""" return list(filter(lambda m: m.is_online, self.members)) @computed_field @property def ranks(self) -> list[str]: """Ranks in their hierarchical order.""" return list(OrderedDict.fromkeys(m.rank for m in self.members)) @property def leader(self) -> GuildMember: """Get the leader of the guild.""" return self.members[0] @property def vice_leaders(self) -> list[GuildMember]: """The vice leader of the guilds.""" if len(self.members) <= 1: return [] return list(take_while(self.members[1:], lambda m: m.rank == self.members[1].rank)) @property def members_by_rank(self) -> dict[str, list[GuildMember]]: """Get a mapping of members, grouped by their guild rank.""" rank_dict = defaultdict(list) [rank_dict[m.rank].append(m) for m in self.members] return dict(rank_dict)
[docs] class GuildEntry(BaseGuild): """Represents a Tibia guild in the guild list of a world.""" logo_url: str """The URL to the guild's logo.""" description: Optional[str] = None """The description of the guild.""" world: str """The world this guild belongs to.""" active: bool """Whether the guild is active or still in formation."""
[docs] class GuildsSection(BaseModel): """The guilds section in Tibia.com.""" world: Optional[str] = None """The name of the world. If :obj:`None`, the section belongs to a world that doesn't exist.""" entries: list[GuildEntry] = [] """The list of guilds in the world.""" available_worlds: list[str] """The list of worlds available for selection.""" @property def active_guilds(self) -> list[GuildEntry]: """Get a list of the guilds that are active.""" return [g for g in self.entries if g.active] @property def in_formation_guilds(self) -> list[GuildEntry]: """Get a list of the guilds that are in course of formation.""" return [g for g in self.entries if not g.active] @property def url(self) -> str: """Get the URL to this guild section.""" return get_world_guilds_url(self.world)
[docs] class GuildWarEntry(BaseModel): """Represents a guild war entry.""" guild_name: str """The name of the guild.""" guild_score: int """The number of kills the guild has scored.""" guild_fee: int """The number of gold coins the guild will pay if they lose the war.""" opponent_name: Optional[str] = None """The name of the opposing guild. If the guild no longer exist, this will be :obj:`None`.""" opponent_score: int """The number of kills the opposing guild has scored.""" opponent_fee: int """The number of gold coins the opposing guild will pay if they lose the war.""" start_date: Optional[datetime.date] = None """The date when the war started. When a war is in progress, the start date is not visible.""" score_limit: int """The number of kills needed to win the war.""" duration: Optional[datetime.timedelta] = None """The set duration of the war. When a war is in progress, the duration is not visible.""" end_date: Optional[datetime.date] = None """The deadline for the war to finish if the score is not reached for wars in progress, or the date when the war ended.""" winner: Optional[str] = None """The name of the guild that won. Note that if the winning guild is disbanded, this may be :obj:`None`.""" surrender: bool """Whether the losing guild surrendered or not.""" @property def guild_url(self) -> str: """The URL to the guild's information page on Tibia.com.""" return get_guild_url(self.guild_name) @property def opponent_guild_url(self) -> Optional[str]: """The URL to the opposing guild's information page on Tibia.com.""" return get_guild_url(self.opponent_name) if self.opponent_name else None
[docs] class GuildWars(BaseModel): """Represents a guild's wars.""" name: Optional[str] = None """The name of the guild.""" is_current: Optional[GuildWarEntry] = None """The current war the guild is involved in.""" history: list[GuildWarEntry] """The previous wars the guild has been involved in.""" @property def url(self) -> str: """The URL of this guild's war page on Tibia.com.""" return get_guild_wars_url(self.name)