Write docs!
This commit is contained in:
parent
c460bb7bf5
commit
bcc598ebd5
37 changed files with 478 additions and 188 deletions
|
|
@ -4,16 +4,17 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// UnlockedChallenges disables dependancy requirement between challenges.
|
||||
var UnlockedChallenges bool
|
||||
|
||||
// Team represents a group of players, come to solve our challenges.
|
||||
type Team struct {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Color uint32 `json:"color"`
|
||||
}
|
||||
|
||||
// Access functions
|
||||
|
||||
// GetTeams returns a list of registered Team from the database.
|
||||
func GetTeams() ([]Team, error) {
|
||||
if rows, err := DBQuery("SELECT id_team, name, color FROM teams"); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -36,6 +37,7 @@ func GetTeams() ([]Team, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetTeam retrieves a Team from its identifier.
|
||||
func GetTeam(id int64) (Team, error) {
|
||||
var t Team
|
||||
if err := DBQueryRow("SELECT id_team, name, color FROM teams WHERE id_team = ?", id).Scan(&t.Id, &t.Name, &t.Color); err != nil {
|
||||
|
|
@ -45,6 +47,7 @@ func GetTeam(id int64) (Team, error) {
|
|||
return t, nil
|
||||
}
|
||||
|
||||
// GetTeamBySerial retrieves a Team from one of its associated certificates.
|
||||
func GetTeamBySerial(serial int64) (Team, error) {
|
||||
var t Team
|
||||
if err := DBQueryRow("SELECT T.id_team, T.name, T.color FROM certificates C INNER JOIN teams T ON T.id_team = C.id_team WHERE id_cert = ?", serial).Scan(&t.Id, &t.Name, &t.Color); err != nil {
|
||||
|
|
@ -54,9 +57,7 @@ func GetTeamBySerial(serial int64) (Team, error) {
|
|||
return t, nil
|
||||
}
|
||||
|
||||
|
||||
// CRUD method
|
||||
|
||||
// CreateTeam creates and fills a new struct Team and registers it into the database.
|
||||
func CreateTeam(name string, color uint32) (Team, error) {
|
||||
if res, err := DBExec("INSERT INTO teams (name, color) VALUES (?, ?)", name, color); err != nil {
|
||||
return Team{}, err
|
||||
|
|
@ -67,6 +68,7 @@ func CreateTeam(name string, color uint32) (Team, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (t Team) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE teams SET name = ?, color = ? WHERE id_team = ?", t.Name, t.Color, t.Id); err != nil {
|
||||
return 0, err
|
||||
|
|
@ -77,6 +79,7 @@ func (t Team) Update() (int64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Delete the challenge from the database
|
||||
func (t Team) Delete() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM team_members WHERE id_team = ?", t.Id); err != nil {
|
||||
return 0, err
|
||||
|
|
@ -89,20 +92,19 @@ func (t Team) Delete() (int64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Exercice related functions
|
||||
|
||||
// HasAccess checks if the Team has access to the given challenge.
|
||||
func (t Team) HasAccess(e Exercice) bool {
|
||||
if e.Depend == nil || UnlockedChallenges {
|
||||
return true
|
||||
} else {
|
||||
ed := Exercice{}
|
||||
ed.Id = *e.Depend
|
||||
s, _, _ := t.HasSolved(ed)
|
||||
s, _ := t.HasSolved(ed)
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// NbTry retrieves the number of attempts made by the Team to the given challenge.
|
||||
func NbTry(t *Team, e Exercice) int {
|
||||
var cnt *int
|
||||
|
||||
|
|
@ -119,17 +121,20 @@ func NbTry(t *Team, e Exercice) int {
|
|||
}
|
||||
}
|
||||
|
||||
// HasHint checks if the Team has revealed the given Hint.
|
||||
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
|
||||
}
|
||||
|
||||
// OpenHint registers to the database that the Team has now revealed.
|
||||
func (t Team) OpenHint(h EHint) (error) {
|
||||
_, err := DBExec("INSERT INTO team_hints (id_team, id_hint, time) VALUES (?, ?, ?)", t.Id, h.Id, time.Now())
|
||||
return err
|
||||
}
|
||||
|
||||
// CountTries gets the amount of attempts made by the Team and retrieves the time of the latest attempt.
|
||||
func (t Team) CountTries(e Exercice) (int64, time.Time) {
|
||||
var nb *int64
|
||||
var tm *time.Time
|
||||
|
|
@ -142,6 +147,8 @@ func (t Team) CountTries(e Exercice) (int64, time.Time) {
|
|||
}
|
||||
}
|
||||
|
||||
// LastTryDist retrieves the distance to the correct answers, for the given challenge.
|
||||
// The distance is the number of bad responses given in differents MCQs.
|
||||
func (t Team) LastTryDist(e Exercice) int64 {
|
||||
var nb *int64
|
||||
if DBQueryRow("SELECT nbdiff FROM exercice_tries WHERE id_team = ? AND id_exercice = ? ORDER BY time DESC LIMIT 1", t.Id, e.Id).Scan(&nb); nb == nil {
|
||||
|
|
@ -151,36 +158,45 @@ func (t Team) LastTryDist(e Exercice) int64 {
|
|||
}
|
||||
}
|
||||
|
||||
func (t Team) HasSolved(e Exercice) (bool, time.Time, int64) {
|
||||
var nb *int64
|
||||
// HasSolved checks if the Team already has validated the given challenge.
|
||||
// Note that the function also returns the effective validation timestamp.
|
||||
func (t Team) HasSolved(e Exercice) (bool, time.Time) {
|
||||
var tm *time.Time
|
||||
if DBQueryRow("SELECT MIN(time) FROM exercice_solved WHERE id_team = ? AND id_exercice = ?", t.Id, e.Id).Scan(&tm); tm == nil {
|
||||
return false, time.Unix(0, 0), 0
|
||||
} else if DBQueryRow("SELECT COUNT(id_exercice) FROM exercice_solved WHERE id_exercice = ? AND time < ?", e.Id, tm).Scan(&nb); nb == nil {
|
||||
return true, *tm, 0
|
||||
return false, time.Unix(0, 0)
|
||||
} else {
|
||||
return true, *tm, *nb + 1
|
||||
return true, *tm
|
||||
}
|
||||
}
|
||||
|
||||
func IsSolved(e Exercice) (int, time.Time) {
|
||||
var nb *int
|
||||
var tm *time.Time
|
||||
if DBQueryRow("SELECT COUNT(id_exercice), MIN(time) FROM exercice_solved WHERE id_exercice = ?", e.Id).Scan(&nb, &tm); nb == nil || tm == nil {
|
||||
return 0, time.Time{}
|
||||
// GetSolvedRank returns the number of teams that solved the challenge before the Team.
|
||||
func (t Team) GetSolvedRank(e Exercice) (nb int64, err error) {
|
||||
if rows, errr := DBQuery("SELECT id_team FROM exercice_solved WHERE id_exercice = ? ORDER BY time ASC", e.Id); err != nil {
|
||||
return nb, errr
|
||||
} else {
|
||||
return *nb, *tm
|
||||
for rows.Next() {
|
||||
var tid int64
|
||||
if err = rows.Scan(&tid); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
nb += 1
|
||||
if t.Id == tid {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (t Team) HasPartiallySolved(k Key) (*time.Time) {
|
||||
var tm *time.Time
|
||||
// HasPartiallySolved checks if the Team already has unlocked the given key and returns the validation's timestamp.
|
||||
func (t Team) HasPartiallySolved(k Key) (tm *time.Time) {
|
||||
DBQueryRow("SELECT MIN(time) FROM key_found WHERE id_team = ? AND id_key = ?", t.Id, k.Id).Scan(&tm)
|
||||
return tm
|
||||
return
|
||||
}
|
||||
|
||||
func (t Team) HasPartiallyRespond(m MCQ) (*time.Time) {
|
||||
var tm *time.Time
|
||||
// HasPartiallyRespond checks if the Team already has unlocked the given MCQ and returns the validation's timestamp.
|
||||
func (t Team) HasPartiallyRespond(m MCQ) (tm *time.Time) {
|
||||
DBQueryRow("SELECT MIN(time) FROM mcq_found WHERE id_team = ? AND id_mcq = ?", t.Id, m.Id).Scan(&tm)
|
||||
return tm
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue