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 rtd j  t jI dH }|r|jt	j
krvt	j|_d|_d|_t| | j| td |st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  zt 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  q1 I dH s0    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! *