Soumettre une solution
diff --git a/libfic/db.go b/libfic/db.go
index 2f2d6228..b3bb4e31 100644
--- a/libfic/db.go
+++ b/libfic/db.go
@@ -64,7 +64,6 @@ CREATE TABLE IF NOT EXISTS exercices(
id_theme INTEGER NOT NULL,
title VARCHAR(255) NOT NULL,
statement TEXT NOT NULL,
- hint TEXT NOT NULL,
depend INTEGER,
gain INTEGER NOT NULL,
video_uri VARCHAR(255) NOT NULL,
@@ -85,6 +84,18 @@ CREATE TABLE IF NOT EXISTS exercice_files(
size INTEGER NOT NULL,
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice)
);
+`); err != nil {
+ return err
+ }
+ if _, err := db.Exec(`
+CREATE TABLE IF NOT EXISTS exercice_hints(
+ id_hint INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ id_exercice INTEGER NOT NULL,
+ title VARCHAR(255) NOT NULL,
+ content TEXT NOT NULL,
+ cost INTEGER NOT NULL,
+ FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice)
+);
`); err != nil {
return err
}
@@ -118,6 +129,17 @@ CREATE TABLE IF NOT EXISTS exercice_tries(
FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice),
FOREIGN KEY(id_team) REFERENCES teams(id_team)
);
+`); err != nil {
+ return err
+ }
+ if _, err := db.Exec(`
+CREATE TABLE IF NOT EXISTS team_hints(
+ id_team INTEGER,
+ id_hint INTEGER,
+ time TIMESTAMP NOT NULL,
+ FOREIGN KEY(id_hint) REFERENCES exercice_hints(id_hint),
+ FOREIGN KEY(id_team) REFERENCES teams(id_team)
+);
`); err != nil {
return err
}
diff --git a/libfic/exercice.go b/libfic/exercice.go
index a977d877..6af662d4 100644
--- a/libfic/exercice.go
+++ b/libfic/exercice.go
@@ -9,7 +9,6 @@ type Exercice struct {
Id int64 `json:"id"`
Title string `json:"title"`
Statement string `json:"statement"`
- Hint string `json:"hint"`
Depend *int64 `json:"depend"`
Gain int64 `json:"gain"`
VideoURI string `json:"videoURI"`
@@ -17,7 +16,7 @@ type Exercice struct {
func GetExercice(id int64) (Exercice, error) {
var e Exercice
- if err := DBQueryRow("SELECT id_exercice, title, statement, hint, depend, gain, video_uri FROM exercices WHERE id_exercice = ?", id).Scan(&e.Id, &e.Title, &e.Statement, &e.Hint, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
+ if err := DBQueryRow("SELECT id_exercice, title, statement, depend, gain, video_uri FROM exercices WHERE id_exercice = ?", id).Scan(&e.Id, &e.Title, &e.Statement, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
return Exercice{}, err
}
@@ -26,7 +25,7 @@ func GetExercice(id int64) (Exercice, error) {
func (t Theme) GetExercice(id int) (Exercice, error) {
var e Exercice
- if err := DBQueryRow("SELECT id_exercice, title, statement, hint, depend, gain, video_uri FROM exercices WHERE id_theme = ? AND id_exercice = ?", t.Id, id).Scan(&e.Id, &e.Title, &e.Statement, &e.Hint, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
+ if err := DBQueryRow("SELECT id_exercice, title, statement, depend, gain, video_uri FROM exercices WHERE id_theme = ? AND id_exercice = ?", t.Id, id).Scan(&e.Id, &e.Title, &e.Statement, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
return Exercice{}, err
}
@@ -34,7 +33,7 @@ func (t Theme) GetExercice(id int) (Exercice, error) {
}
func GetExercices() ([]Exercice, error) {
- if rows, err := DBQuery("SELECT id_exercice, title, statement, hint, depend, gain, video_uri FROM exercices"); err != nil {
+ if rows, err := DBQuery("SELECT id_exercice, title, statement, depend, gain, video_uri FROM exercices"); err != nil {
return nil, err
} else {
defer rows.Close()
@@ -42,7 +41,7 @@ func GetExercices() ([]Exercice, error) {
var exos = make([]Exercice, 0)
for rows.Next() {
var e Exercice
- if err := rows.Scan(&e.Id, &e.Title, &e.Statement, &e.Hint, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
+ if err := rows.Scan(&e.Id, &e.Title, &e.Statement, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
return nil, err
}
exos = append(exos, e)
@@ -56,7 +55,7 @@ func GetExercices() ([]Exercice, error) {
}
func (t Theme) GetExercices() ([]Exercice, error) {
- if rows, err := DBQuery("SELECT id_exercice, title, statement, hint, depend, gain, video_uri FROM exercices WHERE id_theme = ?", t.Id); err != nil {
+ if rows, err := DBQuery("SELECT id_exercice, title, statement, depend, gain, video_uri FROM exercices WHERE id_theme = ?", t.Id); err != nil {
return nil, err
} else {
defer rows.Close()
@@ -64,7 +63,7 @@ func (t Theme) GetExercices() ([]Exercice, error) {
var exos = make([]Exercice, 0)
for rows.Next() {
var e Exercice
- if err := rows.Scan(&e.Id, &e.Title, &e.Statement, &e.Hint, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
+ if err := rows.Scan(&e.Id, &e.Title, &e.Statement, &e.Depend, &e.Gain, &e.VideoURI); err != nil {
return nil, err
}
exos = append(exos, e)
@@ -77,28 +76,28 @@ func (t Theme) GetExercices() ([]Exercice, error) {
}
}
-func (t Theme) AddExercice(title string, statement string, hint string, depend *Exercice, gain int, videoURI string) (Exercice, error) {
+func (t Theme) AddExercice(title string, statement string, depend *Exercice, gain int, videoURI string) (Exercice, error) {
var dpd interface{}
if depend == nil {
dpd = nil
} else {
dpd = depend.Id
}
- if res, err := DBExec("INSERT INTO exercices (id_theme, title, statement, hint, depend, gain, video_uri) VALUES (?, ?, ?, ?, ?, ?, ?)", t.Id, title, statement, hint, dpd, gain, videoURI); err != nil {
+ if res, err := DBExec("INSERT INTO exercices (id_theme, title, statement, depend, gain, video_uri) VALUES (?, ?, ?, ?, ?, ?)", t.Id, title, statement, dpd, gain, videoURI); err != nil {
return Exercice{}, err
} else if eid, err := res.LastInsertId(); err != nil {
return Exercice{}, err
} else {
if depend == nil {
- return Exercice{eid, title, statement, hint, nil, int64(gain), videoURI}, nil
+ return Exercice{eid, title, statement, nil, int64(gain), videoURI}, nil
} else {
- return Exercice{eid, title, statement, hint, &depend.Id, int64(gain), videoURI}, nil
+ return Exercice{eid, title, statement, &depend.Id, int64(gain), videoURI}, nil
}
}
}
func (e Exercice) Update() (int64, error) {
- if res, err := DBExec("UPDATE exercices SET title = ?, statement = ?, hint = ?, depend = ?, gain = ?, video_uri = ? WHERE id_exercice = ?", e.Title, e.Statement, e.Hint, e.Depend, e.Gain, e.VideoURI, e.Id); err != nil {
+ if res, err := DBExec("UPDATE exercices SET title = ?, statement = ?, depend = ?, gain = ?, video_uri = ? WHERE id_exercice = ?", e.Title, e.Statement, e.Depend, e.Gain, e.VideoURI, e.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
diff --git a/libfic/hint.go b/libfic/hint.go
new file mode 100644
index 00000000..46ae6a6f
--- /dev/null
+++ b/libfic/hint.go
@@ -0,0 +1,65 @@
+package fic
+
+import (
+)
+
+type EHint struct {
+ Id int64 `json:"id"`
+ IdExercice int64 `json:"idExercice"`
+ Title string `json:"title"`
+ Content string `json:"content"`
+ Cost int64 `json:"cost"`
+}
+
+func (e Exercice) GetHints() ([]EHint, error) {
+ if rows, err := DBQuery("SELECT id_hint, title, content, cost FROM exercice_hints WHERE id_exercice = ?", e.Id); err != nil {
+ return nil, err
+ } else {
+ defer rows.Close()
+
+ var hints = make([]EHint, 0)
+ for rows.Next() {
+ var h EHint
+ h.IdExercice = e.Id
+ if err := rows.Scan(&h.Id, &h.Title, &h.Content, &h.Cost); err != nil {
+ return nil, err
+ }
+ hints = append(hints, h)
+ }
+ if err := rows.Err(); err != nil {
+ return nil, err
+ }
+
+ return hints, nil
+ }
+}
+
+func (e Exercice) AddHint(title string, content string, cost int64) (EHint, error) {
+ if res, err := DBExec("INSERT INTO exercice_hints (id_exercice, title, content, cost) VALUES (?, ?, ?, ?)", e.Id, title, content, cost); err != nil {
+ return EHint{}, err
+ } else if hid, err := res.LastInsertId(); err != nil {
+ return EHint{}, err
+ } else {
+ return EHint{hid, e.Id, title, content, cost}, nil
+ }
+}
+
+func (h EHint) Update() (int64, error) {
+ if res, err := DBExec("UPDATE exercice_hints SET id_exercice = ?, title = ?, content = ?, cost = ? WHERE id_hint = ?", h.IdExercice, h.Title, h.Content, h.Cost, h.Id); err != nil {
+ return 0, err
+ } else if nb, err := res.RowsAffected(); err != nil {
+ return 0, err
+ } else {
+ return nb, err
+ }
+}
+
+func (h EHint) Delete() (int64, error) {
+ if res, err := DBExec("DELETE FROM exercice_hints WHERE id_hint = ?", h.Id); err != nil {
+ return 0, err
+ } else if nb, err := res.RowsAffected(); err != nil {
+ return 0, err
+ } else {
+ return nb, err
+ }
+}
diff --git a/libfic/team.go b/libfic/team.go
index ecd1a69d..920ab6fd 100644
--- a/libfic/team.go
+++ b/libfic/team.go
@@ -210,6 +210,12 @@ func GetTries(t *Team, e *Exercice) ([]time.Time, error) {
}
}
+func (t Team) HasHint(h EHint) (bool) {
+ var tm *time.Time
+ DBQueryRow("SELECT MIN(time) FROM team_hints WHERE id_team = ? AND id_hint = ?", t.Id, h.Id).Scan(&tm)
+ return tm != nil
+}
+
func (t Team) HasSolved(e Exercice) (bool, time.Time, int64) {
var nb *int64
var tm *time.Time
diff --git a/libfic/team_my.go b/libfic/team_my.go
index 11e04c58..3626fcf1 100644
--- a/libfic/team_my.go
+++ b/libfic/team_my.go
@@ -13,10 +13,17 @@ type myTeamFile struct {
Checksum string `json:"checksum"`
Size int64 `json:"size"`
}
+type myTeamHint struct {
+ HintId int64 `json:"id"`
+ Title string `json:"title"`
+ Content string `json:"content"`
+ Cost int64 `json:"cost"`
+ Unlocked bool `json:"unlocked"`
+}
type myTeamExercice struct {
ThemeId int `json:"theme_id"`
Statement string `json:"statement"`
- Hint string `json:"hint"`
+ Hints []myTeamHint `json:"hints"`
Gain int64 `json:"gain"`
Files []myTeamFile `json:"files"`
Keys []string `json:"keys"`
@@ -35,6 +42,8 @@ type myTeam struct {
func MyJSONTeam(t *Team, started bool) (interface{}, error) {
ret := myTeam{}
+
+ // Fill information about the team
if t == nil {
ret.Id = 0
} else {
@@ -46,8 +55,9 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
}
}
- ret.Exercices = map[string]myTeamExercice{}
+ // Fill exercices, only if the challenge is started
+ ret.Exercices = map[string]myTeamExercice{}
if exos, err := GetExercices(); err != nil {
return ret, err
} else if started {
@@ -58,7 +68,6 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
exercice.ThemeId = tid
}
exercice.Statement = e.Statement
- exercice.Hint = e.Hint
if t == nil {
exercice.VideoURI = e.VideoURI
exercice.Solved = true
@@ -67,6 +76,36 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
exercice.Solved, exercice.SolvedTime, exercice.SolvedNumber = t.HasSolved(e)
}
+ // Expose exercice files
+
+ exercice.Files = []myTeamFile{}
+
+ if files, err := e.GetFiles(); err != nil {
+ return nil, err
+ } else {
+ for _, f := range files {
+ exercice.Files = append(exercice.Files, myTeamFile{path.Join(FilesDir, f.Path), f.Name, hex.EncodeToString(f.Checksum), f.Size})
+ }
+ }
+
+ // Expose exercice hints
+
+ exercice.Hints = []myTeamHint{}
+
+ if hints, err := e.GetHints(); err != nil {
+ return nil, err
+ } else {
+ for _, h := range hints {
+ if t == nil || t.HasHint(h) {
+ exercice.Hints = append(exercice.Hints, myTeamHint{h.Id, h.Title, h.Content, h.Cost, true})
+ } else {
+ exercice.Hints = append(exercice.Hints, myTeamHint{h.Id, h.Title, "", h.Cost, false})
+ }
+ }
+ }
+
+ // Expose exercice keys
+
exercice.Keys = []string{}
if keys, err := e.GetKeys(); err != nil {
@@ -81,16 +120,7 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
}
}
- exercice.Files = []myTeamFile{}
-
- if files, err := e.GetFiles(); err != nil {
- return nil, err
- } else {
- for _, f := range files {
- exercice.Files = append(exercice.Files, myTeamFile{path.Join(FilesDir, f.Path), f.Name, hex.EncodeToString(f.Checksum), f.Size})
- }
- }
-
+ // Hash table ordered by exercice Id
ret.Exercices[fmt.Sprintf("%d", e.Id)] = exercice
}
}