package sync import ( "fmt" "path" "github.com/BurntSushi/toml" "srs.epita.fr/fic-server/libfic" ) // ExerciceHintParams holds EHint definition infomation. type ExerciceHintParams struct { Filename string Content string Cost int64 Title string NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"` } // ExerciceDependency holds dependency definitions information. type ExerciceDependency struct { Id int64 Theme string `toml:",omitempty"` } // ExerciceUnlockFile holds parameters related to a locked file. type ExerciceUnlockFile struct { Filename string `toml:",omitempty"` } // ExerciceFlag holds informations about one flag. type ExerciceFlag struct { Id int64 Label string `toml:",omitempty"` Type string `toml:",omitempty"` Raw interface{} Separator string `toml:",omitempty"` ShowLines bool `toml:",omitempty"` Ordered bool `toml:",omitempty"` CaseSensitive bool `toml:",omitempty"` ValidatorRe string `toml:"validator_regexp,omitempty"` Placeholder string `toml:",omitempty"` Help string `toml:",omitempty"` ChoicesCost int64 `toml:"choices_cost,omitempty"` Choice []ExerciceFlagChoice LockedFile []ExerciceUnlockFile `toml:"unlock_file,omitempty"` NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"` NoShuffle bool } // ExerciceFlagChoice holds informations about a choice (for MCQ and UCQ). type ExerciceFlagChoice struct { ExerciceFlag Value interface{} `toml:",omitempty"` } // ExerciceParams contains values parsed from defines.txt. type ExerciceParams struct { Gain int64 Tags []string Hints []ExerciceHintParams `toml:"hint"` Dependencies []ExerciceDependency `toml:"depend"` Flags []ExerciceFlag `toml:"flag"` FlagsMCQ []ExerciceFlag `toml:"flag_mcq"` FlagsUCQ []ExerciceFlag `toml:"flag_ucq"` } // parseExerciceParams reads challenge definitions from defines.txt and extract usefull data to set up the challenge. func parseExerciceParams(i Importer, exPath string) (p ExerciceParams, md toml.MetaData, err error) { var defs string defs, err = getFileContent(i, path.Join(exPath, "challenge.txt")) if err != nil { return } md, err = toml.Decode(defs, &p) return } // getExerciceParams returns normalized func getExerciceParams(i Importer, exercice fic.Exercice) (params ExerciceParams, errs []string) { var err error if params, _, err = parseExerciceParams(i, exercice.Path); err != nil { errs = append(errs, fmt.Sprintf("%q: challenge.txt: %s", path.Base(exercice.Path), err)) } else if len(params.Flags) == 0 && len(params.FlagsUCQ) == 0 && len(params.FlagsMCQ) == 0 { errs = append(errs, fmt.Sprintf("%q: has no flag", path.Base(exercice.Path))) } else { // Treat legacy UCQ flags as ExerciceFlag for _, flag := range params.FlagsUCQ { params.Flags = append(params.Flags, ExerciceFlag{ Id: flag.Id, Label: flag.Label, Type: "ucq", Raw: flag.Raw, ValidatorRe: flag.ValidatorRe, Placeholder: flag.Placeholder, ChoicesCost: flag.ChoicesCost, Choice: flag.Choice, LockedFile: flag.LockedFile, NeedFlag: flag.NeedFlag, }) } params.FlagsUCQ = []ExerciceFlag{} // Treat legacy MCQ flags as ExerciceFlag for _, flag := range params.FlagsMCQ { params.Flags = append(params.Flags, ExerciceFlag{ Id: flag.Id, Label: flag.Label, Type: "mcq", ChoicesCost: flag.ChoicesCost, Choice: flag.Choice, LockedFile: flag.LockedFile, NeedFlag: flag.NeedFlag, }) } params.FlagsMCQ = []ExerciceFlag{} } return }