a
    
i/                     @   s   d Z ddlZddlZddlZddlZd.ddZdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#Zd$Zd%Zd&Zd'Zd(d) Zd*d+ Zd,d- ZdS )/a  
Utility Helper Functions for BaoLife Game

This module contains general-purpose utility functions extracted from functions.py
to improve code organization and maintainability.

Functions:
    - Array manipulation: getFromArray, randArray
    - Search utilities: find_by_id, find_where, find, find_where_test, findCharacters
    - Random number generation: rand
    - String manipulation: remove_text_before_first_colon, ordinal_suffix
    - Date/time utilities: getWeekDay, upcoming_saturday, generate_random_date, get_season
    - Location utilities: parseLocations
    - Game utilities: getOppositeSex
    - JWT/Authentication: create_jwt_token
    - Pickle compatibility: _unpickle_health_condition, _reduce_health_condition
    Nc                 C   s\   g }t dt| D ] }| | j|kr|| |  q|dkr@|S t|dkrT|d S dS dS )a  
    Filter array by object type attribute.

    Args:
        array: List of objects with 'type' attribute
        type: Value to match against object.type
        amount: If 0, return all matches; if 1, return first match
        value: Unused parameter (kept for compatibility)

    Returns:
        List of matching objects if amount=0, single object if amount=1, False if none found
    r   FN)rangelentypeappend)arrayr   amountvalueresulti r   ./var/www/lichun.app/lichun/ws/utils/helpers.pygetFromArray   s    r   c                 C   s   | t dt| d  S )z
    Return a random element from an array.

    Args:
        array: List to select from

    Returns:
        Random element from the array
    r      )randomrandintr   )r   r   r   r   	randArray8   s    
r   c                 C   s    | D ]}|j |kr|  S qdS )z
    Find an object in iterable by its id attribute.

    Args:
        iterable: Collection of objects with 'id' attribute
        id: ID value to search for

    Returns:
        First matching object or None if not found
    N)id)iterabler   itemr   r   r   
find_by_idI   s    

r   c                    s0   | D ]& t  fdd| D r   S qdS )z
    Find first object where all key-value pairs match.

    Args:
        iterable: Collection of objects to search
        dct: Dictionary of attribute names and values to match

    Returns:
        First matching object or None if not found
    c                 3   s"   | ]\}}t  |d |kV  qd S N)getattr.0keyr   r   r   r   	<genexpr>f       zfind_where.<locals>.<genexpr>N)allitemsr   dctr   r   r   
find_whereZ   s    
r"   c                 C   s"   g }| j D ]}|r
|| q
|S )z
    Filter player relationships based on a check condition.

    Args:
        player: Player object with 'r' (relationships) attribute
        check: Boolean condition to filter by

    Returns:
        List of matching person objects
    )rr   )playercheckresultspersonr   r   r   findCharactersk   s
    
r(   c                 #   s4   | D ]*  j  t fdd| D r V  qdS )a<  
    Generator that yields objects where all key-value pairs match.
    Converts objects to dictionaries for comparison.

    Args:
        iterable: Collection of objects to search
        dct: Dictionary of attribute names and values to match

    Yields:
        Dictionary representation of matching objects
    c                 3   s   | ]\}} | |kV  qd S r   r   r   r   r   r   r      r   zfind.<locals>.<genexpr>N)__dict__r   r   r    r   r   r   find}   s    r*   c                 c   s   | D ]}|j }d}| D ]\}}d|v rT|dd}||td|krd} qqd|v r|dd}||td|krd} qq|||krd} qq|r|V  qdS )	a  
    Generator that yields objects with advanced comparison operators.
    Supports __gt (greater than) and __lt (less than) suffixes in keys.

    Args:
        iterable: Collection of objects to search
        dct: Dictionary with keys like 'age__gt': 23 or 'score__lt': 100

    Yields:
        Matching objects

    Example:
        find_where_test(my_list, {'age__gt': 23, 'name': 'John'})
    TZ__gt z-infFZ__ltinfN)r)   r   replacegetfloat)r   r!   r   Z	item_dictmatchr   r   Zattr_keyr   r   r   find_where_test   s&    r1   c                 C   s   t | |S )z
    Generate random integer between num1 and num2 (inclusive).

    Args:
        num1: Minimum value
        num2: Maximum value

    Returns:
        Random integer in range [num1, num2]
    r   r   )Znum1Znum2r   r   r   rand   s    r3   c                 C   s,   |  dd}t|dkr$|d  S |d S )z
    Remove text before the first colon in a message.

    Args:
        message: String that may contain a colon

    Returns:
        Text after first colon (stripped), or original message if no colon
    :r   r   )splitr   strip)messagepartsr   r   r   remove_text_before_first_colon   s    
r9   c                 C   sP   d| d   k rdk r(n nt | d S dddd}t | || d d S d	S )
z
    Add ordinal suffix to a number (1st, 2nd, 3rd, 4th, etc.).

    Args:
        num: Integer to add suffix to

    Returns:
        String with number and ordinal suffix (e.g., "1st", "22nd")
    
   d      thstndrd)r         N)strr.   )numsuffixesr   r   r   ordinal_suffix   s    
rF   c                 C   sd   | j jd }|dkrdS |dkr$dS |dkr0dS |dkr<d	S |d
krHdS |dkrTdS |dkr`dS dS )z
    Get day of week based on player's age in days.

    Args:
        player: Player object with c.ageDays attribute

    Returns:
        String name of weekday (Sunday through Saturday)
       r   ZSundayr   ZMondayrA   ZTuesdayrB   Z	Wednesday   ZThursday   ZFriday   ZSaturdayN)cageDays)r$   dayr   r   r   
getWeekDay   s    
rN   c                 C   sV   t t| d\}}tj j}t|||}d|  d d }|tj|d  S )z
    Calculate the next Saturday from a given date string.

    Args:
        date_string: Date in format "MM-DD"

    Returns:
        datetime.date object of the upcoming Saturday
    -rI   rG   )days)	mapintr5   datetimenowyearweekday	timedeltadate)Zdate_stringmonthrM   rU   Z
given_dateZdays_until_saturdayr   r   r   upcoming_saturday	  s
    rZ   c                 C   s\   d|   krdkrn ndS d|   kr0dkr8n ndS d|   krLdkrTn nd	S d
S dS )z
    Get season name based on month number.

    Args:
        month: Integer month (1-12)

    Returns:
        String season name (Spring, Summer, Autumn, Winter)
    rB   rI   ZSpringrJ      ZSummer	      ZAutumnZWinterNr   )rY   r   r   r   
get_season!  s    
r^   c                  C   sV   t dd} | dv r"t dd}n"| dkr8t dd}nt dd}| dd	|dS )
z
    Generate a random date in MM-DD format.
    Accounts for different month lengths.

    Returns:
        String in format "MM-DD" (e.g., "03-15")
    r      )rH   rJ   r\   r]      rA         02drO   r2   )rY   rM   r   r   r   generate_random_date5  s    rd   c                 C   sr   | j D ]f}g |_d}| jj|jkr6|j| jj d}| jD ].}|j|jkr<|r\|jd |_|j|j q<q| S )a  
    Update location objects with current people present.
    Increases familiarity between characters at same location.

    Args:
        player: Player object with c (character), r (relationships), l (locations)

    Returns:
        Updated player object
    FTr:   )lpeoplerK   locationr   r   r#   familiarity)r$   re   ZplayerPresentr#   r   r   r   parseLocationsK  s    

ri   c                 C   s   | dkrdS | dkrdS dS )z
    Get the opposite sex/gender.

    Args:
        sex: String "Male" or "Female"

    Returns:
        String opposite sex, or None if input invalid
    MaleFemaleNr   )sexr   r   r   getOppositeSexi  s    
rm   Z
ZW35P75J3Az0/var/www/lichun.app/lichun/AuthKey_ZW35P75J3A.p8Z
2A7RZ5P98Pzlichun.lichunWebsocketZES256c                  C   s0   t jtt dttd tttdd} | S )zw
    Create a JWT token for Apple Push Notification Service (APNS).

    Returns:
        Encoded JWT token string
    )ZissZiatr#   )ZalgZkid)payloadr   	algorithmheaders)	jwtencodeTEAM_IDtimeopenAPNS_AUTH_KEYread	ALGORITHMAPNS_KEY_ID)tokenr   r   r   create_jwt_token  s    r{   c                  G   s   ddl m} ||  S )aF  
    Helper to unpickle old healthCondition objects as HealthCondition.
    Used for backward compatibility with old save games.

    Args:
        *args: Variable arguments passed from pickle

    Returns:
        HealthCondition object

    Note:
        Requires HealthCondition class to be imported where this is used
    r   )HealthCondition)health.health_managerr|   )argsr|   r   r   r   _unpickle_health_condition  s    r   c                 C   s    t | j| j| j| j| j| jffS )z
    Register copyreg reducer for HealthCondition pickle serialization.

    Args:
        obj: HealthCondition object to reduce

    Returns:
        Tuple of (unpickler function, arguments tuple)
    )r   r   titlehealthModifierZaverageDurationdescriptionimage)objr   r   r   _reduce_health_condition  s    
r   )r   r   )__doc__r   rS   rt   rq   r   r   r   r"   r(   r*   r1   r3   r9   rF   rN   rZ   r^   rd   ri   rm   ry   rv   rs   Z	BUNDLE_IDrx   r{   r   r   r   r   r   r   <module>   s8   
(