Files
EscapistsReintroduced/tests/test_convoy_auto_settings.py
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

65 lines
4.6 KiB
Python

"""Actual settings read/default/bounds for next-round automatic convoy startup."""
import os,re
from pathlib import Path
from policy_harness import ROOT,body,run
BASE=Path(os.environ.get('ERR_CONVOY_SETTINGS_ROOT',ROOT))
P=BASE/'addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c'
keys=body(P,'static array<string> Keys(').replace('array<string>','std::vector<string>')
valid='\n'.join(body(P,sig) for sig in ('static bool Valid(', 'static bool Randomizable(', 'static bool ValidSelection('))
default=body(P,'static int AddedDefault(')
read=(body(P,'protected bool Read(')+'\n'+body(P,'static bool Parse(')).replace('protected ','').replace('out map<string, int> values','Map*& values').replace('new map<string, int>()','new Map()')
read=read.replace('JsonLoadContext json','JsonLoadContext* json').replace('json.','json->').replace('values.','values->').replace('foreach (string key : Keys())','for (string key : Keys())').replace('Math.Round','std::round').replace('ERR_ProfileConfig.Load(path, json)', 'json->LoadFromFile(path)')
run(r'''
#include <cassert>
#include <string>
#include <map>
#include <vector>
#include <cmath>
using string=std::string;
struct Map{std::map<string,int> values;void Set(string k,int v){values[k]=v;}int Get(string k){return values[k];}};
std::map<string,std::map<string,float>> files;
struct JsonLoadContext{std::map<string,float>* data=nullptr;
bool LoadFromFile(string path){if(!files.count(path))return false;data=&files[path];return true;}
bool DoesKeyExist(string key){return data->count(key);}
bool ReadValue(string key,float& value){if(!DoesKeyExist(key))return false;value=(*data)[key];return true;}};
struct Settings{
'''+keys+valid+default+read+r'''
};
int main(){
assert(Settings::AddedDefault("automaticConvoyEnabled")==1);
assert(Settings::Valid("automaticConvoyEnabled",0)&&Settings::Valid("automaticConvoyEnabled",1));
assert(!Settings::Valid("automaticConvoyEnabled",-1)&&!Settings::Valid("automaticConvoyEnabled",2));
assert(Settings::AddedDefault("reportIntervalSeconds")==-1);
files["old"]={{"reportIntervalSeconds",10},{"supportSquadLimit",4},{"responseRadiusMetres",2000},
{"aiIntelChancePercent",60},{"intelRevealChancePercent",15},{"radioDefenceSeconds",180}};
Settings s;Map* loaded=nullptr;assert(s.Read("old",loaded)&&loaded->Get("automaticConvoyEnabled")==1);
assert(loaded->Get("reportIntervalSeconds")==10&&loaded->Get("antiAirChancePercent")==7);
files["disabled"]=files["old"];files["disabled"]["automaticConvoyEnabled"]=0;
assert(s.Read("disabled",loaded)&&loaded->Get("automaticConvoyEnabled")==0);
files["enabled"]=files["old"];files["enabled"]["automaticConvoyEnabled"]=1;
assert(s.Read("enabled",loaded)&&loaded->Get("automaticConvoyEnabled")==1);
for(float bad:{-1.0f,2.0f,0.5f}){files["invalid"]=files["old"];files["invalid"]["automaticConvoyEnabled"]=bad;assert(!s.Read("invalid",loaded));}
files["incomplete"]=files["old"];files["incomplete"].erase("reportIntervalSeconds");assert(!s.Read("incomplete",loaded));
for(auto pair:std::map<int,int>{{0,0},{1,100},{15,7},{37,3},{10000,0}}){
files["legacy"]=files["old"];files["legacy"]["stingerChanceOneIn"]=pair.first;
assert(s.Read("legacy",loaded)&&loaded->Get("antiAirChancePercent")==pair.second);
}
for(float bad:{-1.0f,10001.0f,0.5f}){files["legacy"]=files["old"];files["legacy"]["stingerChanceOneIn"]=bad;assert(!s.Read("legacy",loaded));}
files["new"]=files["old"];files["new"]["stingerChanceOneIn"]=15;files["new"]["antiAirChancePercent"]=100;
assert(s.Read("new",loaded)&&loaded->Get("antiAirChancePercent")==100&&loaded->Get("antiPersonnelMineChancePercent")==60);
assert(!s.Read("missing",loaded));
}
''')
assert 'm_Values.Set("automaticConvoyEnabled", AddedDefault("automaticConvoyEnabled"));' in P.read_text()
admin=body(BASE/'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c','void Execute(')
assert 'if (key == "automaticConvoyEnabled") line += " (saved for next round; current startup unchanged)";' in admin
provider=BASE/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c'
helper=body(provider,'protected void ConvoyAutoSetting(')
for forbidden in ('StartConvoy','StartScenarioConvoy','Spawn','m_HQ.'):
assert forbidden not in helper
# Do not advertise this command-only setting as an editable field absent from the actual fixed menu.
menu=body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c','static array<string> Keys(')
assert 'automaticConvoyEnabled' not in menu
assert body(provider,'override bool Help(').count('replies.Insert(')<=5
print('PASS: actual read migrates old valid settings, preserves explicit disabled state, rejects invalid data; next-round feedback and fixed menu remain honest')