Able to check MCQ

This commit is contained in:
nemunaire 2017-12-16 01:16:30 +01:00
parent 037f27c62c
commit 6903c91df2
6 changed files with 79 additions and 13 deletions

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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())
}

View File

@ -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")
}

View File

@ -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
}