diff --git a/.gitignore b/.gitignore index e14fc0f6..a545a9e9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ mail.* /vendor/ +/.vs diff --git a/bup.html b/bup.html index a07c86fa..c739cddb 100644 --- a/bup.html +++ b/bup.html @@ -221,7 +221,7 @@

-
+

@@ -236,6 +236,7 @@

+
@@ -279,8 +280,8 @@

- - + + @@ -322,12 +323,12 @@

-
+
-

+
@@ -349,6 +350,11 @@

+
+
+
+
+
@@ -371,21 +377,22 @@

- +
- - - + + +
diff --git a/css/displaymode.css b/css/displaymode.css index 1cdaaa02..8215d148 100644 --- a/css/displaymode.css +++ b/css/displaymode.css @@ -1,4 +1,5 @@ .d_international_score, +.d_tournament_score, .d_clean_score, .d_score_default { font-family: 'Droid Sans', 'droid_sansregular', 'Noto Mono', Arial, sans-serif; @@ -131,12 +132,15 @@ } .d_international_team, +.d_tournament, .d_clean_team { font-stretch: condensed; position: relative; height: 50%; + text-wrap: nowrap; } .d_international_player_container, +.d_tournament_player_container .d_clean_player_container, .d_bwfonlyplayers_player_container { position: relative; @@ -153,6 +157,12 @@ display: flex; align-items: center; } +.d_tournament_player{ + width: 100%; + font-size: 1vh; + display: flex; + align-items: center; +} .d_bwf_player { width: 100%; font-size: 13vh; @@ -160,6 +170,7 @@ align-items: center; } .d_international_score, +.d_tournament_score, .d_clean_score { font-size: 50vh; line-height: 50vh; @@ -172,6 +183,7 @@ overflow: hidden; } .d_international_score.d_international_score_dd, +.d_tournament_score.d_tournament_score_dd, .d_clean_score.d_clean_score_dd { letter-spacing: -4vh; text-align: left; @@ -191,6 +203,19 @@ justify-content: center; } +.d_tournament_gscore { + font-size: 25vh; + line-height: 25vh; + position: absolute; + top: 0; + bottom: 0; + right: 52vh; + width: 20vh; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; +} .d_2court_side0, .d_2court_side1 { @@ -254,7 +279,9 @@ bottom: 0; display: flex; align-items: center; - justify-content: center; + justify-content: right; + text-wrap: nowrap; + width: calc(50vw - 44vh - 20px); } .d_2court_side0 .d_2court_info, .d_2court_side0 .d_2court_gscore { @@ -471,7 +498,7 @@ bottom: 0; display: flex; flex-direction: column; - justify-content: center; + justify-content: space-evenly; align-items: center; } diff --git a/css/network.css b/css/network.css index 38bdd68d..200e9ea5 100644 --- a/css/network.css +++ b/css/network.css @@ -119,9 +119,25 @@ button > .loading-icon { } .setup_network_match_score { font-style: italic; + font-size: 150%; + font-weight: bold; + margin-top: 10px; } .setup_network_umpire_name { - color: #444; + color: #c14949; +} +.setup_network_umpire { + color: #c14949; + font-weight: bold; + margin-top: 10px; +} + +.setup_network_tabletoperator_name { + color: #c14949; +} +.setup_network_tabletoperator { + color: #c14949; + font-weight: bold; } .setup_network_heading::after { diff --git a/css/score.css b/css/score.css index c8f95248..cc6e05ca 100644 --- a/css/score.css +++ b/css/score.css @@ -89,10 +89,10 @@ table[data-game-count="5"] .score_future-game { padding-right: 0; } .score > input { - max-width: 1.9em; + width: 1.9em; vertical-align: top; - font-size: 2vh; - max-height: 3vh; + font-size: 7.5vh; + height: 8vh; } .score_current-game > .score > input { font-size: 7.5vh; @@ -108,19 +108,19 @@ table[data-game-count="5"] .score_future-game { padding-left: 1.5vh; } -.score_counting_tr, -.score_counting_td { +.score_scoring_format_tr, +.score_scoring_format_td { height: 0; max-height: 0; margin: 0; padding: 0; } -.score_counting_container { +.score_scoring_format_container { position: relative; width: 100%; height: 0; } -.score_counting { +.score_scoring_format { position: absolute; color: #888; padding: 1vh 0; diff --git a/doc/URLs.txt b/doc/URLs.txt index 04490229..7e0100bf 100644 --- a/doc/URLs.txt +++ b/doc/URLs.txt @@ -12,26 +12,26 @@ import_url=https://... Import from the specified match URL (e.g. https://www.tu There are also many demos (which only run locally) available: -demo A one-match demo (will start right in the match) -baydemo Bayernliga demo (also applies to lower divisions) -bldemo Demo of a Bundesliga match -bldemo_incomplete Demo of a Bundesliga match where not all players have been configured yet -bldemo_inprogress Demo of a Bundesliga match already running -e_bldemo Demo of a Bundesliga match where nothing has been configured yet -edemo Demo of an event (empty) -intdemo International team match demo -tdemo International tournament demo -nlademo Demo of Swiss National League -nrwdemo Demo of a match in the lower divisions in NRW -obldemo Austrian Bundesliga demo -rlmdemo German Regionalliga Mitte demo -rlndemo German Regionalliga Nord demo -rlsodemo German Regionalliga SüdOst demo -rlwdemo German Regionalliga West demo -tdemo Tournament demo -txdemo Demo for transmission to turnier.de -vdemo Demo of an event (in progress) -wdmudemo Youth tournament demo (with lots of finals on Sunday) +demo A one-match demo (will start right in the match) +baydemo Bayernliga demo (also applies to lower divisions) +bldemo Demo of a Bundesliga match +bldemo_incomplete Demo of a Bundesliga match where not all players have been configured yet +bldemo_inprogress Demo of a Bundesliga match already running +e_bldemo Demo of a Bundesliga match where nothing has been configured yet +edemo Demo of an event (empty) +intdemo International team match demo +tdemo International tournament demo +nlademo Demo of Swiss National League +nrwdemo Demo of a match in the lower divisions in NRW +obldemo Austrian Bundesliga demo +rlmdemo German Regionalliga Mitte demo +rlndemo German Regionalliga Nord demo +rlsodemo German Regionalliga SüdOst demo +rlwdemo German Regionalliga West demo +tdemo Tournament demo +txdemo Demo for transmission to turnier.de +vdemo Demo of an event (in progress) +wdmudemo Youth tournament demo (with lots of finals on Sunday) There is also: @@ -44,19 +44,19 @@ Initial UI These can be combined with any other options (but not each other), as in #bldemo&display . -settings Show settings UI (currently the default) -nosettings Hide settings by default (click to see) -neversettings Completely hide settings in displaymode -display Start in display mode -referee_mode Start in referee mode -eventsheet=foo Show the dialog for generating the eventsheet named foo -order Show the match order dialog -mo Start with the manual order dialog (allows easy match creation and import) +settings Show settings UI (currently the default) +nosettings Hide settings by default (click to see) +neversettings Completely hide settings in displaymode +display Start in display mode +referee_mode Start in referee mode +eventsheet=foo Show the dialog for generating the eventsheet named foo +order Show the match order dialog +mo Start with the manual order dialog (allows easy match creation and import) Settings ======== -lang=LANGCODE Set language to the specified one. +lang=LANGCODE Set language to the specified one. LANGCODE can be one of: en English de German (Germany) @@ -67,39 +67,59 @@ lang=LANGCODE Set language to the specified one. court=COURTCODE Run on the specified court. COURTCODE depends on the network. Normally, a number like 1, 2, or the string "referee". dm_style=STYLECODE In display mode, start with the specified style. Available styles: - teamcourt Best for team matches. Supports interval timer. - international Best for individual international tournaments - bwf Like international, but geared towards the BWF understanding of names ("LASTNAME, Firstname") - clean Classic style for (national) individual tournaments - 2court Large scores for 2 courts. Supports interval timer. - andre Simple 1-court display, shows game count to the left - castall Greenscreen (all courts) - stream Transparent video overlay - streamcourt Transparent video overlay, one court only (to be scaled in streaming software) - streamteam Transparent video overlay, only team names & match result (scales by width) - greyish Overview for team competitions with muted gray colors - oncourt court score with teams, not colored, including points in all games - onlyplayers players only - bwfonlyplayers players only, in BWF definition of names ("LASTNAME, Firstname" and fixed font size) - onlyscore score (all games) only - giantscore score (current game + game count) only, for very small screens - clubplayers team + players - clubplayerslr team + players (home left / away right) - stripes stripes (vertically: team names, clubs, all scores, for one court) - teamscore Just team names and number of won matches - tim Colored overview of a team competition - top+list Current matches on top, list of all matches below - tournament_overview Shows all courts at once -show_pause=BOOLEAN Show or hide interval timers. - BOOLEAN can be either "true" or "false". - At the moment only supported for some styles, see above. -team_colors=BOOLEAN Use team colors (if applicable in the given style). - BOOLEAN can be either "true" or "false". -d_c0=COLOR, This group of options can be used to set displaymode colors. -d_c1=COLOR, COLOR can be an RGB color value, for instance "0f0" or "00ff00" for lime. -d_cfg=COLOR, d_c0 and d_c1 are the colors for the home and away team, -d_cbg=COLOR, d_cfg the foreground and d_bg the background color, -d_cbg2=COLOR, ... and there are a lot more color names available. - Different styles use different color names. - Hover over a color input in the displaymode or referee UI to get the color names. -hub_url=WSURL WebSocket URL (starting with ws:// or wss://) of the referee mode hub. + teamcourt Best for team matches. Supports interval timer. + international Best for individual international tournaments + bwf Like international, but geared towards the BWF understanding of names ("LASTNAME, Firstname") + tournamentcourt Best for (national) individual tournaments. Supports interval timer, court number, competition, round, remove middle names and underline the receiving player in doubles. + tournamentplayers Best for (national) individual tournaments. Supports interval timer, court number, competition, round, remove middle names and underline the receiving player in doubles. Show only the Players. Use it in combination with onlyscore. + tournament_overview_dm Best for the German Championships 2025 tournament overview. Shows current scores for many courts in a DM-specific layout. + tournament_overview_dm_finals Best for the German Championships 2025 finals overview. Uses the DM layout focused on finals matches. + clean Classic style for (national) individual tournaments + 2court Large scores for 2 courts. Supports interval timer. + andre Simple 1-court display, shows game count to the left + castall Greenscreen (all courts) + stream Transparent video overlay + streamcourt Transparent video overlay, one court only (to be scaled in streaming software) + streamcourt_dm Transparent video overlay, one court only with additional information and ci of dm 2025 in Cloppenburg + streamteam Transparent video overlay, only team names & match result (scales by width) + greyish Overview for team competitions with muted gray colors + oncourt court score with teams, not colored, including points in all games + onlyplayers players only + bwfonlyplayers players only, in BWF definition of names ("LASTNAME, Firstname" and fixed font size) + onlyscore score (all games) only + giantscore score (current game + game count) only, for very small screens + clubplayers team + players + clubplayerslr team + players (home left / away right) + stripes stripes (vertically: team names, clubs, all scores, for one court) + teamscore Just team names and number of won matches + tim Colored overview of a team competition + top+list Current matches on top, list of all matches below + tournament_overview Shows all courts at once +show_pause=BOOLEAN Show or hide interval timers. + BOOLEAN can be either "true" or "false". + At the moment only supported for some styles, see above. +show_court_number=BOOLEAN Show or hide court number. + BOOLEAN can be either "true" or "false". + At the moment only supported for some styles, see above. +show_competition=BOOLEAN Show or hide competition. + BOOLEAN can be either "true" or "false". + At the moment only supported for some styles, see above. +show_round=BOOLEAN Show or hide round. + BOOLEAN can be either "true" or "false". + At the moment only supported for some styles, see above. +show_middle_name=BOOLEAN Show or hide the middle name of the players. + BOOLEAN can be either "true" or "false". + At the moment only supported for some styles, see above. +show_doubles_receiving=BOOLEAN Underline the receiving player in doubles. + BOOLEAN can be either "true" or "false". + At the moment only supported for some styles, see above. +team_colors=BOOLEAN Use team colors (if applicable in the given style). + BOOLEAN can be either "true" or "false". +d_c0=COLOR, This group of options can be used to set displaymode colors. +d_c1=COLOR, COLOR can be an RGB color value, for instance "0f0" or "00ff00" for lime. +d_cfg=COLOR, d_c0 and d_c1 are the colors for the home and away team, +d_cbg=COLOR, d_cfg the foreground and d_bg the background color, +d_cbg2=COLOR, ... and there are a lot more color names available. + Different styles use different color names. + Hover over a color input in the displaymode or referee UI to get the color names. +hub_url=WSURL WebSocket URL (starting with ws:// or wss://) of the referee mode hub. diff --git a/icons/Ball_DM_Cloppenburg.svg b/icons/Ball_DM_Cloppenburg.svg new file mode 100644 index 00000000..4be2d3c7 --- /dev/null +++ b/icons/Ball_DM_Cloppenburg.svg @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/icons/Ball_DM_Cloppenburg_nur_Hintergund.svg b/icons/Ball_DM_Cloppenburg_nur_Hintergund.svg new file mode 100644 index 00000000..0770562c --- /dev/null +++ b/icons/Ball_DM_Cloppenburg_nur_Hintergund.svg @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/icons/Ball_DM_Cloppenburg_ohne_Hintergund.svg b/icons/Ball_DM_Cloppenburg_ohne_Hintergund.svg new file mode 100644 index 00000000..bcba6774 --- /dev/null +++ b/icons/Ball_DM_Cloppenburg_ohne_Hintergund.svg @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/icons/Ball_DM_Cloppenburg_schwarz.svg b/icons/Ball_DM_Cloppenburg_schwarz.svg new file mode 100644 index 00000000..478a8c5b --- /dev/null +++ b/icons/Ball_DM_Cloppenburg_schwarz.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/icons/DBM_Schriftzug_mit_73_wiess.svg b/icons/DBM_Schriftzug_mit_73_wiess.svg new file mode 100644 index 00000000..5039fd46 --- /dev/null +++ b/icons/DBM_Schriftzug_mit_73_wiess.svg @@ -0,0 +1,36 @@ + + + + + + + + + \ No newline at end of file diff --git a/js/btde.js b/js/btde.js index 1df18021..a65e69ff 100644 --- a/js/btde.js +++ b/js/btde.js @@ -209,13 +209,18 @@ function _get_league_key(liga_code) { } function _get_counting(league_key, event_data) { + var scoring_format = _get_scoring_format(league_key, event_data); + return scoring_format ? scoring_format.name : undefined; +} + +function _get_scoring_format(league_key, event_data) { if (league_key) { - var league_counting = eventutils.default_counting(league_key); - if (league_counting) { - return league_counting; + var league_scoring_format = eventutils.default_scoring_format(league_key); + if (league_scoring_format) { + return league_scoring_format; } } - return (event_data.gews == 2) ? '3x21' : '5x11_15^90'; + return calc.scoring_format_from_counting((event_data.gews == 2) ? '3x21' : '5x11_15^90'); } function _parse_event(s, doc, now) { @@ -232,10 +237,12 @@ function _parse_event(s, doc, now) { } var counting; + var scoring_format; var league_key; var team_competition = true; if (event_data.league === 'Turnier') { - counting = '3x21'; + scoring_format = calc.scoring_format_from_counting('3x21'); + counting = scoring_format.name; team_competition = false; } else { if (event_data.league) { @@ -248,7 +255,8 @@ function _parse_event(s, doc, now) { report_problem.silent_error('btde: league key missing'); league_key = (doc.fixtures.length === 8) ? 'RLW-2016' : '1BL-2020'; } - counting = _get_counting(league_key, event_data); + scoring_format = _get_scoring_format(league_key, event_data); + counting = scoring_format ? scoring_format.name : undefined; // Fallback: if everything goes wrong, go for 1BL if (! league_key && (counting == '5x11_15^90')) { league_key = '1BL-2020'; @@ -302,6 +310,7 @@ function _parse_event(s, doc, now) { var setup = { counting: counting, + scoring_format: scoring_format || calc.scoring_format_from_counting(counting), eventsheet_id: eventsheet_id, match_name: match.dis, is_doubles: is_doubles, @@ -547,6 +556,7 @@ return { // Testing only /*@DEV*/ _get_counting: _get_counting, + _get_scoring_format: _get_scoring_format, _get_league_key: _get_league_key, _parse_event: _parse_event, _calc_send_data: _calc_send_data, diff --git a/js/btsh.js b/js/btsh.js index bfdc60c7..05c266f9 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -2,203 +2,383 @@ // BTS support (https://github.com/phihag/bts/) via HTTP function btsh(baseurl, tournament_key) { -var battery; -if (!battery && (typeof navigator != 'undefined') && navigator.getBattery) { - navigator.getBattery().then(function(bat) { - battery = bat; - }); -} + var ws = null; + var WS_PATH = '/ws/bup'; + var reconnect_timeout = 1000; + var bts_update_callback = null; + var bts_update_courts_callback = null; + var display_initialized = false; + var battery; + -function _bat_status() { - if (!battery) { - return undefined; + if (!battery && (typeof navigator != 'undefined') && navigator.getBattery) { + navigator.getBattery().then(function(bat) { + battery = bat; + }); } - return { - charging: battery.charging, - level: battery.level, - chargingTime: battery.chargingTime, - dischargingTime: battery.dischargingTime, - }; -} -function _device_data() { - return { - id: refmode_client_ui.get_node_id(), - battery: _bat_status(), - court: state.settings.court_id, - }; -} - -function _request_json(s, component, options, cb) { - options.dataType = 'text'; - options.timeout = s.settings.network_timeout; - network.$request(component, options).done(function(res_json) { - try { - var res = JSON.parse(res_json); - } catch (e) { - return cb(e); + function _bat_status() { + if (!battery) { + return undefined; } + return { + charging: battery.charging, + level: battery.level, + chargingTime: battery.chargingTime, + dischargingTime: battery.dischargingTime, + }; + } - if (res.status !== 'ok') { - return cb({msg: res.message + ' ' + s._('network:error:status', {status: res.status})}); - } + function _device_data() { + return { + id: refmode_client_ui.get_node_id(), + battery: _bat_status(), + court: state.settings.court_id, + }; + } - return cb(null, res); - }).fail(function (xhr) { - var msg = ((xhr.status === 0) ? - s._('network:error:bts') : - s._('network:error:http', {code: xhr.status}) - ); - return cb({ - type: 'network-error', - status: xhr.status, - msg: msg, - }); - }); -} + function _request_json(s, component, options, cb) { + options.dataType = 'text'; + options.timeout = s.settings.network_timeout; + network.$request(component, options).done(function(res_json) { + try { + var res = JSON.parse(res_json); + } catch (e) { + return cb(e); + } -function send_score(s) { - if (s.settings.court_id === 'referee') { - network.errstate('btsh.score', null); - return; - } - if (! /^bts_/.test(s.setup.match_id)) { - return; - } - var req_match_id = s.setup.match_id; - var match_id = req_match_id.substring('bts_'.length); - - var netscore = calc.netscore(s, true); - var duration_ms = (s.metadata.start && s.metadata.end) ? (s.metadata.end - s.metadata.start) : null; - var end_ts = s.metadata.end ? s.metadata.end : null; - var post_data = { - court_id: s.settings.court_id, - network_team1_serving: s.game.team1_serving, - network_teams_player1_even: s.game.teams_player1_even, - network_score: netscore, - team1_won: s.match.team1_won, - presses: s.presses, - duration_ms: duration_ms, - end_ts: end_ts, - marks: s.match.marks, - shuttle_count: s.match.shuttle_count, - device: _device_data(s, post_data), - }; + if (res.status !== 'ok') { + return cb({msg: res.message + ' ' + s._('network:error:status', {status: res.status})}); + } - var url = baseurl + 'h/' + encodeURIComponent(tournament_key) + '/m/' + encodeURIComponent(match_id) + '/score'; + return cb(null, res); + }).fail(function (xhr) { + var msg = ((xhr.status === 0) ? + s._('network:error:bts') : + s._('network:error:http', {code: xhr.status}) + ); + return cb({ + type: 'network-error', + status: xhr.status, + msg: msg, + }); + }); + } - _request_json(s, 'btsh.score', { - method: 'POST', - url: url, - data: JSON.stringify(post_data), - contentType: 'application/json; charset=utf-8', - }, function(err) { - if (s.setup.match_id !== req_match_id) { // Match changed while the request was underway + function send_score(s) { + if (s.settings.court_id === 'referee') { + network.errstate('btsh.score', null); + return; + } + if (! /^bts_/.test(s.setup.match_id)) { return; } + const req_match_id = s.setup.match_id; + const match_id = req_match_id.substring('bts_'.length); - network.errstate('btsh.score', err); - }); -} + const netscore = calc.netscore(s, true); + const duration_ms = (s.metadata.start && s.metadata.end) ? (s.metadata.end - s.metadata.start) : null; + const end_ts = s.metadata.end ? s.metadata.end : null; + const score_data = { + court_id: s.settings.court_id, + match_id: match_id, + network_team1_serving: s.game.team1_serving, + network_teams_player1_even: s.game.teams_player1_even, + network_score: netscore, + team1_won: s.match.team1_won, + finish_confirmed: s.match.finish_confirmed, + presses: s.presses, + duration_ms: duration_ms, + end_ts: end_ts, + marks: s.match.marks, + shuttle_count: s.match.shuttle_count, + device: _device_data(), + }; + send_score_changed(score_data); + } -function sync(s) { - send_score(s); -} + function sync(s) { + send_score(s); + } -/* s, press */ -function send_press(s) { - sync(s); -} + /* s, press */ + function send_press(s) { + sync(s); + } -function list_matches(s, cb) { - var court_id = ''; - if ((s.ui && s.ui.displaymode_visible)) { - var style = s.settings.displaymode_style; - if (displaymode.option_applies(style, 'court_id') && (style != '2court')) { - court_id = s.settings.displaymode_court_id; + function fetch_courts(s, callback) { + bts_update_courts_callback = callback; + connect(); + if (s.btsh_courts && s.btsh_courts != null){ + callback(null, s.btsh_courts); } - } else { - court_id = s.settings.court_id; } - var filter = court_id ? ('court=' + encodeURIComponent(court_id)) : ''; - var device_url = '&device=' + encodeURIComponent(btoa(JSON.stringify(_device_data(s)))); - _request_json(s, 'btsh.list', { - url: baseurl + 'h/' + encodeURIComponent(tournament_key) + '/matches?' + filter + device_url, - }, function(err, answer) { - if (err) { - return cb(err); + function ui_init() { + if (!baseurl) { + baseurl = '../'; + } + var m = window.location.pathname.match(/^(.*\/)bup\/(?:bup\.html|index\.html)?$/); + if (m) { + baseurl = m[1]; } - var ev = answer.event; - eventutils.annotate(s, ev); + click.qs('.settings_send_export', function (e) { + e.preventDefault(); + persist_display_settings(); + }); + click.qs('.settings_reset_export', function (e) { + e.preventDefault(); + reset_display_settings(); + }); + } - return cb(null, ev); - }); -} + async function persist_display_settings() { + ws_send({ type: 'persist_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); + } + + async function reset_display_settings() { + ws_send({ type: 'reset_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); + } + + async function send_device_info() { + ws_send({ type: 'device_info', tournament_key: tournament_key, device: _device_data() }); + setTimeout(send_device_info, 1000*60*5); + } + async function send_score_changed(score) { + network.errstate('btsh.score', null); + ws_send({ type: 'score_update', tournament_key: tournament_key, score: score }); + } -function fetch_courts(s, callback) { - var device_url = '?device=' + encodeURIComponent(btoa(JSON.stringify(_device_data(s)))); - _request_json(s, 'btsh.courts', { - url: baseurl + 'h/' + encodeURIComponent(tournament_key) + '/courts' + device_url, - }, function(err, response) { - if (err) { - return callback(err); + async function send_command_done(command) { + ws_send({ type: 'command_done', tournament_key: tournament_key, wait_for_command: command}) + } + + function confirm_match_finished() { + if (state.match && (state.match.team1_won != null) && state.metadata.end && state.metadata.end != null){ + control.post_match_confirm(state); + } + } + + async function ws_send(json) { + if (ws == null) { + connect(); } + ws.sendmsg(json); + } + + function service_name() { + return 'BTSh'; + } + + function editable(/*s*/) { + return false; + } + + function courts(s) { + return s.btsh_courts; + } - var courts = response.courts.map(function(rc) { - var res = { - id: rc._id, - label: rc.num, - }; - if (rc.match_id) { - res.match_id = 'bts_' + rc.match_id; + function connect() { + try { + if (ws == null) { + ws = new WebSocket(construct_url(WS_PATH), 'bts-bup'); + ws.sendmsg = ws_sendmsg; + ws.onopen = function () { + reload_match_information(); + send_device_info(); + match_storage.remove_all(12); + }; + ws.onmessage = handle_message; + ws.onclose = function () { + ws = null; + send_bts_not_reachable(); + setTimeout(connect, reconnect_timeout); + }; } - return res; - }); - courts.push({ - id: 'referee', - description: s._('court:referee'), + } catch (e) { + ws = null; + send_bts_not_reachable(); + setTimeout(connect, reconnect_timeout); + } + } + function construct_url(abspath) { + var l = window.location; + return ( + ((l.protocol === 'https:') ? 'wss://' : 'ws://') + + l.hostname + + (((l.port !== 80) && (l.port !== 443)) ? ':' + l.port : '') + + abspath + ); + } + + async function ws_sendmsg(msg) { + + waitForSocketConnection(ws, () => { + const msg_json = JSON.stringify(msg); + ws.send(msg_json); }); - s.btsh_courts = courts; - return callback(err, courts); - }); -} -function ui_init() { - if (!baseurl) { - baseurl = '../'; } - var m = window.location.pathname.match(/^(.*\/)bup\/(?:bup\.html|index\.html)?$/); - if (m) { - baseurl = m[1]; + + // Make the function wait until the connection is made... + function waitForSocketConnection(socket, callback){ + setTimeout( + function () { + if (socket.readyState === 1) { + if (callback != null){ + callback(); + } + } else { + waitForSocketConnection(socket, callback); + } + + }, 5); // wait 5 milisecond for the connection... + } + + function handle_message(ws_msg) { + var msg_json = ws_msg.data; + var msg = JSON.parse(msg_json); + if (!msg) { + send({ + type: 'error', + message: 'Could not parse message', + }); + } + switch (msg.type) { + case 'change': + default_change_handler(msg); + break; + case 'error': + network.errstate('btsh.score', msg); + break; + default: + send({ + type: 'error', + rid: msg.rid, + message: 'Unsupported message ' + msg.type, + }); + } } -} -function service_name() { - return 'BTSh'; -} + function default_change_handler(c) { + switch (c.ctype) { + case 'score-update': + if (bts_update_callback != null) { + bts_update_callback(null, state, c.val.event); + if (state.settings.court_id != '' && c.val.event.matches[0] && c.val.event.matches[0].end_ts != null) { + setTimeout(reload_match_information, 60000); + } + } else { + if (state && state != null) { + state.bts_event = c.val.event; + } + } + break; + case 'settings-update': + state.settings = c.val; + state.dads = c.val.advertisements; + settings.update(state); + settings.on_mode_change(state); + break; + case 'confirm-match-finished': + confirm_match_finished(); + break; + case 'advertisement_add': + state.dads.push(c.val) + break; + case 'advertisement_remove': + if (state.dads) { + const changed_t = utils.find(state.dads, m => m._id === c.val.advertisement_id); + if (changed_t) { + state.dads.splice(state.dads.indexOf(changed_t), 1); + } + } + break; + case 'courts-update': + var courts = c.val.map(function (rc) { + var res = { + id: rc._id, + label: rc.num, + }; + if (rc.match_id) { + res.match_id = 'bts_' + rc.match_id; + } + send_command_done(c); + return res; + }); + courts.push({ + id: 'referee', + description: state._('court:referee'), + }); -function editable(/*s*/) { - return false; -} + state.btsh_courts = courts; + if (bts_update_courts_callback && bts_update_courts_callback != null) { + bts_update_courts_callback(null, state.btsh_courts); + } + if(state.settings.devicemode == "umpire") { + if (!state.initialized || !state.match || state.match.finish_confirmed) { + settings.show(); + settings.on_mode_change(state); + } + } else { + settings.hide_displaymode(); + } + break; + default: + break; + } + send_command_done(c); + } -function courts(s) { - return s.btsh_courts; -} + function reload_match_information() { + if (state.ui.displaymode_visible) { + var style = state.settings.displaymode_style; + if (displaymode.option_applies(style, 'court_id') && (style != '2court')) { + state.settings.court_id = state.settings.displaymode_court_id; + } else { + state.settings.court_id = '' + } + + } else { + state.settings.court_id = state.settings.displaymode_court_id; + } + ws.sendmsg({ type: 'init', initialize_display: !display_initialized, tournament_key: tournament_key, panel_settings: state.settings }); + display_initialized = true; + } + + function subscribe(s, cb, calc_timeout) { + bts_update_callback = cb; + if (state && state.bts_event && state.bts_event != null) { + bts_update_callback(null, state, state.bts_event); + state.bts_event = null; + } + connect(); + } -return { - ui_init: ui_init, - send_press: send_press, - list_matches: list_matches, - sync: sync, - courts: courts, - fetch_courts: fetch_courts, - service_name: service_name, - editable: editable, - limited_ui: true, -}; + function send_bts_not_reachable() { + if (bts_update_callback && bts_update_callback != null) { + var msg = state._('network:error:bts'); + bts_update_callback({ + type: 'network-error', + msg: msg, + }, state, null); + } + } + return { + ui_init: ui_init, + send_press: send_press, + sync: sync, + courts: courts, + fetch_courts: fetch_courts, + service_name: service_name, + editable: editable, + limited_ui: true, + push_service: true, + subscribe: subscribe, + reload_match_information: reload_match_information, + }; } /*@DEV*/ @@ -208,6 +388,7 @@ if ((typeof module !== 'undefined') && (typeof require !== 'undefined')) { var eventutils = require('./eventutils'); var network = require('./network'); var refmode_client_ui = require('./refmode_client_ui'); + var click = require('./click'); module.exports = btsh; } diff --git a/js/calc.js b/js/calc.js index db6b1be9..72e1be88 100644 --- a/js/calc.js +++ b/js/calc.js @@ -27,54 +27,211 @@ function players_present(s) { ); } -function match_started(game_scores) { - return (game_scores.length > 0) && ((game_scores[0][0] > 0) || (game_scores[0][1] > 0)); -} + function match_started(game_scores) { + return (game_scores.length > 0) && ((game_scores[0][0] > 0) || (game_scores[0][1] > 0)); + } -function _is_winner(counting, game_idx, candidate, other) { - if ((counting === '3x21') || (counting === '1x21') || ((counting === '2x21+11') && (game_idx < 2))) { - return ( - ((candidate == 21) && (other < 20)) || - ((candidate > 21) && (candidate <= 30) && (other == candidate - 2)) || - (candidate == 30) && (other == 29) - ); + function scoring_format_from_counting(counting) { + var scoring_format = _legacy_scoring_format(counting); + if (!scoring_format) { + return scoring_format; + } + scoring_format = utils.deep_copy(scoring_format); + if (counting !== undefined) { + scoring_format.name = counting; + } + return scoring_format; } - if ((counting === '5x11_15') || (counting === '5x11_15^90') || (counting === '5x11_15~NLA') || (counting === '1x11_15') || ((counting === '2x21+11') && (game_idx === 2))) { - return ( - ((candidate == 11) && (other < 10)) || - ((candidate > 11) && (candidate <= 15) && (other == candidate - 2)) || - (candidate == 15) && (other == 14) - ); + + function setup_from_counting(counting) { + return { + counting: counting, + scoring_format: scoring_format_from_counting(counting), + }; } - if (counting === '5x11/3') { - return ( - ((candidate == 11) && (other < 10)) || - ((candidate == 13) && (other >= 10) && (other < 13)) - ); + + function setup_from_scoring_format(scoring_format) { + var normalized_scoring_format = scoring_format ? utils.deep_copy(scoring_format) : scoring_format; + return { + counting: normalized_scoring_format && normalized_scoring_format.name, + scoring_format: normalized_scoring_format, + }; + } + + function _legacy_scoring_format(counting) { + switch (counting) { + case '3 x 21 Punkte': + case '3x21': + return { + numSets: 3, + set_points: { end_points: 21, max_points: 30, interval_at: 11, interval_duration_ms: 60000, break_before_set_duration_ms: 120000 }, + last_set_points: { end_points: 21, max_points: 30, interval_at: 11, interval_duration_ms: 60000, break_before_set_duration_ms: 120000 }, + }; + case '1x21': + return { + numSets: 1, + set_points: { end_points: 21, max_points: 30, interval_at: 11, interval_duration_ms: 60000, break_before_set_duration_ms: null }, + last_set_points: { end_points: 21, max_points: 30, interval_at: 11, interval_duration_ms: 60000, break_before_set_duration_ms: null }, + }; + case '2x21+11': + return { + numSets: 3, + set_points: { end_points: 21, max_points: 30, interval_at: 11, interval_duration_ms: 60000, break_before_set_duration_ms: 120000 }, + last_set_points: { end_points: 11, max_points: 15, interval_at: 6, interval_duration_ms: 60000, break_before_set_duration_ms: 120000 }, + }; + case '5x11_15': + return { + numSets: 5, + set_points: { end_points: 11, max_points: 15, interval_at: null, interval_duration_ms: null, break_before_set_duration_ms: 60000 }, + last_set_points: { end_points: 11, max_points: 15, interval_at: 6, interval_duration_ms: 60000, break_before_set_duration_ms: 60000 }, + }; + case '5x11_15^90': + return { + numSets: 5, + set_points: { end_points: 11, max_points: 15, interval_at: null, interval_duration_ms: null, break_before_set_duration_ms: 90000 }, + last_set_points: { end_points: 11, max_points: 15, interval_at: 6, interval_duration_ms: 90000, break_before_set_duration_ms: 90000 }, + }; + case '5x11_15~NLA': + return { + numSets: 5, + set_points: { end_points: 11, max_points: 15, interval_at: null, interval_duration_ms: null, break_before_set_duration_ms: 120000 }, + last_set_points: { end_points: 11, max_points: 15, interval_at: 6, interval_duration_ms: 60000, break_before_set_duration_ms: 120000 }, + }; + case '1x11_15': + return { + numSets: 1, + set_points: { end_points: 11, max_points: 15, interval_at: 6, interval_duration_ms: 60000, break_before_set_duration_ms: null }, + last_set_points: { end_points: 11, max_points: 15, interval_at: 6, interval_duration_ms: 60000, break_before_set_duration_ms: null }, + }; + case '5x11/3': + return { + numSets: 5, + set_points: { end_points: 11, max_points: 13, max_points_min_other: 10, max_only_after_deuce: true, interval_at: null, interval_duration_ms: null, break_before_set_duration_ms: 60000 }, + last_set_points: { end_points: 11, max_points: 13, max_points_min_other: 10, max_only_after_deuce: true, interval_at: 6, interval_duration_ms: 60000, break_before_set_duration_ms: 60000 }, + }; + case '3x15_18': + return { + numSets: 3, + set_points: { end_points: 15, max_points: 18, interval_at: 8, interval_duration_ms: 60000, break_before_set_duration_ms: 120000 }, + last_set_points: { end_points: 15, max_points: 18, interval_at: 8, interval_duration_ms: 60000, break_before_set_duration_ms: 120000 }, + }; + case '5x11_11': + return { + numSets: 5, + set_points: { end_points: 11, max_points: 11, interval_at: null, interval_duration_ms: null, break_before_set_duration_ms: 60000 }, + last_set_points: { end_points: 11, max_points: 11, interval_at: 6, interval_duration_ms: 60000, break_before_set_duration_ms: 60000 }, + }; + default: + return null; + } } - if (counting === '3x15_18') { + + function _normalize_setup(setup_or_counting) { + if ((typeof setup_or_counting === 'string') || !setup_or_counting) { + return setup_from_counting(setup_or_counting); + } + + var setup = setup_or_counting; + var fallback = scoring_format_from_counting(setup.counting); + var scoring_format = setup.scoring_format ? utils.deep_copy(setup.scoring_format) : {}; + + if ((! scoring_format.numSets) && fallback) { + scoring_format.numSets = fallback.numSets; + } + if ((! scoring_format.set_points) && fallback) { + scoring_format.set_points = fallback.set_points; + } + if ((! scoring_format.last_set_points) && fallback) { + scoring_format.last_set_points = fallback.last_set_points; + } + + return { + counting: (setup.scoring_format && setup.scoring_format.name) || setup.counting, + scoring_format: Object.keys(scoring_format).length > 0 ? scoring_format : fallback, + }; + } + + function _set_points_for_game(setup_or_counting, game_idx) { + var normalized = _normalize_setup(setup_or_counting); + var scoring_format = normalized.scoring_format; + if (! scoring_format) { + throw new Error('Invalid counting scheme ' + normalized.counting); + } + var total_sets = Number(scoring_format.numSets); + var is_last_possible_set = Number.isFinite(total_sets) && (game_idx === total_sets - 1); return ( - ((candidate == 15) && (other < 14)) || - ((candidate > 15) && (candidate <= 18) && (other == candidate - 2)) || - (candidate == 18) && (other == 17) + (is_last_possible_set ? scoring_format.last_set_points : scoring_format.set_points) || + scoring_format.set_points || + scoring_format.last_set_points ); } - if (counting === '5x11_11') { - return (candidate === 11) && (other < 11); + + function _required_wins(setup_or_counting) { + var normalized = _normalize_setup(setup_or_counting); + var scoring_format = normalized.scoring_format; + if (! scoring_format || !Number.isFinite(Number(scoring_format.numSets))) { + throw new Error('Invalid counting scheme ' + normalized.counting); + } + return Math.floor(Number(scoring_format.numSets) / 2) + 1; } - throw new Error('Invalid counting scheme ' + counting); -} + function _is_winner(setup_or_counting, game_idx, candidate, other) { + var set_points = _set_points_for_game(setup_or_counting, game_idx); + var end_points = set_points && Number(set_points.end_points); + var max_points = set_points && Number(set_points.max_points); + var max_points_min_other = set_points && Number(set_points.max_points_min_other); + var max_only_after_deuce = !!(set_points && set_points.max_only_after_deuce); + + if (Number.isFinite(end_points) && Number.isFinite(max_points)) { + return ( + ((candidate === end_points) && (other < end_points - 1)) || + (!max_only_after_deuce && (candidate > end_points) && (candidate <= max_points) && (other === candidate - 2)) || + ((candidate === max_points) && ( + (Number.isFinite(max_points_min_other) && (other >= max_points_min_other) && (other < max_points)) || + (!Number.isFinite(max_points_min_other) && (other === max_points - 1)) + )) + ); + } + + return false; + } function warmup_timer(s, cointoss_ts) { switch (s.setup.warmup) { case 'none': return false; + case 'call-down': + // This case covers a feature of BTS in which the warm-up countdown starts the moment + // the game is called. The time can be set in BTS. + return { + start: s.setup.called_timestamp, + duration: s.setup.warmup_start * 1000, + exigent: Math.max(0, s.setup.warmup_start-s.setup.warmup_ready) * 1000 + 499, + restart: false, + }; + case 'call-up': + // This case covers a feature of BTS in which the warm-up timer starts the moment + // the game is called. The timer runs upward until the Game starts. + return { + start: s.setup.called_timestamp, + upwards: true, + restart: false, + }; + case 'choise': + // This case covers a feature of BTS in which the warm-up timer starts the moment + // of the cointoss (first tablet interaction of the umpire). The time can be set in BTS. + return { + start: cointoss_ts, + duration: s.setup.warmup_start * 1000, + exigent: Math.max(0, s.setup.warmup_start-s.setup.warmup_ready) * 1000 + 499, + restart: true, + }; case 'bwf-2016': return { start: cointoss_ts, duration: 120000, exigent: 30499, + restart: true, }; case 'legacy': default: @@ -82,6 +239,7 @@ function warmup_timer(s, cointoss_ts) { start: cointoss_ts, duration: 120000, exigent: 5499, + restart: true, }; } } @@ -130,16 +288,16 @@ function all_games(s) { } -function gamescore(s) { - var gscores = [0, 0]; - all_games(s).forEach(function(g, game_idx) { - var gs = g.score; - var winner = game_winner(s.setup.counting, game_idx, gs[0], gs[1]); - if (winner == 'left') { - gscores[0]++; - } else if (winner == 'right') { - gscores[1]++; - } + function gamescore(s) { + var gscores = [0, 0]; + all_games(s).forEach(function(g, game_idx) { + var gs = g.score; + var winner = game_winner(s.setup, game_idx, gs[0], gs[1]); + if (winner == 'left') { + gscores[0]++; + } else if (winner == 'right') { + gscores[1]++; + } }); return gscores; } @@ -166,104 +324,71 @@ function score_str(s, left_id) { return res; } -// Returns: -// 'inprogress' for game in progress -// 'invalid' if the score can't happen -// 'left' if left side won this game -// 'right' if right side won this game -function game_winner(counting, game_idx, left_score, right_score) { - if (_is_winner(counting, game_idx, left_score, right_score)) { - return 'left'; - } - if (_is_winner(counting, game_idx, right_score, left_score)) { - return 'right'; - } - if ((counting === '3x21') || (counting === '1x21') || ((counting === '2x21+11') && (game_idx < 2))) { - if ((left_score < 21) && (right_score < 21)) { - return 'inprogress'; - } - if ((left_score < 30) && (right_score >= left_score - 1) && (right_score <= left_score + 1)) { - return 'inprogress'; - } - } else if ((counting === '5x11_15') || (counting === '5x11_15^90') || (counting === '5x11_15~NLA') || (counting === '1x11_15') || ((counting === '2x21+11') && (game_idx === 2))) { - if ((left_score < 11) && (right_score < 11)) { - return 'inprogress'; - } - if ((left_score < 15) && (right_score >= left_score - 1) && (right_score <= left_score + 1)) { - return 'inprogress'; + // Returns: + // 'inprogress' for game in progress + // 'invalid' if the score can't happen + // 'left' if left side won this game + // 'right' if right side won this game + function game_winner(setup_or_counting, game_idx, left_score, right_score) { + if (_is_winner(setup_or_counting, game_idx, left_score, right_score)) { + return 'left'; } - } else if (counting === '5x11_11') { - if ((left_score < 11) && (right_score < 11)) { - return 'inprogress'; - } - } else if (counting === '5x11/3') { - if ((left_score < 11) && (right_score < 11)) { - return 'inprogress'; + if (_is_winner(setup_or_counting, game_idx, right_score, left_score)) { + return 'right'; } - if ((left_score >= 10) && (left_score < 13) && (right_score >= 10) && (right_score < 13)) { + var set_points = _set_points_for_game(setup_or_counting, game_idx); + var end_points = set_points && Number(set_points.end_points); + var max_points = set_points && Number(set_points.max_points); + var max_points_min_other = set_points && Number(set_points.max_points_min_other); + var max_only_after_deuce = !!(set_points && set_points.max_only_after_deuce); + if (Number.isFinite(end_points) && (left_score < end_points) && (right_score < end_points)) { return 'inprogress'; } - } else if (counting === '3x15_18') { - if ((left_score < 15) && (right_score < 15)) { + if ( + max_only_after_deuce && + Number.isFinite(max_points) && + Number.isFinite(max_points_min_other) && + (left_score >= max_points_min_other) && + (right_score >= max_points_min_other) && + (left_score < max_points) && + (right_score < max_points) + ) { return 'inprogress'; } - if ((left_score < 18) && (right_score >= left_score - 1) && (right_score <= left_score + 1)) { + if ( + Number.isFinite(max_points) && + (left_score < max_points) && + (right_score >= left_score - 1) && + (right_score <= left_score + 1) + ) { return 'inprogress'; } + return 'invalid'; } - return 'invalid'; -} -function winning_game_count(counting) { - switch (counting) { - case '5x11_15': - case '5x11_15^90': - case '5x11_15~NLA': - case '5x11/3': - case '5x11_11': - return 3; - case '3x21': - case '2x21+11': - case '3x15_18': - return 2; - case '1x21': - case '1x11_15': - return 1; - default: - throw new Error('Invalid counting scheme ' + counting); + function winning_game_count(setup_or_counting) { + return _required_wins(setup_or_counting); } -} -function max_game_count(counting) { - switch (counting) { - case '5x11_15': - case '5x11_15^90': - case '5x11_15~NLA': - case '5x11/3': - case '5x11_11': - return 5; - case '3x21': - case '3x15_18': - case '2x21+11': - return 3; - case '1x21': - case '1x11_15': - return 1; - default: - throw new Error('Invalid counting scheme ' + counting); + function max_game_count(setup_or_counting) { + var normalized = _normalize_setup(setup_or_counting); + var scoring_format = normalized.scoring_format; + if (! scoring_format || !Number.isFinite(Number(scoring_format.numSets))) { + throw new Error('Invalid counting scheme ' + normalized.counting); + } + return Number(scoring_format.numSets); } -} -function match_winner(counting, input_scores) { - var winning_count = winning_game_count(counting); + function match_winner(setup_or_counting, input_scores) { + var winning_count = winning_game_count(setup_or_counting); - var score = [0, 0]; - for (var i = 0;i < input_scores.length;i++) { - var iscore = input_scores[i]; - var winner = iscore.winner; - if (!winner) { - winner = game_winner(counting, i, iscore[0], iscore[1]); - } + var score = [0, 0]; + for (var i = 0;i < input_scores.length;i++) { + var iscore = input_scores[i]; + var winner = iscore.winner; + if (!winner) { + winner = game_winner(setup_or_counting, i, iscore[0], iscore[1]); + } switch (winner) { case 'left': score[0]++; @@ -282,24 +407,87 @@ function match_winner(counting, input_scores) { case 'invalid': return 'invalid'; } + } + return 'inprogress'; } - return 'inprogress'; -} -function calc_game_score(counting, games) { - var res = [0, 0]; - games.forEach(function(g, game_index) { - var winner = game_winner(counting, game_index, g.score[0], g.score[1]); - if (winner === 'left') { - res[0]++; - } else if (winner === 'right') { + function calc_game_score(setup_or_counting, games) { + var res = [0, 0]; + games.forEach(function(g, game_index) { + var winner = game_winner(setup_or_counting, game_index, g.score[0], g.score[1]); + if (winner === 'left') { + res[0]++; + } else if (winner === 'right') { res[1]++; } else { throw new Error('Invalid status for a finished game: ' + winner); } - }); - return res; -} + }); + return res; + } + + function _current_set_points(setup, game_idx) { + return _set_points_for_game(setup, game_idx) || {}; + } + + function _is_break_in_set_enabled(set_points) { + if (!set_points) { + return false; + } + if (typeof set_points.interval_enabled === 'boolean') { + return set_points.interval_enabled; + } + return Number.isFinite(Number(set_points.interval_at)) && Number.isFinite(Number(set_points.interval_duration_ms)); + } + + function _is_interval_reached(setup, game_idx, score, team_id) { + var set_points = _current_set_points(setup, game_idx); + if (!_is_break_in_set_enabled(set_points)) { + return false; + } + var interval_at = Number(set_points.interval_at); + if (!Number.isFinite(interval_at)) { + return false; + } + return (score[team_id] === interval_at) && (score[1 - team_id] < interval_at); + } + + function _interval_duration_ms(setup, game_idx) { + var set_points = _current_set_points(setup, game_idx); + if (!_is_break_in_set_enabled(set_points)) { + return null; + } + var duration = Number(set_points.interval_duration_ms); + return Number.isFinite(duration) ? duration : null; + } + + function _break_before_next_set_duration_ms(setup, next_game_idx) { + var set_points = _current_set_points(setup, next_game_idx); + var duration = Number(set_points.break_before_set_duration_ms); + return Number.isFinite(duration) ? duration : null; + } + + function _next_score_wins_set(setup, game_idx, score, team_id) { + var next_score = score.slice(); + next_score[team_id] += 1; + return _is_winner(setup, game_idx, next_score[team_id], next_score[1 - team_id]); + } + + function _is_gamepoint_score(setup, game_idx, score, team_id) { + var set_points = _current_set_points(setup, game_idx); + var end_points = Number(set_points.end_points); + var max_points = Number(set_points.max_points); + if (!Number.isFinite(end_points) || !Number.isFinite(max_points)) { + return false; + } + return ( + ((score[team_id] === end_points - 1) && ( + (score[1 - team_id] < end_points - 1) || + ((max_points === end_points) && (score[1 - team_id] === end_points - 1)) + )) || + ((max_points > end_points) && (score[team_id] === max_points - 1)) + ); + } function init_state(s, setup, presses, keep_metadata) { if (! keep_metadata) { @@ -318,6 +506,24 @@ function init_state(s, setup, presses, keep_metadata) { s.initialized = true; s.presses = presses ? presses : []; s.timer = false; + + // These calls ensure that the timers are started before the first tablet interaction. + // This is only necessary for warm-up timers that are not started by the referee. + if (s.setup.warmup === 'call-down') { + s.timer = { + start: s.setup.called_timestamp, + duration: s.setup.warmup_start * 1000, + exigent: Math.max(0, s.setup.warmup_start-s.setup.warmup_ready) * 1000 + 499, + restart: false, + }; + } else if (s.setup.warmup === 'call-up') { + s.timer = { + start: s.setup.called_timestamp, + upwards: true, + restart: false, + }; + } + s.remote = {}; delete s.match; @@ -368,30 +574,29 @@ function make_game_state(s, previous_game) { return res; } -function recalc_after_score(s, team_id, press) { - var counting = s.setup.counting; - var game_idx = s.match.finished_games.length; - var team1_won = _is_winner(counting, game_idx, s.game.score[0], s.game.score[1]); - var team2_won = _is_winner(counting, game_idx, s.game.score[1], s.game.score[0]); - if (team1_won || team2_won) { - var winner_idx = team1_won ? 0 : 1; - s.match.game_score = calc_game_score(counting, s.match.finished_games); - s.match.game_score[winner_idx]++; - s.game.won_by_score = true; - s.game.team1_won = team1_won; + function recalc_after_score(s, team_id, press) { + var game_idx = s.match.finished_games.length; + var team1_won = _is_winner(s.setup, game_idx, s.game.score[0], s.game.score[1]); + var team2_won = _is_winner(s.setup, game_idx, s.game.score[1], s.game.score[0]); + if (team1_won || team2_won) { + var winner_idx = team1_won ? 0 : 1; + s.match.game_score = calc_game_score(s.setup, s.match.finished_games); + s.match.game_score[winner_idx]++; + s.game.won_by_score = true; + s.game.team1_won = team1_won; if (!s.game.game) { s.game.final_marks = s.match.marks.slice(); if (press.type == 'red-card') { s.game.final_marks.push(press); } - } - s.game.game = true; - s.game.finished = true; - s.match.injuries = false; - var winning_count = winning_game_count(counting); - if (s.match.game_score[winner_idx] === winning_count) { - if (! s.metadata.end) { - s.metadata.end = press.timestamp; + } + s.game.game = true; + s.game.finished = true; + s.match.injuries = false; + var winning_count = winning_game_count(s.setup); + if (s.match.game_score[winner_idx] === winning_count) { + if (! s.metadata.end) { + s.metadata.end = press.timestamp; } s.match.finished = true; s.match.team1_won = team1_won; @@ -416,72 +621,40 @@ function recalc_after_score(s, team_id, press) { s.game.team1_serving = team_id === 0; } - var is_interval = null; - if (team_id !== null) { - if ((counting === '3x21') || (counting === '1x21') || ((counting === '2x21+11') && (game_idx < 2))) { - is_interval = ( - (s.game.score[team_id] === 11) && (s.game.score[1 - team_id] < 11) - ); - } else if (counting === '3x15_18') { - is_interval = ( - (s.game.score[team_id] === 8) && (s.game.score[1 - team_id] < 8) - ); - } else if ((counting === '1x11_15') || (((counting === '5x11_15') || (counting === '5x11_15^90') || (counting === '5x11_15~NLA') || (counting === '5x11/3') || (counting === '5x11_11')) && (game_idx === 4)) || ((counting === '2x21+11') && (game_idx === 2))) { - is_interval = ( - (s.game.score[team_id] === 6) && (s.game.score[1 - team_id] < 6) - ); - } else if ((counting === '5x11_15') || (counting === '5x11_15^90') || (counting === '5x11_15~NLA') || (counting === '5x11/3') || (counting === '5x11_11')) { - is_interval = false; - } else { - throw new Error('Invalid counting scheme ' + s.setup.counting); - } - if (is_interval) { // First time - s.game.interval_score = s.game.score.slice(); - s.game.interval_service_over = s.game.service_over; + var is_interval = null; + if (team_id !== null) { + is_interval = _is_interval_reached(s.setup, game_idx, s.game.score, team_id); + if (is_interval) { // First time + s.game.interval_score = s.game.score.slice(); + s.game.interval_service_over = s.game.service_over; s.game.interval_team1_serving = s.game.team1_serving; s.game.interval_marks = s.match.marks.slice(); if (press.type == 'red-card') { s.game.interval_marks.push(press); - } - s.timer = { - start: press.timestamp, - duration: (counting === '5x11_15^90' ? 90000 : 60000), - exigent: 25000, - }; + } + var interval_duration = _interval_duration_ms(s.setup, game_idx); + s.timer = { + start: press.timestamp, + duration: interval_duration, + exigent: 25000, + }; } if ((press.type != 'red-card') || is_interval) { s.game.interval = is_interval; } - } - - if (s.game.finished && !s.match.finished) { - var rest_duration; - switch (counting) { - case '5x11_15^90': - rest_duration = 90000; - break; - case '5x11_15': - case '5x11/3': - case '5x11_11': - rest_duration = 60000; - break; - case '3x21': - case '3x15_18': - case '2x21+11': - case '5x11_15~NLA': - rest_duration = 120000; - break; - case '1x21': - case '1x11_15': - throw new Error('Should never happen with ' + counting); - default: - throw new Error('Invalid counting scheme ' + counting); } - s.timer = { - start: press.timestamp, - duration: rest_duration, - exigent: 25000, - }; + + if (s.game.finished && !s.match.finished) { + var rest_duration = _break_before_next_set_duration_ms(s.setup, game_idx + 1); + if (rest_duration !== null) { + s.timer = { + start: press.timestamp, + duration: rest_duration, + exigent: 25000, + }; + } else { + s.timer = false; + } } else if (!s.game.interval && !s.match.suspended && !s.match.injuries) { if (press.type !== 'red-card') { s.timer = false; @@ -522,7 +695,7 @@ function calc_press(s, press) { case 'pick_side': // Manuel Lappe reported a mysterious error where team1_left seems to have been not boolean if (typeof press.team1_left != 'boolean') { - report_problem.silent_error('pick_side value not boolean, but ' + (typeof press.team1_left)); + if (typeof report_problem !== "undefined" && report_problem && report_problem.silent_error) { report_problem.silent_error('pick_side value not boolean, but ' + (typeof press.team1_left)); } } s.game.start_team1_left = press.team1_left; @@ -573,12 +746,12 @@ function calc_press(s, press) { // Report by Manuel Lappe: It is possible to get into a state where both presses effect the same side. var side_type = typeof s.game.team1_left; if (side_type != 'boolean') { - report_problem.silent_error('Unclear sides while scoring, type ' + side_type); + if (typeof report_problem !== "undefined" && report_problem && report_problem.silent_error) { report_problem.silent_error('Unclear sides while scoring, type ' + side_type); } } // This should not be possible in the UI, but could be caused by a race condition or invalid data if (s.game.finished) { - report_problem.silent_error('Ignoring score press: Game is already finished'); + if (typeof report_problem !== "undefined" && report_problem && report_problem.silent_error) { report_problem.silent_error('Ignoring score press: Game is already finished'); } break; } @@ -789,20 +962,20 @@ function calc_press(s, press) { return fgame; } - return { - synthetic: true, - finished: true, - start_team1_left: (fgame ? fgame.start_team1_left : null), - team1_won: _is_winner(s.setup.counting, i, new_score[0], new_score[1]), - score: new_score, - editmode_by_side: !! press.by_side, - }; - }); + return { + synthetic: true, + finished: true, + start_team1_left: (fgame ? fgame.start_team1_left : null), + team1_won: _is_winner(s.setup, i, new_score[0], new_score[1]), + score: new_score, + editmode_by_side: !! press.by_side, + }; + }); - s.match.finished = false; - s.match.team1_won = null; - s.match.game_score = calc_game_score(s.setup.counting, s.match.finished_games); - recalc_after_score(s, null, press); + s.match.finished = false; + s.match.team1_won = null; + s.match.game_score = calc_game_score(s.setup, s.match.finished_games); + recalc_after_score(s, null, press); break; case 'timer_restart': if (s.timer) { @@ -810,6 +983,7 @@ function calc_press(s, press) { start: press.timestamp, duration: s.timer.duration, exigent: s.timer.exigent, + restart: s.timer.restart, }; } break; @@ -846,7 +1020,7 @@ function init_calc(s) { injuries: false, }; - s.match.max_games = max_game_count(s.setup.counting); // TODO: deprecate this property + s.match.max_games = max_game_count(s.setup); // TODO: deprecate this property s.game = make_game_state(s); } @@ -864,82 +1038,22 @@ function state(s) { calc_press(s, press); }); - var counting = s.setup.counting; - var game_idx = s.match.finished_games.length; - - if (! s.game.finished) { - var team_id; // No let in modern browsers :( - if ((counting === '3x21') || ((counting === '2x21+11') && (game_idx < 2))) { - if ((s.game.team1_serving) && (((s.game.score[0] === 20) && (s.game.score[1] < 20)) || (s.game.score[0] == 29))) { - if (s.match.game_score[0] === 0) { - s.game.gamepoint = true; - } else { - s.game.matchpoint = true; - } - } else if ((!s.game.team1_serving) && (((s.game.score[1] === 20) && (s.game.score[0] < 20)) || (s.game.score[1] == 29))) { - if (s.match.game_score[1] === 0) { - s.game.gamepoint = true; - } else { - s.game.matchpoint = true; - } - } - } else if (counting === '3x15_18') { - if ((s.game.team1_serving) && (((s.game.score[0] === 14) && (s.game.score[1] < 14)) || (s.game.score[0] == 17))) { - if (s.match.game_score[0] === 0) { - s.game.gamepoint = true; - } else { - s.game.matchpoint = true; - } - } else if ((!s.game.team1_serving) && (((s.game.score[1] === 14) && (s.game.score[0] < 14)) || (s.game.score[1] == 17))) { - if (s.match.game_score[1] === 0) { - s.game.gamepoint = true; - } else { - s.game.matchpoint = true; - } - } - } else if (counting === '1x21') { - if ((s.game.team1_serving) && (((s.game.score[0] === 20) && (s.game.score[1] < 20)) || (s.game.score[0] == 29))) { - s.game.matchpoint = true; - } else if ((!s.game.team1_serving) && (((s.game.score[1] === 20) && (s.game.score[0] < 20)) || (s.game.score[1] == 29))) { - s.game.matchpoint = true; - } - } else if ((counting === '2x21+11') && (game_idx === 2)) { - if ((s.game.team1_serving) && (((s.game.score[0] === 10) && (s.game.score[1] < 10)) || (s.game.score[0] == 14))) { - s.game.matchpoint = true; - } else if ((!s.game.team1_serving) && (((s.game.score[1] === 10) && (s.game.score[0] < 10)) || (s.game.score[1] == 14))) { - s.game.matchpoint = true; - } - } else if ((counting === '5x11_15') || (counting === '5x11_15^90') || (counting === '5x11_15~NLA') || (counting === '1x11_15')) { - team_id = s.game.team1_serving ? 0 : 1; - if (((s.game.score[team_id] === 10) && (s.game.score[1 - team_id] < 10)) || (s.game.score[team_id] == 14)) { - if ((s.match.game_score[team_id] >= 2) || (counting === '1x11_15')) { - s.game.matchpoint = true; - } else { - s.game.gamepoint = true; - } - } - } else if (counting === '5x11/3') { - team_id = s.game.team1_serving ? 0 : 1; - if (((s.game.score[team_id] === 10) && (s.game.score[1 - team_id] < 10)) || (s.game.score[team_id] == 12)) { - if (s.match.game_score[team_id] < 2) { - s.game.gamepoint = true; - } else { - s.game.matchpoint = true; - } - } - } else if (counting === '5x11_11') { - team_id = s.game.team1_serving ? 0 : 1; - if (s.game.score[team_id] === 10) { - if (s.match.game_score[team_id] < 2) { - s.game.gamepoint = true; - } else { - s.game.matchpoint = true; + var game_idx = s.match.finished_games.length; + + if (! s.game.finished) { + var team_id; // No let in modern browsers :( + + if (typeof s.game.team1_serving === 'boolean') { + team_id = s.game.team1_serving ? 0 : 1; + if (_is_gamepoint_score(s.setup, game_idx, s.game.score, team_id)) { + if ((s.match.game_score[team_id] + 1) >= winning_game_count(s.setup)) { + s.game.matchpoint = true; + } else { + s.game.gamepoint = true; + } } } - } else { - throw new Error('Invalid counting scheme ' + counting); } - } s.match.announce_pregame = ( (s.game.start_server_player_id !== null) && @@ -1017,78 +1131,51 @@ function undo(s) { }); } -// Calculate score according to tournament/division/network adapter rules. -// state(s) must have been called before. -// Not necessarily the same as the score according to the main Badminton laws -function netscore(s, always_zero) { - var counting = s.setup.counting; - - function _finish_score(game_idx, score, team1_won) { - var winner = team1_won ? 0 : 1; - if ((counting === '3x21') || (counting === '1x21') || ((counting === '2x21+11') && (game_idx < 2))) { - if (score[1 - winner] >= 29) { - score[winner] = 30; - } else if (score[1 - winner] >= 20) { - score[winner] = score[1 - winner] + 2; - } else { - score[winner] = 21; + // Calculate score according to tournament/division/network adapter rules. + // state(s) must have been called before. + // Not necessarily the same as the score according to the main Badminton laws + function netscore(s, always_zero) { + function _finish_score(game_idx, score, team1_won) { + var winner = team1_won ? 0 : 1; + var set_points = _current_set_points(s.setup, game_idx); + var end_points = Number(set_points.end_points); + var max_points = Number(set_points.max_points); + if (!Number.isFinite(end_points) || !Number.isFinite(max_points)) { + throw new Error('Invalid scoring format ' + JSON.stringify((s.setup.scoring_format && s.setup.scoring_format.name) || s.setup.counting || null)); } - } else if ((counting === '5x11_15') || (counting === '5x11_15^90') || (counting === '5x11_15~NLA') || (counting === '1x11_15') || ((counting === '2x21+11') && (game_idx === 2))) { - if (score[1 - winner] >= 14) { - score[winner] = 15; - } else if (score[1 - winner] >= 10) { + var max_points_min_other = Number(set_points.max_points_min_other); + if (max_points === end_points) { + score[winner] = end_points; + } else if (Number.isFinite(max_points_min_other) && (score[1 - winner] >= max_points_min_other)) { + score[winner] = max_points; + } else if (score[1 - winner] >= max_points - 1) { + score[winner] = max_points; + } else if (score[1 - winner] >= end_points - 1) { score[winner] = score[1 - winner] + 2; } else { - score[winner] = 11; + score[winner] = end_points; } - } else if (counting === '5x11/3') { - if (score[1 - winner] >= 10) { - score[winner] = 13; - } else { - score[winner] = 11; - } - } else if (counting === '5x11_11') { - score[winner] = 11; - } else if (counting === '3x15_18') { - if (score[1 - winner] >= 17) { - score[winner] = 18; - } else if (score[1 - winner] >= 14) { - score[winner] = score[1 - winner] + 2; - } else { - score[winner] = 15; - } - } else { - throw new Error('Invalid counting scheme ' + counting); } - } var scores = s.match.finished_games.map(function(fg) { return fg.score.slice(); }); - if (! s.match.finish_confirmed && ((s.game.started || s.match.finished || (s.game.score[0] > 0) || (s.game.score[1] > 0) || always_zero))) { - scores.push(s.game.score.slice()); - } - - if (s.match.finished && !s.match.won_by_score) { - if (scores.length > 0) { - var last_score = scores[scores.length - 1]; - if (game_winner(counting, scores.length - 1, last_score[0], last_score[1]) === 'inprogress') { - _finish_score(scores.length - 1, last_score, s.match.team1_won); - } + if (! s.match.finish_confirmed && ((s.game.started || s.match.finished || (s.game.score[0] > 0) || (s.game.score[1] > 0) || always_zero))) { + scores.push(s.game.score.slice()); } - var max_games = max_game_count(counting); - while (scores.length < max_games) { - var mwinner = match_winner(counting, scores); - if ((mwinner == 'left') || (mwinner == 'right')) { - break; + if (s.match.finished && !s.game.won_by_score) { + if (scores.length < 1) { + scores.push([0, 0]); + } + var winner = s.match.team1_won ? 'left' : 'right'; + _finish_score(scores.length - 1, scores[scores.length - 1], s.match.team1_won); + while (match_winner(s.setup, scores) !== winner) { + var extra_score = [0, 0]; + _finish_score(scores.length, extra_score, s.match.team1_won); + scores.push(extra_score); } - - var new_score = [0, 0]; - _finish_score(scores.length, new_score, s.match.team1_won); - scores.push(new_score); } - } return scores; } @@ -1183,6 +1270,9 @@ return { players_present: players_present, undo: undo, remote_state: remote_state, + scoring_format_from_counting: scoring_format_from_counting, + setup_from_counting: setup_from_counting, + setup_from_scoring_format: setup_from_scoring_format, }; })(); @@ -1194,4 +1284,4 @@ if ((typeof module !== 'undefined') && (typeof require !== 'undefined')) { module.exports = calc; } -/*/@DEV*/ \ No newline at end of file +/*/@DEV*/ diff --git a/js/control.js b/js/control.js index 0ec98e0d..64082fc4 100644 --- a/js/control.js +++ b/js/control.js @@ -3,11 +3,13 @@ var control = (function() { function demo_match_start(setup) { if (! setup) { - setup = { - counting: '3x21', - team_competition: true, - }; + setup = calc.setup_from_scoring_format(calc.scoring_format_from_counting('3x21')); + setup.team_competition = true; } + if ((! setup.scoring_format) && setup.counting) { + setup.scoring_format = calc.scoring_format_from_counting(setup.counting); + } + utils.obj_update(setup, { is_doubles: true, teams: [{ @@ -35,8 +37,8 @@ function demo_match_start(setup) { } function empty_match_start(counting) { - var setup = { - counting: counting, + var setup = calc.setup_from_scoring_format(calc.scoring_format_from_counting(counting)); + utils.obj_update(setup, { is_doubles: false, date: ' ', teams: [{ @@ -49,7 +51,7 @@ function empty_match_start(counting) { }], }], team_competition: false, - }; + }); settings.hide(true); start_match(state, setup, [], { @@ -117,7 +119,7 @@ function ask_leave_match(s) { return; } - if (network.score_transmitted()) { + if (s.match.finish_confirmed || network.score_transmitted()) { leave_match(s); return; } @@ -261,14 +263,7 @@ function ui_init() { type: 'postinterval-confirm', }); }); - click.qs('#postmatch-confirm', function() { - if (! state.match.finish_confirmed) { - on_press({ - type: 'postmatch-confirm', - }); - } - ask_leave_match(state); - }); + click.qs('#postmatch-confirm', post_match_confirm); click.qs('#postmatch-leave', function() { ask_leave_match(state); }); @@ -394,6 +389,14 @@ function ui_init() { } +function post_match_confirm(){ + if (!state.match.finish_confirmed) { + on_press({ + type: 'postmatch-confirm', + }); + } + ask_leave_match(state); +} function set_current(s) { buphistory.record(s); @@ -443,6 +446,7 @@ return { hide_exception_dialog: hide_exception_dialog, install_destructor: install_destructor, on_press: on_press, + post_match_confirm: post_match_confirm, resume_match: resume_match, set_current: set_current, start_match: start_match, diff --git a/js/court.js b/js/court.js index 5025ca96..7e5c5743 100644 --- a/js/court.js +++ b/js/court.js @@ -105,6 +105,23 @@ function render(s, cui) { if (umpire_name && s.setup.service_judge_name) { umpire_name += ' / ' + s.setup.service_judge_name; } + + if (s.setup.tabletoperators && s.setup.tabletoperators.length > 0) { + var _tabletoperator_str = function (tabletoperators) { + if (tabletoperators.length === 0) { + return 'N.N'; + } else if (tabletoperators.length == 1) { + return tabletoperators[0].name; + } else { + return tabletoperators[0].name + ' / ' + tabletoperators[1].name; + } + }; + if (umpire_name.length > 0) { + umpire_name += ' / '; + } + umpire_name += _tabletoperator_str(s.setup.tabletoperators); + } + uiu.text(cui.umpire_name, umpire_name); uiu.visible(cui.umpire_name, (cdata.left_serving === null)); diff --git a/js/courtspot.js b/js/courtspot.js index 795d0531..32d5fe82 100644 --- a/js/courtspot.js +++ b/js/courtspot.js @@ -214,7 +214,7 @@ function list_matches(s, cb) { // CourtSpot sometimes set the fourth game to 0 for 3x21. Clamp network_score event.matches.forEach(function(m) { - var max_game_count = calc.max_game_count(m.setup.counting); + var max_game_count = calc.max_game_count(m.setup); if (m.network_score.length > max_game_count) { m.network_score = m.network_score.slice(0, max_game_count); } diff --git a/js/dads.js b/js/dads.js index dfefe5a0..a2699fc8 100644 --- a/js/dads.js +++ b/js/dads.js @@ -563,7 +563,7 @@ function finished_since(match) { return false; // No idea, fail safe } - var winner = calc.match_winner(match.setup.counting, match.network_score); + var winner = calc.match_winner(match.setup, match.network_score); if ((winner === 'inprogress') || (winner === 'invalid')) { _since_matchid = null; return false; diff --git a/js/displaymode.js b/js/displaymode.js index b8b424a4..14c40e6f 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -7,6 +7,8 @@ var ALL_STYLES = [ 'bwf', 'clean', 'teamcourt', + 'tournamentcourt', + 'tournamentplayers', 'stripes', '2court', 'greyish', @@ -22,14 +24,18 @@ var ALL_STYLES = [ 'castall', 'stream', 'streamcourt', + 'streamcourt_dm', 'streamteam', 'tournament_overview', + 'tournament_overview_dm', + 'tournament_overview_dm_finals', 'andre', ]; var ALL_COLORS = [ 'c0', 'c1', 'cb0', 'cb1', 'cbg', 'cbg2', 'cbg3', 'cbg4', - 'cfg', 'cfg2', 'cfg3', 'cfg3', 'cfgdark', + 'cfg', 'cfg2', 'cfg3', 'cfg4', 'cfgdark', + 'cexp', 'ct', // transparent 'cborder', 'cserv', 'cserv2', 'crecv', @@ -65,7 +71,10 @@ function _setup_autosize(el, right_node, determine_height) { if (right_node) { var prect = parent_node.getBoundingClientRect(); var rrect = right_node.getBoundingClientRect(); - w = Math.max(10, Math.min(w, rrect.left - prect.left)); + + // The -20 at the end of the formula is a fixed value. Without the fix, the calculation + // sometimes resulted in the strings going just beyond the end of the planned range. + w = Math.max(10, Math.min(w, rrect.left - prect.left-20)); } var h; @@ -85,7 +94,7 @@ function _setup_autosize(el, right_node, determine_height) { function _calc_matchscore(matches) { var res = [0, 0]; matches.forEach(function(m) { - var winner = calc.match_winner(m.setup.counting, m.network_score || []); + var winner = calc.match_winner(m.setup, m.network_score || []); if (winner === 'left') { res[0] += 1; } else if (winner === 'right') { @@ -183,7 +192,7 @@ function _list_render_team_name(tr, team_name) { function _calc_max_games(event) { var res = 0; event.matches.forEach(function(match) { - res = Math.max(res, calc.max_game_count(match.setup.counting)); + res = Math.max(res, calc.max_game_count(match.setup)); }); return res; } @@ -196,6 +205,11 @@ function hash(settings, event) { court_id: settings.displaymode_court_id, reverse_order: settings.displaymode_reverse_order, show_pause: settings.d_show_pause, + show_court_number: settings.d_show_court_number, + show_competition: settings.d_show_competition, + show_round: settings.d_show_round, + show_middle_name: settings.d_show_middle_name, + show_doubles_receiving: settings.d_show_doubles_receiving, team_colors: settings.d_team_colors, courts: utils.deep_copy(event.courts), matches: utils.deep_copy(event.matches), @@ -232,7 +246,51 @@ function determine_server(match, current_score) { if (netscore && netscore.length > 0) { var game_idx = netscore.length - 1; var last_game = netscore[game_idx]; - var gwinner = calc.game_winner(match.setup.counting, game_idx - 1, last_game[0], last_game[1]); + var gwinner = calc.game_winner(match.setup, game_idx - 1, last_game[0], last_game[1]); + if (gwinner !== 'inprogress') { + return { + team_id: team_id, + }; + } + } + + return { + team_id: team_id, + player_id: player_id, + }; +} + +function determine_receiver(match, current_score) { + var team_id; + if (typeof match.network_team1_serving === 'boolean') { + team_id = match.network_team1_serving ? 1 : 0; // welches Team hat den ersten Aufschlag angenommen? + } + if (team_id === undefined) return {}; + if (!match.network_teams_player1_even) { + return { + team_id: team_id, + }; // This ensures that server.player_id is undefined + } + + var player_id = 0; + if (match.setup.is_doubles) { + var p0even = match.network_teams_player1_even[team_id]; //Welcher spieler des Teams stand bei der Annahme bei 0 Rechts? + if (p0even === null) { + // only team known + return { + team_id: team_id, + }; + } + player_id = (p0even == (current_score[(team_id + 1) % 2] % 2 === 0)) ? 0 : 1; + } + + // Network score only, but at end of game? + // (the positions of players may be relayed, but should not be shown) + var netscore = match.network_score; + if (netscore && netscore.length > 0) { + var game_idx = netscore.length - 1; + var last_game = netscore[game_idx]; + var gwinner = calc.game_winner(match.setup, game_idx - 1, last_game[0], last_game[1]); if (gwinner !== 'inprogress') { return { team_id: team_id, @@ -427,9 +485,6 @@ function render_tournament_overview(s, container, event) { var max_game_count = _calc_max_games(event); var colors = calc_colors(s.settings, event); - var table = uiu.el(container, 'table', 'd_to_table'); - var tbody = uiu.el(table, 'tbody'); - event.courts.forEach(function(court, idx) { var match = _match_by_court(event, court); var nscore = (match ? match.network_score : 0) || []; @@ -464,7 +519,7 @@ function render_tournament_overview(s, container, event) { var n = nscore[game_idx]; if (match && n) { - var gwinner = calc.game_winner(match.setup.counting, game_idx, n[0], n[1]); + var gwinner = calc.game_winner(match.setup, game_idx, n[0], n[1]); uiu.el(score_td, 'span', { 'class': ((gwinner === 'left') ? 'd_to_winning' : ''), }, n[0]); @@ -479,6 +534,722 @@ function render_tournament_overview(s, container, event) { }); } +function _tournament_overview_dm_render_players(tr, players) { + var td = uiu.el(tr, 'td', 'd_to_team'); + uiu.el(td, 'span', {}, namestr(players)); +} + +function render_tournament_overview_dm(s, container, event) { + var max_game_count = _calc_max_games(event); + var colors = calc_colors(s.settings, event); + + var background = uiu.el(container, 'div', { + style: ( + 'position:absolute;top:0vh;left:0vh;' + + 'height:100vh;width:100vw;' + + 'background-color: #000000;' + + 'z-index:10;' + ), + }); + + var courts = [4, 1, 0, 2, 3]; + courts.forEach(function (id , idx) { + var match = _match_by_court(event, event.courts[id]); + var duration = -1; + if (match != null) { + + if (match.presses_json && match.presses_json != null) { + + var presses = JSON.parse(match.presses_json); + const foundpress = presses.find(press => press.type === "love-all"); + if (foundpress && foundpress != null) { + var start = foundpress.timestamp; + duration = Math.floor((Date.now() - start) / 1000/60); + } + + } + } + var nscore = (match ? match.network_score : 0) || []; + + var setup = match ? match.setup : eventutils.default_setup(event.league_key); + var max_games = calc.max_game_count(setup); + var current_score = (nscore.length > 0) ? nscore[nscore.length - 1] : ['', '']; + var server = match ? determine_server(match, current_score) : {}; + + var court_el = uiu.el(background, 'div', { + style: ( + 'position:absolute;top:'+idx*20+'vh;left:0vh;' + + 'height:20vh;width:100vw;' + ), + }); + + var top_bar = uiu.el(court_el, 'div', { + style: ( + 'position:absolute;top:2vh;left:2vw;' + + 'height:16vh;' + + 'z-index:-1;' + + 'display: flex;' + + 'flex-direction: row;' + ), + }); + + + var top_bar_court = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:16vh;width:7.5vw;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;' + ), + }); + + uiu.el(top_bar_court, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-right-radius: 1vh;'+ + 'border-top-left-radius: 1vh;' + ), + }); + + var court_number = uiu.el(top_bar_court, 'div', { + style: ( + 'position:static;' + + 'height:90%;width:100%;' + + 'background-color: #ffffffbb;' + + 'text-align: center;' + ), + }); + + uiu.el(court_number, 'div', { + style: ( + 'font-size: 17.0vh;'+ + 'height: 100%;' + + 'font-weight: bold;' + + 'font-style: oblique;' + + 'margin-top: -2.5vh' + ), + },id+1); + + var top_bar_match = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:16vh;width:7.5vw;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;'+ + 'margin-left: 0.5vh;' + ), + }); + uiu.el(top_bar_match, 'div', { + + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-right-radius: 1vh;'+ + 'border-top-left-radius: 1vh;' + ), + }); + + var match_div = uiu.el(top_bar_match, 'div', { + style: ( + 'position:static;' + + 'height:90%;width:100%;' + + 'background-color: #ffffffbb;' + + 'text-align: center;' + ), + }); + + uiu.el(match_div, 'div', { + style: ( + 'font-size: 3.5vh;' + + 'font-weight: bold;' + + 'font-style: oblique;' + ), + }, (match && match.setup) ? match.setup.event_name: ""); + + uiu.el(match_div, 'div', { + style: ( + 'font-size: 3.5vh;' + + 'font-weight: bold;' + + 'font-style: oblique;' + ), + }, (match && match.setup) ? match.setup.match_name : ""); + + + uiu.el(match_div, 'div', { + style: ( + 'font-size: 6vh;' + + 'font-weight: bold;' + + 'font-style: oblique;' + ), + }, (duration == -1 ) ? "" : duration+"'"); + + uiu.el(top_bar_court, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-right-radius: 1vh;'+ + 'border-bottom-left-radius: 1vh;' + ), + }); + + uiu.el(top_bar_match, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-right-radius: 1vh;'+ + 'border-bottom-left-radius: 1vh;' + ), + }); + + var top_bar_left = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:16vh;width:64.5vw;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;' + + 'margin-left: 0.5vh;' + ), + }); + + var border_top = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-right-radius: 1vh;'+ + 'border-top-left-radius: 1vh;' + ), + }); + + var teams = []; + + teams.push(uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:43%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: space-between;' + ), + })); + + var border_middle = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:4%;width:100%;' + ), + }); + + + teams.push(uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:43%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: space-between;' + ), + })); + + var border_bottom = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-left-radius: 1vh;'+ + 'border-bottom-right-radius: 1vh;' + ), + }); + + var team_service = []; + for (var team_idx = 0;team_idx < 2;team_idx++) { + var team_name = uiu.el(teams[team_idx], 'div', { + style: ( + 'margin-left:1vh;' + + 'font-size:6.0vh;' + + 'height: 100%;' + + 'align-content: center;' + + 'width: fit-content;' + + 'font-weight: bold;' + ) + }, + match ? match.setup.teams[team_idx].players[0].name +(match.setup.teams[team_idx].players.length > 1 ? ' / ' + match.setup.teams[team_idx].players[1].name : '') : ''); + + let service = uiu.el(teams[team_idx], 'div', { + style: ( + 'height: 100%;' + + 'align-content: center;' + + 'width: 6.5vh;' + + 'background-repeat: no-repeat;' + + 'background-position:center;' + + 'background-size:contain;' + + 'background-image:url("icons/Ball_DM_Cloppenburg_schwarz.svg");' + )}); + + service.style.visibility = "hidden"; + + team_service.push(service); + + } + + var sets = []; + + var team_serving = -1; + + // for (var game_idx = 0;game_idx < max_games;game_idx++) { + for (var game_idx = 0;game_idx < 3;game_idx++) { + if (nscore.length > game_idx) { + for (var team_idx = 0;team_idx < 2;team_idx++) { + var gwinner = calc.game_winner( + match.setup, game_idx, nscore[game_idx][0], nscore[game_idx][1]); + var is_team_serving = ( + (gwinner === 'left') ? (team_idx === 0) : ( + (gwinner === 'right') ? (team_idx === 1) : ( + (server.team_id === team_idx)))); + + if(is_team_serving) { + team_serving = team_idx; + } + } + } + + var top_bar_set = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:16vh;width:9vh;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;' + + 'margin-left: 0.5vh;' + ), + }); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-left-radius: 1vh;' + + 'border-top-right-radius: 1vh;' + ), + }); + + let set = []; + set.push(uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:43%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: center;' + + 'font-size:7vh;' + + 'align-items: center;'+ + 'font-weight: bold;' + ), + }, game_idx < nscore.length ? nscore[game_idx][0] : '')); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:4%;width:100%;' + ), + }); + + set.push(uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:43%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: center;' + + 'font-size:7vh;' + + 'align-items: center;'+ + 'font-weight: bold;' + ), + }, game_idx < nscore.length ? nscore[game_idx][1] : '')); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-left-radius: 1vh;' + + 'border-bottom-right-radius: 1vh;' + ), + }); + + sets.push(set); + } + + if(team_serving >= 0) { + team_service[team_serving].style.visibility = 'visible'; + } + + }); +} + + function render_tournament_overview_dm_finals(s, container, event) { + var max_game_count = _calc_max_games(event); + var colors = calc_colors(s.settings, event); + + var background = uiu.el(container, 'div', { + style: ( + 'position:absolute;top:0vh;left:0vh;' + + 'height:100vh;width:100vw;' + + 'background-color: #000000;' + + 'z-index:10;' + ), + }); + + var courts = [1, 0, 2]; + var duration = -1; + courts.forEach(function (id , idx) { + var match = _match_by_court(event, event.courts[id]); + if (match != null) { + if (match.presses_json && match.presses_json != null) { + + var presses = JSON.parse(match.presses_json); + const foundpress = presses.find(press => press.type === "love-all"); + if (foundpress && foundpress != null) { + var start = foundpress.timestamp; + duration = Math.floor((Date.now() - start) / 1000/60); + } + + } + } + var nscore = (match ? match.network_score : 0) || []; + + var setup = match ? match.setup : eventutils.default_setup(event.league_key); + var max_games = calc.max_game_count(setup); + var current_score = (nscore.length > 0) ? nscore[nscore.length - 1] : ['', '']; + var server = match ? determine_server(match, current_score) : {}; + + var court_el = uiu.el(background, 'div', { + style: ( + 'position:absolute;top:' + idx * 33 + 'vh;left:0vh;' + + 'height:20vh;width:100vw;' + ), + }); + + /* + var logo = uiu.el(court_el, 'div', { + style: ( + 'position:absolute;top:1vh;left:2vh;' + + 'height:18vh;width:17.6vh;' + + 'z-index:10;'+ + 'font-size: 15vh;'+ + 'color: #000;'+ + 'display: flex;'+ + 'justify-content: center;'+ + 'align-items: center;'+ + 'font-weight: bold;'+ + 'font-style: oblique;' + ), + }, idx+1);*/ + var top_bar = uiu.el(court_el, 'div', { + style: ( + 'position:absolute;top:2vh;left:2vw;' + + 'height:16vh;' + + 'z-index:-1;' + + 'display: flex;' + + 'flex-direction: row;' + ), + }); + + + var top_bar_court = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:30vh;width:17vw;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;' + ), + }); + + uiu.el(top_bar_court, 'div', { + style: ( + 'position:static;' + + 'height:3%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-right-radius: 1vh;' + + 'border-top-left-radius: 1vh;' + ), + }); + + var court_number = uiu.el(top_bar_court, 'div', { + style: ( + 'position:static;' + + 'height:94%;width:100%;' + + 'background-color: #ffffffbb;' + + 'text-align: center;' + ), + }); + + uiu.el(court_number, 'div', { + style: ( + 'font-size: 18.5vh;' + + 'font-weight: bold;' + + 'font-style: oblique;'+ + 'margin: -2.5vh;' + ), + }, id + 1); + + uiu.el(court_number, 'div', { + style: ( + 'font-size: 4vh;' + + 'font-weight: bold;' + + 'font-style: oblique;' + ), + }, (match && match.setup) ? match.setup.event_name+' - '+match.setup.match_name : ""); + + + uiu.el(court_number, 'div', { + style: ( + 'font-size: 6vh;' + + 'font-weight: bold;' + + 'font-style: oblique;' + ), + }, (duration == -1 ) ? "" : duration+"'"); + + uiu.el(top_bar_court, 'div', { + style: ( + 'position:static;' + + 'height:3%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-right-radius: 1vh;' + + 'border-bottom-left-radius: 1vh;' + ), + }); + + + + var top_bar_left = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:30vh;width:55vw;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;' + + 'margin-left: 0.5vh;' + ), + }); + + var border_top = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:3%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-right-radius: 1vh;' + + 'border-top-left-radius: 1vh;' + ), + }); + + var teams = []; + + teams.push(uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:46%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: space-between;' + ), + })); + + var border_middle = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:2%;width:100%;' + ), + }); + + + teams.push(uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:46%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: space-between;' + ), + })); + + var border_bottom = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:3%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-left-radius: 1vh;' + + 'border-bottom-right-radius: 1vh;' + ), + }); + + var team_service = []; + for (var team_idx = 0; team_idx < 2; team_idx++) { + + var team_name = uiu.el(teams[team_idx], 'div', { + style: ( + 'margin-left:1vh;' + + 'height: 100%;' + + 'display: flex;' + + 'justify-content: center;' + + 'flex-direction: column;' + ) + }); + + uiu.el(team_name, 'div', { + style: ( + 'margin-left:1vh;' + + 'font-size:6.0vh;' + + 'height: 100%;' + + 'align-content: center;' + + 'width: fit-content;' + + 'font-weight: bold;' + ) + }, + match ? match.setup.teams[team_idx].players[0].name : ''); + + if (match && match.setup.teams[team_idx].players.length > 1) { + uiu.el(team_name, 'div', { + style: ( + 'margin-left:1vh;' + + 'font-size:6.0vh;' + + 'height: 100%;' + + 'align-content: center;' + + 'width: fit-content;' + + 'font-weight: bold;' + ) + }, + match.setup.teams[team_idx].players[1].name ); + } + + let service = uiu.el(teams[team_idx], 'div', { + style: ( + 'height: 100%;' + + 'align-content: center;' + + 'width: 6.5vh;' + + 'background-repeat: no-repeat;' + + 'background-position:center;' + + 'background-size:contain;' + + 'background-image:url("icons/Ball_DM_Cloppenburg_schwarz.svg");' + ) + }); + + service.style.visibility = "hidden"; + + team_service.push(service); + + } + + var sets = []; + + var team_serving = -1; + + // for (var game_idx = 0;game_idx < max_games;game_idx++) { + for (var game_idx = 0; game_idx < 3; game_idx++) { + if (nscore.length > game_idx) { + for (var team_idx = 0; team_idx < 2; team_idx++) { + var gwinner = calc.game_winner( + match.setup, game_idx, nscore[game_idx][0], nscore[game_idx][1]); + var is_team_serving = ( + (gwinner === 'left') ? (team_idx === 0) : ( + (gwinner === 'right') ? (team_idx === 1) : ( + (server.team_id === team_idx)))); + + if (is_team_serving) { + team_serving = team_idx; + } + } + } + + var top_bar_set = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:30vh;width:8vw;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;' + + 'margin-left: 0.5vh;' + ), + }); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:3%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-left-radius: 1vh;' + + 'border-top-right-radius: 1vh;' + ), + }); + + let set = []; + set.push(uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:46%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: center;' + + 'font-size:10vh;' + + 'align-items: center;' + + 'font-weight: bold;' + ), + }, game_idx < nscore.length ? nscore[game_idx][0] : '')); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:2%;width:100%;' + ), + }); + + set.push(uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:46%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: center;' + + 'font-size:10vh;' + + 'align-items: center;' + + 'font-weight: bold;' + ), + }, game_idx < nscore.length ? nscore[game_idx][1] : '')); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:3%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-left-radius: 1vh;' + + 'border-bottom-right-radius: 1vh;' + ), + }); + + sets.push(set); + } + + if (team_serving >= 0) { + team_service[team_serving].style.visibility = 'visible'; + } + + }); + } + + + + + function render_castall(s, container, event, colors) { if (!event.courts) { uiu.el(container, 'div', 'error', 'Court information missing'); @@ -499,8 +1270,8 @@ function render_castall(s, container, event, colors) { var real_court_idx = s.settings.displaymode_reverse_order ? (court_count - 1 - court_idx) : court_idx; var court = event.courts[real_court_idx]; var match = _match_by_court(event, court); - var counting = match ? match.setup.counting : eventutils.default_counting(event.league_key); - var max_games = counting ? calc.max_game_count(counting) : 0; + var setup = match ? match.setup : eventutils.default_setup(event.league_key); + var max_games = calc.max_game_count(setup); var nscore = (match ? match.network_score : 0) || []; var match_container = uiu.el(container, 'div', { @@ -697,8 +1468,8 @@ function render_stream(s, container, event/*, colors*/) { var real_court_idx = s.settings.displaymode_reverse_order ? (court_count - 1 - court_idx) : court_idx; var court = event.courts[real_court_idx]; var match = _match_by_court(event, court); - var counting = match ? match.setup.counting : eventutils.default_counting(event.league_key); - var max_games = counting ? calc.max_game_count(counting) : 0; + var setup = match ? match.setup : eventutils.default_setup(event.league_key); + var max_games = calc.max_game_count(setup); var nscore = (match ? match.network_score : 0) || []; var current_score = (nscore.length > 0) ? nscore[nscore.length - 1] : ['', '']; var server = match ? determine_server(match, current_score) : {}; @@ -760,7 +1531,7 @@ function render_stream(s, container, event/*, colors*/) { var team_serving = false; if (game_idx < nscore.length) { var gwinner = calc.game_winner( - match.setup.counting, game_idx, nscore[game_idx][0], nscore[game_idx][1]); + match.setup, game_idx, nscore[game_idx][0], nscore[game_idx][1]); team_serving = ( (gwinner === 'left') ? (team_idx === 0) : ( (gwinner === 'right') ? (team_idx === 1) : ( @@ -878,8 +1649,8 @@ function render_streamcourt(s, container, event/*, colors*/) { return c.court_id == s.settings.displaymode_court_id; }) || event.courts[0]; var match = _match_by_court(event, court); - var counting = match ? match.setup.counting : eventutils.default_counting(event.league_key); - var max_games = counting ? calc.max_game_count(counting) : 0; + var setup = match ? match.setup : eventutils.default_setup(event.league_key); + var max_games = calc.max_game_count(setup); var nscore = (match ? match.network_score : 0) || []; var current_score = (nscore.length > 0) ? nscore[nscore.length - 1] : ['', '']; var server = match ? determine_server(match, current_score) : {}; @@ -944,7 +1715,7 @@ function render_streamcourt(s, container, event/*, colors*/) { var team_serving = false; if (game_idx < nscore.length) { var gwinner = calc.game_winner( - match.setup.counting, game_idx, nscore[game_idx][0], nscore[game_idx][1]); + match.setup, game_idx, nscore[game_idx][0], nscore[game_idx][1]); team_serving = ( (gwinner === 'left') ? (team_idx === 0) : ( (gwinner === 'right') ? (team_idx === 1) : ( @@ -973,6 +1744,371 @@ function render_streamcourt(s, container, event/*, colors*/) { } +function render_streamcourt_dm(s, container, event/*, colors*/) { + if (!event.courts) { + uiu.el(container, 'div', 'error', 'Court information missing'); + return; + } + + var court = event.courts.find(function(c) { + return c.court_id == s.settings.displaymode_court_id; + }) || event.courts[0]; + var match = _match_by_court(event, court); + var setup = match ? match.setup : eventutils.default_setup(event.league_key); + var max_games = calc.max_game_count(setup); + var nscore = (match ? match.network_score : 0) || []; + var current_score = (nscore.length > 0) ? nscore[nscore.length - 1] : ['', '']; + var server = match ? determine_server(match, current_score) : {}; + + + var logo = uiu.el(container, 'div', { + style: ( + 'position:absolute;top:3vh;left:4vh;' + + 'height:10vh;width:9vh;' + + 'background-repeat: no-repeat;' + + 'background-position:center;' + + 'background-size:contain;' + + 'background-image:url("icons/Ball_DM_Cloppenburg.svg");'+ + 'z-index:10;' + ), + }); + var top_bar = uiu.el(container, 'div', { + style: ( + 'position:absolute;top:3.6vh;left:6.6vh;' + + 'height:8.8vh;' + + 'z-index:-1;' + + 'display: flex;' + + 'flex-direction: row;' + + ), + }); + + var top_bar_left = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:8.8vh;width:fit-content;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;' + ), + }); + + + + + + var border_top = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-right-radius: 1vh;' + ), + }); + + var teams = []; + + teams.push(uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:43%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: space-between;' + ), + })); + + var border_middle = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:4%;width:100%;' + ), + }); + + + teams.push(uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:43%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: space-between;' + ), + })); + + var border_bottom = uiu.el(top_bar_left, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-right-radius: 1vh;' + ), + }); + + var team_service = []; + for (var team_idx = 0;team_idx < 2;team_idx++) { + var team_name = uiu.el(teams[team_idx], 'div', { + style: ( + 'margin-left:6.7vh;' + + 'font-size:3vh;' + + 'height: 100%;' + + 'align-content: center;' + + 'width: fit-content;' + ) + }, + match ? namestr_short(match.setup.teams[team_idx].players) : ''); + + let service = uiu.el(teams[team_idx], 'div', { + style: ( + 'height: 100%;' + + 'align-content: center;' + + 'width: 4vh;' + + 'background-repeat: no-repeat;' + + 'background-position:center;' + + 'background-size:contain;' + + 'background-image:url("icons/Ball_DM_Cloppenburg_schwarz.svg");' + )}); + + service.style.visibility = "hidden"; + + team_service.push(service); + + } + + var sets = []; + + var team_serving = -1; + + for (var game_idx = 0;game_idx < max_games;game_idx++) { + + if (game_idx < nscore.length) { + + for (var team_idx = 0;team_idx < 2;team_idx++) { + var gwinner = calc.game_winner( + match.setup, game_idx, nscore[game_idx][0], nscore[game_idx][1]); + var is_team_serving = ( + (gwinner === 'left') ? (team_idx === 0) : ( + (gwinner === 'right') ? (team_idx === 1) : ( + (server.team_id === team_idx)))); + + if(is_team_serving) { + team_serving = team_idx; + } + } + + var top_bar_set = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:8.8vh;width:4vh;' + + 'display: flex;' + + 'flex-direction: column;' + + 'justify-content: space-between;' + + 'margin-left: 0.3vh;' + ), + }); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-top-left-radius: 1vh;' + + 'border-top-right-radius: 1vh;' + ), + }); + + let set = []; + set.push(uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:43%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: center;' + + 'font-size:3vh;' + + 'align-items: center;' + ), + }, nscore[game_idx][0])); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:4%;width:100%;' + ), + }); + + set.push(uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:43%;width:100%;' + + 'background-color: #ffffffbb;' + + 'display: flex;' + + 'justify-content: center;' + + 'font-size:3vh;' + + 'align-items: center;' + ), + }, nscore[game_idx][1])); + + uiu.el(top_bar_set, 'div', { + style: ( + 'position:static;' + + 'height:5%;width:100%;' + + 'background-color: #ffffff;' + + 'border-bottom-left-radius: 1vh;' + + 'border-bottom-right-radius: 1vh;' + ), + }); + + sets.push(set); + } + } + + if(team_serving >= 0) { + team_service[team_serving].style.visibility = 'visible'; + } + + var logo_dm = uiu.el(container, 'div', { + style: ( + 'position:absolute;bottom:1vh;right:2vh;' + + 'height:17.008vh;width:28.346vh;' + + 'background-repeat: no-repeat;' + + 'background-position:center;' + + 'background-size:contain;' + + 'background-image:url("icons/DBM_Schriftzug_mit_73_wiess.svg");'+ + 'z-index:10;' + ), + }); + + + var top_bar_right = uiu.el(container, 'div', { + style: ( + 'position:absolute; top: 3.6vh;left: calc(100% - 33.2vh);' + + 'height:8.8vh;' + + 'z-index:-1;' + + 'display: flex;' + + 'flex-direction: column;' + + 'color: #ffffff' + ), + }); + + uiu.el(top_bar_right, 'div', { + style: ( + 'position:static;' + + 'text-align: center;' + + 'height: 2.5vh;' + + 'width: 100%;' + + 'font-size: 2.1vh;' + + 'font-weight: bold;' + ), + }, s._('Court') + ' ' + (court.label || court.num || court.court_id)); + + uiu.el(top_bar_right, 'div', { + style: ( + 'position:static;' + + 'text-align: center;' + + 'height: 2.5vh;' + + 'width: 100%;' + + 'font-size: 2.1vh;' + + 'font-weight: bold;' + ), + }, createEventAnnouncement(s, match.setup)); + + uiu.el(top_bar_right, 'div', { + style: ( + 'position:static;' + + 'text-align: center;' + + 'height: 2.5vh;' + + 'width: 100%;' + + 'font-size: 2.1vh;' + + 'font-weight: bold;' + ), + }, createRoundAnnouncement(s, match.setup)); +} + +function createRoundAnnouncement(s, matchSetup) { + var round = matchSetup.match_name; + if (round == "R64") { + round = s._('announcements:round_64'); + } else if (round == "R32") { + round = s._('announcements:round_32'); + } else if (round == "R16") { + round = s._('announcements:round_16'); + } else if (round == "VF") { + round = s._('announcements:quaterfinal'); + } else if (round == "HF") { + round = s._('announcements:semifinal'); + } else if (round == "Finale") { + round = s._('announcements:final'); + } else if (round.indexOf('/') !== -1) { + var roundParts = round.split("/") + var diff = roundParts[1] - roundParts[0]; + if (diff > 1) { + round = s._('announcements:intermediate_round'); + } else { + round = s._('announcements:game_for_place') + roundParts[0] + s._('announcements:and') + roundParts[1]; + } + } else if (round.indexOf('-') !== -1) { + round = s._('announcements:intermediate_round'); + } else { + round = ""; + } + return round; +} +function createEventAnnouncement(s, matchSetup) { + var eventParts = matchSetup.event_name.replaceAll("-", " ").split(" "); + var eventName = ""; + if (eventParts[0] == 'JE') { + eventName = s._('announcements:boys_singles'); + } else if (eventParts[0] == 'JD') { + eventName = s._('announcements:boys_doubles'); + } else if (eventParts[0] == 'ME') { + eventName = s._('announcements:girls_singles'); + } else if (eventParts[0] == 'MD') { + eventName = s._('announcements:girls_doubles') + } else if (eventParts[0] == 'GD' || eventParts[0] == 'MX') { + eventName = s._('announcements:mixed_doubles') + } else if (eventParts[0] == 'HE') { + eventName = s._('announcements:men_singles'); + } else if (eventParts[0] == 'HD') { + eventName = s._('announcements:men_doubles'); + } else if (eventParts[0] == 'DE') { + eventName = s._('announcements:women_singles'); + } else if (eventParts[0] == 'DD') { + eventName = s._('announcements:women_doubles'); + } + if (eventName == "") { + if (eventParts[1] == 'JE') { + eventName = s._('announcements:boys_singles'); + } else if (eventParts[1] == 'JD') { + eventName = s._('announcements:boys_doubles'); + } else if (eventParts[1] == 'ME') { + eventName = s._('announcements:girls_singles'); + } else if (eventParts[1] == 'MD') { + eventName = s._('announcements:girls_doubles') + } else if (eventParts[1] == 'GD' || eventParts[1] == 'MX') { + eventName = s._('announcements:mixed_doubles') + } else if (eventParts[1] == 'HE') { + eventName = s._('announcements:men_singles'); + } else if (eventParts[1] == 'HD') { + eventName = s._('announcements:men_doubles'); + } else if (eventParts[1] == 'DE') { + eventName = s._('announcements:women_singles'); + } else if (eventParts[1] == 'DD') { + eventName = s._('announcements:women_doubles'); + } + if (eventParts[0]) { + eventName = eventName + " " + eventParts[0]; + } + } else { + if (eventParts[1]) { + eventName = eventName + " " + eventParts[1]; + } + } + return eventName; +} + + + function render_list(container, event) { render_html_list(container, event); // TODO switch to svg } @@ -1019,7 +2155,7 @@ function render_html_list(container, event) { event.matches.forEach(function(m) { var netscore = m.network_score || []; - var mwinner = calc.match_winner(m.setup.counting, netscore); + var mwinner = calc.match_winner(m.setup, netscore); var row = uiu.el(match_list, 'tr'); uiu.el(row, 'td', { @@ -1043,7 +2179,7 @@ function render_html_list(container, event) { continue; } var nscore = netscore[game_idx]; - var gwinner = calc.game_winner(m.setup.counting, game_idx, nscore[0], nscore[1]); + var gwinner = calc.game_winner(m.setup, game_idx, nscore[0], nscore[1]); uiu.el(score_td, 'span', { 'class': ((gwinner === 'left') ? 'display_list_winning' : ''), 'style': ((gwinner === 'left') ? '' : 'color:#ddd;'), @@ -1160,7 +2296,7 @@ function render_oncourt(s, container, event, court, match, colors) { function _gamescore_from_netscore(netscore, setup) { var gscores = [0, 0]; netscore.forEach(function(gs, game_idx) { - var winner = calc.game_winner(setup.counting, game_idx, gs[0], gs[1]); + var winner = calc.game_winner(setup, game_idx, gs[0], gs[1]); if (winner == 'left') { gscores[0]++; } else if (winner == 'right') { @@ -1177,11 +2313,11 @@ function extract_netscore(match) { return [[0, 0]]; } - var counting = match.setup.counting; + var setup = match.setup; var last_game = res[res.length - 1]; - var last_winner = calc.game_winner(counting, res.length - 1, last_game[0], last_game[1]); + var last_winner = calc.game_winner(setup, res.length - 1, last_game[0], last_game[1]); if ((last_winner === 'left') || (last_winner === 'right')) { - var mwinner = calc.match_winner(counting, res); + var mwinner = calc.match_winner(setup, res); if ((mwinner !== 'left') && (mwinner !== 'right')) { res.push([0, 0]); } @@ -1198,7 +2334,7 @@ function render_andre(s, container, event, court, match, colors) { var server = determine_server(match, current_score); match.setup.teams.forEach(function(team, team_id) { - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -1315,12 +2451,12 @@ function render_international(s, container, event, court, match, colors) { var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); var first_game = (nscore.length < 2); - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var match_over = (mwinner === 'left') || (mwinner === 'right'); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -1403,12 +2539,12 @@ function render_bwf(s, container, event, court, match, colors) { var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); var first_game = (nscore.length < 2); - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var match_over = (mwinner === 'left') || (mwinner === 'right'); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -1485,13 +2621,13 @@ function render_bwfonlyplayers(s, container, event, court, match, colors) { var pcount = is_doubles ? 2 : 1; var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var match_over = (mwinner === 'left') || (mwinner === 'right'); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; var bg_col = colors['b' + team_id] || '#000'; - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -1624,7 +2760,7 @@ function render_greyish(s, container, event, colors) { event.matches.forEach(function(match) { var setup = match.setup; var nscore = extract_netscore(match); - var mwinner = calc.match_winner(setup.counting, nscore); + var mwinner = calc.match_winner(setup, nscore); var tr = uiu.el(table, 'tr', { style: ( @@ -1695,12 +2831,12 @@ function render_clean(s, container, event, court, match, colors) { var pcount = is_doubles ? 2 : 1; var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var match_over = (mwinner === 'left') || (mwinner === 'right'); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -1888,6 +3024,309 @@ function render_teamscore(s, container, event, colors) { }); } +function sleepSync(ms) { + const end = Date.now() + ms; + while (Date.now() < end) { + // tut nichts – blockiert einfach alles + } + } + + +var timer_alternative_text = []; + +function render_tournamentcourt(s, container, event, court, match, colors) { + + //sleepSync(3000); // blockiert synchron für 3 Sekunden + + + var nscore = extract_netscore(match); + var gscore = _gamescore_from_netscore(nscore, match.setup); + var is_doubles = match.setup.is_doubles; + var pcount = is_doubles ? 2 : 1; + var current_score = nscore[nscore.length - 1] || []; + var server = determine_server(match, current_score); + var receiver = determine_receiver(match, current_score); + var first_game = (nscore.length < 2); + var mwinner = calc.match_winner(match.setup, nscore); + var match_over = (mwinner === 'left') || (mwinner === 'right'); + + var match_meta_container = uiu.el(container, 'div', { + style: ( + 'z-index:1;' + + 'position:absolute;' + + 'right: 53vh;' + + 'top:42vh;' + + 'bottom:42vh;' + + 'display:flex;' + + 'align-items:center;' + + 'font-size:10vh;' + + 'justify-content: space-between;' + + 'width: calc(99vw - 53vh);' + + 'text-wrap: nowrap;' + + 'color:' + colors.fg + ), + }); + + var meta_fields = []; + + if (option_applies(s.settings.displaymode_style, 'show_court_number') && s.settings.d_show_court_number) { + meta_fields.push(s._('Court') + ' ' + (court.label || court.num || court.court_id)); + } + + if (option_applies(s.settings.displaymode_style, 'show_competition') && s.settings.d_show_competition) { + if (meta_fields.length) + { + meta_fields.push('\xa0•\xa0'); + } + + meta_fields.push(match.setup.event_name); + } + + if (option_applies(s.settings.displaymode_style, 'show_round') && s.settings.d_show_round) { + if (meta_fields.length) + { + meta_fields.push('\xa0•\xa0'); + } + + meta_fields.push(match.setup.match_name); + } + + show_match_meta(_extract_timer_state(s, match), + match_meta_container, + colors.fg2, + colors.exp, + meta_fields); + + match.setup.teams.forEach(function(team, team_id) { + var col = colors[team_id]; + var bg_col = colors['b' + team_id] || '#000'; + + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); + var team_serving = ( + (gwinner === 'left') ? (team_id === 0) : ( + (gwinner === 'right') ? (team_id === 1) : ( + (server.team_id === team_id)))); + + var team_receiving = ( + (gwinner === 'left') ? (team_id === 1) : ( + (gwinner === 'right') ? (team_id === 0) : ( + (receiver.team_id === team_id)))); + + var player_names = team.players.map(function(player) { + if (!option_applies(s.settings.displaymode_style, 'show_middle_name')) { + return player.name; + } + + if(!s.settings.d_show_middle_name) { + var first_names = player.firstname.split(" "); + return first_names[0] + ' ' + player.lastname; + } + return player.name; + }); + while (player_names.length < pcount) { + player_names.push(''); + } + + var team_container = uiu.el(container, 'div', { + 'class': 'd_tournament', + style: ( + 'color:' + col + ';' + + 'background:' + bg_col + ';' + )}); + + var team_name_container = uiu.el(team_container, 'div', { + style: ( + ((team_id === 0) ? 'position:absolute; bottom: 0;' : '') + + 'width:100%;height:20%;' + + 'font-size: 10vh;' + + 'display: flex;align-items: center;' + ), + }); + + var player_spans = player_names.map(function(pname, player_id) { + var is_server = (!match_over) && team_serving && (server.player_id === player_id); + var is_receiver = (!match_over) && team_receiving && (receiver.player_id === player_id); + var player_container = uiu.el(team_container, 'div', { + 'style': 'height: ' + (is_doubles ? '40%' : '80%') + ';', + 'class': 'd_tournament_player_container', + }); + var pel = uiu.el(player_container, 'div', { + style: ( + 'background: ' + (is_server ? col : bg_col) + ';' + + 'color: ' + (is_server ? bg_col : col) + ';' + + 'height: ' + (is_doubles ? '100%' : '100%') + ';' + ), + 'class': 'd_tournament_player', + }); + return uiu.el(pel, 'div', (s.settings.d_show_doubles_receiving && is_doubles && is_receiver ? {style: ('text-decoration: underline;')} : {}), pname); + }); + + var right_border; + if (! first_game) { + right_border = uiu.el(team_container, 'div', { + 'class': 'd_tournament_gscore', + style: 'background: ' + bg_col + ';' + + 'color: ' + colors.fg + ';' + + 'height: 80%;' + + 'top: ' + (team_id ? '10vh' : '0vh') + ';', + }, gscore[team_id]); + } + + var points = current_score[team_id]; + var points_el = uiu.el(team_container, 'div', { + 'class': 'd_tournament_score' + ((points >= 10) ? ' d_tournament_score_dd' : ''), + style: 'background: ' + (team_serving ? col : bg_col) + '; color: ' + (team_serving ? bg_col : col), + }, points); + if (!right_border) { + right_border = points_el; + } + + player_spans.forEach(function(ps) { + _setup_autosize(ps, right_border, function(parent_node) { + return parent_node.offsetHeight * 0.94; + }); + }); + }); +} + +function render_tournamentplayers(s, container, event, court, match, colors) { + var nscore = extract_netscore(match); + var gscore = _gamescore_from_netscore(nscore, match.setup); + var is_doubles = match.setup.is_doubles; + var pcount = is_doubles ? 2 : 1; + var current_score = nscore[nscore.length - 1] || []; + var server = determine_server(match, current_score); + var receiver = determine_receiver(match, current_score); + var first_game = (nscore.length < 2); + var mwinner = calc.match_winner(match.setup, nscore); + var match_over = (mwinner === 'left') || (mwinner === 'right'); + + var match_meta_container = uiu.el(container, 'div', { + style: ( + 'z-index:1;' + + 'position:absolute;' + + 'right: 1vw;' + + 'top:42vh;' + + 'bottom:42vh;' + + 'display:flex;' + + 'align-items:center;' + + 'font-size:10vh;' + + 'justify-content: space-between;' + + 'width: calc(98vw);' + + 'text-wrap: nowrap;' + + 'color:' + colors.fg + ), + }); + + var meta_fields = []; + + if (option_applies(s.settings.displaymode_style, 'show_court_number') && s.settings.d_show_court_number) { + meta_fields.push(s._('Court') + ' ' + (court.label || court.num || court.court_id)); + } + + if (option_applies(s.settings.displaymode_style, 'show_competition') && s.settings.d_show_competition) { + if (meta_fields.length) + { + meta_fields.push('\xa0•\xa0'); + } + + meta_fields.push(match.setup.event_name); + } + + if (option_applies(s.settings.displaymode_style, 'show_round') && s.settings.d_show_round) { + if (meta_fields.length) + { + meta_fields.push('\xa0•\xa0'); + } + + meta_fields.push(match.setup.match_name); + } + + show_match_meta(_extract_timer_state(s, match), + match_meta_container, + colors.fg2, + colors.exp, + meta_fields); + + match.setup.teams.forEach(function(team, team_id) { + var col = colors[team_id]; + var bg_col = colors['b' + team_id] || '#000'; + + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); + var team_serving = ( + (gwinner === 'left') ? (team_id === 0) : ( + (gwinner === 'right') ? (team_id === 1) : ( + (server.team_id === team_id)))); + + var team_receiving = ( + (gwinner === 'left') ? (team_id === 1) : ( + (gwinner === 'right') ? (team_id === 0) : ( + (receiver.team_id === team_id)))); + + var player_names = team.players.map(function(player) { + if (!option_applies(s.settings.displaymode_style, 'show_middle_name')) { + return player.name; + } + + if(!s.settings.d_show_middle_name) { + var first_names = player.firstname.split(" "); + return first_names[0] + ' ' + player.lastname; + } + return player.name; + }); + while (player_names.length < pcount) { + player_names.push(''); + } + + var team_container = uiu.el(container, 'div', { + 'class': 'd_tournament', + style: ( + 'color:' + col + ';' + + 'background:' + bg_col + ';' + )}); + + var team_name_container = uiu.el(team_container, 'div', { + style: ( + ((team_id === 0) ? 'position:absolute; bottom: 0;' : '') + + 'width:100%;height:20%;' + + 'font-size: 10vh;' + + 'display: flex;align-items: center;' + ), + }); + + var player_spans = player_names.map(function(pname, player_id) { + var is_server = (!match_over) && team_serving && (server.player_id === player_id); + var is_receiver = (!match_over) && team_receiving && (receiver.player_id === player_id); + var player_container = uiu.el(team_container, 'div', { + 'style': 'height: ' + (is_doubles ? '40%' : '80%') + ';', + 'class': 'd_tournament_player_container', + }); + var pel = uiu.el(player_container, 'div', { + style: ( + 'background: ' + (is_server ? col : bg_col) + ';' + + 'color: ' + (is_server ? bg_col : col) + ';' + + 'height: ' + (is_doubles ? '100%' : '100%') + ';' + ), + 'class': 'd_tournament_player', + }); + return uiu.el(pel, 'div', (s.settings.d_show_doubles_receiving && is_doubles && is_receiver ? {style: ('text-decoration: underline;')} : {}), pname); + }); + var right_border; + + right_border = uiu.el(team_container, 'div', { + style: 'position: absolute;' + + 'right: 1vw;', + }, ''); + + player_spans.forEach(function(ps) { + _setup_autosize(ps, right_border, function(parent_node) { + return parent_node.offsetHeight * 0.94; + }); + }); + }); +} + + function render_teamcourt(s, container, event, court, match, colors) { var nscore = extract_netscore(match); var gscore = _gamescore_from_netscore(nscore, match.setup); @@ -1896,7 +3335,7 @@ function render_teamcourt(s, container, event, court, match, colors) { var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); var first_game = (nscore.length < 2); - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var match_over = (mwinner === 'left') || (mwinner === 'right'); var match_name_container = uiu.el(container, 'div', { @@ -1912,18 +3351,22 @@ function render_teamcourt(s, container, event, court, match, colors) { ), }); var timer_state = _extract_timer_state(s, match); + + // First Field is empty because the timer didn't overide the first field + var meta_fields = ["",match.setup.match_name]; if (timer_state) { - create_timer(timer_state, match_name_container, { - style: 'margin-right:1ch', - }); + show_match_meta(timer_state, + match_name_container, + colors.fg2, + colors.fg2, + meta_fields); } - uiu.el(match_name_container, 'div', {}, match.setup.match_name); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; var bg_col = colors['b' + team_id] || '#000'; - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -1998,10 +3441,11 @@ function render_teamcourt(s, container, event, court, match, colors) { }); } + function render_stripes(s, container, event, court, match, colors) { var nscore = extract_netscore(match); var setup = match.setup; - var max_game_count = calc.max_game_count(setup.counting); + var max_game_count = calc.max_game_count(setup); var team_names = event.team_names || ['', '']; var current_score = nscore[nscore.length - 1]; var server = determine_server(match, current_score); @@ -2094,7 +3538,7 @@ function render_stripes(s, container, event, court, match, colors) { var gscore = nscore[game_id]; var cur_serve = ( (nscore.length - 1 === game_id) ? - ((team_id === server.team_id) || (calc.match_winner(setup.counting, nscore) === ((team_id === 0) ? 'left' : 'right'))) : + ((team_id === server.team_id) || (calc.match_winner(setup, nscore) === ((team_id === 0) ? 'left' : 'right'))) : (gscore && (gscore[team_id] > gscore[1 - team_id])) ); uiu.el(tr, 'td', { @@ -2159,14 +3603,14 @@ function render_onlyplayers(s, container, event, court, match, colors) { var is_doubles = match.setup.is_doubles; var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var match_over = (mwinner === 'left') || (mwinner === 'right'); var logo_urls = extradata.team_logos(event); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; var bg_col = colors['b' + team_id]; - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -2245,12 +3689,12 @@ function render_clubplayers(s, container, event, court, match, colors) { var is_doubles = match.setup.is_doubles; var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var match_over = (mwinner === 'left') || (mwinner === 'right'); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -2318,12 +3762,12 @@ function render_clubplayerslr(s, container, event, court, match, colors) { var is_doubles = match.setup.is_doubles; var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var match_over = (mwinner === 'left') || (mwinner === 'right'); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); var team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -2385,7 +3829,7 @@ function render_onlyscore(s, container, event, court, match, colors) { var nscore = extract_netscore(match); var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); - var max_game_count = calc.max_game_count(match.setup.counting); + var max_game_count = calc.max_game_count(match.setup); match.setup.teams.forEach(function(team, team_id) { var col = colors[team_id]; @@ -2396,7 +3840,7 @@ function render_onlyscore(s, container, event, court, match, colors) { var team_serving = false; var current_score = nscore[game_idx]; if (current_score) { - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); team_serving = ( (gwinner === 'left') ? (team_id === 0) : ( (gwinner === 'right') ? (team_id === 1) : ( @@ -2449,7 +3893,7 @@ function render_giantscore(s, container, event, court, match, colors) { var col = colors[team_id]; var bg_col = colors['b' + team_id]; - var mwinner = calc.match_winner(match.setup.counting, nscore); + var mwinner = calc.match_winner(match.setup, nscore); var is_winner = ((mwinner === 'left') && (team_id === 0) || (mwinner === 'right') && (team_id === 1)); var invert = is_winner || (server.team_id === team_id); @@ -2539,27 +3983,86 @@ function _extract_timer_state(s, match) { } var active_timers = []; -function create_timer(timer_state, parent, props) { - var tv = timer.calc(timer_state); - if (!tv.visible || tv.upwards) { + +function show_match_meta(timer_state, parent, default_color, exigent_color, match_meta) { + if(!match_meta){ + match_meta = [""]; + } + + let timer_alternative_text = []; + + var create_text_element = function(parent, element, color) { + let fontSize = '13vh'; + timer_alternative_text.push([uiu.el(parent, 'div', {style: ('font-size:' + fontSize + '; color:' + color +'; width: fit-content;')}, element), fontSize]); + }; + + var auto_size_alternative_strings = function(parrent_el) { + var parrent_width = parrent_el.offsetWidth; + var child_width = 0; + timer_alternative_text.forEach(function(item) { + let [el, origFontSize] = item; + el.style.fontSize = origFontSize; + child_width += el.offsetWidth; + }); + + if(parrent_width < child_width) { + timer_alternative_text.forEach(function(item) { + + let [el, origFontSize] = item; + var match = origFontSize.match(/^(\d*\.?\d+)\s*([a-zA-Z%]+)$/); + var numeric_value = match[1] ? parseFloat(match[1]) : 10; + var unit = match[2] ? match[2] : 'vh'; + + el.style.fontSize = numeric_value * (parrent_width/child_width) + unit; + }); + } + } + + window.addEventListener('resize', () => {auto_size_alternative_strings(parent);} , true); + + if(timer_state) { + var tv = timer.calc(timer_state); + } + + if (!tv || !tv.visible) { + match_meta.forEach(function(element){create_text_element(parent, element, default_color);}); + auto_size_alternative_strings(parent); return; } - var el = uiu.el(parent, 'div', props, tv.str); + + create_text_element(parent, match_meta[0], default_color); + + let timerFontSize = '25vh'; + var el = uiu.el(parent, 'div', {style: ('font-size:' + timerFontSize + '; color:' + default_color +';')}, '\xa0'+tv.str); + timer_alternative_text.push([el, timerFontSize]); var tobj = {}; active_timers.push(tobj); var update = function() { var tv = timer.calc(timer_state); - var visible = tv.visible && !tv.upwards; - uiu.text(el, tv.str); + var visible = tv.visible; + uiu.text(el, '\xa0'+tv.str); + + if(tv.exigent && exigent_color) { + //uiu.attr(el, exigent_color); + el.style.color = exigent_color; + } + if (visible && tv.next) { tobj.timeout = setTimeout(update, tv.next); } else { tobj.timeout = null; } + if (!visible) { - uiu.remove(el); + timer_alternative_text.forEach(function(item) { + let [element, origFontSize] = item; + uiu.remove(element); + }) + timer_alternative_text = []; + match_meta.forEach(function(element){create_text_element(parent, element, default_color);}); } + auto_size_alternative_strings(parent); }; update(); } @@ -2627,7 +4130,7 @@ function render_2court(s, container, event, colors) { var gscore = _gamescore_from_netscore(nscore, match.setup); var current_score = nscore[nscore.length - 1] || []; var server = determine_server(match, current_score); - var gwinner = calc.game_winner(match.setup.counting, nscore.length - 1, current_score[0], current_score[1]); + var gwinner = calc.game_winner(match.setup, nscore.length - 1, current_score[0], current_score[1]); match.setup.teams.forEach(function(team, team_id) { var team_container = uiu.el(court_container, 'div', 'd_2court_team' + team_id); @@ -2664,17 +4167,19 @@ function render_2court(s, container, event, colors) { match.setup.match_name : (match.setup.event_name || '').replace(/(?:\s*-)?\s*Qualification/, 'Q')); var d_2court_info_container = uiu.el(court_container, 'div', 'd_2court_info'); - uiu.el(d_2court_info_container, 'div', { - style: 'color:' + colors.fg + ';', - }, match_name); + + var meta_container = uiu.el(d_2court_info_container, 'div', { + style: 'color:' + colors.fg + '; width:100%; display:flex; flex-wrap: nowrap; justify-content: space-evenly;' , + }); + + var meta_fields = ['', match_name, '']; var timer_state = _extract_timer_state(s, match); - if (timer_state) { - create_timer(timer_state, court_container, { - 'class': 'd_2court_timer', - style: 'background: ' + colors.bg + '; color: ' + colors.fg + ';', - }); - } + show_match_meta(timer_state, + meta_container, + colors.fg, + colors.fg, + meta_fields); } } @@ -2734,6 +4239,11 @@ function update(err, s, event) { uiu.visible_qs('.settings_display_court_id', option_applies(style, 'court_id')); uiu.visible_qs('.settings_display_reverse_order', option_applies(style, 'reverse_order')); uiu.visible_qs('.settings_d_show_pause', option_applies(style, 'show_pause')); + uiu.visible_qs('.settings_d_show_court_number', option_applies(style, 'show_court_number')); + uiu.visible_qs('.settings_d_show_competition', option_applies(style, 'show_competition')); + uiu.visible_qs('.settings_d_show_round', option_applies(style, 'show_round')); + uiu.visible_qs('.settings_d_show_middle_name', option_applies(style, 'show_middle_name')); + uiu.visible_qs('.settings_d_show_doubles_receiving', option_applies(style, 'show_doubles_receiving')); uiu.visible_qs('.settings_d_scale', option_applies(style, 'scale')); uiu.visible_qs('.settings_d_team_colors', option_applies(style, 'team_colors')); @@ -2764,7 +4274,7 @@ function update(err, s, event) { title: uc, value: s.settings['d_' + uc], }); - color_input.addEventListener('change', on_color_select); + color_input.addEventListener('change', on_style_change); }); color_inputs.setAttribute('data-json', JSON.stringify(used_colors)); } @@ -2796,6 +4306,8 @@ function update(err, s, event) { onlyscore: render_onlyscore, stripes: render_stripes, teamcourt: render_teamcourt, + tournamentcourt: render_tournamentcourt, + tournamentplayers: render_tournamentplayers, }[style]; if (xfunc) { var court = _render_court(s, container, event); @@ -2818,6 +4330,7 @@ function update(err, s, event) { ), }); + /* // background for colors for (var team_id = 0;team_id < 2;team_id++) { uiu.el(nomatch_el, 'div', { @@ -2827,6 +4340,7 @@ function update(err, s, event) { ), }); } + */ var _render_team_name = function(team_id) { uiu.el(nomatch_el, 'div', { @@ -2844,9 +4358,10 @@ function update(err, s, event) { } else if (event.tournament_logo_url) { uiu.el(nomatch_el, 'img', { src: event.tournament_logo_url, - style: 'height: 70vh;', + style: 'max-height: 70vh; max-width: 90vw; height:70vh;', alt: (event.tournament_name || ''), }); + } else { var tname = event.tournament_name; if (tname) { @@ -2859,7 +4374,7 @@ function update(err, s, event) { } uiu.el(nomatch_el, 'div', { style: ( - 'font-size:18vmin;' + 'font-size:22vmin;' ), }, s._('Court') + ' ' + (court.label || court.num || court.court_id)); if (is_team) { @@ -2879,10 +4394,13 @@ function update(err, s, event) { castall: render_castall, greyish: render_greyish, tournament_overview: render_tournament_overview, + tournament_overview_dm: render_tournament_overview_dm, + tournament_overview_dm_finals: render_tournament_overview_dm_finals, tim: render_tim, teamscore: render_teamscore, stream: render_stream, streamcourt: render_streamcourt, + streamcourt_dm: render_streamcourt_dm, streamteam: render_streamteam, }[style]; if (ofunc) { @@ -2894,7 +4412,6 @@ function update(err, s, event) { // Default: top+list render_top_list(s, container, event); } - function on_style_change(s) { if (s.ui && s.ui.displaymode_visible) { update(_last_err, s, s.event); @@ -2907,6 +4424,7 @@ function on_style_change(s) { input.value = col; } }); + network.reload_match_information(); } var _cancel_updates = null; @@ -2986,6 +4504,21 @@ function ui_init(s, hash_query) { if (hash_query.show_pause) { settings.change(s, 'd_show_pause', (hash_query.show_pause === 'true')); } + if (hash_query.show_court_number) { + settings.change(s, 'd_show_court_number', (hash_query.show_court_number === 'true')); + } + if (hash_query.show_competition) { + settings.change(s, 'd_show_competition', (hash_query.show_competition === 'true')); + } + if (hash_query.show_round) { + settings.change(s, 'd_show_round', (hash_query.show_round === 'true')); + } + if (hash_query.show_middle_name) { + settings.change(s, 'd_show_middle_name', (hash_query.show_middle_name === 'true')); + } + if (hash_query.show_doubles_receiving) { + settings.change(s, 'd_show_doubles_receiving', (hash_query.show_doubles_receiving === 'true')); + } if (hash_query.team_colors) { settings.change(s, 'd_team_colors', (hash_query.team_colors === 'true')); } @@ -3072,12 +4605,18 @@ function option_applies(style_id, option_name) { onlyscore: ['court_id', 'team_colors', 'c0', 'cb0', 'c1', 'cb1'], stream: ['reverse_order'], streamcourt: ['court_id'], + streamcourt_dm: ['court_id'], streamteam: ['team_colors', 'c0', 'cb0', 'c1', 'cb1', 'cfg', 'cbg'], teamcourt: ['court_id', 'team_colors', 'c0', 'cb0', 'c1', 'cb1', 'cfg', 'cfg2', 'show_pause'], + tournamentcourt: ['court_id', 'team_colors', 'c0', 'cb0', 'c1', 'cb1', 'cfg', 'cfg2', 'cexp', 'show_pause', 'show_court_number', 'show_competition', 'show_round', 'show_middle_name', 'show_doubles_receiving'], + tournamentplayers: ['court_id', 'team_colors', 'c0', 'cb0', 'c1', 'cb1', 'cfg', 'cfg2', 'cexp', 'show_pause', 'show_court_number', 'show_competition', 'show_round', 'show_middle_name', 'show_doubles_receiving'], teamscore: ['team_colors', 'c0', 'c1', 'cfg', 'cbg'], tim: ['cbg', 'cfg', 'ctim_blue', 'ctim_active'], tournament_overview: ['cfg', 'cbg', 'cbg3', 'cborder', 'cfg2'], + tournament_overview_dm: ['cfg', 'cbg', 'cbg3', 'cborder', 'cfg2'], + tournament_overview_dm_finals: ['cfg', 'cbg', 'cbg3', 'cborder', 'cfg2'], stripes: ['court_id', 'cbg', 'team_colors', 'c0', 'c1', 'cfg', 'cfgdark', 'cbg4', 'cserv'], + umpire: ['fullscreen_ask', 'shuttle_counter', 'show_announcements', 'negative_timers', 'editmode_doubleclick', 'click_mode', 'button_block_timeout', 'network_timeout', 'network_update_interval', 'style'], }; var bs = BY_STYLE[style_id]; if (bs) { diff --git a/js/editmode.js b/js/editmode.js index d9b6451d..8d34169a 100644 --- a/js/editmode.js +++ b/js/editmode.js @@ -119,7 +119,7 @@ function read_input() { right_val = 0; } - var winner = calc.game_winner(state.setup.counting, game_index, left_val, right_val); + var winner = calc.game_winner(state.setup, game_index, left_val, right_val); res.push({ winner: winner, left: left_val, @@ -130,7 +130,7 @@ function read_input() { return res; } - var mwinner = calc.match_winner(state.setup.counting, res); + var mwinner = calc.match_winner(state.setup, res); if (mwinner != 'inprogress') { return res; } diff --git a/js/eventsheet.js b/js/eventsheet.js index e4c1c258..862176a9 100644 --- a/js/eventsheet.js +++ b/js/eventsheet.js @@ -171,10 +171,10 @@ function _player_names(match, team_id) { } } -function calc_gamescore(counting, netscore) { +function calc_gamescore(setup, netscore) { var scores = [0, 0]; netscore.forEach(function(game_score, game_idx) { - var winner = calc.game_winner(counting, game_idx, game_score[0], game_score[1]); + var winner = calc.game_winner(setup, game_idx, game_score[0], game_score[1]); if (winner == 'left') { scores[0]++; } else if (winner == 'right') { @@ -184,8 +184,8 @@ function calc_gamescore(counting, netscore) { return scores; } -function calc_matchscore(counting, netscore) { - var winner = calc.match_winner(counting, netscore); +function calc_matchscore(setup, netscore) { + var winner = calc.match_winner(setup, netscore); if (winner == 'left') { return [1, 0]; } else if (winner == 'right') { @@ -335,8 +335,8 @@ function save_bundesliga(ev, es_key, ui8r, extra_data) { points[0] += game_score[0]; points[1] += game_score[1]; }); - games = calc_gamescore(m.setup.counting, netscore); - matches = calc_matchscore(m.setup.counting, netscore); + games = calc_gamescore(m.setup, netscore); + matches = calc_matchscore(m.setup, netscore); } scores.push(points[0]); scores.push(points[1]); @@ -670,13 +670,13 @@ var render_nla = _svg_func(function(svg, ev) { } if (netscore && (netscore.length > 0) && ((netscore[0][0] > 0) || (netscore[0][1] > 0))) { - var games = calc_gamescore(match.setup.counting, netscore); + var games = calc_gamescore(match.setup, netscore); sum_games[0] += games[0]; sum_games[1] += games[1]; _svg_text(svg, eid + '_games0', games[0]); _svg_text(svg, eid + '_games1', games[1]); - var matches_score = calc_matchscore(match.setup.counting, netscore); + var matches_score = calc_matchscore(match.setup, netscore); if (matches_score[0] !== undefined) { sum_matches[0] += matches_score[0]; sum_matches[1] += matches_score[1]; @@ -1124,13 +1124,13 @@ var render_basic_eventsheet = _svg_func(function(svg, ev, es_key, extra_data) { _svg_text(svg, 'match' + match_id + '_points0', points[0]); _svg_text(svg, 'match' + match_id + '_points1', points[1]); - var games = calc_gamescore(match.setup.counting, netscore); + var games = calc_gamescore(match.setup, netscore); sum_games[0] += games[0]; sum_games[1] += games[1]; _svg_text(svg, 'match' + match_id + '_games0', games[0]); _svg_text(svg, 'match' + match_id + '_games1', games[1]); - var matches_score = calc_matchscore(match.setup.counting, netscore); + var matches_score = calc_matchscore(match.setup, netscore); if (matches_score[0] !== undefined) { sum_matches[0] += matches_score[0]; sum_matches[1] += matches_score[1]; @@ -1228,7 +1228,7 @@ function calc_sums(match) { res.p[0] += ngame[0]; res.p[1] += ngame[1]; - var winner = calc.game_winner(match.setup.counting, game_idx, ngame[0], ngame[1]); + var winner = calc.game_winner(match.setup, game_idx, ngame[0], ngame[1]); if (winner === 'left') { res.g[0]++; } else if (winner === 'right') { @@ -1236,7 +1236,7 @@ function calc_sums(match) { } }); - var mwinner = calc.match_winner(match.setup.counting, netscore); + var mwinner = calc.match_winner(match.setup, netscore); if (mwinner === 'left') { res.m = [1, 0]; } else if (mwinner === 'right') { @@ -1742,8 +1742,8 @@ function save_obl(ev, es_key, ui8r, extra_data) { } var netscore = m.network_score || []; - var counting = m.setup.counting; - var mwinner = calc.match_winner(counting, netscore); + var setup = m.setup; + var mwinner = calc.match_winner(setup, netscore); var teams = m.setup.teams; var ID_COLS = ['B', 'J']; diff --git a/js/eventutils.js b/js/eventutils.js index b87872ee..22662b34 100644 --- a/js/eventutils.js +++ b/js/eventutils.js @@ -162,6 +162,8 @@ function annotate(s, event) { event.event_name = event.team_names[0] + ' - ' + event.team_names[1]; } + var scoring_format = event.scoring_format || calc.scoring_format_from_counting(event.counting) || default_scoring_format(league_key); + var counting = event.counting || (scoring_format && scoring_format.name); var props = { league_key: league_key, tournament_name: event.tournament_name, @@ -169,14 +171,15 @@ function annotate(s, event) { team_competition: event.team_competition, nation_competition: event.nation_competition, away_first: event.away_first, - counting: event.counting, + counting: counting, + scoring_format: scoring_format, date: event.date, }; - if (league_key && !event.counting) { - props.counting = default_counting(league_key); - } event.matches.forEach(function(m) { var setup = m.setup; + if (!setup.scoring_format && setup.counting) { + setup.scoring_format = calc.scoring_format_from_counting(setup.counting); + } for (var key in props) { var val = props[key]; if (val === undefined) { @@ -185,7 +188,7 @@ function annotate(s, event) { /*@DEV*/ if (setup[key] === val) { - if (key !== 'counting') { // counting is very important, and in btde it's dynamic + if ((key !== 'counting') && (key !== 'scoring_format')) { // counting is very important, and in btde it's dynamic report_problem.silent_error('Redundant key ' + key + ' in ' + setup.match_id); } } @@ -513,6 +516,19 @@ function default_counting(league_key) { } } +function default_scoring_format(league_key) { + var counting = default_counting(league_key); + return calc.scoring_format_from_counting(counting); +} + +function default_setup(league_key) { + var scoring_format = default_scoring_format(league_key) || calc.scoring_format_from_counting('3x21'); + return { + counting: scoring_format && scoring_format.name, + scoring_format: scoring_format, + }; +} + function umpire_pay(league_key) { if (is_bundesliga(league_key)) { return { // §3.2 BLO @@ -567,7 +583,9 @@ function make_empty_matches(league_key, event_id) { {name: 'GD', is_doubles: true}, {name: '2.HE', is_doubles: false}, ]; - var counting = default_counting(league_key); + var setup_defaults = default_setup(league_key); + var counting = setup_defaults.counting; + var scoring_format = setup_defaults.scoring_format return rawdef.map(function(rd) { return { @@ -575,6 +593,7 @@ function make_empty_matches(league_key, event_id) { match_name: rd.name, match_id: event_id + '_' + rd.name, counting: counting, + scoring_format: scoring_format || calc.scoring_format_from_counting(counting), is_doubles: rd.is_doubles, teams: [{players: []}, {players: []}], }, @@ -644,6 +663,8 @@ return { set_not_before: set_not_before, setups_eq: setups_eq, default_counting: default_counting, + default_scoring_format: default_scoring_format, + default_setup: default_setup, umpire_pay: umpire_pay, name_by_league: name_by_league, is_german8: is_german8, diff --git a/js/i18n_de.js b/js/i18n_de.js index aac6f36e..ab708b41 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -17,7 +17,8 @@ var i18n_de = { 'Call referee': 'Referee rufen', 'Are you retiring?': 'Werden Sie aufgeben?', 'import link': 'Aus Datei importieren ...', -'send export': 'Export senden', +'send export': 'Speichern', +'reset export': 'Zurücksetzen', 'select pick': 'Auswählen', 'back': 'Zurück', @@ -49,11 +50,12 @@ var i18n_de = { 'network:error': 'Fehler bei der Netzwerk-Übertragung', 'network:error:unconfigured': 'Keine Netzwerk-Anbindung konfiguriert! (Einzel-Demo-Modus statt #bldemo?)', -'network:error:bts': 'BTS nicht via HTTP erreichbar', +'network:error:bts': 'Verbindung zum BTS unterbrochen', 'network:error:http': 'Netzwerk-Fehler (Code {code})', 'network:error:status': '(Status ist {status})', 'network:Matches': 'Spiele', 'network:Matches on court': 'Spiele auf Feld {court}', +'network:Tabletoperator': 'Tabletbedienung:', 'network:restart match': 'Spiel bei 0-0 neu starten', 'network:resume match': 'Spiel bei {score} fortsetzen', 'network:in progress': 'Das Spiel {match} wurde bereits angefangen', @@ -142,7 +144,7 @@ var i18n_de = { 'wonby|2': 'Der zweite Satz', 'wonby|3': 'Der dritte Satz', 'wonby|4': 'Der vierte Satz', -'wonby.match': 'Das Spiel wurde gewonnen von {winner_name} {score_str}', +'wonby.match': 'Das Spiel wurde gewonnen von {winner_name} {score_str}\n\nBestätigen des Ergebnisses durch Klick.', 'wonby.walkover': '(Walkover zugunsten von {winner_name}.\n{loser_name} waren nicht anwesend.)', 'wonby.and': ' und ', 'game(won)': 'Satz', @@ -195,6 +197,7 @@ var i18n_de = { 'settings:Network statistics': 'Netzwerkstatistiken', 'settings:Order link': 'Reihenfolge', 'settings:Export link': 'Exportieren', +'settings:Clear Match Archive': 'Alte Spiele löschen', 'settings:New match': 'Neues Spiel', 'settings:Singles': 'Einzel', 'settings:Doubles': 'Doppel', @@ -213,22 +216,23 @@ var i18n_de = { 'settings:Import Event': 'Wettkampf importieren', 'settings:import from URL': 'URL importieren', 'settings:import_url-placeholder': 'z.B. https://www.turnier.de/...', -'settings:counting': 'Zählweise', -'settings:counting|3x21': 'BWF (3x21)', -'settings:counting|2x21+11': '2x21, 3. Satz bis 11', -'settings:counting|5x11_15': 'BWF 2016 Experiment Option 1 (5x11 bis max. 15)', -'settings:counting|5x11_15^90': 'Bundesliga 2017- (5x11 bis max. 15, 90s Pause)', -'settings:counting|5x11_15~NLA': 'NLA 2019 (5x11 bis max. 15, 120s Pause)', -'settings:counting|5x11/3': 'BWF 2016 Experiment Option 2 (5x11, Verlängerung bis 13)', -'settings:counting|5x11_11': 'UAE (5x11 ohne Verlängerung)', -'settings:counting|3x15_18': 'Verkürzt (3x15 bis max. 18)', -'settings:counting|1x21': 'Bundesliga Goldener Satz (1x21)', -'settings:counting|1x11_15': 'Bundesliga Goldener Satz Experiment (1x11 bis max. 15)', +'settings:scoring_format': 'Punktsystem', +'settings:scoring_format|3x21': 'BWF (3x21)', +'settings:scoring_format|2x21+11': '2x21, 3. Satz bis 11', +'settings:scoring_format|5x11_15': 'BWF 2016 Experiment Option 1 (5x11 bis max. 15)', +'settings:scoring_format|5x11_15^90': 'Bundesliga 2017- (5x11 bis max. 15, 90s Pause)', +'settings:scoring_format|5x11_15~NLA': 'NLA 2019 (5x11 bis max. 15, 120s Pause)', +'settings:scoring_format|5x11/3': 'BWF 2016 Experiment Option 2 (5x11, Verlängerung bis 13)', +'settings:scoring_format|5x11_11': 'UAE (5x11 ohne Verlängerung)', +'settings:scoring_format|3x15_18': 'Verkürzt (3x15 bis max. 18)', +'settings:scoring_format|1x21': 'Bundesliga Goldener Satz (1x21)', +'settings:scoring_format|1x11_15': 'Bundesliga Goldener Satz Experiment (1x11 bis max. 15)', 'settings:style': 'Oberfläche', 'settings:style:default': 'Standard', 'settings:style:complete': 'Vollständig', 'settings:style:clean': 'Nur Feld und Vollbild', 'settings:style:focus': 'Fokus', +'settings:style:hidden': 'Verborgen (zentrale Verwaltung)', 'settings:warmup': 'Spielfeld\u00ADgewöhnungszeit', 'settings:warmup:bwf-2016': 'BWF ab 2016 (90s)', @@ -520,6 +524,8 @@ var i18n_de = { 'displaymode|bwf': 'BWF', 'displaymode|clean': 'Clean', 'displaymode|teamcourt': 'Mannschaftskampf', +'displaymode|tournamentcourt': 'Individual-Turnier', +'displaymode|tournamentplayers': 'Individual-Turnier Nur Spieler', 'displaymode|2court': '2 Felder', 'displaymode|andre': 'André', 'displaymode|tim': 'Tim', @@ -536,6 +542,9 @@ var i18n_de = { 'displaymode|stripes': 'Streifen', 'displaymode|stream': 'Stream', 'displaymode|streamcourt': 'Court-Stream', +'displaymode|streamcourt_dm': 'Court-Stream für DM 2025', +'displaymode|tournament_overview_dm': 'Aktuelle Spielstände für DM 2025', +'displaymode|tournament_overview_dm_finals': 'Aktuelle Spielstände für DM 2025 - Finals', 'displaymode|streamteam': 'Stream-Team', 'displaymode:court_id': 'Court:', 'displaymode:court_id:loading': 'lade ...', @@ -545,6 +554,11 @@ var i18n_de = { 'displaymode:colors': 'Farben:', 'displaymode:use team colors': 'Verwende Team-Farben', 'displaymode:show_pause': 'Zeige verbleibende Pausenzeit', +'displaymode:show_court_number': 'Zeige Spielfeldnummer', +'displaymode:show_competition': 'Zeige die Konkurrenz', +'displaymode:show_round': 'Zeige die Runde', +'displaymode:show_middle_name': 'Zeige zweiten Vornamen der Spieler', +'displaymode:show_doubles_receiving': 'Unterstreiche den annehmenden Spieler im Doppel', 'displaymode:hide settings': 'Verbergen', 'liveaw:lost connection': 'Verbindung wird wiederhergestellt ...', @@ -656,6 +670,38 @@ var i18n_de = { 'login:button': 'Einloggen', 'login:link': 'Login als ...', 'login:close': 'Schließen', + +'announcements:begin_to_play': 'Bitte mit dem Spielen beginnen!', +'announcements:second_call': '"Zweiter Aufruf fuer:"', +'announcements:vs': ' gegen ', +'announcements:counting_board_service': 'Klapptafelbedienung:', +'announcements:table_service': 'Tabletbedienung:', +'announcements:umpire': 'Schiedsrichter:', +'announcements:service_judge': 'Aufschlagrichter:', +'announcements:and': ' und ', +'announcements:preparation': 'In Vorbereitung:', +'announcements:meetingpoint': 'Treffen am Meetingpoint!', +'announcements:on_court': 'Auf Spielfeld ', +'announcements:match_number': 'Spiel Nummer ', +'announcements:boys_singles': 'Jungeneinzel', +'announcements:boys_doubles': 'Jungendoppel', +'announcements:girls_singles': 'Maedchenneinzel', +'announcements:girls_doubles': 'Maedchendoppel', +'announcements:mixed_doubles': 'Gemischtes Doppel', +'announcements:men_singles': 'Herreneinzel', +'announcements:men_doubles': 'Herrendoppel', +'announcements:women_singles': 'Dameneinzel', +'announcements:women_doubles': 'Damendoppel', +'announcements:round_64': '1. Runde', +'announcements:round_32': '2. Runde', +'announcements:round_16': '3. Runde', +'announcements:quaterfinal': 'Viertelfinale', +'announcements:semifinal': 'Halbfinale', +'announcements:final': 'Finale', +'announcements:intermediate_round': 'Zwischenrunde', +'announcements:game_for_place': 'Spiel um Platz', +'announcements:voice': 'Google Deutsch', +'announcements:lang': 'de-DE', }; /*@DEV*/ diff --git a/js/i18n_dech.js b/js/i18n_dech.js index 2354c458..ecf51710 100644 --- a/js/i18n_dech.js +++ b/js/i18n_dech.js @@ -14,7 +14,7 @@ var i18n_dech = { 'Event Sheet': 'Resultatblatt', 'match suspended': 'Das Spiel ist suspendiert', 'ready to play': 'Bereit zum Spielen.', -'wonby.match': 'Spiel gewonnen von {winner_name} {score_str}', +'wonby.match': 'Spiel gewonnen von {winner_name} {score_str}\n\nBestätigen des Ergebnisses durch Klick.', 'wonby.winner': ' gewonnen von {winner_name} {winner_score}-{loser_score}', 'wonby|1': 'Erster Satz', 'wonby|2': 'Zweiter Satz', diff --git a/js/i18n_en.js b/js/i18n_en.js index abebf186..9f6116b6 100644 --- a/js/i18n_en.js +++ b/js/i18n_en.js @@ -17,7 +17,8 @@ var i18n_en = { 'Call referee': 'Call referee', 'Are you retiring?': 'Are you retiring?', 'import link': 'Import event from backup file ...', -'send export': 'send export file', +'send export': 'Save setting', +'reset export': 'Reset setting', 'select pick': 'Select', 'back': 'Back', @@ -54,6 +55,7 @@ var i18n_en = { 'network:error:status': '(State is {status})', 'network:Matches': 'Matches', 'network:Matches on court': 'Matches on court {court}', +'network:Tabletoperator': 'Tablet service:', 'network:restart match': 'Restart match at 0-0', 'network:resume match': 'Resume match at {score}', 'network:in progress': 'Match {match} has already been started', @@ -142,7 +144,7 @@ var i18n_en = { 'wonby|2': 'Second game', 'wonby|3': 'Third game', 'wonby|4': 'Fourth game', -'wonby.match': 'Match won by {winner_name} {score_str}', +'wonby.match': 'Match won by {winner_name} {score_str}\n\nConfirming the result by clicking.', 'wonby.walkover': '(Walkover in favor of {winner_name}.\n{loser_name} did not show up.)', 'wonby.and': ' and ', 'game(won)': 'Game', @@ -212,22 +214,23 @@ var i18n_en = { 'settings:Import Event': 'Import event', 'settings:import from URL': 'Import from URL', 'settings:import_url-placeholder': 'https://www.turnier.de/...', -'settings:counting': 'Scoring:', -'settings:counting|3x21': 'BWF (3x21)', -'settings:counting|2x21+11': '2x21, 3rd game until 11', -'settings:counting|5x11_15': 'BWF 2016 Experiment Option 1 (5x11 until max. 15)', -'settings:counting|5x11_15^90': 'German Bundesliga 2017 (5x11 until max. 15, 90s intervals)', -'settings:counting|5x11_15~NLA': 'Swiss NLA 2019 (5x11 until max. 15, 120s intervals)', -'settings:counting|5x11/3': 'BWF 2016 Experiment Option 2 (5x11 with 3 point challenge)', -'settings:counting|5x11_11': 'UAE (5x11 sudden death)', -'settings:counting|1x21': 'One Game (1x21)', -'settings:counting|1x11_15': 'One Game 2016 Experiment Option 1 (1x11 until max. 15)', -'settings:counting|3x15_18': 'Shortened (3x15 until max. 18)', +'settings:scoring_format': 'Scoring format:', +'settings:scoring_format|3x21': 'BWF (3x21)', +'settings:scoring_format|2x21+11': '2x21, 3rd game until 11', +'settings:scoring_format|5x11_15': 'BWF 2016 Experiment Option 1 (5x11 until max. 15)', +'settings:scoring_format|5x11_15^90': 'German Bundesliga 2017 (5x11 until max. 15, 90s intervals)', +'settings:scoring_format|5x11_15~NLA': 'Swiss NLA 2019 (5x11 until max. 15, 120s intervals)', +'settings:scoring_format|5x11/3': 'BWF 2016 Experiment Option 2 (5x11 with 3 point challenge)', +'settings:scoring_format|5x11_11': 'UAE (5x11 sudden death)', +'settings:scoring_format|1x21': 'One Game (1x21)', +'settings:scoring_format|1x11_15': 'One Game 2016 Experiment Option 1 (1x11 until max. 15)', +'settings:scoring_format|3x15_18': 'Shortened (3x15 until max. 18)', 'settings:style': 'User Interface', 'settings:style:default': 'Default', 'settings:style:complete': 'Complete', 'settings:style:clean': 'Clean', 'settings:style:focus': 'Focus Mode', +'settings:style:hidden': 'Hidden Mode (central administration)', 'settings:warmup': 'Warmup:', 'settings:warmup:bwf-2016': 'BWF 2016+ (120s, ready after 90s)', @@ -519,6 +522,8 @@ var i18n_en = { 'displaymode|bwf': 'BWF', 'displaymode|clean': 'clean', 'displaymode|teamcourt': 'team display', +'displaymode|tournamentcourt': 'individual tournament', +'displaymode|tournamentplayers': 'individual tournament players only', 'displaymode|2court': '2 courts', 'displaymode|castall': 'greenscreen (all courts)', 'displaymode|andre': 'André', @@ -535,6 +540,8 @@ var i18n_en = { 'displaymode|stripes': 'stripes', 'displaymode|stream': 'stream', 'displaymode|streamcourt': 'court stream', +'displaymode|streamcourt_dm': 'Court-Stream for DM 2025', +'displaymode|tournament_overview_dm': 'Current Scoresfor DM 2025', 'displaymode|streamteam': 'stream team', 'displaymode:court_id': 'court:', 'displaymode:court_id:loading': 'loading ...', @@ -544,6 +551,11 @@ var i18n_en = { 'displaymode:colors': 'Colors:', 'displaymode:use team colors': 'use team colors', 'displaymode:show_pause': 'Show interval timer', +'displaymode:show_court_number': 'Show court number', +'displaymode:show_competition': 'Show the competition', +'displaymode:show_round': 'Show the round', +'displaymode:show_middle_name': 'Show middle names of players', +'displaymode:show_doubles_receiving': 'Underline the receiving player in doubles', 'displaymode:hide settings': 'Hide', 'liveaw:lost connection': 'Reconnecting ...', @@ -656,6 +668,38 @@ var i18n_en = { 'login:link': 'Log in as ...', 'login:close': 'Close', +'announcements:begin_to_play': 'Start to play!', +'announcements:second_call': '"Second call for:"', +'announcements:vs': ' vs ', +'announcements:counting_board_service': 'Countingboard service:', +'announcements:table_service': 'Tablet service:', +'announcements:umpire': 'Umpire:', +'announcements:service_judge': 'Servicejudge:', +'announcements:and': ' and ', +'announcements:preparation': 'In preparation:', +'announcements:meetingpoint': 'Come to the meetingpoint!', +'announcements:on_court': 'On Court ', +'announcements:match_number': 'Match number ', +'announcements:boys_singles': 'Boys singles', +'announcements:boys_doubles': 'Boys double', +'announcements:girls_singles': 'Girls singles', +'announcements:girls_doubles': 'Girls doubles', +'announcements:mixed_doubles': 'Mixed doubles', +'announcements:men_singles': 'Men singles', +'announcements:men_doubles': 'Men doubles', +'announcements:women_singles': 'Women singles', +'announcements:women_doubles': 'Women doubles', +'announcements:round_64': 'Round of 64', +'announcements:round_32': 'Round of 32', +'announcements:round_16': 'Round of 16', +'announcements:quaterfinal': 'Quarterfinal', +'announcements:semifinal': 'Semifinal', +'announcements:final': 'Final', +'announcements:intermediate_round': 'Intermediate round', +'announcements:game_for_place': 'Game for place ', +'announcements:voice': 'Google UK English Male', +'announcements:lang': 'en-EN', + }; /*@DEV*/ diff --git a/js/i18n_frch.js b/js/i18n_frch.js index 38383241..4c7349c3 100644 --- a/js/i18n_frch.js +++ b/js/i18n_frch.js @@ -18,7 +18,8 @@ var i18n_frch = { 'Call referee': 'Appelle juge-arbitre', 'Are you retiring?': 'Abandonnez-vous?', 'import link': 'Importer un événement à partir du fichier de sauvegarde ...', -'send export': 'Envoyer un fichier d\'exportation', +'send export': 'Enregistrer les paramètres', +'reset export': 'Réinitialiser les paramètres', 'select pick': 'Choisir', 'back': 'Retourner', @@ -52,6 +53,7 @@ var i18n_frch = { 'network:error:unconfigured': 'Connexion réseau non configurée (mode de démonstration? Mettre #nlademo dans l\'URL)', 'network:Matches': 'Jeux', 'network:Matches on court': 'Jeux sur {court}', +'network:Tabletoperator': 'Commande de la tablette:', 'network:restart match': 'Redémarrer le jeu à 0-0', 'network:resume match': 'Reprendre le jeu à {score}', 'network:in progress': 'Le jeu {match} a déjà été lancé', @@ -139,7 +141,7 @@ var i18n_frch = { 'wonby|2': 'Deuxième set', 'wonby|3': 'Troisième set', 'wonby|4': 'Quatrième set', -'wonby.match': 'Match gagné par {winner_name} {score_str}', +'wonby.match': 'Match gagné par {winner_name} {score_str}\n\nConfirmer le résultat en cliquant.', 'wonby.walkover': '(Walkover pour {winner_name}.\n{loser_name} ne s\'est pas présenté.)', 'wonby.and': ' et ', 'game(won)': 'Set', @@ -209,17 +211,17 @@ var i18n_frch = { 'settings:Import Event': 'Import event', 'settings:import from URL': 'Importer de l\'URL', 'settings:import_url-placeholder': 'https://www.turnier.de/...', -'settings:counting': 'Système de score:', -'settings:counting|3x21': 'BWF (3x21)', -'settings:counting|2x21+11': '2x21, 3è set à 11', -'settings:counting|5x11_15': 'BWF 2016 Experiment Option 1 (5x11 jusqu\'à au plus 15)', -'settings:counting|5x11_15^90': 'Bundesliga 2017 (5x11 jusqu\'à au plus 15, 90s intervals)', -'settings:counting|5x11_15~NLA': 'NLA 2019- (5x11 jusqu\'à au plus 15, 120s intervals)', -'settings:counting|5x11/3': 'BWF 2016 Experiment Option 2 (5x11 aven l\'extension 3 points)', -'settings:counting|5x11_11': 'UAE (5x11 sans extension)', -'settings:counting|1x21': 'Un set (1x21)', -'settings:counting|1x11_15': 'Un set 2016 Experiment Option 1 (1x11 jusqu\'à au plus 15)', -'settings:counting|3x15_18': 'Raccourci (3x15 jusqu\'à au plus 18)', +'settings:scoring_format': 'Format de score:', +'settings:scoring_format|3x21': 'BWF (3x21)', +'settings:scoring_format|2x21+11': '2x21, 3è set à 11', +'settings:scoring_format|5x11_15': 'BWF 2016 Experiment Option 1 (5x11 jusqu\'à au plus 15)', +'settings:scoring_format|5x11_15^90': 'Bundesliga 2017 (5x11 jusqu\'à au plus 15, 90s intervals)', +'settings:scoring_format|5x11_15~NLA': 'NLA 2019- (5x11 jusqu\'à au plus 15, 120s intervals)', +'settings:scoring_format|5x11/3': 'BWF 2016 Experiment Option 2 (5x11 aven l\'extension 3 points)', +'settings:scoring_format|5x11_11': 'UAE (5x11 sans extension)', +'settings:scoring_format|1x21': 'Un set (1x21)', +'settings:scoring_format|1x11_15': 'Un set 2016 Experiment Option 1 (1x11 jusqu\'à au plus 15)', +'settings:scoring_format|3x15_18': 'Raccourci (3x15 jusqu\'à au plus 18)', 'settings:warmup': 'Warmup:', 'settings:warmup:bwf-2016': 'BWF 2016+ (120s, ready after 90s)', @@ -269,6 +271,7 @@ var i18n_frch = { 'settings:style:complete': 'Achevée', 'settings:style:clean': 'Nettoyer', 'settings:style:focus': 'Concentré', +'settings:style:hidden': 'Caché', 'settings:mode:label': 'Mode:', 'settings:mode:umpire': 'Arbitre', @@ -514,6 +517,8 @@ var i18n_frch = { 'displaymode|bwf': 'BWF', 'displaymode|clean': 'Clean', 'displaymode|teamcourt': 'Affichage de l\'équipe', +'displaymode|tournamentcourt': 'Tournoi individuel', +'displaymode|tournamentplayers': 'Tournoi individuel Joueurs seulement', 'displaymode|2court': '2 courts', 'displaymode|castall': 'Greenscreen (tous les terrains)', 'displaymode|andre': 'André', @@ -530,6 +535,7 @@ var i18n_frch = { 'displaymode|stripes': 'Bandes', 'displaymode|stream': 'Stream', 'displaymode|streamcourt': 'court stream', +'displaymode|streamcourt_dm': 'Court-Stream für DM 2025', 'displaymode|streamteam': 'stream team', 'displaymode:court_id': 'court:', 'displaymode:court_id:loading': 'chargement ...', @@ -539,6 +545,11 @@ var i18n_frch = { 'displaymode:colors': 'Couleurs:', 'displaymode:use team colors': 'Utiliser les couleurs de l\'équipe', 'displaymode:show_pause': 'Afficher le temps de repos', +'displaymode:show_court_number': 'Afficher le numéro de court', +'displaymode:show_competition': 'Afficher la concurrence', +'displaymode:show_round': 'Afficher le tour', +'displaymode:show_middle_name': 'Afficher le deuxième prénom des joueurs', +'displaymode:show_doubles_receiving': 'Souligner le joueur receveur en double', 'displaymode:hide settings': 'Cacher', 'liveaw:lost connection': 'Reconnecter ...', diff --git a/js/i18n_nlbe.js b/js/i18n_nlbe.js index 29ce2af6..ae3147e1 100644 --- a/js/i18n_nlbe.js +++ b/js/i18n_nlbe.js @@ -56,7 +56,7 @@ var i18n_nlbe = { 'wonby|2': 'Tweede game', 'wonby|3': 'Derde game', 'wonby|4': 'Vierde game', -'wonby.match': 'Wedstrijd gewonnen door {winner_name} {score_str}', +'wonby.match': 'Wedstrijd gewonnen door {winner_name} {score_str}\n\nHet resultaat bevestigen door te klikken.', 'wonby.walkover': '(Walkover in favor of {winner_name}.\n{loser_name} did not show up.) <---', 'wonby.and': ' en ', 'game(won)': 'Game', diff --git a/js/importexport.js b/js/importexport.js index 5fa096e5..c52ad8f4 100644 --- a/js/importexport.js +++ b/js/importexport.js @@ -136,14 +136,8 @@ function ui_init() { ui_import_json(state); }); - click.qs('.settings_send_export', function(e) { - e.preventDefault(); - var status = uiu.qs('.settings_footer_status'); - send_export(state); - uiu.text(status, state._('importexport:export sent')); - window.setTimeout(function() { - uiu.text(status, ''); - }, 10000); + click.qs('.delete_matches_link', function () { + match_storage.remove_all(0); }); } diff --git a/js/match_storage.js b/js/match_storage.js index 834c454f..7c410484 100644 --- a/js/match_storage.js +++ b/js/match_storage.js @@ -57,6 +57,23 @@ function remove(match_id) { window.localStorage.removeItem('bup_match_' + match_id); } +function remove_all(hours_ago) { + var matches = load(); + if (matches && matches.length > 0) { + const now = new Date(); + const hours_ago_ms = hours_ago * 60 * 60 * 1000; + matches.forEach(function (m) { + if (m.metadata && m.metadata.end && m.metadata.end != null) { + const end_time = new Date(m.metadata.end); + const match_diff_ms = now - end_time; + if (match_diff_ms > hours_ago_ms) { + window.localStorage.removeItem('bup_match_' + m.metadata.id); + } + } + }); + } +} + function ui_init() { var matches = load(); matches = matches.filter(function(m) { @@ -102,6 +119,7 @@ return { store: store, remove: remove, load_match: load_match, + remove_all: remove_all, }; })(); diff --git a/js/network.js b/js/network.js index 7f2e5d59..de23ec24 100644 --- a/js/network.js +++ b/js/network.js @@ -173,6 +173,12 @@ function enter_match(match) { netw.prepare_match(state.settings, match); } + if (state.initialized && state.metadata && (String(state.metadata.id) === String(match.setup.match_id))) { + settings.hide(true); + render.show(); + return; + } + settings.hide(true); control.start_match_dialog(state, match.setup); @@ -190,7 +196,7 @@ function enter_match(match) { var netscore = match.network_score; if (netscore) { - var mwinner = calc.match_winner(match.setup.counting, netscore); + var mwinner = calc.match_winner(match.setup, netscore); var on_cancel = function() { control.stop_match(state); @@ -267,7 +273,7 @@ function ui_render_matchlist(s, event) { uiu.el(btn, 'span', { 'class': 'setup_network_match_match_name', - }, match.setup.match_name); + }, match.setup.event_name + ' ' + match.setup.match_name); var _players_str = function(team) { if (match.setup.is_doubles) { @@ -294,16 +300,47 @@ function ui_render_matchlist(s, event) { 'class': 'setup_network_match_away_players', }, _players_str(match.setup.teams[1])); - var umpire_name = match.setup.umpire_name; + var umpire_name = match?.setup?.umpire?.name; if (umpire_name) { - if (match.setup.service_judge_name) { - umpire_name += ' + ' + match.setup.service_judge_name; - } - + uiu.el(btn, 'span', { + 'class': 'setup_network_umpire', + }, s._('settings:Umpire')+':'); uiu.el(btn, 'span', { 'class': 'setup_network_umpire_name', }, umpire_name); } + + var service_judge_name = match?.setup?.service_judge?.name; + if (service_judge_name) { + uiu.el(btn, 'span', { + 'class': 'setup_network_umpire', + }, s._('settings:Service judge')+':'); + uiu.el(btn, 'span', { + 'class': 'setup_network_umpire_name', + }, service_judge_name); + } + + + var _tabletoperator_str = function (tabletoperators) { + if (tabletoperators.length === 0) { + return 'N.N'; + } else if (tabletoperators.length == 1) { + return tabletoperators[0].name; + } else { + return tabletoperators[0].name + ' / ' + tabletoperators[1].name; + } + + }; + + if (match.setup.tabletoperators && match.setup.tabletoperators.length >= 0) { + uiu.el(btn, 'span', { + 'class': 'setup_network_tabletoperator', + }, s._('network:Tabletoperator')); + uiu.el(btn, 'span', { + 'class': 'setup_network_tabletoperator_name', + }, _tabletoperator_str(match.setup.tabletoperators)); + } + var score_text = _score_text(match.network_score); uiu.el(btn, 'span', { 'class': 'setup_network_match_score', @@ -351,57 +388,76 @@ function ui_list_matches(s, silent, no_timer) { return; } - update_event(s, event); + if(event){ + update_event(s, event); + } + eventsheet.render_links(s, uiu.qs('.setup_eventsheets')); urlexport.render_links(s, uiu.qs('.urlexport_links')); var editable = netw.editable(s); - var use_setupsheet = event.team_competition; + var use_setupsheet = event ? event.team_competition : false; uiu.visible_qs('.setupsheet_link', editable && use_setupsheet); uiu.visible_qs('.editevent_link', editable && !use_setupsheet); - ui_render_matchlist(s, event); + if(event){ + ui_render_matchlist(s, event); + } }, function(s) { return no_timer ? 'abort' : s.settings.network_update_interval; }); } +function reload_match_information() { + var netw = get_netw(); + if (netw && netw.push_service) { + netw.reload_match_information(); + } +} + // Returns a callback to be called when the updates are no longer required. // cb gets called with (err, s, event); s is NOT updated implicitly // calc_timeout is called with s and must return immediately the timeout or the string 'abort' function subscribe(s, cb, calc_timeout) { - var cancelled = false; - var timeout = null; - function query() { - if (cancelled) { - return; - } - var netw = get_netw(); - if (!netw) { - cb({ - msg: s._('network:error:unconfigured'), - }, s); - return; + var netw = get_netw(); + if (netw.push_service) { + netw.subscribe(s, cb, calc_timeout); + } else { + + var cancelled = false; + var timeout = null; + + function query() { + if (cancelled) { + return; + } + var netw = get_netw(); + if (!netw) { + cb({ + msg: s._('network:error:unconfigured'), + }, s); + return; + } + list_matches(s, function(err, event) { + cb(err, s, event); + }); + var new_timeout = calc_timeout(s); + if (new_timeout === 'abort') { + cancelled = true; + return; + } + timeout = setTimeout(query, new_timeout); } - list_matches(s, function(err, event) { - cb(err, s, event); - }); - var new_timeout = calc_timeout(s); - if (new_timeout === 'abort') { + query(); + + return function() { cancelled = true; - return; - } - timeout = setTimeout(query, new_timeout); + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + }; } - query(); - - return function() { - cancelled = true; - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - }; } @@ -509,9 +565,9 @@ function _court_by_id(all_courts, court_id) { } function _court_pick_dialog(s, all_courts, on_cancel) { - bupui.make_pick(s, s._('Select Court'), all_courts, function(c) { - _set_court(s, c); - }, on_cancel, uiu.qs('body'), 5); + //bupui.make_pick(s, s._('Select Court'), all_courts, function(c) { + // _set_court(s, c); + //}, on_cancel, uiu.qs('body'), 5); } function ui_init_court(s, hash_query) { @@ -667,11 +723,10 @@ function ui_init(s, hash_query) { } else if (hash_query.btsh_e !== undefined) { networks.btsh = btsh(null, hash_query.btsh_e); } else if (hash_query.mo !== undefined) { - networks.mo = staticnet({ - staticnet_message: 'none', - matches: [], - counting: '3x21', - }); + var mo_event = calc.setup_from_scoring_format(calc.scoring_format_from_counting('3x21')); + mo_event.staticnet_message = 'none'; + mo_event.matches = []; + networks.mo = staticnet(mo_event); } else if (hash_query.import_url) { networks.imported = staticnet(null, hash_query.import_url, function(s, url, cb) { urlimport.import_url(s, url, function(errmsg, event) { @@ -853,6 +908,7 @@ return { ui_uninstall_staticnet: ui_uninstall_staticnet, uninstall_refmode_push: uninstall_refmode_push, update_event: update_event, + reload_match_information: reload_match_information, }; @@ -889,4 +945,4 @@ if ((typeof module !== 'undefined') && (typeof require !== 'undefined')) { module.exports = network; } -/*/@DEV*/ \ No newline at end of file +/*/@DEV*/ diff --git a/js/order.js b/js/order.js index 31ee93fb..b2b8718e 100644 --- a/js/order.js +++ b/js/order.js @@ -665,6 +665,7 @@ function ui_render() { var setup = { is_doubles: (p1_players.length === 2), counting: '3x21', + scoring_format: calc.scoring_format_from_counting('3x21'), match_name: discipline.value, match_id: match_id, teams: [{ diff --git a/js/render.js b/js/render.js index c25f4831..2a62a3b9 100644 --- a/js/render.js +++ b/js/render.js @@ -38,19 +38,19 @@ function _score_display_init(s) { }); score_table.setAttribute('data-game-count', s.match.max_games); - var counting_tr = uiu.el(score_table, 'tr', { - 'class': 'score_counting_tr', + var scoring_format_tr = uiu.el(score_table, 'tr', { + 'class': 'score_scoring_format_tr', }); - var counting_td = uiu.el(counting_tr, 'td', { + var scoring_format_td = uiu.el(scoring_format_tr, 'td', { colspan: 2, - 'class': 'score_counting_td', + 'class': 'score_scoring_format_td', }); - var counting_container = uiu.el(counting_td, 'div', { - 'class': 'score_counting_container', + var scoring_format_container = uiu.el(scoring_format_td, 'div', { + 'class': 'score_scoring_format_container', }); - uiu.el(counting_container, 'div', { - 'class': 'score_counting', - }, s.setup.counting); + uiu.el(scoring_format_container, 'div', { + 'class': 'score_scoring_format', + }, (s.setup.scoring_format && s.setup.scoring_format.name) || s.setup.counting || ''); for (var game_index = 0;game_index < s.match.max_games;game_index++) { var tr = uiu.el(score_table, 'tr', { @@ -105,14 +105,14 @@ function _score_display_set_game(s, game, game_index, is_current) { var left_input = left.children('input'); left.attr('class', 'score score_left'); if (game) { - if (! game.started && !game.finished) { + if (!game.started && !game.finished) { left.addClass('score_empty'); } if (game.finished) { if (game.team1_won == s.game.team1_left) { left.addClass('score_won'); } - } else if ((game.team1_serving !== null) && (game.team1_serving == s.game.team1_left)) { + } else if ((game.team1_serving !== null) && (game.team1_serving == s.game.team1_left)) { left.addClass('score_serving'); } @@ -123,13 +123,23 @@ function _score_display_set_game(s, game, game_index, is_current) { if (editmode_active) { uiu.$visible(left_input, editmode_score_active); } + } else { + left.addClass('score_empty'); + var left_text = left.children('span'); + var left_points = 0; + _val(left_input, left_points); + left_text.text(left_points); + if (editmode_active) { + uiu.$visible(left_input, editmode_score_active); + } + } var right = $(tr.querySelector('.score_right')); var right_input = right.children('input'); right.attr('class', 'score score_right'); if (game) { - if (! game.started && !game.finished) { + if (!game.started && !game.finished) { right.addClass('score_empty'); } if (game.finished) { @@ -147,13 +157,22 @@ function _score_display_set_game(s, game, game_index, is_current) { if (editmode_active) { uiu.$visible(right_input, editmode_score_active); } + } else { + right.addClass('score_empty'); + var right_text = right.children('span'); + var right_points = 0; + _val(right_input, right_points); + right_text.text(right_points); + if (editmode_active) { + uiu.$visible(right_input, editmode_score_active); + } } if (is_current) { - var $counting_tr = $('.score_counting_tr'); - $counting_tr.insertBefore(tr); + var $scoring_format_tr = $('.score_scoring_format_tr'); + $scoring_format_tr.insertBefore(tr); var ann_tr = $('tr.score_announcements'); - ann_tr.insertBefore($counting_tr); + ann_tr.insertBefore($scoring_format_tr); var ann_td = ann_tr.children('td'); ann_td.empty(); @@ -211,9 +230,9 @@ function render_score_display(s) { } } - uiu.$visible_qs('.score_counting_container', ( + uiu.$visible_qs('.score_scoring_format_container', ( !s.ui.editmode_active && - s.setup && s.setup.counting && + s.setup && (s.setup.scoring_format || s.setup.counting) && s.match && (s.match.finished_games.length === 0) && s.game && (s.game.score[0] <= 0) && (s.game.score[1] <= 0) )); diff --git a/js/scoresheet.js b/js/scoresheet.js index fa2026c7..69e59f23 100644 --- a/js/scoresheet.js +++ b/js/scoresheet.js @@ -699,9 +699,12 @@ function sheet_render(s, svg) { _text('.scoresheet_scheduled_time_value', s.setup.scheduled_time_str); } + + console.log(s.match); + _text('.scoresheet_court_id', compat.courtnum(s.match.court_id ? s.match.court_id : s.setup.court_id)); - _text('.scoresheet_umpire_name', s.match.umpire_name ? s.match.umpire_name : s.setup.umpire_name); - _text('.scoresheet_service_judge_name', s.match.service_judge_name ? s.match.service_judge_name : s.setup.service_judge_name); + _text('.scoresheet_umpire_name', s.match.umpire_name ? s.match.umpire_name : (s.setup.umpire && s.setup.umpire.name ? s.setup.umpire.name : "")); + _text('.scoresheet_service_judge_name', s.match.service_judge_name ? s.match.service_judge_name : (s.setup.service_judge && s.setup.service_judge.name ? s.setup.service_judge.name : "")); _text('.scoresheet_begin_value', ((s.metadata.start && !s.match.walkover) ? utils.time_str(s.metadata.start) : '')); if (s.match.finished) { @@ -1032,7 +1035,7 @@ function sheet_name(setup) { return 'obl'; } - if (calc.max_game_count(setup.counting) === 5) { + if (calc.max_game_count(setup) === 5) { return 'international_5x11'; } return 'international'; diff --git a/js/settings.js b/js/settings.js index 782b8588..08ea1ced 100644 --- a/js/settings.js +++ b/js/settings.js @@ -23,6 +23,7 @@ var default_settings = { d_cbg4: '#404040', d_cfg2: '#aaaaaa', d_cfg3: '#cccccc', + d_cexp: '#ff0000', d_cborder: '#444444', d_ct: '#80ff00', d_ctim_blue: '#0070c0', @@ -32,7 +33,12 @@ var default_settings = { d_crecv: '#707676', d_scale: 100, d_team_colors: false, - d_show_pause: false, + d_show_pause: true, + d_show_court_number: true, + d_show_competition: true, + d_show_round: true, + d_show_middle_name: false, + d_show_doubles_receiving: false, settings_autohide: 30000, dads_interval: 20000, dads_wait: 60000, @@ -55,7 +61,7 @@ var default_settings = { refmode_referee_ws_url: 'wss://live.aufschlagwechsel.de/refmode_hub/', refmode_client_node_name: '', referee_service_judges: false, - settings_style: 'default', + style: 'default', }; function load() { @@ -186,15 +192,16 @@ function hide(force, skip_state) { function update_court(s) { var court_select = $('.settings [name="court_select"]'); court_select.val(s.settings.court_id); + network.reload_match_information(); } function update_refclient(s) { - var settings_style = get_settings_style(s); + var style = get_settings_style(s); var ref_ui_visible = ( (get_mode(s) !== 'referee') && s.settings.refmode_client_enabled - && settings_style === 'complete'); + && style === 'complete'); uiu.$visible_qs( '.settings_refmode_client_container', ref_ui_visible); refmode_client_ui.on_settings_change(s); @@ -207,6 +214,11 @@ var _settings_checkboxes = [ 'refmode_client_enabled', 'displaymode_reverse_order', 'd_show_pause', + 'd_show_court_number', + 'd_show_competition', + 'd_show_round', + 'd_show_middle_name', + 'd_show_doubles_receiving', 'd_team_colors', 'referee_service_judges', ]; @@ -258,14 +270,14 @@ var _settings_selects = [ 'language', 'wakelock', 'dads_mode', - 'settings_style', + 'style', ]; function update_court_settings(s) { var automatic = false; var manual = false; if (get_mode(s) === 'umpire') { - automatic = uiu.qs('.settings select[name="court_select"]').getAttribute('data-auto-available') === 'true'; + automatic = true; //uiu.qs('.settings select[name="court_select"]').getAttribute('data-auto-available') === 'true'; manual = ! automatic; } uiu.$visible_qs('.settings_court_manual', manual); @@ -291,6 +303,11 @@ function update(s) { _settings_selects.forEach(function(name) { var $select = $('.settings [name="' + name + '"]'); $select.val(s.settings[name]); + if(name === 'style' && s.settings[name] == 'hidden') { + $select[0].disabled = true; + } else { + $select[0].disabled = false; + } }); update_court(s); @@ -380,7 +397,7 @@ function on_change(s, name) { case 'fullscreen_ask': fullscreen.update_fullscreen_button(); break; - case 'settings_style': + case 'style': on_mode_change(s); break; } @@ -488,7 +505,7 @@ function get_mode(s) { } function get_settings_style(s) { - var res = s.settings.settings_style; + var res = s.settings.style; if (res === 'default') { var netw = network.get_netw(); res = (netw && netw.limited_ui) ? 'clean' : 'complete'; @@ -517,7 +534,7 @@ function on_mode_change(s) { } else { if (styles) { visible = false; - } else if ((settings_style === 'clean') || (settings_style === 'focus')) { + } else if ((settings_style === 'clean') || (settings_style === 'focus')|| (settings_style === 'hidden')) { visible = false; } // else: complete, everything visible } diff --git a/js/startmatch.js b/js/startmatch.js index a91d6e16..8ee930c6 100644 --- a/js/startmatch.js +++ b/js/startmatch.js @@ -29,7 +29,8 @@ function ui_init() { var team1, team2; var setup = { is_doubles: $('#setup_manual_form [name="gametype"]:checked').val() == 'doubles', - counting: _formval('counting'), + scoring_format: calc.scoring_format_from_counting(_formval('scoring_format')), + counting: _formval('scoring_format'), warmup: _formval('warmup'), }; @@ -48,6 +49,7 @@ function ui_init() { // Demo mode var demo_setup = { counting: setup.counting, + scoring_format: setup.scoring_format, warmup: setup.warmup, team_competition: setup.team_competition, }; diff --git a/js/timer.js b/js/timer.js index 90c289d2..0b9237c9 100644 --- a/js/timer.js +++ b/js/timer.js @@ -3,7 +3,7 @@ var timer = (function() { var ui_timer = null; function set() { - uiu.visible_qs('.timer_restart', !state.timer.upwards); + uiu.visible_qs('.timer_restart', !state.timer.upwards && state.timer.restart); if (ui_timer) { window.clearTimeout(ui_timer); diff --git a/js/urlexport.js b/js/urlexport.js index f64d8641..be100601 100644 --- a/js/urlexport.js +++ b/js/urlexport.js @@ -268,7 +268,7 @@ function init(s, page) { password: password, team_names: JSON.stringify(ev.team_names), matches_json: JSON.stringify(xmatches), - max_game_count: calc.max_game_count(ev.matches[0].setup.counting), + max_game_count: calc.max_game_count(ev.matches[0].setup), }), }, function(data_json) { var data = utils.parse_json(data_json); @@ -307,7 +307,7 @@ function init(s, page) { password: password, team_names: JSON.stringify(ev.team_names), matches_json: JSON.stringify(xmatches), - max_game_count: calc.max_game_count(ev.matches[0].setup.counting), + max_game_count: calc.max_game_count(ev.matches[0].setup), extra_fields_json: JSON.stringify(extra_fields), }), }, function(data_json, xhr) { diff --git a/js/utils.js b/js/utils.js index da8a91df..e9eb2e10 100644 --- a/js/utils.js +++ b/js/utils.js @@ -505,6 +505,9 @@ function cmp(a, b) { function cmp_key(key) { return function(x, y) { + if(!isNaN(Number(x[key])) && !isNaN(Number(y[key]))) { + return cmp(Number(x[key]), Number(y[key])); + } return cmp(x[key], y[key]); }; } diff --git a/test/mock/mock_btde.js b/test/mock/mock_btde.js index 3f7dbd04..7478b5e8 100644 --- a/test/mock/mock_btde.js +++ b/test/mock/mock_btde.js @@ -257,7 +257,8 @@ write_handler(req, res, pathname) { } const counting = ev.counting || bup.eventutils.default_counting(ev.league_key); - const max_game_count = bup.calc.max_game_count(counting); + const setup = {counting, scoring_format: ev.scoring_format || bup.calc.scoring_format_from_counting(counting)}; + const max_game_count = bup.calc.max_game_count(setup); if (!max_game_count) { return httpd_utils.send_err(res, new Error( diff --git a/test/order_2017_refrath2-wittorf.json b/test/order_2017_refrath2-wittorf.json index f508242e..a7214a39 100644 --- a/test/order_2017_refrath2-wittorf.json +++ b/test/order_2017_refrath2-wittorf.json @@ -26,8 +26,8 @@ }, { "firstname": "Lukas", - "lastname": "M\u00fchlhaus", - "name": "Lukas M\u00fchlhaus" + "lastname": "Mühlhaus", + "name": "Lukas Mühlhaus" } ] }, @@ -46,7 +46,24 @@ ] } ], - "match_id": "btde_2017-10-08_HD1_TV Refrath 2-Blau-Weiss Wittorf-NMS" + "match_id": "btde_2017-10-08_HD1_TV Refrath 2-Blau-Weiss Wittorf-NMS", + "scoring_format": { + "numSets": 5, + "set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": null, + "interval_duration_ms": null, + "break_before_set_duration_ms": 90000 + }, + "last_set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": 6, + "interval_duration_ms": 90000, + "break_before_set_duration_ms": 90000 + } + } } }, { @@ -65,8 +82,8 @@ }, { "firstname": "Runa", - "lastname": "Pl\u00fctzer", - "name": "Runa Pl\u00fctzer" + "lastname": "Plützer", + "name": "Runa Plützer" } ] }, @@ -79,13 +96,30 @@ }, { "firstname": "Petra", - "lastname": "Schl\u00fcter", - "name": "Petra Schl\u00fcter" + "lastname": "Schlüter", + "name": "Petra Schlüter" } ] } ], - "match_id": "btde_2017-10-08_DD_TV Refrath 2-Blau-Weiss Wittorf-NMS" + "match_id": "btde_2017-10-08_DD_TV Refrath 2-Blau-Weiss Wittorf-NMS", + "scoring_format": { + "numSets": 5, + "set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": null, + "interval_duration_ms": null, + "break_before_set_duration_ms": 90000 + }, + "last_set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": 6, + "interval_duration_ms": 90000, + "break_before_set_duration_ms": 90000 + } + } } }, { @@ -113,8 +147,8 @@ "players": [ { "firstname": "Sebastian", - "lastname": "Sch\u00f6ttler", - "name": "Sebastian Sch\u00f6ttler" + "lastname": "Schöttler", + "name": "Sebastian Schöttler" }, { "firstname": "Lucas", @@ -124,7 +158,24 @@ ] } ], - "match_id": "btde_2017-10-08_HD2_TV Refrath 2-Blau-Weiss Wittorf-NMS" + "match_id": "btde_2017-10-08_HD2_TV Refrath 2-Blau-Weiss Wittorf-NMS", + "scoring_format": { + "numSets": 5, + "set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": null, + "interval_duration_ms": null, + "break_before_set_duration_ms": 90000 + }, + "last_set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": 6, + "interval_duration_ms": 90000, + "break_before_set_duration_ms": 90000 + } + } } }, { @@ -147,13 +198,30 @@ "players": [ { "firstname": "Sebastian", - "lastname": "Sch\u00f6ttler", - "name": "Sebastian Sch\u00f6ttler" + "lastname": "Schöttler", + "name": "Sebastian Schöttler" } ] } ], - "match_id": "btde_2017-10-08_HE1_TV Refrath 2-Blau-Weiss Wittorf-NMS" + "match_id": "btde_2017-10-08_HE1_TV Refrath 2-Blau-Weiss Wittorf-NMS", + "scoring_format": { + "numSets": 5, + "set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": null, + "interval_duration_ms": null, + "break_before_set_duration_ms": 90000 + }, + "last_set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": 6, + "interval_duration_ms": 90000, + "break_before_set_duration_ms": 90000 + } + } } }, { @@ -176,13 +244,30 @@ "players": [ { "firstname": "Petra", - "lastname": "Schl\u00fcter", - "name": "Petra Schl\u00fcter" + "lastname": "Schlüter", + "name": "Petra Schlüter" } ] } ], - "match_id": "btde_2017-10-08_DE_TV Refrath 2-Blau-Weiss Wittorf-NMS" + "match_id": "btde_2017-10-08_DE_TV Refrath 2-Blau-Weiss Wittorf-NMS", + "scoring_format": { + "numSets": 5, + "set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": null, + "interval_duration_ms": null, + "break_before_set_duration_ms": 90000 + }, + "last_set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": 6, + "interval_duration_ms": 90000, + "break_before_set_duration_ms": 90000 + } + } } }, { @@ -201,8 +286,8 @@ }, { "firstname": "Runa", - "lastname": "Pl\u00fctzer", - "name": "Runa Pl\u00fctzer" + "lastname": "Plützer", + "name": "Runa Plützer" } ] }, @@ -221,7 +306,24 @@ ] } ], - "match_id": "btde_2017-10-08_GD_TV Refrath 2-Blau-Weiss Wittorf-NMS" + "match_id": "btde_2017-10-08_GD_TV Refrath 2-Blau-Weiss Wittorf-NMS", + "scoring_format": { + "numSets": 5, + "set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": null, + "interval_duration_ms": null, + "break_before_set_duration_ms": 90000 + }, + "last_set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": 6, + "interval_duration_ms": 90000, + "break_before_set_duration_ms": 90000 + } + } } }, { @@ -250,10 +352,26 @@ ] } ], - "match_id": "btde_2017-10-08_HE2_TV Refrath 2-Blau-Weiss Wittorf-NMS" + "match_id": "btde_2017-10-08_HE2_TV Refrath 2-Blau-Weiss Wittorf-NMS", + "scoring_format": { + "numSets": 5, + "set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": null, + "interval_duration_ms": null, + "break_before_set_duration_ms": 90000 + }, + "last_set_points": { + "end_points": 11, + "max_points": 15, + "interval_at": 6, + "interval_duration_ms": 90000, + "break_before_set_duration_ms": 90000 + } + } } } ] } } - diff --git a/test/test_2x21_11_counting.js b/test/test_2x21_11_counting.js index cc216878..640eb092 100644 --- a/test/test_2x21_11_counting.js +++ b/test/test_2x21_11_counting.js @@ -9,12 +9,13 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; var DOUBLES_SETUP = bup.utils.deep_copy(tutils.DOUBLES_SETUP); -DOUBLES_SETUP.counting = '2x21+11'; +set_counting(DOUBLES_SETUP, '2x21+11'); var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '2x21+11'; +set_counting(SINGLES_SETUP, '2x21+11'); _describe('2x21+11 counting', function() { diff --git a/test/test_3x15_18_counting.js b/test/test_3x15_18_counting.js index e4dc0144..3b646751 100644 --- a/test/test_3x15_18_counting.js +++ b/test/test_3x15_18_counting.js @@ -9,12 +9,13 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; var DOUBLES_SETUP = bup.utils.deep_copy(tutils.DOUBLES_SETUP); -DOUBLES_SETUP.counting = '3x15_18'; +set_counting(DOUBLES_SETUP, '3x15_18'); var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '3x15_18'; +set_counting(SINGLES_SETUP, '3x15_18'); _describe('Short Swiss Match (3x15_18)', function() { @@ -481,10 +482,10 @@ _describe('Short Swiss Match (3x15_18)', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_dech(s), 'Satz.\n\n' + - 'Spiel gewonnen von Alice 15-6 18-17'); + 'Spiel gewonnen von Alice 15-6 18-17\n\nBest�tigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_frch(s), 'Set.\n\n' + - 'Match gagné par Alice 15-6 18-17'); + 'Match gagné par Alice 15-6 18-17\n\nConfirmer le résultat en cliquant.'); presses.push({ type: 'score', @@ -654,10 +655,10 @@ _describe('Short Swiss Match (3x15_18)', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_dech(s), 'Satz.\n\n' + - 'Spiel gewonnen von Bob 6-15 18-17 15-13'); + 'Spiel gewonnen von Bob 6-15 18-17 15-13\n\nBest\uFFFDtigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_frch(s), 'Set.\n\n' + - 'Match gagné par Bob 6-15 18-17 15-13'); + 'Match gagné par Bob 6-15 18-17 15-13\n\nConfirmer le résultat en cliquant.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -745,10 +746,10 @@ _describe('Short Swiss Match (3x15_18)', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_dech(s), 'Satz.\n\n' + - 'Spiel gewonnen von Bob 6-15 18-17 18-17'); + 'Spiel gewonnen von Bob 6-15 18-17 18-17\n\nBest\uFFFDtigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_frch(s), 'Set.\n\n' + - 'Match gagné par Bob 6-15 18-17 18-17'); + 'Match gagné par Bob 6-15 18-17 18-17\n\nConfirmer le résultat en cliquant.'); press_score(presses, 0, 1); @@ -768,10 +769,10 @@ _describe('Short Swiss Match (3x15_18)', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_dech(s), 'Satz.\n\n' + - 'Spiel gewonnen von Alice 15-6 17-18 18-17'); + 'Spiel gewonnen von Alice 15-6 17-18 18-17\n\nBest\uFFFDtigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_frch(s), 'Set.\n\n' + - 'Match gagné par Alice 15-6 17-18 18-17'); + 'Match gagné par Alice 15-6 17-18 18-17\n\nConfirmer le résultat en cliquant.'); presses.push({ type: 'postmatch-confirm', @@ -792,10 +793,10 @@ _describe('Short Swiss Match (3x15_18)', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_dech(s), 'Satz.\n\n' + - 'Spiel gewonnen von Alice 15-6 17-18 18-17'); + 'Spiel gewonnen von Alice 15-6 17-18 18-17\n\nBest\uFFFDtigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_frch(s), 'Set.\n\n' + - 'Match gagné par Alice 15-6 17-18 18-17'); + 'Match gagné par Alice 15-6 17-18 18-17\n\nConfirmer le résultat en cliquant.'); }); _it('game_winner helper function', function() { diff --git a/test/test_511_15_buli2017_counting.js b/test/test_511_15_buli2017_counting.js index 8880450a..dce80795 100644 --- a/test/test_511_15_buli2017_counting.js +++ b/test/test_511_15_buli2017_counting.js @@ -9,12 +9,13 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; var DOUBLES_SETUP = bup.utils.deep_copy(tutils.DOUBLES_SETUP); -DOUBLES_SETUP.counting = '5x11_15^90'; +set_counting(DOUBLES_SETUP, '5x11_15^90'); var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '5x11_15^90'; +set_counting(SINGLES_SETUP, '5x11_15^90'); _describe('Bundesliga 2017 5x11_15 counting with 90s intervals', function() { @@ -559,10 +560,10 @@ _describe('Bundesliga 2017 5x11_15 counting with 90s intervals', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 15-14 11-5'); + 'Das Spiel wurde gewonnen von Alice 11-6 15-14 11-5\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 15-14 11-5'); + 'Match won by Alice 11-6 15-14 11-5\n\nConfirming the result by clicking.'); alt_presses.push({ type: 'postmatch-confirm', @@ -582,10 +583,10 @@ _describe('Bundesliga 2017 5x11_15 counting with 90s intervals', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 15-14 11-5'); + 'Das Spiel wurde gewonnen von Alice 11-6 15-14 11-5\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 15-14 11-5'); + 'Match won by Alice 11-6 15-14 11-5\n\nConfirming the result by clicking.'); press_score(presses, 0, 6); s = state_after(presses, SINGLES_SETUP); @@ -907,10 +908,10 @@ _describe('Bundesliga 2017 5x11_15 counting with 90s intervals', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 6-11 14-15 12-10 11-2 11-9'); + 'Das Spiel wurde gewonnen von Bob 6-11 14-15 12-10 11-2 11-9\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 6-11 14-15 12-10 11-2 11-9'); + 'Match won by Bob 6-11 14-15 12-10 11-2 11-9\n\nConfirming the result by clicking.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -1002,10 +1003,10 @@ _describe('Bundesliga 2017 5x11_15 counting with 90s intervals', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 6-11 14-15 12-10 11-2 15-14'); + 'Das Spiel wurde gewonnen von Bob 6-11 14-15 12-10 11-2 15-14\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 6-11 14-15 12-10 11-2 15-14'); + 'Match won by Bob 6-11 14-15 12-10 11-2 15-14\n\nConfirming the result by clicking.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -1024,10 +1025,10 @@ _describe('Bundesliga 2017 5x11_15 counting with 90s intervals', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 15-14 10-12 2-11 15-14'); + 'Das Spiel wurde gewonnen von Alice 11-6 15-14 10-12 2-11 15-14\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 15-14 10-12 2-11 15-14'); + 'Match won by Alice 11-6 15-14 10-12 2-11 15-14\n\nConfirming the result by clicking.'); presses.push({ type: 'postmatch-confirm', @@ -1048,10 +1049,10 @@ _describe('Bundesliga 2017 5x11_15 counting with 90s intervals', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 15-14 10-12 2-11 15-14'); + 'Das Spiel wurde gewonnen von Alice 11-6 15-14 10-12 2-11 15-14\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 15-14 10-12 2-11 15-14'); + 'Match won by Alice 11-6 15-14 10-12 2-11 15-14\n\nConfirming the result by clicking.'); }); _it('game_winner helper function', function() { diff --git a/test/test_511_15_counting.js b/test/test_511_15_counting.js index 6b4d684d..ea57d12e 100644 --- a/test/test_511_15_counting.js +++ b/test/test_511_15_counting.js @@ -9,12 +9,13 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; var DOUBLES_SETUP = bup.utils.deep_copy(tutils.DOUBLES_SETUP); -DOUBLES_SETUP.counting = '5x11_15'; +set_counting(DOUBLES_SETUP, '5x11_15'); var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '5x11_15'; +set_counting(SINGLES_SETUP, '5x11_15'); _describe('BWF experimental 5x11_15 counting', function() { @@ -555,10 +556,10 @@ _describe('BWF experimental 5x11_15 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 15-14 11-5'); + 'Das Spiel wurde gewonnen von Alice 11-6 15-14 11-5\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 15-14 11-5'); + 'Match won by Alice 11-6 15-14 11-5\n\nConfirming the result by clicking.'); alt_presses.push({ type: 'postmatch-confirm', @@ -578,10 +579,10 @@ _describe('BWF experimental 5x11_15 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 15-14 11-5'); + 'Das Spiel wurde gewonnen von Alice 11-6 15-14 11-5\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 15-14 11-5'); + 'Match won by Alice 11-6 15-14 11-5\n\nConfirming the result by clicking.'); press_score(presses, 0, 6); s = state_after(presses, SINGLES_SETUP); @@ -903,10 +904,10 @@ _describe('BWF experimental 5x11_15 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 6-11 14-15 12-10 11-2 11-9'); + 'Das Spiel wurde gewonnen von Bob 6-11 14-15 12-10 11-2 11-9\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 6-11 14-15 12-10 11-2 11-9'); + 'Match won by Bob 6-11 14-15 12-10 11-2 11-9\n\nConfirming the result by clicking.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -998,10 +999,10 @@ _describe('BWF experimental 5x11_15 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 6-11 14-15 12-10 11-2 15-14'); + 'Das Spiel wurde gewonnen von Bob 6-11 14-15 12-10 11-2 15-14\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 6-11 14-15 12-10 11-2 15-14'); + 'Match won by Bob 6-11 14-15 12-10 11-2 15-14\n\nConfirming the result by clicking.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -1020,10 +1021,10 @@ _describe('BWF experimental 5x11_15 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 15-14 10-12 2-11 15-14'); + 'Das Spiel wurde gewonnen von Alice 11-6 15-14 10-12 2-11 15-14\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 15-14 10-12 2-11 15-14'); + 'Match won by Alice 11-6 15-14 10-12 2-11 15-14\n\nConfirming the result by clicking.'); presses.push({ type: 'postmatch-confirm', @@ -1044,10 +1045,10 @@ _describe('BWF experimental 5x11_15 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 15-14 10-12 2-11 15-14'); + 'Das Spiel wurde gewonnen von Alice 11-6 15-14 10-12 2-11 15-14\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 15-14 10-12 2-11 15-14'); + 'Match won by Alice 11-6 15-14 10-12 2-11 15-14\n\nConfirming the result by clicking.'); }); _it('game_winner helper function', function() { diff --git a/test/test_511_15_nla_counting.js b/test/test_511_15_nla_counting.js index fd0a2552..7fce56ed 100644 --- a/test/test_511_15_nla_counting.js +++ b/test/test_511_15_nla_counting.js @@ -9,12 +9,13 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; var DOUBLES_SETUP = bup.utils.deep_copy(tutils.DOUBLES_SETUP); -DOUBLES_SETUP.counting = '5x11_15~NLA'; +set_counting(DOUBLES_SETUP, '5x11_15~NLA'); var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '5x11_15~NLA'; +set_counting(SINGLES_SETUP, '5x11_15~NLA'); _describe('NLA 2019 5x11_15 counting with 120s between games and 60s interval', function() { diff --git a/test/test_511_3_counting.js b/test/test_511_3_counting.js index 9dcb0f35..52ecc09b 100644 --- a/test/test_511_3_counting.js +++ b/test/test_511_3_counting.js @@ -9,11 +9,12 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; var DOUBLES_SETUP = bup.utils.deep_copy(tutils.DOUBLES_SETUP); -DOUBLES_SETUP.counting = '5x11/3'; +set_counting(DOUBLES_SETUP, '5x11/3'); var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '5x11/3'; +set_counting(SINGLES_SETUP, '5x11/3'); _describe('BWF experimental 5x11/3 counting', function() { @@ -429,10 +430,10 @@ _describe('BWF experimental 5x11/3 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 13-12 11-5'); + 'Das Spiel wurde gewonnen von Alice 11-6 13-12 11-5\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 13-12 11-5'); + 'Match won by Alice 11-6 13-12 11-5\n\nConfirming the result by clicking.'); alt_presses.push({ type: 'postmatch-confirm', @@ -452,10 +453,10 @@ _describe('BWF experimental 5x11/3 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 13-12 11-5'); + 'Das Spiel wurde gewonnen von Alice 11-6 13-12 11-5\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 13-12 11-5'); + 'Match won by Alice 11-6 13-12 11-5\n\nConfirming the result by clicking.'); press_score(presses, 0, 6); s = state_after(presses, SINGLES_SETUP); @@ -809,10 +810,10 @@ _describe('BWF experimental 5x11/3 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 6-11 12-13 13-10 11-2 11-9'); + 'Das Spiel wurde gewonnen von Bob 6-11 12-13 13-10 11-2 11-9\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 6-11 12-13 13-10 11-2 11-9'); + 'Match won by Bob 6-11 12-13 13-10 11-2 11-9\n\nConfirming the result by clicking.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -867,10 +868,10 @@ _describe('BWF experimental 5x11/3 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 6-11 12-13 13-10 11-2 13-12'); + 'Das Spiel wurde gewonnen von Bob 6-11 12-13 13-10 11-2 13-12\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 6-11 12-13 13-10 11-2 13-12'); + 'Match won by Bob 6-11 12-13 13-10 11-2 13-12\n\nConfirming the result by clicking.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -889,10 +890,10 @@ _describe('BWF experimental 5x11/3 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 13-12 10-13 2-11 13-10'); + 'Das Spiel wurde gewonnen von Alice 11-6 13-12 10-13 2-11 13-10\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 13-12 10-13 2-11 13-10'); + 'Match won by Alice 11-6 13-12 10-13 2-11 13-10\n\nConfirming the result by clicking.'); presses.push({ type: 'postmatch-confirm', @@ -913,10 +914,10 @@ _describe('BWF experimental 5x11/3 counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 13-12 10-13 2-11 13-10'); + 'Das Spiel wurde gewonnen von Alice 11-6 13-12 10-13 2-11 13-10\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 13-12 10-13 2-11 13-10'); + 'Match won by Alice 11-6 13-12 10-13 2-11 13-10\n\nConfirming the result by clicking.'); }); _it('game_winner helper function', function() { diff --git a/test/test_5x11_11_counting.js b/test/test_5x11_11_counting.js index 32237402..c55219e5 100644 --- a/test/test_5x11_11_counting.js +++ b/test/test_5x11_11_counting.js @@ -9,12 +9,13 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; var DOUBLES_SETUP = bup.utils.deep_copy(tutils.DOUBLES_SETUP); -DOUBLES_SETUP.counting = '5x11_11'; +set_counting(DOUBLES_SETUP, '5x11_11'); var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '5x11_11'; +set_counting(SINGLES_SETUP, '5x11_11'); _describe('UAE 5x11_11 sudden death scoring', function() { @@ -348,10 +349,10 @@ _describe('UAE 5x11_11 sudden death scoring', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 11-10 11-5'); + 'Das Spiel wurde gewonnen von Alice 11-6 11-10 11-5\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 11-10 11-5'); + 'Match won by Alice 11-6 11-10 11-5\n\nConfirming the result by clicking.'); alt_presses.push({ type: 'postmatch-confirm', @@ -371,10 +372,10 @@ _describe('UAE 5x11_11 sudden death scoring', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 11-10 11-5'); + 'Das Spiel wurde gewonnen von Alice 11-6 11-10 11-5\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 11-10 11-5'); + 'Match won by Alice 11-6 11-10 11-5\n\nConfirming the result by clicking.'); press_score(presses, 0, 5); s = state_after(presses, SINGLES_SETUP); @@ -696,10 +697,10 @@ _describe('UAE 5x11_11 sudden death scoring', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 6-11 10-11 11-10 11-2 11-9'); + 'Das Spiel wurde gewonnen von Bob 6-11 10-11 11-10 11-2 11-9\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 6-11 10-11 11-10 11-2 11-9'); + 'Match won by Bob 6-11 10-11 11-10 11-2 11-9\n\nConfirming the result by clicking.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -738,10 +739,10 @@ _describe('UAE 5x11_11 sudden death scoring', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 6-11 10-11 11-10 11-2 11-10'); + 'Das Spiel wurde gewonnen von Bob 6-11 10-11 11-10 11-2 11-10\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 6-11 10-11 11-10 11-2 11-10'); + 'Match won by Bob 6-11 10-11 11-10 11-2 11-10\n\nConfirming the result by clicking.'); press_score(presses, 0, 1); s = state_after(presses, SINGLES_SETUP); @@ -760,10 +761,10 @@ _describe('UAE 5x11_11 sudden death scoring', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 11-10 10-11 2-11 11-10'); + 'Das Spiel wurde gewonnen von Alice 11-6 11-10 10-11 2-11 11-10\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 11-10 10-11 2-11 11-10'); + 'Match won by Alice 11-6 11-10 10-11 2-11 11-10\n\nConfirming the result by clicking.'); presses.push({ type: 'postmatch-confirm', @@ -784,10 +785,10 @@ _describe('UAE 5x11_11 sudden death scoring', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-6 11-10 10-11 2-11 11-10'); + 'Das Spiel wurde gewonnen von Alice 11-6 11-10 10-11 2-11 11-10\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-6 11-10 10-11 2-11 11-10'); + 'Match won by Alice 11-6 11-10 10-11 2-11 11-10\n\nConfirming the result by clicking.'); }); _it('game_winner helper function', function() { diff --git a/test/test_btde.js b/test/test_btde.js index 09d81f29..59436d05 100644 --- a/test/test_btde.js +++ b/test/test_btde.js @@ -357,6 +357,13 @@ _describe('btde', function() { ], }; + expected.courts.forEach(function(court) { + court.court_id = '' + court.court_id; + }); + expected.matches.forEach(function(match) { + match.setup.scoring_format = bup.calc.scoring_format_from_counting(match.setup.counting); + }); + var date = new Date(2019, 9, 12); let s = {team_competition: true}; i18n.update_state(s, 'de'); diff --git a/test/test_courtspot.js b/test/test_courtspot.js index 87e09d94..42502df9 100644 --- a/test/test_courtspot.js +++ b/test/test_courtspot.js @@ -5,6 +5,7 @@ var assert = require('assert'); var tutils = require('./tutils'); var press_score = tutils.press_score; var bup = tutils.bup; +var set_counting = tutils.set_counting; var state_after = tutils.state_after; var _describe = tutils._describe; var _it = tutils._it; @@ -14,11 +15,11 @@ var settings = { language: 'de', }; var doubles_setup = bup.utils.deep_copy(tutils.DOUBLES_SETUP); -doubles_setup.counting = '5x11_15'; +set_counting(doubles_setup, '5x11_15'); doubles_setup.match_id = 'courtspot_testmatch'; doubles_setup.match_name = 'GD'; var singles_setup = bup.utils.deep_copy(tutils.SINGLES_SETUP); -singles_setup.counting = '5x11_15'; +set_counting(singles_setup, '5x11_15'); singles_setup.match_id = 'courtspot_testmatch_singles'; singles_setup.match_name = 'DE'; diff --git a/test/test_eventutils.js b/test/test_eventutils.js index a7354d81..a2ef8f8f 100644 --- a/test/test_eventutils.js +++ b/test/test_eventutils.js @@ -648,6 +648,14 @@ _describe('eventutils', function() { assert.deepStrictEqual(bup.eventutils.default_counting('bayern-2018'), '3x21'); }); + + _it('default_scoring_format', function() { + assert.deepStrictEqual(bup.eventutils.default_scoring_format('1BL-2016'), bup.calc.scoring_format_from_counting('5x11_15')); + assert.deepStrictEqual(bup.eventutils.default_scoring_format('1BL-2017'), bup.calc.scoring_format_from_counting('5x11_15^90')); + assert.deepStrictEqual(bup.eventutils.default_scoring_format('NLA-2019'), bup.calc.scoring_format_from_counting('5x11_15~NLA')); + assert.deepStrictEqual(bup.eventutils.default_scoring_format('OLM-2020'), bup.calc.scoring_format_from_counting('3x21')); + }); + _it('get_min_pause', function() { assert.deepStrictEqual(bup.eventutils.get_min_pause('NLA-2017'), 900000); assert.deepStrictEqual(bup.eventutils.get_min_pause('NLA-2019'), 900000); @@ -656,7 +664,7 @@ _describe('eventutils', function() { assert.deepStrictEqual(bup.eventutils.get_min_pause('RLSO-2019'), 20 * 60 * 1000); }); - _it('annotate counting', function() { + _it('annotate scoring_format', function() { var s = {}; var ev = { league_key: '1BL-2017', @@ -668,6 +676,7 @@ _describe('eventutils', function() { }; bup.eventutils.annotate(s, ev); assert.deepStrictEqual(ev.matches[0].setup.counting, '5x11_15^90'); + assert.deepStrictEqual(ev.matches[0].setup.scoring_format, bup.calc.scoring_format_from_counting('5x11_15^90')); // Match details should not be overwritten ev = { @@ -681,8 +690,9 @@ _describe('eventutils', function() { }; bup.eventutils.annotate(s, ev); assert.deepStrictEqual(ev.matches[0].setup.counting, '1x21'); + assert.deepStrictEqual(ev.matches[0].setup.scoring_format, bup.calc.scoring_format_from_counting('1x21')); - // counting works as well + // event-level scoring data works as well ev = { counting: '5x11_11', matches: [{ @@ -693,8 +703,9 @@ _describe('eventutils', function() { }; bup.eventutils.annotate(s, ev); assert.deepStrictEqual(ev.matches[0].setup.counting, '5x11_11'); + assert.deepStrictEqual(ev.matches[0].setup.scoring_format, bup.calc.scoring_format_from_counting('5x11_11')); - // counting supercedes league_key + // event-level scoring data supercedes league defaults ev = { counting: '5x11_11', league_key: '1BL-2017', @@ -706,8 +717,9 @@ _describe('eventutils', function() { }; bup.eventutils.annotate(s, ev); assert.deepStrictEqual(ev.matches[0].setup.counting, '5x11_11'); + assert.deepStrictEqual(ev.matches[0].setup.scoring_format, bup.calc.scoring_format_from_counting('5x11_11')); - // match counting supercedes event counting + // match-level scoring data supercedes event-level scoring data ev = { counting: '5x11_11', league_key: '1BL-2017', @@ -720,6 +732,7 @@ _describe('eventutils', function() { }; bup.eventutils.annotate(s, ev); assert.deepStrictEqual(ev.matches[0].setup.counting, '3x21'); + assert.deepStrictEqual(ev.matches[0].setup.scoring_format, bup.calc.scoring_format_from_counting('3x21')); }); _it('pronounce_teamname', function() { diff --git a/test/test_goldengame.js b/test/test_goldengame.js index 4ddcbdc5..a77e0a04 100644 --- a/test/test_goldengame.js +++ b/test/test_goldengame.js @@ -7,12 +7,13 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; (function() { 'use strict'; var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '1x21'; +set_counting(SINGLES_SETUP, '1x21'); _describe('Golden game (1x21) counting', function() { @@ -137,10 +138,10 @@ _describe('Golden game (1x21) counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 21-9'); + 'Das Spiel wurde gewonnen von Alice 21-9\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 21-9'); + 'Match won by Alice 21-9\n\nConfirming the result by clicking.'); press_score(presses, 12, 0); s = state_after(presses, SINGLES_SETUP); diff --git a/test/test_goldengame_11.js b/test/test_goldengame_11.js index 64cf2615..edd4f1aa 100644 --- a/test/test_goldengame_11.js +++ b/test/test_goldengame_11.js @@ -7,12 +7,13 @@ var _it = tutils._it; var press_score = tutils.press_score; var state_after = tutils.state_after; var bup = tutils.bup; +var set_counting = tutils.set_counting; (function() { 'use strict'; var SINGLES_SETUP = bup.utils.deep_copy(tutils.SINGLES_SETUP); -SINGLES_SETUP.counting = '1x11_15'; +set_counting(SINGLES_SETUP, '1x11_15'); _describe('Golden game (1x11_15) counting', function() { @@ -137,10 +138,10 @@ _describe('Golden game (1x11_15) counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-4'); + 'Das Spiel wurde gewonnen von Alice 11-4\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-4'); + 'Match won by Alice 11-4\n\nConfirming the result by clicking.'); press_score(presses, 6, 0); s = state_after(presses, SINGLES_SETUP); @@ -219,10 +220,10 @@ _describe('Golden game (1x11_15) counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 13-11'); + 'Das Spiel wurde gewonnen von Alice 13-11\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 13-11'); + 'Match won by Alice 13-11\n\nConfirming the result by clicking.'); press_score(presses, 2, 0); s = state_after(presses, SINGLES_SETUP); @@ -275,10 +276,10 @@ _describe('Golden game (1x11_15) counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 15-13'); + 'Das Spiel wurde gewonnen von Alice 15-13\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 15-13'); + 'Match won by Alice 15-13\n\nConfirming the result by clicking.'); press_score(presses, 1, 0); s = state_after(presses, SINGLES_SETUP); @@ -316,10 +317,10 @@ _describe('Golden game (1x11_15) counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 15-14'); + 'Das Spiel wurde gewonnen von Alice 15-14\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 15-14'); + 'Match won by Alice 15-14\n\nConfirming the result by clicking.'); press_score(presses, 1, 0); s = state_after(presses, SINGLES_SETUP); @@ -337,10 +338,10 @@ _describe('Golden game (1x11_15) counting', function() { assert.deepStrictEqual(s.timer, false); assert.strictEqual(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 15-14'); + 'Das Spiel wurde gewonnen von Bob 15-14\n\nBestätigen des Ergebnisses durch Klick.'); assert.strictEqual(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 15-14'); + 'Match won by Bob 15-14\n\nConfirming the result by clicking.'); presses.push({ type: 'postmatch-confirm', diff --git a/test/test_pronunciation.js b/test/test_pronunciation.js index 05ddfe82..8cc11306 100644 --- a/test/test_pronunciation.js +++ b/test/test_pronunciation.js @@ -17,6 +17,7 @@ var SINGLES_TEAM_SETUP_AWAY_FIRST = tutils.SINGLES_TEAM_SETUP_AWAY_FIRST; var state_after = tutils.state_after; var press_score = tutils.press_score; var bup = tutils.bup; +var set_counting = tutils.set_counting; function pronounce(lang_name, s, now) { bup.i18n.update_state(s, lang_name); @@ -1317,10 +1318,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, SINGLES_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 23-21 30-29'); + 'Das Spiel wurde gewonnen von Bob 23-21 30-29\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 23-21 30-29'); + 'Match won by Bob 23-21 30-29\n\nConfirming the result by clicking.'); presses.push({ type: 'score', @@ -1496,34 +1497,34 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_TEAM_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von B team 23-21 29-30 22-20'); + 'Das Spiel wurde gewonnen von B team 23-21 29-30 22-20\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by B team 23-21 29-30 22-20'); + 'Match won by B team 23-21 29-30 22-20\n\nConfirming the result by clicking.'); assert.equal(pronounce_frch(s), 'Set.\n\n' + - 'Match gagné par B team 23-21 29-30 22-20'); + 'Match gagné par B team 23-21 29-30 22-20\n\nConfirmer le résultat en cliquant.'); s = state_after(alt_presses, SINGLES_TEAM_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von B team 23-21 29-30 22-20'); + 'Das Spiel wurde gewonnen von B team 23-21 29-30 22-20\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by B team 23-21 29-30 22-20'); + 'Match won by B team 23-21 29-30 22-20\n\nConfirming the result by clicking.'); s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 23-21 29-30 22-20'); + 'Das Spiel wurde gewonnen von Bob und Birgit 23-21 29-30 22-20\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob and Birgit 23-21 29-30 22-20'); + 'Match won by Bob and Birgit 23-21 29-30 22-20\n\nConfirming the result by clicking.'); s = state_after(alt_presses, SINGLES_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Bob 23-21 29-30 22-20'); + 'Das Spiel wurde gewonnen von Bob 23-21 29-30 22-20\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by Bob 23-21 29-30 22-20'); + 'Match won by Bob 23-21 29-30 22-20\n\nConfirming the result by clicking.'); presses.push({ type: 'score', @@ -1532,19 +1533,19 @@ _describe('pronunciation', function() { s = state_after(presses, SINGLES_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 21-23 30-29 21-19'); + 'Das Spiel wurde gewonnen von Alice 21-23 30-29 21-19\n\nBestätigen des Ergebnisses durch Klick.'); s = state_after(presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 21-23 30-29 21-19'); + 'Das Spiel wurde gewonnen von Andrew und Alice 21-23 30-29 21-19\n\nBestätigen des Ergebnisses durch Klick.'); s = state_after(presses, SINGLES_TEAM_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von A team 21-23 30-29 21-19'); + 'Das Spiel wurde gewonnen von A team 21-23 30-29 21-19\n\nBestätigen des Ergebnisses durch Klick.'); s = state_after(presses, DOUBLES_TEAM_SETUP); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von A team 21-23 30-29 21-19'); + 'Das Spiel wurde gewonnen von A team 21-23 30-29 21-19\n\nBestätigen des Ergebnisses durch Klick.'); }); _it('cards basics', function() { @@ -1682,24 +1683,24 @@ _describe('pronunciation', function() { s = state_after(presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Bob, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 4-4'); + 'Das Spiel wurde gewonnen von Andrew und Alice 4-4\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Bob, disqualified for misconduct.\n\n' + - 'Match won by Andrew and Alice 4-4'); + 'Match won by Andrew and Alice 4-4\n\nConfirming the result by clicking.'); assert.equal(pronounce_frch(s), 'Bob, disqualifié pour mauvais comportement.\n\n' + - 'Match gagné par Andrew et Alice 4-4'); + 'Match gagné par Andrew et Alice 4-4\n\nConfirmer le résultat en cliquant.'); assert.equal(pronounce_dech(s), 'Bob, disqualifiziert wegen schlechten Benehmens.\n\n' + - 'Spiel gewonnen von Andrew und Alice 4-4'); + 'Spiel gewonnen von Andrew und Alice 4-4\n\nBest\uFFFDtigen des Ergebnisses durch Klick.'); s = state_after(presses, DOUBLES_TEAM_SETUP); assert.equal(pronounce_de(s), 'Bob, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von A team 4-4'); + 'Das Spiel wurde gewonnen von A team 4-4\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Bob, disqualified for misconduct.\n\n' + - 'Match won by A team 4-4'); + 'Match won by A team 4-4\n\nConfirming the result by clicking.'); }); _it('cards at beginning of match', function() { @@ -2063,11 +2064,11 @@ _describe('pronunciation', function() { assert.deepEqual(s.game.score, [21, 12]); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 21-19 19-21 21-12' + 'Das Spiel wurde gewonnen von Andrew und Alice 21-19 19-21 21-12\n\nBestätigen des Ergebnisses durch Klick.' ); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by Andrew and Alice 21-19 19-21 21-12' + 'Match won by Andrew and Alice 21-19 19-21 21-12\n\nConfirming the result by clicking.' ); presses.push({ @@ -2081,13 +2082,13 @@ _describe('pronunciation', function() { 'Game.\n' + 'Bob, fault for misconduct.\n' + '\n' + - 'Match won by Andrew and Alice 21-19 19-21 21-12' + 'Match won by Andrew and Alice 21-19 19-21 21-12\n\nConfirming the result by clicking.' ); assert.equal(pronounce_de(s), 'Satz.\n' + 'Bob, Fehler wegen unsportlichen Verhaltens.\n' + '\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 21-19 19-21 21-12' + 'Das Spiel wurde gewonnen von Andrew und Alice 21-19 19-21 21-12\n\nBestätigen des Ergebnisses durch Klick.' ); presses.push({ @@ -2101,13 +2102,13 @@ _describe('pronunciation', function() { 'Game.\n' + 'Bob, fault for misconduct.\n' + 'Alice, fault for misconduct.\n\n' + - 'Match won by Andrew and Alice 21-19 19-21 21-12' + 'Match won by Andrew and Alice 21-19 19-21 21-12\n\nConfirming the result by clicking.' ); assert.equal(pronounce_de(s), 'Satz.\n' + 'Bob, Fehler wegen unsportlichen Verhaltens.\n' + 'Alice, Fehler wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 21-19 19-21 21-12' + 'Das Spiel wurde gewonnen von Andrew und Alice 21-19 19-21 21-12\n\nBestätigen des Ergebnisses durch Klick.' ); }); @@ -2220,10 +2221,10 @@ _describe('pronunciation', function() { var s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Bob hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 0-0'); + 'Das Spiel wurde gewonnen von Andrew und Alice 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Bob retired.\n\n' + - 'Match won by Andrew and Alice 0-0'); + 'Match won by Andrew and Alice 0-0\n\nConfirming the result by clicking.'); alt_presses = presses.slice(); press_score(alt_presses, 3, 2); @@ -2235,10 +2236,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_TEAM_SETUP); assert.equal(pronounce_de(s), 'Alice hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von B team 2-3'); + 'Das Spiel wurde gewonnen von B team 2-3\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Alice retired.\n\n' + - 'Match won by B team 2-3'); + 'Match won by B team 2-3\n\nConfirming the result by clicking.'); press_score(presses, 21, 19); presses.push({ @@ -2267,10 +2268,10 @@ _describe('pronunciation', function() { s = state_after(presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Andrew hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 19-21 2-2'); + 'Das Spiel wurde gewonnen von Bob und Birgit 19-21 2-2\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Andrew retired.\n\n' + - 'Match won by Bob and Birgit 19-21 2-2'); + 'Match won by Bob and Birgit 19-21 2-2\n\nConfirming the result by clicking.'); }); _it('retired at game start', function() { @@ -2284,10 +2285,10 @@ _describe('pronunciation', function() { var s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Bob hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 0-0'); + 'Das Spiel wurde gewonnen von Andrew und Alice 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Bob retired.\n\n' + - 'Match won by Andrew and Alice 0-0'); + 'Match won by Andrew and Alice 0-0\n\nConfirming the result by clicking.'); presses.push({ type: 'pick_side', // Andrew&Alice pick left @@ -2302,10 +2303,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Andrew hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 0-0'); + 'Das Spiel wurde gewonnen von Bob und Birgit 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Andrew retired.\n\n' + - 'Match won by Bob and Birgit 0-0'); + 'Match won by Bob and Birgit 0-0\n\nConfirming the result by clicking.'); presses.push({ type: 'pick_server', // Birgit serves @@ -2321,10 +2322,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Birgit hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 0-0'); + 'Das Spiel wurde gewonnen von Andrew und Alice 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Birgit retired.\n\n' + - 'Match won by Andrew and Alice 0-0'); + 'Match won by Andrew and Alice 0-0\n\nConfirming the result by clicking.'); presses.push({ type: 'pick_receiver', // Andrew receives @@ -2340,10 +2341,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Alice hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 0-0'); + 'Das Spiel wurde gewonnen von Bob und Birgit 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Alice retired.\n\n' + - 'Match won by Bob and Birgit 0-0'); + 'Match won by Bob and Birgit 0-0\n\nConfirming the result by clicking.'); presses.push({ type: 'love-all', @@ -2357,10 +2358,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Andrew hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 0-0'); + 'Das Spiel wurde gewonnen von Bob und Birgit 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Andrew retired.\n\n' + - 'Match won by Bob and Birgit 0-0'); + 'Match won by Bob and Birgit 0-0\n\nConfirming the result by clicking.'); press_score(presses, 21, 19); alt_presses = presses.slice(); @@ -2372,10 +2373,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Andrew hat aufgegeben.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 19-21'); + 'Das Spiel wurde gewonnen von Bob und Birgit 19-21\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Andrew retired.\n\n' + - 'Match won by Bob and Birgit 19-21'); + 'Match won by Bob and Birgit 19-21\n\nConfirming the result by clicking.'); }); _it('disqualified at game start', function() { @@ -2389,10 +2390,10 @@ _describe('pronunciation', function() { var s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Bob, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 0-0'); + 'Das Spiel wurde gewonnen von Andrew und Alice 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Bob, disqualified for misconduct.\n\n' + - 'Match won by Andrew and Alice 0-0'); + 'Match won by Andrew and Alice 0-0\n\nConfirming the result by clicking.'); presses.push({ type: 'pick_side', // Andrew&Alice pick left @@ -2407,10 +2408,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Andrew, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 0-0'); + 'Das Spiel wurde gewonnen von Bob und Birgit 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Andrew, disqualified for misconduct.\n\n' + - 'Match won by Bob and Birgit 0-0'); + 'Match won by Bob and Birgit 0-0\n\nConfirming the result by clicking.'); presses.push({ type: 'pick_server', // Birgit serves @@ -2426,10 +2427,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Birgit, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 0-0'); + 'Das Spiel wurde gewonnen von Andrew und Alice 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Birgit, disqualified for misconduct.\n\n' + - 'Match won by Andrew and Alice 0-0'); + 'Match won by Andrew and Alice 0-0\n\nConfirming the result by clicking.'); presses.push({ type: 'pick_receiver', // Andrew receives @@ -2445,10 +2446,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Alice, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 0-0'); + 'Das Spiel wurde gewonnen von Bob und Birgit 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Alice, disqualified for misconduct.\n\n' + - 'Match won by Bob and Birgit 0-0'); + 'Match won by Bob and Birgit 0-0\n\nConfirming the result by clicking.'); presses.push({ type: 'love-all', @@ -2462,10 +2463,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Andrew, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 0-0'); + 'Das Spiel wurde gewonnen von Bob und Birgit 0-0\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Andrew, disqualified for misconduct.\n\n' + - 'Match won by Bob and Birgit 0-0'); + 'Match won by Bob and Birgit 0-0\n\nConfirming the result by clicking.'); press_score(presses, 21, 19); alt_presses = presses.slice(); @@ -2477,10 +2478,10 @@ _describe('pronunciation', function() { s = state_after(alt_presses, DOUBLES_SETUP); assert.equal(pronounce_de(s), 'Andrew, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 19-21'); + 'Das Spiel wurde gewonnen von Bob und Birgit 19-21\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Andrew, disqualified for misconduct.\n\n' + - 'Match won by Bob and Birgit 19-21'); + 'Match won by Bob and Birgit 19-21\n\nConfirming the result by clicking.'); }); _it('red card at interval (RTTO 3.7.5)', function() { @@ -2910,11 +2911,11 @@ _describe('pronunciation', function() { assert.equal(pronounce_de(s), 'Bob, Fehler wegen unsportlichen Verhaltens.\n' + 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 21-23 30-29 21-16'); + 'Das Spiel wurde gewonnen von Alice 21-23 30-29 21-16\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Bob, fault for misconduct.\n' + 'Game.\n\n' + - 'Match won by Alice 21-23 30-29 21-16'); + 'Match won by Alice 21-23 30-29 21-16\n\nConfirming the result by clicking.'); assert.ok(! s.timer); var yellow_card = { @@ -2933,12 +2934,12 @@ _describe('pronunciation', function() { 'Bob, Fehler wegen unsportlichen Verhaltens.\n' + 'Satz.\n' + 'Alice, Verwarnung wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Alice 21-23 30-29 21-16'); + 'Das Spiel wurde gewonnen von Alice 21-23 30-29 21-16\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Bob, fault for misconduct.\n' + 'Game.\n' + 'Alice, warning for misconduct.\n\n' + - 'Match won by Alice 21-23 30-29 21-16'); + 'Match won by Alice 21-23 30-29 21-16\n\nConfirming the result by clicking.'); assert.ok(! s.timer); presses.push(red_card2); @@ -2955,14 +2956,14 @@ _describe('pronunciation', function() { 'Alice, Verwarnung wegen unsportlichen Verhaltens.\n' + 'Alice, Fehler wegen unsportlichen Verhaltens.\n' + '\n' + - 'Das Spiel wurde gewonnen von Alice 21-23 30-29 21-16'); + 'Das Spiel wurde gewonnen von Alice 21-23 30-29 21-16\n\nBestätigen des Ergebnisses durch Klick.'); assert.equal(pronounce_en(s), 'Bob, fault for misconduct.\n' + 'Game.\n' + 'Alice, warning for misconduct.\n' + 'Alice, fault for misconduct.\n' + '\n' + - 'Match won by Alice 21-23 30-29 21-16'); + 'Match won by Alice 21-23 30-29 21-16\n\nConfirming the result by clicking.'); assert.ok(! s.timer); presses.push({ @@ -3214,11 +3215,11 @@ _describe('pronunciation', function() { _it('5x11 end-of game pronunciation', function() { var SINGLES_SETUP_5x11 = bup.utils.deep_copy(SINGLES_SETUP); - SINGLES_SETUP_5x11.counting = '5x11_15'; + set_counting(SINGLES_SETUP_5x11, '5x11_15'); var SINGLES_TEAM_SETUP_5x11 = bup.utils.deep_copy(SINGLES_TEAM_SETUP); - SINGLES_TEAM_SETUP_5x11.counting = '5x11_15'; + set_counting(SINGLES_TEAM_SETUP_5x11, '5x11_15'); var DOUBLES_TEAM_SETUP_5x11 = bup.utils.deep_copy(DOUBLES_TEAM_SETUP); - DOUBLES_TEAM_SETUP_5x11.counting = '5x11_15'; + set_counting(DOUBLES_TEAM_SETUP_5x11, '5x11_15'); var presses = [{ type: 'pick_side', @@ -3527,38 +3528,38 @@ _describe('pronunciation', function() { s = state_after(presses, SINGLES_SETUP_5x11); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Alice 11-1 11-3 4-11 5-11 11-6' + 'Das Spiel wurde gewonnen von Alice 11-1 11-3 4-11 5-11 11-6\n\nBestätigen des Ergebnisses durch Klick.' ); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by Alice 11-1 11-3 4-11 5-11 11-6' + 'Match won by Alice 11-1 11-3 4-11 5-11 11-6\n\nConfirming the result by clicking.' ); s = state_after(presses, DOUBLES_SETUP_5x11); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von Andrew und Alice 11-1 11-3 4-11 5-11 11-6' + 'Das Spiel wurde gewonnen von Andrew und Alice 11-1 11-3 4-11 5-11 11-6\n\nBestätigen des Ergebnisses durch Klick.' ); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by Andrew and Alice 11-1 11-3 4-11 5-11 11-6' + 'Match won by Andrew and Alice 11-1 11-3 4-11 5-11 11-6\n\nConfirming the result by clicking.' ); s = state_after(presses, SINGLES_TEAM_SETUP_5x11); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von A team 11-1 11-3 4-11 5-11 11-6' + 'Das Spiel wurde gewonnen von A team 11-1 11-3 4-11 5-11 11-6\n\nBestätigen des Ergebnisses durch Klick.' ); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by A team 11-1 11-3 4-11 5-11 11-6' + 'Match won by A team 11-1 11-3 4-11 5-11 11-6\n\nConfirming the result by clicking.' ); s = state_after(presses, DOUBLES_TEAM_SETUP_5x11); assert.equal(pronounce_de(s), 'Satz.\n\n' + - 'Das Spiel wurde gewonnen von A team 11-1 11-3 4-11 5-11 11-6' + 'Das Spiel wurde gewonnen von A team 11-1 11-3 4-11 5-11 11-6\n\nBestätigen des Ergebnisses durch Klick.' ); assert.equal(pronounce_en(s), 'Game.\n\n' + - 'Match won by A team 11-1 11-3 4-11 5-11 11-6' + 'Match won by A team 11-1 11-3 4-11 5-11 11-6\n\nConfirming the result by clicking.' ); }); @@ -3987,11 +3988,11 @@ _describe('pronunciation', function() { s = state_after(presses, DOUBLES_SETUP); assert.equal(pronounce_de(s, 1040000), 'Andrew, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 11-6' + 'Das Spiel wurde gewonnen von Bob und Birgit 11-6\n\nBestätigen des Ergebnisses durch Klick.' ); assert.equal(pronounce_en(s, 1040000), 'Andrew, disqualified for misconduct.\n\n' + - 'Match won by Bob and Birgit 11-6' + 'Match won by Bob and Birgit 11-6\n\nConfirming the result by clicking.' ); presses = presses_sav.slice(); @@ -4294,11 +4295,11 @@ _describe('pronunciation', function() { s = state_after(presses, DOUBLES_SETUP); assert.equal(pronounce_de(s, 1040000), 'Andrew, disqualifiziert wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 21-6' + 'Das Spiel wurde gewonnen von Bob und Birgit 21-6\n\nBestätigen des Ergebnisses durch Klick.' ); assert.equal(pronounce_en(s, 1040000), 'Andrew, disqualified for misconduct.\n\n' + - 'Match won by Bob and Birgit 21-6' + 'Match won by Bob and Birgit 21-6\n\nConfirming the result by clicking.' ); presses.push({ @@ -4311,12 +4312,12 @@ _describe('pronunciation', function() { assert.equal(pronounce_de(s, 1040000), 'Andrew, disqualifiziert wegen unsportlichen Verhaltens.\n' + 'Birgit, Fehler wegen unsportlichen Verhaltens.\n\n' + - 'Das Spiel wurde gewonnen von Bob und Birgit 21-6' + 'Das Spiel wurde gewonnen von Bob und Birgit 21-6\n\nBestätigen des Ergebnisses durch Klick.' ); assert.equal(pronounce_en(s, 1040000), 'Andrew, disqualified for misconduct.\n' + 'Birgit, fault for misconduct.\n\n' + - 'Match won by Bob and Birgit 21-6' + 'Match won by Bob and Birgit 21-6\n\nConfirming the result by clicking.' ); diff --git a/test/tutils.js b/test/tutils.js index 9c1f10e8..b381683c 100644 --- a/test/tutils.js +++ b/test/tutils.js @@ -36,6 +36,7 @@ const SINGLES_SETUP = { }], is_doubles: false, counting: '3x21', + scoring_format: bup.calc.scoring_format_from_counting('3x21'), }; var SINGLES_TEAM_SETUP = bup.utils.deep_copy(SINGLES_SETUP); SINGLES_TEAM_SETUP.teams[0].name = 'A team'; @@ -43,8 +44,14 @@ SINGLES_TEAM_SETUP.teams[1].name = 'B team'; SINGLES_TEAM_SETUP.team_competition = true; var SINGLES_TEAM_SETUP_AWAY_FIRST = bup.utils.deep_copy(SINGLES_TEAM_SETUP); SINGLES_TEAM_SETUP_AWAY_FIRST.away_first = true; + +function set_counting(setup, counting) { + setup.counting = counting; + setup.scoring_format = bup.calc.scoring_format_from_counting(counting); + return setup; +} var SINGLES_SETUP_5x11 = bup.utils.deep_copy(SINGLES_SETUP); -SINGLES_SETUP_5x11.counting = '5x11_15'; +set_counting(SINGLES_SETUP_5x11, '5x11_15'); var DOUBLES_SETUP = { teams: [{ @@ -54,6 +61,7 @@ var DOUBLES_SETUP = { }], is_doubles: true, counting: '3x21', + scoring_format: bup.calc.scoring_format_from_counting('3x21'), }; var DOUBLES_TEAM_SETUP = bup.utils.deep_copy(DOUBLES_SETUP); DOUBLES_TEAM_SETUP.teams[0].name = 'A team'; @@ -62,7 +70,7 @@ DOUBLES_TEAM_SETUP.team_competition = true; var DOUBLES_TEAM_SETUP_AWAY_FIRST = bup.utils.deep_copy(DOUBLES_TEAM_SETUP); DOUBLES_TEAM_SETUP_AWAY_FIRST.away_first = true; var DOUBLES_SETUP_5x11 = bup.utils.deep_copy(DOUBLES_SETUP); -DOUBLES_SETUP_5x11.counting = '5x11_15'; +set_counting(DOUBLES_SETUP_5x11, '5x11_15'); var DOUBLES_SETUP_EN = bup.utils.deep_copy(DOUBLES_SETUP); @@ -232,4 +240,5 @@ module.exports = { state_after, state_at, find_object, + set_counting, };