From 9a3ad40db863bddfb66213ee5f83fc4a71a44284 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Sat, 17 Feb 2024 01:00:14 +0100 Subject: [PATCH 01/38] Add new display mode for individual tounaments (optimized for regional tournaments with small dispalys) --- bup.html | 5 + css/displaymode.css | 28 +++- doc/URLs.txt | 146 ++++++++++--------- js/calc.js | 49 +++++++ js/displaymode.js | 340 +++++++++++++++++++++++++++++++++++++++++--- js/i18n_de.js | 6 + js/i18n_en.js | 6 + js/i18n_frch.js | 6 + js/settings.js | 13 +- js/timer.js | 2 +- 10 files changed, 512 insertions(+), 89 deletions(-) diff --git a/bup.html b/bup.html index a07c86fa..3f64d1ac 100644 --- a/bup.html +++ b/bup.html @@ -349,6 +349,11 @@

+
+
+
+
+
diff --git a/css/displaymode.css b/css/displaymode.css index 1cdaaa02..c3a8cedb 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,14 @@ } .d_international_team, +.d_tournament, .d_clean_team { font-stretch: condensed; position: relative; height: 50%; } .d_international_player_container, +.d_tournament_player_container .d_clean_player_container, .d_bwfonlyplayers_player_container { position: relative; @@ -153,6 +156,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 +169,7 @@ align-items: center; } .d_international_score, +.d_tournament_score, .d_clean_score { font-size: 50vh; line-height: 50vh; @@ -172,6 +182,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 +202,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 +278,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 { diff --git a/doc/URLs.txt b/doc/URLs.txt index 04490229..d714bd86 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,55 @@ 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. + 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. +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/js/calc.js b/js/calc.js index db6b1be9..96d4482a 100644 --- a/js/calc.js +++ b/js/calc.js @@ -70,11 +70,38 @@ 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 +109,7 @@ function warmup_timer(s, cointoss_ts) { start: cointoss_ts, duration: 120000, exigent: 5499, + restart: true, }; } } @@ -318,6 +346,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; @@ -447,6 +493,7 @@ function recalc_after_score(s, team_id, press) { start: press.timestamp, duration: (counting === '5x11_15^90' ? 90000 : 60000), exigent: 25000, + restart: true, }; } if ((press.type != 'red-card') || is_interval) { @@ -481,6 +528,7 @@ function recalc_after_score(s, team_id, press) { start: press.timestamp, duration: rest_duration, exigent: 25000, + restart: true, }; } else if (!s.game.interval && !s.match.suspended && !s.match.injuries) { if (press.type !== 'red-card') { @@ -810,6 +858,7 @@ function calc_press(s, press) { start: press.timestamp, duration: s.timer.duration, exigent: s.timer.exigent, + restart: s.timer.restart, }; } break; diff --git a/js/displaymode.js b/js/displaymode.js index b8b424a4..b4099cf4 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -7,6 +7,7 @@ var ALL_STYLES = [ 'bwf', 'clean', 'teamcourt', + 'tournamentcourt', 'stripes', '2court', 'greyish', @@ -30,6 +31,7 @@ var ALL_COLORS = [ 'c0', 'c1', 'cb0', 'cb1', 'cbg', 'cbg2', 'cbg3', 'cbg4', 'cfg', 'cfg2', 'cfg3', 'cfg3', 'cfgdark', + 'cexp', 'ct', // transparent 'cborder', 'cserv', 'cserv2', 'crecv', @@ -65,7 +67,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; @@ -196,6 +201,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), @@ -246,6 +256,50 @@ function determine_server(match, current_score) { }; } +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.counting, 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 _match_by_court(event, court) { return court.match_id ? utils.find(event.matches, function(m) { return court.match_id === m.setup.match_id; @@ -1888,6 +1942,160 @@ function render_teamscore(s, container, event, colors) { }); } +var timer_alternative_text = []; + +function render_tournamentcourt(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.counting, 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.counting, 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_teamcourt(s, container, event, court, match, colors) { var nscore = extract_netscore(match); var gscore = _gamescore_from_netscore(nscore, match.setup); @@ -1912,12 +2120,16 @@ 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]; @@ -1998,6 +2210,7 @@ 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; @@ -2539,27 +2752,88 @@ 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; + console.log(parrent_width); + var child_width = 0; + timer_alternative_text.forEach(function(item) { + let [el, origFontSize] = item; + el.style.fontSize = origFontSize; + console.log(el.offsetWidthX); + 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(); } @@ -2664,17 +2938,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 +3010,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')); @@ -2796,6 +3077,7 @@ function update(err, s, event) { onlyscore: render_onlyscore, stripes: render_stripes, teamcourt: render_teamcourt, + tournamentcourt: render_tournamentcourt, }[style]; if (xfunc) { var court = _render_court(s, container, event); @@ -2986,6 +3268,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')); } @@ -3074,6 +3371,7 @@ function option_applies(style_id, option_name) { streamcourt: ['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'], teamscore: ['team_colors', 'c0', 'c1', 'cfg', 'cbg'], tim: ['cbg', 'cfg', 'ctim_blue', 'ctim_active'], tournament_overview: ['cfg', 'cbg', 'cbg3', 'cborder', 'cfg2'], diff --git a/js/i18n_de.js b/js/i18n_de.js index aac6f36e..ff9235aa 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -520,6 +520,7 @@ var i18n_de = { 'displaymode|bwf': 'BWF', 'displaymode|clean': 'Clean', 'displaymode|teamcourt': 'Mannschaftskampf', +'displaymode|tournamentcourt': 'Individual-Turnier', 'displaymode|2court': '2 Felder', 'displaymode|andre': 'André', 'displaymode|tim': 'Tim', @@ -545,6 +546,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 ...', diff --git a/js/i18n_en.js b/js/i18n_en.js index abebf186..f90e35f9 100644 --- a/js/i18n_en.js +++ b/js/i18n_en.js @@ -519,6 +519,7 @@ var i18n_en = { 'displaymode|bwf': 'BWF', 'displaymode|clean': 'clean', 'displaymode|teamcourt': 'team display', +'displaymode|tournamentcourt': 'individual tournament', 'displaymode|2court': '2 courts', 'displaymode|castall': 'greenscreen (all courts)', 'displaymode|andre': 'André', @@ -544,6 +545,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 ...', diff --git a/js/i18n_frch.js b/js/i18n_frch.js index 38383241..79271c2d 100644 --- a/js/i18n_frch.js +++ b/js/i18n_frch.js @@ -514,6 +514,7 @@ var i18n_frch = { 'displaymode|bwf': 'BWF', 'displaymode|clean': 'Clean', 'displaymode|teamcourt': 'Affichage de l\'équipe', +'displaymode|tournamentcourt': 'Tournoi individuel', 'displaymode|2court': '2 courts', 'displaymode|castall': 'Greenscreen (tous les terrains)', 'displaymode|andre': 'André', @@ -539,6 +540,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/settings.js b/js/settings.js index 782b8588..510e2e22 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, @@ -207,6 +213,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', ]; 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); From f33b958a3778a0332faf62a25c5d185d40e7e60f Mon Sep 17 00:00:00 2001 From: "t.englich" Date: Fri, 29 Mar 2024 09:22:57 +0100 Subject: [PATCH 02/38] Communication betreen BUP and BTS now WS based. That means that there is no further need to pull the score from BTS. BTS is now able to push the scores exact to those clients which requires this information. This reduce the amount of traffic and the load on client an service enormuously. --- .gitignore | 1 + js/btsh.js | 414 +++++++++++++++++++++++++++------------------- js/displaymode.js | 4 +- js/i18n_de.js | 2 +- js/network.js | 73 ++++---- 5 files changed, 296 insertions(+), 198 deletions(-) diff --git a/.gitignore b/.gitignore index e14fc0f6..a545a9e9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ mail.* /vendor/ +/.vs diff --git a/js/btsh.js b/js/btsh.js index bfdc60c7..2a760e73 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -2,203 +2,285 @@ // 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; -function _bat_status() { - if (!battery) { - return undefined; - } - return { - charging: battery.charging, - level: battery.level, - chargingTime: battery.chargingTime, - dischargingTime: battery.dischargingTime, - }; -} + var battery; + -function _device_data() { - return { - id: refmode_client_ui.get_node_id(), - battery: _bat_status(), - court: state.settings.court_id, - }; -} + if (!battery && (typeof navigator != 'undefined') && navigator.getBattery) { + navigator.getBattery().then(function(bat) { + battery = bat; + }); + } -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; } + var req_match_id = s.setup.match_id; + var match_id = req_match_id.substring('bts_'.length); - network.errstate('btsh.score', err); - }); -} + 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), + }; -function sync(s) { - send_score(s); -} + var url = baseurl + 'h/' + encodeURIComponent(tournament_key) + '/m/' + encodeURIComponent(match_id) + '/score'; -/* s, press */ -function send_press(s) { - sync(s); -} + _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 + return; + } -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; - } - } else { - court_id = s.settings.court_id; + network.errstate('btsh.score', err); + }); } - 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 sync(s) { + send_score(s); + } - var ev = answer.event; - eventutils.annotate(s, ev); + /* s, press */ + function send_press(s) { + sync(s); + } - return cb(null, ev); - }); -} + 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); + } -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); + 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; + } + return res; + }); + courts.push({ + id: 'referee', + description: s._('court:referee'), + }); + 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]; + } + } - 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 service_name() { + return 'BTSh'; + } + + function editable(/*s*/) { + return false; + } + + function courts(s) { + return s.btsh_courts; + } + + function connect(cb, s) { + try { + if (ws == null) { + ws = new WebSocket(construct_url(WS_PATH), 'bts-bup'); + ws.sendmsg = ws_sendmsg; + ws.onopen = function () { + reload_match_information(); + }; + ws.onmessage = handle_message; + ws.onclose = function () { + ws = null; + send_bts_not_reachable(cb, s); + setTimeout(connect, reconnect_timeout, cb, s); + }; } - return res; - }); - courts.push({ - id: 'referee', - description: s._('court:referee'), - }); - s.btsh_courts = courts; - return callback(err, courts); - }); -} + } catch (e) { + ws = null; + send_bts_not_reachable(cb, s); + setTimeout(connect, reconnect_timeout, cb, s); + } + } + 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 + ); + } -function ui_init() { - if (!baseurl) { - baseurl = '../'; + function ws_sendmsg(msg) { + const msg_json = JSON.stringify(msg); + ws.send(msg_json); } - var m = window.location.pathname.match(/^(.*\/)bup\/(?:bup\.html|index\.html)?$/); - if (m) { - baseurl = m[1]; + + 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; + 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); + } + } + break; + default: + break; + } + } -function editable(/*s*/) { - return false; -} + 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 = '' + } -function courts(s) { - return s.btsh_courts; -} + } else { + state.settings.court_id = state.settings.displaymode_court_id; + } + ws.sendmsg({ type: 'init', tournament_key: tournament_key, panel_settings: state.settings }); + } + + function subscribe(s, cb, calc_timeout) { + bts_update_callback = cb; + connect(cb,s); + } -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(cb,s) { + var msg = s._('network:error:bts'); + cb({ + type: 'network-error', + msg: msg, + }, s, 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*/ diff --git a/js/displaymode.js b/js/displaymode.js index b4099cf4..daffff23 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -3045,7 +3045,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)); } @@ -3176,7 +3176,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); @@ -3189,6 +3188,7 @@ function on_style_change(s) { input.value = col; } }); + network.reload_match_information(); } var _cancel_updates = null; diff --git a/js/i18n_de.js b/js/i18n_de.js index ff9235aa..89bd9fdb 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -49,7 +49,7 @@ 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', diff --git a/js/network.js b/js/network.js index 7f2e5d59..af0f5c09 100644 --- a/js/network.js +++ b/js/network.js @@ -365,43 +365,57 @@ function ui_list_matches(s, silent, no_timer) { }); } +function reload_match_information() { + var netw = get_netw(); + if (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; - } - }; } @@ -853,6 +867,7 @@ return { ui_uninstall_staticnet: ui_uninstall_staticnet, uninstall_refmode_push: uninstall_refmode_push, update_event: update_event, + reload_match_information: reload_match_information, }; From f3fa1468559b9c62a9fac15d37b8265100181708 Mon Sep 17 00:00:00 2001 From: "t.englich" Date: Fri, 29 Mar 2024 13:42:56 +0100 Subject: [PATCH 03/38] No it is possible to serve an centralised setting for each client from bts. If is a setting stored in displaysettings and a link between client and displaysetting ist stored in display_court_displaysettings on statup of the client it will be fetched and applied to the client. --- js/btsh.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/js/btsh.js b/js/btsh.js index 2a760e73..48d80ef0 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -6,7 +6,7 @@ function btsh(baseurl, tournament_key) { var WS_PATH = '/ws/bup'; var reconnect_timeout = 1000; var bts_update_callback = null; - + var display_initialized = false; var battery; @@ -235,6 +235,9 @@ function btsh(baseurl, tournament_key) { } } break; + case 'settings-update': + state.settings = c.val; + break; default: break; } @@ -252,7 +255,8 @@ function btsh(baseurl, tournament_key) { } else { state.settings.court_id = state.settings.displaymode_court_id; } - ws.sendmsg({ type: 'init', tournament_key: tournament_key, panel_settings: state.settings }); + 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) { From 0e887a236de760b22e356bab5b0006bf88bb95a6 Mon Sep 17 00:00:00 2001 From: "t.englich" Date: Fri, 29 Mar 2024 17:37:27 +0100 Subject: [PATCH 04/38] Now it is possible to persist customized settings per client an reset this settings in bts. --- bup.html | 17 +++++++++-------- js/btsh.js | 18 ++++++++++++++++++ js/i18n_de.js | 3 ++- js/i18n_en.js | 3 ++- js/i18n_frch.js | 3 ++- js/importexport.js | 10 ---------- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/bup.html b/bup.html index 3f64d1ac..872c1455 100644 --- a/bup.html +++ b/bup.html @@ -380,17 +380,18 @@

- - - + + +
diff --git a/js/btsh.js b/js/btsh.js index 48d80ef0..cb7ee77b 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -153,6 +153,23 @@ function btsh(baseurl, tournament_key) { if (m) { baseurl = m[1]; } + + click.qs('.settings_send_export', function (e) { + e.preventDefault(); + persist_display_settings(); + }); + click.qs('.settings_reset_export', function (e) { + e.preventDefault(); + reset_display_settings(); + }); + } + + function persist_display_settings() { + ws.sendmsg({ type: 'persist_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); + } + + function reset_display_settings() { + ws.sendmsg({ type: 'reset_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); } function service_name() { @@ -294,6 +311,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/i18n_de.js b/js/i18n_de.js index 89bd9fdb..f6c99029 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', diff --git a/js/i18n_en.js b/js/i18n_en.js index f90e35f9..ef579b51 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', diff --git a/js/i18n_frch.js b/js/i18n_frch.js index 79271c2d..eb53808b 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', diff --git a/js/importexport.js b/js/importexport.js index 5fa096e5..fc92e0eb 100644 --- a/js/importexport.js +++ b/js/importexport.js @@ -135,16 +135,6 @@ function ui_init() { click.qs('.import_link', function() { 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); - }); } return { From 4cf4f68530ffe915ec40f73e80c02b00334854bb Mon Sep 17 00:00:00 2001 From: "t.englich" Date: Wed, 3 Apr 2024 23:26:09 +0200 Subject: [PATCH 05/38] Bugfix: Old scores of previouse matches were not be nulled --- js/render.js | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/js/render.js b/js/render.js index c25f4831..4f7c9bed 100644 --- a/js/render.js +++ b/js/render.js @@ -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,6 +157,15 @@ 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) { From 8f4fbb2cc4afcf890e6796c2ffde018484fe51a1 Mon Sep 17 00:00:00 2001 From: "t.englich" Date: Wed, 3 Apr 2024 23:26:45 +0200 Subject: [PATCH 06/38] Bugfix: Coourt Changed does not have any effect in umpire Panel --- js/settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/settings.js b/js/settings.js index 510e2e22..75d79a58 100644 --- a/js/settings.js +++ b/js/settings.js @@ -192,6 +192,7 @@ 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) { From 1ca57acdf0a818f4577850c0cc6f4142e4daa9ea Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Thu, 4 Apr 2024 03:38:29 +0200 Subject: [PATCH 07/38] fix errors while starting the soreboard --- js/btsh.js | 26 +++++++++++++++++++++++--- js/network.js | 2 +- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/js/btsh.js b/js/btsh.js index cb7ee77b..769eb7be 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -215,9 +215,29 @@ function btsh(baseurl, tournament_key) { ); } - function ws_sendmsg(msg) { - const msg_json = JSON.stringify(msg); - ws.send(msg_json); + async function ws_sendmsg(msg) { + + waitForSocketConnection(ws, () => { + const msg_json = JSON.stringify(msg); + ws.send(msg_json); + }); + + } + + // Make the function wait until the connection is made... + function waitForSocketConnection(socket, callback){ + setTimeout( + function () { + if (socket.readyState === 1) { + if (callback != null){ + callback(); + } + } else { + console.log("wait for connection...") + waitForSocketConnection(socket, callback); + } + + }, 5); // wait 5 milisecond for the connection... } function handle_message(ws_msg) { diff --git a/js/network.js b/js/network.js index af0f5c09..085c38e4 100644 --- a/js/network.js +++ b/js/network.js @@ -367,7 +367,7 @@ function ui_list_matches(s, silent, no_timer) { function reload_match_information() { var netw = get_netw(); - if (netw.push_service) { + if (netw && netw.push_service) { netw.reload_match_information(); } } From 94a7f36105bea78ee589c56725e37fba6a937a17 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Thu, 4 Apr 2024 03:39:14 +0200 Subject: [PATCH 08/38] remove log messages --- js/displaymode.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/displaymode.js b/js/displaymode.js index daffff23..ac9dbbdb 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -2767,12 +2767,10 @@ function show_match_meta(timer_state, parent, default_color, exigent_color, matc var auto_size_alternative_strings = function(parrent_el) { var parrent_width = parrent_el.offsetWidth; - console.log(parrent_width); var child_width = 0; timer_alternative_text.forEach(function(item) { let [el, origFontSize] = item; el.style.fontSize = origFontSize; - console.log(el.offsetWidthX); child_width += el.offsetWidth; }); From 6f7b9e77b33606eb75882d2eb3e1cbc8ec4d4d32 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Thu, 4 Apr 2024 03:39:58 +0200 Subject: [PATCH 09/38] fix the backgroundcolor if no match is on court (use the setting from bts now) --- css/displaymode.css | 2 +- js/displaymode.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/css/displaymode.css b/css/displaymode.css index c3a8cedb..39ee6092 100644 --- a/css/displaymode.css +++ b/css/displaymode.css @@ -497,7 +497,7 @@ bottom: 0; display: flex; flex-direction: column; - justify-content: center; + justify-content: space-evenly; align-items: center; } diff --git a/js/displaymode.js b/js/displaymode.js index ac9dbbdb..e583a302 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -3098,6 +3098,7 @@ function update(err, s, event) { ), }); + /* // background for colors for (var team_id = 0;team_id < 2;team_id++) { uiu.el(nomatch_el, 'div', { @@ -3107,6 +3108,7 @@ function update(err, s, event) { ), }); } + */ var _render_team_name = function(team_id) { uiu.el(nomatch_el, 'div', { @@ -3124,9 +3126,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;', alt: (event.tournament_name || ''), }); + } else { var tname = event.tournament_name; if (tname) { @@ -3139,7 +3142,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) { From ff33eb7dc95196739ae8c84b78cb91e88bb1b3b8 Mon Sep 17 00:00:00 2001 From: "t.englich" Date: Sun, 28 Apr 2024 09:52:58 +0200 Subject: [PATCH 10/38] Enhancement: Now the names of the tabletoperators will be shown in matchoverview of court ans also in coutzview. --- css/network.css | 5 +++++ js/court.js | 17 +++++++++++++++++ js/i18n_de.js | 1 + js/i18n_en.js | 1 + js/i18n_frch.js | 1 + js/network.js | 21 +++++++++++++++++++++ 6 files changed, 46 insertions(+) diff --git a/css/network.css b/css/network.css index 38bdd68d..1d90e52e 100644 --- a/css/network.css +++ b/css/network.css @@ -124,6 +124,11 @@ button > .loading-icon { color: #444; } +.setup_network_tabletoperator { + color: #c14949; + font-weight: bold; +} + .setup_network_heading::after { /* Set line-height to height, so that we can vertically center with vertical-align: middle; */ content: ''; 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/i18n_de.js b/js/i18n_de.js index f6c99029..368d8db2 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -55,6 +55,7 @@ var i18n_de = { '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', diff --git a/js/i18n_en.js b/js/i18n_en.js index ef579b51..1e569de7 100644 --- a/js/i18n_en.js +++ b/js/i18n_en.js @@ -55,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', diff --git a/js/i18n_frch.js b/js/i18n_frch.js index eb53808b..f7ee2744 100644 --- a/js/i18n_frch.js +++ b/js/i18n_frch.js @@ -53,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é', diff --git a/js/network.js b/js/network.js index 085c38e4..c5005ced 100644 --- a/js/network.js +++ b/js/network.js @@ -304,6 +304,27 @@ function ui_render_matchlist(s, event) { 'class': 'setup_network_umpire_name', }, umpire_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', + }, _tabletoperator_str(match.setup.tabletoperators)); + } + var score_text = _score_text(match.network_score); uiu.el(btn, 'span', { 'class': 'setup_network_match_score', From 9d791b58286b6a4d19d94ae8e7d55a6c1c2fe305 Mon Sep 17 00:00:00 2001 From: "t.englich" Date: Sun, 28 Apr 2024 14:12:04 +0200 Subject: [PATCH 11/38] Enhancement: InputElements for manual input of score was to small if the game was already won --- css/score.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/css/score.css b/css/score.css index c8f95248..dabbc0b4 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; From 69a72c6bc3708be43bc4526b92f0f52ba1c8fe0f Mon Sep 17 00:00:00 2001 From: tengmel Date: Sun, 8 Sep 2024 14:25:53 +0200 Subject: [PATCH 12/38] #53: BUP: Integrate a possibilty to remove all stored Matches from local Cache --- bup.html | 1 + js/i18n_de.js | 1 + js/importexport.js | 4 ++++ js/match_storage.js | 11 +++++++++++ 4 files changed, 17 insertions(+) diff --git a/bup.html b/bup.html index 872c1455..4af1eb55 100644 --- a/bup.html +++ b/bup.html @@ -236,6 +236,7 @@

+ diff --git a/js/i18n_de.js b/js/i18n_de.js index 368d8db2..c25f2734 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -197,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', diff --git a/js/importexport.js b/js/importexport.js index fc92e0eb..7b287b72 100644 --- a/js/importexport.js +++ b/js/importexport.js @@ -135,6 +135,10 @@ function ui_init() { click.qs('.import_link', function() { ui_import_json(state); }); + + click.qs('.delete_matches_link', function () { + match_storage.remove_all("ALL"); + }); } return { diff --git a/js/match_storage.js b/js/match_storage.js index 834c454f..8ac2d088 100644 --- a/js/match_storage.js +++ b/js/match_storage.js @@ -55,6 +55,16 @@ function load_match(match_id) { function remove(match_id) { window.localStorage.removeItem('bup_match_' + match_id); + } + +function remove_all(match_id) { + var matches = load(); + matches.forEach(function (m) { + const m_id = m.metadata.id; + if (match_id != m_id) { + window.localStorage.removeItem('bup_match_' + m_id); + } + }); } function ui_init() { @@ -102,6 +112,7 @@ return { store: store, remove: remove, load_match: load_match, + remove_all: remove_all, }; })(); From 8a1e6de684387b9e5dbb01cdc571e11e7e845c1a Mon Sep 17 00:00:00 2001 From: tengmel Date: Mon, 7 Oct 2024 22:06:31 +0200 Subject: [PATCH 13/38] #64: Server.Core: Call Matchen in preparation after call a new match on court #65: Server.Core: Automatic call of a match which is in preparation when a match is finished --- js/btsh.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/btsh.js b/js/btsh.js index 769eb7be..345f35aa 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -84,6 +84,7 @@ function btsh(baseurl, tournament_key) { 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, From 5de6f8f3f85fb15e9177f82705db51712cda286b Mon Sep 17 00:00:00 2001 From: tengmel Date: Mon, 14 Oct 2024 20:18:09 +0200 Subject: [PATCH 14/38] #51 Admin: Edit tournament: Display battery charge levels for the tablets --- js/btsh.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/js/btsh.js b/js/btsh.js index 345f35aa..d1ba9b98 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -165,14 +165,19 @@ function btsh(baseurl, tournament_key) { }); } - function persist_display_settings() { + async function persist_display_settings() { ws.sendmsg({ type: 'persist_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); } - function reset_display_settings() { + async function reset_display_settings() { ws.sendmsg({ type: 'reset_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); } + async function send_device_info() { + ws.sendmsg({ type: 'device_info', tournament_key: tournament_key, device: _device_data() }); + setTimeout(send_device_info, 1000*60*5); + } + function service_name() { return 'BTSh'; } @@ -192,6 +197,7 @@ function btsh(baseurl, tournament_key) { ws.sendmsg = ws_sendmsg; ws.onopen = function () { reload_match_information(); + send_device_info(); }; ws.onmessage = handle_message; ws.onclose = function () { From 609d3ee920c0329842f185a42afa75de663dc741 Mon Sep 17 00:00:00 2001 From: tengmel Date: Tue, 15 Oct 2024 14:41:15 +0200 Subject: [PATCH 15/38] #53: BUP: Integrate a possibilty to remove all stored matches from local cache --- js/btsh.js | 1 + js/importexport.js | 2 +- js/match_storage.js | 23 +++++++++++++++-------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/js/btsh.js b/js/btsh.js index d1ba9b98..b58b1858 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -198,6 +198,7 @@ function btsh(baseurl, tournament_key) { ws.onopen = function () { reload_match_information(); send_device_info(); + match_storage.remove_all(12); }; ws.onmessage = handle_message; ws.onclose = function () { diff --git a/js/importexport.js b/js/importexport.js index 7b287b72..c52ad8f4 100644 --- a/js/importexport.js +++ b/js/importexport.js @@ -137,7 +137,7 @@ function ui_init() { }); click.qs('.delete_matches_link', function () { - match_storage.remove_all("ALL"); + match_storage.remove_all(0); }); } diff --git a/js/match_storage.js b/js/match_storage.js index 8ac2d088..7c410484 100644 --- a/js/match_storage.js +++ b/js/match_storage.js @@ -55,16 +55,23 @@ function load_match(match_id) { function remove(match_id) { window.localStorage.removeItem('bup_match_' + match_id); - } +} -function remove_all(match_id) { +function remove_all(hours_ago) { var matches = load(); - matches.forEach(function (m) { - const m_id = m.metadata.id; - if (match_id != m_id) { - window.localStorage.removeItem('bup_match_' + m_id); - } - }); + 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() { From 8e8175dbd148ac472d22e9d061305b74db440562 Mon Sep 17 00:00:00 2001 From: tengmel Date: Sun, 20 Oct 2024 19:42:44 +0200 Subject: [PATCH 16/38] [#68] Server.Core: Conversion of communication between tablets and BTS to WebSocket --- js/btsh.js | 146 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 84 insertions(+), 62 deletions(-) diff --git a/js/btsh.js b/js/btsh.js index b58b1858..095757e4 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -6,6 +6,7 @@ function btsh(baseurl, tournament_key) { 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; @@ -72,14 +73,15 @@ function btsh(baseurl, tournament_key) { 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); + const req_match_id = s.setup.match_id; + const 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 = { + 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, @@ -90,23 +92,9 @@ function btsh(baseurl, tournament_key) { end_ts: end_ts, marks: s.match.marks, shuttle_count: s.match.shuttle_count, - device: _device_data(s, post_data), + device: _device_data(), }; - - var url = baseurl + 'h/' + encodeURIComponent(tournament_key) + '/m/' + encodeURIComponent(match_id) + '/score'; - - _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 - return; - } - - network.errstate('btsh.score', err); - }); + send_score_changed(score_data); } function sync(s) { @@ -119,31 +107,11 @@ function btsh(baseurl, tournament_key) { } 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); - } - - 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; - } - return res; - }); - courts.push({ - id: 'referee', - description: s._('court:referee'), - }); - s.btsh_courts = courts; - return callback(err, courts); - }); + bts_update_courts_callback = callback; + connect(); + if (s.btsh_courts && s.btsh_courts != null){ + callback(null, s.btsh_courts); + } } function ui_init() { @@ -166,17 +134,33 @@ function btsh(baseurl, tournament_key) { } async function persist_display_settings() { - ws.sendmsg({ type: 'persist_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); + ws_send({ type: 'persist_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); } async function reset_display_settings() { - ws.sendmsg({ type: 'reset_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); + ws_send({ type: 'reset_display_settings', tournament_key: tournament_key, panel_settings: state.settings }); } async function send_device_info() { - ws.sendmsg({ type: 'device_info', tournament_key: tournament_key, device: _device_data() }); + 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) { + ws_send({ type: 'score_update', tournament_key: tournament_key, score: score}); + } + + function confirm_match_finished() { + if (state.match && state.match.team1_won && 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'; @@ -190,7 +174,7 @@ function btsh(baseurl, tournament_key) { return s.btsh_courts; } - function connect(cb, s) { + function connect() { try { if (ws == null) { ws = new WebSocket(construct_url(WS_PATH), 'bts-bup'); @@ -203,14 +187,14 @@ function btsh(baseurl, tournament_key) { ws.onmessage = handle_message; ws.onclose = function () { ws = null; - send_bts_not_reachable(cb, s); - setTimeout(connect, reconnect_timeout, cb, s); + send_bts_not_reachable(); + setTimeout(connect, reconnect_timeout); }; } } catch (e) { ws = null; - send_bts_not_reachable(cb, s); - setTimeout(connect, reconnect_timeout, cb, s); + send_bts_not_reachable(); + setTimeout(connect, reconnect_timeout); } } function construct_url(abspath) { @@ -261,6 +245,9 @@ function btsh(baseurl, tournament_key) { case 'change': default_change_handler(msg); break; + case 'error': + network.errstate('btsh.score', msg); + break; default: send({ type: 'error', @@ -278,11 +265,40 @@ function btsh(baseurl, tournament_key) { 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; break; + case 'confirm-match-finished': + confirm_match_finished(); + 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; + } + return res; + }); + courts.push({ + id: 'referee', + description: state._('court:referee'), + }); + + state.btsh_courts = courts; + if (bts_update_courts_callback && bts_update_courts_callback != null) { + bts_update_courts_callback(null, state.btsh_courts); + } + break; default: break; } @@ -306,15 +322,21 @@ function btsh(baseurl, tournament_key) { function subscribe(s, cb, calc_timeout) { bts_update_callback = cb; - connect(cb,s); + if (state && state.bts_event && state.bts_event != null) { + bts_update_callback(null, state, state.bts_event); + state.bts_event = null; + } + connect(); } - function send_bts_not_reachable(cb,s) { - var msg = s._('network:error:bts'); - cb({ - type: 'network-error', - msg: msg, - }, s, null); + 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 { From 75a805f62c07199b77f0f3dffe8f42038ba16ab9 Mon Sep 17 00:00:00 2001 From: tengmel Date: Sun, 20 Oct 2024 19:46:08 +0200 Subject: [PATCH 17/38] [#69] AdminPanel: Provision of an option for games to also confirm termination from the admin panel --- js/control.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/js/control.js b/js/control.js index 0ec98e0d..19fd6695 100644 --- a/js/control.js +++ b/js/control.js @@ -261,14 +261,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 +387,14 @@ function ui_init() { } +function post_match_confirn(){ + if (!state.match.finish_confirmed) { + on_press({ + type: 'postmatch-confirm', + }); + } + ask_leave_match(state); +} function set_current(s) { buphistory.record(s); @@ -443,6 +444,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, From d1def7e84954074b7cfa520c7e849159336a0f1c Mon Sep 17 00:00:00 2001 From: tengmel Date: Sun, 20 Oct 2024 20:04:37 +0200 Subject: [PATCH 18/38] [#69] AdminPanel: Provision of an option for games to also confirm termination from the admin panel --- js/control.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/control.js b/js/control.js index 19fd6695..02d87f1e 100644 --- a/js/control.js +++ b/js/control.js @@ -387,7 +387,7 @@ function ui_init() { } -function post_match_confirn(){ +function post_match_confirm(){ if (!state.match.finish_confirmed) { on_press({ type: 'postmatch-confirm', From 182ad048ebee4d57f6f2748cbe57c4591cfb70ed Mon Sep 17 00:00:00 2001 From: tengmel Date: Tue, 5 Nov 2024 07:15:14 +0100 Subject: [PATCH 19/38] [#68] Server.Core: Conversion of communication between tablets and BTS to WebSocket: Bugfix: Errormessage was not reset before next try to send score --- js/btsh.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/btsh.js b/js/btsh.js index 095757e4..a58e6dba 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -146,7 +146,8 @@ function btsh(baseurl, tournament_key) { setTimeout(send_device_info, 1000*60*5); } async function send_score_changed(score) { - ws_send({ type: 'score_update', tournament_key: tournament_key, score: score}); + network.errstate('btsh.score', null); + ws_send({ type: 'score_update', tournament_key: tournament_key, score: score }); } function confirm_match_finished() { From 81dc2d1d81f14bcc4102a7148e740ec5b4fd732a Mon Sep 17 00:00:00 2001 From: tengmel Date: Tue, 5 Nov 2024 21:37:34 +0100 Subject: [PATCH 20/38] [#68] Server.Core: Conversion of communication between tablets and BTS to WebSocket: Bugfix: Opening already finished games raises misleading errormessage --- js/control.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/control.js b/js/control.js index 02d87f1e..90fb865e 100644 --- a/js/control.js +++ b/js/control.js @@ -117,7 +117,7 @@ function ask_leave_match(s) { return; } - if (network.score_transmitted()) { + if (s.match.finish_confirmed || network.score_transmitted()) { leave_match(s); return; } From b530de3f3ef8eb3d5e2e3aeefc30549ff57609f6 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Wed, 25 Dec 2024 10:24:46 +0100 Subject: [PATCH 21/38] New feature #85: Add tournamentplayers displaymaode --- doc/URLs.txt | 1 + js/displaymode.js | 136 ++++++++++++++++++++++++++++++++++++++++++++++ js/i18n_de.js | 1 + js/i18n_en.js | 1 + js/i18n_frch.js | 1 + 5 files changed, 140 insertions(+) diff --git a/doc/URLs.txt b/doc/URLs.txt index d714bd86..4c7af662 100644 --- a/doc/URLs.txt +++ b/doc/URLs.txt @@ -71,6 +71,7 @@ dm_style=STYLECODE In display mode, start with the specified style. 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. 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 diff --git a/js/displaymode.js b/js/displaymode.js index e583a302..6db34822 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -8,6 +8,7 @@ var ALL_STYLES = [ 'clean', 'teamcourt', 'tournamentcourt', + 'tournamentplayers', 'stripes', '2court', 'greyish', @@ -2095,6 +2096,139 @@ function render_tournamentcourt(s, container, event, court, match, colors) { }); } +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.counting, 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.counting, 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; + + 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); @@ -3076,6 +3210,7 @@ function update(err, s, event) { stripes: render_stripes, teamcourt: render_teamcourt, tournamentcourt: render_tournamentcourt, + tournamentplayers: render_tournamentplayers, }[style]; if (xfunc) { var court = _render_court(s, container, event); @@ -3373,6 +3508,7 @@ function option_applies(style_id, option_name) { 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'], diff --git a/js/i18n_de.js b/js/i18n_de.js index c25f2734..364d15ab 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -524,6 +524,7 @@ var i18n_de = { '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', diff --git a/js/i18n_en.js b/js/i18n_en.js index 1e569de7..1ff8f402 100644 --- a/js/i18n_en.js +++ b/js/i18n_en.js @@ -522,6 +522,7 @@ var i18n_en = { '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é', diff --git a/js/i18n_frch.js b/js/i18n_frch.js index f7ee2744..71392157 100644 --- a/js/i18n_frch.js +++ b/js/i18n_frch.js @@ -517,6 +517,7 @@ var i18n_frch = { '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é', From 1f25e241345c80bcad5124662fa5631b4a69128c Mon Sep 17 00:00:00 2001 From: tengmel Date: Fri, 27 Dec 2024 09:53:06 +0100 Subject: [PATCH 22/38] #78: BUP: Request confirmation of the player's result more clearly. --- js/i18n_de.js | 2 +- js/i18n_dech.js | 2 +- js/i18n_en.js | 2 +- js/i18n_frch.js | 2 +- js/i18n_nlbe.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/i18n_de.js b/js/i18n_de.js index 364d15ab..92f8f3e5 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -144,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', 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 1ff8f402..07dc4866 100644 --- a/js/i18n_en.js +++ b/js/i18n_en.js @@ -144,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', diff --git a/js/i18n_frch.js b/js/i18n_frch.js index 71392157..28fb155d 100644 --- a/js/i18n_frch.js +++ b/js/i18n_frch.js @@ -141,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', 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', From 0b17c1c451260267704403c38673d4248de0f00b Mon Sep 17 00:00:00 2001 From: tengmel Date: Fri, 27 Dec 2024 17:18:37 +0100 Subject: [PATCH 23/38] #92: BUP/BTS: Advertisement: Make it possible to confgure the advertisements which should be displayed in BTS --- js/btsh.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/btsh.js b/js/btsh.js index a58e6dba..1a87c9f3 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -274,6 +274,7 @@ function btsh(baseurl, tournament_key) { break; case 'settings-update': state.settings = c.val; + state.dads = c.val.advertisements; break; case 'confirm-match-finished': confirm_match_finished(); From 0bc6dfbfedeeba0f20e822e4e3ae5c7a56e577f9 Mon Sep 17 00:00:00 2001 From: tengmel Date: Sun, 29 Dec 2024 11:32:37 +0100 Subject: [PATCH 24/38] #92: BUP/BTS: Advertisement: Make it possible to confgure the advertisements which should be displayed in BTS --- js/btsh.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/js/btsh.js b/js/btsh.js index 1a87c9f3..06e4bd4b 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -279,6 +279,17 @@ function btsh(baseurl, tournament_key) { 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) { From 347afbfcb33cc98b0f7e832109e1e990c830e116 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Sun, 19 Jan 2025 19:04:13 +0100 Subject: [PATCH 25/38] Add streaming displaymode for DM O19 2025 in Cloppenburg --- doc/URLs.txt | 1 + icons/Ball_DM_Cloppenburg.svg | 220 +++++++++++ icons/Ball_DM_Cloppenburg_nur_Hintergund.svg | 208 ++++++++++ icons/Ball_DM_Cloppenburg_ohne_Hintergund.svg | 214 ++++++++++ icons/Ball_DM_Cloppenburg_schwarz.svg | 134 +++++++ icons/DBM_Schriftzug_mit_73_wiess.svg | 103 +++++ js/displaymode.js | 373 +++++++++++++++++- js/i18n_de.js | 34 ++ js/i18n_en.js | 34 ++ js/i18n_frch.js | 2 + 10 files changed, 1322 insertions(+), 1 deletion(-) create mode 100644 icons/Ball_DM_Cloppenburg.svg create mode 100644 icons/Ball_DM_Cloppenburg_nur_Hintergund.svg create mode 100644 icons/Ball_DM_Cloppenburg_ohne_Hintergund.svg create mode 100644 icons/Ball_DM_Cloppenburg_schwarz.svg create mode 100644 icons/DBM_Schriftzug_mit_73_wiess.svg diff --git a/doc/URLs.txt b/doc/URLs.txt index 4c7af662..75abc8ee 100644 --- a/doc/URLs.txt +++ b/doc/URLs.txt @@ -78,6 +78,7 @@ dm_style=STYLECODE In display mode, start with the specified style. 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 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..8ed59413 --- /dev/null +++ b/icons/DBM_Schriftzug_mit_73_wiess.svg @@ -0,0 +1,103 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/js/displaymode.js b/js/displaymode.js index 6db34822..10f3c8b3 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -24,6 +24,7 @@ var ALL_STYLES = [ 'castall', 'stream', 'streamcourt', + 'streamcourt_dm', 'streamteam', 'tournament_overview', 'andre', @@ -31,7 +32,7 @@ var ALL_STYLES = [ 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', @@ -1028,6 +1029,374 @@ 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 counting = match ? match.setup.counting : eventutils.default_counting(event.league_key); + var max_games = counting ? calc.max_game_count(counting) : 0; + 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.counting, 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; + console.log(team_serving); + } + } + + 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)); + + + console.log(); + 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 } @@ -3301,6 +3670,7 @@ function update(err, s, event) { teamscore: render_teamscore, stream: render_stream, streamcourt: render_streamcourt, + streamcourt_dm: render_streamcourt_dm, streamteam: render_streamteam, }[style]; if (ofunc) { @@ -3505,6 +3875,7 @@ 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'], diff --git a/js/i18n_de.js b/js/i18n_de.js index 364d15ab..caeb7113 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -232,6 +232,7 @@ var i18n_de = { 'settings:style:complete': 'Vollständig', 'settings:style:clean': 'Nur Feld und Vollbild', 'settings:style:focus': 'Fokus', +'settings:style:hidden': 'Verborgen', 'settings:warmup': 'Spielfeld\u00ADgewöhnungszeit', 'settings:warmup:bwf-2016': 'BWF ab 2016 (90s)', @@ -541,6 +542,7 @@ var i18n_de = { 'displaymode|stripes': 'Streifen', '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': 'lade ...', @@ -666,6 +668,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_en.js b/js/i18n_en.js index 1ff8f402..5cbf86ff 100644 --- a/js/i18n_en.js +++ b/js/i18n_en.js @@ -230,6 +230,7 @@ var i18n_en = { 'settings:style:complete': 'Complete', 'settings:style:clean': 'Clean', 'settings:style:focus': 'Focus Mode', +'settings:style:hidden': 'Hidden Mode', 'settings:warmup': 'Warmup:', 'settings:warmup:bwf-2016': 'BWF 2016+ (120s, ready after 90s)', @@ -539,6 +540,7 @@ var i18n_en = { 'displaymode|stripes': 'stripes', 'displaymode|stream': 'stream', 'displaymode|streamcourt': 'court stream', +'displaymode|streamcourt_dm': 'Court-Stream for DM 2025', 'displaymode|streamteam': 'stream team', 'displaymode:court_id': 'court:', 'displaymode:court_id:loading': 'loading ...', @@ -665,6 +667,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 71392157..a45ce3df 100644 --- a/js/i18n_frch.js +++ b/js/i18n_frch.js @@ -271,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', @@ -534,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 ...', From 3bd51d1ec83d1e31a7128b60f8cb9e4791c15ce9 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Tue, 28 Jan 2025 17:32:54 +0100 Subject: [PATCH 26/38] Add score overview for DM 2025 in Cloppenburg --- js/displaymode.js | 250 +++++++++++++++++++++++++++++++++++++++++++++- js/i18n_de.js | 1 + js/i18n_en.js | 1 + 3 files changed, 249 insertions(+), 3 deletions(-) diff --git a/js/displaymode.js b/js/displaymode.js index 10f3c8b3..7d95e1ed 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -27,6 +27,7 @@ var ALL_STYLES = [ 'streamcourt_dm', 'streamteam', 'tournament_overview', + 'tournament_overview_dm', 'andre', ]; var ALL_COLORS = [ @@ -483,9 +484,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) || []; @@ -535,6 +533,250 @@ 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: #333333;' + + 'z-index:10;' + ), + }); + + event.courts.forEach(function(court, idx) { + var match = _match_by_court(event, court); + var nscore = (match ? match.network_score : 0) || []; + + var counting = match ? match.setup.counting : eventutils.default_counting(event.league_key); + var max_games = counting ? calc.max_game_count(counting) : 0; + var current_score = (nscore.length > 0) ? nscore[nscore.length - 1] : ['', '']; + var server = match ? determine_server(match, current_score) : {}; + + var court = uiu.el(background, 'div', { + style: ( + 'position:absolute;top:'+idx*20+'vh;left:0vh;' + + 'height:20vh;width:100vw;' + ), + }); + + var logo = uiu.el(court, 'div', { + style: ( + 'position:absolute;top:3vh;left:18vh;' + + 'height:14vh;width:13.6vh;' + + '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(court, 'div', { + style: ( + 'position:absolute;top:3.84vh;left:22vh;' + + 'height:12.32vh;' + + 'z-index:-1;' + + 'display: flex;' + + 'flex-direction: row;' + ), + }); + + var top_bar_left = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:12.32vh;width:65vw;' + + '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:10vh;' + + 'font-size:4vh;' + + 'height: 100%;' + + 'align-content: center;' + + 'width: fit-content;' + ) + }, + 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: 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++) { + 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.counting, 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; + console.log(team_serving); + } + } + } + + var top_bar_set = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:12.32vh;width:6.6vh;' + + '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:5vh;' + + 'align-items: center;' + ), + }, 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:5vh;' + + 'align-items: center;' + ), + }, 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_castall(s, container, event, colors) { if (!event.courts) { uiu.el(container, 'div', 'error', 'Court information missing'); @@ -3666,6 +3908,7 @@ function update(err, s, event) { castall: render_castall, greyish: render_greyish, tournament_overview: render_tournament_overview, + tournament_overview_dm: render_tournament_overview_dm, tim: render_tim, teamscore: render_teamscore, stream: render_stream, @@ -3883,6 +4126,7 @@ function option_applies(style_id, option_name) { 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'], stripes: ['court_id', 'cbg', 'team_colors', 'c0', 'c1', 'cfg', 'cfgdark', 'cbg4', 'cserv'], }; var bs = BY_STYLE[style_id]; diff --git a/js/i18n_de.js b/js/i18n_de.js index 27421fbd..9c3e96f4 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -543,6 +543,7 @@ var i18n_de = { '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|streamteam': 'Stream-Team', 'displaymode:court_id': 'Court:', 'displaymode:court_id:loading': 'lade ...', diff --git a/js/i18n_en.js b/js/i18n_en.js index 0a0ecfec..279baa0d 100644 --- a/js/i18n_en.js +++ b/js/i18n_en.js @@ -541,6 +541,7 @@ var i18n_en = { '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 ...', From bf4d5a3c4756ebd87634dd5b1995c2d6929e093c Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Tue, 28 Jan 2025 23:32:00 +0100 Subject: [PATCH 27/38] Addapt tournament_overview_dm --- js/displaymode.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/js/displaymode.js b/js/displaymode.js index 7d95e1ed..bdef5515 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -546,7 +546,7 @@ function render_tournament_overview_dm(s, container, event) { style: ( 'position:absolute;top:0vh;left:0vh;' + 'height:100vh;width:100vw;' + - 'background-color: #333333;' + + 'background-color: #000000;' + 'z-index:10;' ), }); @@ -569,8 +569,8 @@ function render_tournament_overview_dm(s, container, event) { var logo = uiu.el(court, 'div', { style: ( - 'position:absolute;top:3vh;left:18vh;' + - 'height:14vh;width:13.6vh;' + + 'position:absolute;top:1vh;left:2vh;' + + 'height:18vh;width:17.6vh;' + 'background-repeat: no-repeat;' + 'background-position:center;' + 'background-size:contain;' + @@ -580,8 +580,8 @@ function render_tournament_overview_dm(s, container, event) { }); var top_bar = uiu.el(court, 'div', { style: ( - 'position:absolute;top:3.84vh;left:22vh;' + - 'height:12.32vh;' + + 'position:absolute;top:2vh;left:7.3vh;' + + 'height:16vh;' + 'z-index:-1;' + 'display: flex;' + 'flex-direction: row;' @@ -591,7 +591,7 @@ function render_tournament_overview_dm(s, container, event) { var top_bar_left = uiu.el(top_bar, 'div', { style: ( 'position:static;' + - 'height:12.32vh;width:65vw;' + + 'height:16vh;width:80vw;' + 'display: flex;' + 'flex-direction: column;' + 'justify-content: space-between;' @@ -650,8 +650,8 @@ function render_tournament_overview_dm(s, container, event) { for (var team_idx = 0;team_idx < 2;team_idx++) { var team_name = uiu.el(teams[team_idx], 'div', { style: ( - 'margin-left:10vh;' + - 'font-size:4vh;' + + 'margin-left:12vh;' + + 'font-size:5.5vh;' + 'height: 100%;' + 'align-content: center;' + 'width: fit-content;' @@ -663,7 +663,7 @@ function render_tournament_overview_dm(s, container, event) { style: ( 'height: 100%;' + 'align-content: center;' + - 'width: 4vh;' + + 'width: 6.5vh;' + 'background-repeat: no-repeat;' + 'background-position:center;' + 'background-size:contain;' + @@ -701,7 +701,7 @@ function render_tournament_overview_dm(s, container, event) { var top_bar_set = uiu.el(top_bar, 'div', { style: ( 'position:static;' + - 'height:12.32vh;width:6.6vh;' + + 'height:16vh;width:9vh;' + 'display: flex;' + 'flex-direction: column;' + 'justify-content: space-between;' + @@ -727,7 +727,7 @@ function render_tournament_overview_dm(s, container, event) { 'background-color: #ffffffbb;' + 'display: flex;' + 'justify-content: center;' + - 'font-size:5vh;' + + 'font-size:7vh;' + 'align-items: center;' ), }, game_idx < nscore.length ? nscore[game_idx][0] : '')); @@ -746,7 +746,7 @@ function render_tournament_overview_dm(s, container, event) { 'background-color: #ffffffbb;' + 'display: flex;' + 'justify-content: center;' + - 'font-size:5vh;' + + 'font-size:7vh;' + 'align-items: center;' ), }, game_idx < nscore.length ? nscore[game_idx][1] : '')); From bfb7db8ea5160108d9648934674ae965c146423a Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Wed, 29 Jan 2025 09:35:42 +0100 Subject: [PATCH 28/38] addapt font size of overview dm --- js/displaymode.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/js/displaymode.js b/js/displaymode.js index bdef5515..3b0c46c2 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -651,10 +651,11 @@ function render_tournament_overview_dm(s, container, event) { var team_name = uiu.el(teams[team_idx], 'div', { style: ( 'margin-left:12vh;' + - 'font-size:5.5vh;' + + 'font-size:6.0vh;' + 'height: 100%;' + 'align-content: center;' + - 'width: fit-content;' + '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 : '') : ''); @@ -728,7 +729,8 @@ function render_tournament_overview_dm(s, container, event) { 'display: flex;' + 'justify-content: center;' + 'font-size:7vh;' + - 'align-items: center;' + 'align-items: center;'+ + 'font-weight: bold;' ), }, game_idx < nscore.length ? nscore[game_idx][0] : '')); @@ -747,7 +749,8 @@ function render_tournament_overview_dm(s, container, event) { 'display: flex;' + 'justify-content: center;' + 'font-size:7vh;' + - 'align-items: center;' + 'align-items: center;'+ + 'font-weight: bold;' ), }, game_idx < nscore.length ? nscore[game_idx][1] : '')); From 661ee3f7a68f436f9599021a5ac07fe5be0fd4bb Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Wed, 29 Jan 2025 16:43:37 +0100 Subject: [PATCH 29/38] set fix height for Image whle no game on court --- js/displaymode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/displaymode.js b/js/displaymode.js index 3b0c46c2..228e9368 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -3875,7 +3875,7 @@ function update(err, s, event) { } else if (event.tournament_logo_url) { uiu.el(nomatch_el, 'img', { src: event.tournament_logo_url, - style: 'max-height: 70vh; max-width: 90vw;', + style: 'max-height: 70vh; max-width: 90vw; height:70vh;', alt: (event.tournament_name || ''), }); From 7318a740da8a0c784aac8500407425378543ab8f Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Wed, 29 Jan 2025 20:48:30 +0100 Subject: [PATCH 30/38] Fix unwanted Text-Wraps in TournamentCourt:Players Only View. --- css/displaymode.css | 1 + js/displaymode.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/css/displaymode.css b/css/displaymode.css index 39ee6092..8215d148 100644 --- a/css/displaymode.css +++ b/css/displaymode.css @@ -137,6 +137,7 @@ font-stretch: condensed; position: relative; height: 50%; + text-wrap: nowrap; } .d_international_player_container, .d_tournament_player_container diff --git a/js/displaymode.js b/js/displaymode.js index 228e9368..223e2058 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -2832,9 +2832,13 @@ function render_tournamentplayers(s, container, event, court, match, colors) { }); 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; From bfb0d16a9ddc60c02dd56fb11e965535f0347724 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Fri, 31 Jan 2025 08:02:32 +0100 Subject: [PATCH 31/38] add court number to dm overview --- js/displaymode.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/js/displaymode.js b/js/displaymode.js index 223e2058..ab9fc412 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -560,14 +560,15 @@ function render_tournament_overview_dm(s, container, event) { var current_score = (nscore.length > 0) ? nscore[nscore.length - 1] : ['', '']; var server = match ? determine_server(match, current_score) : {}; - var court = uiu.el(background, 'div', { + var court_el = uiu.el(background, 'div', { style: ( 'position:absolute;top:'+idx*20+'vh;left:0vh;' + 'height:20vh;width:100vw;' ), }); - var logo = uiu.el(court, 'div', { + + var logo = uiu.el(court_el, 'div', { style: ( 'position:absolute;top:1vh;left:2vh;' + 'height:18vh;width:17.6vh;' + @@ -575,10 +576,17 @@ function render_tournament_overview_dm(s, container, event) { 'background-position:center;' + 'background-size:contain;' + 'background-image:url("icons/Ball_DM_Cloppenburg.svg");'+ - 'z-index:10;' - ), - }); - var top_bar = uiu.el(court, 'div', { + '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:7.3vh;' + 'height:16vh;' + From 8a6a941a3a82689f75e69f111b1d1d8375c08ca2 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Fri, 31 Jan 2025 16:18:13 +0100 Subject: [PATCH 32/38] addapt overvieiw for dm --- js/displaymode.js | 72 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/js/displaymode.js b/js/displaymode.js index ab9fc412..f73c932b 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -567,15 +567,11 @@ function render_tournament_overview_dm(s, container, event) { ), }); - +/* var logo = uiu.el(court_el, 'div', { style: ( 'position:absolute;top:1vh;left:2vh;' + 'height:18vh;width:17.6vh;' + - 'background-repeat: no-repeat;' + - 'background-position:center;' + - 'background-size:contain;' + - 'background-image:url("icons/Ball_DM_Cloppenburg.svg");'+ 'z-index:10;'+ 'font-size: 15vh;'+ 'color: #000;'+ @@ -585,10 +581,10 @@ function render_tournament_overview_dm(s, container, event) { 'font-weight: bold;'+ 'font-style: oblique;' ), - }, idx+1); + }, idx+1);*/ var top_bar = uiu.el(court_el, 'div', { style: ( - 'position:absolute;top:2vh;left:7.3vh;' + + 'position:absolute;top:2vh;left:2vw;' + 'height:16vh;' + 'z-index:-1;' + 'display: flex;' + @@ -596,22 +592,75 @@ function render_tournament_overview_dm(s, container, event) { ), }); - var top_bar_left = uiu.el(top_bar, 'div', { + + var top_bar_court = uiu.el(top_bar, 'div', { style: ( 'position:static;' + - 'height:16vh;width:80vw;' + + 'height:16vh;width:10vw;' + '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: 12.5vh;'+ + 'height: 100%;' + + 'font-weight: bold;' + + 'font-style: oblique;' + ), + },idx+1); + + 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;' + ), + }); + + + + var top_bar_left = uiu.el(top_bar, 'div', { + style: ( + 'position:static;' + + 'height:16vh;width:70vw;' + + '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-right-radius: 1vh;'+ + 'border-top-left-radius: 1vh;' ), }); @@ -650,6 +699,7 @@ function render_tournament_overview_dm(s, container, event) { 'position:static;' + 'height:5%;width:100%;' + 'background-color: #ffffff;' + + 'border-bottom-left-radius: 1vh;'+ 'border-bottom-right-radius: 1vh;' ), }); @@ -658,7 +708,7 @@ function render_tournament_overview_dm(s, container, event) { for (var team_idx = 0;team_idx < 2;team_idx++) { var team_name = uiu.el(teams[team_idx], 'div', { style: ( - 'margin-left:12vh;' + + 'margin-left:1vh;' + 'font-size:6.0vh;' + 'height: 100%;' + 'align-content: center;' + From 7c047356b338e6bf2dbb84499c28cc8187070823 Mon Sep 17 00:00:00 2001 From: tengmel Date: Sat, 1 Feb 2025 00:27:12 +0100 Subject: [PATCH 33/38] addapt overvieiw for dm --- js/displaymode.js | 353 ++++++++++++++++++++++++++++++++++++++++++++++ js/i18n_de.js | 1 + 2 files changed, 354 insertions(+) diff --git a/js/displaymode.js b/js/displaymode.js index f73c932b..1f8e5db2 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -28,6 +28,7 @@ var ALL_STYLES = [ 'streamteam', 'tournament_overview', 'tournament_overview_dm', + 'tournament_overview_dm_finals', 'andre', ]; var ALL_COLORS = [ @@ -832,7 +833,357 @@ function render_tournament_overview_dm(s, container, event) { }); } + 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 counting = match ? match.setup.counting : eventutils.default_counting(event.league_key); + var max_games = counting ? calc.max_game_count(counting) : 0; + 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:18vw;' + + '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: 12.5vh;' + + 'font-weight: bold;' + + 'font-style: oblique;' + ), + }, 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.counting, 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; + console.log(team_serving); + } + } + } + + 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'; + } + + }); + } @@ -3974,6 +4325,7 @@ function update(err, s, event) { 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, @@ -4192,6 +4544,7 @@ function option_applies(style_id, option_name) { 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'], }; var bs = BY_STYLE[style_id]; diff --git a/js/i18n_de.js b/js/i18n_de.js index 9c3e96f4..bffd6168 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -544,6 +544,7 @@ var i18n_de = { '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 ...', From 7db459ada8414074bce411322a0f141807c1b1fb Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Fri, 7 Feb 2025 00:07:11 +0100 Subject: [PATCH 34/38] #94 Fix: the Names of the Umpire and the Service Jude are now shown on the scoresheet. --- js/scoresheet.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/scoresheet.js b/js/scoresheet.js index fa2026c7..1016fd5c 100644 --- a/js/scoresheet.js +++ b/js/scoresheet.js @@ -700,8 +700,8 @@ function sheet_render(s, svg) { } _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) { From 354202e6b2ac26c694d7b8deb0af267f770fc8c3 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Sat, 12 Apr 2025 17:42:42 +0200 Subject: [PATCH 35/38] better display Managment for BTS --- js/btsh.js | 6 ++++++ js/utils.js | 3 +++ 2 files changed, 9 insertions(+) diff --git a/js/btsh.js b/js/btsh.js index 06e4bd4b..e7e2d568 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -150,6 +150,10 @@ function btsh(baseurl, tournament_key) { ws_send({ type: 'score_update', tournament_key: tournament_key, score: score }); } + 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 && state.metadata.end && state.metadata.end != null){ control.post_match_confirm(state); @@ -300,6 +304,7 @@ function btsh(baseurl, tournament_key) { if (rc.match_id) { res.match_id = 'bts_' + rc.match_id; } + send_command_done(c); return res; }); courts.push({ @@ -315,6 +320,7 @@ function btsh(baseurl, tournament_key) { default: break; } + send_command_done(c); } function reload_match_information() { 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]); }; } From 32a134cae5797e4a4ec56f1804595c7f279bf429 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Fri, 25 Apr 2025 17:08:55 +0200 Subject: [PATCH 36/38] current version --- bup.html | 8 ++++---- js/btsh.js | 5 ++--- js/displaymode.js | 14 ++++++++++++++ js/network.js | 6 +++--- js/scoresheet.js | 3 +++ js/settings.js | 4 ++-- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/bup.html b/bup.html index 4af1eb55..98cf1314 100644 --- a/bup.html +++ b/bup.html @@ -221,7 +221,7 @@

-
+

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

-
+
-

+
@@ -377,7 +377,7 @@

- +
diff --git a/js/btsh.js b/js/btsh.js index e7e2d568..e0433d1c 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -154,8 +154,8 @@ function btsh(baseurl, tournament_key) { ws_send({ type: 'command_done', tournament_key: tournament_key, wait_for_command: command}) } - function confirm_match_finished() { - if (state.match && state.match.team1_won && state.metadata.end && state.metadata.end != null){ + function confirm_match_finished() { + if (state.match && (state.match.team1_won != null) && state.metadata.end && state.metadata.end != null){ control.post_match_confirm(state); } } @@ -230,7 +230,6 @@ function btsh(baseurl, tournament_key) { callback(); } } else { - console.log("wait for connection...") waitForSocketConnection(socket, callback); } diff --git a/js/displaymode.js b/js/displaymode.js index 1f8e5db2..f6a5c783 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -2966,9 +2966,21 @@ 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; @@ -3117,6 +3129,7 @@ function render_tournamentcourt(s, container, event, court, match, colors) { }); }); }); + console.log("RENDERN is DONE!"); } function render_tournamentplayers(s, container, event, court, match, colors) { @@ -4546,6 +4559,7 @@ function option_applies(style_id, option_name) { 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/network.js b/js/network.js index c5005ced..cfe14cc7 100644 --- a/js/network.js +++ b/js/network.js @@ -544,9 +544,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) { diff --git a/js/scoresheet.js b/js/scoresheet.js index 1016fd5c..04744d05 100644 --- a/js/scoresheet.js +++ b/js/scoresheet.js @@ -699,6 +699,9 @@ 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 && 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 : "")); diff --git a/js/settings.js b/js/settings.js index 75d79a58..da8b2287 100644 --- a/js/settings.js +++ b/js/settings.js @@ -277,7 +277,7 @@ 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); @@ -529,7 +529,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 } From 39d26e6b25914d90bba21d001b5d63718f935712 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Fri, 9 May 2025 12:42:38 +0200 Subject: [PATCH 37/38] current version --- bup.html | 2 +- js/btsh.js | 9 ++++++++- js/displaymode.js | 6 ------ js/i18n_de.js | 2 +- js/i18n_en.js | 2 +- js/network.js | 11 ++++++++--- js/settings.js | 17 +++++++++++------ 7 files changed, 30 insertions(+), 19 deletions(-) diff --git a/bup.html b/bup.html index 98cf1314..e9a62327 100644 --- a/bup.html +++ b/bup.html @@ -377,7 +377,7 @@

- +
diff --git a/js/btsh.js b/js/btsh.js index e0433d1c..444b69ea 100644 --- a/js/btsh.js +++ b/js/btsh.js @@ -278,6 +278,8 @@ function btsh(baseurl, tournament_key) { 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(); @@ -294,7 +296,6 @@ function btsh(baseurl, tournament_key) { } break; case 'courts-update': - var courts = c.val.map(function (rc) { var res = { id: rc._id, @@ -315,6 +316,12 @@ function btsh(baseurl, tournament_key) { if (bts_update_courts_callback && bts_update_courts_callback != null) { bts_update_courts_callback(null, state.btsh_courts); } + if(state.settings.devicemode == "umpire") { + settings.show(); + settings.on_mode_change(state); + } else { + settings.hide_displaymode(); + } break; default: break; diff --git a/js/displaymode.js b/js/displaymode.js index f6a5c783..31f60177 100644 --- a/js/displaymode.js +++ b/js/displaymode.js @@ -753,7 +753,6 @@ function render_tournament_overview_dm(s, container, event) { if(is_team_serving) { team_serving = team_idx; - console.log(team_serving); } } } @@ -1105,7 +1104,6 @@ function render_tournament_overview_dm(s, container, event) { if (is_team_serving) { team_serving = team_idx; - console.log(team_serving); } } } @@ -1832,7 +1830,6 @@ function render_streamcourt_dm(s, container, event/*, colors*/) { if(is_team_serving) { team_serving = team_idx; - console.log(team_serving); } } @@ -1942,8 +1939,6 @@ function render_streamcourt_dm(s, container, event/*, colors*/) { ), }, s._('Court') + ' ' + (court.label || court.num || court.court_id)); - - console.log(); uiu.el(top_bar_right, 'div', { style: ( 'position:static;' + @@ -3129,7 +3124,6 @@ function render_tournamentcourt(s, container, event, court, match, colors) { }); }); }); - console.log("RENDERN is DONE!"); } function render_tournamentplayers(s, container, event, court, match, colors) { diff --git a/js/i18n_de.js b/js/i18n_de.js index bffd6168..b93f8944 100644 --- a/js/i18n_de.js +++ b/js/i18n_de.js @@ -232,7 +232,7 @@ var i18n_de = { 'settings:style:complete': 'Vollständig', 'settings:style:clean': 'Nur Feld und Vollbild', 'settings:style:focus': 'Fokus', -'settings:style:hidden': 'Verborgen', +'settings:style:hidden': 'Verborgen (zentrale Verwaltung)', 'settings:warmup': 'Spielfeld\u00ADgewöhnungszeit', 'settings:warmup:bwf-2016': 'BWF ab 2016 (90s)', diff --git a/js/i18n_en.js b/js/i18n_en.js index 279baa0d..384f39f0 100644 --- a/js/i18n_en.js +++ b/js/i18n_en.js @@ -230,7 +230,7 @@ var i18n_en = { 'settings:style:complete': 'Complete', 'settings:style:clean': 'Clean', 'settings:style:focus': 'Focus Mode', -'settings:style:hidden': 'Hidden Mode', +'settings:style:hidden': 'Hidden Mode (central administration)', 'settings:warmup': 'Warmup:', 'settings:warmup:bwf-2016': 'BWF 2016+ (120s, ready after 90s)', diff --git a/js/network.js b/js/network.js index cfe14cc7..d6a831ed 100644 --- a/js/network.js +++ b/js/network.js @@ -372,15 +372,20 @@ 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; }); diff --git a/js/settings.js b/js/settings.js index da8b2287..08ea1ced 100644 --- a/js/settings.js +++ b/js/settings.js @@ -61,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() { @@ -196,12 +196,12 @@ function update_court(s) { } 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); @@ -270,7 +270,7 @@ var _settings_selects = [ 'language', 'wakelock', 'dads_mode', - 'settings_style', + 'style', ]; function update_court_settings(s) { @@ -303,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); @@ -392,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; } @@ -500,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'; From e96c53a6bf2055017890b4f87df2791d172963d9 Mon Sep 17 00:00:00 2001 From: Tim Lehr Date: Tue, 3 Jun 2025 22:15:03 +0200 Subject: [PATCH 38/38] current version --- js/calc.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/js/calc.js b/js/calc.js index 96d4482a..aee83fea 100644 --- a/js/calc.js +++ b/js/calc.js @@ -1121,22 +1121,9 @@ function netscore(s, always_zero) { 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); - } } var max_games = max_game_count(counting); - while (scores.length < max_games) { - var mwinner = match_winner(counting, scores); - if ((mwinner == 'left') || (mwinner == 'right')) { - break; - } - - var new_score = [0, 0]; - _finish_score(scores.length, new_score, s.match.team1_won); - scores.push(new_score); - } } return scores;