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rœd} qžqd|v r†| dd¡}| |tdƒ¡|krœd} qžq| |¡|krd} qžq|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   
(