From 61b04dfa16c9630af4a239f29fb2fedb5b0d9cd7 Mon Sep 17 00:00:00 2001 From: Taka Date: Wed, 15 Jul 2020 05:37:06 +0000 Subject: [PATCH] Added snippets for National Capabilities. --- .pylintrc | 3 +- vasl_templates/main_window.py | 4 +- vasl_templates/webapp/__init__.py | 1 + .../data/default-template-pack/nat_caps.j2 | 55 +++ .../national-capabilities.json | 311 ++++++++++++++++ vasl_templates/webapp/nat_caps.py | 18 + vasl_templates/webapp/snippets.py | 5 +- .../webapp/static/css/tabs-scenario.css | 3 + vasl_templates/webapp/static/css/tabs.css | 2 +- .../webapp/static/images/nat-caps.png | Bin 0 -> 12752 bytes .../webapp/static/images/oba-info.png | Bin 0 -> 18571 bytes vasl_templates/webapp/static/main.js | 93 ++++- vasl_templates/webapp/static/nat_caps.js | 117 +++++++ vasl_templates/webapp/static/snippets.js | 177 +++++++--- vasl_templates/webapp/static/sortable.js | 4 +- vasl_templates/webapp/static/user_settings.js | 3 +- vasl_templates/webapp/static/utils.js | 40 +++ vasl_templates/webapp/static/vassal.js | 12 +- vasl_templates/webapp/templates/index.html | 1 + .../templates/national-capabilities.html | 70 ++++ .../webapp/templates/tabs-scenario.html | 9 +- .../templates/user-settings-dialog.html | 5 +- .../data/default-template-pack/nat_caps.j2 | 15 + .../national-capabilities.json | 31 ++ .../tests/fixtures/nat-caps/american/1940.txt | 12 + .../tests/fixtures/nat-caps/american/1941.txt | 12 + .../tests/fixtures/nat-caps/american/1942.txt | 12 + .../tests/fixtures/nat-caps/american/1943.txt | 12 + .../tests/fixtures/nat-caps/american/1944.txt | 12 + .../tests/fixtures/nat-caps/american/1945.txt | 12 + .../tests/fixtures/nat-caps/anzac/1940.txt | 14 + .../tests/fixtures/nat-caps/anzac/1941.txt | 14 + .../tests/fixtures/nat-caps/anzac/1942.txt | 14 + .../tests/fixtures/nat-caps/anzac/1943.txt | 14 + .../tests/fixtures/nat-caps/anzac/1944.txt | 14 + .../tests/fixtures/nat-caps/anzac/1945.txt | 14 + .../tests/fixtures/nat-caps/belgian/1940.txt | 9 + .../tests/fixtures/nat-caps/belgian/1941.txt | 9 + .../tests/fixtures/nat-caps/belgian/1942.txt | 9 + .../tests/fixtures/nat-caps/belgian/1943.txt | 9 + .../tests/fixtures/nat-caps/belgian/1944.txt | 9 + .../tests/fixtures/nat-caps/belgian/1945.txt | 9 + .../tests/fixtures/nat-caps/british/1940.txt | 14 + .../tests/fixtures/nat-caps/british/1941.txt | 14 + .../tests/fixtures/nat-caps/british/1942.txt | 14 + .../tests/fixtures/nat-caps/british/1943.txt | 14 + .../tests/fixtures/nat-caps/british/1944.txt | 14 + .../tests/fixtures/nat-caps/british/1945.txt | 14 + .../nat-caps/british~canadian/1940.txt | 14 + .../nat-caps/british~canadian/1941.txt | 14 + .../nat-caps/british~canadian/1942.txt | 14 + .../nat-caps/british~canadian/1943.txt | 14 + .../nat-caps/british~canadian/1944.txt | 14 + .../nat-caps/british~canadian/1945.txt | 14 + .../nat-caps/british~newzealand/1940.txt | 14 + .../nat-caps/british~newzealand/1941.txt | 14 + .../nat-caps/british~newzealand/1942.txt | 14 + .../nat-caps/british~newzealand/1943.txt | 14 + .../nat-caps/british~newzealand/1944.txt | 14 + .../nat-caps/british~newzealand/1945.txt | 14 + .../fixtures/nat-caps/bulgarian/1940.txt | 14 + .../fixtures/nat-caps/bulgarian/1941.txt | 14 + .../fixtures/nat-caps/bulgarian/1942.txt | 14 + .../fixtures/nat-caps/bulgarian/1943.txt | 14 + .../fixtures/nat-caps/bulgarian/1944.txt | 14 + .../fixtures/nat-caps/bulgarian/1945.txt | 14 + .../tests/fixtures/nat-caps/burmese/1940.txt | 11 + .../tests/fixtures/nat-caps/burmese/1941.txt | 11 + .../tests/fixtures/nat-caps/burmese/1942.txt | 11 + .../tests/fixtures/nat-caps/burmese/1943.txt | 11 + .../tests/fixtures/nat-caps/burmese/1944.txt | 11 + .../tests/fixtures/nat-caps/burmese/1945.txt | 11 + .../tests/fixtures/nat-caps/chinese/1940.txt | 11 + .../tests/fixtures/nat-caps/chinese/1941.txt | 11 + .../tests/fixtures/nat-caps/chinese/1942.txt | 11 + .../tests/fixtures/nat-caps/chinese/1943.txt | 11 + .../tests/fixtures/nat-caps/chinese/1944.txt | 11 + .../tests/fixtures/nat-caps/chinese/1945.txt | 11 + .../fixtures/nat-caps/chinese~gmd/1940.txt | 15 + .../fixtures/nat-caps/chinese~gmd/1941.txt | 15 + .../fixtures/nat-caps/chinese~gmd/1942.txt | 15 + .../fixtures/nat-caps/chinese~gmd/1943.txt | 15 + .../fixtures/nat-caps/chinese~gmd/1944.txt | 15 + .../fixtures/nat-caps/chinese~gmd/1945.txt | 15 + .../tests/fixtures/nat-caps/croatian/1940.txt | 14 + .../tests/fixtures/nat-caps/croatian/1941.txt | 14 + .../tests/fixtures/nat-caps/croatian/1942.txt | 14 + .../tests/fixtures/nat-caps/croatian/1943.txt | 14 + .../tests/fixtures/nat-caps/croatian/1944.txt | 14 + .../tests/fixtures/nat-caps/croatian/1945.txt | 14 + .../tests/fixtures/nat-caps/danish/1940.txt | 9 + .../tests/fixtures/nat-caps/danish/1941.txt | 9 + .../tests/fixtures/nat-caps/danish/1942.txt | 9 + .../tests/fixtures/nat-caps/danish/1943.txt | 9 + .../tests/fixtures/nat-caps/danish/1944.txt | 9 + .../tests/fixtures/nat-caps/danish/1945.txt | 9 + .../tests/fixtures/nat-caps/dutch/1940.txt | 9 + .../tests/fixtures/nat-caps/dutch/1941.txt | 9 + .../tests/fixtures/nat-caps/dutch/1942.txt | 9 + .../tests/fixtures/nat-caps/dutch/1943.txt | 9 + .../tests/fixtures/nat-caps/dutch/1944.txt | 9 + .../tests/fixtures/nat-caps/dutch/1945.txt | 9 + .../tests/fixtures/nat-caps/finnish/1940.txt | 17 + .../tests/fixtures/nat-caps/finnish/1941.txt | 17 + .../tests/fixtures/nat-caps/finnish/1942.txt | 17 + .../tests/fixtures/nat-caps/finnish/1943.txt | 17 + .../tests/fixtures/nat-caps/finnish/1944.txt | 17 + .../tests/fixtures/nat-caps/finnish/1945.txt | 21 ++ .../fixtures/nat-caps/free-french/1940.txt | 14 + .../fixtures/nat-caps/free-french/1941.txt | 14 + .../fixtures/nat-caps/free-french/1942.txt | 14 + .../fixtures/nat-caps/free-french/1943.txt | 14 + .../fixtures/nat-caps/free-french/1944.txt | 14 + .../fixtures/nat-caps/free-french/1945.txt | 14 + .../tests/fixtures/nat-caps/french/1940.txt | 6 + .../tests/fixtures/nat-caps/french/1941.txt | 6 + .../tests/fixtures/nat-caps/french/1942.txt | 6 + .../tests/fixtures/nat-caps/french/1943.txt | 6 + .../tests/fixtures/nat-caps/french/1944.txt | 6 + .../tests/fixtures/nat-caps/french/1945.txt | 6 + .../tests/fixtures/nat-caps/german/1940.txt | 12 + .../tests/fixtures/nat-caps/german/1941.txt | 12 + .../tests/fixtures/nat-caps/german/1942.txt | 12 + .../tests/fixtures/nat-caps/german/1943.txt | 12 + .../tests/fixtures/nat-caps/german/1944.txt | 12 + .../tests/fixtures/nat-caps/german/1945.txt | 12 + .../tests/fixtures/nat-caps/greek/1940.txt | 9 + .../tests/fixtures/nat-caps/greek/1941.txt | 9 + .../tests/fixtures/nat-caps/greek/1942.txt | 9 + .../tests/fixtures/nat-caps/greek/1943.txt | 9 + .../tests/fixtures/nat-caps/greek/1944.txt | 9 + .../tests/fixtures/nat-caps/greek/1945.txt | 9 + .../fixtures/nat-caps/hungarian/1940.txt | 14 + .../fixtures/nat-caps/hungarian/1941.txt | 14 + .../fixtures/nat-caps/hungarian/1942.txt | 14 + .../fixtures/nat-caps/hungarian/1943.txt | 14 + .../fixtures/nat-caps/hungarian/1944.txt | 14 + .../fixtures/nat-caps/hungarian/1945.txt | 14 + .../fixtures/nat-caps/indonesian/1940.txt | 12 + .../fixtures/nat-caps/indonesian/1941.txt | 12 + .../fixtures/nat-caps/indonesian/1942.txt | 12 + .../fixtures/nat-caps/indonesian/1943.txt | 12 + .../fixtures/nat-caps/indonesian/1944.txt | 12 + .../fixtures/nat-caps/indonesian/1945.txt | 12 + .../tests/fixtures/nat-caps/italian/1940.txt | 14 + .../tests/fixtures/nat-caps/italian/1941.txt | 14 + .../tests/fixtures/nat-caps/italian/1942.txt | 14 + .../tests/fixtures/nat-caps/italian/1943.txt | 14 + .../tests/fixtures/nat-caps/italian/1944.txt | 14 + .../tests/fixtures/nat-caps/italian/1945.txt | 14 + .../tests/fixtures/nat-caps/japanese/1940.txt | 30 ++ .../tests/fixtures/nat-caps/japanese/1941.txt | 30 ++ .../tests/fixtures/nat-caps/japanese/1942.txt | 30 ++ .../tests/fixtures/nat-caps/japanese/1943.txt | 30 ++ .../tests/fixtures/nat-caps/japanese/1944.txt | 30 ++ .../tests/fixtures/nat-caps/japanese/1945.txt | 30 ++ .../fixtures/nat-caps/kfw/american/1950.txt | 26 ++ .../fixtures/nat-caps/kfw/american/1951.txt | 29 ++ .../fixtures/nat-caps/kfw/american/1952.txt | 27 ++ .../fixtures/nat-caps/kfw/american/1953.txt | 27 ++ .../fixtures/nat-caps/kfw/british/1950.txt | 13 + .../fixtures/nat-caps/kfw/british/1951.txt | 13 + .../fixtures/nat-caps/kfw/british/1952.txt | 14 + .../fixtures/nat-caps/kfw/british/1953.txt | 14 + .../fixtures/nat-caps/kfw/kfw-cpva/1950.txt | 25 ++ .../fixtures/nat-caps/kfw/kfw-cpva/1951.txt | 26 ++ .../fixtures/nat-caps/kfw/kfw-cpva/1952.txt | 25 ++ .../fixtures/nat-caps/kfw/kfw-cpva/1953.txt | 25 ++ .../fixtures/nat-caps/kfw/kfw-kpa/1950.txt | 21 ++ .../fixtures/nat-caps/kfw/kfw-kpa/1951.txt | 21 ++ .../fixtures/nat-caps/kfw/kfw-kpa/1952.txt | 21 ++ .../fixtures/nat-caps/kfw/kfw-kpa/1953.txt | 21 ++ .../fixtures/nat-caps/kfw/kfw-ounc/1950.txt | 9 + .../fixtures/nat-caps/kfw/kfw-ounc/1951.txt | 9 + .../fixtures/nat-caps/kfw/kfw-ounc/1952.txt | 9 + .../fixtures/nat-caps/kfw/kfw-ounc/1953.txt | 9 + .../fixtures/nat-caps/kfw/kfw-rok/1950.txt | 17 + .../fixtures/nat-caps/kfw/kfw-rok/1951.txt | 17 + .../fixtures/nat-caps/kfw/kfw-rok/1952.txt | 15 + .../fixtures/nat-caps/kfw/kfw-rok/1953.txt | 15 + .../tests/fixtures/nat-caps/polish/1940.txt | 9 + .../tests/fixtures/nat-caps/polish/1941.txt | 9 + .../tests/fixtures/nat-caps/polish/1942.txt | 9 + .../tests/fixtures/nat-caps/polish/1943.txt | 9 + .../tests/fixtures/nat-caps/polish/1944.txt | 9 + .../tests/fixtures/nat-caps/polish/1945.txt | 9 + .../tests/fixtures/nat-caps/romanian/1940.txt | 14 + .../tests/fixtures/nat-caps/romanian/1941.txt | 14 + .../tests/fixtures/nat-caps/romanian/1942.txt | 14 + .../tests/fixtures/nat-caps/romanian/1943.txt | 14 + .../tests/fixtures/nat-caps/romanian/1944.txt | 14 + .../tests/fixtures/nat-caps/romanian/1945.txt | 14 + .../tests/fixtures/nat-caps/russian/1940.txt | 13 + .../tests/fixtures/nat-caps/russian/1941.txt | 13 + .../tests/fixtures/nat-caps/russian/1942.txt | 13 + .../tests/fixtures/nat-caps/russian/1943.txt | 13 + .../tests/fixtures/nat-caps/russian/1944.txt | 13 + .../tests/fixtures/nat-caps/russian/1945.txt | 13 + .../fixtures/nat-caps/slovakian/1940.txt | 14 + .../fixtures/nat-caps/slovakian/1941.txt | 14 + .../fixtures/nat-caps/slovakian/1942.txt | 14 + .../fixtures/nat-caps/slovakian/1943.txt | 14 + .../fixtures/nat-caps/slovakian/1944.txt | 14 + .../fixtures/nat-caps/slovakian/1945.txt | 14 + .../tests/fixtures/nat-caps/thai/1940.txt | 6 + .../tests/fixtures/nat-caps/thai/1941.txt | 6 + .../tests/fixtures/nat-caps/thai/1942.txt | 6 + .../tests/fixtures/nat-caps/thai/1943.txt | 6 + .../tests/fixtures/nat-caps/thai/1944.txt | 6 + .../tests/fixtures/nat-caps/thai/1945.txt | 6 + .../fixtures/nat-caps/yugoslavian/1940.txt | 9 + .../fixtures/nat-caps/yugoslavian/1941.txt | 9 + .../fixtures/nat-caps/yugoslavian/1942.txt | 9 + .../fixtures/nat-caps/yugoslavian/1943.txt | 9 + .../fixtures/nat-caps/yugoslavian/1944.txt | 9 + .../fixtures/nat-caps/yugoslavian/1945.txt | 9 + .../fixtures/template-packs/full/nat_caps.j2 | 1 + .../template-packs/new-default/nat_caps.j2 | 1 + .../tests/test_national_capabilities.py | 331 ++++++++++++++++++ .../webapp/tests/test_template_packs.py | 7 +- vasl_templates/webapp/tests/utils.py | 10 +- vassal-shim/release/vassal-shim.jar | Bin 30041 -> 30053 bytes vassal-shim/src/vassal_shim/VassalShim.java | 4 +- 223 files changed, 3828 insertions(+), 75 deletions(-) create mode 100644 vasl_templates/webapp/data/default-template-pack/nat_caps.j2 create mode 100644 vasl_templates/webapp/data/default-template-pack/national-capabilities.json create mode 100644 vasl_templates/webapp/nat_caps.py create mode 100644 vasl_templates/webapp/static/images/nat-caps.png create mode 100644 vasl_templates/webapp/static/images/oba-info.png create mode 100644 vasl_templates/webapp/static/nat_caps.js create mode 100644 vasl_templates/webapp/templates/national-capabilities.html create mode 100644 vasl_templates/webapp/tests/fixtures/data/default-template-pack/nat_caps.j2 create mode 100644 vasl_templates/webapp/tests/fixtures/data/default-template-pack/national-capabilities.json create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/american/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/american/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/american/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/american/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/american/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/american/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/anzac/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/anzac/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/anzac/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/anzac/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/anzac/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/anzac/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/belgian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/belgian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/belgian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/belgian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/belgian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/belgian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~canadian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~canadian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~canadian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~canadian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~canadian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~canadian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~newzealand/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~newzealand/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~newzealand/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~newzealand/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~newzealand/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/british~newzealand/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/bulgarian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/bulgarian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/bulgarian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/bulgarian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/bulgarian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/bulgarian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/burmese/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/burmese/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/burmese/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/burmese/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/burmese/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/burmese/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese~gmd/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese~gmd/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese~gmd/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese~gmd/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese~gmd/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/chinese~gmd/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/croatian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/croatian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/croatian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/croatian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/croatian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/croatian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/danish/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/danish/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/danish/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/danish/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/danish/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/danish/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/dutch/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/dutch/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/dutch/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/dutch/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/dutch/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/dutch/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/finnish/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/finnish/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/finnish/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/finnish/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/finnish/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/finnish/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/free-french/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/free-french/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/free-french/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/free-french/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/free-french/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/free-french/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/french/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/french/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/french/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/french/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/french/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/french/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/german/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/german/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/german/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/german/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/german/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/german/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/greek/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/greek/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/greek/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/greek/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/greek/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/greek/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/hungarian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/hungarian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/hungarian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/hungarian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/hungarian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/hungarian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/indonesian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/indonesian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/indonesian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/indonesian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/indonesian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/indonesian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/italian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/italian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/italian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/italian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/italian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/italian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/japanese/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/japanese/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/japanese/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/japanese/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/japanese/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/japanese/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/american/1950.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/american/1951.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/american/1952.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/american/1953.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/british/1950.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/british/1951.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/british/1952.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/british/1953.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-cpva/1950.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-cpva/1951.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-cpva/1952.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-cpva/1953.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-kpa/1950.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-kpa/1951.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-kpa/1952.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-kpa/1953.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-ounc/1950.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-ounc/1951.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-ounc/1952.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-ounc/1953.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-rok/1950.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-rok/1951.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-rok/1952.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/kfw/kfw-rok/1953.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/polish/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/polish/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/polish/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/polish/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/polish/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/polish/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/romanian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/romanian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/romanian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/romanian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/romanian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/romanian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/russian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/russian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/russian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/russian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/russian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/russian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/slovakian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/slovakian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/slovakian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/slovakian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/slovakian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/slovakian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/thai/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/thai/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/thai/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/thai/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/thai/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/thai/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/yugoslavian/1940.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/yugoslavian/1941.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/yugoslavian/1942.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/yugoslavian/1943.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/yugoslavian/1944.txt create mode 100644 vasl_templates/webapp/tests/fixtures/nat-caps/yugoslavian/1945.txt create mode 100644 vasl_templates/webapp/tests/fixtures/template-packs/full/nat_caps.j2 create mode 100644 vasl_templates/webapp/tests/fixtures/template-packs/new-default/nat_caps.j2 create mode 100644 vasl_templates/webapp/tests/test_national_capabilities.py diff --git a/.pylintrc b/.pylintrc index 65626e0..21e1e15 100644 --- a/.pylintrc +++ b/.pylintrc @@ -142,7 +142,8 @@ disable=print-statement, too-few-public-methods, too-many-lines, duplicate-code, # can't get it to shut up about @pytest.mark.skipif's :-/ - no-else-return + no-else-return, + len-as-condition # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/vasl_templates/main_window.py b/vasl_templates/main_window.py index 2919aff..9652abe 100644 --- a/vasl_templates/main_window.py +++ b/vasl_templates/main_window.py @@ -86,8 +86,8 @@ class MainWindow( QWidget ): if val : self.restoreGeometry( val ) else : - self.resize( 1000, 600 ) - self.setMinimumSize( 1000, 520 ) + self.resize( 1050, 650 ) + self.setMinimumSize( 1000, 595 ) # initialize the layout layout = QVBoxLayout( self ) diff --git a/vasl_templates/webapp/__init__.py b/vasl_templates/webapp/__init__.py index a0ba415..47ac733 100644 --- a/vasl_templates/webapp/__init__.py +++ b/vasl_templates/webapp/__init__.py @@ -97,6 +97,7 @@ import vasl_templates.webapp.snippets #pylint: disable=cyclic-import import vasl_templates.webapp.files #pylint: disable=cyclic-import import vasl_templates.webapp.vassal #pylint: disable=cyclic-import import vasl_templates.webapp.vo_notes #pylint: disable=cyclic-import +import vasl_templates.webapp.nat_caps #pylint: disable=cyclic-import import vasl_templates.webapp.roar #pylint: disable=cyclic-import if app.config.get( "ENABLE_REMOTE_TEST_CONTROL" ): print( "*** WARNING: Remote test control enabled! ***" ) diff --git a/vasl_templates/webapp/data/default-template-pack/nat_caps.j2 b/vasl_templates/webapp/data/default-template-pack/nat_caps.j2 new file mode 100644 index 0000000..af5fd7d --- /dev/null +++ b/vasl_templates/webapp/data/default-template-pack/nat_caps.j2 @@ -0,0 +1,55 @@ + + + + + + + + + +
+ {{INCLUDE:player_flag}}{{PLAYER_NAME|nbsp}} Capabilities + +
+ +{%if NAT_CAPS%} + +
    +{%if NAT_CAPS.GRENADES%}
  • {{NAT_CAPS.GRENADES}} {%endif%} +{%if NAT_CAPS.HOB_DRM%}
  • Heat of Battle: {{NAT_CAPS.HOB_DRM}} {%endif%} +{%if NAT_CAPS.TH_COLOR%}
  • {{NAT_CAPS.TH_COLOR}} {%endif%} +{%if NAT_CAPS.OBA_BLACK%} +
  • OBA: {{NAT_CAPS.OBA_BLACK}} {{NAT_CAPS.OBA_RED}} + {%if NAT_CAPS.OBA_ACCESS%} (access: {{NAT_CAPS.OBA_ACCESS}}) {%endif%} + + {%if NAT_CAPS.OBA_COMMENTS%} +
      {%for cmt in NAT_CAPS.OBA_COMMENTS%}
    • {{cmt}} {%endfor%}
    + {%endif%} +{%endif%} +
+ +{%if NAT_CAPS.NOTES%} +
    {%for note in NAT_CAPS.NOTES%} +
  • {{note}} +{%endfor%}
+{%endif%} + +{%else%} + +Not available. + +{%endif%} + +
+ + diff --git a/vasl_templates/webapp/data/default-template-pack/national-capabilities.json b/vasl_templates/webapp/data/default-template-pack/national-capabilities.json new file mode 100644 index 0000000..6eaa55a --- /dev/null +++ b/vasl_templates/webapp/data/default-template-pack/national-capabilities.json @@ -0,0 +1,311 @@ +{ + +"german": { + "th_color": "Black", + "oba": [ "8B", "3R" ], "oba_access": "≤ 2", + "hob_drm": "0 DRM", + "grenades": "Smoke", + "notes": [ + "{? 10/1943- | Inherent PF | No Inherent PF | Inherent PF (10/43+) ?}", + "{? 01/1944- | Inherent ATMM | No Inherent ATMM | Inherent ATMM (44+) ?}", + "SS: Disrupt & RtPh Surrender NA vs Russians", + "Massacre OK", + "{? 01/1944- | Squad Assault Fire | No Squad Assault Fire | Squad Assault Fire (44+) ?}" + ] +}, + +"russian": { + "th_color": "Red", + "oba": [ "5B", "2R" ], "oba_access": "≤ 1", + "hob_drm": "+2 DRM", + "grenades": null, + "notes": [ + "Massacre OK", + "Deploy NA", + "Entrench -1 DRM", + "{? 11/1942- | Commissars NA | Commissars | Commissars (pre-11/42) ?}", + "Human Wave", + "{? 01/1942- | Riders OK | Riders NA | Riders (42+) ?}" + ] +}, + +"american": { + "th_color": "{? 01/1944- | Black | Red | Black (44+) ?}", + "oba": [ "10B", "3R", "Plentiful Ammo included" ], + "oba_access": "≤ 2", + "hob_drm": "0 DRM", + "grenades": "SMOKE", + "notes": [ + "U.S.M.C.: " + ] +}, +"kfw-american": { + "th_color": "{! 06/1950-08/1950 = Red | 09/1950- = Black | ??? !}", + "oba": [ "{! 06/1950-08/1950 = 9B | 09/1950- = 10B | ??? !}", "3R", + "{! 09/1950- = Plentiful Ammo included !}" + ], + "oba_access": "≤ 2", + "hob_drm": [ "0 DRM", "+3 for Katusa; NA for TACP" ], + "grenades": "SMOKE", + "notes": [ + "Rangers: 6-6-8 ", + "Airborne: 6-6-7", + "{! 06/1950-08/1950 = Early KW U.S. Army rules: !}", + "Katusa: As U.S. Army MMC ", + "Disruption NA", + "7-6-8 can Self-Deploy", + "Use 5-5-8 when: ", + "Tactical Air Control Party: " + ] +}, + +"british": { + "th_color": "Black", + "oba": [ "8B", "2R" ], "oba_access": "≤ 2", + "hob_drm": "-1 DRM", + "grenades": "{? 01/1944- | SMOKE | Smoke | SMOKE (44+) ?}", + "notes": [ + "Elite & 1st Line: Cowering NA", + "ANZAC: Stealthy (unless Green)", + "Gurkha: " + ] +}, + +"french": { + "th_color": [ "Black", "AFV use Red TH#" ], + "oba": [ "6B", "2R" ], "oba_access": "≤ 1", + "hob_drm": "+1 DRM", + "grenades": "Smoke", + "notes": [] +}, + +"italian": { + "th_color": "Red", + "oba": [ "7B", "3R" ], "oba_access": "≤ 1", + "hob_drm": "+3 DRM", + "grenades": "Smoke", + "notes": [ + "Escape NA", + "1st Line & Conscript: " + ] +}, + +"finnish": { + "th_color": "Red", + "oba": [ + "{! 01/1939-12/1940 = 6B | 01/1941-12/1942 = 7B | 01/1943-09/1944 = 8B | 10/1944- = 7B | ??? !}", + "3R", + "Plentiful Ammo included" + ], + "oba_access": "≤ 1", + "hob_drm": "-1 DRM", + "grenades": null, + "notes": [ + "Deploy (1TC) & Recombine without Leader", + "Self-Rally OK [EXC: Conscript]", + "Cowering NA [EXC: Conscript]", + "Elite & 1st Line: ", + "Ski-trained (don Skis = one MF)", + "Leader Creation NA", + "Captured Use penalties NA for Russian MG [EXC: LMG in 1939; .50-cal]" + ] +}, + +"axis-minor": { + "th_color": "Red", + "oba": [ "6B", "3R" ], "oba_access": "≤ 1", + "hob_drm": "+3 DRM", + "grenades": "Smoke", + "notes": [ + "Escape NA", + "1st Line & Conscript: ", + "Inherent PF in non-Crew MMC (Romanian 3/44+; Hungarian 6/44+): ", + "{? 07/1943- | Inherent ATMM in Romanian non-Crew Elite & 1st Line MMC (-2 CC DRM) | No Inherent ATMM | Inherent ATMM (7/43+) ?}" + ] +}, + +"allied-minor": { + "th_color": "Red", + "oba": [ "6B", "3R" ], "oba_access": "≤ 1", + "hob_drm": "+2 DRM", + "grenades": "Smoke", + "notes": [ + "+1 Broken Morale vs Italians", + "1st Line & Green: 1 PAATC" + ] +}, + +"japanese": { + "th_color": "Black", + "oba": [ "5B", "2R" ], "oba_access": "≤ 1", + "hob_drm": "+4 DRM", + "grenades": "SMOKE", + "notes": [ + "SMC PTC/Pin/Break NA", + "Leaders: ", + "Tank-Hunter Heroes & ATMM", + "Banzai Charge (always Lax)", + "Elite & 1st Line: Always Stealthy", + "Conscript: Always Lax", + "ATR/MMG/HMG Breakdown penalty", + "Always NA: ", + "LLMC → LLTC if unbroken", + "Massacre OK", + "-1 Interrogation DRM", + "-2 Concealment drm", + "Enemy +2 search drm", + "Hand-to-Hand CC & Hara-Kiri" + ] +}, + +"chinese~gmd": { + "th_color": "Red", + "oba": [ "5B", "2R", + "6B/2R if Majority Squad Type is 5-3-7", + "5B/3R if Majority Squad Type is 3-3-7 or 3-3-6" + ], + "oba_access": "≤ 1", + "hob_drm": "0 DRM", + "grenades": "SMOKE", + "notes": [ + "Deploy NA", + "Lax at Night", + "+1 Leader Creation drm", + "1st Line & Conscript: 1 PAATC", + "Human Wave", + "Dare-Death Squads [EXC: 5-3-7]" + ] +}, + +"chinese": { + "th_color": "Red", + "oba": null, + "hob_drm": "+1 DRM", + "grenades": null, + "notes": [ + "Cowering NA", + "Commissars", + "Human Wave", + "Dare-Death Squads" + ] +}, + +"kfw-rok": { + "th_color": "{! -08/1950 = Red | 09/1950-04/1951 = Red (ROK) ; Black (KMC) | 05/1951- = Black | ??? !}", + "oba": [ "{! 06/1950- = 10B | ??? !}", "3R", + "{! 09/1950- = Plentiful Ammo included !}", + "{! 06/1950-08/1950 = ROK: 6B/3R !}" + ], + "oba_access": "≤ 1 (ROK) ; 2 (KMC)", + "hob_drm": "+3/+4 DRM", + "grenades": "SMOKE", + "notes": [ + "Republic of Korea (ROK): ", + "Korean Marine Corps (KMC): " + ] +}, + +"kfw-bcfk": { + "th_color": "Black", + "oba": [ "8B", "2R" ], "oba_access": "≤ 2", + "hob_drm": "-1 DRM", + "grenades": "SMOKE", + "notes": [ + "2nd Line MMC: ELR Replacement → Disrupt", + "{? 01/1952- | Canadian squads have Assault Fire | | Canadian squads have Assault Fire (1/52+) ?}", + "Royal Marines: " + ] +}, + +"kfw-ounc": { + "th_color": "Black", + "oba": [ "9B", "3R" ], "oba_access": "≤ 1", + "hob_drm": [ "0 DRM", "+3 for Turkish" ], + "grenades": "SMOKE", + "notes": [ + "2nd Line MMC: ELR Replacement → Disrupt [EXC: Turkish]", + "Bayonet Charge NTC NA for Ethiopian, French, Turkish leaders" + ] +}, + +"kfw-kpa": { + "th_color": "Red", + "oba": [ "5B", "2R" ], "oba_access": "≤ 1", + "hob_drm": "+2 DRM", + "grenades": null, + "notes": [ + "As Russian ", + "Suicide Heroes", + "Starshell restrictions", + "Assault Engineers: WP grenades", + "Communist Partisans: " + ] +}, + +"kfw-cpva": { + "th_color": "Red", + "oba": [ + "{? 04/1951- | 7B | | 7B (4/51+) ?}", + "{! 04/1951-09/1952 = 3R | 10/1952- = 2R | ??? !}" + ], + "oba_access": "≤ 1", + "hob_drm": "+1 DRM", + "grenades": null, + "notes": [ + "Always Stealthy", + "Starshell restrictions", + "Armored Assault NA", + "Riders NA", + "Assault Engineers: WP grenades", + "{! 10/1950-03/1951 = Early KW CPVA rules !}", + "Leaders & Political Officers increase Morale as if Commissar", + "SW B#/X#/ROF penalty", + "Restricted Fire", + "Infantry Platoon Movement", + "Hand-to-Hand CC (-1 DRM)", + "HS Infantry Overrun", + "Bugles", + "Entrench -1 DRM", + "PAATC NTC NA", + "Infantry Overrun NTC NA", + "Conceal if +2 Hindrance", + "Concealment -1 drm", + "Civilian Interrogation is always in effect" + ] +}, + +"burmese": { + "th_color": "Red", + "oba": null, + "hob_drm": "+2 DRM", + "grenades": null, + "notes": [ + "Dare-Death Squads (as if Chinese)", + "Elite and 1st Line MMC: Always Stealthy", + "Deploy NA [EXC: A20.5 & A21.22]; Recombine OK", + "Leaders: Morale/Berserk/Rally as Commissar" + ] +}, + +"indonesian": { + "th_color": "Red", + "oba": [ "5B", "3R" ], + "hob_drm": "+3 DRM", + "grenades": "Smoke", + "notes": [ + "Tank-Hunter/DC Heroes (as if 1945 Japanese)", + "Hand-to-Hand Combat", + "Massacre OK", + "HoB DR ≥ 12 → Berserk", + "Deploy NA [EXC: A20.5 & A21.22]; Recombine OK" + ] +}, + +"thai": { + "th_color": "Black", + "oba": [ "7B", "3R" ], + "hob_drm": "0 DRM", + "grenades": "Smoke" +} + +} diff --git a/vasl_templates/webapp/nat_caps.py b/vasl_templates/webapp/nat_caps.py new file mode 100644 index 0000000..f504171 --- /dev/null +++ b/vasl_templates/webapp/nat_caps.py @@ -0,0 +1,18 @@ +""" Main webapp handlers. """ + +from flask import render_template + +from vasl_templates.webapp import app + +# --------------------------------------------------------------------- + +@app.route( "/national-capabilities///", defaults={"month":1} ) +@app.route( "/national-capabilities////" ) +def get_national_capabilities( nat, theater, year, month ): + """Get the national capabilities snippet.""" + return render_template( "national-capabilities.html", + NATIONALITY = nat, + THEATER = theater, + YEAR = year, + MONTH = month + ) diff --git a/vasl_templates/webapp/snippets.py b/vasl_templates/webapp/snippets.py index 5ea6799..419e14b 100644 --- a/vasl_templates/webapp/snippets.py +++ b/vasl_templates/webapp/snippets.py @@ -44,9 +44,10 @@ def load_default_template_pack(): #pylint: disable=too-many-locals "default-template-pack/" ) data = { "templates": {} } - fname = os.path.join( base_dir, "nationalities.json" ) - with open(fname,"r") as fp: + with open( os.path.join( base_dir, "nationalities.json" ), "r") as fp: data["nationalities"] = json.load( fp ) + with open( os.path.join( base_dir, "national-capabilities.json" ), "r" ) as fp: + data["national-capabilities"] = json.load( fp ) # NOTE: Similarly, we always load the default extras templates, and user-defined template packs # can add to them, or modify existing ones, but not remove them. diff --git a/vasl_templates/webapp/static/css/tabs-scenario.css b/vasl_templates/webapp/static/css/tabs-scenario.css index bab3952..bae2f7c 100644 --- a/vasl_templates/webapp/static/css/tabs-scenario.css +++ b/vasl_templates/webapp/static/css/tabs-scenario.css @@ -16,6 +16,9 @@ #panel-scenario label.header { font-weight: bold ; width: 3em ; text-align: center ; } #panel-scenario input { margin-bottom: 0.25em ; } +#panel-scenario #oba-info { height: 1em ; } +.oba-info-tooltip { max-width: 500px ; } + #panel-scenario .select2-container { margin: 2px ; } #panel-scenario .select2-selection__rendered { height: 23px ; line-height: 23px ; } #panel-scenario .select2-selection__arrow { margin-top: -2px ; } diff --git a/vasl_templates/webapp/static/css/tabs.css b/vasl_templates/webapp/static/css/tabs.css index 19c3454..4317ba0 100644 --- a/vasl_templates/webapp/static/css/tabs.css +++ b/vasl_templates/webapp/static/css/tabs.css @@ -19,7 +19,7 @@ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #tabs-scenario { display: flex ; } -#tabs-scenario .left { width: 33.5em ; min-width: 33.5em ; } +#tabs-scenario .left { width: 32em ; min-width: 32em ; } #tabs-scenario .right { flex-grow: 1 ; min-width: 25em ; } #tabs-scenario .left { display: flex ; flex-direction: column ; } diff --git a/vasl_templates/webapp/static/images/nat-caps.png b/vasl_templates/webapp/static/images/nat-caps.png new file mode 100644 index 0000000000000000000000000000000000000000..8b0a0ba9365ccfc29c06e5fbedc89e516743a51e GIT binary patch literal 12752 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�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 literal 0 HcmV?d00001 diff --git a/vasl_templates/webapp/static/main.js b/vasl_templates/webapp/static/main.js index a48a7b7..e0622db 100644 --- a/vasl_templates/webapp/static/main.js +++ b/vasl_templates/webapp/static/main.js @@ -137,6 +137,12 @@ $(document).ready( function () { onClose: on_scenario_date_change, } ) ; + // initialize the OBA INFO tooltip + $( "#oba-info" ).tooltip( { + tooltipClass: "oba-info-tooltip", + content: make_oba_info_tooltip, + } ) ; + // initialize the SSR's $("#ssr-sortable").sortable2( "init", { add: add_ssr, edit: edit_ssr @@ -394,6 +400,8 @@ $(document).ready( function () { template_id = "ob_vehicles" ; else if ( template_id.substring(0,12) === "ob_ordnance_" ) template_id = "ob_ordnance" ; + else if ( template_id.substring(0,9) === "nat_caps_" ) + template_id = "nat_caps" ; $( "" @@ -415,14 +423,16 @@ function init_snippet_button( $btn ) var template_id2 ; if ( template_id.substring(0,9) === "ob_setup_" ) template_id2 = "ob_setup" ; - else if ( template_id.substring(0,21) == "ob_vehicles_ma_notes_" ) + else if ( template_id.substring(0,21) === "ob_vehicles_ma_notes_" ) template_id2 = "ob_vehicles_ma_notes" ; - else if ( template_id.substring(0,21) == "ob_ordnance_ma_notes_" ) + else if ( template_id.substring(0,21) === "ob_ordnance_ma_notes_" ) template_id2 = "ob_ordnance_ma_notes" ; - else if ( template_id.substring(0,12) == "ob_vehicles_" ) + else if ( template_id.substring(0,12) === "ob_vehicles_" ) template_id2 = "ob_vehicles" ; - else if ( template_id.substring(0,12) == "ob_ordnance_" ) + else if ( template_id.substring(0,12) === "ob_ordnance_" ) template_id2 = "ob_ordnance" ; + else if ( template_id.substring(0,9) === "nat_caps_" ) + template_id2 = "nat_caps" ; else template_id2 = template_id ; @@ -435,12 +445,18 @@ function init_snippet_button( $btn ) "" ] ; var $newBtn = $( buf.join("") ) ; - $newBtn.find( "button" ).prepend( - $( "" ) - ).click( function( evt ) { - generate_snippet( $(this), evt, null ) ; - return false ; - } ).attr( "title", GENERATE_SNIPPET_HINT ) ; + var fname="snippet.png", style="" ; + if ( template_id.substring( 0, 9 ) === "nat_caps_" ) { + fname = "nat-caps.png" ; + style = "height:15px;margin-right:0;" ; + } + $newBtn.find( "button" ) + .prepend( $( "" ) ) + .click( function( evt ) { + generate_snippet( $(this), evt, null ) ; + return false ; + } ) + .attr( "title", GENERATE_SNIPPET_HINT ) ; // add in the droplist $newBtn.controlgroup() ; @@ -514,6 +530,10 @@ function update_page_load_status( id ) $("#tabs").tabs({ disabled: [] }) ; $("#loader").fadeOut( 500 ) ; adjust_footer_vspacers() ; + // position the PLAYERS snippet button + var $btn = $( ".snippet-control[data-id='players']" ) ; + var $sel = $( ".select2[name='PLAYER_2_SAN']" ) ; + $btn.offset( { left: $sel.offset().left + $sel.outerWidth() - $btn.outerWidth() } ) ; // NOTE: The watermark image appears briefly in IE when reloading the page, but not even // creating the watermark dynamically and removing it when the page unloads fixes it :-( $("#watermark").fadeIn( 5*1000 ) ; @@ -717,6 +737,49 @@ function on_player_change( player_no ) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +function make_oba_info_tooltip() +{ + // initialize + var buf = [ "" ] ; + buf.push( "", "" ) ; + var player_nat = $( "select[name='PLAYER_" + player_no + "']" ).val() ; + var display_name = get_nationality_display_name( player_nat ) ; + buf.push( "", "
Off-Board Artillery" ) ; + + // initialize + var params = { + SCENARIO_THEATER: $( "select.param[name='SCENARIO_THEATER']" ).val() + } ; + var scenario_date = get_scenario_date() ; + if ( scenario_date ) { + params.SCENARIO_MONTH = 1 + scenario_date.getMonth() ; + params.SCENARIO_YEAR = scenario_date.getFullYear() ; + } + + // add the OBA info for each player + for ( var player_no=1 ; player_no <= 2 ; ++player_no ) { + buf.push( "
", display_name+":" ) ; + set_nat_caps_params( player_nat, params ) ; + if ( ! params.NAT_CAPS ) + params.NAT_CAPS = { OBA_BLACK: "-", OBA_RED: "-" } ; + buf.push( "" ) ; + var colors = [ "BLACK", "RED" ] ; + for ( var i=0 ; i < colors.length ; ++i ) { + var val = params.NAT_CAPS[ "OBA_"+colors[i] ] || "-" ; + buf.push( "", val, "" ) ; + } + if ( params.NAT_CAPS.OBA_COMMENTS ) { + for ( i=0 ; i < params.NAT_CAPS.OBA_COMMENTS.length ; ++i ) + buf.push( "
", "", params.NAT_CAPS.OBA_COMMENTS[i] ) ; + } + } + + buf.push( "
" ) ; + return buf.join( "" ) ; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + function update_ob_tab_header( player_no ) { // update the OB tab header for the specified player @@ -741,6 +804,7 @@ function update_nationality_specific_buttons( player_no ) var theater = $( "select.param[name='SCENARIO_THEATER']" ).val().toLowerCase() ; // hide/show each nationality-specific button + var $elem ; for ( var button_id in NATIONALITY_SPECIFIC_BUTTONS ) { var show = false ; for ( var i=0 ; i < NATIONALITY_SPECIFIC_BUTTONS[button_id].length ; ++i ) { @@ -755,9 +819,16 @@ function update_nationality_specific_buttons( player_no ) show = nat.substr(0,pos) == player_nat && nat.substr(pos+1) !== theater ; } } - var $elem = $( "#panel-ob_notes_" + player_no + " div.snippet-control[data-id='" + button_id + "']" ) ; + $elem = $( "#panel-ob_notes_" + player_no + " div.snippet-control[data-id='" + button_id + "']" ) ; $elem.css( "display", show ? "inline-block" : "none" ) ; } + + // update the CAPABILITIES button + var $btn = $( "button.generate[data-id='nat_caps_" + player_no + "']" ) ; + if ( get_national_capabilities( player_nat ) ) + $btn.removeClass( "inactive" ) ; + else + $btn.addClass( "inactive" ) ; } // -------------------------------------------------------------------- diff --git a/vasl_templates/webapp/static/nat_caps.js b/vasl_templates/webapp/static/nat_caps.js new file mode 100644 index 0000000..9462232 --- /dev/null +++ b/vasl_templates/webapp/static/nat_caps.js @@ -0,0 +1,117 @@ +// -------------------------------------------------------------------- + +function set_nat_caps_params( player_nat, params ) +{ + // get the national capabilities + var is_kfw = params.SCENARIO_THEATER == "Korea" ; + var nat_caps = get_national_capabilities( player_nat, is_kfw ) ; + if ( ! nat_caps ) + return ; + + // initialize + params.NAT_CAPS = {} ; + var excRegex = new RegExp( /\[EXC: .*?\]/g ) ; + var val ; + + function add_nat_cap( key, val ) { + if ( val !== undefined ) + params.NAT_CAPS[ key ] = val ; + } + function fixup_content( val ) { + val = strReplaceAll( val, "1st", "1st" ) ; + val = strReplaceAll( val, "2nd", "2nd" ) ; + return wrapSubstrings( val, excRegex, "", "" ) ; + } + + // set the TH# color + if ( nat_caps.th_color ) { + if ( $.isArray( nat_caps.th_color ) ) { + add_nat_cap( "TH_COLOR", + make_time_based_comment( nat_caps.th_color[0], params.SCENARIO_MONTH, params.SCENARIO_YEAR ) + " TH#" + + " (" + nat_caps.th_color[1] + ")" + ) ; + } else { + var th_color = make_time_based_comment( nat_caps.th_color, params.SCENARIO_MONTH, params.SCENARIO_YEAR ) ; + var match = th_color.match( /\(.+\)$/ ) ; + if ( match ) + th_color = th_color.substring(0,match.index) + "TH# " + match[0] ; + else + th_color += " TH#" ; + add_nat_cap( "TH_COLOR", th_color ) ; + } + } + + // set the HoB DRM + if ( nat_caps.hob_drm ) { + if ( $.isArray( nat_caps.hob_drm ) ) { + add_nat_cap( "HOB_DRM", + nat_caps.hob_drm[0] + + " (" + nat_caps.hob_drm[1] + ")" + ) ; + } else { + add_nat_cap( "HOB_DRM", nat_caps.hob_drm ) ; + } + } + + // set the type of grenades available + if ( nat_caps.grenades !== undefined ) { + val = (nat_caps.grenades === null) ? "No" : make_time_based_comment( nat_caps.grenades, params.SCENARIO_MONTH, params.SCENARIO_YEAR ) ; + add_nat_cap( "GRENADES", val+" grenades" ) ; + } + + // set the OBA red/black numbers + if ( nat_caps.oba ) { + params.NAT_CAPS.OBA_BLACK = make_time_based_comment( nat_caps.oba[0], params.SCENARIO_MONTH, params.SCENARIO_YEAR ) ; + params.NAT_CAPS.OBA_RED = make_time_based_comment( nat_caps.oba[1], params.SCENARIO_MONTH, params.SCENARIO_YEAR ) ; + if ( nat_caps.oba.length > 2 ) { + var oba_comments = [] ; + for ( i=2 ; i < nat_caps.oba.length ; ++i ) { + val = make_time_based_comment( nat_caps.oba[i], params.SCENARIO_MONTH, params.SCENARIO_YEAR ) ; + if ( val ) + oba_comments.push( val ) ; + } + if ( oba_comments.length > 0 ) + params.NAT_CAPS.OBA_COMMENTS = oba_comments ; + } + } + + // set the OBA access number + add_nat_cap( "OBA_ACCESS", nat_caps.oba_access ) ; + + // add any additional notes + if ( nat_caps.notes ) { + params.NAT_CAPS.NOTES = [] ; + for ( i=0 ; i < nat_caps.notes.length ; ++i ) { + val = make_time_based_comment( nat_caps.notes[i], params.SCENARIO_MONTH, params.SCENARIO_YEAR ) ; + if ( val ) + params.NAT_CAPS.NOTES.push( fixup_content( val ) ) ; + } + } +} + +// -------------------------------------------------------------------- + +function get_national_capabilities( nat, is_kfw ) +{ + // get the capabilities for the specified nationality + if ( ! nat ) + return null ; + if ( is_kfw ) { + if ( nat === "american" ) + nat = "kfw-american" ; + else if ( ["british","british~canadian","british~newzealand"].indexOf( nat ) !== -1 ) + nat = "kfw-bcfk" ; + } + else if ( nat === "anzac" || nat === "free-french" || nat.substring(0,8) === "british~" ) + nat = "british" ; + var nat_caps = gTemplatePack["national-capabilities"][ nat ] ; + if ( nat_caps ) + return nat_caps ; + if ( gTemplatePack.nationalities[ nat ] ) { + var nat_type = gTemplatePack.nationalities[ nat ].type ; + if ( nat_type ) + return gTemplatePack["national-capabilities"][ nat_type ] ; + } + return null ; +} + diff --git a/vasl_templates/webapp/static/snippets.js b/vasl_templates/webapp/static/snippets.js index 062a31f..3d7b9ce 100644 --- a/vasl_templates/webapp/static/snippets.js +++ b/vasl_templates/webapp/static/snippets.js @@ -151,7 +151,11 @@ function make_snippet( $btn, params, extra_params, show_date_warnings ) params.PLAYER_FLAG_SIZE = "width='11' height='11'" ; // set player-specific parameters - var player_no = get_player_no_for_element( $btn ) ; + var player_no ; + if ( template_id.substring( 0, 9 ) === "nat_caps_" ) + player_no = template_id.substring( 9 ) ; + else + player_no = get_player_no_for_element( $btn ) ; var player_nat = get_player_nat( player_no ) ; if ( player_no ) { params.PLAYER_NAME = get_nationality_display_name( params["PLAYER_"+player_no] ) ; @@ -213,6 +217,8 @@ function make_snippet( $btn, params, extra_params, show_date_warnings ) params.OB_VO_WIDTH = params.OB_ORDNANCE_WIDTH_2 ; snippet_save_name = params.PLAYER_2 + " ordnance" ; } + if ( template_id === "nat_caps_1" || template_id === "nat_caps_2" ) + template_id = "nat_caps" ; // adjust comments adjust_vo_comments( params ) ; @@ -242,12 +248,12 @@ function make_snippet( $btn, params, extra_params, show_date_warnings ) set_vo_note( "ordnance" ) ; // generate snippets for multi-applicable vehicle/ordnance notes - var pos ; + var pos, i ; function add_ma_notes( ma_notes, keys, param_name, nat, vo_type ) { if ( ! keys ) return ; params[ param_name ] = [] ; - for ( var i=0 ; i < keys.length ; ++i ) { + for ( i=0 ; i < keys.length ; ++i ) { var ma_note = get_ma_note( nat, vo_type, keys[i] ) ; var key = keys[i] ; var extn_marker = "" ; @@ -301,7 +307,7 @@ function make_snippet( $btn, params, extra_params, show_date_warnings ) template_id = "ob_" + vo_type + "_ma_notes" ; var vo_type_uc = vo_type.toUpperCase() ; var postfixes = [ "MA_NOTES", "MA_NOTES_WIDTH", "EXTRA_MA_NOTES", "EXTRA_MA_NOTES_CAPTION" ] ; - for ( var i=0 ; i < postfixes.length ; ++i ) { + for ( i=0 ; i < postfixes.length ; ++i ) { params[ "OB_" + postfixes[i] ] = params[ "OB_" + vo_type_uc + "_" + postfixes[i] + "_" + player_no ] ; } snippet_save_name = params["PLAYER_"+player_no] + (vo_type === "vehicles" ? " vehicle notes" : " ordnance notes") ; @@ -371,6 +377,9 @@ function make_snippet( $btn, params, extra_params, show_date_warnings ) params.BAZ_RANGE = 4 ; } + // set the national capabilities parameters + set_nat_caps_params( player_nat, params ) ; + // check for mandatory parameters if ( template_id in _MANDATORY_PARAMS ) { var missing_params = [] ; @@ -432,7 +441,7 @@ function make_snippet( $btn, params, extra_params, show_date_warnings ) snippet = func( params, { autoEscape: false, filters: { - join: function( vals, sep ) { return vals.join( sep ) ; }, + join: function( vals, sep ) { return vals ? vals.join(sep) : "" ; }, nbsp: function( val ) { return strReplaceAll( val, " ", " " ) ; }, } , } ) ; @@ -484,20 +493,14 @@ function adjust_vo_comments( params ) } // allow comment EXC's to be styled - var excRegex = new RegExp( /\[EXC: .*?\]/ ) ; + var excRegex = new RegExp( /\[EXC: .*?\]/g ) ; function adjustExc( val ) { - var match = val.match( excRegex ) ; - if ( match ) { - val = val.substring( 0, match.index ) + - "" + match[0] + "" + - val.substring( match.index + match[0].length ) ; - } - return val ; + return wrapSubstrings( val, excRegex, "", "" ) ; } // adjust comments if ( params.OB_VO ) { - for ( var i=0 ; i < params.OB_VO.length ; ++i ) { + for ( i=0 ; i < params.OB_VO.length ; ++i ) { if ( ! params.OB_VO[i].comments ) continue ; for ( var j=0 ; j < params.OB_VO[i].comments.length ; ++j ) { @@ -935,40 +938,10 @@ function get_vo_comments( vo_entry, month, year ) if ( ! vo_entry.comments ) return vo_entry.comments ; - function parseDate( val ) { - if ( ! val ) - return null ; - var match = val.trim().match( /^(\d\d)\/(19\d\d)$/ ) ; - if ( ! match ) - return null ; - return [ match[1], match[2] ] ; - } - // generate the vehicle/ordnance's comments var voComments=[], cmt, i ; for ( i=0 ; i < vo_entry.comments.length ; ++i ) { - cmt = vo_entry.comments[i] ; - if ( cmt.substr(0,2) === "{?" && cmt.substr(cmt.length-2) === "?}" ) { - // this is a time-based comment, check the scenario date - var words = cmt.substring( 2, cmt.length-2 ).split( "|" ) ; - var dates = words[0].split( "-" ) ; - dates = [ parseDate(dates[0]), parseDate(dates[1]) ] ; - if ( words.length != 4 || dates.length != 2 || (!dates[0] && !dates[1]) ) { - showErrorMsg( "Invalid time-based vehicle/ordnance comment: " + cmt ) ; - continue ; - } - if ( !month || !year ) - cmt = words[3] ; - else { - var rc = true ; - if ( dates[0] && ( year < dates[0][1] || ( year == dates[0][1] && month < dates[0][0] ) ) ) - rc = false ; - if ( dates[1] && ( year > dates[1][1] || ( year == dates[1][1] && month > dates[1][0] ) ) ) - rc = false ; - cmt = rc ? words[1] : words[2] ; - } - } - cmt = cmt.trim() ; + cmt = make_time_based_comment( vo_entry.comments[i], month, year ) ; if ( cmt ) voComments.push( cmt ) ; } @@ -996,6 +969,108 @@ function get_vo_comments( vo_entry, month, year ) return voComments ; } +function make_time_based_comment( val, month, year ) +{ + function parseDateControl( val ) { + // parse a date control string + var dates = val.split( "-" ) ; + if ( dates.length != 2 ) + return null ; + for ( var i=0 ; i < 2 ; ++i ) { + var date = dates[i].trim() ; + if ( date !== "" ) { + var match = date.match( /^(\d\d)\/(19\d\d)$/ ) ; + if ( ! match ) + return null ; + dates[i] = [ match[1], match[2] ] ; + } else { + dates[i] = null ; + } + } + return dates ; + } + function checkDateControl( dateControl ) { + // check if the date passed in falls within the date control + if ( dateControl[0] && ( year < dateControl[0][1] || ( year == dateControl[0][1] && month < dateControl[0][0] ) ) ) + return false ; + if ( dateControl[1] && ( year > dateControl[1][1] || ( year == dateControl[1][1] && month > dateControl[1][0] ) ) ) + return false ; + return true ; + } + + // process any time-based values + var words, dateControl ; + for ( ; ; ) { + + // check for a time-based substitution + var parts = findDelimitedSubstring( val, "{?", "?}" ) ; + if ( $.isArray( parts ) ) { + // found one - this form has the following syntax: + // {? DATE CONTROL | within the date control | outside the date control | fallback text ?} + // parse the date control + words = parts[1].split( "|" ) ; + dateControl = parseDateControl( words[0] ) ; + if ( words.length != 4 || dateControl === null ) { + showErrorMsg( "Invalid time-based comment: " + val ) ; + return null ; + } + // figure out which value to use + if ( month && year ) + val = parts[0] + words[ checkDateControl(dateControl) ? 1 : 2 ].trim() + parts[2] ; + else + val = parts[0] + words[3].trim() + parts[2] ; + continue ; + } + + // check for a time-based substitution + parts = findDelimitedSubstring( val, "{!", "!}" ) ; + if ( $.isArray( parts ) ) { + // found one - this form has the following syntax: + // {! DATE CONTROL = text | DATE CONTROL = text | etc... | fallback text !} + var fallbackText = "" ; + choices = parts[1].split( "|" ) ; + for ( var i=0 ; i < choices.length ; ++i ) { + // parse the next choice + var pos = choices[i].indexOf( "=" ) ; + if ( pos !== -1 ) { + dateControl = parseDateControl( choices[i].substring( 0, pos ) ) ; + if ( dateControl !== null ) { + // the choice is valid - save it, and its substitution text + choices[i] = [ dateControl, choices[i].substring(pos+1).trim() ] ; + continue ; + } + } + // the choice is invalid + if ( i === choices.length-1 ) { + // this is the last choice - use it as the fallback text + fallbackText = choices.pop().trim() ; + break ; + } else { + showErrorMsg( "Invalid time-based comment: " + choices[i] ) ; + return null ; + } + } + // check each choice to try find a match + var replaceText = fallbackText ; + if ( month && year ) { + for ( i=0 ; i < choices.length ; ++i ) { + if ( checkDateControl( choices[i][0] ) ) { + // found a match - replace the content with the substitution text + replaceText = choices[i][1] ; + break ; + } + } + } + val = parts[0] + replaceText + parts[2] ; + } + + // NOTE: If we get here, there are no more time-based substitutions to be made. + break ; + } + + return val ; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function make_capabilities( raw, vo_entry, vo_type, nat, elite, scenario_theater, scenario_year, scenario_month, show_warnings ) @@ -1937,6 +2012,7 @@ function do_load_template_pack( fname, data ) var unknown_template_ids = [] ; var template_pack = { nationalities: $.extend( true, {}, gDefaultTemplatePack.nationalities ), + "national-capabilities": $.extend( true, {}, gDefaultTemplatePack["national-capabilities"] ), templates: {}, css: {}, includes: {}, @@ -1963,6 +2039,17 @@ function do_load_template_pack( fname, data ) $.extend( true, template_pack.nationalities, nationalities ) ; return ; } + if ( fname.toLowerCase() === "national-capabilities.json" ) { + var nat_caps = null ; + try { + nat_caps = JSON.parse( data ) ; + } catch( ex ) { + showWarningMsg( "Can't parse the nationalities JSON data:
" + escapeHTML(ex) + "
" ) ; + return ; + } + $.extend( true, template_pack["national-capabilities"], nat_caps ) ; + return ; + } var extn = getFilenameExtn( fname ) ; if ( [".j2",".css",".include"].indexOf( extn ) === -1 ) { invalid_filename_extns.push( fname ) ; diff --git a/vasl_templates/webapp/static/sortable.js b/vasl_templates/webapp/static/sortable.js index 2d3b52f..815f713 100644 --- a/vasl_templates/webapp/static/sortable.js +++ b/vasl_templates/webapp/static/sortable.js @@ -77,7 +77,7 @@ $.fn.sortable2 = function( action, args ) $sortable2.data( "no_confirm_delete", args.no_confirm_delete ) ; $sortable2.data( "on_edit", args.edit ) ; var $add_btn = find_helper( $sortable2, "add" ) ; - $add_btn.prepend( $( "
Add
" ) ) + $add_btn.prepend( $( "
Add
" ) ) .button( {} ) ; var $add = find_helper( $sortable2, "add" ) ; $add.prop( "title", "Add a new " + display_name[0] ) @@ -85,7 +85,7 @@ $.fn.sortable2 = function( action, args ) if ( args.reset ) { $sortable2.data( "on_reset", args.reset ) ; var $reset_btn = find_helper( $sortable2, "reset" ) ; - $reset_btn.prepend( $( "
Reset
" ) ) + $reset_btn.prepend( $( "
Reset
" ) ) .button( {} ) ; var $reset = find_helper( $sortable2, "reset" ) ; $reset.prop( "title", "Reset the " + display_name[1] ) diff --git a/vasl_templates/webapp/static/user_settings.js b/vasl_templates/webapp/static/user_settings.js index 4a72225..275c15e 100644 --- a/vasl_templates/webapp/static/user_settings.js +++ b/vasl_templates/webapp/static/user_settings.js @@ -9,6 +9,7 @@ USER_SETTINGS = { "date-format": "droplist", "scenario-images-source": "droplist", "hide-unavailable-ma-notes": "checkbox", + "auto-create-national-capabilities-labels": "checkbox", "include-vasl-images-in-snippets": "checkbox", "include-flags-in-snippets": "checkbox", "custom-list-bullets": "checkbox", @@ -76,7 +77,7 @@ function user_settings() dialogClass: "user-settings", modal: true, width: 460, - height: 320, + height: 340, resizable: false, create: function() { init_dialog( $(this), "OK", true ) ; diff --git a/vasl_templates/webapp/static/utils.js b/vasl_templates/webapp/static/utils.js index 72fed09..5e2f4d6 100644 --- a/vasl_templates/webapp/static/utils.js +++ b/vasl_templates/webapp/static/utils.js @@ -4,6 +4,8 @@ function get_nationality_display_name( nat_id ) { // get the nationality's display name + if ( ! gTemplatePack.nationalities[ nat_id ] ) + return null ; return gTemplatePack.nationalities[ nat_id ].display_name ; } @@ -85,6 +87,8 @@ function is_template_available( template_id ) // check if the specified template is available if ( template_id.match( /^ob_(vehicles|ordnance).*_[12]$/ ) ) template_id = template_id.substring( 0, template_id.length-2 ) ; + else if ( template_id === "nat_caps_1" || template_id === "nat_caps_2" ) + template_id = "nat_caps" ; return gTemplatePack.templates[ template_id ] !== undefined ; } @@ -426,6 +430,42 @@ function strReplaceAll( val, searchFor, replaceWith ) } } +function findDelimitedSubstring( val, delim1, delim2 ) +{ + // search for a substring delimited by the 2 specified markers + if ( val === null || val === undefined ) + return null ; + var pos = val.indexOf( delim1 ) ; + if ( pos === -1 ) + return val ; + var pos2 = val.indexOf( delim2, pos ) ; + if ( pos2 === -1 ) + return val ; + // found it - return the prefix/middle/postfix parts + return [ + val.substring( 0, pos ), + val.substring( pos+delim1.length, pos2 ), + val.substring( pos2+delim2.length ) + ] ; +} + +function wrapSubstrings( val, searchFor, delim1, delim2 ) +{ + // search for a substring and wrap it with the specified delimeters + if ( val === null || val === undefined ) + return null ; + // FUDGE! matchAll() isn't available in the PyQt embedded browser :-/ + var matches = [] ; + while ( ( match = searchFor.exec( val ) ) !== null ) + matches.push( match ) ; + for ( var i=matches.length-1 ; i >= 0 ; --i ) { + val = val.substring( 0, matches[i].index ) + + delim1 + matches[i][0] + delim2 + + val.substring( matches[i].index + matches[i][0].length ) ; + } + return val ; +} + function getFilenameExtn( fname ) { // get the filename extension diff --git a/vasl_templates/webapp/static/vassal.js b/vasl_templates/webapp/static/vassal.js index 9d4fc82..4d62962 100644 --- a/vasl_templates/webapp/static/vassal.js +++ b/vasl_templates/webapp/static/vassal.js @@ -100,6 +100,10 @@ function _generate_snippets() } no_autocreate[template_id] = true ; } + if ( ! gUserSettings["auto-create-national-capabilities-labels"] ) { + no_autocreate.nat_caps_1 = true ; + no_autocreate.nat_caps_2 = true ; + } function on_snippet_button( $btn, inactive ) { var template_id = $btn.attr( "data-id" ) ; @@ -114,7 +118,11 @@ function _generate_snippets() var params = unload_snippet_params( true, template_id ) ; var snippet_id = template_id ; var extra_params = {} ; - var player_no = get_player_no_for_element( $btn ) ; + var player_no ; + if ( snippet_id.substring( 0, 9 ) === "nat_caps_" ) + player_no = snippet_id.substring( 9 ) ; + else + player_no = get_player_no_for_element( $btn ) ; var data ; if ( ["scenario_note","ob_setup","ob_note"].indexOf( template_id ) !== -1 ) { data = $btn.parent().parent().data( "sortable2-data" ) ; @@ -225,6 +233,8 @@ function _get_raw_content( snippet_id, $btn, params ) return [ "Bazooka", "Range", "TH#" ] ; if ( snippet_id === "thh" ) return [ "Tank-Hunter Heroes", "Banzai Charge" ] ; + if ( snippet_id.substring( 0, 9 ) === "nat_caps_" ) + return [ "Capabilities" ] ; // handle vehicle/ordnance notes // NOTE: These were implemented after we added snippet ID's, so there's no need to support legacy labels. diff --git a/vasl_templates/webapp/templates/index.html b/vasl_templates/webapp/templates/index.html index 3f434f4..06a36dc 100644 --- a/vasl_templates/webapp/templates/index.html +++ b/vasl_templates/webapp/templates/index.html @@ -110,6 +110,7 @@ gHelpUrl = "{{url_for('show_help')}}" ; + diff --git a/vasl_templates/webapp/templates/national-capabilities.html b/vasl_templates/webapp/templates/national-capabilities.html new file mode 100644 index 0000000..58df26c --- /dev/null +++ b/vasl_templates/webapp/templates/national-capabilities.html @@ -0,0 +1,70 @@ + + + + + + National Capabilities: {{NATIONALITY}} + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vasl_templates/webapp/templates/tabs-scenario.html b/vasl_templates/webapp/templates/tabs-scenario.html index a294121..1146d6d 100644 --- a/vasl_templates/webapp/templates/tabs-scenario.html +++ b/vasl_templates/webapp/templates/tabs-scenario.html @@ -41,16 +41,19 @@ +
+   - - - +
+
+ +
- Hide unavailable multi-applicable notes
+ Auto-create National Capabilities labels
+
+ Hide unavailable multi-applicable notes
+