a
    
Üi¦  ã                   @   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ZddlmZ ddlm	Z	 e 
e¡ZdZde Zdd„ Zd	d
„ Zdd„ Zdd„ ZdS )aT  
Producer/Consumer Pattern for WebSocket Game Loop

This module implements the producer/consumer pattern for managing WebSocket
message flow and game loop execution with FPS control.

The producer generates game updates at a controlled frame rate (TARGET_FPS),
while the consumer processes incoming client messages and dispatches commands.
é    N)Úconfig)ÚRateLimiteriˆ  ç      ð?c                 Ã   s   ddl m} || ƒI dH  dS )z½
    Produce game updates by calling the main game loop.

    Args:
        websocket: The WebSocket connection with userID attribute

    Returns:
        False to indicate completion
    r   )ÚinitLifeSimNF)Úgame_loop.loop_managerr   )Ú	websocketr   © r   ú</var/www/lichun.app/lichun/ws/game_loop/producer_consumer.pyÚproducer   s    
r
   c              
   Ã   sä  ddl m} ddlm} ddl}|j}t ¡ }d}zö| | j¡}|r^|j	dkr^| jdkr^W �qàt ¡ }t
| ƒI dH  t ¡ }	|	| }
|d7 }|	| }t|
 }|dkr¼t d	¡I dH  |	}d}|d
k�r&| | j¡}|�r&|| |_tdt|| ƒ d tt|ƒƒ d t|jjƒ d t|jjƒ ƒ W q2 tjj�y~ } z8tdt|ƒ ƒ || ƒI dH  W Y d}~�qàW Y d}~q2d}~0  t�yÜ } zFtdt ¡  ƒ |  ¡ I dH  || ƒI dH  W Y d}~�qàW Y d}~q2d}~0 0 q2dS )a
  
    Handle producer with FPS control and error catching.

    This continuously runs the producer at TARGET_FPS, tracking frame rate
    and handling disconnections/errors gracefully.

    Args:
        websocket: The WebSocket connection with userID attribute
    r   )Úshutdown)ÚPlayerCacheNÚdisconnectedÚDUMMY_USER_IDé   g‘?gü©ñÒMbP?r   zFPS: Ú z)producer:Client disconnected.  Do cleanupzError in producer_handler: )Úserver.websocket_handlersr   Úplayer_cacher   ÚappÚplayerRecordsÚtimeÚgetÚuserIDÚ
connectionr
   ÚFRAME_DURATIONÚasyncioÚsleepÚfpsÚprintÚstrÚtypeÚcÚ	firstnameÚlastnameÚ
websocketsÚ
exceptionsÚConnectionClosedÚ	ExceptionÚ	tracebackÚ
format_excÚclose)r   r   r   r   r   Ú
start_timeZframe_countÚplayerZframe_start_timeZframe_end_timeZframe_durationZelapsed_timeZsleep_durationÚerrÚer   r   r	   Úproducer_handler,   sF    


H"r.   c                 Ã   sp   ddl m} ttjdd�}| 2 zJ3 dH W }| | j¡sXtd| j› �ƒ || dƒI dH  qt|| ƒI dH  q6 dS )a  
    Handle consumer with rate limiting and error catching.

    This listens for incoming WebSocket messages and processes them
    through the consumer, with rate limiting to prevent abuse.

    Args:
        websocket: The WebSocket connection with userID attribute
    r   )Úerroré<   )Úmax_requestsÚwindow_secondsNzRate limit exceeded for z&Rate limit exceeded. Please slow down.)	r   r/   r   r   Ú!WEBSOCKET_MAX_MESSAGES_PER_MINUTEÚ
is_allowedr   r   Úconsumer)r   r/   Úrate_limiterÚmessager   r   r	   Úconsumer_handlerf   s    
þr8   c           
      Ã   s  ddl m} ddlm} ddlm} ddl}|j}| |j	¡}|j
|j|j|j|jj|jj|jj|jj|jj|jj|jj|jj|jj|jj|jj|jj|jdœ}| s°tdƒ dS t| tƒrÄ|  d	¡} td
|  ƒ t  !| ¡}	||	||ƒI dH  ||||ƒ}|�r|i k�r|||ƒI dH  dS )ay  
    Process incoming WebSocket messages and dispatch commands.

    This function uses a table-driven command dispatcher for clean, maintainable
    command handling with O(1) lookup time.

    Args:
        message: The incoming WebSocket message (string or bytes)
        websocket: The WebSocket connection

    Returns:
        True if successful, False if no message
    r   )Údispatch_command)ÚsendDict)ÚhandleUpdatesN)ÚdateÚ	hourOfDayÚminuteOfHourÚweekDayTextÚenergyÚ
calcEnergyÚmoneyÚdiamondsÚprestigeÚstressÚ	happinessÚ
occupationÚlocationÚ	schedulesÚintraDayMessageÚ	dailyPlanÚ	gameSpeedz
no messageFzutf-8ZreceivedT)"Zserver.command_dispatcherr9   Úserver.websocket_messagingr:   Ú	functionsr;   r   r   r   r   r<   r=   r>   r?   r    r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   r   Ú
isinstanceÚbytesÚdecodeÚjsonÚloads)
r7   r   r9   r:   r;   r   r   r+   ÚupdateObjectÚeventr   r   r	   r5   ‚   sH    ï


r5   )Ú__doc__r   rR   r   r'   r#   Úloggingr   r6   r   Ú	getLoggerÚ__name__ÚloggerZ
TARGET_FPSr   r
   r.   r8   r5   r   r   r   r	   Ú<module>   s   

: