2018-01-10 02:45:56 +00:00
|
|
|
package sync
|
|
|
|
|
|
|
|
import (
|
2019-07-05 20:28:56 +00:00
|
|
|
"fmt"
|
2018-01-10 02:45:56 +00:00
|
|
|
"path"
|
|
|
|
|
|
|
|
"github.com/BurntSushi/toml"
|
2019-07-05 20:28:56 +00:00
|
|
|
"srs.epita.fr/fic-server/libfic"
|
2018-01-10 02:45:56 +00:00
|
|
|
)
|
|
|
|
|
2018-03-09 18:07:08 +00:00
|
|
|
// ExerciceHintParams holds EHint definition infomation.
|
2018-01-10 03:42:50 +00:00
|
|
|
type ExerciceHintParams struct {
|
|
|
|
Filename string
|
2018-05-12 00:01:49 +00:00
|
|
|
Content string
|
2021-11-14 15:15:19 +00:00
|
|
|
Cost *int64
|
2018-01-10 03:42:50 +00:00
|
|
|
Title string
|
2019-10-26 09:33:30 +00:00
|
|
|
NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"`
|
2018-01-10 03:42:50 +00:00
|
|
|
}
|
|
|
|
|
2018-05-12 00:01:49 +00:00
|
|
|
// ExerciceDependency holds dependency definitions information.
|
|
|
|
type ExerciceDependency struct {
|
|
|
|
Id int64
|
|
|
|
Theme string `toml:",omitempty"`
|
|
|
|
}
|
|
|
|
|
2018-09-07 18:53:08 +00:00
|
|
|
// ExerciceUnlockFile holds parameters related to a locked file.
|
|
|
|
type ExerciceUnlockFile struct {
|
|
|
|
Filename string `toml:",omitempty"`
|
|
|
|
}
|
|
|
|
|
2022-10-31 17:52:29 +00:00
|
|
|
// ExerciceFile defines attributes on files.
|
|
|
|
type ExerciceFile struct {
|
|
|
|
Filename string `toml:",omitempty"`
|
|
|
|
Hidden bool `toml:",omitempty"`
|
|
|
|
}
|
|
|
|
|
2019-01-16 04:25:20 +00:00
|
|
|
// ExerciceFlag holds informations about one flag.
|
2018-05-12 00:01:49 +00:00
|
|
|
type ExerciceFlag struct {
|
2019-09-06 21:03:08 +00:00
|
|
|
Id int64
|
|
|
|
Label string `toml:",omitempty"`
|
|
|
|
Type string `toml:",omitempty"`
|
|
|
|
Raw interface{}
|
|
|
|
Separator string `toml:",omitempty"`
|
2019-11-25 16:45:41 +00:00
|
|
|
ShowLines bool `toml:",omitempty"`
|
2019-09-06 21:03:08 +00:00
|
|
|
Ordered bool `toml:",omitempty"`
|
|
|
|
CaseSensitive bool `toml:",omitempty"`
|
2021-12-07 15:33:30 +00:00
|
|
|
NoTrim bool `toml:",omitempty"`
|
2019-09-06 21:03:08 +00:00
|
|
|
ValidatorRe string `toml:"validator_regexp,omitempty"`
|
2022-01-21 07:28:39 +00:00
|
|
|
SortReGroups bool `toml:"sort_validator_regexp_groups,omitempty"`
|
2020-09-07 17:33:09 +00:00
|
|
|
Placeholder string `toml:",omitempty"`
|
2021-08-30 16:33:14 +00:00
|
|
|
Help string `toml:",omitempty"`
|
2022-05-31 20:03:51 +00:00
|
|
|
BonusGain int32 `toml:"bonus_gain,omitempty"`
|
|
|
|
ChoicesCost int32 `toml:"choices_cost,omitempty"`
|
2019-09-06 21:03:08 +00:00
|
|
|
Choice []ExerciceFlagChoice
|
|
|
|
LockedFile []ExerciceUnlockFile `toml:"unlock_file,omitempty"`
|
|
|
|
NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"`
|
|
|
|
NoShuffle bool
|
2021-11-12 22:52:22 +00:00
|
|
|
Unit string `toml:"unit,omitempty"`
|
2022-01-21 12:06:37 +00:00
|
|
|
Variant string `toml:"variant,omitempty"`
|
2021-11-12 20:36:27 +00:00
|
|
|
NumberMin interface{} `toml:"min,omitempty"`
|
|
|
|
NumberMax interface{} `toml:"max,omitempty"`
|
|
|
|
NumberStep interface{} `toml:"step,omitempty"`
|
2018-05-12 00:01:49 +00:00
|
|
|
}
|
|
|
|
|
2019-09-06 20:58:30 +00:00
|
|
|
// ExerciceFlagChoice holds informations about a choice (for MCQ and UCQ).
|
|
|
|
type ExerciceFlagChoice struct {
|
|
|
|
ExerciceFlag
|
|
|
|
Value interface{} `toml:",omitempty"`
|
|
|
|
}
|
|
|
|
|
2018-03-09 18:07:08 +00:00
|
|
|
// ExerciceParams contains values parsed from defines.txt.
|
2018-01-10 02:45:56 +00:00
|
|
|
type ExerciceParams struct {
|
2018-05-12 00:01:49 +00:00
|
|
|
Gain int64
|
2018-11-18 21:44:23 +00:00
|
|
|
Tags []string
|
2022-10-31 17:52:29 +00:00
|
|
|
Files []ExerciceFile `toml:"file"`
|
2018-05-12 00:01:49 +00:00
|
|
|
Hints []ExerciceHintParams `toml:"hint"`
|
|
|
|
Dependencies []ExerciceDependency `toml:"depend"`
|
|
|
|
Flags []ExerciceFlag `toml:"flag"`
|
2019-01-16 04:25:20 +00:00
|
|
|
FlagsMCQ []ExerciceFlag `toml:"flag_mcq"`
|
|
|
|
FlagsUCQ []ExerciceFlag `toml:"flag_ucq"`
|
2018-01-10 02:45:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-09 18:07:08 +00:00
|
|
|
// parseExerciceParams reads challenge definitions from defines.txt and extract usefull data to set up the challenge.
|
2019-07-21 20:31:43 +00:00
|
|
|
func parseExerciceParams(i Importer, exPath string) (p ExerciceParams, md toml.MetaData, err error) {
|
2018-01-10 02:45:56 +00:00
|
|
|
var defs string
|
2022-05-24 19:52:58 +00:00
|
|
|
defs, err = GetFileContent(i, path.Join(exPath, "challenge.txt"))
|
2019-07-21 20:31:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2018-01-10 02:45:56 +00:00
|
|
|
|
2019-07-21 20:31:43 +00:00
|
|
|
md, err = toml.Decode(defs, &p)
|
2018-01-10 02:45:56 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2019-07-05 20:28:56 +00:00
|
|
|
|
|
|
|
// getExerciceParams returns normalized
|
2022-07-01 22:01:05 +00:00
|
|
|
func getExerciceParams(i Importer, exercice *fic.Exercice) (params ExerciceParams, errs []error) {
|
2019-07-05 20:28:56 +00:00
|
|
|
var err error
|
2019-07-21 20:31:43 +00:00
|
|
|
if params, _, err = parseExerciceParams(i, exercice.Path); err != nil {
|
2022-07-11 17:57:33 +00:00
|
|
|
errs = append(errs, NewChallengeTxtError(exercice, 0, err))
|
2019-07-05 20:28:56 +00:00
|
|
|
} else if len(params.Flags) == 0 && len(params.FlagsUCQ) == 0 && len(params.FlagsMCQ) == 0 {
|
2022-07-11 17:57:33 +00:00
|
|
|
errs = append(errs, NewChallengeTxtError(exercice, 0, fmt.Errorf("has no flag")))
|
2019-07-05 20:28:56 +00:00
|
|
|
} 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,
|
2020-09-07 17:33:09 +00:00
|
|
|
Placeholder: flag.Placeholder,
|
2019-07-05 20:28:56 +00:00
|
|
|
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
|
|
|
|
}
|
2022-10-31 17:52:29 +00:00
|
|
|
|
|
|
|
func GetExerciceFilesParams(i Importer, exercice *fic.Exercice) (map[string]ExerciceFile, error) {
|
|
|
|
params, _, err := parseExerciceParams(i, exercice.Path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
paramsFiles := map[string]ExerciceFile{}
|
|
|
|
for _, f := range params.Files {
|
|
|
|
paramsFiles[f.Filename] = f
|
|
|
|
}
|
|
|
|
|
|
|
|
return paramsFiles, nil
|
|
|
|
}
|