From 90e1b54a1b3a7833cabffc9bcba509b3ef9db397 Mon Sep 17 00:00:00 2001 From: Frank Weinberg Date: Thu, 8 Sep 2022 19:11:58 +0200 Subject: [PATCH] Add some diagnostic info for stats export --- html/components/igrf-tab.css | 1 + html/components/igrf-tab.js | 17 ++++++++++ html/components/settings-tab.css | 2 ++ html/components/settings-tab.js | 23 ++++++++----- .../scoreboard/core/admin/SettingsImpl.java | 11 ++++--- .../scoreboard/core/game/GameImpl.java | 33 +++++++++++++++++++ .../scoreboard/core/interfaces/Game.java | 2 ++ .../core/interfaces/ScoreBoard.java | 4 +++ 8 files changed, 80 insertions(+), 13 deletions(-) diff --git a/html/components/igrf-tab.css b/html/components/igrf-tab.css index 2b67e234d..c62beb143 100644 --- a/html/components/igrf-tab.css +++ b/html/components/igrf-tab.css @@ -14,6 +14,7 @@ #Igrf .Variables td { text-align: left; width: 50%; } #Igrf tr.Files > td { background: #ddd; } #Igrf tr.Files .ui-button { margin: 1px 5px; } +#Igrf tr.Files .Warning { color: red; } #Igrf .Expulsions th { font-size: 150%; } #Igrf .Expulsions table { width: 100%; } diff --git a/html/components/igrf-tab.js b/html/components/igrf-tab.js index d9ab6c3fc..b0e60fe11 100644 --- a/html/components/igrf-tab.js +++ b/html/components/igrf-tab.js @@ -67,17 +67,34 @@ function createIgrfTab(tab, gameId) { .button() .appendTo(table.find('tr.Files>td:eq(0)')); var jsonButton = $('').text('Download JSON').button().appendTo(table.find('tr.Files>td:eq(0)')); + var noJson = $('').text(' No JSON yet ').appendTo(table.find('tr.Files>td:eq(0)')); var xlsxButton = $('').text('Download Statsbook').button().appendTo(table.find('tr.Files>td:eq(0)')); + var noXlsx = $('').text(' No Statsbook yet ').appendTo(table.find('tr.Files>td:eq(0)')); $('').text(' Last Updated: ').appendTo(table.find('tr.Files>td:eq(0)')); var downloadDate = $('').appendTo(table.find('tr.Files>td:eq(0)')); + var noBlankStatsbookWarning = $('') + .text(' Blank Statsbook not set up.') + .addClass('Warning') + .appendTo(table.find('tr.Files>td:eq(0)')); WS.Register(gamePrefix + '.Filename', function (k, v) { jsonButton.attr('href', '/game-data/json/' + v + '.json'); xlsxButton.attr('href', '/game-data/xlsx/' + v + '.xlsx'); }); + WS.Register(gamePrefix + '.JsonExists', function (k, v) { + jsonButton.toggle(isTrue(v)); + noJson.toggle(!isTrue(v)); + }); + WS.Register(gamePrefix + '.StatsbookExists', function (k, v) { + xlsxButton.toggle(isTrue(v)); + noXlsx.toggle(!isTrue(v)); + }); WS.Register(gamePrefix + '.LastFileUpdate', function (k, v) { downloadDate.text(v); }); + WS.Register('ScoreBoard.BlankStatsbookFound', function (k, v) { + noBlankStatsbookWarning.toggle(!isTrue(v)); + }); $('').text('Tournament: ').appendTo(table.find('tr.Event>td:eq(0)')); WSControl(gamePrefix + '.EventInfo(Tournament)', $('')).appendTo(table.find('tr.Event>td:eq(0)')); diff --git a/html/components/settings-tab.css b/html/components/settings-tab.css index 62ea24745..7581543f1 100644 --- a/html/components/settings-tab.css +++ b/html/components/settings-tab.css @@ -12,6 +12,8 @@ #ScoreBoardSettings>tr>td.ViewFrames iframe { width: 100%; height: 300px; } #ScoreBoardSettings .EndSubSection>td { padding-bottom: 10px; } #ScoreBoardSettings .ui-button.ui-state-active, #ScoreBoardSettings .Active { background: #3f3; color: #000; } +#ScoreBoardSettings .StatsFile.Readable::after { content: "✓"; color: green; font-size: 150%; } +#ScoreBoardSettings .StatsFile:not(.Readable)::after { content: "❌"; color: red; } /* Intermission Control Dialog */ table.IntermissionControlDialog { width: 100%; border-spacing: 0px; } diff --git a/html/components/settings-tab.js b/html/components/settings-tab.js index 483074330..432912b29 100644 --- a/html/components/settings-tab.js +++ b/html/components/settings-tab.js @@ -125,6 +125,9 @@ function createNonViewRows(table) { var statsbookFile = $('').add( WSControl('ScoreBoard.Settings.Setting(ScoreBoard.Stats.InputFile)', $('')) ); + WS.Register('ScoreBoard.BlankStatsbookFound', function (k, v) { + statsbookFile.parent().addClass('StatsFile').toggleClass('Readable', isTrue(v)); + }); var teamDisplayName = $('').add( WSControl( 'ScoreBoard.Settings.Setting(ScoreBoard.Teams.DisplayName)', @@ -258,13 +261,15 @@ function createScoreBoardViewPreviewRows(table, type) { .attr('ApplyPreview', 'Image'); var imageScaleSelect = $('').add( - WSControl( - 'ScoreBoard.Settings.Setting(ScoreBoard.' + type + '_ImageScaling)', - $('') + .attr('ApplyPreview', 'ImageScaling') + .append('') + .append('') + .append('') + ) + ); var videoViewSelect = $('') .add(mediaSelect('ScoreBoard.Settings.Setting(ScoreBoard.' + type + '_Video)', 'videos', 'fullscreen', 'Video')) @@ -277,7 +282,9 @@ function createScoreBoardViewPreviewRows(table, type) { .attr('ApplyPreview', 'VideoScaling') .append('') .append('') - .append(''))); + .append('') + ) + ); var customPageViewSelect = $('') .add(mediaSelect('ScoreBoard.Settings.Setting(ScoreBoard.' + type + '_CustomHtml)', 'custom', 'view', 'Page')) diff --git a/src/com/carolinarollergirls/scoreboard/core/admin/SettingsImpl.java b/src/com/carolinarollergirls/scoreboard/core/admin/SettingsImpl.java index f3f949e55..2a570bbd2 100644 --- a/src/com/carolinarollergirls/scoreboard/core/admin/SettingsImpl.java +++ b/src/com/carolinarollergirls/scoreboard/core/admin/SettingsImpl.java @@ -1,5 +1,7 @@ package com.carolinarollergirls.scoreboard.core.admin; +import java.nio.file.Paths; + import com.carolinarollergirls.scoreboard.core.interfaces.Clock; import com.carolinarollergirls.scoreboard.core.interfaces.Game; import com.carolinarollergirls.scoreboard.core.interfaces.ScoreBoard; @@ -11,9 +13,6 @@ import com.carolinarollergirls.scoreboard.utils.StatsbookExporter; import com.carolinarollergirls.scoreboard.utils.ValWithId; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - public class SettingsImpl extends ScoreBoardEventProviderImpl implements Settings { public SettingsImpl(ScoreBoard s) { super(s, "", ScoreBoard.SETTINGS); @@ -23,8 +22,10 @@ public SettingsImpl(ScoreBoard s) { @Override protected void itemAdded(Child prop, ValueWithId item, Source source) { - if (item != null && ScoreBoard.SETTING_STATSBOOK_INPUT.equals(item.getId()) && scoreBoard.isInitialLoadDone()) { - StatsbookExporter.preload(item.getValue()); + if (item != null && ScoreBoard.SETTING_STATSBOOK_INPUT.equals(item.getId())) { + boolean found = Paths.get(item.getValue()).toFile().canRead(); + getScoreBoard().set(ScoreBoard.BLANK_STATSBOOK_FOUND, found); + if (found && scoreBoard.isInitialLoadDone()) { StatsbookExporter.preload(item.getValue()); } } } diff --git a/src/com/carolinarollergirls/scoreboard/core/game/GameImpl.java b/src/com/carolinarollergirls/scoreboard/core/game/GameImpl.java index 998b8279a..6fcc141de 100644 --- a/src/com/carolinarollergirls/scoreboard/core/game/GameImpl.java +++ b/src/com/carolinarollergirls/scoreboard/core/game/GameImpl.java @@ -17,6 +17,8 @@ import com.carolinarollergirls.scoreboard.core.interfaces.Expulsion; import com.carolinarollergirls.scoreboard.core.interfaces.Game; import com.carolinarollergirls.scoreboard.core.interfaces.Jam; +import com.carolinarollergirls.scoreboard.core.interfaces.Media.MediaFile; +import com.carolinarollergirls.scoreboard.core.interfaces.Media.MediaType; import com.carolinarollergirls.scoreboard.core.interfaces.Penalty; import com.carolinarollergirls.scoreboard.core.interfaces.Period; import com.carolinarollergirls.scoreboard.core.interfaces.Period.PeriodSnapshot; @@ -196,6 +198,32 @@ public void scoreBoardChange(ScoreBoardEvent event) { refreshRuleset((Ruleset) event.getProvider()); } })); + + // handle file updates + scoreBoard.getMedia() + .getFormat("game-data") + .getType("json") + .addScoreBoardListener( + new ConditionalScoreBoardListener<>(MediaType.class, MediaType.FILE, new ScoreBoardListener() { + @Override + public void scoreBoardChange(ScoreBoardEvent event) { + if (((MediaFile) event.getValue()).getId().equals(getFilename() + ".json")) { + set(JSON_EXISTS, true); + } + } + })); + scoreBoard.getMedia() + .getFormat("game-data") + .getType("xlsx") + .addScoreBoardListener( + new ConditionalScoreBoardListener<>(MediaType.class, MediaType.FILE, new ScoreBoardListener() { + @Override + public void scoreBoardChange(ScoreBoardEvent event) { + if (((MediaFile) event.getValue()).getId().equals(getFilename() + ".xlsx")) { + set(STATSBOOK_EXISTS, true); + } + } + })); } @Override @@ -251,6 +279,10 @@ protected Object computeValue(Value prop, Object value, Object last, Source s } else { return checkNewFilename(newName); } + } else if (prop == STATSBOOK_EXISTS) { + return BasePath.get().toPath().resolve("html/game-data/xlsx/" + getFilename() + ".xlsx").toFile().canRead(); + } else if (prop == JSON_EXISTS) { + return BasePath.get().toPath().resolve("html/game-data/json/" + getFilename() + ".json").toFile().canRead(); } else if (prop == RULESET && value != null && !source.isFile()) { if (get(STATE) != State.PREPARED && source == Source.WS) { return null; // no change after game start @@ -389,6 +421,7 @@ public ScoreBoardEventProvider create(Child p if (prop == NSO) { return new OfficialImpl(this, id, NSO); } if (prop == REF) { return new OfficialImpl(this, id, REF); } if (prop == EXPULSION && source.isFile()) { + if (elements.get(Penalty.class) == null) { return null; } Penalty p = (Penalty) elements.get(Penalty.class).get(id); if (p != null) { Expulsion e = get(EXPULSION, p.getId()); diff --git a/src/com/carolinarollergirls/scoreboard/core/interfaces/Game.java b/src/com/carolinarollergirls/scoreboard/core/interfaces/Game.java index 560432235..2b04a5c73 100644 --- a/src/com/carolinarollergirls/scoreboard/core/interfaces/Game.java +++ b/src/com/carolinarollergirls/scoreboard/core/interfaces/Game.java @@ -124,6 +124,8 @@ public static State fromString(String s) { public static final Value FILENAME = new Value<>(String.class, "Filename", "STATS-0000-00-00_Team1_vs_Team_2", props); public static final Value LAST_FILE_UPDATE = new Value<>(String.class, "LastFileUpdate", "Never", props); + public static final Value STATSBOOK_EXISTS = new Value<>(Boolean.class, "StatsbookExists", false, props); + public static final Value JSON_EXISTS = new Value<>(Boolean.class, "JsonExists", false, props); public static final Child CLOCK = new Child<>(Clock.class, "Clock", props); public static final Child TEAM = new Child<>(Team.class, "Team", props); diff --git a/src/com/carolinarollergirls/scoreboard/core/interfaces/ScoreBoard.java b/src/com/carolinarollergirls/scoreboard/core/interfaces/ScoreBoard.java index c703dea7a..49c103cda 100644 --- a/src/com/carolinarollergirls/scoreboard/core/interfaces/ScoreBoard.java +++ b/src/com/carolinarollergirls/scoreboard/core/interfaces/ScoreBoard.java @@ -6,6 +6,7 @@ import com.carolinarollergirls.scoreboard.event.Child; import com.carolinarollergirls.scoreboard.event.Property; import com.carolinarollergirls.scoreboard.event.ScoreBoardEventProvider; +import com.carolinarollergirls.scoreboard.event.Value; import com.carolinarollergirls.scoreboard.json.JSONStateManager; import com.carolinarollergirls.scoreboard.utils.ValWithId; @@ -36,6 +37,9 @@ public interface ScoreBoard extends ScoreBoardEventProvider { public static Collection> props = new ArrayList<>(); + public static final Value BLANK_STATSBOOK_FOUND = + new Value<>(Boolean.class, "BlankStatsbookFound", false, props); + public static final Child VERSION = new Child<>(ValWithId.class, "Version", props); public static final Child SETTINGS = new Child<>(Settings.class, "Settings", props); public static final Child TWITTER = new Child<>(Twitter.class, "Twitter", props);