From d7553f0392bd855b84ae1337a911cf1bb41b9eb5 Mon Sep 17 00:00:00 2001 From: nemunaire Date: Wed, 21 Nov 2018 04:40:32 +0100 Subject: [PATCH] Handle justified MCQ in admin and sync part --- admin/sync/README.md | 4 +-- admin/sync/exercice_defines.go | 2 +- admin/sync/exercice_keys.go | 30 +++++++++++++++++-- libfic/team_my.go | 54 +++++++++++++++++++--------------- 4 files changed, 62 insertions(+), 28 deletions(-) diff --git a/admin/sync/README.md b/admin/sync/README.md index 428a9e6b..30f9b31d 100644 --- a/admin/sync/README.md +++ b/admin/sync/README.md @@ -27,7 +27,7 @@ Tous les textes doivent utiliser l'encodage UTF8. * `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 : + `label = "Intitulé de la réponse"`, - + `value = true` : (facultatif, par défaut `false`) valeur attendue pour ce choix ; + + `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) ; - `[[flag_ucq]]` : drapeau sous forme de question à choix unique : * `label = "Intitulé du groupe"` : (facultatif) intitulé du groupe de choix ; * `raw = 'MieH2athxuPhai6u'` : drapeau attendu parmi les propositions ; @@ -221,5 +221,5 @@ Exemple `DIGESTS.txt` {#exemple-digeststxt} --- title: Format des répertoires pour la synchronisation author: FIC team 2019 -date: "Dernière mise à jour du document : 17 août 2018" +date: "Dernière mise à jour du document : 27 novembre 2018" --- diff --git a/admin/sync/exercice_defines.go b/admin/sync/exercice_defines.go index 641984e5..c1958bdb 100644 --- a/admin/sync/exercice_defines.go +++ b/admin/sync/exercice_defines.go @@ -38,7 +38,7 @@ type ExerciceFlag struct { // ExerciceFlagMCQChoice holds a choice for an MCQ flag. type ExerciceFlagMCQChoice struct { Label string - Value bool `toml:",omitempty"` + Value interface{} `toml:",omitempty"` } // ExerciceFlagMCQ holds information about a MCQ flag. diff --git a/admin/sync/exercice_keys.go b/admin/sync/exercice_keys.go index 4f0c8d6c..ab8e62f2 100644 --- a/admin/sync/exercice_keys.go +++ b/admin/sync/exercice_keys.go @@ -120,13 +120,39 @@ func SyncExerciceFlags(i Importer, exercice fic.Exercice) (errs []string) { continue } else { hasOne := false + isJustified := false for cid, choice := range quest.Choice { - if _, err := flag.AddEntry(choice.Label, choice.Value); err != nil { + var val bool + if choice.Value == nil { + val = false + } 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 p, ok := choice.Value.(string); ok { + val = true + 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 + } + isJustified = true + if _, err := exercice.AddRawFlag("%" + quest.Label + "%" + choice.Label, "", false, nil, []byte(p)); err != nil { + errs = append(errs, fmt.Sprintf("%q: error MCQ #%d: %s", path.Base(exercice.Path), nline + 1, err)) + continue + } + } else { + errs = append(errs, fmt.Sprintf("%q: error in MCQ %d choice %d: has an invalid type. Expected true, false or a string", path.Base(exercice.Path), nline + 1, cid)) + continue + } + + if _, err := flag.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 } - if choice.Value { + if val { hasOne = true } } diff --git a/libfic/team_my.go b/libfic/team_my.go index e986a7c9..5881b313 100644 --- a/libfic/team_my.go +++ b/libfic/team_my.go @@ -23,6 +23,7 @@ type myTeamHint struct { } type myTeamMCQ struct { Title string `json:"title"` + Justify bool `json:"justify,omitempty"` Choices map[int64]string `json:"choices,omitempty"` Solved *time.Time `json:"solved,omitempty"` } @@ -146,6 +147,28 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) { } } + // Expose exercice flags + + var justifiedMCQ map[string]bool + exercice.Flags = []string{} + + if flags, err := e.GetFlags(); err != nil { + return nil, err + } else { + for _, k := range flags { + if k.Label[0] == '%' { + justifiedMCQ[k.Label[1:]] = true + } else if t == nil { + exercice.Flags = append(exercice.Flags, fmt.Sprintf("%x", k.Checksum)+k.Label) + } else { + exercice.Flags = append(exercice.Flags, k.Label) + if PartialValidation { + exercice.SolvedMat = append(exercice.SolvedMat, t.HasPartiallySolved(k) != nil) + } + } + } + } + // Expose exercice MCQs exercice.MCQs = []myTeamMCQ{} @@ -155,33 +178,18 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) { } else { for _, mcq := range mcqs { choices := map[int64]string{} + justified := false for _, e := range mcq.Entries { choices[e.Id] = e.Label - } - if t == nil { - exercice.MCQs = append(exercice.MCQs, myTeamMCQ{mcq.Title, choices, nil}) - } else { - exercice.MCQs = append(exercice.MCQs, myTeamMCQ{mcq.Title, choices, t.HasPartiallyRespond(mcq)}) - } - } - } - - // Expose exercice flags - - exercice.Flags = []string{} - - if flags, err := e.GetFlags(); err != nil { - return nil, err - } else { - for _, k := range flags { - if t == nil { - exercice.Flags = append(exercice.Flags, fmt.Sprintf("%x", k.Checksum)+k.Label) - } else { - exercice.Flags = append(exercice.Flags, k.Label) - if PartialValidation { - exercice.SolvedMat = append(exercice.SolvedMat, t.HasPartiallySolved(k) != nil) + if _, ok := justifiedMCQ[m.Title + "%" + e.Label]; ok { + justified = true } } + if t == nil { + exercice.MCQs = append(exercice.MCQs, myTeamMCQ{mcq.Title, justified, choices, nil}) + } else { + exercice.MCQs = append(exercice.MCQs, myTeamMCQ{mcq.Title, justified, choices, t.HasPartiallyRespond(mcq)}) + } } }