From 79799bf1c2778fb656c1d15e94567e4cd14f2dd8 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Fri, 29 Sep 2023 15:37:18 -0600 Subject: [PATCH] State: add "Enabeled", remove "Messages" Fixes #164 --- CHANGELOG.md | 2 ++ cmd/mothd/httpd_test.go | 4 ++-- cmd/mothd/server.go | 6 +++--- cmd/mothd/server_test.go | 4 ---- cmd/mothd/state.go | 33 ++++++++++----------------------- cmd/mothd/state_test.go | 22 +++++++++++----------- docs/api.md | 2 -- theme/index.mjs | 4 +--- theme/moth.mjs | 6 ++---- 9 files changed, 31 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fd80c8..69eba71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Reworked the built-in theme - [moth.mjs](theme/moth.mjs) is now the standard MOTH library for ECMAScript - Devel mode no longer accepts an empty team ID +- messages.html moved into theme +- Exported state now includes "Enabled" boolean ## [v4.4.9] - 2022-05-12 ### Changed diff --git a/cmd/mothd/httpd_test.go b/cmd/mothd/httpd_test.go index 28e7076..1f7d22d 100644 --- a/cmd/mothd/httpd_test.go +++ b/cmd/mothd/httpd_test.go @@ -45,7 +45,7 @@ func TestHttpd(t *testing.T) { if r := hs.TestRequest("/state", nil); r.Result().StatusCode != 200 { t.Error(r.Result()) - } else if r.Body.String() != `{"Config":{"Devel":false},"Messages":"messages.html","TeamNames":{},"PointsLog":[],"Puzzles":{}}` { + } else if r.Body.String() != `{"Config":{"Devel":false},"TeamNames":{},"PointsLog":[],"Puzzles":{}}` { t.Error("Unexpected state", r.Body.String()) } @@ -71,7 +71,7 @@ func TestHttpd(t *testing.T) { if r := hs.TestRequest("/state", nil); r.Result().StatusCode != 200 { t.Error(r.Result()) - } else if r.Body.String() != `{"Config":{"Devel":false},"Messages":"messages.html","TeamNames":{"self":"GoTeam"},"PointsLog":[],"Puzzles":{"pategory":[1]}}` { + } else if r.Body.String() != `{"Config":{"Devel":false},"TeamNames":{"self":"GoTeam"},"PointsLog":[],"Puzzles":{"pategory":[1]}}` { t.Error("Unexpected state", r.Body.String()) } diff --git a/cmd/mothd/server.go b/cmd/mothd/server.go index 52e2400..f689089 100644 --- a/cmd/mothd/server.go +++ b/cmd/mothd/server.go @@ -30,7 +30,7 @@ type Configuration struct { // StateExport is given to clients requesting the current state. type StateExport struct { Config Configuration - Messages string + Enabled bool TeamNames map[string]string PointsLog award.List Puzzles map[string][]int @@ -53,7 +53,7 @@ type ThemeProvider interface { // StateProvider defines what's required to provide MOTH state. type StateProvider interface { - Messages() string + Enabled() bool PointsLog() award.List TeamName(teamID string) (string, error) SetTeamName(teamID, teamName string) error @@ -194,7 +194,7 @@ func (mh *MothRequestHandler) exportStateIfRegistered(forceRegistered bool) *Sta teamName, err := mh.State.TeamName(mh.teamID) registered := forceRegistered || mh.Config.Devel || (err == nil) - export.Messages = mh.State.Messages() + export.Enabled = mh.State.Enabled() export.TeamNames = make(map[string]string) // Anonymize team IDs in points log, and write out team names diff --git a/cmd/mothd/server_test.go b/cmd/mothd/server_test.go index 828d08b..9de5d1b 100644 --- a/cmd/mothd/server_test.go +++ b/cmd/mothd/server_test.go @@ -22,7 +22,6 @@ func NewTestServer() TestServer { state := NewTestState() afero.WriteFile(state, "teamids.txt", []byte("teamID\n"), 0644) - afero.WriteFile(state, "messages.html", []byte("messages.html"), 0644) state.refresh() theme := NewTestTheme() @@ -101,9 +100,6 @@ func TestProdServer(t *testing.T) { if len(es.Puzzles) != 1 { t.Error("Puzzle categories wrong length", len(es.Puzzles)) } - if es.Messages != "messages.html" { - t.Error("Messages has wrong contents") - } if len(es.PointsLog) != 0 { t.Error("Points log not empty") } diff --git a/cmd/mothd/state.go b/cmd/mothd/state.go index d9da27b..a7bd870 100644 --- a/cmd/mothd/state.go +++ b/cmd/mothd/state.go @@ -37,7 +37,7 @@ type State struct { afero.Fs // Enabled tracks whether the current State system is processing updates - Enabled bool + enabled bool enabledWhy string refreshNow chan bool @@ -49,7 +49,6 @@ type State struct { teamNamesLastChange time.Time teamNames map[string]string pointsLog award.List - messages string lock sync.RWMutex } @@ -57,7 +56,7 @@ type State struct { func NewState(fs afero.Fs) *State { s := &State{ Fs: fs, - Enabled: true, + enabled: true, refreshNow: make(chan bool, 5), eventStream: make(chan []string, 80), @@ -117,11 +116,11 @@ func (s *State) updateEnabled() { } } - if (nextEnabled != s.Enabled) || (why != s.enabledWhy) { - s.Enabled = nextEnabled + if (nextEnabled != s.enabled) || (why != s.enabledWhy) { + s.enabled = nextEnabled s.enabledWhy = why - log.Printf("Setting enabled=%v: %s", s.Enabled, s.enabledWhy) - if s.Enabled { + log.Printf("Setting enabled=%v: %s", s.enabled, s.enabledWhy) + if s.enabled { s.LogEvent("enabled", "", "", 0, s.enabledWhy) } else { s.LogEvent("disabled", "", "", 0, s.enabledWhy) @@ -193,11 +192,9 @@ func (s *State) PointsLog() award.List { return ret } -// Messages retrieves the current messages. -func (s *State) Messages() string { - s.lock.RLock() // It's not clear to me that this actually needs to happen - defer s.lock.RUnlock() - return s.messages +// Enabled returns true if the server is in "enabled" state +func (s *State) Enabled() bool { + return s.enabled } // AwardPoints gives points to teamID in category. @@ -313,7 +310,6 @@ func (s *State) maybeInitialize() { s.Remove("hours.txt") s.Remove("points.log") s.Remove("events.csv") - s.Remove("messages.html") s.Remove("mothd.log") s.RemoveAll("points.tmp") s.RemoveAll("points.new") @@ -369,11 +365,6 @@ func (s *State) maybeInitialize() { f.Close() } - if f, err := s.Create("messages.html"); err == nil { - fmt.Fprintln(f, "") - f.Close() - } - if f, err := s.Create("points.log"); err == nil { f.Close() } @@ -465,16 +456,12 @@ func (s *State) updateCaches() { } } } - - if bMessages, err := afero.ReadFile(s, "messages.html"); err == nil { - s.messages = string(bMessages) - } } func (s *State) refresh() { s.maybeInitialize() s.updateEnabled() - if s.Enabled { + if s.enabled { s.collectPoints() } s.updateCaches() diff --git a/cmd/mothd/state_test.go b/cmd/mothd/state_test.go index ed7c9e2..55e29bc 100644 --- a/cmd/mothd/state_test.go +++ b/cmd/mothd/state_test.go @@ -185,7 +185,7 @@ func TestStateDisabled(t *testing.T) { s := NewTestState() s.refresh() - if !s.Enabled { + if !s.Enabled() { t.Error("Brand new state is disabled") } @@ -195,35 +195,35 @@ func TestStateDisabled(t *testing.T) { } defer hoursFile.Close() s.refresh() - if !s.Enabled { + if !s.Enabled() { t.Error("Empty hours.txt not enabled") } fmt.Fprintln(hoursFile, "- 1970-01-01T01:01:01Z") hoursFile.Sync() s.refresh() - if s.Enabled { + if s.Enabled() { t.Error("1970-01-01") } fmt.Fprintln(hoursFile, "+ 1970-01-02 01:01:01+05:00") hoursFile.Sync() s.refresh() - if !s.Enabled { + if !s.Enabled() { t.Error("1970-01-02") } fmt.Fprintln(hoursFile, "-") hoursFile.Sync() s.refresh() - if s.Enabled { + if s.Enabled() { t.Error("bare -") } fmt.Fprintln(hoursFile, "+") hoursFile.Sync() s.refresh() - if !s.Enabled { + if !s.Enabled() { t.Error("bare +") } @@ -231,21 +231,21 @@ func TestStateDisabled(t *testing.T) { fmt.Fprintln(hoursFile, "# Comment") hoursFile.Sync() s.refresh() - if !s.Enabled { + if !s.Enabled() { t.Error("Comment") } fmt.Fprintln(hoursFile, "intentional parse error") hoursFile.Sync() s.refresh() - if !s.Enabled { + if !s.Enabled() { t.Error("intentional parse error") } fmt.Fprintln(hoursFile, "- 1980-01-01T01:01:01Z") hoursFile.Sync() s.refresh() - if s.Enabled { + if s.Enabled() { t.Error("1980-01-01") } @@ -253,13 +253,13 @@ func TestStateDisabled(t *testing.T) { t.Error(err) } s.refresh() - if !s.Enabled { + if !s.Enabled() { t.Error("Removing `hours.txt` disabled event") } s.Remove("initialized") s.refresh() - if !s.Enabled { + if !s.Enabled() { t.Error("Re-initializing didn't start event") } } diff --git a/docs/api.md b/docs/api.md index 45ee0c5..803a83b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -53,7 +53,6 @@ Returns the current Moth event state as a JSON object. "Config": { "Devel": false // true means this is a development server }, - "Messages: "HTML to be rendered as broadcast messages", "TeamNames": { "self": "Requesting team name", // Only if regestered team id is a provided "0": "Team 1 Name", @@ -91,7 +90,6 @@ Content-Type: application/json {"Config": {"Devel":false}, - "Messages":"

Welcome to the event!

Event ends at 19:00!

", "TeamNames":{ "0":"Mike and Jack", "12":"Team 2", diff --git a/theme/index.mjs b/theme/index.mjs index 4b91d5e..f3864e9 100644 --- a/theme/index.mjs +++ b/theme/index.mjs @@ -167,9 +167,7 @@ class App { } function init() { - window.app = { - server: new App() - } + window.app = new App() } common.WhenDOMLoaded(init) diff --git a/theme/moth.mjs b/theme/moth.mjs index dd23081..9351e3a 100644 --- a/theme/moth.mjs +++ b/theme/moth.mjs @@ -367,10 +367,8 @@ class State { Devel: obj.Config.Devel, } - /** Global messages, in HTML - * @type {string} - */ - this.Messages = obj.Messages + /** True if the server is in enabled state */ + this.Enabled = obj.Enabled /** Map from Team ID to Team Name * @type {Object.}