diff --git a/CHANGELOG.md b/CHANGELOG.md
index e12853c..9fc8422 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- We are now using djb2xor instead of sha256 to hash puzzle answers
- Lots of work on 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
## [v4.4.9] - 2022-05-12
### Changed
diff --git a/cmd/mothd/httpd_test.go b/cmd/mothd/httpd_test.go
index f77e044..28e7076 100644
--- a/cmd/mothd/httpd_test.go
+++ b/cmd/mothd/httpd_test.go
@@ -128,7 +128,7 @@ func TestHttpd(t *testing.T) {
if r := hs.TestRequest("/answer", map[string]string{"cat": "pategory", "points": "1", "answer": "answer123"}); r.Result().StatusCode != 200 {
t.Error(r.Result())
- } else if r.Body.String() != `{"status":"fail","data":{"short":"not accepted","description":"error awarding points: points already awarded to this team in this category"}}` {
+ } else if r.Body.String() != `{"status":"fail","data":{"short":"not accepted","description":"points already awarded to this team in this category"}}` {
t.Error("Unexpected body", r.Body.String())
}
}
diff --git a/cmd/mothd/server.go b/cmd/mothd/server.go
index 5cf6582..52e2400 100644
--- a/cmd/mothd/server.go
+++ b/cmd/mothd/server.go
@@ -156,7 +156,7 @@ func (mh *MothRequestHandler) CheckAnswer(cat string, points int, answer string)
return fmt.Errorf("invalid team ID")
}
if err := mh.State.AwardPoints(mh.teamID, cat, points); err != nil {
- return fmt.Errorf("error awarding points: %s", err)
+ return err
}
return nil
diff --git a/theme/basic.css b/theme/basic.css
index 9b28c51..90be911 100644
--- a/theme/basic.css
+++ b/theme/basic.css
@@ -75,6 +75,9 @@ input {
.category h2 {
margin: 0 0.2em;
}
+.category .solved {
+ text-decoration: line-through;
+}
nav ul, .category ul {
margin: 0;
padding: 0.2em 1em;
diff --git a/theme/common.mjs b/theme/common.mjs
index 3b8d0c2..c797475 100644
--- a/theme/common.mjs
+++ b/theme/common.mjs
@@ -34,10 +34,30 @@ function WhenDOMLoaded(cb) {
}
}
+/**
+ * Interprets a String as a Boolean.
+ *
+ * Values like "no" or "disabled" to mean false here.
+ *
+ * @param {String} s
+ * @returns {Boolean}
+ */
+function Truthy(s) {
+ switch (s.toLowerCase()) {
+ case "disabled":
+ case "no":
+ case "off":
+ case "false":
+ return false
+ }
+ return true
+}
+
export {
Millisecond,
Second,
Minute,
Toast,
WhenDOMLoaded,
+ Truthy,
}
diff --git a/theme/config.json b/theme/config.json
new file mode 100644
index 0000000..9f39211
--- /dev/null
+++ b/theme/config.json
@@ -0,0 +1,4 @@
+{
+ "TrackSolved": true,
+ "__sentry__": "this is here so you don't have to remember to take the comma off the last item"
+}
\ No newline at end of file
diff --git a/theme/index.html b/theme/index.html
index 4457033..ee6853b 100644
--- a/theme/index.html
+++ b/theme/index.html
@@ -22,9 +22,19 @@
-
-
+
+
+
+ Solved puzzle tracking: disabled.
+
+
+ Your team's Incident Coordinator can help coordinate team activity.
+
+
+
+
+