Add export rank script and preload region when reading all schools
This commit is contained in:
parent
0df72995c5
commit
4de256e9fb
6 changed files with 156 additions and 0 deletions
2
go.mod
2
go.mod
|
@ -42,6 +42,7 @@ require (
|
||||||
github.com/urfave/negroni v1.0.0 // indirect
|
github.com/urfave/negroni v1.0.0 // indirect
|
||||||
github.com/wcharczuk/go-chart v2.0.1+incompatible // indirect
|
github.com/wcharczuk/go-chart v2.0.1+incompatible // indirect
|
||||||
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d // indirect
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d // indirect
|
||||||
|
golang.org/x/exp/errors v0.0.0-20201229011636-eab1b5eb1a03
|
||||||
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
|
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
|
||||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect
|
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect
|
||||||
|
@ -49,4 +50,5 @@ require (
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/russross/blackfriday.v2 v2.0.0
|
gopkg.in/russross/blackfriday.v2 v2.0.0
|
||||||
gopkg.in/yaml.v2 v2.2.4
|
gopkg.in/yaml.v2 v2.2.4
|
||||||
|
gorm.io/gorm v1.20.11
|
||||||
)
|
)
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -110,6 +110,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
||||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/jinzhu/now v1.1.1 h1:g39TucaRWyV3dwDO++eEc6qf8TVIQ/Da48WmqjZ3i7E=
|
||||||
|
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
@ -196,7 +198,11 @@ golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H
|
||||||
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522 h1:OeRHuibLsmZkFj773W4LcfAGsSxJgfPONhr8cmO+eLA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/exp v0.0.0-20201229011636-eab1b5eb1a03 h1:XlAInxBYX5nBofPaY51uv/x9xmRgZGr/lDOsePd2AcE=
|
||||||
|
golang.org/x/exp/errors v0.0.0-20201229011636-eab1b5eb1a03 h1:A4FptnpJ/z3jSXVmYXbcrFGO2wsfwGqel7BJcgT99hU=
|
||||||
|
golang.org/x/exp/errors v0.0.0-20201229011636-eab1b5eb1a03/go.mod h1:YgqsNsAu4fTvlab/7uiYK9LJrCIzKg/NiZUIH1/ayqo=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 h1:5h3ngYt7+vXCDZCup/HkCQgW5XwmSvR/nA2JmJ0RErg=
|
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 h1:5h3ngYt7+vXCDZCup/HkCQgW5XwmSvR/nA2JmJ0RErg=
|
||||||
golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
@ -304,6 +310,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gorm.io/gorm v1.20.11 h1:jYHQ0LLUViV85V8dM1TP9VBBkfzKTnuTXDjYObkI6yc=
|
||||||
|
gorm.io/gorm v1.20.11/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
@ -240,6 +240,7 @@ func (model *School) ReadAll(db *Database, args map[string]string, w http.Respon
|
||||||
if err := db._db.
|
if err := db._db.
|
||||||
Preload("Participants").
|
Preload("Participants").
|
||||||
Preload("Participants.Category").
|
Preload("Participants.Category").
|
||||||
|
Preload("Region").
|
||||||
Order("code").
|
Order("code").
|
||||||
Find(&schools).Error; err != nil {
|
Find(&schools).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
1
scripts/rank/.gitignore
vendored
Normal file
1
scripts/rank/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.csv
|
144
scripts/rank/main.go
Normal file
144
scripts/rank/main.go
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
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
|
||||||
|
Lastname string
|
||||||
|
School string
|
||||||
|
Region string
|
||||||
|
Score int
|
||||||
|
Duration uint
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
school, err := findSchool(schools, r.Participant.SchoolID)
|
||||||
|
|
||||||
|
csvResponses = append(
|
||||||
|
csvResponses,
|
||||||
|
&Response{
|
||||||
|
Firstname: r.Participant.Firstname,
|
||||||
|
Lastname: r.Participant.Lastname,
|
||||||
|
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)
|
||||||
|
|
||||||
|
}
|
BIN
scripts/rank/rank
Executable file
BIN
scripts/rank/rank
Executable file
Binary file not shown.
Loading…
Reference in a new issue