Add flags and more robust functionality than "until" provided

This commit is contained in:
Neale Pickett 2019-11-24 15:58:43 -07:00
parent 309432d05c
commit 65f810539a
4 changed files with 96 additions and 33 deletions

View File

@ -25,4 +25,4 @@ func (c *Component) path(parts ...string) string {
func (c *Component) Run(updateInterval time.Duration) { func (c *Component) Run(updateInterval time.Duration) {
// Stub! // Stub!
} }

View File

@ -1,24 +1,50 @@
package main package main
import ( import (
"time" "github.com/namsral/flag"
"log" "log"
"time"
) )
func main() { func main() {
log.Print("Started") log.Print("Started")
theme := NewTheme("../../theme") themePath := flag.String(
state := NewState("../../state") "theme",
puzzles := NewMothballs("../../mothballs") "theme",
"Path to theme files",
)
interval := 2 * time.Second statePath := flag.String(
go theme.Run(interval) "state",
go state.Run(interval) "state",
go puzzles.Run(interval) "Path to state files",
)
puzzlePath := flag.String(
"mothballs",
"mothballs",
"Path to mothballs to host",
)
refreshInterval := flag.Duration(
"refresh",
2*time.Second,
"Duration between maintenance tasks",
)
bindStr := flag.String(
"bind",
":8000",
"Bind [host]:port for HTTP service",
)
theme := NewTheme(*themePath)
state := NewState(*statePath)
puzzles := NewMothballs(*puzzlePath)
go theme.Run(*refreshInterval)
go state.Run(*refreshInterval)
go puzzles.Run(*refreshInterval)
log.Println("I would be binding to", *bindStr)
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
log.Print(state.Export("")) log.Print(state.Export(""))
time.Sleep(19 * time.Second) time.Sleep(19 * time.Second)
} }

View File

@ -1,10 +1,10 @@
package main package main
import ( import (
"time"
"io/ioutil" "io/ioutil"
"strings"
"log" "log"
"strings"
"time"
) )
type Mothballs struct { type Mothballs struct {

View File

@ -34,6 +34,7 @@ type StateExport struct {
// The only thing State methods need to know is the path to the state directory. // The only thing State methods need to know is the path to the state directory.
type State struct { type State struct {
Component Component
Enabled bool
update chan bool update chan bool
} }
@ -42,32 +43,60 @@ func NewState(baseDir string) *State {
Component: Component{ Component: Component{
baseDir: baseDir, baseDir: baseDir,
}, },
Enabled: true,
update: make(chan bool, 10), update: make(chan bool, 10),
} }
} }
// Check a few things to see if this state directory is "enabled". // Check a few things to see if this state directory is "enabled".
func (s *State) Enabled() bool { func (s *State) UpdateEnabled() {
if _, err := os.Stat(s.path("enabled")); os.IsNotExist(err) { if _, err := os.Stat(s.path("enabled")); os.IsNotExist(err) {
s.Enabled = false
log.Print("Suspended: enabled file missing") log.Print("Suspended: enabled file missing")
return false return
} }
untilspec, err := ioutil.ReadFile(s.path("until")) nextEnabled := true
if err == nil { untilFile, err := os.Open(s.path("hours"))
untilspecs := strings.TrimSpace(string(untilspec)) if err != nil {
until, err := time.Parse(time.RFC3339, untilspecs) return
}
defer untilFile.Close()
scanner := bufio.NewScanner(untilFile)
for scanner.Scan() {
line := scanner.Text()
if len(line) < 1 {
continue
}
thisEnabled := true
switch line[0] {
case '+':
thisEnabled = true
line = line[1:]
case '-':
thisEnabled = false
line = line[1:]
case '#':
continue
default:
log.Printf("Misformatted line in hours file")
}
line = strings.TrimSpace(line)
until, err := time.Parse(time.RFC3339, line)
if err != nil { if err != nil {
log.Printf("Suspended: Unparseable until date: %s", untilspec) log.Printf("Suspended: Unparseable until date: %s", line)
return false continue
} }
if until.Before(time.Now()) { if until.Before(time.Now()) {
log.Print("Suspended: until time reached, suspending maintenance") nextEnabled = thisEnabled
return false
} }
} }
if nextEnabled != s.Enabled {
return true s.Enabled = nextEnabled
log.Println("Setting enabled to", s.Enabled, "based on hours file")
}
} }
// Returns team name given a team ID. // Returns team name given a team ID.
@ -291,17 +320,23 @@ func (s *State) maybeInitialize() {
// Create some files // Create some files
ioutil.WriteFile( ioutil.WriteFile(
s.path("initialized"), s.path("initialized"),
[]byte("Remove this file to re-initialized the contest\n"), []byte("state/initialized: remove to re-initialize the contest\n"),
0644, 0644,
) )
ioutil.WriteFile( ioutil.WriteFile(
s.path("enabled"), s.path("enabled"),
[]byte("Remove this file to suspend the contest\n"), []byte("state/enabled: remove to suspend the contest\n"),
0644, 0644,
) )
ioutil.WriteFile( ioutil.WriteFile(
s.path("until"), s.path("hours"),
[]byte("3009-10-31T00:00:00Z\n"), []byte(
"# state/hours: when the contest is enabled\n"+
"# Lines starting with + enable, with - disable.\n"+
"\n"+
"+ 1970-01-01T00:00:00Z\n"+
"- 3019-10-31T00:00:00Z\n",
),
0644, 0644,
) )
ioutil.WriteFile( ioutil.WriteFile(
@ -319,10 +354,12 @@ func (s *State) maybeInitialize() {
func (s *State) Run(updateInterval time.Duration) { func (s *State) Run(updateInterval time.Duration) {
for { for {
s.maybeInitialize() s.maybeInitialize()
if s.Enabled() { s.UpdateEnabled()
if s.Enabled {
s.collectPoints() s.collectPoints()
} }
// Wait for something to happen
select { select {
case <-s.update: case <-s.update:
case <-time.After(updateInterval): case <-time.After(updateInterval):