package main import ( "bufio" "flag" "fmt" "log" "net/http" "os" "path" "time" ) const startedFile = "started" var TeamsDir string var SubmissionDir string func touchStartedFile(startSub time.Duration) { time.Sleep(startSub) if fd, err := os.Create(path.Join(TeamsDir, startedFile)); err == nil { log.Println("Started! Go, Go, Go!!") fd.Close() } else { log.Fatal("Unable to start challenge:", err) } } func main() { var bind = flag.String("bind", "127.0.0.1:8080", "Bind port/socket") var prefix = flag.String("prefix", "", "Request path prefix to strip (from proxy)") var start = flag.Int64("start", 0, fmt.Sprintf("Challenge start timestamp (in 2 minutes: %d)", time.Now().Unix()/60*60+120)) var duration = flag.Duration("duration", 180*time.Minute, "Challenge duration") var denyChName = flag.Bool("denyChName", false, "Deny team to change their name") var allowRegistration = flag.Bool("allowRegistration", false, "New team can add itself") var resolutionRoute = flag.Bool("resolutionRoute", false, "Enable resolution route") flag.StringVar(&TeamsDir, "teams", "./TEAMS", "Base directory where save teams JSON files") flag.StringVar(&SubmissionDir, "submission", "./submissions/", "Base directory where save submissions") flag.Parse() log.SetPrefix("[frontend] ") log.Println("Creating submission directory...") if _, err := os.Stat(SubmissionDir); os.IsNotExist(err) { if err := os.MkdirAll(SubmissionDir, 0777); err != nil { log.Fatal("Unable to create submission directory: ", err) } } startTime := time.Unix(*start, 0) startSub := startTime.Sub(time.Now()) end := startTime.Add(*duration).Add(time.Duration(1 * time.Second)) log.Println("Challenge ends on", end) if startSub > 0 { log.Println("Challenge starts at", startTime, "in", startSub) fmt.Printf("PRESS ENTER TO LAUNCH THE COUNTDOWN ") bufio.NewReader(os.Stdin).ReadLine() if _, err := os.Stat(path.Join(TeamsDir, startedFile)); !os.IsNotExist(err) { os.Remove(path.Join(TeamsDir, startedFile)) } go touchStartedFile(startTime.Sub(time.Now().Add(time.Duration(1 * time.Second)))) } else { log.Println("Challenge started at", startTime, "since", -startSub) go touchStartedFile(time.Duration(0)) } log.Println("Registering handlers...") http.Handle(fmt.Sprintf("%s/time.json", *prefix), http.StripPrefix(*prefix, TimeHandler{startTime, *duration})) if *resolutionRoute { http.Handle(fmt.Sprintf("%s/resolution/", *prefix), http.StripPrefix(fmt.Sprintf("%s/resolution/", *prefix), ResolutionHandler{})) } if *allowRegistration { http.Handle(fmt.Sprintf("%s/registration", *prefix), http.StripPrefix(fmt.Sprintf("%s/registration", *prefix), RegistrationHandler{})) } if !*denyChName { http.Handle(fmt.Sprintf("%s/chname/", *prefix), http.StripPrefix(fmt.Sprintf("%s/chname/", *prefix), ChNameHandler{})) } http.Handle(fmt.Sprintf("%s/openhint/", *prefix), http.StripPrefix(fmt.Sprintf("%s/openhint/", *prefix), HintHandler{})) http.Handle(fmt.Sprintf("%s/submission/", *prefix), http.StripPrefix(fmt.Sprintf("%s/submission/", *prefix), SubmissionHandler{end})) log.Println(fmt.Sprintf("Ready, listening on %s", *bind)) if err := http.ListenAndServe(*bind, nil); err != nil { log.Fatal("Unable to listen and serve: ", err) } }