From 1f752f501ae1e51b7c7e39e5157412915d22f734 Mon Sep 17 00:00:00 2001 From: CMDR furrycat Date: Tue, 19 Jan 2016 07:11:24 -0500 Subject: [PATCH] Validate waypoint order when defining the race. --- entry.js | 7 +++++++ images/locked.gif | Bin 0 -> 914 bytes lib/entry.php | 36 ++++++++++++++++++++++-------------- lib/race.php | 2 ++ race.js | 47 +++++++++++++++++++++++++++++++++++++++-------- style.css | 2 ++ 6 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 images/locked.gif diff --git a/entry.js b/entry.js index bd97c91..2106e61 100644 --- a/entry.js +++ b/entry.js @@ -107,6 +107,11 @@ function get_system_id(table, i) { return get_row_attribute_id(table, i, 'system'); } +/* Get leg order; for set-course races. */ +function get_course_order(table, i) { + return get_row_attribute_id(table, i, 'order'); +} + /* Pad string. */ function zero_pad(n) { if (n < 10) return '0' + String(n); @@ -344,6 +349,8 @@ function reorder_column(table, j) { for (var i = first_row(table); valid_row(table, i, 1); i++) { if (start_line(table, i) || finish_line(table, i)) continue; if (start_line(table, i + 1) || finish_line(table, i + 1)) continue; + if (get_course_order(table, i)) continue; + if (get_course_order(table, i + 1)) continue; var above = get_cell_input(i, j).value || 'zzz'; var below = get_cell_input(i + 1, j).value || 'zzz'; if (above == below) continue; diff --git a/images/locked.gif b/images/locked.gif new file mode 100644 index 0000000000000000000000000000000000000000..216833885ed5b6bf7d467deeaefce64130937f16 GIT binary patch literal 914 zcmZ?wbhEHb6kyucXhunKk!T_PpDb%kS5$e9*e#aq`TYKt|uTXA2L%UUKx!wu_(k zUi%D0M{a)uqGNZy-F@@-_1FI|zx@C7>;KRH|G)hH|Mx!vF#KoW83m&uFc2Z2_>+YZ zmR>QPK6Ye6k!zQbl3mUQgNKY>O=3-4TLTUr_U|(*e6>a4VEUuD$W+nz}04~U>xBvhE literal 0 HcmV?d00001 diff --git a/lib/entry.php b/lib/entry.php index 0dd4207..b5f1413 100644 --- a/lib/entry.php +++ b/lib/entry.php @@ -85,6 +85,17 @@ return true; } + function show_leg($station, $start_finish, $station_id, $system_id, $order, $n) { + $td_class = $start_finish ? " class=\"$start_finish\"" : ''; + echo "\n"; + $classes = array("station$station_id", "system$system_id"); + if (is_int($order)) $classes[] = "order$order"; + $class_list = implode(' ', $classes); + echo "

$station

\n"; + echo "

\n"; + echo "\n"; + } + function sort_legs($a, $b) { list($a_flags, $a_station_id, $a_system_id, $a_order) = $a; list($b_flags, $b_station_id, $b_system_id, $b_order) = $b; @@ -183,25 +194,22 @@ echo "Leg\n"; $n = 0; foreach ($legs as $station => $attributes) { - list($flags, $id, $system_id) = $attributes; + list($flags, $station_id, $system_id, $order) = $attributes; /* Skip finish line. */ if ($flags & Course::FinishFlag() && ! ($flags & Course::StartFlag())) continue; - $n++; - $label = $station; - $class = ($flags & Course::StartFlag()) ? ' class="start_line"' : ''; - echo "\n"; - echo "

$station

\n"; - echo "

\n"; - echo "\n"; + if ($flags & Course::StartFlag()) { + $class = 'start_line'; + $order = 0; + } + else $class = ''; + show_leg($station, $class, $station_id, $system_id, $order, ++$n); } foreach ($legs as $station => $attributes) { - list($flags, $id, $system_id) = $attributes; + list($flags, $station_id, $system_id, $order) = $attributes; if (! ($flags & Course::FinishFlag())) continue; - $class = ' class="finish_line"'; - echo "\n"; - echo "

$station

\n"; - echo "

\n"; - echo "\n"; + /* Last leg. */ + $order = 0; + show_leg($station, 'finish_line', $station_id, $system_id, $order, ++$n); } echo "\n"; echo ""; diff --git a/lib/race.php b/lib/race.php index 877e3e8..d02f2c6 100644 --- a/lib/race.php +++ b/lib/race.php @@ -227,6 +227,7 @@ if (do_race($name, $allotted_time, $posted)) return true; } + echo "
\n"; form(); echo "\n"; foreach ($stations as $station) { @@ -253,6 +254,7 @@ hidden('allotted_time', $allotted_time); submit('add_race', 'Submit race'); end_form(); + echo "\n"; return false; } diff --git a/race.js b/race.js index 4ec19d6..4f07761 100644 --- a/race.js +++ b/race.js @@ -42,24 +42,49 @@ function toggle_classification(event) { /* Check start and finish lines are set. */ function validate() { - var stations = 0; var flags = 0; - for (input of document.getElementsByClassName('station')) { - var value = parseInt(input.value); + var stations = []; + for (select of document.getElementsByClassName('station')) { + var value = parseInt(select.value); var flag = value & mandatory_flags; - if (value && ! flag) stations++; + if (value && ! flag) stations.push(select); flags |= flag; } var valid = (flags == mandatory_flags); if (valid) { /* Either all stations must be ordered or none. */ - var ordered = 0; + var ordered = {}; for (input of document.getElementsByTagName('input')) { if (! input.name.match(/^station\d+order$/)) continue; - if (input.value) ordered++; + if (input.value) { + ordered[input.value] = input; + /* Stations not in the course can't be ordered. */ + var select = document.getElementById(input.name.replace(/order$/, '')); + if (select && ! parseInt(select.value)) input.setCustomValidity("Not part of race"); + } + else input.setCustomValidity(""); + } + var keys = Object.keys(ordered); + if (keys.length) { + /* If one station is ordered they all must be. */ + for (select of stations) { + var input = document.getElementById(select.name + "order"); + if (input && ! input.value) input.setCustomValidity("Missing order"); + } + valid = false; + /* Ordering must be contiguous from 1. */ + for (var i = 1; i <= stations.length; i++) { + if (ordered[i]) continue; + for (var j = 0; j < keys.length; j++) { + if (parseInt(keys[j]) <= i) continue; + var input = ordered[keys[j]]; + input.setCustomValidity("Out of order"); + valid = false; + } + break; + } } - if (ordered > 0 && ordered < stations) valid = false; } var submits = document.getElementsByName('add_race'); @@ -72,7 +97,8 @@ function changed_waypoint(event) { if (input == event.target) continue; input.value &= ~(event.target.value & mandatory_flags); } - if (event.target.value & mandatory_flags) { + var flag = parseInt(event.target.value); + if (flag & mandatory_flags || ! flag) { /* Clear order. */ var input = document.getElementById(event.target.name + 'order'); if (input) input.value = ''; @@ -85,6 +111,8 @@ function changed_waypoint(event) { function changed_order(event) { var order = parseInt(event.target.value); if (order) { + var select = document.getElementById(event.target.name.replace(/order$/, '')); + if (select) select.value = 1; for (input of document.getElementsByTagName('input')) { if (input == event.target) continue; if (! input.name.match(/^station\d+order$/)) continue; @@ -102,7 +130,10 @@ function loaded() { } var waypoints = document.getElementsByClassName('station'); if (waypoints.length) { + var div = document.getElementById('waypoints'); + if (div && div.offsetHeight > window.innerHeight * 0.9) div.style.height = '80%'; for (input of waypoints) { + input.id = input.name; input.addEventListener('change', changed_waypoint, true); input.addEventListener('focusout', changed_waypoint, true); } diff --git a/style.css b/style.css index 22a3052..b157101 100644 --- a/style.css +++ b/style.css @@ -2,6 +2,7 @@ #laps table { background-color: rgba(20, 50, 100, 0.2); } #laps th, #laps td { padding-left: 1em; } #laps label:nth-child(even) { padding-top: 0.5em; padding-bottom: 0.5em; background-color: rgba(128, 128, 128, 0.1); } +#laps p[class*='order']:after { background-image: url(images/locked.gif); background-position: left center; position: relative; padding-left: 16px; background-repeat: no-repeat; content: ""; } th { text-align: left; } th:nth-child(n+2),td:nth-child(n+2) { text-align: center; } #stats td:nth-child(n+1) { text-align: left; } @@ -10,3 +11,4 @@ table.entries th, table.entries td { text-align: center; } .classification .bbcode { display: none; background-color: rgba(0, 0, 0, 0.1); } #systems { overflow-x: auto; } #stations { overflow-x: auto; } +#waypoints { overflow-x: auto; } -- 2.7.4