From 766ba387a65cb059cf1e7ea5b1318ea61f2743b8 Mon Sep 17 00:00:00 2001 From: Andrea Fazzi Date: Wed, 8 Jan 2020 15:41:04 +0100 Subject: [PATCH] import_contest prototype script --- client/client.go | 103 ++++++++++++++++++ handlers/handlers.go | 4 +- orm/contest.go | 17 ++- scripts/import_contest/.gitignore | 4 +- .../example/test_diagnostico.toml | 26 +++++ scripts/import_contest/main.go | 76 ++++++++++++- 6 files changed, 217 insertions(+), 13 deletions(-) create mode 100644 scripts/import_contest/example/test_diagnostico.toml diff --git a/client/client.go b/client/client.go index 8cf9bc79..07e5d5a1 100644 --- a/client/client.go +++ b/client/client.go @@ -8,8 +8,11 @@ import ( "io/ioutil" "net/http" "net/url" + "reflect" + "strconv" "strings" + "git.andreafazzi.eu/andrea/oef/i18n" "git.andreafazzi.eu/andrea/oef/orm" "git.andreafazzi.eu/andrea/oef/renderer" "github.com/jinzhu/inflection" @@ -114,6 +117,106 @@ func (c *Client) ReadAll(model interface{}) error { return nil } +func (c *Client) Create(model interface{}) (uint, error) { + var response renderer.JsonResponse + data, err := json.Marshal(model) + if err != nil { + return 0, err + } + + resp, err := c.SendRequest("POST", fmt.Sprintf("/api/%s/create/?format=json", pluralizedModelName(model)), data) + if err != nil { + return 0, err + } + + if err := json.Unmarshal(resp, &response); err != nil { + return 0, err + } + + if string(response.Error) != "" { + return 0, errors.New(string(response.Error)) + } + + id, err := strconv.Atoi(string(response.Result)) + if err != nil { + return 0, err + } + + return uint(id), nil +} + +func (c *Client) Delete(model orm.IDer) (uint, error) { + var response renderer.JsonResponse + data, err := json.Marshal(model) + if err != nil { + return 0, err + } + + resp, err := c.SendRequest("DELETE", fmt.Sprintf("/api/%s/%d/delete?format=json", pluralizedModelName(model), model.GetID()), data) + if err != nil { + return 0, err + } + + if err := json.Unmarshal(resp, &response); err != nil { + return 0, err + } + + if string(response.Error) != "" { + return 0, errors.New(string(response.Error)) + } + + id, err := strconv.Atoi(string(response.Result)) + if err != nil { + return 0, err + } + + return uint(id), nil +} + +func (c *Client) DeleteAllByName(model interface{}, name string) error { + err := c.ReadAll(model) + if err != nil { + return err + } + switch reflect.TypeOf(model).Kind() { + case reflect.Ptr: + s := reflect.ValueOf(model).Elem() + + // FIXME: Check whatever s is a slice before cycling through it! + + for i := 0; i < s.Len(); i++ { + if callString(s.Index(i).Interface()) == name { + _, err := c.Delete(s.Index(i).Interface().(orm.IDer)) + if err != nil { + return err + } + } + + } + } + return nil +} + +// FIXME: refactor this (it's duplicated across the code) func pluralizedModelName(value interface{}) string { return inflection.Plural(strings.ToLower(orm.ModelName(value))) } + +// FIXME: refactor this (it's duplicated across the code) +func callString(value interface{}) string { + if value != nil { + switch reflect.ValueOf(value).Kind() { + case reflect.String: + return value.(string) + case reflect.Bool: + if value.(bool) { + return i18n.Text["answerCorrect"]["it"] + } + return "false" + default: + return reflect.ValueOf(value).MethodByName("String").Interface().(func() string)() + } + } else { + return "" + } +} diff --git a/handlers/handlers.go b/handlers/handlers.go index d0f83b99..5c48fdcb 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -6,7 +6,6 @@ import ( "io/ioutil" "log" "net/http" - "path" "path/filepath" "reflect" "runtime/debug" @@ -79,7 +78,7 @@ func generateHandler(r *mux.Router, model interface{}) { // Generate API patterns prefixing "api" path for _, p := range patterns { - apiPatterns = append(apiPatterns, PathPattern{path.Join("/", "api", p.PathPattern), "", p.Methods, p.Permission}) + apiPatterns = append(apiPatterns, PathPattern{"/api" + p.PathPattern, "", p.Methods, p.Permission}) } // Install standard paths @@ -246,7 +245,6 @@ func get(w http.ResponseWriter, r *http.Request, model string, pattern PathPatte respondWithError(w, r, err) } else { claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims) - log.Println(claims) role := claims["role"].(string) if !hasPermission(role, pattern.Path(model)) { setFlashMessage(w, r, "notAuthorized") diff --git a/orm/contest.go b/orm/contest.go index ab2da7d3..3aff913d 100644 --- a/orm/contest.go +++ b/orm/contest.go @@ -55,9 +55,9 @@ func (c *Contest) Create(args map[string]string, w http.ResponseWriter, r *http. endTime := r.FormValue("EndTime") log.Println("Zero time", date) if date == "" { - r.PostForm.Set("Date", time.Time{}.String()) - r.PostForm.Set("StartTime", time.Time{}.String()) - r.PostForm.Set("EndTime", time.Time{}.String()) + r.PostForm.Set("Date", time.Time{}.Format(time.RFC3339)) + r.PostForm.Set("StartTime", time.Time{}.Format(time.RFC3339)) + r.PostForm.Set("EndTime", time.Time{}.Format(time.RFC3339)) } else { r.PostForm.Set("Date", fmt.Sprintf("%sT%s:00+01:00", date, startTime)) r.PostForm.Set("StartTime", fmt.Sprintf("%sT%s:00+01:00", date, startTime)) @@ -160,8 +160,15 @@ func (c *Contest) Update(args map[string]string, w http.ResponseWriter, r *http. } } -func (c *Contest) Delete(args map[string]string, w http.ResponseWriter, r *http.Request) (interface{}, error) { - return nil, nil +func (model *Contest) Delete(args map[string]string, w http.ResponseWriter, r *http.Request) (interface{}, error) { + contest, err := model.Read(args, w, r) + if err != nil { + return nil, err + } + if err := DB().Unscoped().Delete(contest.(*Contest)).Error; err != nil { + return nil, err + } + return contest.(*Contest), nil } func CreateContest(contest *Contest) (*Contest, error) { diff --git a/scripts/import_contest/.gitignore b/scripts/import_contest/.gitignore index 51f895ee..dc65c5b0 100644 --- a/scripts/import_contest/.gitignore +++ b/scripts/import_contest/.gitignore @@ -1,2 +1,4 @@ import_contest -contests +config.yaml + + diff --git a/scripts/import_contest/example/test_diagnostico.toml b/scripts/import_contest/example/test_diagnostico.toml new file mode 100644 index 00000000..760eb6dc --- /dev/null +++ b/scripts/import_contest/example/test_diagnostico.toml @@ -0,0 +1,26 @@ +name = "Test Diagnostico" + +[[questions]] + text = "Quanto fa 1+1?" + + [[questions.answers]] + text = "2" + [[questions.answers]] + text = "3" + [[questions.answers]] + text = "4" + [[questions.answers]] + text = "5" + +[[questions]] + text = "Il sole รจ" + + [[questions.answers]] + text = "una stella" + [[questions.answers]] + text = "un pianeta" + [[questions.answers]] + text = "una galassia" + [[questions.answers]] + text = "una nebulosa" + diff --git a/scripts/import_contest/main.go b/scripts/import_contest/main.go index dd81afb2..4602a576 100644 --- a/scripts/import_contest/main.go +++ b/scripts/import_contest/main.go @@ -1,31 +1,99 @@ package main import ( + "flag" "log" + "os" "git.andreafazzi.eu/andrea/oef/client" + "git.andreafazzi.eu/andrea/oef/config" "git.andreafazzi.eu/andrea/oef/orm" "github.com/BurntSushi/toml" ) func main() { - url := "http://localhost:3000" + 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) + } log.Println("Reading toml file...") var contest *orm.Contest - if _, err := toml.DecodeFile("contests/test_diagnostico.toml", &contest); err != nil { + if _, err := toml.DecodeFile(flag.Arg(0), &contest); err != nil { panic(err) } var contests []*orm.Contest - err := client.ReadAll(&contests) + err = client.ReadAll(&contests) if err != nil { panic(err) } - id, err := client.Create(contest) + // 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 { + panic(err) + } + + } + } + + contestID, err := client.Create(contest) if err != nil { panic(err) } + log.Println("Create contest with ID", contestID) + log.Println("Creating questions...") + + for _, question := range contest.Questions { + + err := client.DeleteAllByName(&[]*orm.Question{}, question.Text) + if err != nil { + panic(err) + } + + question.ContestID = contestID + questionID, err := client.Create(question) + if err != nil { + panic(err) + } + log.Println("Create question with ID", questionID) + + for pos, answer := range question.Answers { + + err := client.DeleteAllByName(&[]*orm.Answer{}, answer.Text) + if err != nil { + panic(err) + } + + answer.QuestionID = questionID + if pos == 0 { + answer.Correct = true + } + id, err := client.Create(answer) + if err != nil { + panic(err) + } + log.Println("Create answer with ID", id) + + } + + } }