package main import ( "flag" "log" "os" "strconv" "strings" "time" "git.andreafazzi.eu/andrea/oef/client" "git.andreafazzi.eu/andrea/oef/orm" "github.com/gocarina/gocsv" "golang.org/x/exp/errors/fmt" ) type Response struct { Firstname string `csv:"Nome"` Lastname string `csv:"Cognome"` FiscalCode string `csv:"Codice fiscale"` School string `csv:"Scuola"` Region string `csv:"Regione"` Score int `csv:"Punteggio"` Duration uint `csv:"Durata"` } func findAnswer(answers []*orm.Answer, id uint) (*orm.Answer, error) { for _, a := range answers { if a.ID == id { return a, nil } } return nil, fmt.Errorf("Answer with ID %v not found", id) } func findSchool(schools []*orm.School, id uint) (*orm.School, error) { for _, s := range schools { if s.ID == id { return s, nil } } return nil, fmt.Errorf("School with ID %v not found", id) } func calcScoreAndDuration(answers []*orm.Answer, response *orm.Response) error { response.Score = 0 if response.AnswersIDs != "" { srIDs := strings.Split(response.AnswersIDs, " ") for _, srID := range srIDs { id, err := strconv.Atoi(srID) if err != nil { return err } response.SingleResponses = append(response.SingleResponses, &orm.SingleResponse{uint(id)}) } for _, sr := range response.SingleResponses { answer, err := findAnswer(answers, sr.AnswerID) if err != nil { panic(err) } if answer.Correct { response.Score++ } } } if !response.StartTime.IsZero() { response.Duration = response.UpdatedAt.Sub(response.StartTime) } return nil } func main() { username := flag.String("username", "admin", "Username") password := flag.String("password", "admin", "Password") output := flag.String("output", "rank.csv", "Output filename") contestId := flag.Int("id", 0, "Contest ID") all := flag.Bool("all", false, "Rank all participants") flag.Parse() log.Printf("Contacting %v", flag.Arg(0)) client, err := client.Dial(flag.Arg(0), *username, *password) if err != nil { panic(err) } log.Println("Fetching all the schools...") schools := make([]*orm.School, 0) err = client.ReadAll(&schools) if err != nil { panic(err) } log.Println("Fetching all the responses...") responses := make([]*orm.Response, 0) err = client.ReadAll(&responses) if err != nil { panic(err) } log.Println("Fetching all the answers...") answers := make([]*orm.Answer, 0) err = client.ReadAll(&answers) if err != nil { panic(err) } csvResponses := make([]*Response, 0) for _, r := range responses { if r.ContestID != uint(*contestId) { continue } err := calcScoreAndDuration(answers, r) if err != nil { panic(err) } if r.Score > 0 && r.Duration > 0 && !*all { school, err := findSchool(schools, r.Participant.SchoolID) if err != nil { panic(err) } csvResponses = append( csvResponses, &Response{ Firstname: r.Participant.Firstname, Lastname: r.Participant.Lastname, FiscalCode: r.Participant.FiscalCode, School: school.String(), Region: school.Region.String(), Score: r.Score, Duration: uint(r.Duration / time.Second), }, ) } else { school, err := findSchool(schools, r.Participant.SchoolID) if err != nil { panic(err) } csvResponses = append( csvResponses, &Response{ Firstname: r.Participant.Firstname, Lastname: r.Participant.Lastname, FiscalCode: r.Participant.FiscalCode, School: school.String(), Region: school.Region.String(), Score: r.Score, Duration: uint(r.Duration / time.Second), }, ) } } f, err := os.Create(*output) if err != nil { panic(err) } defer f.Close() gocsv.MarshalFile(csvResponses, f) }