diff --git a/bts/admin.js b/bts/admin.js index 56876b9..a4de32e 100644 --- a/bts/admin.js +++ b/bts/admin.js @@ -55,6 +55,7 @@ function handle_tournament_edit_props(app, ws, msg) { 'btp_enabled', 'btp_autofetch_enabled', 'btp_readonly', 'btp_ip', 'btp_password', 'is_team', 'is_nation_competition', 'only_now_on_court', + 'warmup', 'warmup_ready', 'warmup_start', 'ticker_enabled', 'ticker_url', 'ticker_password', 'language', 'dm_style', 'logo_background_color', 'logo_foreground_color']); @@ -175,6 +176,7 @@ function _extract_setup(msg_setup) { 'incomplete', 'scheduled_time_str', 'scheduled_date', + 'called_timestamp', 'teams', 'override_colors', ]); diff --git a/bts/btp_sync.js b/bts/btp_sync.js index 625f99c..99b1b35 100644 --- a/bts/btp_sync.js +++ b/bts/btp_sync.js @@ -18,7 +18,7 @@ function date_str(dt) { return utils.pad(dt.year, 2, '0') + '-' + utils.pad(dt.month, 2, '0') + '-' + utils.pad(dt.day, 2, '0'); } -function craft_match(tkey, btp_id, court_map, event, draw, officials, bm, match_ids_on_court, match_types, is_league) { +function craft_match(app, tkey, btp_id, court_map, event, draw, officials, bm, match_ids_on_court, match_types, is_league) { if (!bm.IsMatch) { return; } @@ -53,7 +53,24 @@ function craft_match(tkey, btp_id, court_map, event, draw, officials, bm, match_ match_name, event_name, teams, + warmup: 'none', }; + + app.db.tournaments.findOne({key: tkey}, (err, tournament) => { + if (err) { + return callback(err); + } + if (tournament.warmup) { + setup.warmup = tournament.warmup; + } + if (tournament.warmup_ready) { + setup.warmup_ready = tournament.warmup_ready; + } + if (tournament.warmup_start) { + setup.warmup_start = tournament.warmup_start; + } + }); + if (scheduled_time_str) { setup.scheduled_time_str = scheduled_time_str; } @@ -201,13 +218,18 @@ function integrate_matches(app, tkey, btp_state, court_map, callback) { return; } - const match = craft_match(tkey, btp_id, court_map, event, draw, officials, bm, match_ids_on_court); + const match = craft_match(app, tkey, btp_id, court_map, event, draw, officials, bm, match_ids_on_court); if (!match) { cb(); return; } if (cur_match) { + if(cur_match.setup.called_timestamp) { + // The called_timestamp is not from btp so we have to coppy it to the match generated by btp. + match.setup.called_timestamp = cur_match.setup.called_timestamp; + } + if (utils.plucked_deep_equal(match, cur_match, Object.keys(match), true)) { // No update required cb(); @@ -381,16 +403,27 @@ function integrate_now_on_court(app, tkey, callback) { async.each(now_on_court_matches, (match, cb) => { const court_id = match.setup.court_id; const match_id = match._id; - if (!court_id || !match_id) return cb(); // TODO in async we would assert both to be true + const called_timestamp = Date.now(); - const court_q = {_id: court_id}; - app.db.courts.find(court_q, (err, courts) => { - if (err) return cb(err); - if (courts.length !== 1) return cb(); - const [court] = courts; + if (!court_id || !match_id) return cb(); // TODO in async we would assert both to be true - app.db.courts.update(court_q, {$set: {match_id}}, {}, (err) => cb(err)); - }); + const setup = match.setup; + if(!setup.called_timestamp) { + setup.called_timestamp = called_timestamp; + const match_q = {_id: match_id}; + app.db.matches.update(match_q, {$set: {setup}}, {}, (err) => { + if (err) return cb(err); + + const court_q = {_id: court_id}; + app.db.courts.find(court_q, (err, courts) => { + if (err) return cb(err); + if (courts.length !== 1) return cb(); + const [court] = courts; + + app.db.courts.update(court_q, {$set: {match_id}}, {}, (err) => cb(err)); + }); + }); + } }, callback); }); }); diff --git a/bts/http_api.js b/bts/http_api.js index 4e8014a..77b1523 100644 --- a/bts/http_api.js +++ b/bts/http_api.js @@ -164,6 +164,9 @@ function matches_handler(req, res) { if (dc.match_id) { res.match_id = 'bts_' + dc.match_id; } + if (dc.called_timestamp) { + res.called_timestamp = dc.called_timestamp; + } return res; }); diff --git a/fetch-btp.js b/fetch-btp.js index 8a2e6c3..f329dbb 100755 --- a/fetch-btp.js +++ b/fetch-btp.js @@ -286,7 +286,7 @@ async function main() { const btp_id = tkey + '_' + discipline_name + '_' + match_num; const match = btp_sync.craft_match( - tkey, btp_id, pseudo_court_map, event, draw, officials, bm, match_ids_on_court); + btp_conn.app, tkey, btp_id, pseudo_court_map, event, draw, officials, bm, match_ids_on_court); if (!match) { continue; } diff --git a/static/js/change.js b/static/js/change.js index b7bee05..11a50cd 100644 --- a/static/js/change.js +++ b/static/js/change.js @@ -44,6 +44,9 @@ function default_handler_func(rerender, special_funcs, c) { curt.is_nation_competition = c.val.is_nation_competition; curt.only_now_on_court = c.val.only_now_on_court; curt.btp_timezone = c.val.btp_timezone; + curt.warmup = c.val.warmup; + curt.warmup_ready = c.val.warmup_ready; + curt.warmup_start = c.val.warmup_start; curt.btp_enabled = c.val.btp_enabled; curt.btp_autofetch_enabled = c.val.btp_autofetch_enabled; curt.btp_readonly = c.val.btp_readonly; diff --git a/static/js/ci18n_de.js b/static/js/ci18n_de.js index 2df4b56..bbc9ddc 100644 --- a/static/js/ci18n_de.js +++ b/static/js/ci18n_de.js @@ -51,6 +51,15 @@ var ci18n_de = { 'tournament:edit:courts': 'Felder:', 'tournament:edit:dm_style': 'Standard-Ansicht:', 'tournament:edit:only_now_on_court': 'Spiele müssen auf Feld gezogen werden', +'tournament:edit:warmup_timer_behavior': 'Verhalten des Vorbereitungs-Countdowns:', +'tournament:edit:warmup_timer_behavior:bwf-2016': 'BWF ab 2016 (ab Auslosung)', +'tournament:edit:warmup_timer_behavior:legacy': 'Deutschland (ab Auslosung)', +'tournament:edit:warmup_timer_behavior:choise': 'ab Auslosung (individuelle Zeit)', +'tournament:edit:warmup_timer_behavior:call-down': 'ab Aufruf (Countdown)', +'tournament:edit:warmup_timer_behavior:call-up': 'ab Aufruf (Timer)', +'tournament:edit:warmup_timer_behavior:none': 'Sofort beginen', +'tournament:edit:warmup_ready': 'Spielbereit in Sekunden:', +'tournament:edit:warmup_start': 'Spielstart nach Sekunden:', 'tournament:edit:btp:enabled': 'BTP-Anbindung aktivieren', 'tournament:edit:btp:autofetch_enabled': 'Automatisch synchronisieren', 'tournament:edit:btp:readonly': 'Nur lesen', diff --git a/static/js/ci18n_en.js b/static/js/ci18n_en.js index bd4e9fd..c3a69df 100644 --- a/static/js/ci18n_en.js +++ b/static/js/ci18n_en.js @@ -51,6 +51,15 @@ var ci18n_en = { 'tournament:edit:courts': 'Courts:', 'tournament:edit:dm_style': 'Default display style:', 'tournament:edit:only_now_on_court': 'Matches have to be dragged onto court', +'tournament:edit:warmup_timer_behavior': 'Behaviour of the preparation countdown:', +'tournament:edit:warmup_timer_behavior:bwf-2016': 'BWF 2016+ (after choice of side)', +'tournament:edit:warmup_timer_behavior:legacy': 'legacy (after choice of side)', +'tournament:edit:warmup_timer_behavior:choise': 'after choice of side (individual time)', +'tournament:edit:warmup_timer_behavior:call-down': 'from call (countdown)', +'tournament:edit:warmup_timer_behavior:call-up': 'from call (timer)', +'tournament:edit:warmup_timer_behavior:none': 'none', +'tournament:edit:warmup_ready': 'Ready in seconds:', +'tournament:edit:warmup_start': 'Game starts after seconds:', 'tournament:edit:btp:enabled': 'Enable BTP synchronization', 'tournament:edit:btp:autofetch_enabled': 'Automatic synchronization', 'tournament:edit:btp:readonly': 'Read only', diff --git a/static/js/ctournament.js b/static/js/ctournament.js index 2a48c34..88f10fc 100644 --- a/static/js/ctournament.js +++ b/static/js/ctournament.js @@ -360,6 +360,99 @@ function ui_edit() { uiu.el(only_now_on_court_label, 'input', attrs); uiu.el(only_now_on_court_label, 'span', {}, ci18n('tournament:edit:only_now_on_court')); + // Warmup Timer + if (!curt.warmup_ready) { + curt.warmup_ready = 150; + } + + if (!curt.warmup_start) { + curt.warmup_start = 180; + } + + var warmup_options = [ ['bwf-2016' , 90, 120, true], + ['legacy' , 120, 120, true], + ['choise' , curt.warmup_ready, curt.warmup_start, false], + ['call-down' , curt.warmup_ready, curt.warmup_start, false], + ['call-up' , 0, 0, true], + ['none' , 0, 0, true]]; + + var last_selected_warmup = warmup_options[0]; + + const warmup_timer_label = uiu.el(form, 'label'); + uiu.el(warmup_timer_label, 'span', {}, ci18n('tournament:edit:warmup_timer_behavior')); + const warmup_timer_select = uiu.el(warmup_timer_label, 'select', { + name: 'warmup', + }); + uiu.el(warmup_timer_select, 'option', {value: warmup_options[0][0]}, ci18n('tournament:edit:warmup_timer_behavior:' + warmup_options[0][0]), {wo: warmup_options[0][0]}); + let warmup_marked = false; + + const warmup_ready = uiu.el(form, 'label'); + uiu.el(warmup_ready, 'span', {}, ci18n('tournament:edit:warmup_ready')); + var warmup_ready_input = uiu.el(warmup_ready, 'input', { + type: 'number', + name: 'warmup_ready', + required: 'required', + disabled: warmup_options[0][3], + value: warmup_options[0][1], + 'class': 'ct_name', + }); + + const warmup_start = uiu.el(form, 'label'); + uiu.el(warmup_start, 'span', {}, ci18n('tournament:edit:warmup_start')); + var warmup_start_input = uiu.el(warmup_start, 'input', { + type: 'number', + name: 'warmup_start', + required: 'required', + disabled: warmup_options[0][3], + value: warmup_options[0][2], + 'class': 'ct_name', + }); + + for (const wo of warmup_options.slice(1)) { + const attrs = { + value: wo[0], + } + + if ((wo[0] === curt.warmup) && !warmup_marked) { + warmup_marked = true; + attrs.selected = 'selected'; + + warmup_ready_input.value = wo[1]; + warmup_ready_input.disabled = wo[3]; + warmup_start_input.value = wo[2]; + warmup_start_input.disabled = wo[3]; + + last_selected_warmup = wo; + } + + uiu.el(warmup_timer_select, 'option', attrs, ci18n('tournament:edit:warmup_timer_behavior:'+wo[0])); + } + + warmup_timer_select.onchange = function() { + console.log(last_selected_warmup); + if (!last_selected_warmup[3]) { + console.log("Sichern!"); + for (const wo of warmup_options) { + if (!wo[3]) + { + wo[1] = warmup_ready_input.value; + wo[2] = warmup_start_input.value; + } + } + } + + for (const wo of warmup_options) { + if (warmup_timer_select.value == wo[0]) { + warmup_ready_input.value = wo[1]; + warmup_ready_input.disabled = wo[3]; + warmup_start_input.value = wo[2]; + warmup_start_input.disabled = wo[3]; + + last_selected_warmup = wo; + } + } + }; + // BTP const btp_fieldset = uiu.el(form, 'fieldset'); const btp_enabled_label = uiu.el(btp_fieldset, 'label'); @@ -480,6 +573,9 @@ function ui_edit() { btp_password: data.btp_password, btp_timezone: data.btp_timezone, dm_style: data.dm_style, + warmup: data.warmup, + warmup_ready: data.warmup_ready, + warmup_start: data.warmup_start, ticker_enabled: (!! data.ticker_enabled), ticker_url: data.ticker_url, ticker_password: data.ticker_password,