sync: import MCQ justification as Flag

This commit is contained in:
Pierre-Olivier Mercier 2019-01-18 04:24:28 +01:00
parent 07ec6cb613
commit 4f98536f91
2 changed files with 55 additions and 52 deletions

View File

@ -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

View File

@ -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
}