from common import *
import re,json
g,t=load();main=g[g.valid&~g.free&~g.explicit];pool=main[main.year.between(2023,2025)]
# Pair fragility, largest maker and title removal. Selected pairs fixed in market.py.
rows=[]
for names in [['Local Co-Op','Action Roguelike'],['Online Co-Op','Roguelite'],['Roguelite','Mystery'],['Card Game','Base Building'],['Retro','Idler'],['Loot','Idler']]:
    for rank in [7,20]:
        ids=member(t,names,rank);a=pool[pool.appid.isin(ids)]
        remove_dev=a.groupby('dev').reviews.sum().idxmax() if len(a) else None
        remove_pub=a.groupby('pub').reviews.sum().idxmax() if len(a) else None
        for label,x in [('full',a),('remove_top3',a.sort_values('reviews',ascending=False).iloc[3:]),('remove_top_dev',a[a.dev.ne(remove_dev)]),('remove_top_pub',a[a.pub.ne(remove_pub)])]:
            rows.append(dict(group=' + '.join(names),rank=rank,sensitivity=label,**stats(x)))
save(rows,'pair_removals.csv')
# Release-share growth is measured on equal calendar windows, not outcome aging.
rows=[]
for rank in [7,20]:
    for names in [['Desktop Companion'],['Shop Keeper'],['Boomer Shooter'],['Roguelike Deckbuilder'],['Idler'],['Bullet Heaven'],['Card Game','Base Building'],['Retro','Idler'],['Loot','Idler']]:
        ids=member(t,names,rank)
        for y in [2023,2024,2025,2026]:
            p=main[main.year.eq(y)&main.month.le(6)];a=p[p.appid.isin(ids)]
            rows.append(dict(group=' + '.join(names),rank=rank,year=y,window='H1',eligible=len(p),supply_share=len(a)/len(p),**stats(a)))
save(rows,'tag_supply_and_age.csv')
# Price-gradient test with price absent from the review-count outcome.
rows=[]
for label,p in [('all',pool),('selfpub',pool[pool.selfpub])]:
    for band,a in p.groupby('price_band'):
        rows.append(dict(population=label,band=band,**stats(a),**compare(a,p[p.price_band.ne(band)],cols=('year','primary','length_band'))))
save(rows,'price_adjustment.csv')
# Review-count prior definition independent of price, same historical windows.
c=pd.read_parquet(R/'career_games.parquet');early=c[c.year.between(2020,2022)];later=c[c.year.between(2023,2025)].copy()
past=early.groupby('dev').reviews.max();later['prior2020_22']=later.dev.map(past)
rows=[]
for threshold in [100,556,1000]:
    for w,d in [('release',later),('first_per_dev',later.drop_duplicates('dev',keep='first'))]:
        for state,a in [('prior_above',d[d.prior2020_22.ge(threshold)]),('prior_below',d[d.prior2020_22.lt(threshold)])]:
            rows.append(dict(threshold=threshold,weighting=w,state=state,**stats(a)))
save(rows,'prior_fixed_thresholds.csv')
# Migration/sequels among previous successes, unlike the pure-miss analysis.
def base(s):
    s=re.sub('[™®©]','',str(s).casefold()).strip()
    return re.sub(r'\s*[:\-–—]?\s*(?:[2-9]|1[0-9]|ii|iii|iv|v|vi|vii|viii|ix|x)$','',s).strip(' :-')
def sequel(a,b):
    aa,bb=base(a),base(b);ca=str(a).lower().split(':');cb=str(b).lower().split(':')
    return (len(aa)>=5 and aa==bb and a!=b) or (len(ca)>1 and len(cb)>1 and len(ca[0])>=6 and ca[0]==cb[0])
x=c[c.date.le(pd.Timestamp('2025-07-01',tz='UTC'))&c.debut.ge(pd.Timestamp('2015-01-01',tz='UTC'))&c.prior_best.ge(556)&c.gap_days.ge(30)].copy()
x['sequel']=[sequel(a,b) for a,b in zip(x['name'],x.prev_name)];x['same_primary']=x.primary.eq(x.prev_primary)
top=t[t['rank'].le(10)].groupby('appid').tag.agg(set).to_dict()
x['overlap']=[len(top.get(a,set())&top.get(b,set()))/max(1,len(top.get(a,set())|top.get(b,set()))) for a,b in zip(x.appid,x.prev_appid)]
x['overlap_band']=pd.cut(x.overlap,[-.001,.1,.25,.5,1],labels=['<=.1','.1-.25','.25-.5','>.5']).astype(str)
rows=[]
for w,d in [('release',x),('one_latest_per_dev',x.drop_duplicates('dev',keep='last'))]:
    for dim in ['same_primary','sequel','overlap_band']:
        for val,a in d.groupby(dim):rows.append(dict(weighting=w,dimension=dim,value=str(val),**stats(a),**compare(a,d[d[dim].ne(val)],cols=('year','price_band','prior_band'))))
save(rows,'successful_migration.csv')
# Named counterexamples: minimally overlapping store labels are not verified design pivots.
x[x.overlap.le(.1)][['dev','prev_name','name','prev_appid','appid','overlap','reviews','prev_reviews']].to_csv(R/'low_overlap_pairs.csv',index=False)
print('Follow-up tests complete')
