diff options
-rw-r--r-- | src/challenge.go | 24 | ||||
-rw-r--r-- | src/http.go | 16 | ||||
-rw-r--r-- | src/seed.go | 24 |
3 files changed, 57 insertions, 7 deletions
diff --git a/src/challenge.go b/src/challenge.go index 991e4e5..1d0a210 100644 --- a/src/challenge.go +++ b/src/challenge.go @@ -1,10 +1,12 @@ package main +import "time" + type Challenge struct { Name string Description string Flag string // this should never leave the server - FoundFlag bool + FoundFlag time.Time FlagTries uint Container string // this could, but is not required as well Category string @@ -15,18 +17,34 @@ type StrippedChallenge struct { Name string `json:"name"` Description string `json:"description"` Category string `json:"category"` - FoundFlag bool `json:"foundFlag"` + FoundFlag int64 `json:"foundFlag"` + FlagTries uint `json:"flagTries"` ContainsLaunchable bool `json:"ContainsLaunchable"` IPAddress string `json:"IPAddress"` } +type StatsStrippedChallenge struct { + Name string `json:"name"` + FoundFlag int64 `json:"foundFlag"` + FlagTries uint `json:"flagTries"` +} + func stripChallenge(c Challenge) (StrippedChallenge) { return StrippedChallenge{ Name: c.Name, Description: c.Description, Category: c.Category, - FoundFlag: c.FoundFlag, + FoundFlag: c.FoundFlag.Unix(), + FlagTries: c.FlagTries, ContainsLaunchable: c.Container != "", IPAddress: getAddressForChallengeContainer(c.Container), } } + +func stripChallengeForStatistics(c Challenge) (StatsStrippedChallenge) { + return StatsStrippedChallenge{ + Name: c.Name, + FoundFlag: c.FoundFlag.Unix(), + FlagTries: c.FlagTries, + } +} diff --git a/src/http.go b/src/http.go index 1e60046..480e356 100644 --- a/src/http.go +++ b/src/http.go @@ -37,6 +37,7 @@ func setupHTTPServer() (http.Server) { r.HandleFunc("/api/stopContainer", stopContainerHandler).Methods("POST") r.HandleFunc("/api/getAccess", getAccessHandler).Methods("GET") r.HandleFunc("/api/getTimeLimit", getTimeLimitHandler).Methods("GET") + r.HandleFunc("/api/getStats", getStatsHandler).Methods("GET") return http.Server{ Addr: fmt.Sprintf("0.0.0.0:%d", *port), @@ -203,6 +204,17 @@ func getChallengesHandler(w http.ResponseWriter, r *http.Request) { } } +func getStatsHandler(w http.ResponseWriter, r *http.Request) { + json, jsonErr := generateJSONFromChallengesForStats() + + if jsonErr == nil { + w.Write([]byte(json)) + } else { + log.Println(jsonErr) + w.WriteHeader(500) + } +} + func submitFlagHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm() challengeName := r.Form.Get("challengeName") @@ -232,11 +244,11 @@ func submitFlagHandler(w http.ResponseWriter, r *http.Request) { if challenge.Flag == flag { // our user found the flag \o/ - challenges[index].FoundFlag = true + challenges[index].FoundFlag = time.Now() correctFlag = true } else { // ow, bummer :( - challenge.FlagTries++ + challenges[index].FlagTries++ } break } diff --git a/src/seed.go b/src/seed.go index 3dce55f..dd836ff 100644 --- a/src/seed.go +++ b/src/seed.go @@ -1,12 +1,13 @@ package main import ( + "encoding/json" "flag" "fmt" "github.com/pkg/errors" "io/ioutil" "log" - "encoding/json" + "time" ) var ( @@ -54,7 +55,7 @@ func readSeedFile(path string) ([]Challenge, error) { Name: name, Description: desc, Flag: flag, - FoundFlag: false, + FoundFlag: time.Unix(0, 0), FlagTries: 0, Container: cont, Category: category, @@ -108,3 +109,22 @@ func generateJSONFromChallenges() (string, error) { }) return string(marshalled), marshalError } + +// Generate a JSON string from the stored challenges, just containing enough to call it statistics +func generateJSONFromChallengesForStats() (string, error) { + // To include only required information for statistics, we need to strip the challenge + var strippedChallenges []StatsStrippedChallenge + categories := map[string]int{} + + for _, challenge := range challenges { + // Append challenge to list + strippedChallenges = append(strippedChallenges, stripChallengeForStatistics(challenge)) + + categories[challenge.Category]++ + } + + marshalled, marshalError := json.Marshal(map[string]interface{}{ + "challenges": strippedChallenges, + }) + return string(marshalled), marshalError +} |