Everything but puzzle content serving

This commit is contained in:
Neale Pickett 2018-09-19 03:29:05 +00:00
parent b4d8dc5b74
commit a9f8cba6f9
7 changed files with 50 additions and 18 deletions

View File

@ -32,6 +32,10 @@ input {
padding: 0.6em; padding: 0.6em;
margin: 0.2em; margin: 0.2em;
} }
#scoreboard .category {
border: solid white 1px;
display: inline-block;
}
nav { nav {
border: solid black 2px; border: solid black 2px;
} }

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Open Puzzles</title> <title>Scoreboard</title>
<link rel="stylesheet" href="basic.css"> <link rel="stylesheet" href="basic.css">
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<link rel="icon" href="res/icon.svg" type="image/svg+xml"> <link rel="icon" href="res/icon.svg" type="image/svg+xml">
@ -97,6 +97,7 @@ function scoreboard(element, continuous) {
var width = maxWidth * catPct; var width = maxWidth * catPct;
var bar = document.createElement("span"); var bar = document.createElement("span");
bar.classList.add("category");
bar.classList.add("cat" + ncat); bar.classList.add("cat" + ncat);
bar.style.width = width + "%"; bar.style.width = width + "%";
bar.textContent = category + ": " + catTeam; bar.textContent = category + ": " + catTeam;

View File

@ -17,7 +17,7 @@ type Award struct {
func ParseAward(s string) (*Award, error) { func ParseAward(s string) (*Award, error) {
ret := Award{} ret := Award{}
s = strings.Trim(s, " \t\n") s = strings.TrimSpace(s)
var whenEpoch int64 var whenEpoch int64

View File

@ -5,11 +5,9 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"log" "log"
"net/http" "net/http"
"os" "os"
"rand"
"strconv" "strconv"
"strings" "strings"
) )
@ -287,19 +285,37 @@ func (ctx Instance) puzzlesHandler(w http.ResponseWriter, req *http.Request) {
} }
func (ctx Instance) pointsHandler(w http.ResponseWriter, req *http.Request) { func (ctx Instance) pointsHandler(w http.ResponseWriter, req *http.Request) {
plog := ctx.PointsLog() var ret struct {
jlog, err := json.Marshal(plog) Teams map[string]string `json:"teams"`
Points []*Award `json:"points"`
}
ret.Teams = map[string]string{}
ret.Points = ctx.PointsLog()
teamNumbersById := map[string]int{}
for nr, a := range ret.Points {
teamNumber, ok := teamNumbersById[a.TeamId]
if !ok {
teamName, err := ctx.TeamName(a.TeamId)
if err != nil {
teamName = "[unregistered]"
}
teamNumber = nr
teamNumbersById[a.TeamId] = teamNumber
ret.Teams[strconv.FormatInt(int64(teamNumber), 16)] = teamName
}
a.TeamId = strconv.FormatInt(int64(teamNumber), 16)
}
jret, err := json.Marshal(ret)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
// XXX: go through plog, building an array of teams, so we can anonymize team IDs
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write(jret)
w.Write(jlog)
} }
func (ctx Instance) staticHandler(w http.ResponseWriter, req *http.Request) { func (ctx Instance) staticHandler(w http.ResponseWriter, req *http.Request) {

View File

@ -159,3 +159,9 @@ func (ctx *Instance) OpenCategoryFile(category string, parts ...string) (io.Read
f, err := mb.Open(filename) f, err := mb.Open(filename)
return f, err return f, err
} }
func (ctx *Instance) TeamName(teamId string) (string, error) {
teamNameBytes, err := ioutil.ReadFile(ctx.StatePath("teams", teamId))
teamName := strings.TrimSpace(string(teamNameBytes))
return teamName, err
}

View File

@ -34,6 +34,16 @@ func (ctx *Instance) Tidy() {
} }
} }
// Refresh all current categories
for categoryName, mb := range ctx.Categories {
if err := mb.Refresh(); err != nil {
// Backing file vanished: remove this category
log.Printf("Removing category: %s: %s", categoryName, err)
mb.Close()
delete(ctx.Categories, categoryName)
}
}
// Any new categories? // Any new categories?
files, err := ioutil.ReadDir(ctx.MothballPath()) files, err := ioutil.ReadDir(ctx.MothballPath())
if err != nil { if err != nil {
@ -58,9 +68,6 @@ func (ctx *Instance) Tidy() {
} }
} }
// Any old categories?
log.Print("XXX: Check for and reap old categories")
ctx.CollectPoints() ctx.CollectPoints()
} }

View File

@ -60,10 +60,10 @@ func ShowHtml(w http.ResponseWriter, status Status, title string, body string) {
fmt.Fprintf(w, "<html><head>") fmt.Fprintf(w, "<html><head>")
fmt.Fprintf(w, "<title>%s</title>", title) fmt.Fprintf(w, "<title>%s</title>", title)
fmt.Fprintf(w, "<link rel=\"stylesheet\" href=\"basic.css\">") fmt.Fprintf(w, "<link rel=\"stylesheet\" href=\"basic.css\">")
fmt.Fprintf(w, "<meta name=\"viewport\" content=\"width=device-width\"></head>") fmt.Fprintf(w, "<meta name=\"viewport\" content=\"width=device-width\">")
fmt.Fprintf(w, "<link rel=\"icon\" href=\"res/icon.svg\" type=\"image/svg+xml\">") fmt.Fprintf(w, "<link rel=\"icon\" href=\"res/icon.svg\" type=\"image/svg+xml\">")
fmt.Fprintf(w, "<link rel=\"icon\" href=\"res/icon.png\" type=\"image/png\">") fmt.Fprintf(w, "<link rel=\"icon\" href=\"res/icon.png\" type=\"image/png\">")
fmt.Fprintf(w, "<body><h1 class=\"%s\">%s</h1>", statusStr, title) fmt.Fprintf(w, "</head><body><h1 class=\"%s\">%s</h1>", statusStr, title)
fmt.Fprintf(w, "<section>%s</section>", body) fmt.Fprintf(w, "<section>%s</section>", body)
fmt.Fprintf(w, "<nav>") fmt.Fprintf(w, "<nav>")
fmt.Fprintf(w, "<ul>") fmt.Fprintf(w, "<ul>")
@ -159,9 +159,7 @@ func staticScoreboard(w http.ResponseWriter) {
w, Success, w, Success,
"Scoreboard", "Scoreboard",
` `
<section>
<div id="scoreboard"></div> <div id="scoreboard"></div>
</section>
<script> <script>
function loadJSON(url, callback) { function loadJSON(url, callback) {
function loaded(e) { function loaded(e) {