o
    [hQ?                     @   s  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 d dlmZ d dlm	Z	 d dl
mZ d dlZd dlmZ d dlmZmZ d d	lmZmZ d d
lmZmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z" d dl#m$Z$ d dl%m&Z& d dlm'Z' e(e)Z*dd Z+dd Z,dd Z-dd Z.dDddZ/dd  Z0dEd!e1fd"d#Z2d$d% Z3d&e4fd'd(Z5d)d* Z6d+d, Z7d-e	e  fd.d/Z8d0d1 Z9d&e4fd2d3Z:d4d5 Z;d6d7 Z<dEd8d9Z=d:d; Z>d d<l?m@Z@ d=d> ZAd?d@ ZBdAdB ZCdCZDdS )F    N)OrderedDict)defaultdict)escape)List)func)get_models_module)TimeSpentRowwrite_page_completion_buffer)CurrencyRealWorldCurrency)dbqvalues_flat)database)	BaseGroup)Participant)
BasePlayer)Session)BaseSubsession)PageTimeBatch)SessionConfig)settingsc                 C   s   dd | j jD S )Nc                 S      g | ]}|j qS  )name.0fr   r   s/home/ubuntu/experiments/live_experiments/Pythonexperiments/Otree/venv/lib/python3.10/site-packages/otree/export.py
<listcomp>       z'inspect_field_names.<locals>.<listcomp>)Z	__table__columnsModelr   r   r   inspect_field_names   s   r#   c                 c   s2    t | }|j|j|jfD ]	}t|ddV  qd S NF
for_export)r   PlayerGroup
Subsession_get_table_fields)app_namemodels_moduler"   r   r   r   get_fields_for_data_tab"   s
   r-   c                   C   s   t tddS r$   )r*   r   r   r   r   r   get_fields_for_monitor(      r.   c                 C   s   t | ddS )NTr%   )r*   r!   r   r   r   get_fields_for_csv,   r/   r0   Fc                 C   s   | t u rg dS | tu r|rg dS g dS t| tr3dd t| D }g d| }|r.|S dg| S t| trFdd t| D }d	g| S t| tr]d
d t| D }|r[dg| S |S d S )N)codelabelZmturk_HITIdZmturk_HITGroupIdcommentZis_demo)id_in_sessionr1   r2   Z_is_botZ_index_in_pagesZ_max_page_index_current_app_name_current_page_nameZtime_started_utcvisitedZmturk_worker_idZmturk_assignment_idpayoff)	_numeric_labelr1   r2   _current_pager5   Z_round_numberr6   Z_monitor_noteZ_last_page_timestampc                 S      g | ]
}|t tvr|qS r   )dirr   r   r   r   r   r   `       z%_get_table_fields.<locals>.<listcomp>)Zid_in_grouproler8   groupc                 S   r;   r   r<   r   r   r   r   r   r   j   r=   id_in_subsessionc                 S   r;   r   r@   r   r   r   r   r   q   r=   round_number)r   r   
issubclassr   r#   r   r   )r"   r&   Zsubclass_fieldsfieldsr   r   r   r*   0   s6   	





r*   c                 C   sf   | d u rdS | du rdS | du rdS t | ttfrt| S t | tjr%| S t| } | ddddS )	N T   Fr   
 )
isinstancer
   r   floatnumbersNumberstrreplace)valuer   r   r   sanitize_for_csvz   s   rQ   playerc                 C   s,   | d | d< | d | d< |r|| d< dS dS )zBbecause these are actually properties, the DB field starts with _.Z_payoffr8   Z_roler>   r?   Nr   )rR   Zgroup_id_in_subsessionr   r   r   tweak_player_values_dict   s
   rS   c                 C   s4   t tt| } d}t| |kr| d | d S | S )N   u   …)r   rN   rQ   len)rP   Z
MAX_LENGTHr   r   r   sanitize_for_live_update   s
   rV   returnc                  C   sD   t  } ttD ]}|jd D ]}|tjv r| | qqtt| S )z
    this is just important for devserver.
    on prodserver there should never be an inconsistency between
    currently installed apps and apps with data, because you resetdb each time
    app_sequence)	setr   r   configr   Z
OTREE_APPSaddlistsorted)app_names_with_datasessionr+   r   r   r   get_installed_apps_with_data   s   

r`   c                    sh   t  }| D ]}|jd }|t|  |j7  < q|dd d  t } fdd|D }t | S )NrX   rF   r   c                    s   g | ]}| vr|qS r   r   )r   ZappZmost_common_app_sequencer   r   r      s    z'_get_best_app_order.<locals>.<listcomp>)collectionsCounterrZ   tuplenum_participantsmost_commonr`   r\   )sessionsZapp_sequencesr_   rX   r^   Zapps_not_in_popular_sequencer   ra   r   _get_best_app_order   s   

rh   c              	      st  | r
t j| dg}n	tt d }tt }tt}dd |D }ttj	|tj
 }dd |D }dh}|D ]tj D ]}|| qFq=t|}|sXg gS dd |D }	|	d	d tjD 7 }	|	d
d |D 7 }	|	dd |D 7 }	|	dd tjD 7 }	|	g}
|D ]C | j  fdd|D }| fddtjD 7 }|fdd|D 7 }|fdd|D 7 }|fddtjD 7 }|
| qt|}t }|D ]/}zt|}W n ty   td| d Y qw tt|jj }|d ur|||< q|D ])}td|| d D ]}t |||}tt!|
D ]}|
| "||  q"qq	dd |
D S )N)r1   idc                 S   r   r   ri   )r   r_   r   r   r   r      r   z)get_rows_for_wide_csv.<locals>.<listcomp>c                 S   s   i | ]}|j |qS r   rj   r   rowr   r   r   
<dictcomp>       z)get_rows_for_wide_csv.<locals>.<dictcomp>r   c                 S      g | ]}d | qS zparticipant.r   r   fnamer   r   r   r          c                 S   ro   rp   r   rq   r   r   r   r      rs   c                 S   ro   zsession.r   rq   r   r   r   r      rs   c                 S   ro   )zsession.config.r   rq   r   r   r   r      rs   c                 S   ro   rt   r   rq   r   r   r   r      rs   c                       g | ]}t  |qS r   getattrrq   ppr   r   r      rs   c                       g | ]	} j |d qS Nvarsgetrq   rx   r   r   r          c                    ru   r   rv   rq   r_   r   r   r      rs   c                    s   g | ]} j |qS r   )rZ   r~   rq   r   r   r   r      s    c                    rz   r{   r|   rq   r   r   r   r      r   zCannot export data for app z>, which existed when the session was run but no longer exists.rF   c                 S   s   g | ]	}d d |D qS )c                 S      g | ]}t |qS r   rQ   r   vr   r   r   r      rn   z4get_rows_for_wide_csv.<locals>.<listcomp>.<listcomp>r   rk   r   r   r   r      r   )#r   Zobjects_getr   order_byallr0   r   Zobjects_filter
session_idin_ri   r   rZ   Zeditable_fieldsr[   r\   r   ZPARTICIPANT_FIELDSZSESSION_FIELDSappendrh   r   r   ModuleNotFoundErrorloggerwarningr   maxr)   rB   Zscalarrangeget_rows_for_wide_csv_roundrU   extend)session_coderg   Zsession_fieldsZparticipant_fieldssession_idsZppsZsession_cacheZsession_config_fields
field_name
header_rowrowsrl   Zorder_of_appsZrounds_per_appr+   r,   Zhighest_round_numberrB   Znew_rowsir   )ry   r_   r   get_rows_for_wide_csv   sx   

	
r   rg   c                    s  t j| }|j}|j}|j}t|}t|}t|}	g }
dd |j|dD }g }d|fd|fd|	ffD ]\}}|D ]}||  d| d| d|  q;q5|
| dd	 t	t
|D  |D ]}|j|j|d
}|sz fdd	t	|jD }nb|\|jd dd}t
||jkrd|j d|j d| d|  dt
| d}t|g }|D ]0|d  t fdd	|D }|fdd	|D 7 }|fdd	|	D 7 }|| q|
| qa|
S )Nc                 S      i | ]}|d  |qS rj   r   rk   r   r   r   rm         
z/get_rows_for_wide_csv_round.<locals>.<dictcomp>)rB   rR   r?   
subsession.c                 S   s   g | ]}d qS )rE   r   r   _r   r   r   r         z/get_rows_for_wide_csv_round.<locals>.<listcomp>)r   rB   c                    s   g | ]} qS r   r   r   )	empty_rowr   r   r   !  r   ri   )subsession_idr   zSession z has z participants, but round z	 of app 'z' has z players. The number of players in the subsession should always match the number of players in the session. Please report this issue and then reset the database.group_idc                       g | ]} | qS r   r   rq   )rR   r   r   r   6  rn   c                    r   r   r   rq   )r?   r   r   r   7  rn   c                    r   r   r   rq   )r   r   r   r   8  rn   )otreecommonr   r'   r(   r)   r0   values_dictsr   r   rU   ri   re   r1   AssertionErrorrS   r   )r+   rB   rg   r,   r'   r(   r)   pfieldsgfieldssfieldsr   Zgroup_cacher   
model_namerD   rr   r_   subsessionsZsubsession_rowsplayersmsgrl   r   )r   r?   rR   r   r   r     sb   
"
r   c              
      s<  t j| }|j}|j}|j}dd |||ttfD  tt	||j
}|jdd}tdd | D dd | D dd ttj
|D dd ttj|D d	}g d
} fdd|D g}	|D ]4}
t|
 g }|D ]$}|dkrz|
}n|| |
| d  } | D ]}|t||  qqq|	| qg|	S )Nc                 S   s   i | ]
}|j  t|qS r   )__name__lowerr0   )r   r"   r   r   r   rm   G  s    z$get_rows_for_csv.<locals>.<dictcomp>ri   )r   c                 S   r   rj   r   rk   r   r   r   rm   Q  rs   c                 S   r   rj   r   rk   r   r   r   rm   R  rs   c                 S   r   rj   r   rk   r   r   r   rm   U  s    c                 S   r   rj   r   rk   r   r   r   rm   Y  r   )r?   r   participantr_   )r   rR   r?   r   r_   c                    s(   g | ]} | D ]	}| d | qqS )r   r   )r   mcolZcolumns_for_modelsr   r   r   a  s   ( z$get_rows_for_csv.<locals>.<listcomp>rR   Z_id)r   r   r   r'   r(   r)   r   r   r   r   r   r   dictr   ri   rS   r   rQ   )r+   r,   r'   r(   r)   r   r   Zvalue_dictsZmodel_orderr   rR   rl   r   objZcolnamer   r   r   get_rows_for_csv?  sB   r   c                 C   sb   t  }ddh}g }| D ]#}i }|D ]}t||}||v r| }|||< q|j|d< || q|S )Nr9   r:   r4   )r.   rw   r4   r   )Zparticipantsfield_namesZcallable_fieldsr   r   rl   r   rP   r   r   r   get_rows_for_monitors  s   


r   c                 c   s&    | j d D ]
}t| |E d H  qd S )NrX   )rZ   get_rows_for_data_tab_app)r_   r+   r   r   r   get_rows_for_data_tab  s   r   c                 #   s,   t |}|j}|j}|j}t|\}}}|j| dd}	tt}
|	D ]|
d   q"dd |j| dD }dd |j| dD }t	dt
|d D ]F}g }|
| D ]:|d	   t d
  |d  fdd|D  fdd|D  fdd|D  }|dd |D  qU|V  qMd S )Nri   )r_   r   rB   c                 S   r   rj   r   )r   gr   r   r   rm     rs   z-get_rows_for_data_tab_app.<locals>.<dictcomp>r   c                 S   r   rj   r   )r   sr   r   r   rm     rs   rF   r   rA   r   c                    r   r   r   rq   )pr   r   r     rn   z-get_rows_for_data_tab_app.<locals>.<listcomp>c                    r   r   r   rq   )r   r   r   r     rn   c                    r   r   r   rq   )r   r   r   r     rn   c                 S   r   r   )rV   r   r   r   r   r     rn   )r   r'   r(   r)   r-   r   r   r\   r   r   rU   rS   )r_   r+   r,   r'   r(   r)   r   r   r   r   Zplayers_by_roundgroupsr   rB   tablerl   r   )r   r   r   r   r     s6   r   c                 C   s   t |d}t| | d S )N)r   )r   _export_csv)fpr   r   r   r   r   export_wide     
r   c                 C   s   t | }t|| d S r{   )r   r   )r+   r   r   r   r   r   
export_app  s   r   )
joinedloadc           	   
   C   s   t | }|j}tt|dt|jddt|jddt|j	ddt|j
dd}|D ]}d|_q,||}g }|D ]}|dd |D  q;t|| d S )Nri   T)Z	innerjoinFc                 S   r   r   r   )r   Zeler   r   r   r     rn   z%custom_export_app.<locals>.<listcomp>)r   r'   r\   r   r   optionsr   r   r?   r   r_   Z
_is_frozenZcustom_exportr   r   )	r+   r   r,   r'   qsrR   r   Zstr_rowsrl   r   r   r   custom_export_app  s&   

r   c                 C   s   t | }|| d S r{   )csvwriter	writerows)r   r   r   r   r   r   r     r   r   c                 C   sN   t   tttdtj}| dtj	
 d  |D ]}| | qd S )Nri   ,rG   )r	   r   r   r   r   textwritejoinr   __annotations__keys)r   Zbatchesbatchr   r   r   export_page_times  s   r   u   ﻿)Fr{   )Erb   r   loggingrL   r   r   htmlr   typingr   Zsqlalchemy.sql.functionsr   r   Zotree.commonr   Zotree.common2r   r	   Zotree.currencyr
   r   Zotree.databaser   r   r   Zotree.models.groupr   Zotree.models.participantr   Zotree.models.playerr   Zotree.models.sessionr   Zotree.models.subsessionr   Zotree.models_concreter   Zotree.sessionr   r   	getLoggerr   r   r#   r-   r.   r0   r*   rQ   r   rS   rV   r\   r`   rh   r   r   r   r   r   r   r   r   Zsqlalchemy.ormr   r   r   r   BOMr   r   r   r   <module>   s^    

JH=4
 