a
    `iT                  3   @   s  d Z ddlmZmZmZmZ ddlZddlZddl	m
Z
 eeZddddd	d
ddddddddddddddd	d
dddddddddddddddddddd d!dd"d#ddd$d%d&dd'd(ddd)d*d+dd,d-ddd.d/d0dd1d2ddd3d4d5dd6d7ddd8d9d:d;dd<ddd=d>d?d;d1d@dddAdBdCd;d'dDdddEdFdGd;dd#dddHdIdJd;ddKdddLdMdNd;d"dOdddPdQdRd;dSdTdddUdVdWd;d	dXdddYdZd[d\dd]ddd^d_d`d\d'dadddbdcddd\d	dedddfdgdhd\didjdddkdldmd\d"dndddodpdqd\ddrdddsdtdud\dvdwdddxdydzd{d|d}ddd~ddd{d1ddddddd{d,ddddddd{dddddddd{d	d2dddddd{dddddddd{ddddddddddddddddd	dddddddd'dddddddd,dddddddd1dddddddd"dTddddddddddddddd'dddddddddddddddd,ddddddddidddddddd	dddg,ZddɄ Zdeeeeef ee dʜdd̄Zeeee d͜ddτZeeeef dМdd҄ZdS )z
Achievement System

Tracks and unlocks achievements based on player actions.
Includes 40+ achievements across multiple categories.
    )DictAnyListOptionalN)get_database_connectionZfirst_stepszFirst Stepsz Complete the onboarding tutorialZlife_milestone   ZgraduationcapF)keynamedesccategoryrewardiconhiddenfirst_day_schoolzFirst Day of SchoolzStart elementary school
   Zbookgraduate_hszHigh School GraduatezGraduate from high schoolgraduate_collegezCollege DegreezGraduate from college2   scrollgraduate_masterszMaster ScholarzComplete a master's degreeK   Zbraingraduate_phdzDoctor of Philosophyz
Earn a PhDd   Zcrownget_marriedzHappily Ever AfterzGet married   Zheart
have_childz
New ParentzHave your first child(   zfigure.2
live_to_50zHalf CenturyzLive to 50 years old   Zstarlive_to_100zCentury ClubzLive to 100 years old   z	star.fill	first_jobzWorking ClasszGet your first jobcareerZ	briefcase	promotionzClimbing the LadderzGet promotedzarrow.upbecome_managerzManagement MaterialzBecome a managerzperson.2
become_ceozCorner OfficezBecome a CEOZ	earn_100kzSix FigureszEarn $100,000 in a yearzdollarsign.circleearn_1m_lifetimeZMillionairez Earn $1,000,000 in your lifetimeZbanknoteearn_10m_lifetimezMulti-Millionairez!Earn $10,000,000 in your lifetime   zbanknote.fillZperfect_performancezEmployee of the YearzAchieve 100% job performanceZtrophymake_first_friendzSocial Butterfly BeginszMake your first friendrelationshippersonbest_friendzBest Friends ForeverzReach 100 affinity with someonez
heart.filldate_10_peoplezDating AroundzDate 10 different peoplezheart.multiple
first_kissz
First KisszShare your first kiss   zheart.circlegolden_anniversaryzGolden AnniversaryzStay married for 50 yearsZsparklesfive_childrenz
Big FamilyzHave 5 childrenz
house.fillpopularzMr/Ms PopularzHave 10 friends#   zperson.3first_purchasezFirst PurchasezBuy your first itemZ
collection   Zbagown_25_itemsZ	CollectorzOwn 25 itemszsquare.grid.3x3own_50_itemsZHoarderzOwn 50 itemszsquare.grid.4x3own_100_itemszUltimate CollectorzOwn 100 itemsP   zsquare.stack.3d.upprestige_100zRising StarzReach 100 prestigeprestige_500zCelebrity StatuszReach 500 prestigezstar.circlemax_prestigezMaximum PrestigezReach 1000 prestige   zstar.circle.fill	die_at_69ZNicezDie at exactly 69 years oldsecretzface.smilingTfired_3_timeszProfessional QuitterzGet fired 3 timeszxmark.circlenever_marryzForever Alonez Complete a life without marryingzperson.fillmarry_3_timeszSerial MonogamistzGet married 3 different timeszarrow.triangle.2.circlepathdie_poorzBroke at DeathzDie with less than $100zbanknote.slashdie_richzDied WealthyzDie with over $1,000,000Zperfect_healthz
Health Nutz$Maintain 100% health for a full yearzheart.text.square.fillZ
workaholicZ
WorkaholiczWork 80+ hours in a weekZ	deskclockZearly_retirementzEarly RetirementzRetire before age 40zbeach.umbrella
straight_azStraight A StudentzGraduate with a 4.0 GPAza.circle.fillZdropoutzSchool DropoutzDrop out of high schoolzbook.closedZ
no_friendsz	Lone Wolfz'Reach age 30 without making any friendszperson.fill.questionmarkc                  C   s   d} d}zzpt  } |  }tD ]:}|d|d |d |d |d |d |d |d	 f q|   td
tt d W nD ty } z,| r| 	  tj
d| dd W Y d}~n
d}~0 0 W |r|  | r|   n|r|  | r|   0 dS )z-Insert achievement definitions into database.Na  INSERT INTO achievements
                   (key_name, display_name, description, category, diamond_reward, icon_name, hidden)
                   VALUES (%s, %s, %s, %s, %s, %s, %s) AS new_ach
                   ON DUPLICATE KEY UPDATE
                   display_name=new_ach.display_name,
                   description=new_ach.description,
                   diamond_reward=new_ach.diamond_rewardr   r	   r
   r   r   r   r   zInitialized z achievementsz!Error initializing achievements: Texc_info)r   cursorACHIEVEMENT_DEFINITIONSexecutecommitlogginginfolen	Exceptionrollbackerrorclose)connrH   Zache rU   7/var/www/lichun.app/lichun/ws/retention/achievements.pyinitialize_achievementsv   s4    ,
rW   )	player_id
event_type
event_datareturnc              
   C   s  |du ri }g }d}d}zpzt  }|jdd}z@|d| f | }|spg W W W |rb|  |rn|  S W nn tjjjy } zPdt	|v rt
d g W  Y d}~W W |r|  |r|  S  W Y d}~n
d}~0 0 |d| f | }|dkr|t| d	|| n|d
kr|dd}	d|	 v rz|t| d|| |dddkr |t| d|| nd|	 v sd|	 v r|t| d|| nTd|	 v r|t| d|| n0d|	 v sd|	 v r0|t| d|| n,|dkr:|r0|d dkr0|t| d|| n|dkr|t| d|| |d d }
d!|
v r|t| d"|| n(d#|
v sd$|
v r0|t| d%|| n||d&kr|t| d'|| |r0|d( r0|t| d)|| n6|d*krZ|r.|d+ dkr.|t| d,|| n(|r0|d+ d-kr0|t| d.|| n|d/kr||t| d/|| n|d0kr|d1|d1 }|d2kr|t| d3|| n>|d4kr|t| d5|| n|d6kr0|t| d7|| n8|d8kr|d9 d6k r&|t| d:|| n"|d9 d;krH|t| d<|| |r0|d( sl|t| d=|| |d> d;kr|t| d?|| n"|d> d@kr0|t| dA|| nz|dBkr|r|dC dkr|t| dD|| n(|r0|dC dEkr0|t| dF|| n|dGkr|dH| f | }|rD|dI nd}|dkrh|t| dJ|| n^|dKkr|t| dL|| n>|d2kr|t| dM|| n|d6kr0|t| dN|| nh|dOkr|dPd}|d6kr0|t| dQ|| n2|dRkr0|r0|dS dTkr0|t| dU|| |dV d6krR|t| dW|| |dV dXkrt|t| dY|| |dV dZkr|t| d[|| |r|d\ dEkr|t| d]|| |r|d^ d2kr|t| d_|| |W W |r|  |r|  S  tyj } zHtjd`|  da| ddb g W  Y d}~W |rR|  |r`|  S d}~0 0 W |r||  |r|  n|r|  |r|  0 dS )ca  
    Check if any achievements should be unlocked based on event.

    Args:
        player_id: The player's ID
        event_type: Type of event that occurred
        event_data: Additional event data

    Returns:
        List of unlocked achievements
    NT
dictionaryzSELECT age, money, diamonds, prestige, health, happiness,
                          educationLevel, occupation, occupationSalary
                   FROM players WHERE id = %sZ42S02zDPlayers table not found - achievements disabled until migration runsz4SELECT * FROM player_statistics WHERE player_id = %sZstart_schoolr   Zgraduatelevel high_schoolr   gpar   g      @rE   collegeZ
universityr   Zmasterr   ZphdZ	doctorater   Zget_jobZ	job_count   r!   r#   titlemanagerr$   Zceozchief executiver%   marriager   Zever_marriedrB   Zbirth_childZchildren_countr   r5   r1   r.   birthdayager   r   E   r>   r   r   ZdeathmoneyrC   i@B rD   rA   Zlifetime_earningsr&   i r'   Zmake_friendZfriends_countr)   r   r2   Zpurchase_itemzWSELECT COUNT(DISTINCT item_id) as item_count FROM player_inventory WHERE player_id = %s
item_countr4   r   r6   r7   r8   Zaffinity_milestoneaffinityr,   firedZtimes_fired   r@   prestiger:   i  r;   i  r<   Zpeople_datedr-   Zyears_marriedr0   z'Error checking achievements for player : rF   )r   rH   rJ   fetchonerR   mysql	connectorerrorsProgrammingErrorstrloggerwarningextendcheck_and_unlockgetlowerrO   rL   rQ   )rX   rY   rZ   unlockedrS   rH   playerrT   statsr^   rd   rh   resultrk   rl   rU   rU   rV   check_achievements   s4     
  























r   )rX   achievement_keyr[   c              
   C   s(  z| d|f | }|s2td|  g W S | d| |d f | }|rXg W S | d| |d |d f ddlm} || d	| |d
  |  td|  d|  |d |d |d |d |d |d
 dgW S  ty" } z*tj	d| d| dd g W  Y d}~S d}~0 0 dS )ar  
    Check if player has unlocked achievement. If not yet unlocked, unlock it.

    Args:
        player_id: The player's ID
        achievement_key: Achievement key name
        cursor: Database cursor (for efficiency)
        conn: Database connection (for commit)

    Returns:
        List containing the achievement dict if newly unlocked, empty list otherwise
    z.SELECT * FROM achievements WHERE key_name = %szAchievement not found: zqSELECT * FROM player_achievements
               WHERE player_id = %s AND achievement_id = %s AND unlocked = TRUEidzINSERT INTO player_achievements
               (player_id, achievement_id, progress, unlocked, unlock_date)
               VALUES (%s, %s, %s, TRUE, NOW())
               ON DUPLICATE KEY UPDATE unlocked = TRUE, unlock_date = NOW()Zprogress_maxr   )award_diamondsZachievement_Zdiamond_rewardzPlayer z unlocked achievement: Zkey_nameZdisplay_namedescriptionZ	icon_name)r   r   r	   r   r   r   zError unlocking achievement rp   TrF   N)
rJ   rq   rL   rx   Zmonetization.diamond_economyr   rK   rM   rO   rQ   )rX   r   rH   rS   ZachievementZ
player_achr   rT   rU   rU   rV   rz   X  sD    
	
	rz   )rX   r[   c              
   C   s@  d}d}zzt  }|jdd}|d| f | }|d| f | }||ttt|tt|tt d dW W |r|  |r|  S  t y } zPt	j
d|  d	| dd
 g g ddddW  Y d}~W |r|  |r|  S d}~0 0 W |r|  |r<|  n|r,|  |r:|  0 dS )z
    Get all achievements and player's progress.

    Args:
        player_id: The player's ID

    Returns:
        Dict with 'unlocked' and 'locked' achievement lists
    NTr\   zSELECT a.*, pa.unlock_date
               FROM achievements a
               JOIN player_achievements pa ON a.id = pa.achievement_id
               WHERE pa.player_id = %s AND pa.unlocked = TRUE
               ORDER BY pa.unlock_date DESCa8  SELECT a.*
               FROM achievements a
               WHERE a.id NOT IN (
                   SELECT achievement_id FROM player_achievements
                   WHERE player_id = %s AND unlocked = TRUE
               )
               AND a.hidden = FALSE
               ORDER BY a.category, a.diamond_rewardr   )r}   lockedZtotal_countZunlocked_countZprogress_percentz&Error getting achievements for player rp   rF   r   )r   rH   rJ   fetchallrN   rI   intrR   rO   rL   rQ   )rX   rS   rH   r}   r   rT   rU   rU   rV   get_player_achievements  sT    

r   )N)__doc__typingr   r   r   r   rL   Zmysql.connector.errorsrr   databaser   	getLogger__name__rw   rI   rW   r   rv   r   rz   r   rU   rU   rU   rV   <module>   s  
e%" >C