diff --git a/chapter-h/README.md b/chapter-h/README.md new file mode 100644 index 0000000..edc6fbb --- /dev/null +++ b/chapter-h/README.md @@ -0,0 +1,5 @@ +# Chapter H Vehicle/Ordnance notes + +*VASL Templates* supports including Chapter H notes in your VASL scenarios, but since this is copyrighted material, it is not included in releases, and you will need to set up the data yourself. + +The ZIP file in this directory contains placeholder files for the Chapter H notes, refer to the [documentation](https://rawgit.com/pacman-ghost/vasl-templates/master/vasl_templates/webapp/static/help/index.html?tab=chapterh) for instructions on how to set things up. diff --git a/chapter-h/chapter-h-placeholders.zip b/chapter-h/chapter-h-placeholders.zip new file mode 100644 index 0000000..c4b5034 Binary files /dev/null and b/chapter-h/chapter-h-placeholders.zip differ diff --git a/vasl_templates/tools/make_chapter_h_placeholders.py b/vasl_templates/tools/make_chapter_h_placeholders.py new file mode 100755 index 0000000..6f009ff --- /dev/null +++ b/vasl_templates/tools/make_chapter_h_placeholders.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +""" Create placeholder files for the Chapter H notes. """ + +import os +import zipfile +import json +import re + +import click + +# --------------------------------------------------------------------- + +@click.command() +@click.option( "--output","-o", "output_fname", help="Output ZIP file to generate." ) +def main( output_fname ): # pylint: disable=too-many-locals,too-many-branches + """Create a ZIP file with placeholder files for each Chapter H note and multi-applicable note.""" + + # initialize + if not output_fname: + raise RuntimeError( "Output ZIP file not specified." ) + if os.path.isfile( output_fname ): + raise RuntimeError( "Output ZIP file exists." ) + results = {} + + # load the vehicle/ordnance data files + base_dir = os.path.join( os.path.split(__file__)[0], "../webapp/data/" ) + for vo_type in ("vehicles","ordnance"): + dname = os.path.join( base_dir, vo_type ) + for root,_,fnames in os.walk( dname ): + for fname in fnames: + fname = os.path.join( root, fname ) + if os.path.splitext( fname )[1] != ".json": + continue + dname2, fname2 = os.path.split( fname ) + 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"): + continue + notes, ma_notes = load_vo_data( fname ) + if nat not in results: + results[ nat ] = {} + if nat == "landing-craft": + results[ nat ][ vo_type ] = { "notes": notes, "ma_notes": ma_notes } + else: + results[ nat ][ vo_type ] = { "notes": notes, "ma_notes": ma_notes } + + # generate the placeholder files + with zipfile.ZipFile( output_fname, "w" ) as zip_file: + nats = sorted( results.keys() ) + for nat in nats: #pylint: disable=too-many-nested-blocks + for vo_type in ("vehicles","ordnance"): + print( "Generating {} {}...".format( nat, vo_type ) ) + for note_type in ("notes","ma_notes"): + + # get the next set of note ID's + vals = results[nat].get( vo_type, {} ).get( note_type ) + if not vals: + continue + print( "- {}: {}".format( note_type, ", ".join( str(v) for v in vals ) ) ) + + for val in vals: + + # generate the filename for the next note placeholder + if isinstance(val, str): + # NOTE: Filenames are always lower-case, unless the note ID itself is lower-case, + # in which case we indicate this with a trailing underscore + if re.search( r"^[A-Z][A-Za-z]?$", val ): + val = val.lower() + elif re.search( r"^[a-z]{1,2}?$", val ): + val += "_" + if nat == "landing-craft": + fname = "{}/{}.{}".format( nat, val, "png" if note_type == "notes" else "html" ) + else: + fname = "{}/{}/{}.{}".format( nat, vo_type, val, "png" if note_type == "notes" else "html" ) + + # add the placeholder file to the ZIP + zip_file.writestr( fname, b"" ) + + print() + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +MA_NOTE_REGEXES = [ + re.compile( r"^([A-Z]{1,2})$" ), + re.compile( r"^([A-Z]{1,2})\u2020" ), + re.compile( r"^([a-z])$" ), + re.compile( r"^([a-z])\u2020" ), + re.compile( r"^([A-Z][a-z])$" ), + re.compile( r"^([A-Za-z])" ), + re.compile( r"^([A-Za-z])$" ), +] + +def load_vo_data( fname ): + """Load a vehicle/ordnance data file.""" + + # initialize + notes, ma_notes = set(), set() + + # load the file + vo_data = json.load( open( fname, "r" ) ) + for vo_entry in vo_data: + + # load the vehicle/ordnance's note number + mo = re.search( r"^\d+", vo_entry["note_number"] ) + notes.add( int( mo.group() ) ) + + # load the multi-applicable note ID's + for ma_note in vo_entry.get("notes",[]): + matches = [ regex.search(ma_note) for regex in MA_NOTE_REGEXES ] + matches = [ mo.group(1) for mo in matches if mo ] + assert len(matches) == 1 + ma_notes.add( matches[0] ) + + return sorted(notes), sorted(ma_notes) + +# --------------------------------------------------------------------- + +if __name__ == "__main__": + main() #pylint: disable=no-value-for-parameter diff --git a/vasl_templates/webapp/files.py b/vasl_templates/webapp/files.py index 4bff877..0e13fec 100644 --- a/vasl_templates/webapp/files.py +++ b/vasl_templates/webapp/files.py @@ -10,7 +10,7 @@ from flask import send_file, send_from_directory, jsonify, redirect, url_for, ab from vasl_templates.webapp import app from vasl_templates.webapp.file_server.vasl_mod import get_vasl_mod -from vasl_templates.webapp.utils import resize_image_response +from vasl_templates.webapp.utils import resize_image_response, is_empty_file # --------------------------------------------------------------------- @@ -23,7 +23,7 @@ class FileServer: else: self.base_dir = os.path.abspath( base_dir ) - def serve_file( self, path ): + def serve_file( self, path, ignore_empty=False ): """Serve a file.""" # NOTE: We return a Flask Response object, instead of the file data, so that (1) we can use # send_from_directory() and (2) if we have to download a file from a URL, we can include @@ -44,6 +44,8 @@ class FileServer: return send_file( buf, mimetype=mime_type ) else: path = path.replace( "\\", "/" ) # nb: for Windows :-/ + if ignore_empty and is_empty_file( os.path.join( self.base_dir, path ) ): + return None return send_from_directory( self.base_dir, path ) @staticmethod @@ -60,6 +62,8 @@ def get_user_file( path ): if not dname: abort( 404 ) resp = FileServer( dname ).serve_file( path ) + if not resp: + abort( 404 ) return resize_image_response( resp ) # --------------------------------------------------------------------- diff --git a/vasl_templates/webapp/static/help/images/chapter-h/ma-notes-snippet.png b/vasl_templates/webapp/static/help/images/chapter-h/ma-notes-snippet.png new file mode 100644 index 0000000..8e76820 Binary files /dev/null and b/vasl_templates/webapp/static/help/images/chapter-h/ma-notes-snippet.png differ diff --git a/vasl_templates/webapp/static/help/images/chapter-h/ma-notes-snippet.small.png b/vasl_templates/webapp/static/help/images/chapter-h/ma-notes-snippet.small.png new file mode 100644 index 0000000..f095b52 Binary files /dev/null and b/vasl_templates/webapp/static/help/images/chapter-h/ma-notes-snippet.small.png differ diff --git a/vasl_templates/webapp/static/help/images/chapter-h/notes-snippet.png b/vasl_templates/webapp/static/help/images/chapter-h/notes-snippet.png new file mode 100644 index 0000000..e0ecfc9 Binary files /dev/null and b/vasl_templates/webapp/static/help/images/chapter-h/notes-snippet.png differ diff --git a/vasl_templates/webapp/static/help/images/chapter-h/notes-snippet.small.png b/vasl_templates/webapp/static/help/images/chapter-h/notes-snippet.small.png new file mode 100644 index 0000000..9baeb30 Binary files /dev/null and b/vasl_templates/webapp/static/help/images/chapter-h/notes-snippet.small.png differ diff --git a/vasl_templates/webapp/static/help/images/chapter-h/psw-234.1-note74.png b/vasl_templates/webapp/static/help/images/chapter-h/psw-234.1-note74.png new file mode 100644 index 0000000..a91a83b Binary files /dev/null and b/vasl_templates/webapp/static/help/images/chapter-h/psw-234.1-note74.png differ diff --git a/vasl_templates/webapp/static/help/images/chapter-h/psw-234.1-note74.small.png b/vasl_templates/webapp/static/help/images/chapter-h/psw-234.1-note74.small.png new file mode 100644 index 0000000..95e5d69 Binary files /dev/null and b/vasl_templates/webapp/static/help/images/chapter-h/psw-234.1-note74.small.png differ diff --git a/vasl_templates/webapp/static/help/images/chapter-h/ui.png b/vasl_templates/webapp/static/help/images/chapter-h/ui.png new file mode 100644 index 0000000..00d05f9 Binary files /dev/null and b/vasl_templates/webapp/static/help/images/chapter-h/ui.png differ diff --git a/vasl_templates/webapp/static/help/images/chapter-h/ui.small.png b/vasl_templates/webapp/static/help/images/chapter-h/ui.small.png new file mode 100644 index 0000000..083093e Binary files /dev/null and b/vasl_templates/webapp/static/help/images/chapter-h/ui.small.png differ diff --git a/vasl_templates/webapp/static/help/index.html b/vasl_templates/webapp/static/help/index.html index 3fb1441..8823975 100644 --- a/vasl_templates/webapp/static/help/index.html +++ b/vasl_templates/webapp/static/help/index.html @@ -26,6 +26,7 @@