Dependancy between flags
This commit is contained in:
parent
711db60a4c
commit
f9abdd23c6
8 changed files with 111 additions and 1 deletions
|
|
@ -18,6 +18,7 @@ Tous les textes doivent utiliser l'encodage UTF8.
|
|||
* `id = CHID` : identifiant du challenge ;
|
||||
* `theme = "NomDuTheme"` : (facultatif) nom du thème dans lequel aller chercher l'identifiant (par défaut, on prend le thème courant) ;
|
||||
- `[[flag]]` : drapeau classique à valider pour résoudre le challenge :
|
||||
* `id = 42` : (facultatif) identifiant du flag au sein de l'exercice, pour définir des dépendances ;
|
||||
* `label = "Intitulé"` : (facultatif, par défaut : `Flag`) intitulé du drapeau ;
|
||||
* `raw = 'MieH2athxuPhai6u'` : drapeau exact à trouver ;
|
||||
* `validator_regexp = "^(?:sudo +)?(.*)$"` : (facultatif) expression rationnelle dont les groupes capturés serviront comme chaîne à valider (notez que `?:` au début d'un groupe ne le capturera pas) ;
|
||||
|
|
@ -25,6 +26,8 @@ Tous les textes doivent utiliser l'encodage UTF8.
|
|||
* `help = "Indication"` : (facultatif) chaîne de caractères placée sous le champ du formulaire, idéale pour donner une indication de format ;
|
||||
* `[[flag.unlock_file]]` : bloque l'accès à un fichier tant que le flag n'est pas obtenu :
|
||||
+ `filename = "toto.txt"` : nom du fichier tel qu'il apparaît dans le dossier `files` ;
|
||||
* `[[flag.need_flag]]` : liste des flags devant être validés avant de débloquer celui-ci :
|
||||
+ `id = 23` : identifiant du flag tel qu'il a été défini plus tôt dans le fichier ;
|
||||
- `[[flag_mcq]]` : drapeau sous forme de question à choix multiple (cases à cocher) :
|
||||
* `label = "Intitulé du groupe"` : (facultatif) intitulé du groupe de choix ;
|
||||
* `[[flag_mcq.choice]]` : représente un choix, répétez autant de fois qu'il y a de choix :
|
||||
|
|
@ -32,6 +35,7 @@ Tous les textes doivent utiliser l'encodage UTF8.
|
|||
+ `value = true` : (facultatif, par défaut `false`) valeur attendue pour ce choix ; pour un QCM justifié, utilisez une chaîne de caractères (notez qu'il n'est pas possible de combiner des réponses vraies justifiées et justifiées),
|
||||
+ `help = "Flag correspondant"` : (facultatif) indication affichée dans le champ de texte des QCM justifiés ;
|
||||
- `[[flag_ucq]]` : drapeau sous forme de question à choix unique :
|
||||
* `id = 42` : (facultatif) identifiant du flag au sein de l'exercice, pour définir des dépendances ;
|
||||
* `label = "Intitulé du groupe"` : (facultatif) intitulé du groupe de choix ;
|
||||
* `raw = 'MieH2athxuPhai6u'` : drapeau attendu parmi les propositions ;
|
||||
* `validator_regexp = "^(?:sudo +)?(.*)$"` : (facultatif) expression rationnelle dont les groupes capturés serviront comme chaîne à valider (notez que `?:` au début d'un groupe ne le capturera pas) ;
|
||||
|
|
@ -43,6 +47,8 @@ Tous les textes doivent utiliser l'encodage UTF8.
|
|||
+ `label = "Intitulé de la réponse"` : (facultatif, par défaut identique à `value`) ;
|
||||
* `[[flag_ucq.unlock_file]]` : bloque l'accès à un fichier tant que le flag n'est pas obtenu :
|
||||
+ `filename = "toto.txt"` : nom du fichier tel qu'il apparaît dans le dossier `files` ;
|
||||
* `[[flag_ucq.need_flag]]` : liste des flags devant être validés avant de débloquer celui-ci :
|
||||
+ `id = 23` : identifiant du flag tel qu'il a été défini plus tôt dans le fichier ;
|
||||
- `[[hint]]` : paramètres pour un indice :
|
||||
* `filename = "toto.txt"` : (mutuellement exclusif avec `content`) nom du fichier tel qu'il apparaît dans le dossier `hints` ;
|
||||
* `content = "Contenu de l'indice"` : (mutuellement exclusif avec `filename`) contenu de l'indice affiché, en markdown ;
|
||||
|
|
|
|||
|
|
@ -27,12 +27,14 @@ type ExerciceUnlockFile struct {
|
|||
|
||||
// ExerciceFlag holds informations about a "classic" flag.
|
||||
type ExerciceFlag struct {
|
||||
Id int64
|
||||
Label string `toml:",omitempty"`
|
||||
Raw string
|
||||
IgnoreCase bool `toml:",omitempty"`
|
||||
ValidatorRe string `toml:"validator_regexp,omitempty"`
|
||||
Help string `toml:",omitempty"`
|
||||
LockedFile []ExerciceUnlockFile `toml:"unlock_file,omitempty"`
|
||||
NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"`
|
||||
}
|
||||
|
||||
// ExerciceFlagMCQChoice holds a choice for an MCQ flag.
|
||||
|
|
@ -57,6 +59,7 @@ type ExerciceFlagUCQChoice struct {
|
|||
|
||||
// ExerciceFlagUCQ holds information about a UCQ flag.
|
||||
type ExerciceFlagUCQ struct {
|
||||
Id int64
|
||||
Label string `toml:",omitempty"`
|
||||
Raw string
|
||||
IgnoreCase bool `toml:",omitempty"`
|
||||
|
|
@ -66,6 +69,7 @@ type ExerciceFlagUCQ struct {
|
|||
Choices_Cost int64 `toml:",omitempty"`
|
||||
Choice []ExerciceFlagUCQChoice
|
||||
LockedFile []ExerciceUnlockFile `toml:"unlock_file,omitempty"`
|
||||
NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"`
|
||||
NoShuffle bool
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ func SyncExerciceFlags(i Importer, exercice fic.Exercice) (errs []string) {
|
|||
} 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 {
|
||||
kmap := map[int64]fic.Flag{}
|
||||
|
||||
// Import normal flags
|
||||
for nline, flag := range params.Flags {
|
||||
if len(flag.Label) == 0 {
|
||||
|
|
@ -54,6 +56,21 @@ func SyncExerciceFlags(i Importer, exercice fic.Exercice) (errs []string) {
|
|||
errs = append(errs, fmt.Sprintf("%q: error flag #%d: %s", path.Base(exercice.Path), nline + 1, err))
|
||||
continue
|
||||
} else {
|
||||
if flag.Id != 0 {
|
||||
kmap[flag.Id] = k
|
||||
}
|
||||
|
||||
// Import dependency to flag
|
||||
for _, nf := range flag.NeedFlag {
|
||||
if rf, ok := kmap[nf.Id]; !ok {
|
||||
errs = append(errs, fmt.Sprintf("%q: error flag #%d dependency to flag id=%s: id not defined, perhaps not available at time of processing", path.Base(exercice.Path), nline + 1, nf.Id))
|
||||
continue
|
||||
} else if err := k.AddDepend(rf); err != nil {
|
||||
errs = append(errs, fmt.Sprintf("%q: error flag #%d dependency to %s: %s", path.Base(exercice.Path), nline + 1, nf.Id, err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Import dependency to file
|
||||
for _, lf := range flag.LockedFile {
|
||||
if rf, err := exercice.GetFileByFilename(lf.Filename); err != nil {
|
||||
|
|
@ -81,6 +98,22 @@ func SyncExerciceFlags(i Importer, exercice fic.Exercice) (errs []string) {
|
|||
errs = append(errs, fmt.Sprintf("%q: error flag UCQ #%d: %s", path.Base(exercice.Path), nline + 1, err))
|
||||
continue
|
||||
} else {
|
||||
// Import dependency to file
|
||||
if flag.Id != 0 {
|
||||
kmap[flag.Id] = k
|
||||
}
|
||||
|
||||
// Import dependency to flag
|
||||
for _, nf := range flag.NeedFlag {
|
||||
if rf, ok := kmap[nf.Id]; !ok {
|
||||
errs = append(errs, fmt.Sprintf("%q: error flag #%d dependency to flag id=%s: id not defined, perhaps not available at time of processing", path.Base(exercice.Path), nline + 1, nf.Id))
|
||||
continue
|
||||
} else if err := k.AddDepend(rf); err != nil {
|
||||
errs = append(errs, fmt.Sprintf("%q: error flag #%d dependency to %s: %s", path.Base(exercice.Path), nline + 1, nf.Id, err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Import dependency to file
|
||||
for _, lf := range flag.LockedFile {
|
||||
if rf, err := exercice.GetFileByFilename(lf.Filename); err != nil {
|
||||
|
|
|
|||
Reference in a new issue