"""Проверка вымышленных CSV из статей Qupi. Python 3, без внешних пакетов. Запуск: python3 check-fleet-warehouse-demo.py Не предназначено для управления техникой или технической диагностики. """ from pathlib import Path import csv,json,math ROOT=Path(__file__).resolve().parent def rows(name): with (ROOT/name).open(encoding='utf-8',newline='') as f: return list(csv.DictReader(f)) def close(a,b): assert math.isclose(a,b,rel_tol=1e-9,abs_tol=1e-9),(a,b) r=rows('fleet-idle-demo.csv') engine=sum(float(x['engine_min']) for x in r);idle=sum(float(x['idle_min']) for x in r) assert all(0<=float(x['idle_min'])<=float(x['engine_min']) for x in r) liters=sum(float(x['idle_min'])/60*float(x['assumed_idle_l_h']) for x in r) close(engine,1800);close(idle,558);close(idle/engine,.31);close(liters,28.45) close(liters*.25*72,512.1);close(liters*.25*72*22,11266.2) out={'idle':{'engine_min':engine,'idle_min':idle,'weighted_idle_pct':idle/engine*100,'assumed_idle_l':liters,'scenario_saving_rub_shift':round(liters*.25*72,2),'scenario_saving_rub_22_shifts':round(liters*.25*72*22,2)}} r=rows('machine-camera-evaluation-demo.csv');tp=fn=fp=tn=0 for x in r: truth=x['person_in_defined_zone']=='1';alarm=x['alarm']=='1' if truth and alarm:tp+=1 elif truth:fn+=1 elif alarm:fp+=1 else:tn+=1 assert (tp,fn,fp,tn)==(10,2,3,3) out['camera']={'TP':tp,'FN':fn,'FP':fp,'TN':tn,'recall':tp/(tp+fn),'precision':tp/(tp+fp)} r=rows('fleet-maintenance-demo.csv');same=[x for x in r if x['machine_id']=='EX01' and x['mode']=='loading'] v=[float(x['coolant_c']) for x in same];assert v==[82,83,91] baseline=sum(v[:2])/2;close(baseline,82.5);close(v[-1]-baseline,8.5) out['maintenance']={'same_mode_records':[x['record_id'] for x in same],'baseline_c':baseline,'change_c':v[-1]-baseline,'diagnosis':'not_established'} r=rows('warehouse-reconciliation-demo.csv');eligible=[x for x in r if x['observation_status'] in ['read','confirmed_empty']];matches=[x for x in eligible if x['wms_pallet']==x['observed_pallet']];diff=[x['location'] for x in eligible if x['wms_pallet']!=x['observed_pallet']] assert len(r)==8 and len(eligible)==6 and len(matches)==3 and diff==['A02','A03','A04'] out['inventory']={'target':len(r),'visited':sum(x['observation_status']!='not_visited' for x in r),'comparable':len(eligible),'matches':len(matches),'discrepancies':diff,'unknown':[x['location'] for x in r if x not in eligible],'recognition_accuracy':'not_established'} r=rows('warehouse-drone-coverage-demo.csv');visit=sum(int(x['visited']) for x in r);read=sum(x['identification_status']=='read' for x in r);match=sum(x['comparison_status']=='match' for x in r) assert (len(r),visit,read,match)==(10,9,8,6) out['drone']={'target':len(r),'visited':visit,'read':read,'match':match,'discrepancy':sum(x['comparison_status']=='discrepancy' for x in r),'visit_coverage':visit/len(r),'read_coverage':read/len(r),'match_share':match/read} r=rows('warehouse-safety-events-demo.csv');periods={} for period in ['before','after']: group=[x for x in r if x['period']==period];denominators={int(x['exposure_forklift_passages']) for x in group} assert len(denominators)==1,'Exposure must be constant within each period' exposure=denominators.pop();confirmed=sum(x['review_status']=='confirmed' for x in group) periods[period]={'alarms':len(group),'confirmed':confirmed,'exposure':exposure,'per_1000':confirmed/exposure*1000,'confirmed_alarm_share':confirmed/len(group)} assert periods['before']['per_1000']==8 and periods['after']['per_1000']==4 out['safety']={'periods':periods,'absolute_change':1-periods['after']['confirmed']/periods['before']['confirmed'],'rate_change':1-periods['after']['per_1000']/periods['before']['per_1000'],'recall':'not_established'} print(json.dumps({'status':'passed','data':'fictional teaching examples','results':out},ensure_ascii=False,indent=2))