Able to check MCQ
This commit is contained in:
parent
a51aa38d74
commit
e31f325177
|
@ -14,17 +14,22 @@ import (
|
|||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
||||
type ResponsesUpload struct {
|
||||
Keys map[string]string `json:"flags"`
|
||||
MCQs map[int64]bool `json:"mcqs"`
|
||||
}
|
||||
|
||||
func treatSubmission(pathname string, team fic.Team, exercice_id string) {
|
||||
bid := make([]byte, 5)
|
||||
binary.LittleEndian.PutUint32(bid, rand.Uint32())
|
||||
id := "[" + base64.StdEncoding.EncodeToString(bid) + "]"
|
||||
log.Println(id, "New submission receive", pathname)
|
||||
|
||||
var keys map[string]string
|
||||
var responses ResponsesUpload
|
||||
|
||||
if cnt_raw, err := ioutil.ReadFile(pathname); err != nil {
|
||||
log.Println(id, "[ERR]", err)
|
||||
} else if err := json.Unmarshal(cnt_raw, &keys); err != nil {
|
||||
} else if err := json.Unmarshal(cnt_raw, &responses); err != nil {
|
||||
log.Println(id, "[ERR]", err)
|
||||
} else if eid, err := strconv.Atoi(exercice_id); err != nil {
|
||||
log.Println(id, "[ERR]", err)
|
||||
|
@ -35,7 +40,7 @@ func treatSubmission(pathname string, team fic.Team, exercice_id string) {
|
|||
} else if s, tm, _ := team.HasSolved(exercice); s {
|
||||
log.Printf("%s [WRN] Team %d ALREADY solved exercice %d (%s : %s)\n", id, team.Id, exercice.Id, theme.Name, exercice.Title)
|
||||
} else {
|
||||
if solved, err := exercice.CheckResponse(keys, team); err != nil {
|
||||
if solved, err := exercice.CheckResponse(responses.Keys, responses.MCQs, team); err != nil {
|
||||
log.Println(id, "[ERR]", err)
|
||||
genTeamMyFile(team)
|
||||
} else if solved {
|
||||
|
|
12
libfic/db.go
12
libfic/db.go
|
@ -160,6 +160,18 @@ CREATE TABLE IF NOT EXISTS mcq_entries(
|
|||
response BOOLEAN NOT NULL,
|
||||
FOREIGN KEY(id_mcq) REFERENCES exercice_mcq(id_mcq)
|
||||
);
|
||||
`); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS mcq_found(
|
||||
id_mcq INTEGER NOT NULL,
|
||||
id_team INTEGER NOT NULL,
|
||||
time TIMESTAMP NOT NULL,
|
||||
CONSTRAINT uq_found UNIQUE (id_mcq,id_team),
|
||||
FOREIGN KEY(id_mcq) REFERENCES exercice_mcq(id_mcq),
|
||||
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
||||
);
|
||||
`); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
)
|
||||
|
||||
var PartialValidation bool
|
||||
var PartialMCQValidation bool
|
||||
|
||||
type Exercice struct {
|
||||
Id int64 `json:"id"`
|
||||
|
@ -202,19 +203,41 @@ func (e Exercice) TriedCount() int64 {
|
|||
}
|
||||
}
|
||||
|
||||
func (e Exercice) CheckResponse(resps map[string]string, t Team) (bool, error) {
|
||||
func (e Exercice) CheckResponse(respkeys map[string]string, respmcq map[int64]bool, t Team) (bool, error) {
|
||||
if err := e.NewTry(t); err != nil {
|
||||
return false, err
|
||||
} else if keys, err := e.GetKeys(); err != nil {
|
||||
return false, err
|
||||
} else if mcqs, err := e.GetMCQ(); err != nil {
|
||||
return false, err
|
||||
} else if len(keys) < 1 && len(mcqs) < 1 {
|
||||
return true, errors.New("Exercice with no key registered")
|
||||
} else {
|
||||
if len(keys) < 1 {
|
||||
return true, errors.New("Exercice with no key registered")
|
||||
valid := true
|
||||
diff := 0
|
||||
|
||||
// Check MCQs
|
||||
for _, mcq := range mcqs {
|
||||
if d := mcq.Check(respmcq); d > 0 {
|
||||
if !PartialValidation || t.HasPartiallyRespond(mcq) == nil {
|
||||
valid = false
|
||||
diff += d
|
||||
}
|
||||
} else if !PartialMCQValidation {
|
||||
mcq.FoundBy(t)
|
||||
}
|
||||
}
|
||||
|
||||
valid := true
|
||||
// Validate MCQs if no error
|
||||
if valid {
|
||||
for _, mcq := range mcqs {
|
||||
mcq.FoundBy(t)
|
||||
}
|
||||
}
|
||||
|
||||
// Check keys
|
||||
for _, key := range keys {
|
||||
if res, ok := resps[key.Label]; !ok {
|
||||
if res, ok := respkeys[key.Label]; !ok {
|
||||
valid = false
|
||||
} else if !key.Check(res) {
|
||||
if !PartialValidation || t.HasPartiallySolved(key) == nil {
|
||||
|
@ -225,6 +248,10 @@ func (e Exercice) CheckResponse(resps map[string]string, t Team) (bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if diff > 0 {
|
||||
e.UpdateTry(t, diff)
|
||||
}
|
||||
|
||||
return valid, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fic
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type MCQ struct {
|
||||
|
@ -32,13 +33,23 @@ func (e Exercice) GetMCQ() ([]MCQ, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if entries_rows, err := DBQuery("SELECT id_mcq, id_exercice, label, response FROM mcq_entries WHERE id_mcq = ?", m.Id); err != nil {
|
||||
if entries_rows, err := DBQuery("SELECT id_mcq_entry, label, response FROM mcq_entries WHERE id_mcq = ?", m.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer entries_rows.Close()
|
||||
|
||||
mcqs = append(mcqs, m)
|
||||
for entries_rows.Next() {
|
||||
var e MCQ_entry
|
||||
|
||||
if err := entries_rows.Scan(&e.Id, &e.Label, &e.Response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.Entries = append(m.Entries, e)
|
||||
}
|
||||
}
|
||||
|
||||
mcqs = append(mcqs, m)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -110,6 +121,7 @@ func (n MCQ_entry) Delete() (int64, error) {
|
|||
|
||||
func (m MCQ) Check(vals map[int64]bool) int {
|
||||
diff := 0
|
||||
|
||||
for _, n := range m.Entries {
|
||||
if v, ok := vals[n.Id]; ok && v == n.Response {
|
||||
continue
|
||||
|
@ -119,3 +131,7 @@ func (m MCQ) Check(vals map[int64]bool) int {
|
|||
|
||||
return diff
|
||||
}
|
||||
|
||||
func (m MCQ) FoundBy(t Team) {
|
||||
DBExec("INSERT INTO mcq_found (id_mcq, id_team, time) VALUES (?, ?, ?)", m.Id, t.Id, time.Now())
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ func truncateTable(tables ...string) (error) {
|
|||
}
|
||||
|
||||
func ResetGame() (error) {
|
||||
return truncateTable("team_hints", "key_found", "exercice_solved", "exercice_tries")
|
||||
return truncateTable("team_hints", "key_found", "mcq_found", "exercice_solved", "exercice_tries")
|
||||
}
|
||||
|
||||
func ResetExercices() (error) {
|
||||
return truncateTable("team_hints", "exercice_files", "key_found", "exercice_keys", "exercice_solved", "exercice_tries", "exercice_hints", "mcq_entries", "exercice_mcq", "exercices", "themes")
|
||||
return truncateTable("team_hints", "exercice_files", "key_found", "exercice_keys", "exercice_solved", "exercice_tries", "exercice_hints", "mcq_found", "mcq_entries", "exercice_mcq", "exercices", "themes")
|
||||
}
|
||||
|
||||
func ResetTeams() (error) {
|
||||
return truncateTable("team_hints", "key_found", "exercice_solved", "exercice_tries", "team_members", "teams")
|
||||
return truncateTable("team_hints", "key_found", "mcq_found", "exercice_solved", "exercice_tries", "team_members", "teams")
|
||||
}
|
||||
|
|
|
@ -173,3 +173,9 @@ func (t Team) HasPartiallySolved(k Key) (*time.Time) {
|
|||
DBQueryRow("SELECT MIN(time) FROM key_found WHERE id_team = ? AND id_key = ?", t.Id, k.Id).Scan(&tm)
|
||||
return tm
|
||||
}
|
||||
|
||||
func (t Team) HasPartiallyRespond(m MCQ) (*time.Time) {
|
||||
var tm *time.Time
|
||||
DBQueryRow("SELECT MIN(time) FROM mcq_found WHERE id_team = ? AND id_mcq = ?", t.Id, m.Id).Scan(&tm)
|
||||
return tm
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue