const cm = (o) => ({ ...BLANK_MEMBER(), ...o });
const RIFLE_BILLETS = [
['PL','Platoon Leader (O-1/2)'], ['PSG','Platoon Sergeant (E-7)'], ['RTO','Radio Operator'], ['68W','Platoon Medic'], ['FO','Forward Observer (13F)'],
...[1,2,3].flatMap(n => [[`SL`,`${n}${n===1?'st':n===2?'nd':'rd'} Squad Leader`], ['TL','Alpha Team Leader'], ['GRN','Grenadier'], ['AR','Automatic Rifleman'], ['RFL','Rifleman'], ['TL','Bravo Team Leader'], ['GRN','Grenadier'], ['AR','Automatic Rifleman'], ['RFL','Rifleman']]),
['WSL','Weapons Squad Leader'], ['MG','Gunner (M240)'], ['AG','Assistant Gunner'], ['AB','Ammo Bearer'], ['MG','Gunner (M240)'], ['AG','Assistant Gunner'], ['AB','Ammo Bearer'],
];
const RIFLE_SQUADS = [
{ name: 'Platoon HQ', slots: [0,1,2,3,4] }, { name: '1st Squad · A / B teams', slots: [5,6,7,8,9,10,11,12,13] }, { name: '2nd Squad · A / B teams', slots: [14,15,16,17,18,19,20,21,22] },
{ name: '3rd Squad · A / B teams', slots: [23,24,25,26,27,28,29,30,31] }, { name: 'Weapons Squad · 2 × M240', slots: [32,33,34,35,36,37,38] },
];
const HQ_BILLETS = [
['CO','Company Commander (O-3)'], ['XO','Executive Officer (O-2)'], ['1SG','First Sergeant (E-8)'], ['RTO','Cdr RTO'], ['RTO','1SG RTO'], ['SUP','Supply Sergeant'], ['CBRN','CBRN NCO'], ['ARM','Armorer'],
['FSO','Fire Support Officer (13A)'], ['FSN','Fire Support NCO'], ['RTO','FIST RTO'],
['SRM','Senior Medic (68W)'], ['68W','Company Medic'], ['68W','Company Medic'],
];
const HQ_SQUADS = [{ name: 'Command Group', slots: [0,1,2,3,4,5,6,7] }, { name: 'Fire Support Team', slots: [8,9,10] }, { name: 'Medical · CCP', slots: [11,12,13] }];
const WPN_BILLETS = [
['PL','Weapons Plt Leader'], ['PSG','Weapons Plt Sergeant'], ['RTO','Radio Operator'], ['68W','Platoon Medic'],
['SEC','Mortar Section Leader'], ['SL','Mortar Squad Leader'], ['GNR','Gunner (60 mm)'], ['AG','Assistant Gunner'], ['AB','Ammo Bearer'], ['SL','Mortar Squad Leader'], ['GNR','Gunner (60 mm)'], ['AG','Assistant Gunner'], ['AB','Ammo Bearer'],
['SEC','Anti-Armor Section Leader'], ['TL','Javelin Team Leader'], ['GNR','Javelin Gunner'], ['AB','Ammo Bearer'], ['TL','Javelin Team Leader'], ['GNR','Javelin Gunner'], ['AB','Ammo Bearer'], ['TL','Javelin Team Leader'], ['GNR','Javelin Gunner'], ['AB','Ammo Bearer'],
];
const WPN_SQUADS = [{ name: 'Platoon HQ', slots: [0,1,2,3] }, { name: 'Mortar Section · 2 × 60 mm', slots: [4,5,6,7,8,9,10,11,12] }, { name: 'Anti-Armor Section · 3 × Javelin', slots: [13,14,15,16,17,18,19,20,21,22] }];
const SUR = ['CARRINGTON','MALDONADO','PIKE','OSEI','BRANDT','HOLLIS','NAVARRO','TREMBLAY','WASHINGTON','GUTIERREZ','FENN','ODUYA','KELLERMAN','SZABO','REDFEATHER','LARKIN','MBATHA','DOMINGUEZ','COLE','YOUNGBLOOD','PATEL','SORENSEN','BAKER','VILLARREAL','ABARA','LINDGREN','HAWKINS','MORENO','DUFRESNE','KIM','BELLAMY','OYELOWO','STRICKLAND','RAMIREZ','FOSTER','NDIAYE','HALVERSON','CRUZ','WEBB','ACOSTA','BRENNAN','CHAVEZ','DECKER','ELLISON','FARRELL','GALLO','HARDIN','IBARRA','JENSEN','KOWALCZYK','LOPEZ','MERRITT','NOLAN','ORTEGA','PRUITT','QUINN','ROWE','SALAZAR','TANNER','UPTON','VANCE','WHITAKER','XIONG','YATES','ZIMMERMAN','ADEBAYO','BOOKER','CASTRO','DONNELLY','ESCOBAR','FLYNN','GRIMES','HUANG','IRWIN','JIMENEZ','KEATING','LUCERO','MCBRIDE','NAKANO','OKAFOR','PEREIRA','RANDALL','SCHULTZ','THORNE','UNDERWOOD','VELEZ','WOLFE','YOUNG','ZAVALA','AHMED','BARNES','COPELAND','DIAZ','EMERSON','FRANKLIN','GOMEZ','HENDRIX','INGRAM','JORDAN','KNIGHT','LAWSON','MENDOZA','NEWTON','OCHOA','PARKER','REYES','SANTOS','TORRES','VARGAS','WATSON'];
const INI = 'JRTKMDSALCEBNPWGHV';
const BT = ['O+','O+','O+','A+','A+','B+','O-','A-','AB+','B-','O+','A+','AB-'];
const nameAt = (seed) => [`${SUR[seed % SUR.length]}, ${INI[(seed * 7) % INI.length]}.`, String(1000 + (seed * 2653) % 9000), BT[(seed * 5) % BT.length], 74 + (seed * 13) % 24];
const mk = (prefix, unit, billets, squads, seed0, over = {}) => billets.map(([role, title], i) => { const n = nameAt(seed0 + i); return cm({ id: `${prefix}${String(i + 1).padStart(2, '0')}`, role, title, name: n[0], last4: n[1], bloodType: n[2], weight: n[3], pos: i + 1, unit, squad: squads.findIndex(s => s.slots.includes(i)), ...(over[i] || {}) }); });
const GSW = (tqTime, notes) => ({ evac:'urgent', triage:'immediate', mechanism:['GSW'], injuries:[{view:'front',x:78,y:295,type:'gsw'},{view:'front',x:130,y:200,type:'gsw'}],
tourniquets:{ ...EMPTY_TQ(), rLeg:{active:true,type:'CAT',time:tqTime,position:'Proximal'} },
vitals:[{time:'1408',hr:'134',sbp:'86',dbp:'54',rr:'26',spo2:'92',pain:'9'},{time:'1416',hr:'122',sbp:'94',dbp:'60',rr:'22',spo2:'95',pain:'6'},{time:'1424',hr:'112',sbp:'100',dbp:'66',rr:'18',spo2:'97',pain:'4'}], draftVitals:{hr:'112',sbp:'100',dbp:'66',rr:'18',spo2:'97',pain:'4'}, avpu:'V',
interventions:['M:Tourniquet applied','M:Wound packed (hemostatic)','M:TXA 2g IV/IO','C:IV 18g established','C:Whole blood started','H:HPMK applied','P:Ketamine IV/IO 20–30 mg','A2:Ertapenem 1 g IV/IM'],
medsGiven:[{id:1,time:'1413',name:'TXA',dose:'2 g IV'},{id:2,time:'1419',name:'Ketamine IV',dose:'30 mg'}], fluidsGiven:[{id:1,time:'1418',type:'Whole Blood',vol:'500'}], pain:{rung:'severe'}, abx:{erta:true}, ammo:'red', injuryTime:'1410', notes });
const BLAST = (notes) => ({ evac:'priority', triage:'delayed', mechanism:['IED','Blast','Burn'], injuries:[{view:'front',x:100,y:180,type:'shrap'},{view:'back',x:60,y:380,type:'frac'}], burnedRegions:['f-rArm','f-chest'],
vitals:[{time:'1411',hr:'116',sbp:'118',dbp:'76',rr:'24',spo2:'95',pain:'8'},{time:'1425',hr:'104',sbp:'122',dbp:'78',rr:'20',spo2:'96',pain:'5'}], draftVitals:{hr:'104',sbp:'122',dbp:'78',rr:'20',spo2:'96',pain:'5'},
interventions:['R:SpO₂ monitored','C:IV 18g established','H:Remove wet / burned clothing','H:HPMK applied','W:Burns covered dry sterile','S:SAM splint applied','P:Fentanyl OTFC 800 mcg'],
medsGiven:[{id:1,time:'1414',name:'Fentanyl OTFC',dose:'800 mcg'}], fluidsGiven:[{id:1,time:'1420',type:'LR',vol:'500'}], burn:{ formula:'parkland', burnTime:'1406', inhal:false, circ:false, uop:[], care:['Stop','Assess','Wounds','Hypothermia'] }, pain:{rung:'moderate'}, equip:'amber', injuryTime:'1406', notes });
const TBI = (notes) => ({ evac:'routine', triage:'minimal', mechanism:['Blast'], vitals:[{time:'1420',hr:'92',sbp:'132',dbp:'84',rr:'16',spo2:'98',pain:'4'}], draftVitals:{hr:'92',sbp:'132',dbp:'84',rr:'16',spo2:'98',pain:'4'}, tbi:{ aoc:true, headache:true }, interventions:['H:TBI screen (MACE 2)','P:Acetaminophen 1 g PO + Meloxicam 15 mg PO'], pain:{rung:'mild'}, injuryTime:'1409', notes });
const FX = (notes) => ({ evac:'routine', triage:'minimal', mechanism:['Fall'], injuries:[{view:'back',x:135,y:150,type:'frac'}], interventions:['S:SAM splint applied','S:Distal CSM checked','P:Acetaminophen 1 g PO + Meloxicam 15 mg PO'], pain:{rung:'mild'}, vitals:[{time:'1330',hr:'88',sbp:'126',dbp:'80',rr:'14',spo2:'99',pain:'5'}], draftVitals:{hr:'88',sbp:'126',dbp:'80',rr:'14',spo2:'99',pain:'5'}, injuryTime:'1328', notes });
const HEAT = (notes) => ({ evac:'priority', triage:'delayed', mechanism:['Other'], avpu:'V', vitals:[{time:'1350',hr:'128',sbp:'98',dbp:'62',rr:'24',spo2:'97',pain:'2'},{time:'1405',hr:'118',sbp:'104',dbp:'66',rr:'22',spo2:'98',pain:'2'}], draftVitals:{hr:'118',sbp:'104',dbp:'66',rr:'22',spo2:'98',pain:'2'}, interventions:['C:IV 18g established','H:Core temp monitored','D:Vitals q15 min'], fluidsGiven:[{id:1,time:'1352',type:'LR',vol:'1000'}], injuryTime:'1348', notes });
const CO_HQ = mk('H', 'HQ/B/1-502 IN', HQ_BILLETS, HQ_SQUADS, 200, { 6: { ammo:'amber' } });
const P1 = mk('1', '1/B/1-502 IN', RIFLE_BILLETS, RIFLE_SQUADS, 0, { 9: GSW('1412', '1410: Contact from tree line, GSW R thigh + L flank. CAT high R thigh, L flank packed. TXA 2 g, FWB. CCP bldg 4.'), 17: BLAST('1408: Pressure-plate IED, dismounted. Flash burns R arm / ant chest, frag L abdomen, closed L lower-leg fx.'), 4: TBI('1409: ~5 m from IED, dazed, no LOC. HA 4/10.'), 36: FX('1328: Fell off wall with the 240 tripod, R shoulder — probable clavicle fx.'), 12: { ammo:'amber' }, 30: { ammo:'red' } });
const P2 = mk('2', '2/B/1-502 IN', RIFLE_BILLETS, RIFLE_SQUADS, 50, { 26: HEAT('1348: Heat casualty on the move, confused, tachycardic. Shade, cooled, 1 L LR. Improving.'), 20: { ammo:'amber' } });
const P3 = mk('3', '3/B/1-502 IN', RIFLE_BILLETS, RIFLE_SQUADS, 100, { 7: GSW('1355', '1352: GSW R thigh during clearance of OBJ LION. CAT applied, TXA given. Awaiting MEDEVAC at HLZ SPARROW.'), 33: TBI('1356: RPG impact 8 m away, dazed 30 s, HA. Pulled off the gun.'), 15: { equip:'amber' }, 38: { ammo:'amber' } });
const WP = mk('W', 'WPN/B/1-502 IN', WPN_BILLETS, WPN_SQUADS, 160, { 8: FX('1340: Ankle inversion carrying mortar rounds — splinted, ambulatory with assist.'), 6: { ammo:'amber' }, 16: { ammo:'red' } });
const CO_ALL = [CO_HQ, P1, P2, P3, WP].reduce((n, t) => n + t.length, 0);
window.UNIT_PROFILE = {
key: 'tccc360-co-v1',
brand: <><b>TCCC</b> · INFANTRY COMPANY VIEW · 360</>,
appClass: 'inf company',
unitShort: 'PLT', paxLabel: `RIFLE CO · ${CO_ALL} PAX`, boardTitle: 'INFANTRY COMPANY STATUS BOARD',
leaderLbl: '1SG', medicLbl: 'SR MEDIC', leader: '1SG D. MALDONADO', medic: 'SSG K. OSEI', opName: 'IRON RESOLVE',
pax: CO_ALL, squads: RIFLE_SQUADS, billets: RIFLE_BILLETS, blankUnit: '',
blankTitle: 'Blank rifle platoon (39)', blankDesc: 'Clears the ACTIVE platoon to an empty, fillable roster — HQ, three rifle squads with A/B teams, weapons squad. Other platoons are untouched.',
blankConfirm: 'Start a blank platoon here? All names, blood types and casualty data in the active platoon will be cleared.',
resetConfirm: 'Reset the whole company to the sample rosters?',
teamName: 'B CO 1-502 IN', teamLabel: 'CO',
platoons: [
{ id: 'HQ', name: 'CO HQ', team: CO_HQ, squads: HQ_SQUADS, billets: HQ_BILLETS },
{ id: 'P1', name: '1ST PLT', team: P1 }, { id: 'P2', name: '2ND PLT', team: P2 }, { id: 'P3', name: '3RD PLT', team: P3 },
{ id: 'WP', name: 'WPNS PLT', team: WP, squads: WPN_SQUADS, billets: WPN_BILLETS },
],
defaultPlatoon: 'P1', defaultSelected: '110',
settingsDefaults: { compactStrip: true },
companyView: true,
migrate: null,
};