Use pointer receiver more offen
This commit is contained in:
parent
6999b4e728
commit
c7569b5e54
59 changed files with 688 additions and 672 deletions
|
@ -24,14 +24,14 @@ type Certificate struct {
|
|||
}
|
||||
|
||||
// GetCertificates returns the list of all generated certificates.
|
||||
func GetCertificates() (certificates []Certificate, err error) {
|
||||
func GetCertificates() (certificates []*Certificate, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_cert, creation, password, revoked FROM certificates ORDER BY creation"); err == nil {
|
||||
defer rows.Close()
|
||||
|
||||
certificates = make([]Certificate, 0)
|
||||
certificates = []*Certificate{}
|
||||
for rows.Next() {
|
||||
var c Certificate
|
||||
c := &Certificate{}
|
||||
if err = rows.Scan(&c.Id, &c.Creation, &c.Password, &c.Revoked); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ func GetCertificates() (certificates []Certificate, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
|
||||
// GetCertificate retrieves a certificate from its serial number.
|
||||
func GetCertificate(serial uint64) (c Certificate, err error) {
|
||||
func GetCertificate(serial uint64) (c *Certificate, err error) {
|
||||
c = &Certificate{}
|
||||
err = DBQueryRow("SELECT id_cert, creation, password, revoked FROM certificates WHERE id_cert = ?", serial).Scan(&c.Id, &c.Creation, &c.Password, &c.Revoked)
|
||||
return
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func RegisterCertificate(serial uint64, password string) (Certificate, error) {
|
|||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (c Certificate) Update() (int64, error) {
|
||||
func (c *Certificate) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE certificates SET creation = ?, password = ?, revoked = ? WHERE id_cert = ?", c.Creation, c.Password, c.Revoked, c.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -100,7 +100,6 @@ func (c Certificate) Delete() (int64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ClearCertificates removes all certificates from database.
|
||||
func ClearCertificates() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM certificates"); err != nil {
|
||||
|
|
|
@ -36,15 +36,15 @@ func GetLastEvents() ([]Event, error) {
|
|||
}
|
||||
|
||||
// GetEvents returns the list of all events, sorted by date, last first
|
||||
func GetEvents() ([]Event, error) {
|
||||
func GetEvents() ([]*Event, error) {
|
||||
if rows, err := DBQuery("SELECT id_event, txt, kind, time FROM events ORDER BY time DESC"); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var events = make([]Event, 0)
|
||||
var events []*Event
|
||||
for rows.Next() {
|
||||
var e Event
|
||||
e := &Event{}
|
||||
if err := rows.Scan(&e.Id, &e.Text, &e.Kind, &e.Time); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -59,24 +59,25 @@ func GetEvents() ([]Event, error) {
|
|||
}
|
||||
|
||||
// GetEvent retrieves the event with the given id
|
||||
func GetEvent(id int64) (e Event, err error) {
|
||||
func GetEvent(id int64) (e *Event, err error) {
|
||||
e = &Event{}
|
||||
err = DBQueryRow("SELECT id_event, txt, kind, time FROM events WHERE id_event=?", id).Scan(&e.Id, &e.Text, &e.Kind, &e.Time)
|
||||
return
|
||||
}
|
||||
|
||||
// NewEvent creates a new event in the database and returns the corresponding structure
|
||||
func NewEvent(txt string, kind string) (Event, error) {
|
||||
func NewEvent(txt string, kind string) (*Event, error) {
|
||||
if res, err := DBExec("INSERT INTO events (txt, kind, time) VALUES (?, ?, ?)", txt, kind, time.Now()); err != nil {
|
||||
return Event{}, err
|
||||
return nil, err
|
||||
} else if eid, err := res.LastInsertId(); err != nil {
|
||||
return Event{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return Event{eid, txt, kind, time.Now()}, nil
|
||||
return &Event{eid, txt, kind, time.Now()}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database
|
||||
func (e Event) Update() (int64, error) {
|
||||
func (e *Event) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE events SET txt = ?, kind = ?, time = ? WHERE id_event = ?", e.Text, e.Kind, e.Time, e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -87,7 +88,7 @@ func (e Event) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the event from the database
|
||||
func (e Event) Delete() (int64, error) {
|
||||
func (e *Event) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM events WHERE id_event = ?", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
|
|
@ -52,45 +52,45 @@ type Exercice struct {
|
|||
}
|
||||
|
||||
// GetExercice retrieves the challenge with the given id.
|
||||
func GetExercice(id int64) (Exercice, error) {
|
||||
func GetExercice(id int64) (*Exercice, error) {
|
||||
var e Exercice
|
||||
if err := DBQueryRow("SELECT id_exercice, id_theme, title, url_id, path, statement, overview, headline, issue, issue_kind, depend, gain, coefficient_cur, video_uri, finished FROM exercices WHERE id_exercice = ?", id).Scan(&e.Id, &e.IdTheme, &e.Title, &e.URLId, &e.Path, &e.Statement, &e.Overview, &e.Headline, &e.Issue, &e.IssueKind, &e.Depend, &e.Gain, &e.Coefficient, &e.VideoURI, &e.Finished); err != nil {
|
||||
return Exercice{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e, nil
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
// GetExercice retrieves the challenge with the given id.
|
||||
func (t Theme) GetExercice(id int) (Exercice, error) {
|
||||
var e Exercice
|
||||
func (t *Theme) GetExercice(id int) (*Exercice, error) {
|
||||
e := &Exercice{}
|
||||
if err := DBQueryRow("SELECT id_exercice, id_theme, title, url_id, path, statement, overview, headline, issue, issue_kind, depend, gain, coefficient_cur, video_uri, finished FROM exercices WHERE id_theme = ? AND id_exercice = ?", t.Id, id).Scan(&e.Id, &e.IdTheme, &e.Title, &e.URLId, &e.Path, &e.Statement, &e.Overview, &e.Headline, &e.Issue, &e.IssueKind, &e.Depend, &e.Gain, &e.Coefficient, &e.VideoURI, &e.Finished); err != nil {
|
||||
return Exercice{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// GetExerciceByTitle retrieves the challenge with the given title.
|
||||
func (t Theme) GetExerciceByTitle(title string) (Exercice, error) {
|
||||
var e Exercice
|
||||
func (t *Theme) GetExerciceByTitle(title string) (*Exercice, error) {
|
||||
e := &Exercice{}
|
||||
if err := DBQueryRow("SELECT id_exercice, id_theme, title, url_id, path, statement, overview, headline, issue, issue_kind, depend, gain, coefficient_cur, video_uri, finished FROM exercices WHERE id_theme = ? AND title = ?", t.Id, title).Scan(&e.Id, &e.IdTheme, &e.Title, &t.URLId, &e.Path, &e.Statement, &e.Overview, &e.Headline, &e.Issue, &e.IssueKind, &e.Depend, &e.Gain, &e.Coefficient, &e.VideoURI, &e.Finished); err != nil {
|
||||
return Exercice{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// GetExercices returns the list of all challenges present in the database.
|
||||
func GetExercices() ([]Exercice, error) {
|
||||
func GetExercices() ([]*Exercice, error) {
|
||||
if rows, err := DBQuery("SELECT id_exercice, id_theme, title, url_id, path, statement, overview, headline, issue, issue_kind, depend, gain, coefficient_cur, video_uri, finished FROM exercices"); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var exos = make([]Exercice, 0)
|
||||
exos := []*Exercice{}
|
||||
for rows.Next() {
|
||||
var e Exercice
|
||||
e := &Exercice{}
|
||||
if err := rows.Scan(&e.Id, &e.IdTheme, &e.Title, &e.URLId, &e.Path, &e.Statement, &e.Overview, &e.Headline, &e.Issue, &e.IssueKind, &e.Depend, &e.Gain, &e.Coefficient, &e.VideoURI, &e.Finished); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -105,15 +105,15 @@ func GetExercices() ([]Exercice, error) {
|
|||
}
|
||||
|
||||
// GetExercices returns the list of all challenges in the Theme.
|
||||
func (t Theme) GetExercices() ([]Exercice, error) {
|
||||
func (t *Theme) GetExercices() ([]*Exercice, error) {
|
||||
if rows, err := DBQuery("SELECT id_exercice, id_theme, title, url_id, path, statement, overview, headline, issue, issue_kind, depend, gain, coefficient_cur, video_uri, finished FROM exercices WHERE id_theme = ?", t.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var exos = make([]Exercice, 0)
|
||||
exos := []*Exercice{}
|
||||
for rows.Next() {
|
||||
var e Exercice
|
||||
e := &Exercice{}
|
||||
if err := rows.Scan(&e.Id, &e.IdTheme, &e.Title, &e.URLId, &e.Path, &e.Statement, &e.Overview, &e.Headline, &e.Issue, &e.IssueKind, &e.Depend, &e.Gain, &e.Coefficient, &e.VideoURI, &e.Finished); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -128,8 +128,8 @@ func (t Theme) GetExercices() ([]Exercice, error) {
|
|||
}
|
||||
|
||||
// SaveNamedExercice looks for an exercice with the same title to update it, or create it if it doesn't exists yet.
|
||||
func (t Theme) SaveNamedExercice(e *Exercice) (err error) {
|
||||
var search Exercice
|
||||
func (t *Theme) SaveNamedExercice(e *Exercice) (err error) {
|
||||
var search *Exercice
|
||||
if search, err = t.GetExerciceByTitle(e.Title); err == nil {
|
||||
// Force ID
|
||||
e.Id = search.Id
|
||||
|
@ -152,7 +152,7 @@ func (t Theme) SaveNamedExercice(e *Exercice) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (t Theme) addExercice(e *Exercice) (err error) {
|
||||
func (t *Theme) addExercice(e *Exercice) (err error) {
|
||||
var ik = "DEFAULT"
|
||||
if len(e.IssueKind) > 0 {
|
||||
ik = fmt.Sprintf("%q", e.IssueKind)
|
||||
|
@ -175,13 +175,13 @@ func (t Theme) addExercice(e *Exercice) (err error) {
|
|||
}
|
||||
|
||||
// AddExercice creates and fills a new struct Exercice and registers it into the database.
|
||||
func (t Theme) AddExercice(title string, urlId string, path string, statement string, overview string, headline string, depend *Exercice, gain int64, videoURI string, finished string) (e Exercice, err error) {
|
||||
func (t *Theme) AddExercice(title string, urlId string, path string, statement string, overview string, headline string, depend *Exercice, gain int64, videoURI string, finished string) (e *Exercice, err error) {
|
||||
var dpd *int64 = nil
|
||||
if depend != nil {
|
||||
dpd = &depend.Id
|
||||
}
|
||||
|
||||
e = Exercice{
|
||||
e = &Exercice{
|
||||
Title: title,
|
||||
URLId: urlId,
|
||||
Path: path,
|
||||
|
@ -194,13 +194,13 @@ func (t Theme) AddExercice(title string, urlId string, path string, statement st
|
|||
VideoURI: videoURI,
|
||||
}
|
||||
|
||||
err = t.addExercice(&e)
|
||||
err = t.addExercice(e)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (e Exercice) Update() (int64, error) {
|
||||
func (e *Exercice) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE exercices SET title = ?, url_id = ?, path = ?, statement = ?, overview = ?, headline = ?, issue = ?, issue_kind = ?, depend = ?, gain = ?, coefficient_cur = ?, video_uri = ?, finished = ? WHERE id_exercice = ?", e.Title, e.URLId, e.Path, e.Statement, e.Overview, e.Headline, e.Issue, e.IssueKind, e.Depend, e.Gain, e.Coefficient, e.VideoURI, e.Finished, e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -221,7 +221,7 @@ func (e *Exercice) FixURLId() bool {
|
|||
}
|
||||
|
||||
// Delete the challenge from the database.
|
||||
func (e Exercice) Delete() (int64, error) {
|
||||
func (e *Exercice) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM exercices WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -232,7 +232,7 @@ func (e Exercice) Delete() (int64, error) {
|
|||
}
|
||||
|
||||
// DeleteCascade the challenge from the database, including inner content but not player content.
|
||||
func (e Exercice) DeleteCascade() (int64, error) {
|
||||
func (e *Exercice) DeleteCascade() (int64, error) {
|
||||
if _, err := DBExec("UPDATE exercices SET depend = NULL WHERE depend = ?", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if _, err := DBExec("DELETE FROM exercice_files_okey_deps WHERE id_file IN (SELECT id_file FROM exercice_files WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
|
@ -269,7 +269,7 @@ func (e Exercice) DeleteCascade() (int64, error) {
|
|||
}
|
||||
|
||||
// DeleteCascadePlayer delete player content related to this challenge.
|
||||
func (e Exercice) DeleteCascadePlayer() (int64, error) {
|
||||
func (e *Exercice) DeleteCascadePlayer() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM mcq_found WHERE id_mcq IN (SELECT id_mcq FROM exercice_mcq WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if _, err := DBExec("DELETE FROM flag_found WHERE id_flag IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
|
@ -288,7 +288,7 @@ func (e Exercice) DeleteCascadePlayer() (int64, error) {
|
|||
}
|
||||
|
||||
// DeleteDeep the challenge from the database, including player content.
|
||||
func (e Exercice) DeleteDeep() (int64, error) {
|
||||
func (e *Exercice) DeleteDeep() (int64, error) {
|
||||
if _, err := e.DeleteCascadePlayer(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
|
@ -297,13 +297,13 @@ func (e Exercice) DeleteDeep() (int64, error) {
|
|||
}
|
||||
|
||||
// GetLevel returns the number of dependancy challenges.
|
||||
func (e Exercice) GetLevel() (int, error) {
|
||||
func (e *Exercice) GetLevel() (int, error) {
|
||||
dep := e.Depend
|
||||
nb := 1
|
||||
for dep != nil {
|
||||
nb += 1
|
||||
if nb > 10 || *dep == e.Id {
|
||||
return nb, errors.New("Exceed number of levels")
|
||||
return nb, errors.New("exceed number of levels")
|
||||
} else if edep, err := GetExercice(*dep); err != nil {
|
||||
return nb, err
|
||||
} else {
|
||||
|
@ -314,7 +314,7 @@ func (e Exercice) GetLevel() (int, error) {
|
|||
}
|
||||
|
||||
// NewTry registers a solving attempt for the given Team.
|
||||
func (e Exercice) NewTry(t Team, cksum []byte) error {
|
||||
func (e *Exercice) NewTry(t *Team, cksum []byte) error {
|
||||
if _, err := DBExec("INSERT INTO exercice_tries (id_exercice, id_team, time, cksum) VALUES (?, ?, ?, ?)", e.Id, t.Id, time.Now(), cksum); err != nil {
|
||||
return err
|
||||
} else {
|
||||
|
@ -324,7 +324,7 @@ func (e Exercice) NewTry(t Team, cksum []byte) error {
|
|||
|
||||
// UpdateTry applies modifications to the latest try registered for the given Team.
|
||||
// Updated values are time and the given nbdiff.
|
||||
func (e Exercice) UpdateTry(t Team, nbdiff int, oneGood bool) error {
|
||||
func (e *Exercice) UpdateTry(t *Team, nbdiff int, oneGood bool) error {
|
||||
if _, err := DBExec("UPDATE exercice_tries SET nbdiff = ?, onegood = ?, time = ? WHERE id_exercice = ? AND id_team = ? ORDER BY time DESC LIMIT 1", nbdiff, oneGood, time.Now(), e.Id, t.Id); err != nil {
|
||||
return err
|
||||
} else {
|
||||
|
@ -333,7 +333,7 @@ func (e Exercice) UpdateTry(t Team, nbdiff int, oneGood bool) error {
|
|||
}
|
||||
|
||||
// Solved registers that the given Team solves the challenge.
|
||||
func (e Exercice) Solved(t Team) error {
|
||||
func (e *Exercice) Solved(t *Team) error {
|
||||
if _, err := DBExec("INSERT INTO exercice_solved (id_exercice, id_team, time, coefficient) VALUES (?, ?, ?, ?)", e.Id, t.Id, time.Now(), e.Coefficient*ExerciceCurrentCoefficient); err != nil {
|
||||
return err
|
||||
} else {
|
||||
|
@ -342,7 +342,7 @@ func (e Exercice) Solved(t Team) error {
|
|||
}
|
||||
|
||||
// SolvedCount returns the number of Team that already have solved the challenge.
|
||||
func (e Exercice) SolvedCount() int64 {
|
||||
func (e *Exercice) SolvedCount() int64 {
|
||||
var nb int64
|
||||
if err := DBQueryRow("SELECT COUNT(id_exercice) FROM exercice_solved WHERE id_exercice = ?", e.Id).Scan(&nb); err != nil {
|
||||
return 0
|
||||
|
@ -352,7 +352,7 @@ func (e Exercice) SolvedCount() int64 {
|
|||
}
|
||||
|
||||
// TriedTeamCount returns the number of Team that attempted to solve the exercice.
|
||||
func (e Exercice) TriedTeamCount() int64 {
|
||||
func (e *Exercice) TriedTeamCount() int64 {
|
||||
tries_table := "exercice_tries"
|
||||
if SubmissionUniqueness {
|
||||
tries_table = "exercice_distinct_tries"
|
||||
|
@ -367,7 +367,7 @@ func (e Exercice) TriedTeamCount() int64 {
|
|||
}
|
||||
|
||||
// TriedCount returns the number of cumulative attempts, all Team combined, for the exercice.
|
||||
func (e Exercice) TriedCount() int64 {
|
||||
func (e *Exercice) TriedCount() int64 {
|
||||
tries_table := "exercice_tries"
|
||||
if SubmissionUniqueness {
|
||||
tries_table = "exercice_distinct_tries"
|
||||
|
@ -382,7 +382,7 @@ func (e Exercice) TriedCount() int64 {
|
|||
}
|
||||
|
||||
// FlagSolved returns the list of flags solved.
|
||||
func (e Exercice) FlagSolved() (res []int64) {
|
||||
func (e *Exercice) FlagSolved() (res []int64) {
|
||||
if rows, err := DBQuery("SELECT F.id_flag FROM flag_found F INNER JOIN exercice_flags E ON E.id_flag = F.id_flag WHERE E.id_exercice = ? GROUP BY id_flag", e.Id); err != nil {
|
||||
return
|
||||
} else {
|
||||
|
@ -400,7 +400,7 @@ func (e Exercice) FlagSolved() (res []int64) {
|
|||
}
|
||||
|
||||
// MCQSolved returns the list of mcqs solved.
|
||||
func (e Exercice) MCQSolved() (res []int64) {
|
||||
func (e *Exercice) MCQSolved() (res []int64) {
|
||||
if rows, err := DBQuery("SELECT F.id_mcq FROM mcq_found F INNER JOIN exercice_mcq E ON E.id_mcq = F.id_mcq WHERE E.id_exercice = ? GROUP BY id_mcq", e.Id); err != nil {
|
||||
return
|
||||
} else {
|
||||
|
@ -419,7 +419,7 @@ func (e Exercice) MCQSolved() (res []int64) {
|
|||
|
||||
// CheckResponse, given both flags and MCQ responses, figures out if thoses are correct (or if they are previously solved).
|
||||
// In the meanwhile, CheckResponse registers good answers given (but it does not mark the challenge as solved at the end).
|
||||
func (e Exercice) CheckResponse(cksum []byte, respflags map[int]string, respmcq map[int]bool, t Team) (bool, error) {
|
||||
func (e *Exercice) CheckResponse(cksum []byte, respflags map[int]string, respmcq map[int]bool, t *Team) (bool, error) {
|
||||
if err := e.NewTry(t, cksum); err != nil {
|
||||
return false, err
|
||||
} else if flags, err := e.GetFlagKeys(); err != nil {
|
||||
|
@ -477,12 +477,12 @@ func (e Exercice) CheckResponse(cksum []byte, respflags map[int]string, respmcq
|
|||
}
|
||||
|
||||
// IsSolved returns the number of time this challenge has been solved and the time of the first solve occurence.
|
||||
func (e Exercice) IsSolved() (int, time.Time) {
|
||||
func (e *Exercice) IsSolved() (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{}
|
||||
return 0, nil
|
||||
} else {
|
||||
return *nb, *tm
|
||||
return *nb, tm
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
// GetHistory aggregates all sources of events or actions for an Exercice
|
||||
func (e Exercice) GetHistory() ([]map[string]interface{}, error) {
|
||||
func (e *Exercice) GetHistory() ([]map[string]interface{}, error) {
|
||||
hist := make([]map[string]interface{}, 0)
|
||||
|
||||
if rows, err := DBQuery(`SELECT id_team, U.name, U.color, "tries" AS kind, time, 0, id_exercice, NULL, NULL FROM exercice_tries NATURAL JOIN teams U WHERE id_exercice = ? UNION
|
||||
|
@ -57,7 +57,7 @@ func (e Exercice) GetHistory() ([]map[string]interface{}, error) {
|
|||
}
|
||||
|
||||
// UpdateHistoryItem sets values an entry from the history.
|
||||
func (e Exercice) UpdateHistoryItem(coeff float32, tId int64, kind string, h time.Time, secondary *int64) (interface{}, error) {
|
||||
func (e *Exercice) UpdateHistoryItem(coeff float32, tId int64, kind string, h time.Time, secondary *int64) (interface{}, error) {
|
||||
if kind == "hint" && secondary != nil {
|
||||
if res, err := DBExec("UPDATE team_hints SET coefficient = ?, time = ? WHERE id_team = ? AND time = ? AND id_hint = ?", coeff, h, tId, h, *secondary); err != nil {
|
||||
return 0, err
|
||||
|
@ -88,7 +88,7 @@ func (e Exercice) UpdateHistoryItem(coeff float32, tId int64, kind string, h tim
|
|||
}
|
||||
|
||||
// DelHistoryItem removes from the database an entry from the history.
|
||||
func (e Exercice) DelHistoryItem(tId int64, kind string, h time.Time, secondary *int64) (interface{}, error) {
|
||||
func (e *Exercice) DelHistoryItem(tId int64, kind string, h time.Time, secondary *int64) (interface{}, error) {
|
||||
if kind == "tries" {
|
||||
if res, err := DBExec("DELETE FROM exercice_tries WHERE id_team = ? AND time = ? AND id_exercice = ?", tId, h, e.Id); err != nil {
|
||||
return 0, err
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
// GetTags returns tags associated with this exercice.
|
||||
func (e Exercice) GetTags() (tags []string, err error) {
|
||||
func (e *Exercice) GetTags() (tags []string, err error) {
|
||||
if rows, errr := DBQuery("SELECT tag FROM exercice_tags WHERE id_exercice = ?", e.Id); errr != nil {
|
||||
return nil, errr
|
||||
} else {
|
||||
|
@ -25,7 +25,7 @@ func (e Exercice) GetTags() (tags []string, err error) {
|
|||
}
|
||||
|
||||
// AddTag assign a new tag to the exercice and registers it into the database.
|
||||
func (e Exercice) AddTag(tag string) (string, error) {
|
||||
func (e *Exercice) AddTag(tag string) (string, error) {
|
||||
tag = strings.Title(tag)
|
||||
if _, err := DBExec("INSERT INTO exercice_tags (id_exercice, tag) VALUES (?, ?)", e.Id, tag); err != nil {
|
||||
return "", err
|
||||
|
@ -35,7 +35,7 @@ func (e Exercice) AddTag(tag string) (string, error) {
|
|||
}
|
||||
|
||||
// DeleteTag delete a tag assigned to the current exercice from the database.
|
||||
func (e Exercice) DeleteTag(tag string) (int64, error) {
|
||||
func (e *Exercice) DeleteTag(tag string) (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM exercice_tags WHERE id_exercice = ? AND tag = ?", e.Id, tag); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -46,7 +46,7 @@ func (e Exercice) DeleteTag(tag string) (int64, error) {
|
|||
}
|
||||
|
||||
// WipeTags delete all tag assigned to the current exercice from the database.
|
||||
func (e Exercice) WipeTags() (int64, error) {
|
||||
func (e *Exercice) WipeTags() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM exercice_tags WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
|
|
@ -45,15 +45,15 @@ type EFile struct {
|
|||
}
|
||||
|
||||
// GetFiles returns a list of all files living in the database.
|
||||
func GetFiles() ([]EFile, error) {
|
||||
func GetFiles() ([]*EFile, error) {
|
||||
if rows, err := DBQuery("SELECT id_file, id_exercice, origin, path, name, cksum, size FROM exercice_files"); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var files = make([]EFile, 0)
|
||||
files := []*EFile{}
|
||||
for rows.Next() {
|
||||
var f EFile
|
||||
f := &EFile{}
|
||||
if err := rows.Scan(&f.Id, &f.IdExercice, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.Size); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -68,16 +68,17 @@ func GetFiles() ([]EFile, error) {
|
|||
}
|
||||
|
||||
// GetFile retrieves the file with the given id.
|
||||
func GetFile(id int64) (f EFile, err error) {
|
||||
func GetFile(id int64) (f *EFile, err error) {
|
||||
f = &EFile{}
|
||||
err = DBQueryRow("SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE id_file = ?", id).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.Size)
|
||||
return
|
||||
}
|
||||
|
||||
// GetFileByPath retrieves the file that should be found at the given location.
|
||||
func GetFileByPath(path string) (EFile, error) {
|
||||
func GetFileByPath(path string) (*EFile, error) {
|
||||
path = strings.TrimPrefix(path, FilesDir)
|
||||
|
||||
var f EFile
|
||||
f := &EFile{}
|
||||
if err := DBQueryRow("SELECT id_file, origin, path, id_exercice, name, cksum, size FROM exercice_files WHERE path = ?", path).Scan(&f.Id, &f.origin, &f.Path, &f.IdExercice, &f.Name, &f.Checksum, &f.Size); err != nil {
|
||||
return f, err
|
||||
}
|
||||
|
@ -86,24 +87,25 @@ func GetFileByPath(path string) (EFile, error) {
|
|||
}
|
||||
|
||||
// GetFileByFilename retrieves the file that should be called so.
|
||||
func (e Exercice) GetFileByFilename(filename string) (f EFile, err error) {
|
||||
func (e *Exercice) GetFileByFilename(filename string) (f *EFile, err error) {
|
||||
filename = path.Base(filename)
|
||||
|
||||
f = &EFile{}
|
||||
err = DBQueryRow("SELECT id_file, origin, path, id_exercice, name, cksum, size FROM exercice_files WHERE id_exercice = ? AND origin LIKE ?", e.Id, "%/"+filename).Scan(&f.Id, &f.origin, &f.Path, &f.IdExercice, &f.Name, &f.Checksum, &f.Size)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetFiles returns a list of files coming with the challenge.
|
||||
func (e Exercice) GetFiles() ([]EFile, error) {
|
||||
func (e *Exercice) GetFiles() ([]*EFile, error) {
|
||||
if rows, err := DBQuery("SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var files = make([]EFile, 0)
|
||||
files := []*EFile{}
|
||||
for rows.Next() {
|
||||
var f EFile
|
||||
f := &EFile{}
|
||||
f.IdExercice = e.Id
|
||||
if err := rows.Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.Size); err != nil {
|
||||
return nil, err
|
||||
|
@ -119,12 +121,12 @@ func (e Exercice) GetFiles() ([]EFile, error) {
|
|||
}
|
||||
|
||||
// GetFileByPath retrieves the file that should be found at the given location, limited to the challenge files.
|
||||
func (e Exercice) GetFileByPath(path string) (EFile, error) {
|
||||
func (e *Exercice) GetFileByPath(path string) (*EFile, error) {
|
||||
path = strings.TrimPrefix(path, FilesDir)
|
||||
|
||||
var f EFile
|
||||
f := &EFile{}
|
||||
if err := DBQueryRow("SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE id_exercice = ? AND path = ?", e.Id, path).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.Size); err != nil {
|
||||
return f, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return f, nil
|
||||
|
@ -182,7 +184,7 @@ func CheckBufferHash(hash160 *hash.Hash, hash512 *hash.Hash, digest []byte) ([]b
|
|||
// It also returns the file's size.
|
||||
func checkFileHash(filePath string, digest []byte) (dgst []byte, size int64, err error) {
|
||||
if digest == nil {
|
||||
return []byte{}, 0, errors.New("No digest given.")
|
||||
return []byte{}, 0, errors.New("no digest given")
|
||||
} else if fi, errr := os.Stat(filePath); errr != nil {
|
||||
return []byte{}, 0, errr
|
||||
} else if fd, errr := os.Open(filePath); errr != nil {
|
||||
|
@ -204,7 +206,7 @@ func checkFileHash(filePath string, digest []byte) (dgst []byte, size int64, err
|
|||
}
|
||||
|
||||
// ImportFile registers (ou updates if it already exists in database) the file in database.
|
||||
func (e Exercice) ImportFile(filePath string, origin string, digest []byte) (interface{}, error) {
|
||||
func (e *Exercice) ImportFile(filePath string, origin string, digest []byte) (interface{}, error) {
|
||||
if result512, size, err := checkFileHash(filePath, digest); !OptionalDigest && err != nil {
|
||||
return EFile{}, err
|
||||
} else {
|
||||
|
@ -229,18 +231,18 @@ func (e Exercice) ImportFile(filePath string, origin string, digest []byte) (int
|
|||
}
|
||||
|
||||
// AddFile creates and fills a new struct File and registers it into the database.
|
||||
func (e Exercice) AddFile(path string, origin string, name string, checksum []byte, size int64) (EFile, error) {
|
||||
func (e *Exercice) AddFile(path string, origin string, name string, checksum []byte, size int64) (*EFile, error) {
|
||||
if res, err := DBExec("INSERT INTO exercice_files (id_exercice, origin, path, name, cksum, size) VALUES (?, ?, ?, ?, ?, ?)", e.Id, origin, path, name, checksum, size); err != nil {
|
||||
return EFile{}, err
|
||||
return nil, err
|
||||
} else if fid, err := res.LastInsertId(); err != nil {
|
||||
return EFile{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return EFile{fid, origin, path, e.Id, name, checksum, size}, nil
|
||||
return &EFile{fid, origin, path, e.Id, name, checksum, size}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (f EFile) Update() (int64, error) {
|
||||
func (f *EFile) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE exercice_files SET id_exercice = ?, origin = ?, path = ?, name = ?, cksum = ?, size = ? WHERE id_file = ?", f.IdExercice, f.origin, f.Path, f.Name, f.Checksum, f.Size, f.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -288,36 +290,36 @@ func ClearFiles() (int64, error) {
|
|||
}
|
||||
|
||||
// GetOrigin access the private field origin of the file.
|
||||
func (f EFile) GetOrigin() string {
|
||||
func (f *EFile) GetOrigin() string {
|
||||
return f.origin
|
||||
}
|
||||
|
||||
// AddDepend insert a new dependency to a given flag.
|
||||
func (f EFile) AddDepend(j Flag) (err error) {
|
||||
if k, ok := j.(FlagKey); ok {
|
||||
func (f *EFile) AddDepend(j Flag) (err error) {
|
||||
if k, ok := j.(*FlagKey); ok {
|
||||
_, err = DBExec("INSERT INTO exercice_files_okey_deps (id_file, id_flag) VALUES (?, ?)", f.Id, k.Id)
|
||||
} else if m, ok := j.(MCQ); ok {
|
||||
} else if m, ok := j.(*MCQ); ok {
|
||||
_, err = DBExec("INSERT INTO exercice_files_omcq_deps (id_file, id_mcq) VALUES (?, ?)", f.Id, m.Id)
|
||||
} else {
|
||||
err = errors.New("Dependancy type not implemented for this file.")
|
||||
err = errors.New("dependancy type not implemented for this file")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteDepend insert a new dependency to a given flag.
|
||||
func (f EFile) DeleteDepend(j Flag) (err error) {
|
||||
if k, ok := j.(FlagKey); ok {
|
||||
func (f *EFile) DeleteDepend(j Flag) (err error) {
|
||||
if k, ok := j.(*FlagKey); ok {
|
||||
_, err = DBExec("DELETE FROM exercice_files_okey_deps WHERE id_file = ? AND id_flag = ?", f.Id, k.Id)
|
||||
} else if m, ok := j.(MCQ); ok {
|
||||
} else if m, ok := j.(*MCQ); ok {
|
||||
_, err = DBExec("DELETE FROM exercice_files_omcq_deps WHERE id_file = ? AND id_mcq = ?", f.Id, m.Id)
|
||||
} else {
|
||||
err = errors.New("Dependancy type not implemented for this file.")
|
||||
err = errors.New("dependancy type not implemented for this file")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetDepends retrieve the flag's dependency list.
|
||||
func (f EFile) GetDepends() ([]Flag, error) {
|
||||
func (f *EFile) GetDepends() ([]Flag, error) {
|
||||
var deps = make([]Flag, 0)
|
||||
|
||||
if rows, err := DBQuery("SELECT id_flag FROM exercice_files_okey_deps WHERE id_file = ?", f.Id); err != nil {
|
||||
|
@ -330,7 +332,7 @@ func (f EFile) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, FlagKey{d, f.IdExercice, 0, "", "", "", "", "", false, false, nil, []byte{}, 0})
|
||||
deps = append(deps, &FlagKey{d, f.IdExercice, 0, "", "", "", "", "", false, false, nil, []byte{}, 0})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -347,7 +349,7 @@ func (f EFile) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, MCQ{d, f.IdExercice, 0, "", []MCQ_entry{}})
|
||||
deps = append(deps, &MCQ{d, f.IdExercice, 0, "", []*MCQ_entry{}})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -358,11 +360,11 @@ func (f EFile) GetDepends() ([]Flag, error) {
|
|||
}
|
||||
|
||||
// CheckFileOnDisk recalculates the hash of the file on disk.
|
||||
func (f EFile) CheckFileOnDisk() error {
|
||||
func (f *EFile) CheckFileOnDisk() error {
|
||||
if _, size, err := checkFileHash(path.Join(FilesDir, f.Path), f.Checksum); err != nil {
|
||||
return err
|
||||
} else if size == 0 {
|
||||
return errors.New("Empty file!")
|
||||
return errors.New("empty file")
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,19 +5,19 @@ import ()
|
|||
type Flag interface {
|
||||
GetId() int
|
||||
RecoverId() (Flag, error)
|
||||
Create(e Exercice) (Flag, error)
|
||||
Create(e *Exercice) (Flag, error)
|
||||
Update() (int64, error)
|
||||
Delete() (int64, error)
|
||||
AddDepend(d Flag) error
|
||||
GetDepends() ([]Flag, error)
|
||||
GetOrder() int8
|
||||
Check(val interface{}) int
|
||||
FoundBy(t Team)
|
||||
FoundBy(t *Team)
|
||||
}
|
||||
|
||||
// GetFlag returns a list of flags comming with the challenge.
|
||||
func (e Exercice) GetFlags() ([]Flag, error) {
|
||||
var flags = make([]Flag, 0)
|
||||
func (e *Exercice) GetFlags() ([]Flag, error) {
|
||||
var flags []Flag
|
||||
|
||||
if ks, err := e.GetFlagKeys(); err != nil {
|
||||
return nil, err
|
||||
|
@ -39,12 +39,12 @@ func (e Exercice) GetFlags() ([]Flag, error) {
|
|||
}
|
||||
|
||||
// AddFlag add the given flag and eventually its entries (from MCQ).
|
||||
func (e Exercice) AddFlag(flag Flag) (f Flag, err error) {
|
||||
func (e *Exercice) AddFlag(flag Flag) (Flag, error) {
|
||||
return flag.Create(e)
|
||||
}
|
||||
|
||||
// WipeFlags deletes flags coming with the challenge.
|
||||
func (e Exercice) WipeFlags() (int64, error) {
|
||||
func (e *Exercice) WipeFlags() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM exercice_files_okey_deps WHERE id_flag IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if _, err := DBExec("DELETE FROM exercice_files_omcq_deps WHERE id_mcq IN (SELECT id_mcq FROM exercice_mcq WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
|
|
|
@ -14,15 +14,15 @@ type FlagChoice struct {
|
|||
}
|
||||
|
||||
// GetChoices returns a list of choices for the given Flag.
|
||||
func (f FlagKey) GetChoices() ([]FlagChoice, error) {
|
||||
func (f *FlagKey) GetChoices() ([]*FlagChoice, error) {
|
||||
if rows, err := DBQuery("SELECT id_choice, id_flag, label, response FROM flag_choices WHERE id_flag = ?", f.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var choices = make([]FlagChoice, 0)
|
||||
var choices []*FlagChoice
|
||||
for rows.Next() {
|
||||
var c FlagChoice
|
||||
c := &FlagChoice{}
|
||||
c.IdFlag = f.Id
|
||||
|
||||
if err := rows.Scan(&c.Id, &c.IdFlag, &c.Label, &c.Value); err != nil {
|
||||
|
@ -40,7 +40,8 @@ func (f FlagKey) GetChoices() ([]FlagChoice, error) {
|
|||
}
|
||||
|
||||
// GetChoice returns a choice for the given Flag.
|
||||
func (f FlagKey) GetChoice(id int) (c FlagChoice, err error) {
|
||||
func (f *FlagKey) GetChoice(id int) (c *FlagChoice, err error) {
|
||||
c = &FlagChoice{}
|
||||
if errr := DBQueryRow("SELECT id_choice, id_flag, label, response FROM flag_choices WHERE id_choice = ?", id).Scan(&c.Id, &c.IdFlag, &c.Label, &c.Value); errr != nil {
|
||||
return c, errr
|
||||
}
|
||||
|
@ -48,7 +49,7 @@ func (f FlagKey) GetChoice(id int) (c FlagChoice, err error) {
|
|||
}
|
||||
|
||||
// AddChoice creates and fills a new struct FlagChoice, from a label and a value.
|
||||
func (f FlagKey) AddChoice(c FlagChoice) (FlagChoice, error) {
|
||||
func (f *FlagKey) AddChoice(c *FlagChoice) (*FlagChoice, error) {
|
||||
if res, err := DBExec("INSERT INTO flag_choices (id_flag, label, response) VALUES (?, ?, ?)", f.Id, c.Label, c.Value); err != nil {
|
||||
return c, err
|
||||
} else {
|
||||
|
@ -59,7 +60,7 @@ func (f FlagKey) AddChoice(c FlagChoice) (FlagChoice, error) {
|
|||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (c FlagChoice) Update() (int64, error) {
|
||||
func (c *FlagChoice) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE flag_choices SET id_flag = ?, label = ?, response = ? WHERE id_choice = ?", c.IdFlag, c.Label, c.Value, c.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -70,7 +71,7 @@ func (c FlagChoice) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the flag from the database.
|
||||
func (c FlagChoice) Delete() (int64, error) {
|
||||
func (c *FlagChoice) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM flag_choices WHERE id_choice = ?", c.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -81,7 +82,7 @@ func (c FlagChoice) Delete() (int64, error) {
|
|||
}
|
||||
|
||||
// WipeFlags deletes flags coming with the challenge.
|
||||
func (f FlagKey) WipeChoices() (int64, error) {
|
||||
func (f *FlagKey) WipeChoices() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM flag_choices WHERE id_flag = ?", f.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
|
|
@ -40,15 +40,15 @@ type FlagKey struct {
|
|||
}
|
||||
|
||||
// GetFlagKeys returns a list of key's flags comming with the challenge.
|
||||
func (e Exercice) GetFlagKeys() ([]FlagKey, error) {
|
||||
func (e *Exercice) GetFlagKeys() ([]*FlagKey, error) {
|
||||
if rows, err := DBQuery("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var flags = make([]FlagKey, 0)
|
||||
flags := []*FlagKey{}
|
||||
for rows.Next() {
|
||||
var k FlagKey
|
||||
k := &FlagKey{}
|
||||
k.IdExercice = e.Id
|
||||
|
||||
if err := rows.Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost); err != nil {
|
||||
|
@ -66,13 +66,15 @@ func (e Exercice) GetFlagKeys() ([]FlagKey, error) {
|
|||
}
|
||||
|
||||
// GetFlagKey returns a list of flags comming with the challenge.
|
||||
func GetFlagKey(id int) (k FlagKey, err error) {
|
||||
func GetFlagKey(id int) (k *FlagKey, err error) {
|
||||
k = &FlagKey{}
|
||||
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE id_flag = ?", id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost)
|
||||
return
|
||||
}
|
||||
|
||||
// GetFlagKeyByLabel returns a flag matching the given label.
|
||||
func (e Exercice) GetFlagKeyByLabel(label string) (k FlagKey, err error) {
|
||||
func (e *Exercice) GetFlagKeyByLabel(label string) (k *FlagKey, err error) {
|
||||
k = &FlagKey{}
|
||||
err = DBQueryRow("SELECT id_flag, id_exercice, ordre, label, type, placeholder, help, unit, ignorecase, multiline, validator_regexp, cksum, choices_cost FROM exercice_flags WHERE type LIKE ? AND id_exercice = ?", label, e.Id).Scan(&k.Id, &k.IdExercice, &k.Order, &k.Label, &k.Type, &k.Placeholder, &k.Help, &k.Unit, &k.IgnoreCase, &k.Multiline, &k.ValidatorRegexp, &k.Checksum, &k.ChoicesCost)
|
||||
return
|
||||
}
|
||||
|
@ -92,7 +94,7 @@ func ComputeHashedFlag(raw_value []byte, ignorecase bool, validator_regexp *stri
|
|||
|
||||
// Check that the value is not empty
|
||||
if len(raw_value) == 0 {
|
||||
err = errors.New("Empty flag after applying filters")
|
||||
err = errors.New("empty flag after applying filters")
|
||||
}
|
||||
|
||||
hash = blake2b.Sum512(raw_value)
|
||||
|
@ -106,20 +108,20 @@ func ExecValidatorRegexp(vre string, val []byte, ignorecase bool) ([]byte, error
|
|||
if re, err := regexp.Compile(vre); err != nil {
|
||||
return val, err
|
||||
} else if res := re.FindSubmatch(val); res == nil {
|
||||
return val, errors.New("Expected flag doesn't pass through the validator_regexp")
|
||||
return val, errors.New("expected flag doesn't pass through the validator_regexp")
|
||||
} else {
|
||||
return bytes.Join(res[1:], []byte("+")), nil
|
||||
}
|
||||
}
|
||||
|
||||
// AddRawFlagKey creates and fills a new struct FlagKey, from a non-hashed flag, and registers it into the database.
|
||||
func (e Exercice) AddRawFlagKey(name string, t string, placeholder string, ignorecase bool, multiline bool, validator_regexp *string, raw_value []byte, choicescost int64) (f FlagKey, err error) {
|
||||
hash, errr := ComputeHashedFlag(raw_value, ignorecase, validator_regexp)
|
||||
if errr != nil {
|
||||
return f, err
|
||||
func (e *Exercice) AddRawFlagKey(name string, t string, placeholder string, ignorecase bool, multiline bool, validator_regexp *string, raw_value []byte, choicescost int64) (*FlagKey, error) {
|
||||
hash, err := ComputeHashedFlag(raw_value, ignorecase, validator_regexp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f = FlagKey{
|
||||
f := &FlagKey{
|
||||
Type: t,
|
||||
Label: name,
|
||||
Placeholder: placeholder,
|
||||
|
@ -131,25 +133,25 @@ func (e Exercice) AddRawFlagKey(name string, t string, placeholder string, ignor
|
|||
}
|
||||
|
||||
_, err = f.Create(e)
|
||||
return
|
||||
return f, err
|
||||
}
|
||||
|
||||
// GetId returns the Flag identifier.
|
||||
func (k FlagKey) GetId() int {
|
||||
func (k *FlagKey) GetId() int {
|
||||
return k.Id
|
||||
}
|
||||
|
||||
// RecoverId returns the Flag identifier as register in DB.
|
||||
func (k FlagKey) RecoverId() (Flag, error) {
|
||||
func (k *FlagKey) RecoverId() (Flag, error) {
|
||||
if err := DBQueryRow("SELECT id_flag FROM exercice_flags WHERE label LIKE ? AND id_exercice = ?", k.Label, k.IdExercice).Scan(&k.Id); err != nil {
|
||||
return FlagKey{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return k, err
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlagKey creates and fills a new struct Flag, from a hashed flag, and registers it into the database.
|
||||
func (k FlagKey) Create(e Exercice) (Flag, error) {
|
||||
func (k *FlagKey) Create(e *Exercice) (Flag, error) {
|
||||
// Check the regexp compile
|
||||
if k.ValidatorRegexp != nil {
|
||||
if _, err := regexp.Compile(*k.ValidatorRegexp); err != nil {
|
||||
|
@ -169,13 +171,13 @@ func (k FlagKey) Create(e Exercice) (Flag, error) {
|
|||
}
|
||||
|
||||
// ComputeChecksum calculates the checksum for a given value.
|
||||
func (k FlagKey) ComputeChecksum(val []byte) ([]byte, error) {
|
||||
func (k *FlagKey) ComputeChecksum(val []byte) ([]byte, error) {
|
||||
cksum, err := ComputeHashedFlag(val, k.IgnoreCase, k.ValidatorRegexp)
|
||||
return cksum[:], err
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (k FlagKey) Update() (int64, error) {
|
||||
func (k *FlagKey) Update() (int64, error) {
|
||||
if k.ValidatorRegexp != nil {
|
||||
if _, err := regexp.Compile(*k.ValidatorRegexp); err != nil {
|
||||
return 0, err
|
||||
|
@ -192,7 +194,7 @@ func (k FlagKey) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the flag from the database.
|
||||
func (k FlagKey) Delete() (int64, error) {
|
||||
func (k *FlagKey) Delete() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM exercice_files_okey_deps WHERE id_flag = ?", k.Id); err != nil {
|
||||
return 0, err
|
||||
} else if _, err := DBExec("DELETE FROM exercice_mcq_okey_deps WHERE id_flag_dep = ?", k.Id); err != nil {
|
||||
|
@ -214,25 +216,25 @@ func (k FlagKey) Delete() (int64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (k FlagKey) GetOrder() int8 {
|
||||
func (k *FlagKey) GetOrder() int8 {
|
||||
return k.Order
|
||||
}
|
||||
|
||||
// AddDepend insert a new dependency to a given flag.
|
||||
func (k FlagKey) AddDepend(j Flag) (err error) {
|
||||
if d, ok := j.(FlagKey); ok {
|
||||
func (k *FlagKey) AddDepend(j Flag) (err error) {
|
||||
if d, ok := j.(*FlagKey); ok {
|
||||
_, err = DBExec("INSERT INTO exercice_flags_deps (id_flag, id_flag_dep) VALUES (?, ?)", k.Id, d.Id)
|
||||
} else if d, ok := j.(MCQ); ok {
|
||||
} else if d, ok := j.(*MCQ); ok {
|
||||
_, err = DBExec("INSERT INTO exercice_flags_omcq_deps (id_flag, id_mcq_dep) VALUES (?, ?)", k.Id, d.Id)
|
||||
} else {
|
||||
err = fmt.Errorf("Dependancy type for key (%T) not implemented for this flag.", j)
|
||||
err = fmt.Errorf("dependancy type for key (%T) not implemented for this flag", j)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetDepends retrieve the flag's dependency list.
|
||||
func (k FlagKey) GetDepends() ([]Flag, error) {
|
||||
var deps = make([]Flag, 0)
|
||||
func (k *FlagKey) GetDepends() ([]Flag, error) {
|
||||
var deps []Flag
|
||||
|
||||
if rows, err := DBQuery("SELECT id_flag_dep FROM exercice_flags_deps WHERE id_flag = ?", k.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -244,7 +246,7 @@ func (k FlagKey) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, FlagKey{Id: d, IdExercice: k.IdExercice})
|
||||
deps = append(deps, &FlagKey{Id: d, IdExercice: k.IdExercice})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -261,7 +263,7 @@ func (k FlagKey) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, MCQ{Id: d, IdExercice: k.IdExercice})
|
||||
deps = append(deps, &MCQ{Id: d, IdExercice: k.IdExercice})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -272,7 +274,7 @@ func (k FlagKey) GetDepends() ([]Flag, error) {
|
|||
}
|
||||
|
||||
// Check if the given val is the expected one for this flag.
|
||||
func (k FlagKey) Check(v interface{}) int {
|
||||
func (k *FlagKey) Check(v interface{}) int {
|
||||
var val []byte
|
||||
|
||||
if va, ok := v.([]byte); !ok {
|
||||
|
@ -299,15 +301,15 @@ func (k FlagKey) Check(v interface{}) int {
|
|||
}
|
||||
|
||||
// FoundBy registers in the database that the given Team solved the flag.
|
||||
func (k FlagKey) FoundBy(t Team) {
|
||||
func (k *FlagKey) FoundBy(t *Team) {
|
||||
DBExec("INSERT INTO flag_found (id_flag, id_team, time) VALUES (?, ?, ?)", k.Id, t.Id, time.Now())
|
||||
}
|
||||
|
||||
// GetExercice returns the parent Exercice where this flag can be found.
|
||||
func (k FlagKey) GetExercice() (Exercice, error) {
|
||||
func (k *FlagKey) GetExercice() (*Exercice, error) {
|
||||
var eid int64
|
||||
if err := DBQueryRow("SELECT id_exercice FROM exercice_flags WHERE id_flag = ?", k.Id).Scan(&eid); err != nil {
|
||||
return Exercice{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return GetExercice(eid)
|
||||
|
|
|
@ -36,42 +36,42 @@ func treatHintContent(h *EHint) {
|
|||
}
|
||||
|
||||
// GetHint retrieves the hint with the given id.
|
||||
func GetHint(id int64) (EHint, error) {
|
||||
var h EHint
|
||||
func GetHint(id int64) (*EHint, error) {
|
||||
h := &EHint{}
|
||||
if err := DBQueryRow("SELECT id_hint, id_exercice, title, content, cost FROM exercice_hints WHERE id_hint = ?", id).Scan(&h.Id, &h.IdExercice, &h.Title, &h.Content, &h.Cost); err != nil {
|
||||
return h, err
|
||||
return nil, err
|
||||
}
|
||||
treatHintContent(&h)
|
||||
treatHintContent(h)
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// GetHintByTitle retrieves the hint with the given id.
|
||||
func (e Exercice) GetHintByTitle(id int64) (EHint, error) {
|
||||
var h EHint
|
||||
func (e *Exercice) GetHintByTitle(id int64) (*EHint, error) {
|
||||
h := &EHint{}
|
||||
if err := DBQueryRow("SELECT id_hint, id_exercice, title, content, cost FROM exercice_hints WHERE title = ? AND id_exercice = ?", id, e.Id).Scan(&h.Id, &h.IdExercice, &h.Title, &h.Content, &h.Cost); err != nil {
|
||||
return h, err
|
||||
return nil, err
|
||||
}
|
||||
treatHintContent(&h)
|
||||
treatHintContent(h)
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// GetHints returns a list of hints comming with the challenge.
|
||||
func (e Exercice) GetHints() ([]EHint, error) {
|
||||
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)
|
||||
var hints []*EHint
|
||||
for rows.Next() {
|
||||
var h EHint
|
||||
h := &EHint{}
|
||||
h.IdExercice = e.Id
|
||||
if err := rows.Scan(&h.Id, &h.Title, &h.Content, &h.Cost); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
treatHintContent(&h)
|
||||
treatHintContent(h)
|
||||
hints = append(hints, h)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
|
@ -83,18 +83,18 @@ func (e Exercice) GetHints() ([]EHint, error) {
|
|||
}
|
||||
|
||||
// AddHint creates and fills a new struct EHint and registers it into the database.
|
||||
func (e Exercice) AddHint(title string, content string, cost int64) (EHint, error) {
|
||||
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
|
||||
return nil, err
|
||||
} else if hid, err := res.LastInsertId(); err != nil {
|
||||
return EHint{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return EHint{hid, e.Id, title, content, "", cost}, nil
|
||||
return &EHint{hid, e.Id, title, content, "", cost}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (h EHint) Update() (int64, error) {
|
||||
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 {
|
||||
|
@ -105,7 +105,7 @@ func (h EHint) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the hint from the database.
|
||||
func (h EHint) Delete() (int64, error) {
|
||||
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 {
|
||||
|
@ -116,7 +116,7 @@ func (h EHint) Delete() (int64, error) {
|
|||
}
|
||||
|
||||
// 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 _, err := DBExec("DELETE FROM exercice_hints_okey_deps WHERE id_hint IN (SELECT id_hint FROM exercice_hints WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if _, err := DBExec("DELETE FROM exercice_hints_omcq_deps WHERE id_hint IN (SELECT id_hint FROM exercice_hints WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
|
@ -131,20 +131,20 @@ 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 {
|
||||
func (h *EHint) AddDepend(f Flag) (err error) {
|
||||
if d, ok := f.(*FlagKey); ok {
|
||||
_, err = DBExec("INSERT INTO exercice_hints_okey_deps (id_hint, id_flag_dep) VALUES (?, ?)", h.Id, d.Id)
|
||||
} else if d, ok := f.(MCQ); ok {
|
||||
} else if d, ok := f.(*MCQ); ok {
|
||||
_, err = DBExec("INSERT INTO exercice_hints_omcq_deps (id_hint, id_mcq_dep) VALUES (?, ?)", h.Id, d.Id)
|
||||
} else {
|
||||
err = fmt.Errorf("Dependancy type for key (%T) not implemented for this flag.", f)
|
||||
err = fmt.Errorf("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)
|
||||
func (h *EHint) GetDepends() ([]Flag, error) {
|
||||
var deps []Flag
|
||||
|
||||
if rows, err := DBQuery("SELECT id_flag_dep FROM exercice_hints_okey_deps WHERE id_hint = ?", h.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -156,7 +156,7 @@ func (h EHint) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, FlagKey{Id: d, IdExercice: h.IdExercice})
|
||||
deps = append(deps, &FlagKey{Id: d, IdExercice: h.IdExercice})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -173,7 +173,7 @@ func (h EHint) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, MCQ{Id: d, IdExercice: h.IdExercice})
|
||||
deps = append(deps, &MCQ{Id: d, IdExercice: h.IdExercice})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -184,10 +184,10 @@ func (h EHint) GetDepends() ([]Flag, error) {
|
|||
}
|
||||
|
||||
// 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
|
||||
if err := DBQueryRow("SELECT id_exercice FROM exercice_hints WHERE id_hint = ?", h.Id).Scan(&eid); err != nil {
|
||||
return Exercice{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return GetExercice(eid)
|
||||
|
|
|
@ -16,7 +16,7 @@ type MCQ struct {
|
|||
// Title is the label of the question
|
||||
Title string `json:"title"`
|
||||
// Entries stores the set of proposed answers
|
||||
Entries []MCQ_entry `json:"entries"`
|
||||
Entries []*MCQ_entry `json:"entries"`
|
||||
}
|
||||
|
||||
// MCQ_entry represents a proposed response for a given MCQ.
|
||||
|
@ -29,20 +29,21 @@ type MCQ_entry struct {
|
|||
}
|
||||
|
||||
// GetMCQ returns a list of flags comming with the challenge.
|
||||
func GetMCQ(id int) (m MCQ, err error) {
|
||||
func GetMCQ(id int) (m *MCQ, err error) {
|
||||
m = &MCQ{}
|
||||
err = DBQueryRow("SELECT id_mcq, id_exercice, order, title FROM exercice_mcq WHERE id_mcq = ?", id).Scan(&m.Id, &m.IdExercice, &m.Order, &m.Title)
|
||||
m.fillEntries()
|
||||
return
|
||||
}
|
||||
|
||||
func (m *MCQ) fillEntries() ([]MCQ_entry, error) {
|
||||
func (m *MCQ) fillEntries() ([]*MCQ_entry, error) {
|
||||
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()
|
||||
|
||||
for entries_rows.Next() {
|
||||
var e MCQ_entry
|
||||
e := &MCQ_entry{}
|
||||
|
||||
if err := entries_rows.Scan(&e.Id, &e.Label, &e.Response); err != nil {
|
||||
return nil, err
|
||||
|
@ -56,15 +57,15 @@ func (m *MCQ) fillEntries() ([]MCQ_entry, error) {
|
|||
}
|
||||
|
||||
// GetMCQ returns the MCQs coming with the challenge.
|
||||
func (e Exercice) GetMCQ() ([]MCQ, error) {
|
||||
func (e *Exercice) GetMCQ() ([]*MCQ, error) {
|
||||
if rows, err := DBQuery("SELECT id_mcq, id_exercice, ordre, title FROM exercice_mcq WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var mcqs = make([]MCQ, 0)
|
||||
var mcqs = []*MCQ{}
|
||||
for rows.Next() {
|
||||
var m MCQ
|
||||
m := &MCQ{}
|
||||
m.IdExercice = e.Id
|
||||
|
||||
if err := rows.Scan(&m.Id, &m.IdExercice, &m.Order, &m.Title); err != nil {
|
||||
|
@ -84,18 +85,19 @@ func (e Exercice) GetMCQ() ([]MCQ, error) {
|
|||
}
|
||||
|
||||
// GetMCQbyChoice returns the MCQ corresponding to a choice ID.
|
||||
func GetMCQbyChoice(cid int) (m MCQ, c MCQ_entry, err error) {
|
||||
func GetMCQbyChoice(cid int) (m *MCQ, c *MCQ_entry, err error) {
|
||||
m = &MCQ{}
|
||||
if errr := DBQueryRow("SELECT id_mcq, id_exercice, ordre, title FROM exercice_mcq WHERE id_mcq = (SELECT id_mcq FROM mcq_entries WHERE id_mcq_entry = ?)", cid).Scan(&m.Id, &m.IdExercice, &m.Order, &m.Title); errr != nil {
|
||||
return MCQ{}, MCQ_entry{}, errr
|
||||
return nil, nil, errr
|
||||
}
|
||||
|
||||
if entries_rows, errr := DBQuery("SELECT id_mcq_entry, label, response FROM mcq_entries WHERE id_mcq = ?", m.Id); errr != nil {
|
||||
return MCQ{}, MCQ_entry{}, errr
|
||||
return nil, nil, errr
|
||||
} else {
|
||||
defer entries_rows.Close()
|
||||
|
||||
for entries_rows.Next() {
|
||||
var e MCQ_entry
|
||||
e := &MCQ_entry{}
|
||||
|
||||
if err = entries_rows.Scan(&e.Id, &e.Label, &e.Response); err != nil {
|
||||
return
|
||||
|
@ -113,21 +115,21 @@ func GetMCQbyChoice(cid int) (m MCQ, c MCQ_entry, err error) {
|
|||
}
|
||||
|
||||
// GetId returns the MCQ identifier.
|
||||
func (m MCQ) GetId() int {
|
||||
func (m *MCQ) GetId() int {
|
||||
return m.Id
|
||||
}
|
||||
|
||||
// RecoverId returns the MCQ identifier as register in DB.
|
||||
func (m MCQ) RecoverId() (Flag, error) {
|
||||
func (m *MCQ) RecoverId() (Flag, error) {
|
||||
if err := DBQueryRow("SELECT id_mcq FROM exercice_mcq WHERE title LIKE ? AND id_exercice = ?", m.Title, m.IdExercice).Scan(&m.Id); err != nil {
|
||||
return MCQ{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return m, err
|
||||
}
|
||||
}
|
||||
|
||||
// Create registers a MCQ into the database and recursively add its entries.
|
||||
func (m MCQ) Create(e Exercice) (Flag, error) {
|
||||
func (m *MCQ) Create(e *Exercice) (Flag, error) {
|
||||
if res, err := DBExec("INSERT INTO exercice_mcq (id_exercice, ordre, title) VALUES (?, ?, ?)", e.Id, m.Order, m.Title); err != nil {
|
||||
return m, err
|
||||
} else if qid, err := res.LastInsertId(); err != nil {
|
||||
|
@ -150,7 +152,7 @@ func (m MCQ) Create(e Exercice) (Flag, error) {
|
|||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (m MCQ) Update() (int64, error) {
|
||||
func (m *MCQ) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE exercice_mcq SET id_exercice = ?, ordre = ?, title = ? WHERE id_mcq = ?", m.IdExercice, m.Order, m.Title, m.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -161,7 +163,7 @@ func (m MCQ) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the MCQ from the database.
|
||||
func (m MCQ) Delete() (int64, error) {
|
||||
func (m *MCQ) Delete() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM exercice_files_omcq_deps WHERE id_mcq = ?", m.Id); err != nil {
|
||||
return 0, err
|
||||
} else if _, err := DBExec("DELETE FROM exercice_mcq_okey_deps WHERE id_mcq = ?", m.Id); err != nil {
|
||||
|
@ -184,7 +186,7 @@ func (m MCQ) Delete() (int64, error) {
|
|||
}
|
||||
|
||||
// AddEntry creates and fills a new struct MCQ_entry and registers it into the database.
|
||||
func (m MCQ) AddEntry(e MCQ_entry) (MCQ_entry, error) {
|
||||
func (m *MCQ) AddEntry(e *MCQ_entry) (*MCQ_entry, error) {
|
||||
if res, err := DBExec("INSERT INTO mcq_entries (id_mcq, label, response) VALUES (?, ?, ?)", m.Id, e.Label, e.Response); err != nil {
|
||||
return e, err
|
||||
} else if nid, err := res.LastInsertId(); err != nil {
|
||||
|
@ -196,7 +198,7 @@ func (m MCQ) AddEntry(e MCQ_entry) (MCQ_entry, error) {
|
|||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (n MCQ_entry) Update() (int64, error) {
|
||||
func (n *MCQ_entry) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE mcq_entries SET label = ?, response = ? WHERE id_mcq = ?", n.Label, n.Response, n.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -207,7 +209,7 @@ func (n MCQ_entry) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the MCQ entry from the database.
|
||||
func (n MCQ_entry) Delete() (int64, error) {
|
||||
func (n *MCQ_entry) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM mcq_entries WHERE id_mcq_entry = ?", n.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -218,7 +220,7 @@ func (n MCQ_entry) Delete() (int64, error) {
|
|||
}
|
||||
|
||||
// WipeMCQs deletes MCQs coming with the challenge.
|
||||
func (e Exercice) WipeMCQs() (int64, error) {
|
||||
func (e *Exercice) WipeMCQs() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM exercice_files_omcq_deps WHERE id_mcq IN (SELECT id_mcq FROM exercice_mcq WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if _, err := DBExec("DELETE FROM mcq_entries WHERE id_mcq IN (SELECT id_mcq FROM exercice_mcq WHERE id_exercice = ?);", e.Id); err != nil {
|
||||
|
@ -240,25 +242,25 @@ func (e Exercice) WipeMCQs() (int64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (m MCQ) GetOrder() int8 {
|
||||
func (m *MCQ) GetOrder() int8 {
|
||||
return m.Order
|
||||
}
|
||||
|
||||
// AddDepend insert a new dependency to a given flag.
|
||||
func (m MCQ) AddDepend(j Flag) (err error) {
|
||||
if d, ok := j.(FlagKey); ok {
|
||||
func (m *MCQ) AddDepend(j Flag) (err error) {
|
||||
if d, ok := j.(*FlagKey); ok {
|
||||
_, err = DBExec("INSERT INTO exercice_mcq_okey_deps (id_mcq, id_flag_dep) VALUES (?, ?)", m.Id, d.Id)
|
||||
} else if d, ok := j.(MCQ); ok {
|
||||
} else if d, ok := j.(*MCQ); ok {
|
||||
_, err = DBExec("INSERT INTO exercice_mcq_omcq_deps (id_mcq, id_mcq_dep) VALUES (?, ?)", m.Id, d.Id)
|
||||
} else {
|
||||
err = errors.New("Dependancy type not implemented for this flag.")
|
||||
err = errors.New("dependancy type not implemented for this flag")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetDepends retrieve the flag's dependency list.
|
||||
func (m MCQ) GetDepends() ([]Flag, error) {
|
||||
var deps = make([]Flag, 0)
|
||||
func (m *MCQ) GetDepends() ([]Flag, error) {
|
||||
deps := []Flag{}
|
||||
|
||||
if rows, err := DBQuery("SELECT id_flag_dep FROM exercice_mcq_okey_deps WHERE id_mcq = ?", m.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -270,7 +272,7 @@ func (m MCQ) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, FlagKey{Id: d, IdExercice: m.IdExercice})
|
||||
deps = append(deps, &FlagKey{Id: d, IdExercice: m.IdExercice})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -288,7 +290,7 @@ func (m MCQ) GetDepends() ([]Flag, error) {
|
|||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, MCQ{Id: d, IdExercice: m.IdExercice})
|
||||
deps = append(deps, &MCQ{Id: d, IdExercice: m.IdExercice})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
@ -300,12 +302,12 @@ func (m MCQ) GetDepends() ([]Flag, error) {
|
|||
}
|
||||
|
||||
// GetJustifiedFlag searchs for a flag in the scope of the given exercice.
|
||||
func (c MCQ_entry) GetJustifiedFlag(e Exercice) (FlagKey, error) {
|
||||
func (c *MCQ_entry) GetJustifiedFlag(e *Exercice) (*FlagKey, error) {
|
||||
return e.GetFlagKeyByLabel(fmt.Sprintf("\\%%%d\\%%%%", c.Id))
|
||||
}
|
||||
|
||||
// Check if the given vals are the expected ones to validate this flag.
|
||||
func (m MCQ) Check(v interface{}) int {
|
||||
func (m *MCQ) Check(v interface{}) int {
|
||||
var vals map[int]bool
|
||||
if va, ok := v.(map[int]bool); !ok {
|
||||
return -1
|
||||
|
@ -326,6 +328,6 @@ func (m MCQ) Check(v interface{}) int {
|
|||
}
|
||||
|
||||
// FoundBy registers in the database that the given Team solved the MCQ.
|
||||
func (m MCQ) FoundBy(t Team) {
|
||||
func (m *MCQ) FoundBy(t *Team) {
|
||||
DBExec("INSERT INTO mcq_found (id_mcq, id_team, time) VALUES (?, ?, ?)", m.Id, t.Id, time.Now())
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ func (k FlagKey) GetMCQJustification() (fl FlagLabel, err error) {
|
|||
fl.IdChoice = int(idChoice)
|
||||
fl.Label = strings.Join(spl[2:], "%")
|
||||
} else {
|
||||
err = errors.New("This is not a MCQ justification")
|
||||
err = errors.New("this is not a MCQ justification")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -12,15 +12,15 @@ type Member struct {
|
|||
}
|
||||
|
||||
// GetMembers retrieves the members of the Team
|
||||
func (t Team) GetMembers() ([]Member, error) {
|
||||
func (t *Team) GetMembers() ([]*Member, error) {
|
||||
if rows, err := DBQuery("SELECT id_member, firstname, lastname, nickname, company FROM team_members WHERE id_team = ?", t.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var members = make([]Member, 0)
|
||||
var members []*Member
|
||||
for rows.Next() {
|
||||
var m Member
|
||||
m := &Member{}
|
||||
if err := rows.Scan(&m.Id, &m.Firstname, &m.Lastname, &m.Nickname, &m.Company); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -35,18 +35,18 @@ func (t Team) GetMembers() ([]Member, error) {
|
|||
}
|
||||
|
||||
// AddMember creates and fills a new struct Member and registers it into the database.
|
||||
func (t Team) AddMember(firstname string, lastname string, nickname string, company string) (Member, error) {
|
||||
func (t *Team) AddMember(firstname string, lastname string, nickname string, company string) (*Member, error) {
|
||||
if res, err := DBExec("INSERT INTO team_members (id_team, firstname, lastname, nickname, company) VALUES (?, ?, ?, ?, ?)", t.Id, firstname, lastname, nickname, company); err != nil {
|
||||
return Member{}, err
|
||||
return nil, err
|
||||
} else if mid, err := res.LastInsertId(); err != nil {
|
||||
return Member{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return Member{mid, firstname, lastname, nickname, company}, nil
|
||||
return &Member{mid, firstname, lastname, nickname, company}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// GainMember associates (or registers, it if it doesn't exists yet) a member to the team.
|
||||
func (t Team) GainMember(m Member) error {
|
||||
func (t *Team) GainMember(m *Member) error {
|
||||
if m.Id == 0 {
|
||||
if res, err := DBExec("INSERT INTO team_members (id_team, firstname, lastname, nickname, company) VALUES (?, ?, ?, ?, ?)", t.Id, m.Firstname, m.Lastname, m.Nickname, m.Company); err != nil {
|
||||
return err
|
||||
|
@ -65,7 +65,7 @@ func (t Team) GainMember(m Member) error {
|
|||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (m Member) Update() (int64, error) {
|
||||
func (m *Member) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE team_members SET firstname = ?, lastname = ?, nickname = ?, company = ? WHERE id_member = ?", m.Firstname, m.Lastname, m.Nickname, m.Company, m.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -76,7 +76,7 @@ func (m Member) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the member from the database.
|
||||
func (m Member) Delete() (int64, error) {
|
||||
func (m *Member) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM team_members WHERE id_member = ?", m.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -87,7 +87,7 @@ func (m Member) Delete() (int64, error) {
|
|||
}
|
||||
|
||||
// ClearMembers deletes members in the team.
|
||||
func (t Team) ClearMembers() (int64, error) {
|
||||
func (t *Team) ClearMembers() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM team_members WHERE id_team = ?", t.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
|
73
libfic/qa.go
73
libfic/qa.go
|
@ -19,13 +19,14 @@ type QAQuery struct {
|
|||
}
|
||||
|
||||
// GetQAQuery retrieves the query with the given identifier.
|
||||
func GetQAQuery(id int64) (q QAQuery, err error) {
|
||||
func GetQAQuery(id int64) (q *QAQuery, err error) {
|
||||
q = &QAQuery{}
|
||||
err = DBQueryRow("SELECT id_qa, id_exercice, id_team, authuser, creation, state, subject, solved, closed FROM exercices_qa WHERE id_qa = ?", id).Scan(&q.Id, &q.IdExercice, &q.IdTeam, &q.User, &q.Creation, &q.State, &q.Subject, &q.Solved, &q.Closed)
|
||||
return
|
||||
}
|
||||
|
||||
// GetQAQueries returns a list of all QAQuery registered in the database.
|
||||
func GetQAQueries() (res []QAQuery, err error) {
|
||||
func GetQAQueries() (res []*QAQuery, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_qa, id_exercice, id_team, authuser, creation, state, subject, solved, closed FROM exercices_qa"); err != nil {
|
||||
return
|
||||
|
@ -33,7 +34,7 @@ func GetQAQueries() (res []QAQuery, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var q QAQuery
|
||||
q := &QAQuery{}
|
||||
if err = rows.Scan(&q.Id, &q.IdExercice, &q.IdTeam, &q.User, &q.Creation, &q.State, &q.Subject, &q.Solved, &q.Closed); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -45,7 +46,7 @@ func GetQAQueries() (res []QAQuery, err error) {
|
|||
}
|
||||
|
||||
// GetQAQueries returns a list of all QAQuery registered for the Exercice.
|
||||
func (e Exercice) GetQAQueries() (res []QAQuery, err error) {
|
||||
func (e *Exercice) GetQAQueries() (res []*QAQuery, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_qa, id_exercice, id_team, authuser, creation, state, subject, solved, closed FROM exercices_qa WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -53,7 +54,7 @@ func (e Exercice) GetQAQueries() (res []QAQuery, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var q QAQuery
|
||||
q := &QAQuery{}
|
||||
if err = rows.Scan(&q.Id, &q.IdExercice, &q.IdTeam, &q.User, &q.Creation, &q.State, &q.Subject, &q.Solved, &q.Closed); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ func (e Exercice) GetQAQueries() (res []QAQuery, err error) {
|
|||
}
|
||||
|
||||
// GetQAQueries returns a list of all QAQuery registered for the Exercice.
|
||||
func (t Team) GetQAQueries() (res []QAQuery, err error) {
|
||||
func (t *Team) GetQAQueries() (res []*QAQuery, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_qa, id_exercice, id_team, authuser, creation, state, subject, solved, closed FROM exercices_qa WHERE id_team = ?", t.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -73,7 +74,7 @@ func (t Team) GetQAQueries() (res []QAQuery, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var q QAQuery
|
||||
q := &QAQuery{}
|
||||
if err = rows.Scan(&q.Id, &q.IdExercice, &q.IdTeam, &q.User, &q.Creation, &q.State, &q.Subject, &q.Solved, &q.Closed); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -85,24 +86,25 @@ func (t Team) GetQAQueries() (res []QAQuery, err error) {
|
|||
}
|
||||
|
||||
// GetQAQuery retrieves the query with the given identifier.
|
||||
func (e Exercice) GetQAQuery(id int64) (q QAQuery, err error) {
|
||||
func (e *Exercice) GetQAQuery(id int64) (q *QAQuery, err error) {
|
||||
q = &QAQuery{}
|
||||
err = DBQueryRow("SELECT id_qa, id_exercice, id_team, authuser, creation, state, subject, solved, closed FROM exercices_qa WHERE id_qa = ? AND id_exercice = ?", id, e.Id).Scan(&q.Id, &q.IdExercice, &q.IdTeam, &q.User, &q.Creation, &q.State, &q.Subject, &q.Solved, &q.Closed)
|
||||
return
|
||||
}
|
||||
|
||||
// NewQAQuery creates and fills a new struct QAQuery and registers it into the database.
|
||||
func (e Exercice) NewQAQuery(subject string, teamId *int64, user string, state string) (QAQuery, error) {
|
||||
func (e *Exercice) NewQAQuery(subject string, teamId *int64, user string, state string) (*QAQuery, error) {
|
||||
if res, err := DBExec("INSERT INTO exercices_qa (id_exercice, id_team, authuser, creation, state, subject) VALUES (?, ?, ?, ?, ?, ?)", e.Id, teamId, user, time.Now(), state, subject); err != nil {
|
||||
return QAQuery{}, err
|
||||
return nil, err
|
||||
} else if qid, err := res.LastInsertId(); err != nil {
|
||||
return QAQuery{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return QAQuery{qid, e.Id, teamId, user, time.Now(), state, subject, nil, nil}, nil
|
||||
return &QAQuery{qid, e.Id, teamId, user, time.Now(), state, subject, nil, nil}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (q QAQuery) Update() (int64, error) {
|
||||
func (q *QAQuery) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE exercices_qa SET subject = ?, id_team = ?, authuser = ?, id_exercice = ?, creation = ?, state = ?, solved = ?, closed = ? WHERE id_qa = ?", q.Subject, q.IdTeam, q.User, q.IdExercice, q.Creation, q.State, q.Solved, q.Closed, q.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -113,7 +115,7 @@ func (q QAQuery) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the query from the database.
|
||||
func (q QAQuery) Delete() (int64, error) {
|
||||
func (q *QAQuery) Delete() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM qa_comments WHERE id_qa = ?", q.Id); err != nil {
|
||||
return 0, err
|
||||
} else if res, err := DBExec("DELETE FROM exercices_qa WHERE id_qa = ?", q.Id); err != nil {
|
||||
|
@ -146,7 +148,7 @@ type QAComment struct {
|
|||
}
|
||||
|
||||
// GetComments returns a list of all descriptions stored in the database for the QAQuery.
|
||||
func (q QAQuery) GetComments() (res []QAComment, err error) {
|
||||
func (q *QAQuery) GetComments() (res []*QAComment, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_comment, id_team, authuser, date, content FROM qa_comments WHERE id_qa = ?", q.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -154,7 +156,7 @@ func (q QAQuery) GetComments() (res []QAComment, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var c QAComment
|
||||
c := &QAComment{}
|
||||
if err = rows.Scan(&c.Id, &c.IdTeam, &c.User, &c.Date, &c.Content); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -166,24 +168,25 @@ func (q QAQuery) GetComments() (res []QAComment, err error) {
|
|||
}
|
||||
|
||||
// GetComment returns the comment stored in the database for the QAQuery.
|
||||
func (q QAQuery) GetComment(id int64) (c QAComment, err error) {
|
||||
func (q *QAQuery) GetComment(id int64) (c *QAComment, err error) {
|
||||
c = &QAComment{}
|
||||
err = DBQueryRow("SELECT id_comment, id_team, authuser, date, content FROM qa_comments WHERE id_comment = ? AND id_qa = ?", id, q.Id).Scan(&c.Id, &c.IdTeam, &c.User, &c.Date, &c.Content)
|
||||
return
|
||||
}
|
||||
|
||||
// AddComment append in the database a new description; then returns the corresponding structure.
|
||||
func (q QAQuery) AddComment(content string, teamId *int64, user string) (QAComment, error) {
|
||||
func (q *QAQuery) AddComment(content string, teamId *int64, user string) (*QAComment, error) {
|
||||
if res, err := DBExec("INSERT INTO qa_comments (id_qa, id_team, authuser, date, content) VALUES (?, ?, ?, ?, ?)", q.Id, teamId, user, time.Now(), content); err != nil {
|
||||
return QAComment{}, err
|
||||
return nil, err
|
||||
} else if cid, err := res.LastInsertId(); err != nil {
|
||||
return QAComment{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return QAComment{cid, teamId, user, time.Now(), content}, nil
|
||||
return &QAComment{cid, teamId, user, time.Now(), content}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database
|
||||
func (c QAComment) Update() (int64, error) {
|
||||
func (c *QAComment) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE qa_comments SET id_team = ?, authuser = ?, date = ?, content = ? WHERE id_comment = ?", c.IdTeam, c.User, c.Date, c.Content, c.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -194,7 +197,7 @@ func (c QAComment) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the comment in the database.
|
||||
func (c QAComment) Delete() (int64, error) {
|
||||
func (c *QAComment) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM qa_comments WHERE id_comment = ?", c.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -210,7 +213,7 @@ type QATodo struct {
|
|||
IdExercice int64 `json:"id_exercice"`
|
||||
}
|
||||
|
||||
func (t Team) GetQATodo() (res []QATodo, err error) {
|
||||
func (t *Team) GetQATodo() (res []*QATodo, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_todo, id_exercice FROM teams_qa_todo WHERE id_team = ?", t.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -218,7 +221,7 @@ func (t Team) GetQATodo() (res []QATodo, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var t QATodo
|
||||
t := &QATodo{}
|
||||
if err = rows.Scan(&t.Id, &t.IdExercice); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -229,19 +232,19 @@ func (t Team) GetQATodo() (res []QATodo, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (t Team) NewQATodo(idExercice int64) (QATodo, error) {
|
||||
func (t *Team) NewQATodo(idExercice int64) (*QATodo, error) {
|
||||
if res, err := DBExec("INSERT INTO teams_qa_todo (id_team, id_exercice) VALUES (?, ?)", t.Id, idExercice); err != nil {
|
||||
return QATodo{}, err
|
||||
return nil, err
|
||||
} else if tid, err := res.LastInsertId(); err != nil {
|
||||
return QATodo{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return QATodo{tid, t.Id, idExercice}, nil
|
||||
return &QATodo{tid, t.Id, idExercice}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// QAView
|
||||
|
||||
func (t Team) GetQAView() (res []QATodo, err error) {
|
||||
func (t *Team) GetQAView() (res []*QATodo, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_view, id_exercice FROM teams_qa_view WHERE id_team = ?", t.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -249,7 +252,7 @@ func (t Team) GetQAView() (res []QATodo, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var t QATodo
|
||||
t := &QATodo{}
|
||||
if err = rows.Scan(&t.Id, &t.IdExercice); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -260,12 +263,12 @@ func (t Team) GetQAView() (res []QATodo, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (t Team) NewQAView(idExercice int64) (QATodo, error) {
|
||||
func (t *Team) NewQAView(idExercice int64) (*QATodo, error) {
|
||||
if res, err := DBExec("INSERT INTO teams_qa_view (id_team, id_exercice) VALUES (?, ?)", t.Id, idExercice); err != nil {
|
||||
return QATodo{}, err
|
||||
return nil, err
|
||||
} else if tid, err := res.LastInsertId(); err != nil {
|
||||
return QATodo{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return QATodo{tid, t.Id, idExercice}, nil
|
||||
return &QATodo{tid, t.Id, idExercice}, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ func rankQuery(whereTeam string) string {
|
|||
) A ` + whereTeam + ` GROUP BY A.id_team ORDER BY score DESC, time ASC`
|
||||
}
|
||||
|
||||
func (t Team) ScoreGrid() (grid []map[string]interface{}, err error) {
|
||||
func (t *Team) ScoreGrid() (grid []map[string]interface{}, err error) {
|
||||
q := "SELECT G.reason, G.id_exercice, G.time, G.points, G.coeff FROM (" + teamptsQuery() + ") AS G WHERE G.id_team = ? AND G.points != 0"
|
||||
if rows, err := DBQuery(q, t.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -80,7 +80,7 @@ func (t Team) ScoreGrid() (grid []map[string]interface{}, err error) {
|
|||
// Points
|
||||
|
||||
// EstimateGain calculates the amount of point the Team has (or could have, if not already solved) won.
|
||||
func (e Exercice) EstimateGain(t Team, solved bool) (float64, error) {
|
||||
func (e *Exercice) EstimateGain(t *Team, solved bool) (float64, error) {
|
||||
var pts float64
|
||||
err := DBQueryRow("SELECT SUM(A.points * A.coeff) AS score FROM ("+exoptsQuery("WHERE S.id_team = ? AND S.id_exercice = ?")+") A GROUP BY id_team", t.Id, e.Id, t.Id, e.Id).Scan(&pts)
|
||||
if solved {
|
||||
|
@ -95,7 +95,7 @@ func (e Exercice) EstimateGain(t Team, solved bool) (float64, error) {
|
|||
}
|
||||
|
||||
// GetPoints returns the score for the Team.
|
||||
func (t Team) GetPoints() (float64, error) {
|
||||
func (t *Team) GetPoints() (float64, error) {
|
||||
var tid *int64
|
||||
var nb *float64
|
||||
var tzzz *time.Time
|
||||
|
|
|
@ -24,15 +24,15 @@ type Team struct {
|
|||
Password *string `json:"password"`
|
||||
}
|
||||
|
||||
func getTeams(filter string) ([]Team, error) {
|
||||
func getTeams(filter string) ([]*Team, error) {
|
||||
if rows, err := DBQuery("SELECT id_team, name, color, active, external_id, password FROM teams " + filter); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var teams = make([]Team, 0)
|
||||
var teams []*Team
|
||||
for rows.Next() {
|
||||
var t Team
|
||||
t := &Team{}
|
||||
if err := rows.Scan(&t.Id, &t.Name, &t.Color, &t.Active, &t.ExternalId, &t.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -47,18 +47,18 @@ func getTeams(filter string) ([]Team, error) {
|
|||
}
|
||||
|
||||
// GetTeams returns a list of registered Team from the database.
|
||||
func GetTeams() ([]Team, error) {
|
||||
func GetTeams() ([]*Team, error) {
|
||||
return getTeams("")
|
||||
}
|
||||
|
||||
// GetActiveTeams returns a list of registered Team from the database, limited to team to generate.
|
||||
func GetActiveTeams() ([]Team, error) {
|
||||
func GetActiveTeams() ([]*Team, error) {
|
||||
return getTeams("WHERE active = 1")
|
||||
}
|
||||
|
||||
// GetTeam retrieves a Team from its identifier.
|
||||
func GetTeam(id int64) (Team, error) {
|
||||
var t Team
|
||||
func GetTeam(id int64) (*Team, error) {
|
||||
t := &Team{}
|
||||
if err := DBQueryRow("SELECT id_team, name, color, active, external_id, password FROM teams WHERE id_team = ?", id).Scan(&t.Id, &t.Name, &t.Color, &t.Active, &t.ExternalId, &t.Password); err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ func GetTeam(id int64) (Team, error) {
|
|||
}
|
||||
|
||||
// GetTeamBySerial retrieves a Team from one of its associated certificates.
|
||||
func GetTeamBySerial(serial int64) (Team, error) {
|
||||
var t Team
|
||||
func GetTeamBySerial(serial int64) (*Team, error) {
|
||||
t := &Team{}
|
||||
if err := DBQueryRow("SELECT T.id_team, T.name, T.color, T.active, T.external_id, T.password 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, &t.Active, &t.ExternalId, &t.Password); err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
@ -77,18 +77,18 @@ func GetTeamBySerial(serial int64) (Team, error) {
|
|||
}
|
||||
|
||||
// CreateTeam creates and fills a new struct Team and registers it into the database.
|
||||
func CreateTeam(name string, color uint32, externalId string) (Team, error) {
|
||||
func CreateTeam(name string, color uint32, externalId string) (*Team, error) {
|
||||
if res, err := DBExec("INSERT INTO teams (name, color, external_id) VALUES (?, ?, ?)", name, color, externalId); err != nil {
|
||||
return Team{}, err
|
||||
return nil, err
|
||||
} else if tid, err := res.LastInsertId(); err != nil {
|
||||
return Team{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return Team{tid, name, color, true, "", nil}, nil
|
||||
return &Team{tid, name, color, true, "", nil}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (t Team) Update() (int64, error) {
|
||||
func (t *Team) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE teams SET name = ?, color = ?, active = ?, external_id = ?, password = ? WHERE id_team = ?", t.Name, t.Color, t.Active, t.ExternalId, t.Password, t.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -99,7 +99,7 @@ func (t Team) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the challenge from the database
|
||||
func (t Team) Delete() (int64, error) {
|
||||
func (t *Team) Delete() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM team_members WHERE id_team = ?", t.Id); err != nil {
|
||||
return 0, err
|
||||
} else if res, err := DBExec("DELETE FROM teams WHERE id_team = ?", t.Id); err != nil {
|
||||
|
@ -112,7 +112,7 @@ func (t Team) Delete() (int64, error) {
|
|||
}
|
||||
|
||||
// HasAccess checks if the Team has access to the given challenge.
|
||||
func (t Team) HasAccess(e Exercice) bool {
|
||||
func (t *Team) HasAccess(e *Exercice) bool {
|
||||
if UnlockedChallengeDepth < 0 {
|
||||
return true
|
||||
}
|
||||
|
@ -123,11 +123,11 @@ func (t Team) HasAccess(e Exercice) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
ed := Exercice{}
|
||||
ed := &Exercice{}
|
||||
ed.Id = *e.Depend
|
||||
s, _ := t.HasSolved(ed)
|
||||
if s {
|
||||
return s
|
||||
s := t.HasSolved(ed)
|
||||
if s != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
// Prepare next iteration
|
||||
|
@ -141,7 +141,7 @@ func (t Team) HasAccess(e Exercice) bool {
|
|||
}
|
||||
|
||||
// CanDownload checks if the Team has access to the given file.
|
||||
func (t Team) CanDownload(f EFile) bool {
|
||||
func (t *Team) CanDownload(f *EFile) bool {
|
||||
if deps, err := f.GetDepends(); err != nil {
|
||||
log.Printf("Unable to retrieve file dependencies: %s\n", err)
|
||||
return false
|
||||
|
@ -160,7 +160,7 @@ 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 {
|
||||
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
|
||||
|
@ -179,7 +179,7 @@ func (t Team) CanSeeHint(h EHint) bool {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
log.Printf("Unable to retrieve flag dependencies: %s\n", err)
|
||||
return false
|
||||
|
@ -198,7 +198,7 @@ func (t Team) CanSeeFlag(k Flag) bool {
|
|||
}
|
||||
|
||||
// NbTry retrieves the number of attempts made by the Team to the given challenge.
|
||||
func NbTry(t *Team, e Exercice) int {
|
||||
func NbTry(t *Team, e *Exercice) int {
|
||||
tries_table := "exercice_tries"
|
||||
if SubmissionUniqueness {
|
||||
tries_table = "exercice_distinct_tries"
|
||||
|
@ -220,33 +220,33 @@ func NbTry(t *Team, e Exercice) int {
|
|||
}
|
||||
|
||||
// HasHint checks if the Team has revealed the given Hint.
|
||||
func (t Team) HasHint(h EHint) bool {
|
||||
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 {
|
||||
func (t *Team) OpenHint(h *EHint) error {
|
||||
_, err := DBExec("INSERT INTO team_hints (id_team, id_hint, time, coefficient) VALUES (?, ?, ?, ?)", t.Id, h.Id, time.Now(), math.Max(HintCoefficient, 0.0))
|
||||
return err
|
||||
}
|
||||
|
||||
// SeeChoices checks if the Team has revealed the given choices.
|
||||
func (t Team) SeeChoices(k FlagKey) bool {
|
||||
func (t *Team) SeeChoices(k *FlagKey) bool {
|
||||
var tm *time.Time
|
||||
DBQueryRow("SELECT MIN(time) FROM team_wchoices WHERE id_team = ? AND id_flag = ?", t.Id, k.Id).Scan(&tm)
|
||||
return tm != nil
|
||||
}
|
||||
|
||||
// DisplayChoices registers to the database that the Team has now revealed.
|
||||
func (t Team) DisplayChoices(k FlagKey) error {
|
||||
func (t *Team) DisplayChoices(k *FlagKey) error {
|
||||
_, err := DBExec("INSERT INTO team_wchoices (id_team, id_flag, time, coefficient) VALUES (?, ?, ?, ?)", t.Id, k.Id, time.Now(), math.Max(WChoiceCoefficient, 0.0))
|
||||
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) {
|
||||
func (t *Team) CountTries(e *Exercice) (int64, *time.Time) {
|
||||
table := "exercice_tries"
|
||||
if CountOnlyNotGoodTries {
|
||||
table += "_notgood"
|
||||
|
@ -257,22 +257,22 @@ func (t Team) CountTries(e Exercice) (int64, time.Time) {
|
|||
if DBQueryRow("SELECT COUNT(id_exercice), MAX(time) FROM "+table+" WHERE id_team = ? AND id_exercice = ?", t.Id, e.Id).Scan(&nb, &tm); tm == nil {
|
||||
if CountOnlyNotGoodTries {
|
||||
if DBQueryRow("SELECT COUNT(id_exercice), MAX(time) FROM exercice_tries WHERE id_team = ? AND id_exercice = ?", t.Id, e.Id).Scan(&nb, &tm); tm == nil {
|
||||
return 0, time.Unix(0, 0)
|
||||
return 0, nil
|
||||
} else {
|
||||
return 0, *tm
|
||||
return 0, tm
|
||||
}
|
||||
}
|
||||
return 0, time.Unix(0, 0)
|
||||
return 0, nil
|
||||
} else if nb == nil {
|
||||
return 0, *tm
|
||||
return 0, tm
|
||||
} else {
|
||||
return *nb, *tm
|
||||
return *nb, tm
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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 {
|
||||
return 0
|
||||
|
@ -283,17 +283,13 @@ func (t Team) LastTryDist(e Exercice) 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)
|
||||
} else {
|
||||
return true, *tm
|
||||
}
|
||||
func (t *Team) HasSolved(e *Exercice) (tm *time.Time) {
|
||||
DBQueryRow("SELECT MIN(time) FROM exercice_solved WHERE id_team = ? AND id_exercice = ?", t.Id, e.Id).Scan(&tm)
|
||||
return
|
||||
}
|
||||
|
||||
// GetSolvedRank returns the number of teams that solved the challenge before the Team.
|
||||
func (t Team) GetSolvedRank(e Exercice) (nb int64, err error) {
|
||||
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); errr != nil {
|
||||
return nb, errr
|
||||
} else {
|
||||
|
@ -315,10 +311,10 @@ func (t Team) GetSolvedRank(e Exercice) (nb int64, err error) {
|
|||
}
|
||||
|
||||
// HasPartiallySolved checks if the Team already has unlocked the given flag and returns the validation's timestamp.
|
||||
func (t Team) HasPartiallySolved(f Flag) (tm *time.Time) {
|
||||
if k, ok := f.(FlagKey); ok {
|
||||
func (t *Team) HasPartiallySolved(f Flag) (tm *time.Time) {
|
||||
if k, ok := f.(*FlagKey); ok {
|
||||
DBQueryRow("SELECT MIN(time) FROM flag_found WHERE id_team = ? AND id_flag = ?", t.Id, k.Id).Scan(&tm)
|
||||
} else if m, ok := f.(MCQ); ok {
|
||||
} else if m, ok := f.(*MCQ); ok {
|
||||
DBQueryRow("SELECT MIN(time) FROM mcq_found WHERE id_team = ? AND id_mcq = ?", t.Id, m.Id).Scan(&tm)
|
||||
} else {
|
||||
log.Fatal("Unknown flag type")
|
||||
|
@ -327,7 +323,7 @@ func (t Team) HasPartiallySolved(f Flag) (tm *time.Time) {
|
|||
}
|
||||
|
||||
// HashedPassword compute a bcrypt version of the team's password.
|
||||
func (t Team) HashedPassword() (string, error) {
|
||||
func (t *Team) HashedPassword() (string, error) {
|
||||
if t.Password == nil {
|
||||
if passwd, err := GeneratePassword(); err != nil {
|
||||
return "", err
|
||||
|
|
|
@ -6,17 +6,17 @@ import (
|
|||
|
||||
// exportedTeam is a structure representing a Team, as exposed to players.
|
||||
type ExportedTeam struct {
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
Rank int `json:"rank"`
|
||||
Points float64 `json:"score"`
|
||||
Members []Member `json:"members,omitempty"`
|
||||
ExternalId string `json:"external_id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
Rank int `json:"rank"`
|
||||
Points float64 `json:"score"`
|
||||
Members []*Member `json:"members,omitempty"`
|
||||
ExternalId string `json:"external_id,omitempty"`
|
||||
}
|
||||
|
||||
// Exportedteam creates the structure to respond as teams.json.
|
||||
func ExportTeams(includeMembers bool) (ret map[string]ExportedTeam, err error) {
|
||||
var teams []Team
|
||||
var teams []*Team
|
||||
var rank map[int64]int
|
||||
|
||||
if teams, err = GetTeams(); err != nil {
|
||||
|
@ -27,7 +27,7 @@ func ExportTeams(includeMembers bool) (ret map[string]ExportedTeam, err error) {
|
|||
ret = map[string]ExportedTeam{}
|
||||
for _, team := range teams {
|
||||
points, _ := team.GetPoints()
|
||||
var members []Member
|
||||
var members []*Member
|
||||
if includeMembers {
|
||||
if members, err = team.GetMembers(); err != nil {
|
||||
return
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
// GetHistory aggregates all sources of events or actions for a Team
|
||||
func (t Team) GetHistory() ([]map[string]interface{}, error) {
|
||||
func (t *Team) GetHistory() ([]map[string]interface{}, error) {
|
||||
hist := make([]map[string]interface{}, 0)
|
||||
|
||||
if rows, err := DBQuery(`SELECT id_team, "tries" AS kind, time, 0, E.id_exercice, E.title, NULL, NULL FROM exercice_tries T INNER JOIN exercices E ON E.id_exercice = T.id_exercice WHERE id_team = ? UNION
|
||||
|
@ -55,7 +55,7 @@ func (t Team) GetHistory() ([]map[string]interface{}, error) {
|
|||
}
|
||||
|
||||
// UpdateHistoryCoeff updates the coefficient for a given entry.
|
||||
func (t Team) UpdateHistoryCoeff(kind string, h time.Time, givenId int64, newCoeff float32) (interface{}, error) {
|
||||
func (t *Team) UpdateHistoryCoeff(kind string, h time.Time, givenId int64, newCoeff float32) (interface{}, error) {
|
||||
if kind == "hint" {
|
||||
if res, err := DBExec("UPDATE team_hints SET coefficient = ? WHERE id_team = ? AND time = ? AND id_hint = ?", newCoeff, t.Id, h, givenId); err != nil {
|
||||
return 0, err
|
||||
|
@ -86,7 +86,7 @@ func (t Team) UpdateHistoryCoeff(kind string, h time.Time, givenId int64, newCoe
|
|||
}
|
||||
|
||||
// DelHistoryItem removes from the database an entry from the history.
|
||||
func (t Team) DelHistoryItem(kind string, h time.Time, primary *int64, secondary *int64) (interface{}, error) {
|
||||
func (t *Team) DelHistoryItem(kind string, h time.Time, primary *int64, secondary *int64) (interface{}, error) {
|
||||
if kind == "tries" && primary != nil {
|
||||
if res, err := DBExec("DELETE FROM exercice_tries WHERE id_team = ? AND time = ? AND id_exercice = ?", t.Id, h, *primary); err != nil {
|
||||
return 0, err
|
||||
|
|
|
@ -79,7 +79,7 @@ type myTeam struct {
|
|||
Id int64 `json:"team_id"`
|
||||
Name string `json:"name"`
|
||||
Points int64 `json:"score"`
|
||||
Members []Member `json:"members"`
|
||||
Members []*Member `json:"members,omitempty"`
|
||||
Exercices map[string]myTeamExercice `json:"exercices"`
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,6 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||
if members, err := t.GetMembers(); err == nil {
|
||||
ret.Members = members
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Fill exercices, only if the challenge is started
|
||||
|
@ -130,16 +129,16 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||
exercice.TotalTries = e.TriedCount()
|
||||
exercice.Gain = int(float64(e.Gain) * e.Coefficient * GlobalScoreCoefficient)
|
||||
} else {
|
||||
solved, stime := t.HasSolved(e)
|
||||
exercice.SolvedTime = &stime
|
||||
stime := t.HasSolved(e)
|
||||
exercice.SolvedTime = stime
|
||||
|
||||
if solved {
|
||||
if stime != nil {
|
||||
exercice.SolvedRank, _ = t.GetSolvedRank(e)
|
||||
exercice.Finished = e.Finished
|
||||
exercice.Tries, _ = t.CountTries(e)
|
||||
} else {
|
||||
exercice.Tries, stime = t.CountTries(e)
|
||||
exercice.SolvedTime = &stime
|
||||
exercice.SolvedTime = stime
|
||||
if exercice.Tries > 0 {
|
||||
exercice.SolveDist = t.LastTryDist(e)
|
||||
}
|
||||
|
@ -149,7 +148,7 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||
exercice.SolvedTime = nil
|
||||
}
|
||||
|
||||
if gain, err := e.EstimateGain(*t, solved); err == nil {
|
||||
if gain, err := e.EstimateGain(t, stime != nil); err == nil {
|
||||
exercice.Gain = int(gain * GlobalScoreCoefficient)
|
||||
} else {
|
||||
log.Println("ERROR during gain estimation:", err)
|
||||
|
|
|
@ -71,7 +71,7 @@ func GetTeamsStats(t *Team) (interface{}, error) {
|
|||
sLvl.Total += 1
|
||||
|
||||
if t != nil {
|
||||
if b, _ := t.HasSolved(exercice); b {
|
||||
if b := t.HasSolved(exercice); b != nil {
|
||||
solved += 1
|
||||
sLvl.Solved += 1
|
||||
}
|
||||
|
|
|
@ -18,20 +18,20 @@ type Theme struct {
|
|||
}
|
||||
|
||||
// CmpTheme returns true if given Themes are identicals.
|
||||
func CmpTheme(t1 Theme, t2 Theme) bool {
|
||||
return !(t1.Name != t2.Name || t1.URLId != t2.URLId || t1.Path != t2.Path || t1.Authors != t2.Authors || t1.Intro != t2.Intro || t1.Headline != t2.Headline || t1.Image != t2.Image || t1.PartnerImage != t2.PartnerImage || t1.PartnerLink != t2.PartnerLink || t1.PartnerText != t2.PartnerText)
|
||||
func CmpTheme(t1 *Theme, t2 *Theme) bool {
|
||||
return t1 != nil && t2 != nil && !(t1.Name != t2.Name || t1.URLId != t2.URLId || t1.Path != t2.Path || t1.Authors != t2.Authors || t1.Intro != t2.Intro || t1.Headline != t2.Headline || t1.Image != t2.Image || t1.PartnerImage != t2.PartnerImage || t1.PartnerLink != t2.PartnerLink || t1.PartnerText != t2.PartnerText)
|
||||
}
|
||||
|
||||
// GetThemes returns a list of registered Themes from the database.
|
||||
func GetThemes() ([]Theme, error) {
|
||||
func GetThemes() ([]*Theme, error) {
|
||||
if rows, err := DBQuery("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_href, partner_text FROM themes"); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var themes = make([]Theme, 0)
|
||||
var themes []*Theme
|
||||
for rows.Next() {
|
||||
var t Theme
|
||||
t := &Theme{}
|
||||
if err := rows.Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerLink, &t.PartnerText); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ func GetThemes() ([]Theme, error) {
|
|||
}
|
||||
|
||||
// GetTheme retrieves a Theme from its identifier.
|
||||
func GetTheme(id int64) (Theme, error) {
|
||||
var t Theme
|
||||
func GetTheme(id int64) (*Theme, error) {
|
||||
t := &Theme{}
|
||||
if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_href, partner_text FROM themes WHERE id_theme=?", id).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerLink, &t.PartnerText); err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ func GetTheme(id int64) (Theme, error) {
|
|||
}
|
||||
|
||||
// GetThemeByName retrieves a Theme from its title
|
||||
func GetThemeByName(name string) (Theme, error) {
|
||||
var t Theme
|
||||
func GetThemeByName(name string) (*Theme, error) {
|
||||
t := &Theme{}
|
||||
if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_text FROM themes WHERE name=?", name).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerText); err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
@ -66,21 +66,19 @@ func GetThemeByName(name string) (Theme, error) {
|
|||
}
|
||||
|
||||
// GetThemeByPath retrieves a Theme from its dirname
|
||||
func GetThemeByPath(dirname string) (Theme, error) {
|
||||
var t Theme
|
||||
if err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_href, partner_text FROM themes WHERE path=?", dirname).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerLink, &t.PartnerText); err != nil {
|
||||
return t, err
|
||||
}
|
||||
func GetThemeByPath(dirname string) (*Theme, error) {
|
||||
t := &Theme{}
|
||||
err := DBQueryRow("SELECT id_theme, name, url_id, path, authors, intro, headline, image, partner_img, partner_href, partner_text FROM themes WHERE path=?", dirname).Scan(&t.Id, &t.Name, &t.URLId, &t.Path, &t.Authors, &t.Intro, &t.Headline, &t.Image, &t.PartnerImage, &t.PartnerLink, &t.PartnerText)
|
||||
|
||||
return t, nil
|
||||
return t, err
|
||||
}
|
||||
|
||||
// CreateTheme creates and fills a new struct Theme and registers it into the database.
|
||||
func CreateTheme(theme Theme) (Theme, error) {
|
||||
func CreateTheme(theme *Theme) (*Theme, error) {
|
||||
if res, err := DBExec("INSERT INTO themes (name, url_id, authors, path, intro, headline, image, partner_img, partner_href, partner_text) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", theme.Name, theme.URLId, theme.Authors, theme.Path, theme.Intro, theme.Headline, theme.Image, theme.PartnerImage, theme.PartnerLink, theme.PartnerText); err != nil {
|
||||
return Theme{}, err
|
||||
return nil, err
|
||||
} else if theme.Id, err = res.LastInsertId(); err != nil {
|
||||
return Theme{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return theme, nil
|
||||
}
|
||||
|
@ -97,7 +95,7 @@ func (t *Theme) FixURLId() bool {
|
|||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (t Theme) Update() (int64, error) {
|
||||
func (t *Theme) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE themes SET name = ?, url_id = ?, authors = ?, path = ?, intro = ?, headline = ?, image = ?, partner_img = ?, partner_href = ?, partner_text = ? WHERE id_theme = ?", t.Name, t.URLId, t.Authors, t.Path, t.Intro, t.Headline, t.Image, t.PartnerImage, t.PartnerLink, t.PartnerText, t.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -108,7 +106,7 @@ func (t Theme) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the theme from the database.
|
||||
func (t Theme) Delete() (int64, error) {
|
||||
func (t *Theme) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM themes WHERE id_theme = ?", t.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -118,7 +116,7 @@ func (t Theme) Delete() (int64, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t Theme) deleteFunc(f func(Exercice) (int64, error)) (int64, error) {
|
||||
func (t *Theme) deleteFunc(f func(*Exercice) (int64, error)) (int64, error) {
|
||||
exercices, err := t.GetExercices()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
@ -135,8 +133,8 @@ func (t Theme) deleteFunc(f func(Exercice) (int64, error)) (int64, error) {
|
|||
}
|
||||
|
||||
// DeleteCascade the theme from the database, including inner content but not player content.
|
||||
func (t Theme) DeleteCascade() (int64, error) {
|
||||
_, err := t.deleteFunc(func(e Exercice) (int64, error) {
|
||||
func (t *Theme) DeleteCascade() (int64, error) {
|
||||
_, err := t.deleteFunc(func(e *Exercice) (int64, error) {
|
||||
return e.DeleteCascade()
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -147,8 +145,8 @@ func (t Theme) DeleteCascade() (int64, error) {
|
|||
}
|
||||
|
||||
// DeleteCascadePlayer delete player content related to this theme.
|
||||
func (t Theme) DeleteCascadePlayer() (int64, error) {
|
||||
_, err := t.deleteFunc(func(e Exercice) (int64, error) {
|
||||
func (t *Theme) DeleteCascadePlayer() (int64, error) {
|
||||
_, err := t.deleteFunc(func(e *Exercice) (int64, error) {
|
||||
return e.DeleteCascadePlayer()
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -159,8 +157,8 @@ func (t Theme) DeleteCascadePlayer() (int64, error) {
|
|||
}
|
||||
|
||||
// DeleteDeep the theme from the database, including player content.
|
||||
func (t Theme) DeleteDeep() (int64, error) {
|
||||
_, err := t.deleteFunc(func(e Exercice) (int64, error) {
|
||||
func (t *Theme) DeleteDeep() (int64, error) {
|
||||
_, err := t.deleteFunc(func(e *Exercice) (int64, error) {
|
||||
return e.DeleteDeep()
|
||||
})
|
||||
if err != nil {
|
||||
|
|
105
libfic/todo.go
105
libfic/todo.go
|
@ -20,13 +20,14 @@ type Claim struct {
|
|||
}
|
||||
|
||||
// GetClaim retrieves the claim with the given identifier.
|
||||
func GetClaim(id int64) (c Claim, err error) {
|
||||
func GetClaim(id int64) (c *Claim, err error) {
|
||||
c = &Claim{}
|
||||
err = DBQueryRow("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_claim = ?", id).Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority)
|
||||
return
|
||||
}
|
||||
|
||||
// GetClaims returns a list of all Claim registered in the database.
|
||||
func GetClaims() (res []Claim, err error) {
|
||||
func GetClaims() (res []*Claim, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims"); err != nil {
|
||||
return
|
||||
|
@ -34,7 +35,7 @@ func GetClaims() (res []Claim, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var c Claim
|
||||
c := &Claim{}
|
||||
if err = rows.Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -46,13 +47,14 @@ func GetClaims() (res []Claim, err error) {
|
|||
}
|
||||
|
||||
// GetClaim retrieves the claim with the given identifier and registered for the given Team.
|
||||
func (t Team) GetClaim(id int64) (c Claim, err error) {
|
||||
func (t *Team) GetClaim(id int64) (c *Claim, err error) {
|
||||
c = &Claim{}
|
||||
err = DBQueryRow("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_claim = ? AND id_team = ?", id, t.Id).Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority)
|
||||
return
|
||||
}
|
||||
|
||||
// GetClaims returns a list of all Claim registered for the Team.
|
||||
func (t Team) GetClaims() (res []Claim, err error) {
|
||||
func (t *Team) GetClaims() (res []*Claim, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_team = ?", t.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -60,7 +62,7 @@ func (t Team) GetClaims() (res []Claim, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var c Claim
|
||||
c := &Claim{}
|
||||
if err = rows.Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -72,7 +74,7 @@ func (t Team) GetClaims() (res []Claim, err error) {
|
|||
}
|
||||
|
||||
// GetExercices returns a list of all Claim registered for the Exercice.
|
||||
func (e Exercice) GetClaims() (res []Claim, err error) {
|
||||
func (e *Exercice) GetClaims() (res []*Claim, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -80,7 +82,7 @@ func (e Exercice) GetClaims() (res []Claim, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var c Claim
|
||||
c := &Claim{}
|
||||
if err = rows.Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -92,7 +94,7 @@ func (e Exercice) GetClaims() (res []Claim, err error) {
|
|||
}
|
||||
|
||||
// NewClaim creates and fills a new struct Claim and registers it into the database.
|
||||
func NewClaim(subject string, team *Team, exercice *Exercice, assignee *ClaimAssignee, priority string) (Claim, error) {
|
||||
func NewClaim(subject string, team *Team, exercice *Exercice, assignee *ClaimAssignee, priority string) (*Claim, error) {
|
||||
var tid *int64
|
||||
if team == nil {
|
||||
tid = nil
|
||||
|
@ -115,48 +117,48 @@ func NewClaim(subject string, team *Team, exercice *Exercice, assignee *ClaimAss
|
|||
}
|
||||
|
||||
if res, err := DBExec("INSERT INTO claims (subject, id_team, id_exercice, id_assignee, creation, state, priority) VALUES (?, ?, ?, ?, ?, ?, ?)", subject, tid, eid, aid, time.Now(), "new", priority); err != nil {
|
||||
return Claim{}, err
|
||||
return nil, err
|
||||
} else if cid, err := res.LastInsertId(); err != nil {
|
||||
return Claim{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return Claim{cid, subject, tid, eid, aid, time.Now(), "new", priority}, nil
|
||||
return &Claim{cid, subject, tid, eid, aid, time.Now(), "new", priority}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetTeam returns the Team linked to the issue, if any.
|
||||
func (c Claim) GetTeam() (*Team, error) {
|
||||
func (c *Claim) GetTeam() (*Team, error) {
|
||||
if c.IdTeam == nil {
|
||||
return nil, nil
|
||||
} else if t, err := GetTeam(*c.IdTeam); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &t, nil
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetTeam defines the Team that is linked to this issue.
|
||||
func (c Claim) SetTeam(t Team) {
|
||||
func (c *Claim) SetTeam(t Team) {
|
||||
c.IdTeam = &t.Id
|
||||
}
|
||||
|
||||
// GetExercice returns the Exercice linked to the issue, if any.
|
||||
func (c Claim) GetExercice() (*Exercice, error) {
|
||||
func (c *Claim) GetExercice() (*Exercice, error) {
|
||||
if c.IdExercice == nil {
|
||||
return nil, nil
|
||||
} else if e, err := GetExercice(*c.IdExercice); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &e, nil
|
||||
return e, nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetExercice defines the Exercice that is linked to this issue.
|
||||
func (c Claim) SetExercice(e Exercice) {
|
||||
func (c *Claim) SetExercice(e Exercice) {
|
||||
c.IdExercice = &e.Id
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (c Claim) Update() (int64, error) {
|
||||
func (c *Claim) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE claims SET subject = ?, id_team = ?, id_exercice = ?, id_assignee = ?, creation = ?, state = ?, priority = ? WHERE id_claim = ?", c.Subject, c.IdTeam, c.IdExercice, c.IdAssignee, c.Creation, c.State, c.Priority, c.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -167,7 +169,7 @@ func (c Claim) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the issue from the database.
|
||||
func (c Claim) Delete() (int64, error) {
|
||||
func (c *Claim) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM claims WHERE id_claim = ?", c.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -202,13 +204,13 @@ type ClaimDescription struct {
|
|||
}
|
||||
|
||||
// GetLastUpdate returns the date of the latest message written for the given Claim.
|
||||
func (c Claim) GetLastUpdate() (res *time.Time, err error) {
|
||||
func (c *Claim) GetLastUpdate() (res *time.Time, err error) {
|
||||
err = DBQueryRow("SELECT MAX(date) FROM claim_descriptions WHERE id_claim = ? GROUP BY id_claim", c.Id).Scan(&res)
|
||||
return
|
||||
}
|
||||
|
||||
// GetDescriptions returns a list of all descriptions stored in the database for the Claim.
|
||||
func (c Claim) GetDescriptions() (res []ClaimDescription, err error) {
|
||||
func (c *Claim) GetDescriptions() (res []*ClaimDescription, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_description, id_assignee, content, date, publish FROM claim_descriptions WHERE id_claim = ?", c.Id); err != nil {
|
||||
return nil, err
|
||||
|
@ -216,7 +218,7 @@ func (c Claim) GetDescriptions() (res []ClaimDescription, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var d ClaimDescription
|
||||
d := &ClaimDescription{}
|
||||
if err = rows.Scan(&d.Id, &d.IdAssignee, &d.Content, &d.Date, &d.Publish); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -228,24 +230,30 @@ func (c Claim) GetDescriptions() (res []ClaimDescription, err error) {
|
|||
}
|
||||
|
||||
// AddDescription append in the database a new description; then returns the corresponding structure.
|
||||
func (c Claim) AddDescription(content string, assignee ClaimAssignee, publish bool) (ClaimDescription, error) {
|
||||
if res, err := DBExec("INSERT INTO claim_descriptions (id_claim, id_assignee, content, date, publish) VALUES (?, ?, ?, ?, ?)", c.Id, assignee.Id, content, time.Now(), publish); err != nil {
|
||||
return ClaimDescription{}, err
|
||||
func (c *Claim) AddDescription(content string, assignee *ClaimAssignee, publish bool) (*ClaimDescription, error) {
|
||||
var assignee_id *int64
|
||||
if assignee != nil {
|
||||
assignee_id = &assignee.Id
|
||||
}
|
||||
|
||||
if res, err := DBExec("INSERT INTO claim_descriptions (id_claim, id_assignee, content, date, publish) VALUES (?, ?, ?, ?, ?)", c.Id, assignee_id, content, time.Now(), publish); err != nil {
|
||||
return nil, err
|
||||
} else if did, err := res.LastInsertId(); err != nil {
|
||||
return ClaimDescription{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return ClaimDescription{did, assignee.Id, content, time.Now(), publish}, nil
|
||||
return &ClaimDescription{did, assignee.Id, content, time.Now(), publish}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetAssignee retrieves an assignee from its identifier.
|
||||
func (d ClaimDescription) GetAssignee() (a ClaimAssignee, err error) {
|
||||
func (d *ClaimDescription) GetAssignee() (a *ClaimAssignee, err error) {
|
||||
a = &ClaimAssignee{}
|
||||
err = DBQueryRow("SELECT id_assignee, name FROM claim_assignees WHERE id_assignee = ?", d.IdAssignee).Scan(&a.Id, &a.Name)
|
||||
return
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database
|
||||
func (d ClaimDescription) Update() (int64, error) {
|
||||
func (d *ClaimDescription) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE claim_descriptions SET id_assignee = ?, content = ?, date = ?, publish = ? WHERE id_description = ?", d.IdAssignee, d.Content, d.Date, d.Publish, d.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -256,7 +264,7 @@ func (d ClaimDescription) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the description in the database.
|
||||
func (d ClaimDescription) Delete() (int64, error) {
|
||||
func (d *ClaimDescription) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM claim_descriptions WHERE id_description = ?", d.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -273,13 +281,14 @@ type ClaimAssignee struct {
|
|||
}
|
||||
|
||||
// GetAssignee retrieves an assignee from its identifier.
|
||||
func GetAssignee(id int64) (a ClaimAssignee, err error) {
|
||||
func GetAssignee(id int64) (a *ClaimAssignee, err error) {
|
||||
a = &ClaimAssignee{}
|
||||
err = DBQueryRow("SELECT id_assignee, name FROM claim_assignees WHERE id_assignee = ?", id).Scan(&a.Id, &a.Name)
|
||||
return
|
||||
}
|
||||
|
||||
// GetAssignees returns a list of all assignees found in the database.
|
||||
func GetAssignees() (res []ClaimAssignee, err error) {
|
||||
func GetAssignees() (res []*ClaimAssignee, err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = DBQuery("SELECT id_assignee, name FROM claim_assignees"); err != nil {
|
||||
return
|
||||
|
@ -287,7 +296,7 @@ func GetAssignees() (res []ClaimAssignee, err error) {
|
|||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var a ClaimAssignee
|
||||
a := &ClaimAssignee{}
|
||||
if err = rows.Scan(&a.Id, &a.Name); err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -299,18 +308,18 @@ func GetAssignees() (res []ClaimAssignee, err error) {
|
|||
}
|
||||
|
||||
// NewClaimAssignee creates and fills a new struct ClaimAssignee and registers it into the database.
|
||||
func NewClaimAssignee(name string) (ClaimAssignee, error) {
|
||||
func NewClaimAssignee(name string) (*ClaimAssignee, error) {
|
||||
if res, err := DBExec("INSERT INTO claim_assignees (name) VALUES (?)", name); err != nil {
|
||||
return ClaimAssignee{}, err
|
||||
return nil, err
|
||||
} else if aid, err := res.LastInsertId(); err != nil {
|
||||
return ClaimAssignee{}, err
|
||||
return nil, err
|
||||
} else {
|
||||
return ClaimAssignee{aid, name}, nil
|
||||
return &ClaimAssignee{aid, name}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database
|
||||
func (a ClaimAssignee) Update() (int64, error) {
|
||||
func (a *ClaimAssignee) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE claim_assignees SET name = ? WHERE id_assignee = ?", a.Name, a.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -321,7 +330,7 @@ func (a ClaimAssignee) Update() (int64, error) {
|
|||
}
|
||||
|
||||
// Delete the assignee in the database.
|
||||
func (a ClaimAssignee) Delete() (int64, error) {
|
||||
func (a *ClaimAssignee) Delete() (int64, error) {
|
||||
if res, err := DBExec("DELETE FROM claim_assignees WHERE id_assignee = ?", a.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
|
@ -343,18 +352,18 @@ func ClearAssignees() (int64, error) {
|
|||
}
|
||||
|
||||
// GetAssignee returns the assignee assigned to the claim.
|
||||
func (c Claim) GetAssignee() (*ClaimAssignee, error) {
|
||||
func (c *Claim) GetAssignee() (*ClaimAssignee, error) {
|
||||
if c.IdAssignee == nil {
|
||||
return nil, nil
|
||||
} else if a, err := GetAssignee(*c.IdAssignee); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &a, nil
|
||||
return a, nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetAssignee defines the assignee that'll handle the claim.
|
||||
func (c Claim) SetAssignee(a ClaimAssignee) {
|
||||
func (c *Claim) SetAssignee(a ClaimAssignee) {
|
||||
c.IdAssignee = &a.Id
|
||||
}
|
||||
|
||||
|
@ -375,8 +384,8 @@ type teamIssueFile struct {
|
|||
Texts []teamIssueText `json:"texts"`
|
||||
}
|
||||
|
||||
func (t Team) MyIssueFile() (ret []teamIssueFile, err error) {
|
||||
var claims []Claim
|
||||
func (t *Team) MyIssueFile() (ret []teamIssueFile, err error) {
|
||||
var claims []*Claim
|
||||
if claims, err = t.GetClaims(); err == nil {
|
||||
for _, claim := range claims {
|
||||
var exercice *string = nil
|
||||
|
@ -395,7 +404,7 @@ func (t Team) MyIssueFile() (ret []teamIssueFile, err error) {
|
|||
}
|
||||
|
||||
if descriptions, err := claim.GetDescriptions(); err != nil {
|
||||
return nil, fmt.Errorf("Error occurs during description retrieval (cid=%d): %w", claim.Id, err)
|
||||
return nil, fmt.Errorf("error occurs during description retrieval (cid=%d): %w", claim.Id, err)
|
||||
} else {
|
||||
tif := teamIssueFile{
|
||||
Id: claim.Id,
|
||||
|
@ -411,7 +420,7 @@ func (t Team) MyIssueFile() (ret []teamIssueFile, err error) {
|
|||
for _, description := range descriptions {
|
||||
if description.Publish {
|
||||
if people, err := description.GetAssignee(); err != nil {
|
||||
return nil, fmt.Errorf("Error ocurs during assignee retrieval (aid=%d): %w", description.IdAssignee, err)
|
||||
return nil, fmt.Errorf("error ocurs during assignee retrieval (aid=%d): %w", description.IdAssignee, err)
|
||||
} else {
|
||||
tif.Texts = append(tif.Texts, teamIssueText{
|
||||
Content: description.Content,
|
||||
|
@ -426,7 +435,7 @@ func (t Team) MyIssueFile() (ret []teamIssueFile, err error) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("Error occurs during claim retrieval: %w", err)
|
||||
err = fmt.Errorf("error occurs during claim retrieval: %w", err)
|
||||
}
|
||||
|
||||
return
|
||||
|
|
Reference in a new issue