oef/scripts/import/main.go
2020-01-10 12:56:25 +01:00

190 lines
3.9 KiB
Go

package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
"git.andreafazzi.eu/andrea/oef/client"
"git.andreafazzi.eu/andrea/oef/config"
"git.andreafazzi.eu/andrea/oef/orm"
"github.com/BurntSushi/toml"
"github.com/gocarina/gocsv"
)
type importer struct {
client *client.Client
importFuncs map[string]func(*client.Client, string) error
}
func newImporter(c *client.Client) *importer {
return &importer{
c,
map[string]func(*client.Client, string) error{
"contests": importContest,
"schools": importSchools,
"participants": importParticipants,
},
}
}
func (i *importer) runImport(importer, filename string) error {
f, ok := i.importFuncs[importer]
if !ok {
return fmt.Errorf("Importer %s not defined!", importer)
}
return f(i.client, filename)
}
func importSchools(client *client.Client, filename string) error {
var schools []*orm.School
data, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
if err := gocsv.Unmarshal(strings.NewReader(string(data)), &schools); err != nil {
panic(err)
}
for _, s := range schools {
id, err := client.Create(s)
if err != nil {
panic(err)
}
log.Println("Create school with ID", id)
}
return nil
}
func importParticipants(client *client.Client, filename string) error {
var participants []*orm.Participant
data, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
if err := gocsv.Unmarshal(strings.NewReader(string(data)), &participants); err != nil {
panic(err)
}
for _, p := range participants {
id, err := client.Create(p)
if err != nil {
panic(err)
}
log.Println("Create participant with ID", id)
}
return nil
}
func importContest(client *client.Client, filename string) error {
log.Println("Reading contest data from toml file...")
var contest *orm.Contest
if _, err := toml.DecodeFile(filename, &contest); err != nil {
return err
}
var contests []*orm.Contest
err := client.ReadAll(&contests)
if err != nil {
return err
}
// Remove all contest with the same name
for _, c := range contests {
if c.Name == contest.Name {
log.Println("Remove contest with ID", c.ID)
_, err := client.Delete(c)
if err != nil {
return err
}
}
}
contestID, err := client.Create(contest)
if err != nil {
return err
}
log.Println("Create contest with ID", contestID)
log.Println("Creating questions...")
for _, question := range contest.Questions {
err := client.DeleteAllFunc(&[]*orm.Question{}, func(model interface{}) bool {
return model.(*orm.Question).Text == question.Text
})
if err != nil {
return err
}
question.ContestID = contestID
questionID, err := client.Create(question)
if err != nil {
return err
}
log.Println("Create question with ID", questionID)
for pos, answer := range question.Answers {
err := client.DeleteAllFunc(&[]*orm.Answer{}, func(model interface{}) bool {
return model.(*orm.Answer).Text == answer.Text && model.(*orm.Answer).Question != nil && model.(*orm.Answer).Question.Text == question.Text
})
if err != nil {
return err
}
answer.QuestionID = questionID
if pos == 0 {
answer.Correct = true
}
id, err := client.Create(answer)
if err != nil {
return err
}
log.Println("Create answer with ID", id)
}
}
return nil
}
func main() {
var importer string
flag.StringVar(&importer, "importer", "contest", "Name of importer to use")
flag.Parse()
if flag.NArg() == 0 {
panic("A toml filename is needed as first argument of this script.")
}
conf := new(config.ConfigT)
if _, err := os.Stat("./config.yaml"); err != nil {
panic(err)
}
err := config.ReadFile("./config.yaml", conf)
if err != nil {
panic(err)
}
client, err := client.Dial(conf.Url, conf.Admin.Username, conf.Admin.Password)
if err != nil {
panic(err)
}
i := newImporter(client)
err = i.runImport(importer, flag.Arg(0))
if err != nil {
panic(err)
}
}