150 lines
3.2 KiB
Go
150 lines
3.2 KiB
Go
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")
|
|
|
|
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 {
|
|
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)
|
|
|
|
}
|