diff --git a/vasl_templates/tools/make_chapter_h_placeholders.py b/vasl_templates/tools/make_chapter_h_placeholders.py
index 789cccd..429399f 100755
--- a/vasl_templates/tools/make_chapter_h_placeholders.py
+++ b/vasl_templates/tools/make_chapter_h_placeholders.py
@@ -59,7 +59,7 @@ def make_chapter_h_placeholders( output_fname, log=None \
nat = os.path.splitext( fname2 )[0]
if nat == "common":
nat = os.path.split( dname2 )[1]
- if nat in ("british-commonwealth-forces-korea","cvpa","kpa","us-rok-ounc","un-forces"):
+ if nat in ("free-french","british-commonwealth-forces-korea","cvpa","kpa","us-rok-ounc","un-forces"):
continue
notes, ma_notes = load_vo_data( fname, nat )
if nat not in results:
diff --git a/vasl_templates/webapp/data/default-template-pack/nationalities.json b/vasl_templates/webapp/data/default-template-pack/nationalities.json
index d2ed6ff..d49025a 100644
--- a/vasl_templates/webapp/data/default-template-pack/nationalities.json
+++ b/vasl_templates/webapp/data/default-template-pack/nationalities.json
@@ -24,6 +24,10 @@
"display_name": "French",
"ob_colors": [ "#a2ddff","#41a5ff", "#41a5ff" ]
},
+"free-french": {
+ "display_name": "Free French",
+ "ob_colors": [ "#a2ddff","#41a5ff", "#41a5ff" ]
+},
"italian": {
"display_name": "Italian",
diff --git a/vasl_templates/webapp/data/ordnance/free-french.json b/vasl_templates/webapp/data/ordnance/free-french.json
new file mode 100644
index 0000000..c4c807c
--- /dev/null
+++ b/vasl_templates/webapp/data/ordnance/free-french.json
@@ -0,0 +1,107 @@
+[
+
+{ "id": "ff/o:000",
+ "copy_from": "fr/o:000"
+},
+{ "id": "ff/o:001",
+ "copy_from": "br/o:000",
+ "note_number": "Fr 22\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/o:002",
+ "copy_from": "fr/o:001",
+ "name": "Mortier de 60 mle 35(f)"
+},
+{ "id": "ff/o:003",
+ "copy_from": "am/o:000",
+ "note_number": "Fr 22",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/o:004",
+ "copy_from": "br/o:002",
+ "note_number": "Fr 22\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/o:005",
+ "copy_from": "fr/o:002",
+ "name": "Mortier de 81 mle 27/31(f)"
+},
+{ "id": "ff/o:006",
+ "copy_from": "am/o:002",
+ "note_number": "Fr 22",
+ "notes": [ "Fr D", "Fr Y\u2020" ]
+},
+{ "id": "ff/o:007",
+ "copy_from": "fr/o:003",
+ "name": "Boys ATR"
+},
+{ "id": "ff/o:008",
+ "copy_from": "br/o:004",
+ "note_number": "Fr 23\u20201",
+ "notes": [ "Fr V", "Fr W\u2020" ]
+},
+{ "id": "ff/o:009",
+ "copy_from": "fr/o:005",
+ "name": "Canon AC de 47 SA 37 APX(f)"
+},
+{ "id": "ff/o:010",
+ "copy_from": "br/o:006",
+ "note_number": "Fr 24",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/o:011",
+ "copy_from": "am/o:006",
+ "note_number": "Fr 24",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/o:012",
+ "copy_from": "br/o:010",
+ "note_number": "Fr 25\u20201",
+ "notes": [ "Fr V", "Fr W\u2020" ]
+},
+{ "id": "ff/o:013",
+ "copy_from": "br/o:013",
+ "note_number": "Fr 26\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/o:014",
+ "copy_from": "am/o:013",
+ "note_number": "Fr 27",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/o:015",
+ "copy_from": "am/o:014",
+ "note_number": "Fr 27",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/o:016",
+ "copy_from": "br/o:017",
+ "note_number": "Fr 28\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/o:017",
+ "copy_from": "am/o:017",
+ "note_number": "Fr 29",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/o:018",
+ "copy_from": "am/o:018",
+ "note_number": "Fr 29",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/o:019",
+ "copy_from": "fr/o:017",
+ "name": "Mitrailleuse de 13.2 CAJ"
+},
+{ "id": "ff/o:020",
+ "copy_from": "br/o:022",
+ "note_number": "Fr 30",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/o:021",
+ "copy_from": "am/o:023",
+ "note_number": "Fr 30",
+ "notes": [ "Fr Y\u2020" ]
+}
+
+]
diff --git a/vasl_templates/webapp/data/vehicles/free-french.json b/vasl_templates/webapp/data/vehicles/free-french.json
new file mode 100644
index 0000000..e1801df
--- /dev/null
+++ b/vasl_templates/webapp/data/vehicles/free-french.json
@@ -0,0 +1,258 @@
+[
+
+{ "id": "ff/v:000",
+ "name": "H39(f)",
+ "copy_from": "fr/v:009"
+},
+{ "id": "ff/v:002",
+ "copy_from": "am/v:004",
+ "note_number": "Fr 37\u20201",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:003",
+ "copy_from": "fr/v:010",
+ "name": "H39(L)(f)"
+},
+{ "id": "ff/v:004",
+ "copy_from": "fr/v:012",
+ "name": "R35(L)(f)"
+},
+{ "id": "ff/v:005",
+ "copy_from": "br/v:017",
+ "note_number": "Fr 38",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:006",
+ "copy_from": "br/v:019",
+ "note_number": "Fr 38",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:007",
+ "copy_from": "am/v:007",
+ "note_number": "Fr 39",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:008",
+ "copy_from": "am/v:008",
+ "note_number": "Fr 39\u2020",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:009",
+ "copy_from": "am/v:009",
+ "note_number": "Fr 39\u20201",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:010",
+ "copy_from": "am/v:012",
+ "note_number": "Fr 40",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:011",
+ "copy_from": "am/v:016",
+ "note_number": "Fr 40",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:012",
+ "copy_from": "am/v:018",
+ "note_number": "Fr 40",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:013",
+ "copy_from": "am/v:019",
+ "note_number": "Fr 40",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:014",
+ "copy_from": "fr/v:017",
+ "name": "S35(f)"
+},
+{ "id": "ff/v:015",
+ "copy_from": "fr/v:018",
+ "name": "B1-bis(f)"
+},
+{ "id": "ff/v:016",
+ "copy_from": "am/v:024",
+ "note_number": "Fr 41",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:017",
+ "copy_from": "br/v:059",
+ "note_number": "Fr 42\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:018",
+ "copy_from": "fr/v:020"
+},
+{ "id": "ff/v:019",
+ "copy_from": "am/v:041",
+ "note_number": "Fr 43\u20201",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:020",
+ "copy_from": "am/v:042",
+ "note_number": "Fr 43\u20201",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:021",
+ "copy_from": "br/v:070",
+ "note_number": "Fr 44",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:022",
+ "copy_from": "br/v:071",
+ "note_number": "Fr 44",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:023",
+ "copy_from": "br/v:072",
+ "note_number": "Fr 45",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:024",
+ "copy_from": "am/v:044",
+ "note_number": "Fr 43",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:025",
+ "copy_from": "am/v:045",
+ "note_number": "Fr 46",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:026",
+ "copy_from": "am/v:046",
+ "note_number": "Fr 46",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:027",
+ "copy_from": "am/v:037",
+ "note_number": "Fr 47",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:028",
+ "copy_from": "am/v:028",
+ "note_number": "Fr 47",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:029",
+ "copy_from": "am/v:029",
+ "note_number": "Fr 47",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:030",
+ "copy_from": "br/v:090",
+ "name": "M5",
+ "note_number": "Fr 47\u2020",
+ "notes": [ "Fr U" ],
+ "gpid": [ 1895 ]
+},
+{ "id": "ff/v:031",
+ "copy_from": "br/v:092",
+ "name": "M5A1",
+ "note_number": "Fr 47\u2020",
+ "notes": [ "Fr U" ],
+ "gpid": [ 1897 ]
+},
+{ "id": "ff/v:032",
+ "copy_from": "br/v:091",
+ "name": "M9",
+ "note_number": "Fr 47\u2020",
+ "notes": [ "Fr U" ],
+ "gpid": [ 1903 ]
+},
+{ "id": "ff/v:036",
+ "copy_from": "br/v:094",
+ "note_number": "Fr 48\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:037",
+ "copy_from": "br/v:095",
+ "note_number": "Fr 48\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:038",
+ "copy_from": "br/v:096",
+ "note_number": "Fr 48\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:039",
+ "copy_from": "br/v:097",
+ "note_number": "Fr 48\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:040",
+ "copy_from": "fr/v:042"
+},
+{ "id": "ff/v:041",
+ "copy_from": "fr/v:031",
+ "name": "Ac de 25 CA(f)"
+},
+{ "id": "ff/v:042",
+ "copy_from": "fr/v:026"
+},
+{ "id": "ff/v:043",
+ "copy_from": "fr/v:032"
+},
+{ "id": "ff/v:044",
+ "copy_from": "fr/v:033",
+ "name": "Ac de 75 mle 13/34(f)"
+},
+{ "id": "ff/v:045",
+ "copy_from": "br/v:118",
+ "note_number": "Fr 49",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:046",
+ "copy_from": "br/v:122",
+ "name": "Jeep(a)",
+ "note_number": "Fr 50\u20201",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:047",
+ "copy_from": "br/v:119",
+ "note_number": "Fr 50",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:048",
+ "copy_from": "br/v:120",
+ "note_number": "Fr 50",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:049",
+ "copy_from": "br/v:121",
+ "note_number": "Fr 50",
+ "notes": [ "Fr W\u2020" ]
+},
+{ "id": "ff/v:050",
+ "copy_from": "am/v:058",
+ "name": "Jeep",
+ "note_number": "Fr 51",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:051",
+ "copy_from": "am/v:057",
+ "name": "Jeep GPA",
+ "note_number": "Fr 51",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:052",
+ "copy_from": "am/v:059",
+ "note_number": "Fr 51",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:053",
+ "copy_from": "am/v:060",
+ "note_number": "Fr 51",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:054",
+ "copy_from": "am/v:061",
+ "note_number": "Fr 51",
+ "notes": [ "Fr Y\u2020" ]
+},
+{ "id": "ff/v:055",
+ "copy_from": "am/v:062",
+ "note_number": "Fr 51",
+ "notes": [ "Fr Y\u2020" ]
+}
+
+]
diff --git a/vasl_templates/webapp/data/vehicles/russian.lend-lease.json b/vasl_templates/webapp/data/vehicles/russian.lend-lease.json
index 958b36a..3e7f0ac 100644
--- a/vasl_templates/webapp/data/vehicles/russian.lend-lease.json
+++ b/vasl_templates/webapp/data/vehicles/russian.lend-lease.json
@@ -138,27 +138,27 @@
},
{ "id": "ru/v:094",
"copy_from": "br/v:123",
- "note_number": "Br 85",
+ "note_number": null,
"extra_notes": [ "LL" ]
},
{ "id": "ru/v:095",
"copy_from": "br/v:124",
- "note_number": "Br 85",
+ "note_number": null,
"extra_notes": [ "LL" ]
},
{ "id": "ru/v:096",
"copy_from": "br/v:125",
- "note_number": "Br 85",
+ "note_number": null,
"extra_notes": [ "LL" ]
},
{ "id": "ru/v:097",
"copy_from": "br/v:126",
- "note_number": "Br 85",
+ "note_number": null,
"extra_notes": [ "LL" ]
},
{ "id": "ru/v:084",
"copy_from": "am/v:056",
- "note_number": "US 52\u2020",
+ "note_number": null,
"extra_notes": [ "LL" ],
"gpid": 7120
}
diff --git a/vasl_templates/webapp/static/images/flags/free-french.png b/vasl_templates/webapp/static/images/flags/free-french.png
new file mode 100644
index 0000000..72e5b67
Binary files /dev/null and b/vasl_templates/webapp/static/images/flags/free-french.png differ
diff --git a/vasl_templates/webapp/static/main.js b/vasl_templates/webapp/static/main.js
index 368efef..6dda418 100644
--- a/vasl_templates/webapp/static/main.js
+++ b/vasl_templates/webapp/static/main.js
@@ -657,7 +657,8 @@ function on_player_change( player_no )
// show/hide the vehicle/ordnance multi-applicable notes controls
function update_ma_notes_controls( vo_type ) {
var show = ( gVehicleOrdnanceNotes[vo_type] && gVehicleOrdnanceNotes[vo_type][player_nat] ) ||
- ["allied-minor","axis-minor"].indexOf( gTemplatePack.nationalities[ player_nat ].type ) !== -1 ;
+ ["allied-minor","axis-minor"].indexOf( gTemplatePack.nationalities[ player_nat ].type ) !== -1 ||
+ player_nat === "free-french" ;
var $fieldset = $( "#tabs-ob" + player_no + " fieldset[name='ob_" + vo_type + "_" + player_no ) ;
$fieldset.find( ".snippets-notes" ).css( "display", show?"block":"none" ) ;
$fieldset.find( "label[for='ob']" ).css( "display", show?"inline-block":"none" ) ;
diff --git a/vasl_templates/webapp/static/snippets.js b/vasl_templates/webapp/static/snippets.js
index 178e8a2..422c483 100644
--- a/vasl_templates/webapp/static/snippets.js
+++ b/vasl_templates/webapp/static/snippets.js
@@ -392,7 +392,7 @@ function get_vo_note_key( vo_entry )
if ( ! vo_entry.note_number )
return null ;
// NOTE: There are some note numbers of the form "1.2" :-/ We also need to handle redirects.
- var match = vo_entry.note_number.match( new RegExp( "^((Br|US) )?([0-9]+(.\\d)?)" ) ) ;
+ var match = vo_entry.note_number.match( new RegExp( "^((Br|US|Fr) )?([0-9]+(.\\d)?)" ) ) ;
if ( ! match )
return null ;
var key = match[0] ;
@@ -407,7 +407,7 @@ function make_vo_note_key_url( vo_type, nat, key )
return null ;
// check for redirects
- var match = key.match( /^(Br|US) (.+)$/ ) ;
+ var match = key.match( /^(Br|US|Fr) (.+)$/ ) ;
if ( match ) {
nat = MA_NOTE_REDIRECTS[ match[1] ] ;
key = match[2] ;
diff --git a/vasl_templates/webapp/templates/vo-report.html b/vasl_templates/webapp/templates/vo-report.html
index d1ef484..7d3ffe1 100644
--- a/vasl_templates/webapp/templates/vo-report.html
+++ b/vasl_templates/webapp/templates/vo-report.html
@@ -71,7 +71,8 @@ function load_vo_listings( objs )
buf.push( "
", listval(capabilities) ) ;
var capabilities = make_capabilities( false, obj, nat, false, theater, year, month, true ) ;
buf.push( " | ", listval(capabilities) ) ;
- buf.push( " | ", "" + fmtval(obj.note_number) + "" ) ;
+ var note_number = obj.note_number ? "" + fmtval(obj.note_number) + "" : fmtval("") ;
+ buf.push( " | ", note_number ) ;
buf.push( " | ", listval(obj.notes) ) ;
buf.push( " | ", obj.comments ? listval(obj.comments) : "" ) ;
}
diff --git a/vasl_templates/webapp/tests/fixtures/vasl-pieces.txt b/vasl_templates/webapp/tests/fixtures/vasl-pieces.txt
index 42c6af9..8619685 100644
--- a/vasl_templates/webapp/tests/fixtures/vasl-pieces.txt
+++ b/vasl_templates/webapp/tests/fixtures/vasl-pieces.txt
@@ -497,6 +497,9 @@
1836 Peugeot 202 fr/veh/peugeot
1837 Citroen 23 fr/veh/citroen
1839 Renault AGR2 fr/veh/renagr
+ 1895 M5 ht fr/veh/m5
+ 1897 M5A1 ht fr/veh/m5a1
+ 1903 M9 ht fr/veh/m9
1982 40 MTR ch/chM40 ch/chM40b
1983 45* MTR(i) <41 ch/chM45 ch/chM45b
1984 45* MTR(i) ch/chM452 ch/chM45b
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1940.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1940.txt
new file mode 100644
index 0000000..854b384
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1940.txt
@@ -0,0 +1,26 @@
+=== ordnance/free-french/1940 ===
+
+Name Capabilities (effective) # Notes Comments
+--------------------------- ------------------------------ ------------------ --------- -------------------- ----------------------
+LG de 50 mle 37(f) 2PP 2PP Fr 1 Fr A Fr B Fr C† Fr E crewed†
+OML 2-in. Mortar 4PP IR[2+]† s7 4PP s7 Fr 22†[1] Fr W†
+Mortier de 60 mle 35(f) 5PP no OBA† IR[2+]† 5PP no OBA† Fr 2† Fr A Fr B Fr V
+M2 60mm Mortar IR WP7[5] 5PP OBA† IR 5PP OBA† Fr 22 Fr W†
+OML 3-in. Mortar QSU IR[2+]†[1] WP7 s8[1+]† QSU WP7 Fr 22†[1] Fr W†
+Mortier de 81 mle 27/31(f) QSU s8 QSU s8 Fr 3† Fr A Fr B Fr D Fr V
+M1 81mm Mortar QSU WP8 QSU WP8 Fr 22 Fr D Fr Y†
+Boys ATR 1PP 1PP Fr 4† Fr B
+OQF 25mm Hotchkiss QSU QSU Fr 23†[1] Fr V Fr W†
+Canon AC de 47 SA 37 APX(f) QSU APCR only†[1] QSU APCR only†[1] Fr 6†[1] Fr B Fr G† Fr P Fr V
+OQF 6-Pounder 7-cwt QSU D6[J4E]7[5]† HE7[F3]8[4+]† QSU Fr 24 Fr W†
+M1 57mm AT Gun QSU D4[J4+E]† HE7[J4E]7[5]† QSU Fr 24 Fr Y†
+Canon de 75 mle 1897 QSU s8 QSU s8 Fr 25†[1] Fr V Fr W†
+OQF 25-Pounder Gun-Howitzer LF [NT, 0 ROF] s8 LF [NT, 0 ROF] s8 Fr 26†[1] Fr W†
+M2A1 105mm Howitzer C7[4+P]†[1] H6 WP8 s7 H6 WP8 s7 Fr 27 Fr Y†
+M3 105mm Howitzer C7[P]†[1] H7 WP8 s7 H7 WP8 s7 Fr 27 Fr Y†
+OBL 5.5-in. Gun-Howitzer Fr 28†[1] Fr W†
+M1 155mm Howitzer WP8 s7 WP8 s7 Fr 29 Fr Y†
+M1918M1 155mm Gun RFNM AP4†[1] WP8 RFNM AP4†[1] WP8 Fr 29 Fr Y† No IF.
+Mitrailleuse de 13.2 CAJ 2 TK DR†[1] 2 TK DR†[1] Fr 18†[1] Fr B Fr G† Fr V Towing NA†1
+OQF 40mm AA LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr W†
+M1 40mm AA Gun LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1941.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1941.txt
new file mode 100644
index 0000000..93372da
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1941.txt
@@ -0,0 +1,26 @@
+=== ordnance/free-french/1941 ===
+
+Name Capabilities (effective) # Notes Comments
+--------------------------- ------------------------------ ------------------ --------- -------------------- ----------------------
+LG de 50 mle 37(f) 2PP 2PP Fr 1 Fr A Fr B Fr C† Fr E crewed†
+OML 2-in. Mortar 4PP IR[2+]† s7 4PP s7 Fr 22†[1] Fr W†
+Mortier de 60 mle 35(f) 5PP no OBA† IR[2+]† 5PP no OBA† Fr 2† Fr A Fr B Fr V
+M2 60mm Mortar IR WP7[5] 5PP OBA† IR 5PP OBA† Fr 22 Fr W†
+OML 3-in. Mortar QSU IR[2+]†[1] WP7 s8[1+]† QSU WP7 s8† Fr 22†[1] Fr W†
+Mortier de 81 mle 27/31(f) QSU s8 QSU s8 Fr 3† Fr A Fr B Fr D Fr V
+M1 81mm Mortar QSU WP8 QSU WP8 Fr 22 Fr D Fr Y†
+Boys ATR 1PP 1PP Fr 4† Fr B
+OQF 25mm Hotchkiss QSU QSU Fr 23†[1] Fr V Fr W†
+Canon AC de 47 SA 37 APX(f) QSU APCR only†[1] QSU APCR only†[1] Fr 6†[1] Fr B Fr G† Fr P Fr V
+OQF 6-Pounder 7-cwt QSU D6[J4E]7[5]† HE7[F3]8[4+]† QSU Fr 24 Fr W†
+M1 57mm AT Gun QSU D4[J4+E]† HE7[J4E]7[5]† QSU Fr 24 Fr Y†
+Canon de 75 mle 1897 QSU s8 QSU s8 Fr 25†[1] Fr V Fr W†
+OQF 25-Pounder Gun-Howitzer LF [NT, 0 ROF] s8 LF [NT, 0 ROF] s8 Fr 26†[1] Fr W†
+M2A1 105mm Howitzer C7[4+P]†[1] H6 WP8 s7 H6 WP8 s7 Fr 27 Fr Y†
+M3 105mm Howitzer C7[P]†[1] H7 WP8 s7 H7 WP8 s7 Fr 27 Fr Y†
+OBL 5.5-in. Gun-Howitzer Fr 28†[1] Fr W†
+M1 155mm Howitzer WP8 s7 WP8 s7 Fr 29 Fr Y†
+M1918M1 155mm Gun RFNM AP4†[1] WP8 RFNM AP4†[1] WP8 Fr 29 Fr Y† No IF.
+Mitrailleuse de 13.2 CAJ 2 TK DR†[1] 2 TK DR†[1] Fr 18†[1] Fr B Fr G† Fr V Towing NA†1
+OQF 40mm AA LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr W†
+M1 40mm AA Gun LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1942.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1942.txt
new file mode 100644
index 0000000..b8c2c61
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1942.txt
@@ -0,0 +1,26 @@
+=== ordnance/free-french/1942 ===
+
+Name Capabilities (effective) # Notes Comments
+--------------------------- ------------------------------ ------------------ --------- -------------------- ----------------------
+LG de 50 mle 37(f) 2PP 2PP Fr 1 Fr A Fr B Fr C† Fr E crewed†
+OML 2-in. Mortar 4PP IR[2+]† s7 4PP IR† s7 Fr 22†[1] Fr W†
+Mortier de 60 mle 35(f) 5PP no OBA† IR[2+]† 5PP no OBA† IR† Fr 2† Fr A Fr B Fr V
+M2 60mm Mortar IR WP7[5] 5PP OBA† IR 5PP OBA† Fr 22 Fr W†
+OML 3-in. Mortar QSU IR[2+]†[1] WP7 s8[1+]† QSU IR†[1] WP7 s8† Fr 22†[1] Fr W†
+Mortier de 81 mle 27/31(f) QSU s8 QSU s8 Fr 3† Fr A Fr B Fr D Fr V
+M1 81mm Mortar QSU WP8 QSU WP8 Fr 22 Fr D Fr Y†
+Boys ATR 1PP 1PP Fr 4† Fr B
+OQF 25mm Hotchkiss QSU QSU Fr 23†[1] Fr V Fr W†
+Canon AC de 47 SA 37 APX(f) QSU APCR only†[1] QSU APCR only†[1] Fr 6†[1] Fr B Fr G† Fr P Fr V
+OQF 6-Pounder 7-cwt QSU D6[J4E]7[5]† HE7[F3]8[4+]† QSU Fr 24 Fr W†
+M1 57mm AT Gun QSU D4[J4+E]† HE7[J4E]7[5]† QSU Fr 24 Fr Y†
+Canon de 75 mle 1897 QSU s8 QSU s8 Fr 25†[1] Fr V Fr W†
+OQF 25-Pounder Gun-Howitzer LF [NT, 0 ROF] s8 LF [NT, 0 ROF] s8 Fr 26†[1] Fr W†
+M2A1 105mm Howitzer C7[4+P]†[1] H6 WP8 s7 H6 WP8 s7 Fr 27 Fr Y†
+M3 105mm Howitzer C7[P]†[1] H7 WP8 s7 H7 WP8 s7 Fr 27 Fr Y†
+OBL 5.5-in. Gun-Howitzer Fr 28†[1] Fr W†
+M1 155mm Howitzer WP8 s7 WP8 s7 Fr 29 Fr Y†
+M1918M1 155mm Gun RFNM AP4†[1] WP8 RFNM AP4†[1] WP8 Fr 29 Fr Y† No IF.
+Mitrailleuse de 13.2 CAJ 2 TK DR†[1] 2 TK DR†[1] Fr 18†[1] Fr B Fr G† Fr V Towing NA†1
+OQF 40mm AA LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr W†
+M1 40mm AA Gun LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1943.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1943.txt
new file mode 100644
index 0000000..ea6ea5f
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1943.txt
@@ -0,0 +1,26 @@
+=== ordnance/free-french/1943 ===
+
+Name Capabilities (effective) # Notes Comments
+--------------------------- ------------------------------ ------------------ --------- -------------------- ----------------------
+LG de 50 mle 37(f) 2PP 2PP Fr 1 Fr A Fr B Fr C† Fr E crewed†
+OML 2-in. Mortar 4PP IR[2+]† s7 4PP IR† s7 Fr 22†[1] Fr W†
+Mortier de 60 mle 35(f) 5PP no OBA† IR[2+]† 5PP no OBA† IR† Fr 2† Fr A Fr B Fr V
+M2 60mm Mortar IR WP7[5] 5PP OBA† IR 5PP OBA† Fr 22 Fr W†
+OML 3-in. Mortar QSU IR[2+]†[1] WP7 s8[1+]† QSU IR†[1] WP7 s8† Fr 22†[1] Fr W†
+Mortier de 81 mle 27/31(f) QSU s8 QSU s8 Fr 3† Fr A Fr B Fr D Fr V
+M1 81mm Mortar QSU WP8 QSU WP8 Fr 22 Fr D Fr Y†
+Boys ATR 1PP 1PP Fr 4† Fr B
+OQF 25mm Hotchkiss QSU QSU Fr 23†[1] Fr V Fr W†
+Canon AC de 47 SA 37 APX(f) QSU APCR only†[1] QSU APCR only†[1] Fr 6†[1] Fr B Fr G† Fr P Fr V
+OQF 6-Pounder 7-cwt QSU D6[J4E]7[5]† HE7[F3]8[4+]† QSU Fr 24 Fr W†
+M1 57mm AT Gun QSU D4[J4+E]† HE7[J4E]7[5]† QSU Fr 24 Fr Y†
+Canon de 75 mle 1897 QSU s8 QSU s8 Fr 25†[1] Fr V Fr W†
+OQF 25-Pounder Gun-Howitzer LF [NT, 0 ROF] s8 LF [NT, 0 ROF] s8 Fr 26†[1] Fr W†
+M2A1 105mm Howitzer C7[4+P]†[1] H6 WP8 s7 H6 WP8 s7 Fr 27 Fr Y†
+M3 105mm Howitzer C7[P]†[1] H7 WP8 s7 H7 WP8 s7 Fr 27 Fr Y†
+OBL 5.5-in. Gun-Howitzer Fr 28†[1] Fr W†
+M1 155mm Howitzer WP8 s7 WP8 s7 Fr 29 Fr Y†
+M1918M1 155mm Gun RFNM AP4†[1] WP8 RFNM AP4†[1] WP8 Fr 29 Fr Y† No IF.
+Mitrailleuse de 13.2 CAJ 2 TK DR†[1] 2 TK DR†[1] Fr 18†[1] Fr B Fr G† Fr V Towing NA†1
+OQF 40mm AA LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr W†
+M1 40mm AA Gun LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1944.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1944.txt
new file mode 100644
index 0000000..bf6565b
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1944.txt
@@ -0,0 +1,26 @@
+=== ordnance/free-french/1944 ===
+
+Name Capabilities (effective) # Notes Comments
+--------------------------- ------------------------------ ------------------ --------- -------------------- ----------------------
+LG de 50 mle 37(f) 2PP 2PP Fr 1 Fr A Fr B Fr C† Fr E crewed†
+OML 2-in. Mortar 4PP IR[2+]† s7 4PP IR† s7 Fr 22†[1] Fr W†
+Mortier de 60 mle 35(f) 5PP no OBA† IR[2+]† 5PP no OBA† IR† Fr 2† Fr A Fr B Fr V
+M2 60mm Mortar IR WP7[5] 5PP OBA† IR 5PP OBA† Fr 22 Fr W†
+OML 3-in. Mortar QSU IR[2+]†[1] WP7 s8[1+]† QSU IR†[1] WP7 s8† Fr 22†[1] Fr W†
+Mortier de 81 mle 27/31(f) QSU s8 QSU s8 Fr 3† Fr A Fr B Fr D Fr V
+M1 81mm Mortar QSU WP8 QSU WP8 Fr 22 Fr D Fr Y†
+Boys ATR 1PP 1PP Fr 4† Fr B
+OQF 25mm Hotchkiss QSU QSU Fr 23†[1] Fr V Fr W†
+Canon AC de 47 SA 37 APX(f) QSU APCR only†[1] QSU APCR only†[1] Fr 6†[1] Fr B Fr G† Fr P Fr V
+OQF 6-Pounder 7-cwt QSU D6[J4E]7[5]† HE7[F3]8[4+]† QSU HE8† Fr 24 Fr W†
+M1 57mm AT Gun QSU D4[J4+E]† HE7[J4E]7[5]† QSU Fr 24 Fr Y†
+Canon de 75 mle 1897 QSU s8 QSU s8 Fr 25†[1] Fr V Fr W†
+OQF 25-Pounder Gun-Howitzer LF [NT, 0 ROF] s8 LF [NT, 0 ROF] s8 Fr 26†[1] Fr W†
+M2A1 105mm Howitzer C7[4+P]†[1] H6 WP8 s7 H6 WP8 s7 Fr 27 Fr Y†
+M3 105mm Howitzer C7[P]†[1] H7 WP8 s7 H7 WP8 s7 Fr 27 Fr Y†
+OBL 5.5-in. Gun-Howitzer Fr 28†[1] Fr W†
+M1 155mm Howitzer WP8 s7 WP8 s7 Fr 29 Fr Y†
+M1918M1 155mm Gun RFNM AP4†[1] WP8 RFNM AP4†[1] WP8 Fr 29 Fr Y† No IF.
+Mitrailleuse de 13.2 CAJ 2 TK DR†[1] 2 TK DR†[1] Fr 18†[1] Fr B Fr G† Fr V Towing NA†1
+OQF 40mm AA LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr W†
+M1 40mm AA Gun LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1945.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1945.txt
new file mode 100644
index 0000000..3b298b8
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/ordnance/free-french/1945.txt
@@ -0,0 +1,26 @@
+=== ordnance/free-french/1945 ===
+
+Name Capabilities (effective) # Notes Comments
+--------------------------- ------------------------------ ------------------ --------- -------------------- ----------------------
+LG de 50 mle 37(f) 2PP 2PP Fr 1 Fr A Fr B Fr C† Fr E crewed†
+OML 2-in. Mortar 4PP IR[2+]† s7 4PP IR† s7 Fr 22†[1] Fr W†
+Mortier de 60 mle 35(f) 5PP no OBA† IR[2+]† 5PP no OBA† IR† Fr 2† Fr A Fr B Fr V
+M2 60mm Mortar IR WP7[5] 5PP OBA† IR WP7 5PP OBA† Fr 22 Fr W†
+OML 3-in. Mortar QSU IR[2+]†[1] WP7 s8[1+]† QSU IR†[1] WP7 s8† Fr 22†[1] Fr W†
+Mortier de 81 mle 27/31(f) QSU s8 QSU s8 Fr 3† Fr A Fr B Fr D Fr V
+M1 81mm Mortar QSU WP8 QSU WP8 Fr 22 Fr D Fr Y†
+Boys ATR 1PP 1PP Fr 4† Fr B
+OQF 25mm Hotchkiss QSU QSU Fr 23†[1] Fr V Fr W†
+Canon AC de 47 SA 37 APX(f) QSU APCR only†[1] QSU APCR only†[1] Fr 6†[1] Fr B Fr G† Fr P Fr V
+OQF 6-Pounder 7-cwt QSU D6[J4E]7[5]† HE7[F3]8[4+]† QSU D7† HE8† Fr 24 Fr W†
+M1 57mm AT Gun QSU D4[J4+E]† HE7[J4E]7[5]† QSU D4† HE7† Fr 24 Fr Y†
+Canon de 75 mle 1897 QSU s8 QSU s8 Fr 25†[1] Fr V Fr W†
+OQF 25-Pounder Gun-Howitzer LF [NT, 0 ROF] s8 LF [NT, 0 ROF] s8 Fr 26†[1] Fr W†
+M2A1 105mm Howitzer C7[4+P]†[1] H6 WP8 s7 H6 WP8 s7 Fr 27 Fr Y†
+M3 105mm Howitzer C7[P]†[1] H7 WP8 s7 H7 WP8 s7 Fr 27 Fr Y†
+OBL 5.5-in. Gun-Howitzer Fr 28†[1] Fr W†
+M1 155mm Howitzer WP8 s7 WP8 s7 Fr 29 Fr Y†
+M1918M1 155mm Gun RFNM AP4†[1] WP8 RFNM AP4†[1] WP8 Fr 29 Fr Y† No IF.
+Mitrailleuse de 13.2 CAJ 2 TK DR†[1] 2 TK DR†[1] Fr 18†[1] Fr B Fr G† Fr V Towing NA†1
+OQF 40mm AA LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr W†
+M1 40mm AA Gun LF [40†[1], 2 ROF] LF [40†[1], 2 ROF] Fr 30 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1940.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1940.txt
new file mode 100644
index 0000000..dd35fb7
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1940.txt
@@ -0,0 +1,56 @@
+=== vehicles/free-french/1940 ===
+
+Name Capabilities (effective) # Notes Comments
+------------------------ ----------------------------------------- --------------------------------------- --------- -------------------------------------------------------------------------------------- ----------
+H39(f) ® AP10 CS 2 ® AP10 CS 2 Fr 7† Fr A†1 Fr C Fr F
+M5A1 C7†[2] CS 4 C7†[2] CS 4 Fr 37†[1] Fr Y†
+H39(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+R35(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+Crusader II sM8 CS 4[brewup] sM8 CS 4[brewup] Fr 38 Fr W†
+Crusader III HE7[F3+]†[1] sD7 sM8†[2] CS 3[brewup] sD7 sM8†[2] CS 3[brewup] Fr 38 Fr W†
+M4 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39 Fr Y†
+M4A1 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39† Fr Y†
+M4A2 WP7[J4+]†[2] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39†[1] Fr Y†
+M4A3(75)W WP7 s5 sM8 CS 6 WP7 s5 sM8 CS 6 Fr 40 Fr Y†
+M4A3(76)W A4[A4]5[5]†[2] s5[5] sM8 CS 6 sM8 CS 6 Fr 40 Fr Y†
+M4A3(105) C7[P]†[1] H9 WP9 s7 sM8 CS 6 H9 WP9 s7 sM8 CS 6 Fr 40 Fr Y†
+M4 Tankdozer WP7 s5 sM6 CS 5[brewup] WP7 s5 sM6 CS 5[brewup] Fr 40 Fr Y†
+S35(f) ®9†[1] CS 4 ®9†[1] CS 4 Fr 12† Fr A†3 Fr C Fr F Fr I†2 Fr R†1
+B1-bis(f) ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] Fr 13† Fr A†4 Fr B†3 Fr C Fr E Fr F Fr I†2 Fr R†1
+M10 GMC A5[A4E]6[5E]†[1] s5[5] sP5 CS 7 sP5 CS 7 Fr 41 Fr Y†
+Daimler sD4[4+]† CS 2 CS 2 Fr 42†[1] Fr W†
+AM Dodge(a) AP10 CS 6† AP10 CS 6† Fr 15† Fr F
+M3A1 CS 4 CS 4 Fr 43†[1] Fr Y†
+M20 sP5 CS 4 sP5 CS 4 Fr 43†[1] Fr Y†
+Marmon-Herrington III ME CS 4 CS 4 Fr 44 Fr W†
+Marmon-Herrington IIIv CS 4 CS 4 Fr 44 Fr W†
+Humber II sD6 CS 3 sD6 CS 3 Fr 45 Fr W†
+M8 C7†[2] sP5 CS 4 C7†[2] sP5 CS 4 Fr 43 Fr Y†
+M8 HMC C4[4+]†[1] H9 WP9 CS 5 H9 WP9 CS 5 Fr 46 Fr Y†
+M7 HMC C7[P]†[1] H7 WP8 s7 CS 7 H7 WP8 s7 CS 7 Fr 46 Fr Y†
+T30 HMC AP7 H5 WP9 CS 4 AP7 H5 WP9 CS 4 Fr 47 Fr Y†
+M2 CS 4 CS 4 Fr 47 Fr Y†
+M3 CS 5 CS 5 Fr 47 Fr Y†
+M5 cs 5†[1] cs 5†[1] Fr 47† Fr U
+M5A1 cs 5† cs 5† Fr 47† Fr U
+M9 cs 4†[1] cs 4†[1] Fr 47† Fr U
+Carrier A sD5[4+]†[1] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier B sD5[4+]†[2] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier C sD5[4+]†[1] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier, MMG A sD5[4+]†[2] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier AC(b) CS 3 CS 3 Fr 31† Fr F Fr M†1
+Ac de 25 CA(f) CS 4 CS 4 Fr 21† Fr F Fr AA†1
+Ac de 75 Conus(b) s8 CS 5 s8 CS 5 Fr 20† Fr F Fr M†1
+Ac de 40 CA(a) CS 4 CS 4 Fr 22 Fr E Fr F Fr M† Fr AA†1
+Ac de 75 mle 13/34(f) CS 7 CS 7 Fr 23† Fr D†1 Fr F Fr AA†2
+Quad FAT CS 5[brewup]† CS 5[brewup]† Fr 49 Fr W†
+Jeep(a) cs 2†[1] cs 2†[1] Fr 50†[1] Fr W†
+15-cwt Truck cs 5 cs 5 Fr 50 Fr W†
+30-cwt Lorry cs 6 cs 6 Fr 50 Fr W†
+3-Ton Lorry cs 7 cs 7 Fr 50 Fr W†
+Jeep cs 2†[1] cs 2†[1] Fr 51 Fr Y†
+Jeep GPA cs 2 cs 2 Fr 51 Fr Y†
+¾-Ton cs 4 cs 4 Fr 51 Fr Y†
+1½-Ton cs 6 cs 6 Fr 51 Fr Y†
+2½-Ton cs 7 cs 7 Fr 51 Fr Y†
+7½-Ton cs 7 cs 7 Fr 51 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1941.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1941.txt
new file mode 100644
index 0000000..5c9c696
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1941.txt
@@ -0,0 +1,56 @@
+=== vehicles/free-french/1941 ===
+
+Name Capabilities (effective) # Notes Comments
+------------------------ ----------------------------------------- --------------------------------------- --------- -------------------------------------------------------------------------------------- ----------
+H39(f) ® AP10 CS 2 ® AP10 CS 2 Fr 7† Fr A†1 Fr C Fr F
+M5A1 C7†[2] CS 4 C7†[2] CS 4 Fr 37†[1] Fr Y†
+H39(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+R35(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+Crusader II sM8 CS 4[brewup] sM8 CS 4[brewup] Fr 38 Fr W†
+Crusader III HE7[F3+]†[1] sD7 sM8†[2] CS 3[brewup] sD7 sM8†[2] CS 3[brewup] Fr 38 Fr W†
+M4 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39 Fr Y†
+M4A1 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39† Fr Y†
+M4A2 WP7[J4+]†[2] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39†[1] Fr Y†
+M4A3(75)W WP7 s5 sM8 CS 6 WP7 s5 sM8 CS 6 Fr 40 Fr Y†
+M4A3(76)W A4[A4]5[5]†[2] s5[5] sM8 CS 6 sM8 CS 6 Fr 40 Fr Y†
+M4A3(105) C7[P]†[1] H9 WP9 s7 sM8 CS 6 H9 WP9 s7 sM8 CS 6 Fr 40 Fr Y†
+M4 Tankdozer WP7 s5 sM6 CS 5[brewup] WP7 s5 sM6 CS 5[brewup] Fr 40 Fr Y†
+S35(f) ®9†[1] CS 4 ®9†[1] CS 4 Fr 12† Fr A†3 Fr C Fr F Fr I†2 Fr R†1
+B1-bis(f) ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] Fr 13† Fr A†4 Fr B†3 Fr C Fr E Fr F Fr I†2 Fr R†1
+M10 GMC A5[A4E]6[5E]†[1] s5[5] sP5 CS 7 sP5 CS 7 Fr 41 Fr Y†
+Daimler sD4[4+]† CS 2 CS 2 Fr 42†[1] Fr W†
+AM Dodge(a) AP10 CS 6† AP10 CS 6† Fr 15† Fr F
+M3A1 CS 4 CS 4 Fr 43†[1] Fr Y†
+M20 sP5 CS 4 sP5 CS 4 Fr 43†[1] Fr Y†
+Marmon-Herrington III ME CS 4 CS 4 Fr 44 Fr W†
+Marmon-Herrington IIIv CS 4 CS 4 Fr 44 Fr W†
+Humber II sD6 CS 3 sD6 CS 3 Fr 45 Fr W†
+M8 C7†[2] sP5 CS 4 C7†[2] sP5 CS 4 Fr 43 Fr Y†
+M8 HMC C4[4+]†[1] H9 WP9 CS 5 H9 WP9 CS 5 Fr 46 Fr Y†
+M7 HMC C7[P]†[1] H7 WP8 s7 CS 7 H7 WP8 s7 CS 7 Fr 46 Fr Y†
+T30 HMC AP7 H5 WP9 CS 4 AP7 H5 WP9 CS 4 Fr 47 Fr Y†
+M2 CS 4 CS 4 Fr 47 Fr Y†
+M3 CS 5 CS 5 Fr 47 Fr Y†
+M5 cs 5†[1] cs 5†[1] Fr 47† Fr U
+M5A1 cs 5† cs 5† Fr 47† Fr U
+M9 cs 4†[1] cs 4†[1] Fr 47† Fr U
+Carrier A sD5[4+]†[1] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier B sD5[4+]†[2] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier C sD5[4+]†[1] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier, MMG A sD5[4+]†[2] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier AC(b) CS 3 CS 3 Fr 31† Fr F Fr M†1
+Ac de 25 CA(f) CS 4 CS 4 Fr 21† Fr F Fr AA†1
+Ac de 75 Conus(b) s8 CS 5 s8 CS 5 Fr 20† Fr F Fr M†1
+Ac de 40 CA(a) CS 4 CS 4 Fr 22 Fr E Fr F Fr M† Fr AA†1
+Ac de 75 mle 13/34(f) CS 7 CS 7 Fr 23† Fr D†1 Fr F Fr AA†2
+Quad FAT CS 5[brewup]† CS 5[brewup]† Fr 49 Fr W†
+Jeep(a) cs 2†[1] cs 2†[1] Fr 50†[1] Fr W†
+15-cwt Truck cs 5 cs 5 Fr 50 Fr W†
+30-cwt Lorry cs 6 cs 6 Fr 50 Fr W†
+3-Ton Lorry cs 7 cs 7 Fr 50 Fr W†
+Jeep cs 2†[1] cs 2†[1] Fr 51 Fr Y†
+Jeep GPA cs 2 cs 2 Fr 51 Fr Y†
+¾-Ton cs 4 cs 4 Fr 51 Fr Y†
+1½-Ton cs 6 cs 6 Fr 51 Fr Y†
+2½-Ton cs 7 cs 7 Fr 51 Fr Y†
+7½-Ton cs 7 cs 7 Fr 51 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1942.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1942.txt
new file mode 100644
index 0000000..dbe2341
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1942.txt
@@ -0,0 +1,56 @@
+=== vehicles/free-french/1942 ===
+
+Name Capabilities (effective) # Notes Comments
+------------------------ ----------------------------------------- --------------------------------------- --------- -------------------------------------------------------------------------------------- ----------
+H39(f) ® AP10 CS 2 ® AP10 CS 2 Fr 7† Fr A†1 Fr C Fr F
+M5A1 C7†[2] CS 4 C7†[2] CS 4 Fr 37†[1] Fr Y†
+H39(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+R35(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+Crusader II sM8 CS 4[brewup] sM8 CS 4[brewup] Fr 38 Fr W†
+Crusader III HE7[F3+]†[1] sD7 sM8†[2] CS 3[brewup] sD7 sM8†[2] CS 3[brewup] Fr 38 Fr W†
+M4 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39 Fr Y†
+M4A1 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39† Fr Y†
+M4A2 WP7[J4+]†[2] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39†[1] Fr Y†
+M4A3(75)W WP7 s5 sM8 CS 6 WP7 s5 sM8 CS 6 Fr 40 Fr Y†
+M4A3(76)W A4[A4]5[5]†[2] s5[5] sM8 CS 6 sM8 CS 6 Fr 40 Fr Y†
+M4A3(105) C7[P]†[1] H9 WP9 s7 sM8 CS 6 H9 WP9 s7 sM8 CS 6 Fr 40 Fr Y†
+M4 Tankdozer WP7 s5 sM6 CS 5[brewup] WP7 s5 sM6 CS 5[brewup] Fr 40 Fr Y†
+S35(f) ®9†[1] CS 4 ®9†[1] CS 4 Fr 12† Fr A†3 Fr C Fr F Fr I†2 Fr R†1
+B1-bis(f) ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] Fr 13† Fr A†4 Fr B†3 Fr C Fr E Fr F Fr I†2 Fr R†1
+M10 GMC A5[A4E]6[5E]†[1] s5[5] sP5 CS 7 sP5 CS 7 Fr 41 Fr Y†
+Daimler sD4[4+]† CS 2 CS 2 Fr 42†[1] Fr W†
+AM Dodge(a) AP10 CS 6† AP10 CS 6† Fr 15† Fr F
+M3A1 CS 4 CS 4 Fr 43†[1] Fr Y†
+M20 sP5 CS 4 sP5 CS 4 Fr 43†[1] Fr Y†
+Marmon-Herrington III ME CS 4 CS 4 Fr 44 Fr W†
+Marmon-Herrington IIIv CS 4 CS 4 Fr 44 Fr W†
+Humber II sD6 CS 3 sD6 CS 3 Fr 45 Fr W†
+M8 C7†[2] sP5 CS 4 C7†[2] sP5 CS 4 Fr 43 Fr Y†
+M8 HMC C4[4+]†[1] H9 WP9 CS 5 H9 WP9 CS 5 Fr 46 Fr Y†
+M7 HMC C7[P]†[1] H7 WP8 s7 CS 7 H7 WP8 s7 CS 7 Fr 46 Fr Y†
+T30 HMC AP7 H5 WP9 CS 4 AP7 H5 WP9 CS 4 Fr 47 Fr Y†
+M2 CS 4 CS 4 Fr 47 Fr Y†
+M3 CS 5 CS 5 Fr 47 Fr Y†
+M5 cs 5†[1] cs 5†[1] Fr 47† Fr U
+M5A1 cs 5† cs 5† Fr 47† Fr U
+M9 cs 4†[1] cs 4†[1] Fr 47† Fr U
+Carrier A sD5[4+]†[1] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier B sD5[4+]†[2] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier C sD5[4+]†[1] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier, MMG A sD5[4+]†[2] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier AC(b) CS 3 CS 3 Fr 31† Fr F Fr M†1
+Ac de 25 CA(f) CS 4 CS 4 Fr 21† Fr F Fr AA†1
+Ac de 75 Conus(b) s8 CS 5 s8 CS 5 Fr 20† Fr F Fr M†1
+Ac de 40 CA(a) CS 4 CS 4 Fr 22 Fr E Fr F Fr M† Fr AA†1
+Ac de 75 mle 13/34(f) CS 7 CS 7 Fr 23† Fr D†1 Fr F Fr AA†2
+Quad FAT CS 5[brewup]† CS 5[brewup]† Fr 49 Fr W†
+Jeep(a) cs 2†[1] cs 2†[1] Fr 50†[1] Fr W†
+15-cwt Truck cs 5 cs 5 Fr 50 Fr W†
+30-cwt Lorry cs 6 cs 6 Fr 50 Fr W†
+3-Ton Lorry cs 7 cs 7 Fr 50 Fr W†
+Jeep cs 2†[1] cs 2†[1] Fr 51 Fr Y†
+Jeep GPA cs 2 cs 2 Fr 51 Fr Y†
+¾-Ton cs 4 cs 4 Fr 51 Fr Y†
+1½-Ton cs 6 cs 6 Fr 51 Fr Y†
+2½-Ton cs 7 cs 7 Fr 51 Fr Y†
+7½-Ton cs 7 cs 7 Fr 51 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1943.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1943.txt
new file mode 100644
index 0000000..01898f3
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1943.txt
@@ -0,0 +1,56 @@
+=== vehicles/free-french/1943 ===
+
+Name Capabilities (effective) # Notes Comments
+------------------------ ----------------------------------------- --------------------------------------- --------- -------------------------------------------------------------------------------------- ----------
+H39(f) ® AP10 CS 2 ® AP10 CS 2 Fr 7† Fr A†1 Fr C Fr F
+M5A1 C7†[2] CS 4 C7†[2] CS 4 Fr 37†[1] Fr Y†
+H39(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+R35(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+Crusader II sM8 CS 4[brewup] sM8 CS 4[brewup] Fr 38 Fr W†
+Crusader III HE7[F3+]†[1] sD7 sM8†[2] CS 3[brewup] sD7 sM8†[2] CS 3[brewup] Fr 38 Fr W†
+M4 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39 Fr Y†
+M4A1 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39† Fr Y†
+M4A2 WP7[J4+]†[2] s5[J4+] sM5[4+] CS 5[brewup] CS 5[brewup] Fr 39†[1] Fr Y†
+M4A3(75)W WP7 s5 sM8 CS 6 WP7 s5 sM8 CS 6 Fr 40 Fr Y†
+M4A3(76)W A4[A4]5[5]†[2] s5[5] sM8 CS 6 sM8 CS 6 Fr 40 Fr Y†
+M4A3(105) C7[P]†[1] H9 WP9 s7 sM8 CS 6 H9 WP9 s7 sM8 CS 6 Fr 40 Fr Y†
+M4 Tankdozer WP7 s5 sM6 CS 5[brewup] WP7 s5 sM6 CS 5[brewup] Fr 40 Fr Y†
+S35(f) ®9†[1] CS 4 ®9†[1] CS 4 Fr 12† Fr A†3 Fr C Fr F Fr I†2 Fr R†1
+B1-bis(f) ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] Fr 13† Fr A†4 Fr B†3 Fr C Fr E Fr F Fr I†2 Fr R†1
+M10 GMC A5[A4E]6[5E]†[1] s5[5] sP5 CS 7 sP5 CS 7 Fr 41 Fr Y†
+Daimler sD4[4+]† CS 2 CS 2 Fr 42†[1] Fr W†
+AM Dodge(a) AP10 CS 6† AP10 CS 6† Fr 15† Fr F
+M3A1 CS 4 CS 4 Fr 43†[1] Fr Y†
+M20 sP5 CS 4 sP5 CS 4 Fr 43†[1] Fr Y†
+Marmon-Herrington III ME CS 4 CS 4 Fr 44 Fr W†
+Marmon-Herrington IIIv CS 4 CS 4 Fr 44 Fr W†
+Humber II sD6 CS 3 sD6 CS 3 Fr 45 Fr W†
+M8 C7†[2] sP5 CS 4 C7†[2] sP5 CS 4 Fr 43 Fr Y†
+M8 HMC C4[4+]†[1] H9 WP9 CS 5 H9 WP9 CS 5 Fr 46 Fr Y†
+M7 HMC C7[P]†[1] H7 WP8 s7 CS 7 H7 WP8 s7 CS 7 Fr 46 Fr Y†
+T30 HMC AP7 H5 WP9 CS 4 AP7 H5 WP9 CS 4 Fr 47 Fr Y†
+M2 CS 4 CS 4 Fr 47 Fr Y†
+M3 CS 5 CS 5 Fr 47 Fr Y†
+M5 cs 5†[1] cs 5†[1] Fr 47† Fr U
+M5A1 cs 5† cs 5† Fr 47† Fr U
+M9 cs 4†[1] cs 4†[1] Fr 47† Fr U
+Carrier A sD5[4+]†[1] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier B sD5[4+]†[2] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier C sD5[4+]†[1] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier, MMG A sD5[4+]†[2] CS 3 CS 3 Fr 48†[1] Fr W†
+Carrier AC(b) CS 3 CS 3 Fr 31† Fr F Fr M†1
+Ac de 25 CA(f) CS 4 CS 4 Fr 21† Fr F Fr AA†1
+Ac de 75 Conus(b) s8 CS 5 s8 CS 5 Fr 20† Fr F Fr M†1
+Ac de 40 CA(a) CS 4 CS 4 Fr 22 Fr E Fr F Fr M† Fr AA†1
+Ac de 75 mle 13/34(f) CS 7 CS 7 Fr 23† Fr D†1 Fr F Fr AA†2
+Quad FAT CS 5[brewup]† CS 5[brewup]† Fr 49 Fr W†
+Jeep(a) cs 2†[1] cs 2†[1] Fr 50†[1] Fr W†
+15-cwt Truck cs 5 cs 5 Fr 50 Fr W†
+30-cwt Lorry cs 6 cs 6 Fr 50 Fr W†
+3-Ton Lorry cs 7 cs 7 Fr 50 Fr W†
+Jeep cs 2†[1] cs 2†[1] Fr 51 Fr Y†
+Jeep GPA cs 2 cs 2 Fr 51 Fr Y†
+¾-Ton cs 4 cs 4 Fr 51 Fr Y†
+1½-Ton cs 6 cs 6 Fr 51 Fr Y†
+2½-Ton cs 7 cs 7 Fr 51 Fr Y†
+7½-Ton cs 7 cs 7 Fr 51 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1944.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1944.txt
new file mode 100644
index 0000000..6489e13
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1944.txt
@@ -0,0 +1,56 @@
+=== vehicles/free-french/1944 ===
+
+Name Capabilities (effective) # Notes Comments
+------------------------ ----------------------------------------- --------------------------------------- --------- -------------------------------------------------------------------------------------- ----------
+H39(f) ® AP10 CS 2 ® AP10 CS 2 Fr 7† Fr A†1 Fr C Fr F
+M5A1 C7†[2] CS 4 C7†[2] CS 4 Fr 37†[1] Fr Y†
+H39(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+R35(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+Crusader II sM8 CS 4[brewup] sM8 CS 4[brewup] Fr 38 Fr W†
+Crusader III HE7[F3+]†[1] sD7 sM8†[2] CS 3[brewup] HE7†[1] sD7 sM8†[2] CS 3[brewup] Fr 38 Fr W†
+M4 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] sM5 CS 5[brewup] Fr 39 Fr Y†
+M4A1 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] sM5 CS 5[brewup] Fr 39† Fr Y†
+M4A2 WP7[J4+]†[2] s5[J4+] sM5[4+] CS 5[brewup] sM5 CS 5[brewup] Fr 39†[1] Fr Y†
+M4A3(75)W WP7 s5 sM8 CS 6 WP7 s5 sM8 CS 6 Fr 40 Fr Y†
+M4A3(76)W A4[A4]5[5]†[2] s5[5] sM8 CS 6 sM8 CS 6 Fr 40 Fr Y†
+M4A3(105) C7[P]†[1] H9 WP9 s7 sM8 CS 6 H9 WP9 s7 sM8 CS 6 Fr 40 Fr Y†
+M4 Tankdozer WP7 s5 sM6 CS 5[brewup] WP7 s5 sM6 CS 5[brewup] Fr 40 Fr Y†
+S35(f) ®9†[1] CS 4 ®9†[1] CS 4 Fr 12† Fr A†3 Fr C Fr F Fr I†2 Fr R†1
+B1-bis(f) ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] Fr 13† Fr A†4 Fr B†3 Fr C Fr E Fr F Fr I†2 Fr R†1
+M10 GMC A5[A4E]6[5E]†[1] s5[5] sP5 CS 7 sP5 CS 7 Fr 41 Fr Y†
+Daimler sD4[4+]† CS 2 sD4† CS 2 Fr 42†[1] Fr W†
+AM Dodge(a) AP10 CS 6† AP10 CS 6† Fr 15† Fr F
+M3A1 CS 4 CS 4 Fr 43†[1] Fr Y†
+M20 sP5 CS 4 sP5 CS 4 Fr 43†[1] Fr Y†
+Marmon-Herrington III ME CS 4 CS 4 Fr 44 Fr W†
+Marmon-Herrington IIIv CS 4 CS 4 Fr 44 Fr W†
+Humber II sD6 CS 3 sD6 CS 3 Fr 45 Fr W†
+M8 C7†[2] sP5 CS 4 C7†[2] sP5 CS 4 Fr 43 Fr Y†
+M8 HMC C4[4+]†[1] H9 WP9 CS 5 C4†[1] H9 WP9 CS 5 Fr 46 Fr Y†
+M7 HMC C7[P]†[1] H7 WP8 s7 CS 7 H7 WP8 s7 CS 7 Fr 46 Fr Y†
+T30 HMC AP7 H5 WP9 CS 4 AP7 H5 WP9 CS 4 Fr 47 Fr Y†
+M2 CS 4 CS 4 Fr 47 Fr Y†
+M3 CS 5 CS 5 Fr 47 Fr Y†
+M5 cs 5†[1] cs 5†[1] Fr 47† Fr U
+M5A1 cs 5† cs 5† Fr 47† Fr U
+M9 cs 4†[1] cs 4†[1] Fr 47† Fr U
+Carrier A sD5[4+]†[1] CS 3 sD5†[1] CS 3 Fr 48†[1] Fr W†
+Carrier B sD5[4+]†[2] CS 3 sD5†[2] CS 3 Fr 48†[1] Fr W†
+Carrier C sD5[4+]†[1] CS 3 sD5†[1] CS 3 Fr 48†[1] Fr W†
+Carrier, MMG A sD5[4+]†[2] CS 3 sD5†[2] CS 3 Fr 48†[1] Fr W†
+Carrier AC(b) CS 3 CS 3 Fr 31† Fr F Fr M†1
+Ac de 25 CA(f) CS 4 CS 4 Fr 21† Fr F Fr AA†1
+Ac de 75 Conus(b) s8 CS 5 s8 CS 5 Fr 20† Fr F Fr M†1
+Ac de 40 CA(a) CS 4 CS 4 Fr 22 Fr E Fr F Fr M† Fr AA†1
+Ac de 75 mle 13/34(f) CS 7 CS 7 Fr 23† Fr D†1 Fr F Fr AA†2
+Quad FAT CS 5[brewup]† CS 5[brewup]† Fr 49 Fr W†
+Jeep(a) cs 2†[1] cs 2†[1] Fr 50†[1] Fr W†
+15-cwt Truck cs 5 cs 5 Fr 50 Fr W†
+30-cwt Lorry cs 6 cs 6 Fr 50 Fr W†
+3-Ton Lorry cs 7 cs 7 Fr 50 Fr W†
+Jeep cs 2†[1] cs 2†[1] Fr 51 Fr Y†
+Jeep GPA cs 2 cs 2 Fr 51 Fr Y†
+¾-Ton cs 4 cs 4 Fr 51 Fr Y†
+1½-Ton cs 6 cs 6 Fr 51 Fr Y†
+2½-Ton cs 7 cs 7 Fr 51 Fr Y†
+7½-Ton cs 7 cs 7 Fr 51 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1945.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1945.txt
new file mode 100644
index 0000000..622c295
--- /dev/null
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/free-french/1945.txt
@@ -0,0 +1,56 @@
+=== vehicles/free-french/1945 ===
+
+Name Capabilities (effective) # Notes Comments
+------------------------ ----------------------------------------- --------------------------------------- --------- -------------------------------------------------------------------------------------- ----------
+H39(f) ® AP10 CS 2 ® AP10 CS 2 Fr 7† Fr A†1 Fr C Fr F
+M5A1 C7†[2] CS 4 C7†[2] CS 4 Fr 37†[1] Fr Y†
+H39(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+R35(L)(f) ® AP10 CS 2 ® AP10 CS 2 Fr 8† Fr A†1 Fr C Fr E Fr F
+Crusader II sM8 CS 4[brewup] sM8 CS 4[brewup] Fr 38 Fr W†
+Crusader III HE7[F3+]†[1] sD7 sM8†[2] CS 3[brewup] HE7†[1] sD7 sM8†[2] CS 3[brewup] Fr 38 Fr W†
+M4 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] WP7†[3] s5 sM5 CS 5[brewup] Fr 39 Fr Y†
+M4A1 WP7[J4+]†[3] s5[J4+] sM5[4+] CS 5[brewup] WP7†[3] s5 sM5 CS 5[brewup] Fr 39† Fr Y†
+M4A2 WP7[J4+]†[2] s5[J4+] sM5[4+] CS 5[brewup] WP7†[2] s5 sM5 CS 5[brewup] Fr 39†[1] Fr Y†
+M4A3(75)W WP7 s5 sM8 CS 6 WP7 s5 sM8 CS 6 Fr 40 Fr Y†
+M4A3(76)W A4[A4]5[5]†[2] s5[5] sM8 CS 6 A5†[2] s5 sM8 CS 6 Fr 40 Fr Y†
+M4A3(105) C7[P]†[1] H9 WP9 s7 sM8 CS 6 H9 WP9 s7 sM8 CS 6 Fr 40 Fr Y†
+M4 Tankdozer WP7 s5 sM6 CS 5[brewup] WP7 s5 sM6 CS 5[brewup] Fr 40 Fr Y†
+S35(f) ®9†[1] CS 4 ®9†[1] CS 4 Fr 12† Fr A†3 Fr C Fr F Fr I†2 Fr R†1
+B1-bis(f) ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] ®9†[1] no IF[75]† AP9[75]† CS 5[brewup] Fr 13† Fr A†4 Fr B†3 Fr C Fr E Fr F Fr I†2 Fr R†1
+M10 GMC A5[A4E]6[5E]†[1] s5[5] sP5 CS 7 A6†[1] s5 sP5 CS 7 Fr 41 Fr Y†
+Daimler sD4[4+]† CS 2 sD4† CS 2 Fr 42†[1] Fr W†
+AM Dodge(a) AP10 CS 6† AP10 CS 6† Fr 15† Fr F
+M3A1 CS 4 CS 4 Fr 43†[1] Fr Y†
+M20 sP5 CS 4 sP5 CS 4 Fr 43†[1] Fr Y†
+Marmon-Herrington III ME CS 4 CS 4 Fr 44 Fr W†
+Marmon-Herrington IIIv CS 4 CS 4 Fr 44 Fr W†
+Humber II sD6 CS 3 sD6 CS 3 Fr 45 Fr W†
+M8 C7†[2] sP5 CS 4 C7†[2] sP5 CS 4 Fr 43 Fr Y†
+M8 HMC C4[4+]†[1] H9 WP9 CS 5 C4†[1] H9 WP9 CS 5 Fr 46 Fr Y†
+M7 HMC C7[P]†[1] H7 WP8 s7 CS 7 H7 WP8 s7 CS 7 Fr 46 Fr Y†
+T30 HMC AP7 H5 WP9 CS 4 AP7 H5 WP9 CS 4 Fr 47 Fr Y†
+M2 CS 4 CS 4 Fr 47 Fr Y†
+M3 CS 5 CS 5 Fr 47 Fr Y†
+M5 cs 5†[1] cs 5†[1] Fr 47† Fr U
+M5A1 cs 5† cs 5† Fr 47† Fr U
+M9 cs 4†[1] cs 4†[1] Fr 47† Fr U
+Carrier A sD5[4+]†[1] CS 3 sD5†[1] CS 3 Fr 48†[1] Fr W†
+Carrier B sD5[4+]†[2] CS 3 sD5†[2] CS 3 Fr 48†[1] Fr W†
+Carrier C sD5[4+]†[1] CS 3 sD5†[1] CS 3 Fr 48†[1] Fr W†
+Carrier, MMG A sD5[4+]†[2] CS 3 sD5†[2] CS 3 Fr 48†[1] Fr W†
+Carrier AC(b) CS 3 CS 3 Fr 31† Fr F Fr M†1
+Ac de 25 CA(f) CS 4 CS 4 Fr 21† Fr F Fr AA†1
+Ac de 75 Conus(b) s8 CS 5 s8 CS 5 Fr 20† Fr F Fr M†1
+Ac de 40 CA(a) CS 4 CS 4 Fr 22 Fr E Fr F Fr M† Fr AA†1
+Ac de 75 mle 13/34(f) CS 7 CS 7 Fr 23† Fr D†1 Fr F Fr AA†2
+Quad FAT CS 5[brewup]† CS 5[brewup]† Fr 49 Fr W†
+Jeep(a) cs 2†[1] cs 2†[1] Fr 50†[1] Fr W†
+15-cwt Truck cs 5 cs 5 Fr 50 Fr W†
+30-cwt Lorry cs 6 cs 6 Fr 50 Fr W†
+3-Ton Lorry cs 7 cs 7 Fr 50 Fr W†
+Jeep cs 2†[1] cs 2†[1] Fr 51 Fr Y†
+Jeep GPA cs 2 cs 2 Fr 51 Fr Y†
+¾-Ton cs 4 cs 4 Fr 51 Fr Y†
+1½-Ton cs 6 cs 6 Fr 51 Fr Y†
+2½-Ton cs 7 cs 7 Fr 51 Fr Y†
+7½-Ton cs 7 cs 7 Fr 51 Fr Y†
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1940.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1940.txt
index 1e6fe36..b7c440c 100644
--- a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1940.txt
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1940.txt
@@ -95,11 +95,11 @@ Carrier C sD5[4+]†[1] CS 3 CS 3
Carrier, MMG A sD5[4+]†[2] CS 3 CS 3 57 Br N Br P Br Q†1 Br U†2 LL
Carrier, MMG B sD5[4+]†[2] CS 4 CS 4 57 Br U†2 Br BB†1 LL
Jeep(a) cs 2 cs 2 58 H† L†1 LL
-¾-Ton Truck(a) cs 4 cs 4 Br 85 Br A Br N LL
-1½-Ton Truck(a) cs 6 cs 6 Br 85 Br A Br N LL
-2½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-7½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-DUKW cs 7†[1] cs 7†[1] US 52† US D†3 US O†2 US CC†1 LL
+¾-Ton Truck(a) cs 4 cs 4 n/a Br A Br N LL
+1½-Ton Truck(a) cs 6 cs 6 n/a Br A Br N LL
+2½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+7½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+DUKW cs 7†[1] cs 7†[1] n/a US D†3 US O†2 US CC†1 LL
BT-2A ® C5†[2] CS 3 ® C5†[2] CS 3 1† C†2 Ru M†1 CMG 2:00 from MA
BT-2A(L) ® C6†[2] CS 3 ® C6†[2] CS 3 2† C†2 Ru M†1
BT-2B ® CS 3 ® CS 3 3† Ru M†1 2 TK DR (MG)
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1941.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1941.txt
index 33a93f3..75b2033 100644
--- a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1941.txt
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1941.txt
@@ -95,11 +95,11 @@ Carrier C sD5[4+]†[1] CS 3 CS 3
Carrier, MMG A sD5[4+]†[2] CS 3 CS 3 57 Br N Br P Br Q†1 Br U†2 LL
Carrier, MMG B sD5[4+]†[2] CS 4 CS 4 57 Br U†2 Br BB†1 LL
Jeep(a) cs 2 cs 2 58 H† L†1 LL
-¾-Ton Truck(a) cs 4 cs 4 Br 85 Br A Br N LL
-1½-Ton Truck(a) cs 6 cs 6 Br 85 Br A Br N LL
-2½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-7½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-DUKW cs 7†[1] cs 7†[1] US 52† US D†3 US O†2 US CC†1 LL
+¾-Ton Truck(a) cs 4 cs 4 n/a Br A Br N LL
+1½-Ton Truck(a) cs 6 cs 6 n/a Br A Br N LL
+2½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+7½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+DUKW cs 7†[1] cs 7†[1] n/a US D†3 US O†2 US CC†1 LL
BT-2A ® C5†[2] CS 3 ® C5†[2] CS 3 1† C†2 Ru M†1 CMG 2:00 from MA
BT-2A(L) ® C6†[2] CS 3 ® C6†[2] CS 3 2† C†2 Ru M†1
BT-2B ® CS 3 ® CS 3 3† Ru M†1 2 TK DR (MG)
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1942.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1942.txt
index a7da671..9eb51f2 100644
--- a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1942.txt
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1942.txt
@@ -95,11 +95,11 @@ Carrier C sD5[4+]†[1] CS 3 CS 3
Carrier, MMG A sD5[4+]†[2] CS 3 CS 3 57 Br N Br P Br Q†1 Br U†2 LL
Carrier, MMG B sD5[4+]†[2] CS 4 CS 4 57 Br U†2 Br BB†1 LL
Jeep(a) cs 2 cs 2 58 H† L†1 LL
-¾-Ton Truck(a) cs 4 cs 4 Br 85 Br A Br N LL
-1½-Ton Truck(a) cs 6 cs 6 Br 85 Br A Br N LL
-2½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-7½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-DUKW cs 7†[1] cs 7†[1] US 52† US D†3 US O†2 US CC†1 LL
+¾-Ton Truck(a) cs 4 cs 4 n/a Br A Br N LL
+1½-Ton Truck(a) cs 6 cs 6 n/a Br A Br N LL
+2½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+7½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+DUKW cs 7†[1] cs 7†[1] n/a US D†3 US O†2 US CC†1 LL
BT-2A ® C5†[2] CS 3 ® C5†[2] CS 3 1† C†2 Ru M†1 CMG 2:00 from MA
BT-2A(L) ® C6†[2] CS 3 ® C6†[2] CS 3 2† C†2 Ru M†1
BT-2B ® CS 3 ® CS 3 3† Ru M†1 2 TK DR (MG)
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1943.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1943.txt
index 15e1c4b..3d4cb50 100644
--- a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1943.txt
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1943.txt
@@ -95,11 +95,11 @@ Carrier C sD5[4+]†[1] CS 3 CS 3
Carrier, MMG A sD5[4+]†[2] CS 3 CS 3 57 Br N Br P Br Q†1 Br U†2 LL
Carrier, MMG B sD5[4+]†[2] CS 4 CS 4 57 Br U†2 Br BB†1 LL
Jeep(a) cs 2 cs 2 58 H† L†1 LL
-¾-Ton Truck(a) cs 4 cs 4 Br 85 Br A Br N LL
-1½-Ton Truck(a) cs 6 cs 6 Br 85 Br A Br N LL
-2½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-7½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-DUKW cs 7†[1] cs 7†[1] US 52† US D†3 US O†2 US CC†1 LL
+¾-Ton Truck(a) cs 4 cs 4 n/a Br A Br N LL
+1½-Ton Truck(a) cs 6 cs 6 n/a Br A Br N LL
+2½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+7½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+DUKW cs 7†[1] cs 7†[1] n/a US D†3 US O†2 US CC†1 LL
BT-2A ® C5†[2] CS 3 ® C5†[2] CS 3 1† C†2 Ru M†1 CMG 2:00 from MA
BT-2A(L) ® C6†[2] CS 3 ® C6†[2] CS 3 2† C†2 Ru M†1
BT-2B ® CS 3 ® CS 3 3† Ru M†1 2 TK DR (MG)
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1944.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1944.txt
index 08f815e..b3f7e3c 100644
--- a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1944.txt
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1944.txt
@@ -95,11 +95,11 @@ Carrier C sD5[4+]†[1] CS 3 sD5†[1] C
Carrier, MMG A sD5[4+]†[2] CS 3 sD5†[2] CS 3 57 Br N Br P Br Q†1 Br U†2 LL
Carrier, MMG B sD5[4+]†[2] CS 4 sD5†[2] CS 4 57 Br U†2 Br BB†1 LL
Jeep(a) cs 2 cs 2 58 H† L†1 LL
-¾-Ton Truck(a) cs 4 cs 4 Br 85 Br A Br N LL
-1½-Ton Truck(a) cs 6 cs 6 Br 85 Br A Br N LL
-2½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-7½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-DUKW cs 7†[1] cs 7†[1] US 52† US D†3 US O†2 US CC†1 LL
+¾-Ton Truck(a) cs 4 cs 4 n/a Br A Br N LL
+1½-Ton Truck(a) cs 6 cs 6 n/a Br A Br N LL
+2½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+7½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+DUKW cs 7†[1] cs 7†[1] n/a US D†3 US O†2 US CC†1 LL
BT-2A ® C5†[2] CS 3 ® C5†[2] CS 3 1† C†2 Ru M†1 CMG 2:00 from MA
BT-2A(L) ® C6†[2] CS 3 ® C6†[2] CS 3 2† C†2 Ru M†1
BT-2B ® CS 3 ® CS 3 3† Ru M†1 2 TK DR (MG)
diff --git a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1945.txt b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1945.txt
index cc012c5..712b8fd 100644
--- a/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1945.txt
+++ b/vasl_templates/webapp/tests/fixtures/vo-reports/vehicles/russian/1945.txt
@@ -95,11 +95,11 @@ Carrier C sD5[4+]†[1] CS 3 sD5†[1] C
Carrier, MMG A sD5[4+]†[2] CS 3 sD5†[2] CS 3 57 Br N Br P Br Q†1 Br U†2 LL
Carrier, MMG B sD5[4+]†[2] CS 4 sD5†[2] CS 4 57 Br U†2 Br BB†1 LL
Jeep(a) cs 2 cs 2 58 H† L†1 LL
-¾-Ton Truck(a) cs 4 cs 4 Br 85 Br A Br N LL
-1½-Ton Truck(a) cs 6 cs 6 Br 85 Br A Br N LL
-2½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-7½-Ton Truck(a) cs 7 cs 7 Br 85 Br A Br N LL
-DUKW cs 7†[1] cs 7†[1] US 52† US D†3 US O†2 US CC†1 LL
+¾-Ton Truck(a) cs 4 cs 4 n/a Br A Br N LL
+1½-Ton Truck(a) cs 6 cs 6 n/a Br A Br N LL
+2½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+7½-Ton Truck(a) cs 7 cs 7 n/a Br A Br N LL
+DUKW cs 7†[1] cs 7†[1] n/a US D†3 US O†2 US CC†1 LL
BT-2A ® C5†[2] CS 3 ® C5†[2] CS 3 1† C†2 Ru M†1 CMG 2:00 from MA
BT-2A(L) ® C6†[2] CS 3 ® C6†[2] CS 3 2† C†2 Ru M†1
BT-2B ® CS 3 ® CS 3 3† Ru M†1 2 TK DR (MG)
diff --git a/vasl_templates/webapp/vo.py b/vasl_templates/webapp/vo.py
index 749dbf9..6e1f5e3 100644
--- a/vasl_templates/webapp/vo.py
+++ b/vasl_templates/webapp/vo.py
@@ -121,14 +121,13 @@ def _do_load_vo_listings( vo_type, merge_common, report ): #pylint: disable=too-
return listings
-def _copy_vo_entry( placeholder_vo_entry, src_vo_entry ):
+def _copy_vo_entry( placeholder_vo_entry, src_vo_entry ): #pylint: disable=too-many-branches
"""Create a new vehicle/ordnance entry by copying an existing one."""
# Anjuna, India (FEB/19)
+
# create the new vehicle/ordnance entry
new_vo_entry = copy.deepcopy( src_vo_entry )
new_vo_entry["id"] = placeholder_vo_entry["id"]
- if "note_number" in placeholder_vo_entry:
- new_vo_entry["note_number"] = placeholder_vo_entry["note_number"]
if "name" in placeholder_vo_entry:
new_vo_entry["name"] = placeholder_vo_entry["name"]
if "gpid" in placeholder_vo_entry:
@@ -137,19 +136,33 @@ def _copy_vo_entry( placeholder_vo_entry, src_vo_entry ):
if not isinstance( new_vo_entry["gpid"], list ):
new_vo_entry["gpid"] = [ new_vo_entry["gpid"] ]
new_vo_entry["gpid"].extend( placeholder_vo_entry["extra_gpids"] )
- # fixup any multi-applicable notes
- if "notes" in new_vo_entry:
- vo_id = placeholder_vo_entry[ "copy_from" ]
- if vo_id.startswith( "br/" ):
- prefix = "Br"
- elif vo_id.startswith( "am/" ):
- prefix = "US"
- else:
- logging.warning( "Unexpected vehicle/ordnance reference nationality: %s", vo_id )
- prefix = ""
+
+ # fixup any note numbers and multi-applicable notes
+ vo_id = placeholder_vo_entry[ "copy_from" ]
+ if vo_id.startswith( "br/" ):
+ prefix = "Br"
+ elif vo_id.startswith( "am/" ):
+ prefix = "US"
+ elif vo_id.startswith( "fr/" ):
+ prefix = "Fr"
+ else:
+ logging.warning( "Unexpected vehicle/ordnance reference nationality: %s", vo_id )
+ prefix = ""
+ if "note_number" in placeholder_vo_entry:
+ # replace the note# with the explicitly-defined one
+ new_vo_entry["note_number"] = placeholder_vo_entry["note_number"]
+ else:
+ # fixup the note# from the original vehicle/ordnance
+ new_vo_entry["note_number"] = "{} {}".format( prefix, new_vo_entry["note_number"] )
+ if "notes" in placeholder_vo_entry:
+ # replace the multi-applicable notes with the explicitly-defined ones
+ new_vo_entry["notes"] = placeholder_vo_entry["notes"]
+ elif "notes" in new_vo_entry:
+ # fixup the multi-applicable notes from the original vehicle/ordnance
new_vo_entry["notes"] = [ "{} {}".format( prefix, n ) for n in new_vo_entry["notes"] ]
if "extra_notes" in placeholder_vo_entry:
new_vo_entry["notes"].extend( placeholder_vo_entry["extra_notes"] )
+
return new_vo_entry
def _apply_extn_info( listings, extn_fname, extn_info, vo_index, vo_type ):
|