from common import *
import json,html
p=pd.read_csv(R/'catalogs.csv');g=pd.read_parquet(R/'games.parquet');x=pd.read_parquet(R/'latest_transitions.parquet')
names=g[['developer_id','credit','creator_page_key']].drop_duplicates();names['punctuation_key']=names.credit.map(lambda s:''.join(c for c in html.unescape(s).casefold() if c.isalnum()))
counts=names.groupby('punctuation_key').developer_id.nunique();keys=set(counts[counts.gt(1)].index)
ambig=set(names.loc[names.punctuation_key.isin(keys),'developer_id']);placeholder=set(names.loc[names.punctuation_key.str.len().lt(2),'developer_id']);excluded=ambig|placeholder
names[names.developer_id.isin(excluded)].to_csv(R/'identity_sensitivity_exclusions.csv',index=False)
rows=[]
for label,mask in [('main',pd.Series(True,index=p.index)),('exclude_possible_name_fragments',~p.developer_id.isin(excluded))]:
    a=p[mask&p.core_shape&p.hits.ge(1)]
    for pattern,z in a.groupby('pattern'):rows.append(dict(scope=label,pattern=pattern,n=len(z),denominator=len(a),share=len(z)/len(a)))
save(rows,'identity_pattern_sensitivity.csv')
# At least two prior titles to permit repetition; controls with exactly one
# prior strong game. Exact strata report support rather than force sparse matches.
x=x[x['index'].ge(3)&x.prior_best.ge(1000)].copy();x['era']=np.where(x.year.le(2021),'2019-21','2022-25');x['price_coarse']=pd.cut(x.price,[0,10,20,np.inf],labels=['<=10','10-20','>20']).astype(str).fillna('missing');x['peak_coarse']=pd.cut(x.prior_best,[999,2999,9999,29999,np.inf],labels=['1000-2999','3000-9999','10000-29999','30000+']).astype(str)
control=x[x.prior_hits_1000.eq(1)];rows=[]
for name,mask in [('two',x.prior_hits_1000.eq(2)),('three_plus',x.prior_hits_1000.ge(3)),('two_plus',x.prior_hits_1000.ge(2))]:
    a=x[mask]
    for cols in [['era','peak_coarse'],['era','peak_coarse','price_coarse'],['era','peak_coarse','price_coarse','prior_n_band']]:
        rows.append(dict(prior_hits=name,controls='+'.join(cols),**stats(a),**compare(a,control,cols,min_n=3)))
save(rows,'repeat_hit_adjusted.csv')
# One-hit catalogs are split by the age of the qualifying release.
m=g[g.mature];first=m[m.reviews.ge(1000)].sort_values('date').drop_duplicates('developer_id').set_index('developer_id').date
one=pd.read_csv(R/'one_hit_catalogs.csv');one['first_strong_date']=pd.to_datetime(one.developer_id.map(first),utc=True)
one['peak_age_group']=np.where(one.first_strong_date.le(pd.Timestamp('2022-09-01',tz='UTC')),'at_least3years','under3years')
save([dict(peak_age=k[0],followup_state=k[1],n=len(a)) for k,a in one.groupby(['peak_age_group','followup_state'])],'one_hit_age_states.csv')
one.to_csv(R/'one_hit_catalogs_with_age.csv',index=False)
# Threshold dependence of consistency, with a fixed >=4-release sample.
core=set(p.loc[p.n.between(4,10)&pd.to_datetime(p.first_date,utc=True).ge(pd.Timestamp('2010-01-01',tz='UTC')),'developer_id']);a=m[m.developer_id.isin(core)];rows=[]
for threshold in [500,1000,2000]:
    z=a.groupby('developer_id').reviews.agg(['min','max','median','size']);hit=z[z['max'].ge(threshold)]
    rows.append(dict(threshold=threshold,catalogs=len(z),with_peak=len(hit),every_game_strong=int(hit['min'].ge(threshold).sum()),every_game_100=int(hit['min'].ge(100).sum()),median_floor=hit['min'].median(),median_catalog_median=hit['median'].median()))
save(rows,'consistency_thresholds.csv')
print('Identity names excluded in sensitivity',len(excluded),'core affected',int((p.core_shape&p.developer_id.isin(excluded)).sum()))
