"""Actual start setting parse/save and admin command bodies; native IO/UI are doubled. Frozen-mode lifecycle itself is tested by the separate core start fixture. """ import os,re from pathlib import Path from policy_harness import ROOT,body,run BASE=Path(os.environ.get('ERR_START_SETTINGS_ROOT',ROOT));CORE=BASE/'addons/core/Scripts/Game/ERR/00_Core' S=Path(os.environ.get('ERR_SETTINGS_SOURCE', CORE/'ERR_Settings.c'));A=CORE/'ERR_AdminService.c';M=CORE/'ERR_AdminMenu.c' def cpp(s): s=s.replace('protected ','').replace('out int ','int& ').replace('out map values','Values& values').replace('new map()','Values()').replace('map','Values') s=s.replace('array parts','Array parts').replace('array replies','Array& replies').replace('array','Array').replace('foreach (','for (') s=s.replace('JsonLoadContext json = new JsonLoadContext();','JsonLoadContext json;').replace('JsonSaveContext json = new JsonSaveContext();','JsonSaveContext json;').replace('JsonLoadContext json,','JsonLoadContext& json,') s=s.replace('ERR_GameMode mode','Mode* mode').replace('mode.','mode->').replace('Settings().','Settings()->').replace('Math.Round','std::round') for n in ['ERR_Settings','ERR_ProfileConfig','ERR_CommandArguments','ERR_AdminMenuFields','ERR_TimeService','ERR_EnvironmentService','Replication','FileIO']:s=s.replace(n+'.',n+'::') s=s.replace('"0123456789".IndexOf','string("0123456789").IndexOf') for n in ['value','saved','current']:s=s.replace(n+'.ToString()','string(std::to_string('+n+'))') return s settings='\n'.join(cpp(body(S,sig)) for sig in ['static array Keys(','static bool Valid(','static bool Randomizable(','static bool ValidSelection(','static string SelectionText(','static int AddedDefault(','protected bool Read(','static bool Parse(','bool Set(']) args='\n'.join(cpp(body(A,sig)) for sig in ['static bool Integer(','static bool Selection(']) fields='\n'.join(cpp(body(M,sig)) for sig in ['static string Display(','static string StartSummary(']) command=cpp(body(A,'protected bool StartCommand(')) run(r''' #include #include #include #include #include #include struct string:std::string{using std::string::string;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}int Length(){return size();}int ToInt(){return std::stoi(*this);}int IndexOf(string x){auto n=find(x);return n==npos?-1:int(n);}string Substring(int a,int n){return substr(a,n);}}; templatestruct Array:std::vector{using std::vector::vector;int Count(){return this->size();}void Insert(T v){this->push_back(v);}}; struct Values{std::map data;int Get(string k){return data.at(k);}void Set(string k,int v){data[k]=v;}void Remove(string k){data.erase(k);}}; std::map> disk;bool failSave=false; struct JsonLoadContext{std::map data;bool DoesKeyExist(string k){return data.count(k);}bool ReadValue(string k,float& v){if(!data.count(k))return false;v=data[k];return true;}}; struct JsonSaveContext{std::map data;void EnableTypeDiscriminator(bool){}void WriteValue(string k,int v){data[k]=v;}bool SaveToFile(string p){if(failSave)return false;disk[p]=data;return true;}}; namespace ERR_ProfileConfig{bool Load(string p,JsonLoadContext& j){if(!disk.count(p))return false;j.data=disk[p];return true;}bool Save(string p,JsonSaveContext&j){return j.SaveToFile(p);}bool Exists(string p){return disk.count(p);}} namespace FileIO{bool CopyFile(string a,string b){if(!disk.count(a))return false;disk[b]=disk[a];return true;}void DeleteFile(string p){disk.erase(p);}} namespace Replication{bool server=true;bool IsServer(){return server;}} struct ERR_Settings{static constexpr auto PATH="settings";string m_Path=PATH;bool m_ReadOnly=false;Values m_Values,m_Resolved;int Get(string k){return m_Values.Get(k);} '''+settings+r''' }; namespace ERR_TimeService{bool ParseClock(string,int&){return false;}string Clock(int){return "clock";}} namespace ERR_EnvironmentService{bool ParseDate(string,int&){return false;}bool ParseProfile(string,int&){return false;}string Date(int){return "date";}string ProfileName(int){return "weather";}} struct ERR_CommandArguments{ '''+args+r''' }; struct ERR_AdminMenuFields{ '''+fields+r''' }; struct Mode{ERR_Settings* settings;int frozen;ERR_Settings*Settings(){return settings;}int StartMode(){return frozen;}}; struct Admin{ '''+command+r''' }; int main(){ assert(ERR_Settings::AddedDefault("startMode")==0); assert(!ERR_Settings::Randomizable("startMode")&&!ERR_Settings::ValidSelection("startMode",-1)&&!ERR_Settings::ValidSelection("startMode",-2)); disk["old"]={{"reportIntervalSeconds",10},{"supportSquadLimit",4},{"responseRadiusMetres",2000},{"aiIntelChancePercent",60},{"intelRevealChancePercent",15},{"radioDefenceSeconds",180}}; ERR_Settings settings;assert(settings.Read("old",settings.m_Values)&&settings.Get("startMode")==0); for(float bad:{-1.f,-2.f,2.f,.5f}){disk["bad"]=disk["old"];disk["bad"]["startMode"]=bad;Values ignored;assert(!settings.Read("bad",ignored));} Mode mode{&settings,0};Admin admin;Array replies; assert(!admin.StartCommand(&mode,{"mission","radio","show"},replies)); assert(admin.StartCommand(&mode,{"mission","start","set","crash"},replies)); assert(settings.Get("startMode")==1&&mode.StartMode()==0&&disk["settings"]["startMode"]==1); assert(replies.back().find("Next start: Crash | Current round: Prison")!=string::npos); assert(replies.back().find("Saved for next round")!=string::npos); ERR_Settings restarted;assert(restarted.Read("settings",restarted.m_Values));Mode next{&restarted,restarted.Get("startMode")};assert(next.StartMode()==1); auto saved=disk["settings"];failSave=true;admin.StartCommand(&mode,{"mission","start","set","prison"},replies);assert(settings.Get("startMode")==1&&disk["settings"]==saved&&mode.StartMode()==0);failSave=false; for(string bad:{"random","random-day","2","-1","0.5","crashjunk"}){admin.StartCommand(&mode,{"mission","start","set",bad},replies);assert(settings.Get("startMode")==1&&disk["settings"]==saved);} admin.StartCommand(&mode,{"mission","start","set","prison","extra"},replies);assert(settings.Get("startMode")==1); Replication::server=false;admin.StartCommand(&mode,{"mission","start","set","prison"},replies);assert(settings.Get("startMode")==1);Replication::server=true; settings.m_ReadOnly=true;admin.StartCommand(&mode,{"mission","start","set","prison"},replies);assert(settings.Get("startMode")==1);settings.m_ReadOnly=false; admin.StartCommand(&mode,{"mission","start","set","0"},replies);assert(settings.Get("startMode")==0&&mode.StartMode()==0); admin.StartCommand(&next,{"mission","start","show"},replies);assert(replies.back()=="Next start: Crash | Current round: Crash"); } ''') assert 'm_Values.Set("startMode", AddedDefault("startMode"));' in S.read_text() execute=body(A,'void Execute(');assert execute.index('if (!authorized)')