a
    'Ni	9  ã                   @   s    d Z ddlZddlZddlmZmZmZ ddlm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S )a  
Stats Manager Module

This module contains all stats and state update functions extracted from functions.py.
It manages player statistics, character updates, event checking, and various game state modifications.

Functions included:
- connect(player): Handle player reconnection and offline stats
- checkDilemmas(player): Check and trigger active dilemmas
- checkEvents(player, type): Check and trigger regular events
- checkDayEvents(player, type): Check and trigger day-specific events
- checkTutorialEvents(player, type): Check and trigger tutorial events
- scheduleComplete(person, scheduleID): Check if a schedule is complete
- updateAge(player): Update character ages and handle birthdays/deaths
- setLikesDislikes(person): Set random likes and dislikes for a character
- handleUpdates(updateObject, player, websocket): Handle incremental state updates
- parseOneTimeEvents(player): Parse and trigger one-time scheduled events
- handleMoods(player, person): Update character moods based on stats
- handleFinances(person): Handle character finances and savings
- getPeakEnergy(person): Calculate peak energy based on activities and habits

Note:
- FocusClass, getFocus(), getFocuses() are imported from education.education_manager
- updateDeathChance() is imported from health.health_manager
é    N)Ú
FocusClassÚ
getFocusesÚgetFocus)ÚupdateDeathChancec                 C   s€   d| _ | jj}|dkr||dk r(d}|}n"|dk r>d}|d }nd}|d }|dkrZ|d	7 }| j d
|› d|› d�¡ d| j_dS )zv
    Handle player reconnection and display offline time message.

    Args:
        player: playerClass instance
    Ú	connectedr   é<   Úminutei   ÚhourÚdayé   ÚszWelcome back, you missed Ú z of your life.N)Ú
connectionÚofflineStatsÚminutesOfflineÚmessageQueueÚappend)ÚplayerÚminutesÚunitÚtime© r   ú4/var/www/lichun.app/lichun/ws/stats/stats_manager.pyÚconnect'   s    
r   c                 C   s`   | j D ]T}t ¡ d dk rddl}t|ƒD ].}||jkr*t||ƒ}|| d|d�    S q*qdS )zª
    Check active dilemmas and trigger them randomly.

    Args:
        player: playerClass instance

    Returns:
        Event result if triggered, None otherwise
    éd   é   r   NÚdilemma)Útyper   )ÚactiveDilemmasÚrandomÚeventsÚdirÚfunctionÚgetattr)r   r   r    ÚiÚitemr   r   r   ÚcheckDilemmasD   s    



r&   c                 C   sf   ddl }ddl}h d£}t|ƒD ]@}t||ƒ}t|ƒr |j|vr | |¡s || |ƒ}|r |  S q dS )zÖ
    Check and trigger regular events from events.py.

    Args:
        player: playerClass instance
        type (str): Event type to check for

    Returns:
        Event result if triggered, None otherwise
    r   N>   Úapply_tutorial_modifiersÚanswerOptionÚdilemmaClassÚ	timeEventÚcheck_tutorial_triggersÚquestionEventZget_event_typeÚoneTimeEventZparse_event_dataÚConversationContextManagerÚmessageEvent)r    Úinspectr!   r#   ÚcallableÚ__name__Úiscoroutinefunction)r   r   r    r0   Úexcluded_namesr$   r%   Úresultr   r   r   ÚcheckEventsX   s    


r6   c                 C   sf   ddl }ddl}h d£}t|ƒD ]@}t||ƒ}t|ƒr |j|vr | |¡s || |ƒ}|r |  S q dS )zÞ
    Check and trigger day-specific events from dayEvents.py.

    Args:
        player: playerClass instance
        type (str): Event type to check for

    Returns:
        Event result if triggered, None otherwise
    r   N>   r)   r*   r,   Úget_dailyPlanr-   r.   r/   )Ú	dayEventsr0   r!   r#   r1   r2   r3   )r   r   r8   r0   r4   r$   r%   r5   r   r   r   ÚcheckDayEventsv   s    


r9   c              
   C   s‚   zHddl }| | ¡sW dS | | ¡}|D ]}|| |ƒ}|r(|  W S q(W n4 ty| } zt d|› �¡ W Y d}~n
d}~0 0 dS )zæ
    Check and trigger tutorial events if player is in tutorial mode.

    Args:
        player: playerClass instance
        type (str): Event type to check for

    Returns:
        Event result if triggered, None otherwise
    r   Nz Error checking tutorial events: )Útutorial_eventsÚis_tutorial_moder+   Ú	ExceptionÚloggingÚerror)r   r   r:   ZtriggersZtrigger_funcr5   Úer   r   r   ÚcheckTutorialEvents’   s    


&r@   c                 C   sH   t dt| jƒƒD ]2}|| j| jv r| j| j| j| jkr dS qdS )zá
    Check if a schedule has been completed.

    Args:
        person: personClass instance
        scheduleID (str): ID of the schedule to check

    Returns:
        bool: True if schedule is complete, False otherwise
    r   TF)ÚrangeÚlenÚ	schedulesÚidÚ
executionsÚduration)ÚpersonZ
scheduleIDr$   r   r   r   ÚscheduleComplete®   s    (rH   c                 C   sÒ  ddl m} | jjd | j_| jjd dk�rÎ| jjd | j_t| jƒD �]‚\}}|jdkrH|jd | j| _| jjdkrœ|jd dkrœ| j|  j	d8  _	|jd dk�r@| j|  jd7  _| j|  j	d8  _	t
|ƒ| j| _d	|jv�r@t|d
dƒ�r@d|j d |j d |j d t|jƒ d }|d|| dƒ  S |j|j d t ¡ d k�sj|jdk�r°d| j| _d|j d |j ¡  d |j ¡  d t|jƒ d | _| j| j	dk rHd| j| _	qH| S )zá
    Update character ages and handle birthdays, deaths, and relationship decay.

    Args:
        player: playerClass instance

    Returns:
        playerClass or messageEvent: Updated player or birthday message event
    r   )ÚmessageFunctionr   é   Úaliveé   é   im  Ú	classmateÚtitleFzYour r   z is now z years old.ÚbirthdayTr   éx   Zdeadz has died at the age of iœÿÿÿ)r    rI   ÚcÚageHoursÚageDaysÚ	enumerateÚrÚstatusÚageYearsÚaffinityr   ÚdeathChanceÚrelationshipsr#   rO   Ú	firstnameÚlastnameÚstrÚhealthr   Ú
capitalizeÚmessage)r   rI   Úindexr%   ra   r   r   r   Ú	updateAge¿   s,    

0*:rc   c                    sJ   g d¢}t  |t  dd¡¡ˆ _‡ fdd„|D ƒ}t  |t  dd¡¡ˆ _ˆ S )z²
    Set random likes and dislikes for a character.

    Args:
        person: personClass instance

    Returns:
        personClass: Updated person with likes and dislikes
    )0ZsportsZmusicZartÚreadingÚwritingZscienceÚmathÚhistoryZpoliticsZ
philosophyZreligionZnatureZanimalsÚtravelÚfoodZcookingZcarsZfashionZfitnessr_   Z
technologyzvideo gamesZmoviesZtvZtheaterZdanceZcomedyZdramaZhorrorÚromanceÚactionZ	adventureZfantasyzsci-fiZmysteryZthrillerZcrimeZdocumentaryZanimeZmangaZcartoonszboard gamesz
card gamesÚBroccoliÚCeleryÚ	MushroomszBrussels sproutsÚOnionsr   é   c                    s   g | ]}|ˆ j vr|‘qS r   )Úlikes)Ú.0Zinterest©rG   r   r   Ú
<listcomp>ð   ó    z$setLikesDislikes.<locals>.<listcomp>)r   ÚsampleÚrandintrq   Údislikes)rG   Zpossible_interestsr   rs   r   ÚsetLikesDislikesã   s
    
ry   c                 C   s\  g d¢}|D ]4}t |j|ƒ}||  |¡kr4|| |< q|  |d¡ qddg}|D ]>}t |j|ƒ}t|ƒt|  |g ¡ƒkr€|| |< qN|  |d¡ qN|j|  d¡kr´t|jƒ |j| d< n|  dd¡ |j|  d¡krê|  |j	|j|j
dœ¡ n\|jdk�r.|j	|  d	¡k�r.|jd
k�r.|  |j	|j|j
dœ¡ ndD ]}|  |d¡ �q2| �rXd| d< | S dS )a†  
    Handle incremental state updates to send to client.
    Only includes changed values to minimize data transfer.

    Args:
        updateObject (dict): Object to populate with updates
        player: playerClass instance
        websocket: WebSocket connection (not currently used)

    Returns:
        dict or False: Update object with type 'u' if changes exist, False otherwise
    )	ÚenergyÚ
calcEnergyÚ	happinessÚstressÚmoneyÚprestigeÚ
occupationÚintraDayMessageÚlocationNrC   Ú	dailyPlanÚ	gameSpeedÚ	hourOfDay)Údater…   ÚweekDayTextr   r†   r   Úur   F)r#   rR   ÚgetÚpoprB   r„   Úprintr…   Úupdater†   r‡   )ZupdateObjectr   Ú	websocketÚ
attributesÚ	attributeZplayer_valueZlist_attributesÚkeyr   r   r   ÚhandleUpdatesö   sD    


ý
*ý
r‘   c                 C   sŒ   t dt| jjƒƒD ]t}| jj| }|j| jkr| j|jkr| j |j	¡ | jj 
|¡ |jdkrt|dƒrt| | ¡ d|_d|_d|_qdS )zf
    Parse and trigger one-time scheduled events.

    Args:
        player: playerClass instance
    r   NÚrun_funcF)rA   rB   rR   ÚoneTimeEventsr†   r…   r	   r   r   ra   rŠ   ÚcompletionFuncÚhasattrr’   ÚcompletionArgsÚcompletionKwargs)r   r$   Úeventr   r   r   ÚparseOneTimeEvents;  s    


r™   c                 C   s–   |j dk r|j dkrd|_|j dkr*d|_|j dkr:d|_|j dkrT|jdkrTd|_|j dkrn|jdkrnd|_|j dkr’|jdkr’|jdkr’d	|_d
S )zÂ
    Update character mood based on energy and happiness levels.

    Args:
        player: playerClass instance (not currently used)
        person: personClass instance to update mood for
    é(   é
   ÚStressedÚ	ExhaustedÚCalmr   Ú	FulfilledÚ	DepressedÚHappyN)rz   Úmoodr|   )r   rG   r   r   r   ÚhandleMoodsO  s    


r£   c                 C   s�   d}| j dkrd}n| j dkr"d}d}| jdkrŒ| jD ]}|jdkr6||jj7 }q6t| dd	ƒ}|rŒt|d
d	ƒdkrz|d9 }|  j|| 7  _d	S )zq
    Handle character finances including income and savings.

    Args:
        person: personClass instance
    gš™™™™™¹?Úfrugalgš™™™™™É?Úextravagantgš™™™™™©?r   FÚjobNÚhourTypeÚpartTimeg333333Ó?)ÚspendingHabitsr¦   ÚactivityRecordsr   ÚlevelÚsalaryr#   r~   )rG   ZsavingRatioÚincomeÚrecordr¦   r   r   r   ÚhandleFinancesg  s    




r¯   c                 C   s¢   d}| j D ]}|jdkr
|d7 }q
| jD ]`}t|ddƒrB||j7 }| jD ]>}|j|jkrH|jdkrn||jj	7 }t
|jƒ}|rH||j7 }qHq(|| _| j| j | _dS )zµ
    Calculate peak energy based on activities, habits, and focus settings.
    Updates person.peakEnergy and person.calcEnergy.

    Args:
        person: personClass instance
    r   Úquittingrp   ÚenergyModifierFr¦   N)ÚhabitsrW   Ú
activitiesr#   r±   rª   rD   r   r«   Úenergy_modifierr   ÚfocusÚ
peakEnergyrz   r{   )rG   r¶   ÚhabitÚactivityr®   Z
foundFocusr   r   r   ÚgetPeakEnergy  s     	







r¹   )Ú__doc__r   r=   Úeducation.education_managerr   r   r   Úhealth.health_managerr   r   r&   r6   r9   r@   rH   rc   ry   r‘   r™   r£   r¯   r¹   r   r   r   r   Ú<module>   s"   $E