From 4f98536f9130a7c34040defae55467703da21ee0 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 18 Jan 2019 04:24:28 +0100 Subject: [PATCH] sync: import MCQ justification as Flag --- admin/sync/exercice_defines.go | 10 +++- admin/sync/exercice_keys.go | 97 ++++++++++++++++------------------ 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/admin/sync/exercice_defines.go b/admin/sync/exercice_defines.go index 9ac269b4..20666fde 100644 --- a/admin/sync/exercice_defines.go +++ b/admin/sync/exercice_defines.go @@ -25,20 +25,26 @@ type ExerciceUnlockFile struct { Filename string `toml:",omitempty"` } +// ExerciceFlagChoice holds informations about a choice (for MCQ and UCQ). +type ExerciceFlagChoice struct { + Label string `toml:",omitempty"` + Value interface{} `toml:",omitempty"` + Justification *ExerciceFlag `toml:",omitempty""` +} + // ExerciceFlag holds informations about one flag. type ExerciceFlag struct { Id int64 Label string `toml:",omitempty"` Type string `toml:",omitempty"` Raw interface{} - Value interface{} `toml:",omitempty"` Separator string `toml:",omitempty"` Ordered bool `toml:",omitempty"` IgnoreCase bool `toml:",omitempty"` ValidatorRe string `toml:"validator_regexp,omitempty"` Help string `toml:",omitempty"` ChoicesCost int64 `toml:"choices_cost,omitempty"` - Choice []ExerciceFlag + Choice []ExerciceFlagChoice LockedFile []ExerciceUnlockFile `toml:"unlock_file,omitempty"` NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"` NoShuffle bool diff --git a/admin/sync/exercice_keys.go b/admin/sync/exercice_keys.go index 7c3fd619..a20bbbd0 100644 --- a/admin/sync/exercice_keys.go +++ b/admin/sync/exercice_keys.go @@ -31,25 +31,27 @@ func validatorRegexp(vre string) (validator_regexp *string) { return } -func getRawKey(flag ExerciceFlag) (raw string, prep string, errs []string) { +func getRawKey(input interface{}, validatorRe string, ordered bool) (raw string, prep string, errs []string) { + separator := "," + // Concatenate array - if f, ok := flag.Raw.([]interface{}); ok { - if len(flag.ValidatorRe) > 0 { + if f, ok := input.([]interface{}); ok { + if len(validatorRe) > 0 { errs = append(errs, "ValidatorRe cannot be defined for this kind of flag.") - flag.ValidatorRe = "" + validatorRe = "" } - if len(flag.Separator) == 0 { - flag.Separator = "," - } else if len(flag.Separator) > 1 { - flag.Separator = string(flag.Separator[0]) + if len(separator) == 0 { + separator = "," + } else if len(separator) > 1 { + separator = string(separator[0]) errs = append(errs, "separator truncated to %q") } var fitems []string for _, v := range f { if g, ok := v.(string); ok { - if strings.Index(g, flag.Separator) != -1 { + if strings.Index(g, separator) != -1 { errs = append(errs, "flag items cannot contain %q character as it is used as separator. Change the separator attribute for this flag.") return } else { @@ -62,19 +64,17 @@ func getRawKey(flag ExerciceFlag) (raw string, prep string, errs []string) { } ignord := "f" - if !flag.Ordered { + if !ordered { sort.Strings(fitems) ignord = "t" } - raw = strings.Join(fitems, flag.Separator) + flag.Separator + raw = strings.Join(fitems, separator) + separator - prep = "`" + flag.Separator + ignord - } else if f, ok := flag.Raw.(int64); ok { + prep = "`" + separator + ignord + } else if f, ok := input.(int64); ok { raw = fmt.Sprintf("%d", f) - } else if f, ok := flag.Value.(string); ok && len(f) > 0 { - raw = f - } else if f, ok := flag.Raw.(string); !ok { - errs = append(errs, fmt.Sprintf("has an invalid type: can only be []string or string, not %T", flag.Raw)) + } else if f, ok := input.(string); !ok { + errs = append(errs, fmt.Sprintf("has an invalid type: can only be []string or string, not %T", input)) return } else { raw = f @@ -152,7 +152,7 @@ func SyncExerciceFlags(i Importer, exercice fic.Exercice) (errs []string) { var addedFlag fic.Flag if flag.Type == "key" || flag.Type == "ucq" { - raw, prep, terrs := getRawKey(flag) + raw, prep, terrs := getRawKey(flag.Raw, flag.ValidatorRe, flag.Ordered) if len(terrs) > 0 { for _, err := range terrs { @@ -182,18 +182,18 @@ func SyncExerciceFlags(i Importer, exercice fic.Exercice) (errs []string) { } for cid, choice := range flag.Choice { - val, prep, terrs := getRawKey(choice) + val, prep, terrs := getRawKey(choice.Value, "", false) if len(terrs) > 0 { for _, err := range terrs { errs = append(errs, fmt.Sprintf("%q: flag UCQ #%d: %s", path.Base(exercice.Path), nline + 1, err)) } continue } - choice.Label = prep + choice.Label if len(choice.Label) == 0 { choice.Label = val } + choice.Label = prep + choice.Label if _, err := k.AddChoice(choice.Label, val); err != nil { errs = append(errs, fmt.Sprintf("%q: error in UCQ %d choice %d: %s", path.Base(exercice.Path), nline + 1, cid, err)) @@ -228,50 +228,47 @@ func SyncExerciceFlags(i Importer, exercice fic.Exercice) (errs []string) { var val bool var justify string - if choice.Value == nil { - val = false - } else if p, ok := choice.Value.(bool); ok { - val = p - if len(choice.Help) > 0 { - errs = append(errs, fmt.Sprintf("%q: error MCQ #%d: help field has to be used only with justified mcq.", path.Base(exercice.Path), nline + 1)) - continue - } - if isJustified { - errs = append(errs, fmt.Sprintf("%q: error MCQ #%d: all true items has to be justified in this MCQ.", path.Base(exercice.Path), nline + 1)) - continue - } - } else { - if choice.Raw == nil && choice.Value != nil { - choice.Raw = choice.Value - choice.Value = nil - } - if len(choice.Help) == 0 { - choice.Help = "Flag correspondant" - } + if choice.Justification != nil { if hasOne && !isJustified { errs = append(errs, fmt.Sprintf("%q: error MCQ #%d: all true items has to be justified in this MCQ.", path.Base(exercice.Path), nline + 1)) continue } - var prep string - var terrs []string val = true isJustified = true - justify, prep, terrs = getRawKey(choice) + } else if p, ok := choice.Value.(bool); ok { + val = p + if isJustified { + errs = append(errs, fmt.Sprintf("%q: error MCQ #%d: all true items has to be justified in this MCQ.", path.Base(exercice.Path), nline + 1)) + continue + } + } else if choice.Value == nil { + val = false + } else { + errs = append(errs, fmt.Sprintf("%q: error in MCQ %d choice %d: incorrect type for value: %T is not boolean.", path.Base(exercice.Path), nline + 1, cid, choice.Value)) + continue + } + + if e, err := f.AddEntry(choice.Label, val); err != nil { + errs = append(errs, fmt.Sprintf("%q: error in MCQ %d choice %d: %s", path.Base(exercice.Path), nline + 1, cid, err)) + continue + } else if isJustified && choice.Justification != nil { + var prep string + var terrs []string + justify, prep, terrs = getRawKey(choice.Justification.Raw, choice.Justification.ValidatorRe, choice.Justification.Ordered) if len(terrs) > 0 { for _, err := range terrs { errs = append(errs, fmt.Sprintf("%q: flag MCQ #%d, choice #%d: %s", path.Base(exercice.Path), nline + 1, cid, err)) } continue } - choice.Help = prep + choice.Help - } - if e, err := f.AddEntry(choice.Label, val); err != nil { - errs = append(errs, fmt.Sprintf("%q: error in MCQ %d choice %d: %s", path.Base(exercice.Path), nline + 1, cid, err)) - continue - } else if len(justify) > 0 { - if _, err := exercice.AddRawFlagKey(fmt.Sprintf("%%%d%%%s", e.Id, choice.Help), "", false, nil, []byte(justify), 0); err != nil { + if len(choice.Justification.Label) == 0 { + choice.Justification.Label = "Flag correspondant" + } + choice.Justification.Label = prep + choice.Justification.Label + + if _, err := exercice.AddRawFlagKey(fmt.Sprintf("%%%d%%%s", e.Id, choice.Justification.Label), choice.Justification.Help, choice.Justification.IgnoreCase, validatorRegexp(choice.Justification.ValidatorRe), []byte(justify), flag.ChoicesCost); err != nil { errs = append(errs, fmt.Sprintf("%q: error MCQ #%d: %s", path.Base(exercice.Path), nline + 1, err)) continue }