package main import ( "encoding/base64" "encoding/binary" "encoding/json" "fmt" "io/ioutil" "log" "math/rand" "os" "strconv" "srs.epita.fr/fic-server/libfic" ) type ResponsesUpload struct { Keys map[string]string `json:"flags"` MCQs map[int64]bool `json:"mcqs"` } func treatSubmission(pathname string, team fic.Team, exercice_id string) { // Generate a unique identifier to follow the request in logs bid := make([]byte, 5) binary.LittleEndian.PutUint32(bid, rand.Uint32()) id := "[" + base64.StdEncoding.EncodeToString(bid) + "]" log.Println(id, "New submission receive", pathname) // Parse exercice_id argument eid, err := strconv.Atoi(exercice_id) if err != nil { log.Printf("%s [ERR] %s is not a valid number: %s\n", id, exercice_id, err) return } // Find the given exercice exercice, err := fic.GetExercice(int64(eid)) if err != nil { log.Printf("%s [ERR] Unable to find exercice %d: %s", id, eid, err) return } // Find the corresponding theme theme, err := exercice.GetTheme() if err != nil { log.Println("%s [ERR] Unable to retrieve theme for exercice %d: %s", id, eid, err) return } // Read received file cnt_raw, err := ioutil.ReadFile(pathname) if err != nil { log.Println(id, "[ERR] Unable to read file;", err) return } // Parse it var responses ResponsesUpload err = json.Unmarshal(cnt_raw, &responses) if err != nil { log.Println(id, "[ERR] JSON parsing error:", err) return } // Ensure the team didn't already solve this exercice s, tm := team.HasSolved(exercice) if s { log.Printf("%s [WRN] Team %d ALREADY solved exercice %d (%s : %s)\n", id, team.Id, exercice.Id, theme.Name, exercice.Title) return } // Check given answers solved, err := exercice.CheckResponse(responses.Keys, responses.MCQs, team) if err != nil { log.Println(id, "[ERR] Unable to CheckResponse:", err) genTeamMyFile(team) return } // At this point, we have treated the file, so it can be safely deleted if err := os.Remove(pathname); err != nil { log.Println(id, "[ERR] Can't remove file:", err) } if solved { log.Printf("%s Team %d SOLVED exercice %d (%s : %s)\n", id, team.Id, exercice.Id, theme.Name, exercice.Title) if err := exercice.Solved(team); err != nil { log.Println(id, "[ERR] Unable to mark the challenge as solved:", err) } // Write event if lvl, err := exercice.GetLevel(); err != nil { log.Println(id, "[ERR] Unable to get exercice level:", err) } else if _, err := fic.NewEvent(fmt.Sprintf("L'équipe %s a résolu le %de challenge %s !", team.Name, lvl, theme.Name), "alert-success"); err != nil { log.Println(id, "[WRN] Unable to create event:", err) } genTeamAll(team) } else { log.Printf("%s Team %d submit an invalid solution for exercice %d (%s : %s)\n", id, team.Id, exercice.Id, theme.Name, exercice.Title) // Write event (only on first try) if tm.Unix() == 0 { if lvl, err := exercice.GetLevel(); err != nil { log.Println(id, "[ERR] Unable to get exercice level:", err) } else if _, err := fic.NewEvent(fmt.Sprintf("L'équipe %s tente le %de challenge %s !", team.Name, lvl, theme.Name), "alert-warning"); err != nil { log.Println(id, "[WRN] Unable to create event:", err) } } genTeamMyFile(team) } if err := genEventsFile(); err != nil { log.Println("events.json generation error: ", err) } }