2016-01-13 19:25:25 +00:00
package fic
2016-01-07 17:43:02 +00:00
2016-01-18 18:40:11 +00:00
import (
"time"
)
2016-01-07 17:43:02 +00:00
2018-03-09 18:07:08 +00:00
// UnlockedChallenges disables dependancy requirement between challenges.
2016-12-04 17:58:53 +00:00
var UnlockedChallenges bool
2018-03-09 18:07:08 +00:00
// Team represents a group of players, come to solve our challenges.
2016-01-07 17:43:02 +00:00
type Team struct {
2016-04-28 14:11:19 +00:00
Id int64 ` json:"id" `
Name string ` json:"name" `
Color uint32 ` json:"color" `
2016-01-07 17:43:02 +00:00
}
2018-03-09 18:07:08 +00:00
// GetTeams returns a list of registered Team from the database.
2016-01-07 17:43:02 +00:00
func GetTeams ( ) ( [ ] Team , error ) {
2018-01-21 13:07:44 +00:00
if rows , err := DBQuery ( "SELECT id_team, name, color FROM teams" ) ; err != nil {
2016-01-07 17:43:02 +00:00
return nil , err
} else {
defer rows . Close ( )
var teams = make ( [ ] Team , 0 )
for rows . Next ( ) {
var t Team
2018-01-21 13:07:44 +00:00
if err := rows . Scan ( & t . Id , & t . Name , & t . Color ) ; err != nil {
2016-01-07 17:43:02 +00:00
return nil , err
}
teams = append ( teams , t )
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return teams , nil
}
}
2018-03-09 18:07:08 +00:00
// GetTeam retrieves a Team from its identifier.
2018-01-21 13:18:26 +00:00
func GetTeam ( id int64 ) ( Team , error ) {
2016-01-07 17:43:02 +00:00
var t Team
2018-01-21 13:07:44 +00:00
if err := DBQueryRow ( "SELECT id_team, name, color FROM teams WHERE id_team = ?" , id ) . Scan ( & t . Id , & t . Name , & t . Color ) ; err != nil {
2016-04-28 14:11:19 +00:00
return t , err
}
return t , nil
}
2018-03-09 18:07:08 +00:00
// GetTeamBySerial retrieves a Team from one of its associated certificates.
2018-01-21 13:07:44 +00:00
func GetTeamBySerial ( serial int64 ) ( Team , error ) {
2016-04-28 14:11:19 +00:00
var t Team
2018-01-21 13:07:44 +00:00
if err := DBQueryRow ( "SELECT T.id_team, T.name, T.color FROM certificates C INNER JOIN teams T ON T.id_team = C.id_team WHERE id_cert = ?" , serial ) . Scan ( & t . Id , & t . Name , & t . Color ) ; err != nil {
2016-01-07 17:43:02 +00:00
return t , err
}
return t , nil
}
2018-03-09 18:07:08 +00:00
// CreateTeam creates and fills a new struct Team and registers it into the database.
2016-02-26 00:29:01 +00:00
func CreateTeam ( name string , color uint32 ) ( Team , error ) {
2018-01-21 13:07:44 +00:00
if res , err := DBExec ( "INSERT INTO teams (name, color) VALUES (?, ?)" , name , color ) ; err != nil {
2016-01-07 17:43:02 +00:00
return Team { } , err
} else if tid , err := res . LastInsertId ( ) ; err != nil {
return Team { } , err
} else {
2018-01-21 13:07:44 +00:00
return Team { tid , name , color } , nil
2016-01-07 17:43:02 +00:00
}
}
2018-03-09 18:07:08 +00:00
// Update applies modifications back to the database.
2016-01-07 17:43:02 +00:00
func ( t Team ) Update ( ) ( int64 , error ) {
2016-01-20 09:14:13 +00:00
if res , err := DBExec ( "UPDATE teams SET name = ?, color = ? WHERE id_team = ?" , t . Name , t . Color , t . Id ) ; err != nil {
2016-01-07 17:43:02 +00:00
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2018-03-09 18:07:08 +00:00
// Delete the challenge from the database
2016-01-07 17:43:02 +00:00
func ( t Team ) Delete ( ) ( int64 , error ) {
2017-11-10 19:23:45 +00:00
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 {
2016-01-07 17:43:02 +00:00
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2016-01-15 11:57:35 +00:00
2018-03-09 18:07:08 +00:00
// HasAccess checks if the Team has access to the given challenge.
2016-01-18 17:24:46 +00:00
func ( t Team ) HasAccess ( e Exercice ) bool {
2016-12-04 17:58:53 +00:00
if e . Depend == nil || UnlockedChallenges {
2016-01-18 17:24:46 +00:00
return true
} else {
ed := Exercice { }
ed . Id = * e . Depend
2018-03-09 18:07:08 +00:00
s , _ := t . HasSolved ( ed )
2016-01-18 18:40:11 +00:00
return s
2016-01-18 17:24:46 +00:00
}
}
2018-03-09 18:07:08 +00:00
// NbTry retrieves the number of attempts made by the Team to the given challenge.
2016-10-13 17:52:13 +00:00
func NbTry ( t * Team , e Exercice ) int {
var cnt * int
if t != nil {
DBQueryRow ( "SELECT COUNT(*) FROM exercice_tries WHERE id_team = ? AND id_exercice = ?" , t . Id , e . Id ) . Scan ( & cnt )
} else {
DBQueryRow ( "SELECT COUNT(*) FROM exercice_tries WHERE id_exercice = ?" , e . Id ) . Scan ( & cnt )
}
if cnt == nil {
return 0
} else {
return * cnt
}
}
2018-03-09 18:07:08 +00:00
// HasHint checks if the Team has revealed the given Hint.
2016-12-04 18:15:39 +00:00
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
}
2018-03-09 18:07:08 +00:00
// OpenHint registers to the database that the Team has now revealed.
2016-12-09 10:49:29 +00:00
func ( t Team ) OpenHint ( h EHint ) ( error ) {
_ , err := DBExec ( "INSERT INTO team_hints (id_team, id_hint, time) VALUES (?, ?, ?)" , t . Id , h . Id , time . Now ( ) )
return err
}
2018-03-09 18:07:08 +00:00
// CountTries gets the amount of attempts made by the Team and retrieves the time of the latest attempt.
2017-01-16 12:09:31 +00:00
func ( t Team ) CountTries ( e Exercice ) ( int64 , time . Time ) {
var nb * int64
var tm * time . Time
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 )
} else if nb == nil {
return 0 , * tm
} else {
return * nb , * tm
}
}
2018-03-09 18:07:08 +00:00
// LastTryDist retrieves the distance to the correct answers, for the given challenge.
// The distance is the number of bad responses given in differents MCQs.
2017-12-17 01:48:02 +00:00
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
} else {
return * nb
}
}
2018-03-09 18:07:08 +00:00
// 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 ) {
2016-01-23 12:16:31 +00:00
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 {
2018-03-09 18:07:08 +00:00
return false , time . Unix ( 0 , 0 )
2016-01-15 11:57:35 +00:00
} else {
2018-03-09 18:07:08 +00:00
return true , * tm
2016-01-15 11:57:35 +00:00
}
}
2016-03-06 17:57:08 +00:00
2018-03-09 18:07:08 +00:00
// GetSolvedRank returns the number of teams that solved the challenge before the Team.
func ( t Team ) GetSolvedRank ( e Exercice ) ( nb int64 , err error ) {
if rows , errr := DBQuery ( "SELECT id_team FROM exercice_solved WHERE id_exercice = ? ORDER BY time ASC" , e . Id ) ; err != nil {
return nb , errr
2016-10-13 17:52:40 +00:00
} else {
2018-03-09 18:07:08 +00:00
for rows . Next ( ) {
var tid int64
if err = rows . Scan ( & tid ) ; err != nil {
return
}
nb += 1
if t . Id == tid {
break
}
}
return
2016-10-13 17:52:40 +00:00
}
}
2018-03-09 18:07:08 +00:00
// HasPartiallySolved checks if the Team already has unlocked the given key and returns the validation's timestamp.
func ( t Team ) HasPartiallySolved ( k Key ) ( tm * time . Time ) {
2016-12-04 18:08:46 +00:00
DBQueryRow ( "SELECT MIN(time) FROM key_found WHERE id_team = ? AND id_key = ?" , t . Id , k . Id ) . Scan ( & tm )
2018-03-09 18:07:08 +00:00
return
2016-12-04 18:08:46 +00:00
}
2017-12-16 00:16:30 +00:00
2018-03-09 18:07:08 +00:00
// HasPartiallyRespond checks if the Team already has unlocked the given MCQ and returns the validation's timestamp.
func ( t Team ) HasPartiallyRespond ( m MCQ ) ( tm * time . Time ) {
2017-12-16 00:16:30 +00:00
DBQueryRow ( "SELECT MIN(time) FROM mcq_found WHERE id_team = ? AND id_mcq = ?" , t . Id , m . Id ) . Scan ( & tm )
2018-03-09 18:07:08 +00:00
return
2017-12-16 00:16:30 +00:00
}