Utilise a new field to send justifications instead of too complex guessing crap
This commit is contained in:
parent
69a866bbbf
commit
d40922629b
6 changed files with 69 additions and 24 deletions
|
@ -19,6 +19,7 @@ import (
|
||||||
type ResponsesUpload struct {
|
type ResponsesUpload struct {
|
||||||
Keys map[int64]string `json:"flags"`
|
Keys map[int64]string `json:"flags"`
|
||||||
MCQs map[int64]bool `json:"mcqs"`
|
MCQs map[int64]bool `json:"mcqs"`
|
||||||
|
MCQJ map[int64]string `json:"justifications"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func treatSubmission(pathname string, team fic.Team, exercice_id string) {
|
func treatSubmission(pathname string, team fic.Team, exercice_id string) {
|
||||||
|
@ -78,6 +79,25 @@ func treatSubmission(pathname string, team fic.Team, exercice_id string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle MCQ justifications: convert to expected keyid
|
||||||
|
for cid, j := range responses.MCQJ {
|
||||||
|
if mcq, choice, err := fic.GetMCQbyChoice(cid); err != nil {
|
||||||
|
log.Println(id, "[ERR] Unable to retrieve mcq from justification:", err)
|
||||||
|
return
|
||||||
|
} else if mcq.IdExercice != exercice.Id {
|
||||||
|
log.Println(id, "[ERR] We retrieve an invalid MCQ: from exercice", mcq.IdExercice, "whereas expected from exercice", exercice.Id)
|
||||||
|
return
|
||||||
|
} else if key, err := mcq.GetJustifiedFlag(exercice, choice); err != nil {
|
||||||
|
log.Println(id, "[ERR] Unable to retrieve mcq justification flag:", err)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if responses.Keys == nil {
|
||||||
|
responses.Keys = map[int64]string{}
|
||||||
|
}
|
||||||
|
responses.Keys[key.Id] = j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check given answers
|
// Check given answers
|
||||||
solved, err := exercice.CheckResponse(cksum[:], responses.Keys, responses.MCQs, team)
|
solved, err := exercice.CheckResponse(cksum[:], responses.Keys, responses.MCQs, team)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -268,11 +268,12 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"])
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.ssubmit = function() {
|
$scope.ssubmit = function() {
|
||||||
var resp = {"flags":{}}
|
var resp = {}
|
||||||
var check = undefined
|
var check = undefined
|
||||||
|
|
||||||
if ($scope.my.exercices[$rootScope.current_exercice].flags && Object.keys($scope.my.exercices[$rootScope.current_exercice].flags).length)
|
if ($scope.my.exercices[$rootScope.current_exercice].flags && Object.keys($scope.my.exercices[$rootScope.current_exercice].flags).length)
|
||||||
{
|
{
|
||||||
|
resp["flags"] = {};
|
||||||
angular.forEach($scope.my.exercices[$rootScope.current_exercice].flags, function(flag,kid) {
|
angular.forEach($scope.my.exercices[$rootScope.current_exercice].flags, function(flag,kid) {
|
||||||
if (flag.found == null) {
|
if (flag.found == null) {
|
||||||
if (flag.soluce !== undefined) {
|
if (flag.soluce !== undefined) {
|
||||||
|
@ -293,7 +294,6 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"])
|
||||||
var soluce = "";
|
var soluce = "";
|
||||||
resp["mcqs"] = {};
|
resp["mcqs"] = {};
|
||||||
angular.forEach($scope.my.exercices[$rootScope.current_exercice].mcqs, function(mcq) {
|
angular.forEach($scope.my.exercices[$rootScope.current_exercice].mcqs, function(mcq) {
|
||||||
var nid = 0;
|
|
||||||
if (mcq.solved == null) {
|
if (mcq.solved == null) {
|
||||||
angular.forEach(mcq.choices, function(choice, cid) {
|
angular.forEach(mcq.choices, function(choice, cid) {
|
||||||
if (mcq.soluce !== undefined) {
|
if (mcq.soluce !== undefined) {
|
||||||
|
@ -304,10 +304,10 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"])
|
||||||
if (choice.value) {
|
if (choice.value) {
|
||||||
resp["mcqs"][cid] = choice.value;
|
resp["mcqs"][cid] = choice.value;
|
||||||
if (mcq.justify !== undefined) {
|
if (mcq.justify !== undefined) {
|
||||||
|
if (resp["justifications"] == undefined)
|
||||||
|
resp["justifications"] = {};
|
||||||
if (choice.justify)
|
if (choice.justify)
|
||||||
resp["flags"][mcq.justify[nid++]] = choice.justify;
|
resp["justifications"][cid] = choice.justify;
|
||||||
else if (!choice.solved)
|
|
||||||
nid++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
<div class="custom-control custom-checkbox" ng-repeat="(cid,choice) in mcq.choices" ng-if="!mcq.solved">
|
<div class="custom-control custom-checkbox" ng-repeat="(cid,choice) in mcq.choices" ng-if="!mcq.solved">
|
||||||
<input class="custom-control-input" type="checkbox" id="mcq_{{k}}_{{cid}}" name="mcq_{{k}}_{{cid}}" ng-model="choice.value" ng-disabled="choice.disabled">
|
<input class="custom-control-input" type="checkbox" id="mcq_{{k}}_{{cid}}" name="mcq_{{k}}_{{cid}}" ng-model="choice.value" ng-disabled="choice.disabled">
|
||||||
<label class="custom-control-label" for="mcq_{{k}}_{{cid}}" ng-bind="choice.label"></label>
|
<label class="custom-control-label" for="mcq_{{k}}_{{cid}}" ng-bind="choice.label"></label>
|
||||||
<input type="text" class="form-control" autocomplete="off" placeholder="Flag correspondant" name="sol_{{ cid }}" ng-model="choice.justify" ng-if="choice.value && mcq.justify.length && !choice.solved">
|
<input type="text" class="form-control" autocomplete="off" placeholder="Flag correspondant" name="sol_{{ cid }}" ng-model="choice.justify" ng-if="choice.value && mcq.justify && !choice.solved">
|
||||||
<span class="glyphicon glyphicon-ok form-control-feedback text-success" aria-hidden="true" ng-if="choice.solved" title="Flag trouvé !"></span>
|
<span class="glyphicon glyphicon-ok form-control-feedback text-success" aria-hidden="true" ng-if="choice.solved" title="Flag trouvé !"></span>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
|
@ -52,6 +52,12 @@ func (e Exercice) GetFlags() ([]Flag, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFlagByLabel returns a flag matching the given label.
|
||||||
|
func (e Exercice) GetFlagByLabel(label string) (k Flag, err error) {
|
||||||
|
err = DBQueryRow("SELECT id_flag, id_exercice, type, help, ignorecase, validator_regexp, cksum FROM exercice_flags WHERE type = ? AND id_exercice = ?", label, e.Id).Scan(&k.Id, &k.IdExercice, &k.Label, &k.Help, &k.IgnoreCase, &k.ValidatorRegexp, &k.Checksum)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// getHashedFlag calculates the expected checksum for the given raw_value.
|
// getHashedFlag calculates the expected checksum for the given raw_value.
|
||||||
func getHashedFlag(raw_value []byte) [blake2b.Size]byte {
|
func getHashedFlag(raw_value []byte) [blake2b.Size]byte {
|
||||||
hash := blake2b.Sum512(raw_value)
|
hash := blake2b.Sum512(raw_value)
|
||||||
|
|
|
@ -66,6 +66,35 @@ func (e Exercice) GetMCQ() ([]MCQ, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMCQbyChoice returns the MCQ corresponding to a choice ID.
|
||||||
|
func GetMCQbyChoice(cid int64) (m MCQ, c MCQ_entry, err error) {
|
||||||
|
if errr := DBQueryRow("SELECT id_mcq, id_exercice, title FROM exercice_mcq WHERE id_mcq = (SELECT id_mcq FROM mcq_entries WHERE id_mcq_entry = ?)", cid).Scan(&m.Id, &m.IdExercice, &m.Title); err != nil {
|
||||||
|
return MCQ{}, MCQ_entry{}, errr
|
||||||
|
}
|
||||||
|
|
||||||
|
if entries_rows, errr := DBQuery("SELECT id_mcq_entry, label, response FROM mcq_entries WHERE id_mcq = ?", m.Id); err != nil {
|
||||||
|
return MCQ{}, MCQ_entry{}, errr
|
||||||
|
} else {
|
||||||
|
defer entries_rows.Close()
|
||||||
|
|
||||||
|
for entries_rows.Next() {
|
||||||
|
var e MCQ_entry
|
||||||
|
|
||||||
|
if err = entries_rows.Scan(&e.Id, &e.Label, &e.Response); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Id == cid {
|
||||||
|
c = e
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Entries = append(m.Entries, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// AddMCQ creates and fills a new struct MCQ and registers it into the database.
|
// AddMCQ creates and fills a new struct MCQ and registers it into the database.
|
||||||
func (e Exercice) AddMCQ(title string) (MCQ, error) {
|
func (e Exercice) AddMCQ(title string) (MCQ, error) {
|
||||||
if res, err := DBExec("INSERT INTO exercice_mcq (id_exercice, title) VALUES (?, ?)", e.Id, title); err != nil {
|
if res, err := DBExec("INSERT INTO exercice_mcq (id_exercice, title) VALUES (?, ?)", e.Id, title); err != nil {
|
||||||
|
@ -145,6 +174,11 @@ func (e Exercice) WipeMCQs() (int64, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetJustifiedFlag searchs for a flag in the scope of the given exercice.
|
||||||
|
func (m MCQ) GetJustifiedFlag(e Exercice, c MCQ_entry) (Flag, error) {
|
||||||
|
return e.GetFlagByLabel("%" + m.Title + "%" + c.Label)
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the given vals are the expected ones to validate this flag.
|
// Check if the given vals are the expected ones to validate this flag.
|
||||||
func (m MCQ) Check(vals map[int64]bool) int {
|
func (m MCQ) Check(vals map[int64]bool) int {
|
||||||
diff := 0
|
diff := 0
|
||||||
|
|
|
@ -23,7 +23,7 @@ type myTeamHint struct {
|
||||||
}
|
}
|
||||||
type myTeamMCQ struct {
|
type myTeamMCQ struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Justify []int64 `json:"justify,omitempty"`
|
Justify bool `json:"justify,omitempty"`
|
||||||
Choices map[int64]string `json:"choices,omitempty"`
|
Choices map[int64]string `json:"choices,omitempty"`
|
||||||
Solved *time.Time `json:"solved,omitempty"`
|
Solved *time.Time `json:"solved,omitempty"`
|
||||||
PSolved map[int64]int `json:"checks_solved,omitempty"`
|
PSolved map[int64]int `json:"checks_solved,omitempty"`
|
||||||
|
@ -211,8 +211,6 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
||||||
|
|
||||||
soluce := ""
|
soluce := ""
|
||||||
solved_justify := true
|
solved_justify := true
|
||||||
var nb_gen_justify_id int64
|
|
||||||
var max_justify_id int64
|
|
||||||
|
|
||||||
for _, e := range mcq.Entries {
|
for _, e := range mcq.Entries {
|
||||||
m.Choices[e.Id] = e.Label
|
m.Choices[e.Id] = e.Label
|
||||||
|
@ -222,29 +220,16 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
||||||
soluce += "f"
|
soluce += "f"
|
||||||
}
|
}
|
||||||
if v, ok := justifiedMCQ[m.Title + "%" + e.Label]; ok {
|
if v, ok := justifiedMCQ[m.Title + "%" + e.Label]; ok {
|
||||||
if m.Justify == nil {
|
m.Justify = true
|
||||||
m.Justify = []int64{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if t == nil {
|
if t == nil {
|
||||||
soluce += hex.EncodeToString(v)
|
soluce += hex.EncodeToString(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, ok := justifiedMCQ_ids[m.Title + "%" + e.Label]; ok {
|
if _, ok := justifiedMCQ_ids[m.Title + "%" + e.Label]; ok {
|
||||||
solved_justify = false
|
solved_justify = false
|
||||||
m.Justify = append(m.Justify, v)
|
|
||||||
if v > max_justify_id {
|
|
||||||
max_justify_id = v
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
nb_gen_justify_id += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill the rest of the array with factice values in order to hide number of valid choices
|
|
||||||
for i := int64(0); i < nb_gen_justify_id; i++ {
|
|
||||||
m.Justify = append(m.Justify, max_justify_id + 1 + i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if t != nil {
|
if t != nil {
|
||||||
|
|
Reference in a new issue