Justified MCQ are back!

This commit is contained in:
nemunaire 2022-10-31 21:55:43 +01:00
parent a28f108b8a
commit 960122dfb6
5 changed files with 44 additions and 20 deletions

View File

@ -253,6 +253,7 @@ func buildKeyFlag(exercice *fic.Exercice, flag ExerciceFlag, flagline int, defau
type importFlag struct { type importFlag struct {
Line int Line int
Flag fic.Flag Flag fic.Flag
JustifyOf *fic.MCQ_entry
Choices []*fic.FlagChoice Choices []*fic.FlagChoice
FilesDeps []string FilesDeps []string
FlagsDeps []int64 FlagsDeps []int64
@ -272,7 +273,7 @@ func iface2Number(input interface{}, output *string) error {
return nil return nil
} }
// buildExerciceFlags read challenge.txt and extract all flags. // buildExerciceFlag read challenge.txt and extract all flags.
func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nline int, exceptions *CheckExceptions) (ret []importFlag, errs []error) { func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nline int, exceptions *CheckExceptions) (ret []importFlag, errs []error) {
switch strings.ToLower(flag.Type) { switch strings.ToLower(flag.Type) {
case "": case "":
@ -395,10 +396,11 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl
continue continue
} }
addedFlag.Entries = append(addedFlag.Entries, &fic.MCQ_entry{ entry := &fic.MCQ_entry{
Label: choice.Label, Label: choice.Label,
Response: val, Response: val,
}) }
addedFlag.Entries = append(addedFlag.Entries, entry)
if isJustified && choice.Raw != nil { if isJustified && choice.Raw != nil {
addedFlag, choices, berrs := buildKeyFlag(exercice, choice.ExerciceFlag, nline+1, "Flag correspondant", exceptions) addedFlag, choices, berrs := buildKeyFlag(exercice, choice.ExerciceFlag, nline+1, "Flag correspondant", exceptions)
@ -407,9 +409,10 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl
} }
if addedFlag != nil { if addedFlag != nil {
ret = append(ret, importFlag{ ret = append(ret, importFlag{
Line: nline + 1, Line: nline + 1,
Flag: *addedFlag, Flag: *addedFlag,
Choices: choices, JustifyOf: entry,
Choices: choices,
}) })
} }
} }
@ -422,10 +425,10 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl
} }
} }
ret = append(ret, importFlag{ ret = append([]importFlag{importFlag{
Line: nline + 1, Line: nline + 1,
Flag: &addedFlag, Flag: &addedFlag,
}) }}, ret...)
} }
return return
} }
@ -548,6 +551,12 @@ func SyncExerciceFlags(i Importer, exercice *fic.Exercice, exceptions *CheckExce
// Import flags // Import flags
for _, flagid := range flagids { for _, flagid := range flagids {
if flag, ok := flags[flagid]; ok { if flag, ok := flags[flagid]; ok {
if flag.JustifyOf != nil {
if f, ok := flag.Flag.(*fic.FlagKey); ok {
f.Label = fmt.Sprintf("%%%d%%%s", flag.JustifyOf.Id, f.Label)
}
}
if addedFlag, err := exercice.AddFlag(flag.Flag); err != nil { if addedFlag, err := exercice.AddFlag(flag.Flag); err != nil {
errs = append(errs, NewFlagError(exercice, nil, flag.Line, err)) errs = append(errs, NewFlagError(exercice, nil, flag.Line, err))
} else { } else {

View File

@ -211,6 +211,7 @@
/> />
{:else} {:else}
<FlagKey <FlagKey
class="mb-3"
exercice_id={exercice.id} exercice_id={exercice.id}
{flag} {flag}
bind:value={responses.flags[flag.id]} bind:value={responses.flags[flag.id]}

View File

@ -9,8 +9,12 @@
import { my } from '$lib/stores/my.js'; import { my } from '$lib/stores/my.js';
import { settings } from '$lib/stores/settings.js'; import { settings } from '$lib/stores/settings.js';
export { className as class };
let className = '';
export let exercice_id = 0; export let exercice_id = 0;
export let flag = { }; export let flag = { };
export let no_label = false;
export let value = ""; export let value = "";
let values = [""]; let values = [""];
@ -99,13 +103,15 @@
} }
</script> </script>
<div class="form-group mb-3"> <div class={className + " form-group"}>
{#if flag.bonus_gain} {#if flag.bonus_gain}
<div class={'float-end badge bg-' + (flag.found?'success':'danger')} title={'Ce flag est optionnel, si vous le complétez il vous rapportera ' + flag.bonus_gain + ' points supplémentaires'}> <div class={'float-end badge bg-' + (flag.found?'success':'danger')} title={'Ce flag est optionnel, si vous le complétez il vous rapportera ' + flag.bonus_gain + ' points supplémentaires'}>
optionnel | {#if flag.bonus_gain > 0}+{/if}{flag.bonus_gain}&nbsp;pts optionnel | {#if flag.bonus_gain > 0}+{/if}{flag.bonus_gain}&nbsp;pts
</div> </div>
{/if} {/if}
<label for="sol_{flag.type}{flag.id}_0">{flag.label}&nbsp;:</label> {#if !no_label}
<label for="sol_{flag.type}{flag.id}_0">{flag.label}&nbsp;:</label>
{/if}
{#if flag.found && flag.value} {#if flag.found && flag.value}
<span>{flag.value}</span> <span>{flag.value}</span>
{/if} {/if}

View File

@ -23,19 +23,27 @@
{#if !flag.found || flag.justify} {#if !flag.found || flag.justify}
{#each Object.keys(flag.choices) as cid, index} {#each Object.keys(flag.choices) as cid, index}
<div class="form-check ms-3"> <div class="form-check ms-3">
<input class="form-check-input" type="checkbox" id="mcq_{flag.id}_{cid}" bind:checked={values[Number(cid)]} disabled={flag.found}> {#if typeof flag.choices[cid] != "object"}
<label class="form-check-label" for="mcq_{flag.id}_{cid}"> <input class="form-check-input" type="checkbox" id="mcq_{flag.id}_{cid}" bind:checked={values[Number(cid)]} disabled={flag.found || flag.part_solved}>
{#if typeof flag.choices[cid] == "Object"} <label class="form-check-label" for="mcq_{flag.id}_{cid}">
{flag.choices[cid].label} {flag.choices[cid]}{#if values[Number(cid)] && flag.justify}&nbsp;:{/if}
{:else} </label>
{flag.choices[cid]} {#if values[Number(cid)] && flag.justify}
<FlagKey
class="mb-3"
{exercice_id}
flag={{id: cid, placeholder: "Flag correspondant"}}
no_label={true}
bind:value={justifications[cid]}
/>
{/if} {/if}
</label> {:else}
{#if values[Number(cid)] && flag.justify && (!flag.choices[cid].justification || !flag.choices[cid].justification.solved)} <input class="form-check-input" type="checkbox" id="mcq_{flag.id}_{cid}" checked disabled>
<FlagKey <FlagKey
class={flag.choices[cid].justification.found?"":"mb-3"}
{exercice_id} {exercice_id}
flag={flag.choices[cid].justification} flag={flag.choices[cid].justification}
bind:values={justifications[flag.choices[cid].justification.id]} bind:value={justifications[cid]}
/> />
{/if} {/if}
{#if flag.choices[cid].justification && flag.choices[cid].justification.solved} {#if flag.choices[cid].justification && flag.choices[cid].justification.solved}

View File

@ -141,7 +141,7 @@ func (e *Exercice) GetFlagKey(id int) (k *FlagKey, err error) {
// GetFlagKeyByLabel returns a flag matching the given label. // GetFlagKeyByLabel returns a flag matching the given label.
func (e *Exercice) GetFlagKeyByLabel(label string) (k *FlagKey, err error) { func (e *Exercice) GetFlagKeyByLabel(label string) (k *FlagKey, err error) {
k = &FlagKey{} k = &FlagKey{}
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost, bonus_gain FROM exercice_flags WHERE type LIKE ? AND id_exercice = ?", label, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost, &k.BonusGain) err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, notrim, multiline, validator_regexp, sort_re_grps, cksum, choices_cost, bonus_gain FROM exercice_flags WHERE label LIKE ? AND id_exercice = ?", label, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.NoTrim, &k.Multiline, &k.ValidatorRegexp, &k.SortReGroups, &k.Checksum, &k.ChoicesCost, &k.BonusGain)
return return
} }