from pathlib import Path
import json
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
R=Path(__file__).resolve().parent
v=pd.read_parquet(R/'reviews.parquet');t=pd.read_parquet(R/'targets.parquet').set_index('appid')
asof=pd.Timestamp(json.loads((R/'analysis_spec.json').read_text())['asof'])
BLUE='#287ba5';ORANGE='#d56b43';GRAY='#8696a3';INK='#253545'
plt.rcParams.update({'font.family':'DejaVu Sans','font.size':10,'text.color':INK,'text.parse_math':False,
 'axes.spines.top':False,'axes.spines.right':False,'axes.edgecolor':'#ccd6df','figure.facecolor':'#fafbfc','axes.facecolor':'#fafbfc','savefig.facecolor':'#fafbfc'})
seqs=[('Rad Codex',1224290,1366100,2276830),('Studio Fizbin',1191900,1278750,2129810),('Tuatara Games',505630,1186660,2050800),('Desert Fox',538070,2540460,3202410)]
fig,axs=plt.subplots(2,2,figsize=(14,10));fig.subplots_adjust(top=.85,bottom=.12,hspace=.45,wspace=.23)
fig.suptitle('Compare the games at the same age: the apparent decline often changes',x=.055,ha='left',y=.975,fontsize=18,fontweight='bold')
fig.text(.055,.928,'Four selected catalogs • cumulative creation dates of currently returned reviews • not a representative sample',fontsize=11)
for ax,(dev,a,b,c) in zip(axs.flat,seqs):
 for appid,color,style in [(a,BLUE,'-'),(b,GRAY,'--'),(c,ORANGE,'-')]:
  launch=t.loc[appid,'first_date'];last=min(365,int((asof-launch).total_seconds()/86400));days=np.arange(last+1)
  dates=np.sort(v.loc[v.appid.eq(appid),'timestamp_created'].to_numpy());cutoffs=launch.timestamp()+days*86400
  counts=np.searchsorted(dates,cutoffs,side='left')
  ax.step(days,counts,where='post',color=color,ls=style,lw=2,label=t.loc[appid,'name'])
 ax.axvline(90,color='#abb7bf',ls=':',lw=1);ax.set_xlim(0,365);ax.set_ylim(bottom=0)
 ax.set_xticks([0,30,90,180,270,365]);ax.grid(axis='y',alpha=.14)
 ax.set_title(dev,loc='left',fontsize=13,fontweight='bold');ax.set_xlabel('Days since recorded Steam release');ax.set_ylabel('Dated reviews accumulated')
 ax.legend(loc='upper left',frameon=False,fontsize=9)
fig.text(.055,.055,'Blue: earlier prominent game  •  Gray: intervening quiet release  •  Orange: later release. Lines stop at the available age.',fontsize=11)
fig.text(.055,.02,'Historical counts exclude reviews since deleted or filtered out. Current text and recommendations may have changed after posting.',fontsize=10)
for ext in ['png','svg']:fig.savefig(R/f'age_comparison.{ext}',dpi=160)
plt.close(fig)

fig,axs=plt.subplots(1,2,figsize=(14,6.5));fig.subplots_adjust(top=.79,bottom=.24,wspace=.30,left=.07,right=.96)
fig.suptitle('BYTEPATH and SNKRX: a similar first week, then very different trajectories',x=.04,ha='left',y=.975,fontsize=17,fontweight='bold')
fig.text(.04,.913,'Surviving Steam-purchase review records collected September 6, 2026 • neither series is a sales estimate',fontsize=11)
for appid,color in [(760330,BLUE),(915310,ORANGE)]:
 launch=t.loc[appid,'first_date'];dates=np.sort(v.loc[v.appid.eq(appid),'timestamp_created'].to_numpy())
 for ax,limit in zip(axs,[14,365]):
  days=np.arange(limit+1);counts=np.searchsorted(dates,launch.timestamp()+days*86400,side='left')
  ax.step(days,counts,where='post',color=color,lw=2.5,label=t.loc[appid,'name'])
  ax.set_xlim(0,limit);ax.set_ylim(bottom=0);ax.grid(axis='y',alpha=.15)
  ax.set_xlabel('Days since recorded release');ax.set_ylabel('Dated reviews accumulated')
for ax,limit in zip(axs,[14,365]):
 maximum=max(int(v.loc[v.appid.eq(appid),'timestamp_created'].lt(t.loc[appid,'first_date'].timestamp()+limit*86400).sum()) for appid in [760330,915310])
 ax.set_ylim(0,maximum*1.08)
axs[0].set_title('First 14 days',loc='left',fontweight='bold');axs[1].set_title('First year',loc='left',fontweight='bold')
axs[0].legend(frameon=False);axs[1].legend(frameon=False)
fig.text(.04,.13,'At day 7: BYTEPATH 61, SNKRX 52. At day 90: BYTEPATH 85, SNKRX 2,298.',fontsize=12,fontweight='bold')
fig.text(.04,.065,'Before SNKRX launched, BYTEPATH had 219 of its currently surviving dated reviews; it has 306 in the collection now.',fontsize=11)
fig.text(.04,.025,'The curves describe review arrival, not its cause. They cannot separate discovery, promotion, updates or other influences.',fontsize=10)
for ext in ['png','svg']:fig.savefig(R/f'own_game_history.{ext}',dpi=160)
plt.close(fig)
print('Saved two PNG/SVG figures.')
