Added the default scenario.

master
Pacman Ghost 6 years ago
parent 721e9bdeae
commit 3b84cc2cf5
  1. 15
      vasl_templates/webapp/data/default-scenario.json
  2. 23
      vasl_templates/webapp/main.py
  3. 4
      vasl_templates/webapp/static/main.js
  4. 20
      vasl_templates/webapp/static/simple_notes.js
  5. 59
      vasl_templates/webapp/static/snippets.js
  6. 1
      vasl_templates/webapp/templates/index.html
  7. 11
      vasl_templates/webapp/tests/fixtures/data/default-scenario.json
  8. 61
      vasl_templates/webapp/tests/fixtures/new-default-scenario.json
  9. 108
      vasl_templates/webapp/tests/test_default_scenario.py
  10. 13
      vasl_templates/webapp/tests/test_scenario_persistence.py

@ -0,0 +1,15 @@
{
"PLAYER_1": "german",
"PLAYER_1_ELR": "5",
"PLAYER_1_SAN": "2",
"PLAYER_2": "russian",
"PLAYER_2_ELR": "5",
"PLAYER_2_SAN": "2",
"VICTORY_CONDITIONS_WIDTH": "300px",
"SSR_WIDTH": "300px",
"_OB_NOTE_WIDTH": "200px"
}

@ -1,8 +1,13 @@
""" Main webapp handlers. """
import os
import json
from flask import request, render_template
from flask import jsonify
from vasl_templates.webapp import app
from vasl_templates.webapp.config.constants import DATA_DIR
# ---------------------------------------------------------------------
@ -13,6 +18,24 @@ def main():
# ---------------------------------------------------------------------
default_scenario = None
@app.route( "/default-scenario" )
def get_default_scenario():
"""Return the default scenario."""
# check if a default scenario has been configured
if default_scenario:
fname = default_scenario
else:
fname = os.path.join( app.config.get("DATA_DIR",DATA_DIR), "default-scenario.json" )
# return the default scenario
with open(fname,"r") as fp:
return jsonify( json.load( fp ) )
# ---------------------------------------------------------------------
@app.route( "/ping" )
def ping():
"""Let the caller know we're alive."""

@ -17,7 +17,7 @@ $(document).ready( function () {
// initialize the menu
var $menu = $("#menu input") ;
$menu.popmenu( {
new_scenario: { label: "New scenario", action: on_new_scenario },
new_scenario: { label: "New scenario", action: function() { on_new_scenario(true) ; } },
load_scenario: { label: "Load scenario", action: on_load_scenario },
save_scenario: { label: "Save scenario", action: on_save_scenario },
separator: { type: "separator" },
@ -159,7 +159,7 @@ $(document).ready( function () {
width: "3em"
} ) ;
}
buf = [ "<option></option>" ] ; // nb: allow scenarios that have no SAN
buf = [ "<option value=''></option>" ] ; // nb: allow scenarios that have no SAN
for ( i=2 ; i <= 7 ; ++i ) // nb: A14.1: SAN is 2-7
buf.push( "<option value='" + i + "'>" + i + "</option>" ) ;
buf = buf.join( "" ) ;

@ -4,25 +4,25 @@
// --------------------------------------------------------------------
function add_scenario_note() { _do_edit_simple_note( $("#scenario_notes-sortable"), null ) ; }
function add_scenario_note() { _do_edit_simple_note( $("#scenario_notes-sortable"), null, gDefaultScenario._SCENARIO_NOTE_WIDTH ) ; }
function do_add_scenario_note( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
function edit_scenario_note( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry ) ; }
function edit_scenario_note( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry, null ) ; }
function add_ssr() { _do_edit_simple_note( $("#ssr-sortable"), null ) ; }
function add_ssr() { _do_edit_simple_note( $("#ssr-sortable"), null, null ) ; }
function do_add_ssr( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
function edit_ssr( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry ) ; }
function edit_ssr( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry, null ) ; }
function add_ob_setup( player_id ) { _do_edit_simple_note( $("#ob_setups-sortable_"+player_id), null ) ; }
function add_ob_setup( player_id ) { _do_edit_simple_note( $("#ob_setups-sortable_"+player_id), null, gDefaultScenario._OB_SETUP_WIDTH ) ; }
function do_add_ob_setup( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
function edit_ob_setup( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry ) ; }
function edit_ob_setup( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry, null ) ; }
function add_ob_note( player_id ) { _do_edit_simple_note( $("#ob_notes-sortable_"+player_id), null ) ; }
function add_ob_note( player_id ) { _do_edit_simple_note( $("#ob_notes-sortable_"+player_id), null, gDefaultScenario._OB_NOTE_WIDTH ) ; }
function do_add_ob_note( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
function edit_ob_note( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry ) ; }
function edit_ob_note( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry, null ) ; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function _do_edit_simple_note( $sortable2, $entry )
function _do_edit_simple_note( $sortable2, $entry, default_width )
{
// figure out what we're editing
var note_type = _get_note_type_for_sortable( $sortable2 ) ;
@ -53,7 +53,7 @@ function _do_edit_simple_note( $sortable2, $entry )
// load the dialog
var data = $entry ? $entry.data("sortable2-data") : null ;
$caption.val( data ? data.caption : "" ) ;
$width.val( data ? data.width : "" ) ;
$width.val( data ? data.width : default_width ) ;
$(this).height( $(this).height() ) ; // fudge: force the textarea to resize
$width.keydown( function(evt) { auto_dismiss_dialog( evt, "OK" ) ; } ) ;
},

@ -14,6 +14,8 @@ var _DAY_OF_MONTH_POSTFIXES = { // nb: we assume English :-/
11: "th", 12: "th", 13: "th"
} ;
var gDefaultScenario = null ;
// --------------------------------------------------------------------
function generate_snippet( $btn, extra_params )
@ -474,17 +476,27 @@ function on_load_scenario_file_selected()
function do_load_scenario( params )
{
// reset the scenario
on_new_scenario( false ) ;
reset_scenario() ;
// load the scenario parameters
var params_loaded = {} ;
var unknown_vo = [] ;
var set_param = function( $elem, key ) { $elem.val(params[key]) ; params_loaded[key]=true ; return $elem ; } ;
var set_param = function( $elem, key ) {
$elem.val( params[key] ) ;
if ( $elem[0].nodeName.toLowerCase() === "select" )
$elem.selectmenu( "refresh" ) ;
params_loaded[key] = true ;
return $elem ;
} ;
// FUDGE! We must set the players first, since changing these will reset the OB tabs.
if ( "PLAYER_1" in params )
set_param( $("select[name='PLAYER_1']"), "PLAYER_1" ).trigger( "change" ) ;
if ( "PLAYER_2" in params )
set_param( $("select[name='PLAYER_2']"), "PLAYER_2" ).trigger( "change" ) ;
if ( "PLAYER_1" in params ) {
set_param( $("select[name='PLAYER_1']"), "PLAYER_1" ) ;
on_player_change( $("select[name='PLAYER_1']") ) ;
}
if ( "PLAYER_2" in params ) {
set_param( $("select[name='PLAYER_2']"), "PLAYER_2" ) ;
on_player_change( $("select[name='PLAYER_2']") ) ;
}
var i ;
for ( var key in params ) {
var player_id, $sortable2 ;
@ -548,7 +560,7 @@ function do_load_scenario( params )
// look for unrecognized keys
var buf = [] ;
for ( key in params ) {
if ( ! (key in params_loaded) )
if ( !(key in params_loaded) && key.substring(0,1) !== "_" )
buf.push( key + " = " + params[key] ) ;
}
if ( buf.length > 0 ) {
@ -616,18 +628,38 @@ function on_new_scenario( verbose )
{
// FIXME! confirm this operation if the scenario is dirty
// load the default scenario
if ( gDefaultScenario )
do_load_scenario( gDefaultScenario ) ;
else {
$.getJSON( gGetDefaultScenarioUrl, function(data) {
gDefaultScenario = data ;
do_load_scenario( data ) ;
} ).fail( function( xhr, status, errorMsg ) {
showErrorMsg( "Can't get the default scenario:<div class='pre'>" + escapeHTML(errorMsg) + "</div>" ) ;
return ;
} ) ;
}
// provide some feedback to the user
$("#tabs").tabs( "option", "active", 0 ) ;
if ( verbose )
showInfoMsg( "The scenario was reset." ) ;
}
function reset_scenario()
{
// reset all the template parameters
$("input[type='text'].param").each( function() { $(this).val("") ; } ) ;
$("textarea.param").each( function() { $(this).val("") ; } ) ;
// reset all the template parameters
$("select[name='PLAYER_1']").val( "german" ).selectmenu( "refresh" ) ;
$("select[name='PLAYER_2']").val( "russian" ).selectmenu( "refresh" ) ;
// nb: there's no way to reset the player droplist's
var player_id ;
for ( player_id=1 ; player_id <= 2 ; ++player_id ) {
on_player_change( $( "select[name='PLAYER_" + player_id + "']" ) ) ;
$("select[name='PLAYER_" + player_id + "_ELR']").val( 5 ).selectmenu( "refresh" ) ;
$("select[name='PLAYER_" + player_id + "_SAN']").val( 2 ).selectmenu( "refresh" ) ;
$("select[name='PLAYER_" + player_id + "_ELR']").val( 0 ).selectmenu( "refresh" ) ;
$("select[name='PLAYER_" + player_id + "_SAN']").val( "" ).selectmenu( "refresh" ) ;
}
// reset all the template parameters
@ -639,11 +671,6 @@ function on_new_scenario( verbose )
$( "#vehicles-sortable_" + player_id ).sortable2( "delete-all" ) ;
$( "#ordnance-sortable_" + player_id ).sortable2( "delete-all" ) ;
}
// provide some feedback to the user
$("#tabs").tabs( "option", "active", 0 ) ;
if ( verbose )
showInfoMsg( "The scenario was reset." ) ;
}
// --------------------------------------------------------------------

@ -242,6 +242,7 @@
<script>
gImagesBaseUrl = "{{url_for('static',filename='images')}}" ;
gGetTemplatePackUrl = "{{url_for('get_template_pack')}}" ;
gGetDefaultScenarioUrl = "{{url_for('get_default_scenario')}}" ;
gVehicleListingsUrl = "{{url_for('get_vehicle_listings')}}" ;
gOrdnanceListingsUrl = "{{url_for('get_ordnance_listings')}}" ;
</script>

@ -0,0 +1,11 @@
{
"PLAYER_1": "german",
"PLAYER_1_ELR": "5",
"PLAYER_1_SAN": "2",
"PLAYER_2": "russian",
"PLAYER_2_ELR": "5",
"PLAYER_2_SAN": "2"
}

@ -0,0 +1,61 @@
{
"SCENARIO_NAME": "default scenario name",
"SCENARIO_LOCATION": "default location",
"SCENARIO_DATE": "01/01/2000",
"SCENARIO_WIDTH": "1px",
"PLAYER_1": "american",
"PLAYER_1_ELR": "1",
"PLAYER_1_SAN": "2",
"PLAYER_2": "japanese",
"PLAYER_2_ELR": "3",
"PLAYER_2_SAN": "4",
"VICTORY_CONDITIONS": "default victory conditions",
"VICTORY_CONDITIONS_WIDTH": "123px",
"SCENARIO_NOTES": [
{ "caption": "default scenario note #1", "width": "1px" },
{ "caption": "default scenario note #2", "width": "2px" },
{ "caption": "default scenario note #3", "width": "3px" }
],
"SSR": [
"default SSR #1",
"default SSR #2",
"default SSR #3"
],
"SSR_WIDTH": "999px",
"OB_SETUPS_1": [
{ "caption": "default american OB setup #1", "width": "101px" },
{ "caption": "default american OB setup #2", "width": "102px" }
],
"OB_NOTES_1": [
{ "caption": "default american OB note #1", "width": "103px" },
{ "caption": "default american OB note #2", "width": "104px" }
],
"VEHICLES_1": [],
"VEHICLES_WIDTH_1": "110px",
"ORDNANCE_1": [],
"ORDNANCE_WIDTH_1": "120px",
"OB_SETUPS_2": [
{ "caption": "default japanese OB setup #1", "width": "201px" },
{ "caption": "default japanese OB setup #2", "width": "202px" }
],
"OB_NOTES_2": [
{ "caption": "default japanese OB note #1", "width": "203px" },
{ "caption": "default japanese OB note #2", "width": "204px" }
],
"VEHICLES_2": [],
"VEHICLES_WIDTH_2": "210px",
"ORDNANCE_2": [],
"ORDNANCE_WIDTH_2": "211px",
"_OB_SETUP_WIDTH": "900px",
"_OB_NOTE_WIDTH": "901px"
}

@ -0,0 +1,108 @@
"""Test the loading of the default scenario."""
import os
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys
from vasl_templates.webapp import main
from vasl_templates.webapp.tests.utils import select_tab, find_child, get_sortable_entry_text, wait_for
# ---------------------------------------------------------------------
def test_default_scenario( webapp, webdriver, monkeypatch ):
"""Test loading the default scenario."""
# configure a new default scenario
fname = os.path.join( os.path.split(__file__)[0], "fixtures/new-default-scenario.json" )
monkeypatch.setattr( main, "default_scenario", fname )
# initialize
webdriver.get( webapp.url_for( "main" ) )
# wait for the scenario to load
elem = find_child( "input[name='SCENARIO_NAME']" )
wait_for( 5, lambda: elem.get_attribute("value") != "" )
def check_textbox( field_name, expected ):
"""Check that a field has been loaded correctly."""
elem = find_child( "input[name='{}']".format( field_name ) )
assert elem.get_attribute( "value" ) == expected
def check_textarea( field_name, expected ):
"""Check that a field has been loaded correctly."""
elem = find_child( "textarea[name='{}']".format( field_name ) )
assert elem.get_attribute( "value" ) == expected
def check_droplist( field_name, expected ):
"""Check that a field has been loaded correctly."""
elem = find_child( "select[name='{}']".format( field_name ) )
assert Select(elem).first_selected_option.get_attribute("value") == expected
select_tab( "scenario" )
# check the scenario fields
check_textbox( "SCENARIO_NAME", "default scenario name" )
check_textbox( "SCENARIO_LOCATION", "default location" )
check_textbox( "SCENARIO_DATE", "01/01/2000" )
check_textbox( "SCENARIO_WIDTH", "1px" )
# check the player fields
check_droplist( "PLAYER_1", "american" )
check_droplist( "PLAYER_1_ELR", "1" )
check_droplist( "PLAYER_1_SAN", "2" )
check_droplist( "PLAYER_2", "japanese" )
check_droplist( "PLAYER_2_ELR", "3" )
check_droplist( "PLAYER_2_SAN", "4" )
# check the victory conditions
check_textarea( "VICTORY_CONDITIONS", "default victory conditions" )
check_textbox( "VICTORY_CONDITIONS_WIDTH", "123px" )
# check the scenario notes
assert get_sortable_entry_text( find_child( "#scenario_notes-sortable" ) ) \
== [ "default scenario note #{}".format(i) for i in [1,2,3] ]
# nb: should check the snippet widths as well (not really important for a default scenario)
# check the SSR's
assert get_sortable_entry_text( find_child( "#ssr-sortable" ) ) \
== [ "default SSR #{}".format(i) for i in [1,2,3] ]
check_textbox( "SSR_WIDTH", "999px" )
select_tab( "ob1" )
# check the OB setups/notes (player 1)
assert get_sortable_entry_text( find_child( "#ob_setups-sortable_1" ) ) \
== [ "default american OB setup #{}".format(i) for i in [1,2] ]
assert get_sortable_entry_text( find_child( "#ob_notes-sortable_1" ) ) \
== [ "default american OB note #{}".format(i) for i in [1,2] ]
# nb: should check the snippet widths as well (not really important for a default scenario)
# check the vehicles/ordnance (player 1)
assert get_sortable_entry_text( find_child( "#vehicles-sortable_1" ) ) == []
check_textbox( "VEHICLES_WIDTH_1", "110px" )
assert get_sortable_entry_text( find_child( "#ordnance-sortable_1" ) ) == []
check_textbox( "ORDNANCE_WIDTH_1", "120px" )
select_tab( "ob2" )
# check the OB setups/notes (player 2)
assert get_sortable_entry_text( find_child( "#ob_setups-sortable_2" ) ) \
== [ "default japanese OB setup #{}".format(i) for i in [1,2] ]
assert get_sortable_entry_text( find_child( "#ob_notes-sortable_2" ) ) \
== [ "default japanese OB note #{}".format(i) for i in [1,2] ]
# nb: should check the snippet widths as well (not really important for a default scenario)
# check the vehicles/ordnance (player 2)
assert get_sortable_entry_text( find_child( "#vehicles-sortable_2" ) ) == []
check_textbox( "VEHICLES_WIDTH_2", "210px" )
assert get_sortable_entry_text( find_child( "#ordnance-sortable_2" ) ) == []
check_textbox( "ORDNANCE_WIDTH_2", "211px" )
# check that the default OB setup/note width is being used
elem = find_child( "#ob_setups-add_2" )
elem.click()
elem = find_child( ".ui-dialog-buttonpane input[name='width']" )
assert elem.get_attribute( "value" ) == "900px"
elem.send_keys( Keys.ESCAPE )
elem = find_child( "#ob_notes-add_2" )
elem.click()
elem = find_child( ".ui-dialog-buttonpane input[name='width']" )
assert elem.get_attribute( "value" ) == "901px"

@ -5,7 +5,7 @@ import json
from selenium.webdriver.support.ui import Select
from vasl_templates.webapp.tests.utils import \
set_template_params, select_tab, select_menu_option, get_sortable_entry_text, \
get_nationalities, set_template_params, select_tab, select_menu_option, get_sortable_entry_text, \
get_stored_msg, set_stored_msg, find_child, find_children
# ---------------------------------------------------------------------
@ -15,6 +15,14 @@ def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-lo
# initialize
webdriver.get( webapp.url_for( "main", scenario_persistence=1 ) )
nationalities = get_nationalities( webapp )
def check_ob_tabs( *args ):
"""Check that the OB tabs have been set correctly."""
for player_no in [1,2]:
elem = find_child( "#tabs .ui-tabs-nav a[href='#tabs-ob{}']".format( player_no ) )
nat = args[ player_no-1 ]
assert elem.text.strip() == "{} OB".format( nationalities[nat]["display_name"] )
# load the scenario fields
scenario_params = {
@ -54,6 +62,7 @@ def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-lo
for tab_id,fields in scenario_params.items():
select_tab( tab_id )
set_template_params( fields )
check_ob_tabs( "russian", "german" )
# save the scenario and check the results
saved_scenario = _save_scenario()
@ -64,6 +73,7 @@ def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-lo
# reset the scenario and check the save results
select_menu_option( "new_scenario" )
check_ob_tabs( "german", "russian" )
data = _save_scenario()
data2 = { k: v for k,v in data.items() if v }
assert data2 == {
@ -84,6 +94,7 @@ def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-lo
# load a scenario and make sure it was loaded into the UI correctly
_load_scenario( saved_scenario )
check_ob_tabs( "russian", "german" )
for tab_id in scenario_params:
select_tab( tab_id )
for field,val in scenario_params[tab_id].items():

Loading…
Cancel
Save