a
    'Nié  ã                   @   s´   d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	m
Z
mZmZmZmZ ddlmZ ddlmZ ddlmZmZ dd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )a8  
WebSocket lifecycle and handler functions.

This module contains the core WebSocket connection handlers, lifecycle management
functions, and background tasks for the BaoLife game server.

Functions:
    - start: Handles WebSocket connection initialization and game loading
    - shutdown: Handles WebSocket disconnection and cleanup
    - error: Sends error messages to clients
    - every_minute: Background task for periodic game iteration
    - handler: Main WebSocket connection handler
    - initialize_dummy_user: Creates a dummy user for server initialization
é    N)Ú
exceptions)ÚloadGameAsyncÚsaveGameAsyncÚplayerClassÚgetOccupationsÚ
insertGameÚconnect)Úconfig)ÚUSERS)ÚsendUserInfoÚsendDictc           
      ƒ   s¤  ddl }|j}|j}|j}ˆ h}tdƒ d}| ˆ j¡}|du râtdˆ j ƒ tˆ jƒI dH }|r |jt	j
krvt	j|_d|_d|_t|ƒ | ˆ j|¡ tdƒ |sàtd	ƒ tƒ }tƒ |_ˆ j|_t|ƒ t|ƒ | ˆ j|¡ nT|}td
|jj d |jj d t|jjƒ ƒ |jt	j
k�r(t	j|_d|_t|ƒ t|ˆ ƒI dH  tdt ¡ › d| ¡ › �ƒ ddlm} ‡ fdd„}	||j|	ƒ t  !|ˆ ƒ|ˆ ƒ¡I dH  dS )aÿ  
    Initialize a WebSocket connection and load/create player game.

    Handles:
    - Loading existing games from database
    - Creating new games for first-time players
    - Reconnecting disconnected players
    - Initializing game controller and connection state
    - Sending initial player data to client
    - Checking daily login rewards

    Args:
        websocket: WebSocket connection with userID attribute

    Returns:
        None - Starts consumer and producer handlers via asyncio.gather
    r   Nzstarting connection...Fzattempting load for ÚactiveÚ	connectedzloaded gamez3no loaded games, no saved game -- creating new gamezreconnected Ú z age zUSERS: z
 Players: )Úhandle_daily_login_checkc                    s   t  tˆ |ƒ¡ d S )N)ÚasyncioÚcreate_taskr   )Ú	player_idÚmessage©Ú	websocket© ú:/var/www/lichun.app/lichun/ws/server/websocket_handlers.pyÚsend_to_client_wrappera   s    z%start.<locals>.send_to_client_wrapper)"ÚappÚconsumer_handlerÚproducer_handlerÚplayerRecordsÚprintÚgetÚuserIDr   Ú	gameSpeedr	   ÚSPEED_QUESTION_PAUSEÚSPEED_DEFAULTÚ
controllerÚ
connectionr   Úsetr   r   ÚoccupationsÚidr   ÚcÚ	firstnameÚlastnameÚstrÚageYearsr   r
   ÚcountÚsizeÚretention.daily_rewardsr   r   Úgather)
r   r   r   r   r   r   ÚplayerZcached_playerr   r   r   r   r   Ústart$   sT    ,þr3   c                 Ã   sd   ddl }|j}ttjƒ tdƒ | | j¡}|r`d|j_d|_	d|_
t|ƒI dH  t | ¡ dS dS )a^  
    Handle WebSocket disconnection and cleanup.

    Performs:
    - Resets offline tracking
    - Updates player connection state
    - Saves game to database
    - Removes from active users registry

    Args:
        websocket: WebSocket connection with userID attribute

    Returns:
        bool: True if cleanup successful, None otherwise
    r   Nz!Client disconnected.  Do cleanup ÚdisconnectedÚinactiveT)r   r   r   Úwebsockets_exceptionsÚConnectionClosedr   r    ÚofflineStatsÚminutesOffliner%   r$   r   r
   Úremove)r   r   r   r2   r   r   r   Úshutdownk   s    

r;   c                 Ã   s$   d|dœ}|   t |¡¡I dH  dS )z³
    Send an error message to the client.

    Args:
        websocket: WebSocket connection to send error to
        message: Error message string

    Returns:
        None
    Úerror)Útyper   N)ÚsendÚjsonÚdumps)r   r   Úeventr   r   r   r<   Œ   s    þr<   c                  Ã   sŠ   ddl } | j}ddl m} tdƒ |ƒ I dH  | ¡ }td|d › d|d › d	|d
 › d|d › d|d d›d�ƒ t d¡I dH  qdS )aP  
    Background task that runs every minute to iterate offline games.

    This task:
    - Checks for disconnected games that need updates
    - Iterates game state for offline players (1 game-minute per real-world minute)
    - Logs player cache statistics

    Runs indefinitely until server shutdown.

    Returns:
        None
    r   N)ÚiterateGamesz(every minute, checking for offline gameszPlayerCache: r/   ú/Úmax_sizez
 players (r   z connected, r4   z disconnected), Ú	memory_mbz.1fÚMBé<   )r   r   rB   r   Ú	get_statsr   Úsleep)r   r   rB   Ústatsr   r   r   Úevery_minutež   s    ÿÿþ
rK   c              
   Ã   s  zÊt tj ¡ ƒ |  ¡ I dH }t |¡}|d dkrf|d | _t d| j ƒ t | ¡ t	| ƒI dH  nT|d | _t d| j ƒ t | ¡ t	| ƒI dH  t
| dƒI dH  |  ¡ I dH  W dS |  ¡ I dH  W nH tj�y } z,t dt|ƒ ƒ t| ƒI dH  W Y d}~dS d}~0 0 dS )	a×  
    Main WebSocket connection handler.

    This is the entry point for all WebSocket connections. It:
    - Receives and validates the initial "init" message
    - Extracts userID from the init message
    - Registers the connection in the USERS registry
    - Delegates to start() for game initialization
    - Handles connection errors and cleanup

    Args:
        websocket: WebSocket connection object

    Returns:
        bool: False on error or completion
    Nr=   Úinitr    zClient connected with userID zFirst message must be 'init'Fz)handler: Client disconnected.  Do cleanup)r   ÚdatetimeÚnowÚrecvr?   Úloadsr    r
   Úaddr3   r<   Úcloser6   r7   r,   r;   )r   r   rA   Úerrr   r   r   Úhandler¾   s*    




rT   c                  Ã   s¾   d} t  | ¡4 I dH šŽ}dddœ}z(| t |¡¡I dH  | ¡ I dH  W nD tjyŽ } z*tdt	|ƒ ƒ t
|ƒI dH  W Y d}~n
d}~0 0 W d  ƒI dH  qº1 I dH s°0    Y  dS )a  
    Create a dummy user for server initialization testing.

    This function connects to the local WebSocket server and sends a test
    message to ensure the server is properly initialized before accepting
    real connections.

    Returns:
        bool: False after completion
    zws://localhost:8001NÚtestZDUMMY_USER_ID)r=   r    z7initialize_dummy_user: Client disconnected.  Do cleanupF)Ú
websocketsr   r>   r?   r@   rR   r6   r7   r   r,   r;   )Úurir   Zdummy_messagerS   r   r   r   Úinitialize_dummy_userè   s    
NrX   )Ú__doc__r   rM   r?   Ú	tracebackrV   r   r6   Ú	functionsr   r   r   r   r   r   r	   Úserver.websocket_registryr
   Úserver.websocket_messagingr   r   r3   r;   r<   rK   rT   rX   r   r   r   r   Ú<module>   s     G! *