sync: implement hint dependency on flags
This commit is contained in:
parent
20f2597248
commit
6740256a32
6 changed files with 72 additions and 2 deletions
|
@ -14,6 +14,7 @@ type ExerciceHintParams struct {
|
||||||
Content string
|
Content string
|
||||||
Cost int64
|
Cost int64
|
||||||
Title string
|
Title string
|
||||||
|
NeedFlag []ExerciceDependency `toml:"need_flag,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExerciceDependency holds dependency definitions information.
|
// ExerciceDependency holds dependency definitions information.
|
||||||
|
|
10
libfic/db.go
10
libfic/db.go
|
@ -179,6 +179,16 @@ CREATE TABLE IF NOT EXISTS exercice_flags(
|
||||||
choices_cost INTEGER NOT NULL,
|
choices_cost INTEGER NOT NULL,
|
||||||
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice)
|
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice)
|
||||||
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
||||||
|
`); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := db.Exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS exercice_hints_deps(
|
||||||
|
id_hint INTEGER NOT NULL,
|
||||||
|
id_flag_dep INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(id_hint) REFERENCES exercice_hints(id_hint),
|
||||||
|
FOREIGN KEY(id_flag_dep) REFERENCES exercice_flags(id_flag)
|
||||||
|
) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin;
|
||||||
`); err != nil {
|
`); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ func (e Exercice) WipeFlags() (int64, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
} else if _, err := DBExec("DELETE FROM exercice_flags_omcq_deps WHERE id_flag IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
} else if _, err := DBExec("DELETE FROM exercice_flags_omcq_deps WHERE id_flag IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
} else if _, err := DBExec("DELETE FROM exercice_hints_deps WHERE id_flag_dep IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
||||||
|
return 0, err
|
||||||
} else if _, err := DBExec("DELETE FROM exercice_mcq_okey_deps WHERE id_flag_dep IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
} else if _, err := DBExec("DELETE FROM exercice_mcq_okey_deps WHERE id_flag_dep IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
} else if _, err := DBExec("DELETE FROM team_wchoices WHERE id_flag IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
} else if _, err := DBExec("DELETE FROM team_wchoices WHERE id_flag IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package fic
|
package fic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -105,7 +107,9 @@ func (h EHint) Delete() (int64, error) {
|
||||||
|
|
||||||
// WipeHints deletes (only in the database, not on disk) hints coming with the challenge.
|
// WipeHints deletes (only in the database, not on disk) hints coming with the challenge.
|
||||||
func (e Exercice) WipeHints() (int64, error) {
|
func (e Exercice) WipeHints() (int64, error) {
|
||||||
if res, err := DBExec("DELETE FROM exercice_hints WHERE id_exercice = ?", e.Id); err != nil {
|
if _, err := DBExec("DELETE FROM exercice_hints_deps WHERE id_hint IN (SELECT id_hint FROM exercice_hints WHERE id_exercice = ?)", e.Id); err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else if res, err := DBExec("DELETE FROM exercice_hints WHERE id_exercice = ?", e.Id); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
} else if nb, err := res.RowsAffected(); err != nil {
|
} else if nb, err := res.RowsAffected(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
@ -114,6 +118,40 @@ func (e Exercice) WipeHints() (int64, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddDepend insert a new dependency to a given flag.
|
||||||
|
func (h EHint) AddDepend(f Flag) (err error) {
|
||||||
|
if d, ok := f.(FlagKey); ok {
|
||||||
|
_, err = DBExec("INSERT INTO exercice_hints_deps (id_hint, id_flag_dep) VALUES (?, ?)", h.Id, d.Id)
|
||||||
|
} else {
|
||||||
|
err = errors.New(fmt.Sprintf("Dependancy type for key (%T) not implemented for this flag.", f))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDepends retrieve the flag's dependency list.
|
||||||
|
func (h EHint) GetDepends() ([]Flag, error) {
|
||||||
|
var deps = make([]Flag, 0)
|
||||||
|
|
||||||
|
if rows, err := DBQuery("SELECT id_flag_dep FROM exercice_hints_deps WHERE id_hint = ?", h.Id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var d int64
|
||||||
|
if err := rows.Scan(&d); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
deps = append(deps, FlagKey{Id: d, IdExercice: h.IdExercice})
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deps, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetExercice returns the parent Exercice where this hint can be found.
|
// GetExercice returns the parent Exercice where this hint can be found.
|
||||||
func (h EHint) GetExercice() (Exercice, error) {
|
func (h EHint) GetExercice() (Exercice, error) {
|
||||||
var eid int64
|
var eid int64
|
||||||
|
|
|
@ -155,6 +155,25 @@ func (t Team) CanDownload(f EFile) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanSeeHint checks if the Team has access to the given hint.
|
||||||
|
func (t Team) CanSeeHint(h EHint) bool {
|
||||||
|
if deps, err := h.GetDepends(); err != nil {
|
||||||
|
log.Printf("Unable to retrieve flag dependencies: %s\n", err)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
res := true
|
||||||
|
|
||||||
|
for _, dep := range deps {
|
||||||
|
if t.HasPartiallySolved(dep) == nil {
|
||||||
|
res = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CanSeeFlag checks if the Team has access to the given flag.
|
// CanSeeFlag checks if the Team has access to the given flag.
|
||||||
func (t Team) CanSeeFlag(k Flag) bool {
|
func (t Team) CanSeeFlag(k Flag) bool {
|
||||||
if deps, err := k.GetDepends(); err != nil {
|
if deps, err := k.GetDepends(); err != nil {
|
||||||
|
|
|
@ -168,7 +168,7 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
||||||
for _, h := range hints {
|
for _, h := range hints {
|
||||||
if t == nil || HintCoefficient < 0 || t.HasHint(h) {
|
if t == nil || HintCoefficient < 0 || t.HasHint(h) {
|
||||||
exercice.Hints = append(exercice.Hints, myTeamHint{h.Id, h.Title, h.Content, h.File, h.Cost})
|
exercice.Hints = append(exercice.Hints, myTeamHint{h.Id, h.Title, h.Content, h.File, h.Cost})
|
||||||
} else {
|
} else if t.CanSeeHint(h) {
|
||||||
exercice.Hints = append(exercice.Hints, myTeamHint{h.Id, h.Title, "", "", h.Cost})
|
exercice.Hints = append(exercice.Hints, myTeamHint{h.Id, h.Title, "", "", h.Cost})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue