Allow turn track squares to be shaded.

master
Pacman Ghost 2 years ago
parent 40c2b87cbe
commit cd831446fd
  1. 36
      vasl_templates/webapp/data/default-template-pack/turn_track.j2
  2. 25
      vasl_templates/webapp/static/snippets.js
  3. 23
      vasl_templates/webapp/static/turn_track.js
  4. 7
      vasl_templates/webapp/templates/tabs-scenario.html
  5. 92
      vasl_templates/webapp/tests/test_turn_track.py

@ -22,14 +22,15 @@ td.no-reinforce { {{RESET_TD}} ; width: 13px ; }
td.reinforce1 { {{RESET_TD}} ; width: 13px ; background: url("{{TURN_TRACK_FLAG_1}}") top left no-repeat ; vertical-align: top ; }
td.reinforce2 { {{RESET_TD}} ; width: 13px ; background: url("{{TURN_TRACK_FLAG_2}}") bottom right no-repeat ; vertical-align: bottom ; }
td.half-turn {
background: url("{{IMAGES_BASE_URL}}/turn-track-half-turn.png") bottom right no-repeat ;
background: url("{{TURN_TRACK_HALF_TURN_IMAGE_URL}}") bottom right no-repeat ;
background-size: contain ; {# nb: doesn't work in VASSAL, the image file needs to be the correct size :-/ #}
}
{% if TURN_TRACK_PREVIEW_MODE %}
body { margin: 0 ; }
.reinforce1, .reinforce2 { opacity: 0 ; }
.click { width: 13px ; height: 13px ; cursor: pointer ; }
.flag-click { width: 13px ; height: 13px ; cursor: pointer ; }
.shading-click { cursor: pointer ; }
{%endif%}
</style>
@ -45,6 +46,12 @@ function onFlagClick( turnNo, playerNo ) {
turnNo: turnNo, uiPlayerNo: playerNo
}, "*" ) ;
}
function onShadingClick( turnNo ) {
window.parent.postMessage( {
type: "ShadingClick",
turnNo: turnNo
}, "*" ) ;
}
</script>
{%endif%}
@ -54,27 +61,40 @@ function onFlagClick( turnNo, playerNo ) {
<tr>
{% for turnSquare in row %}
<td {%if turnSquare[0] == TURN_TRACK_HALF_TURN%} class="half-turn" {%endif%} >
<td id="turn-square-{{turnSquare[0]}}"
{%if turnSquare[0] == TURN_TRACK_HALF_TURN%} class="half-turn" {%endif%}
{% if turnSquare[1] %} style="background-color:{{TURN_TRACK_SHADING_COLOR}};" {%endif%}
>
<table style="width:100%;height:100%;"> <tr>
<td id="flag-{{turnSquare[0]}}_1" width="100%"
class = {% if turnSquare[1] %} "reinforce1" {%else%} "no-reinforce" {%endif%}
class = {% if turnSquare[2] %} "reinforce1" {%else%} "no-reinforce" {%endif%}
>
{% if TURN_TRACK_PREVIEW_MODE %}
<div class="click"
<div class="flag-click"
onclick = "onFlagClick( {{turnSquare[0]}}, 1 )"
> </div>
{%endif%}
</td>
<td class="turn-no"> {{turnSquare[0]}} </td>
<td class="turn-no">
{% if TURN_TRACK_PREVIEW_MODE %}
<div class="shading-click"
onclick = "onShadingClick( {{turnSquare[0]}} )"
>
{{turnSquare[0]}}
</div>
{%else%}
{{turnSquare[0]}}
{%endif%}
</td>
<td id="flag-{{turnSquare[0]}}_2" width="100%"
class = {% if turnSquare[2] and turnSquare[0] != TURN_TRACK_HALF_TURN %} "reinforce2" {%else%} "no-reinforce" {%endif%}
class = {% if turnSquare[3] and turnSquare[0] != TURN_TRACK_HALF_TURN %} "reinforce2" {%else%} "no-reinforce" {%endif%}
>
{% if TURN_TRACK_PREVIEW_MODE and turnSquare[0] != TURN_TRACK_HALF_TURN %}
<div class="click"
<div class="flag-click"
onclick = "onFlagClick( {{turnSquare[0]}}, 2 )"
> </div>
{%endif%}

@ -530,23 +530,31 @@ function make_turn_track_params( params )
turnNo = 1 + row * args.width + col ;
if ( turnNo > args.nTurns )
break ;
var val = [ turnNo, args.reinforce2[turnNo]?true:false, args.reinforce1[turnNo]?true:false ] ;
var val = [ turnNo,
args.shading[turnNo] ? true : false,
args.reinforce2[turnNo] ? true : false,
args.reinforce1[turnNo] ? true : false,
] ;
if ( params.TURN_TRACK.SWAP_PLAYERS )
val = [ val[0], val[2], val[1] ] ;
val = [ val[0], val[1], val[3], val[2] ] ;
turnTrackSquares[ turnTrackSquares.length-1 ].push( val ) ;
nTurnTrackSquares += 1 ;
}
}
// update the snippet params
var forceLocalImages = params.TURN_TRACK_PREVIEW_MODE ;
params.TURN_TRACK_SQUARES = turnTrackSquares ;
if ( args.halfTurn )
params.TURN_TRACK_HALF_TURN = nTurnTrackSquares ;
params.TURN_TRACK_HALF_TURN_IMAGE_URL = forceLocalImages ?
make_app_url( "/static/images/turn-track-half-turn.png", true ) :
params.IMAGES_BASE_URL + "/turn-track-half-turn.png" ;
params.TURN_TRACK_SHADING_COLOR = TURN_TRACK_SHADING_COLOR ;
// NOTE: The convention is that player 1 sets up first, player 2 moves first,
// so swapping players actually maps turn track player 1 to the real player 1.
// NOTE: We generate the player flag URL's instead of using params.PLAYER_FLAG_1/2
// so that flags will work even if the user has disabled player flags in snippets.
var forceLocalImages = params.TURN_TRACK_PREVIEW_MODE ;
params.TURN_TRACK_FLAG_1 = make_player_flag_url(
get_player_nat( params.TURN_TRACK.SWAP_PLAYERS ? 1 : 2 ),
true, forceLocalImages
@ -559,7 +567,7 @@ function make_turn_track_params( params )
function parseTurnTrackParams( params )
{
function parseReinforcements( reinf ) {
function parseCommaList( reinf ) {
var turnFlags = {} ;
reinf.split( "," ).forEach( function( turnNo ) {
turnNo = parseInt( turnNo.trim() ) ;
@ -580,12 +588,13 @@ function parseTurnTrackParams( params )
var width = params.TURN_TRACK.WIDTH ;
if ( width === "" )
width = vertical ? 1 : nTurns ;
var reinforce1 = parseReinforcements( params.TURN_TRACK.REINFORCEMENTS_1 ) ;
var reinforce2 = parseReinforcements( params.TURN_TRACK.REINFORCEMENTS_2 ) ;
var shading = parseCommaList( params.TURN_TRACK.SHADING ) ;
var reinforce1 = parseCommaList( params.TURN_TRACK.REINFORCEMENTS_1 ) ;
var reinforce2 = parseCommaList( params.TURN_TRACK.REINFORCEMENTS_2 ) ;
return {
nTurns: nTurns, halfTurn: halfTurn,
vertical: vertical, width: width,
vertical: vertical, width: width, shading: shading,
reinforce1: reinforce1, reinforce2: reinforce2
} ;
}
@ -959,6 +968,7 @@ function unload_snippet_params( unpack_scenario_date, template_id )
"NTURNS": nTurns,
"WIDTH": isNaN( parseInt( width ) ) ? "" : width,
"VERTICAL": $( "input[name='TURN_TRACK_VERTICAL']" ).prop( "checked" ),
"SHADING": $( "input[name='TURN_TRACK_SHADING']" ).val().trim(),
"REINFORCEMENTS_1": $( "input[name='TURN_TRACK_REINFORCEMENTS_1']" ).val().trim(),
"REINFORCEMENTS_2": $( "input[name='TURN_TRACK_REINFORCEMENTS_2']" ).val().trim(),
"SWAP_PLAYERS": $( "input[name='TURN_TRACK_SWAP_PLAYERS']" ).prop( "checked" ),
@ -1756,6 +1766,7 @@ function do_load_scenario_data( params )
setTurnTrackNTurns( params[key].NTURNS ) ;
$( "input[name='TURN_TRACK_VERTICAL']" ).prop( "checked", params[key].VERTICAL ) ;
$( "input[name='TURN_TRACK_WIDTH']" ).val( params[key].WIDTH ) ;
$( "input[name='TURN_TRACK_SHADING']" ).val( params[key].SHADING ) ;
$( "input[name='TURN_TRACK_REINFORCEMENTS_1']" ).val( params[key].REINFORCEMENTS_1 ) ;
$( "input[name='TURN_TRACK_REINFORCEMENTS_2']" ).val( params[key].REINFORCEMENTS_2 ) ;
$( "input[name='TURN_TRACK_SWAP_PLAYERS']" ).prop( "checked", params[key].SWAP_PLAYERS ) ;

@ -1,10 +1,12 @@
DEFAULT_TURN_TRACK_TURNS_MIN = 6 ;
DEFAULT_TURN_TRACK_TURNS_MAX = 10 ;
TURN_TRACK_SHADING_COLOR = "#e0e0e0" ;
// NOTE: Reinforcement flags get clipped on turn 100, but this is unlikely to be an issue :-/
_MAX_TURN_TRACK_TURNS = 100 ;
gTurnTrackReinforcements = null ;
gTurnTrackShading = null ;
// --------------------------------------------------------------------
@ -14,6 +16,7 @@ function editTurnTrackSettings()
var $dlg, $iframe, iframeSeqNo=0 ;
// FUDGE! This should work as a local variable, but causes a weird problem where it doesn't get reset properly :-/
gTurnTrackReinforcements = null ;
gTurnTrackShading = null ;
function loadControls() {
// load the dialog controls
@ -34,6 +37,7 @@ function editTurnTrackSettings()
var params = updatePreview( false ) ;
var args = parseTurnTrackParams( params ) ;
gTurnTrackReinforcements = { 1: args.reinforce1, 2: args.reinforce2 } ;
gTurnTrackShading = args.shading ;
// update the UI
updateUI() ;
}
@ -46,9 +50,11 @@ function editTurnTrackSettings()
$panel.find( "input[name='TURN_TRACK_WIDTH']" ).val( "" ) ;
$panel.find( "input[name='TURN_TRACK_VERTICAL']" ).prop( "checked", false ) ;
$panel.find( "input[name='TURN_TRACK_SWAP_PLAYERS']" ).prop( "checked", false ) ;
$panel.find( "input[name='TURN_TRACK_SHADING']" ).val( "" ) ;
$panel.find( "input[name='TURN_TRACK_REINFORCEMENTS_1']" ).val( "" ) ;
$panel.find( "input[name='TURN_TRACK_REINFORCEMENTS_2']" ).val( "" ) ;
gTurnTrackReinforcements = null ;
gTurnTrackShading = null ;
loadControls() ;
}
} ) ;
@ -141,6 +147,21 @@ function editTurnTrackSettings()
updateFlag( turnNo, playerNo ) ;
}
function onShadingClick( turnNo ) {
// NOTE: This method gets called by a click handler in the snippet HTML.
// toggle the turn track square's shading
if ( gTurnTrackShading[turnNo] )
delete gTurnTrackShading[turnNo] ;
else
gTurnTrackShading[turnNo] = true ;
$panel.find( "input[name='TURN_TRACK_SHADING']" ).val(
Object.keys( gTurnTrackShading ).join( "," )
) ;
$iframe.contents().find( "#turn-square-" + turnNo ).css( {
"background-color": gTurnTrackShading && gTurnTrackShading[turnNo] ? TURN_TRACK_SHADING_COLOR : "inherit"
} ) ;
}
function updateFlag( turnNo, playerNo ) {
// update the specified reinforcement flag
$iframe.contents().find( "#flag-" + turnNo + "_" + flipPlayerNo2(playerNo) ).css( {
@ -225,6 +246,8 @@ function editTurnTrackSettings()
window.addEventListener( "message", function( evt ) {
if ( evt.data.type === "FlagClick" )
onFlagClick( evt.data.turnNo, flipPlayerNo2(evt.data.uiPlayerNo) ) ;
else if ( evt.data.type === "ShadingClick" )
onShadingClick( evt.data.turnNo ) ;
} ) ;
},

@ -35,9 +35,10 @@
<div class="small" style="display:none;">
Width: <input type="text" name="TURN_TRACK_WIDTH" class="param" size="1">
<input type="checkbox" name="TURN_TRACK_VERTICAL" class="param"> Vertical </input> &nbsp;
R<sub>1</sub>: <input type="text" name="TURN_TRACK_REINFORCEMENTS_1" class="param" size=8">
R<sub>2</sub>: <input type="text" name="TURN_TRACK_REINFORCEMENTS_2" class="param" size=8">
<input type="checkbox" name="TURN_TRACK_SWAP_PLAYERS" class="param"> Swap players </input>
S: <input type="text" name="TURN_TRACK_SHADING" class="param" size="5">
R<sub>1</sub>: <input type="text" name="TURN_TRACK_REINFORCEMENTS_1" class="param" size=7">
R<sub>2</sub>: <input type="text" name="TURN_TRACK_REINFORCEMENTS_2" class="param" size=7">
<input type="checkbox" name="TURN_TRACK_SWAP_PLAYERS" class="param"> Swap </input>
</div>
<div class="row" style="margin-top:-0.6em;">
<label></label>

@ -44,10 +44,10 @@ def test_turn_track_controls( webapp, webdriver ):
# show the turn track dialog
dlg = _show_turn_track_dialog( 6 )
with SwitchFrame( webdriver, "#turn-track-preview" ):
_click_reinf_flag( 1, 1 )
_click_reinf_flag( 2, 1 )
_click_reinf_flag( 2, 2 )
_click_reinf_flag( 3, 2 )
_toggle_reinf( 1, 1 )
_toggle_reinf( 2, 1 )
_toggle_reinf( 2, 2 )
_toggle_reinf( 3, 2 )
# change the width
_change_turn_track_width( dlg, 3 )
@ -100,10 +100,10 @@ def test_turn_track_reinforcements( webapp, webdriver ):
# turn on some reinforcements, then check the snippet
with SwitchFrame( webdriver, "#turn-track-preview" ):
_click_reinf_flag( 2, 1 )
_click_reinf_flag( 3, 1 )
_click_reinf_flag( 3, 2 )
_click_reinf_flag( 7, 1 )
_toggle_reinf( 2, 1 )
_toggle_reinf( 3, 1 )
_toggle_reinf( 3, 2 )
_toggle_reinf( 7, 1 )
assert _generate_turn_track_snippet( dlg ) == [
[ (1,None,None), (2,"player1",None), (3,"player1","player2"),
(4,None,None), (5,None,None) , (6,None,None), (7,"player1",None)
@ -112,11 +112,11 @@ def test_turn_track_reinforcements( webapp, webdriver ):
# turn off some reinforcements, turn some on, then check the snippet
with SwitchFrame( webdriver, "#turn-track-preview" ):
_click_reinf_flag( 2, 2 )
_click_reinf_flag( 3, 1 )
_click_reinf_flag( 3, 2 )
_click_reinf_flag( 5, 2 )
_click_reinf_flag( 7, 1 )
_toggle_reinf( 2, 2 )
_toggle_reinf( 3, 1 )
_toggle_reinf( 3, 2 )
_toggle_reinf( 5, 2 )
_toggle_reinf( 7, 1 )
assert _generate_turn_track_snippet( dlg ) == [
[ (1,None,None), (2,"player1","player2"), (3,None,None),
(4,None,None), (5,None,"player2") , (6,None,None), (7,None,None)
@ -125,6 +125,40 @@ def test_turn_track_reinforcements( webapp, webdriver ):
# ---------------------------------------------------------------------
def test_turn_track_shading( webapp, webdriver ):
"""Test shading squares on the turn track."""
# initialize
webapp.control_tests.set_data_dir( "{REAL}" )
init_webapp( webapp, webdriver )
# show the turn track dialog
dlg = _show_turn_track_dialog( 6.5 )
# shade some turn track squares, then check the snippet
with SwitchFrame( webdriver, "#turn-track-preview" ):
_toggle_shading( 1 )
_toggle_shading( 2 )
_toggle_shading( 7 )
assert _generate_turn_track_snippet( dlg ) == [
[ (1,None,None,True), (2,None,None,True), (3,None,None),
(4,None,None), (5,None,None) , (6,None,None), (7,None,None,True)
]
]
# change the shading for some turn track squares, then check the snippet
with SwitchFrame( webdriver, "#turn-track-preview" ):
_toggle_shading( 1 )
_toggle_shading( 3 )
_toggle_shading( 7 )
assert _generate_turn_track_snippet( dlg ) == [
[ (1,None,None), (2,None,None,True), (3,None,None,True),
(4,None,None), (5,None,None) , (6,None,None), (7,None,None)
]
]
# ---------------------------------------------------------------------
def test_turn_track_persistence( webapp, webdriver ):
"""Test saving and loading turn track settings."""
@ -141,10 +175,12 @@ def test_turn_track_persistence( webapp, webdriver ):
# configure the turn track
with SwitchFrame( webdriver, "#turn-track-preview" ):
_click_reinf_flag( 1, 1 )
_click_reinf_flag( 2, 2 )
_click_reinf_flag( 3, 1 )
_click_reinf_flag( 3, 2 )
_toggle_reinf( 1, 1 )
_toggle_reinf( 2, 2 )
_toggle_reinf( 3, 1 )
_toggle_reinf( 3, 2 )
_toggle_shading( 2 )
_toggle_shading( 4 )
_change_turn_track_width( dlg, 4 )
_swap_turn_track_players( dlg )
_change_turn_track_direction( dlg )
@ -152,7 +188,7 @@ def test_turn_track_persistence( webapp, webdriver ):
# check the snippet
expected = [
[ (1,None,"player2"), (3,"player1","player2"), (5,None,None), (7,None,None) ],
[ (2,"player1",None) , (4,None,None), (6,None,None) ]
[ (2,"player1",None,True) , (4,None,None,True), (6,None,None) ]
]
wait_for( 2,
lambda: _generate_turn_track_snippet( dlg ) == expected
@ -164,6 +200,7 @@ def test_turn_track_persistence( webapp, webdriver ):
assert saved_scenario["TURN_TRACK"] == {
"NTURNS": "6.5",
"WIDTH": "4", "VERTICAL": True, "SWAP_PLAYERS": True,
"SHADING": "2,4",
"REINFORCEMENTS_1": "2,3", "REINFORCEMENTS_2": "1,3",
}
assert _generate_turn_track_snippet( None ) == expected
@ -264,13 +301,18 @@ def _generate_turn_track_snippet( dlg ):
return None
def unload_square( square ):
# unload the reinforcement flags
cells = square.xpath( ".//td" )
assert len(cells) == 3
return (
vals = (
int( cells[1].text ),
get_reinforce_class( cells[0] ),
get_reinforce_class( cells[2] ),
)
# check if the square is shaded
if any( s.startswith( "background-color:" ) for s in square.xpath( ".//@style" ) ):
vals = ( *vals, True )
return vals
# unload the snippet contents
squares = unload_table( "//table[@class='turn-track']", html=clipboard, unload=False )
@ -302,10 +344,16 @@ def _unload_turn_track_droplist():
keys.append( key )
return keys
def _click_reinf_flag( turn_no, player_no ):
"""Click on a reinforcement flag."""
def _toggle_reinf( turn_no, player_no ):
"""Toggle a player's reinforcements for the specified turn."""
find_child(
"#flag-{}_{} .flag-click".format( turn_no, player_no )
).click()
def _toggle_shading( turn_no ):
"""Toggle the shading for a turn track square."""
find_child(
"#flag-{}_{} .click".format( turn_no, player_no )
"#turn-square-{} .shading-click".format( turn_no )
).click()
# ---------------------------------------------------------------------

Loading…
Cancel
Save