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 (
2016-10-13 17:52:13 +00:00
"database/sql"
2016-03-06 17:57:08 +00:00
"fmt"
2016-01-18 18:40:11 +00:00
"time"
)
2016-01-07 17:43:02 +00:00
2016-12-04 17:58:53 +00:00
var UnlockedChallenges bool
2016-01-07 17:43:02 +00:00
type Team struct {
2016-04-28 14:11:19 +00:00
Id int64 ` json:"id" `
InitialName string ` json:"initialName" `
Name string ` json:"name" `
Color uint32 ` json:"color" `
2016-01-07 17:43:02 +00:00
}
func GetTeams ( ) ( [ ] Team , error ) {
2016-04-28 14:11:19 +00:00
if rows , err := DBQuery ( "SELECT id_team, initial_name, 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
2016-04-28 14:11:19 +00:00
if err := rows . Scan ( & t . Id , & t . InitialName , & 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
}
}
func GetTeam ( id int ) ( Team , error ) {
var t Team
2016-04-28 14:11:19 +00:00
if err := DBQueryRow ( "SELECT id_team, initial_name, name, color FROM teams WHERE id_team = ?" , id ) . Scan ( & t . Id , & t . InitialName , & t . Name , & t . Color ) ; err != nil {
return t , err
}
return t , nil
}
func GetTeamByInitialName ( initialName string ) ( Team , error ) {
var t Team
if err := DBQueryRow ( "SELECT id_team, initial_name, name, color FROM teams WHERE initial_name = ?" , initialName ) . Scan ( & t . Id , & t . InitialName , & t . Name , & t . Color ) ; err != nil {
2016-01-07 17:43:02 +00:00
return t , err
}
return t , nil
}
2016-02-26 00:29:01 +00:00
func CreateTeam ( name string , color uint32 ) ( Team , error ) {
2016-04-28 14:11:19 +00:00
if res , err := DBExec ( "INSERT INTO teams (initial_name, name, color) VALUES (?, ?, ?)" , name , 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 {
2016-04-28 14:11:19 +00:00
return Team { tid , name , name , color } , nil
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
}
}
func ( t Team ) Delete ( ) ( int64 , error ) {
2016-01-13 00:20:21 +00:00
if res , err := DBExec ( "DELETE FROM team_members WHERE id_team = ?; DELETE FROM teams WHERE id_team = ?" , t . Id , 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
2016-01-21 00:36:58 +00:00
func ( t Team ) GetPoints ( ) ( int64 , error ) {
var nb * int64
err := DBQueryRow ( "SELECT SUM(E.gain) FROM exercice_solved S INNER JOIN exercices E ON E.id_exercice = S.id_exercice WHERE id_team = ?" , t . Id ) . Scan ( & nb )
if nb != nil {
return * nb , err
} else {
return 0 , err
}
}
2016-01-21 04:00:15 +00:00
func GetRank ( ) ( map [ int64 ] int , error ) {
2016-01-24 13:32:36 +00:00
if rows , err := DBQuery ( "SELECT id_team, SUM(E.gain) AS score, MAX(S.time) FROM exercice_solved S INNER JOIN exercices E ON E.id_exercice = S.id_exercice GROUP BY id_team HAVING score > 0 ORDER BY score DESC, time ASC" ) ; err != nil {
2016-01-21 04:00:15 +00:00
return nil , err
} else {
defer rows . Close ( )
rank := map [ int64 ] int { }
nteam := 0
for rows . Next ( ) {
nteam += 1
var tid int64
var score int64
2016-01-23 13:12:03 +00:00
var tzzz time . Time
2016-01-21 04:00:15 +00:00
if err := rows . Scan ( & tid , & score , & tzzz ) ; err != nil {
return nil , err
}
rank [ tid ] = nteam
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return rank , nil
}
}
2016-01-25 02:06:58 +00:00
func GetTryRank ( ) ( [ ] int64 , error ) {
if rows , err := DBQuery ( "SELECT id_team, COUNT(*) AS score FROM exercice_tries GROUP BY id_team HAVING score > 0 ORDER BY score DESC" ) ; err != nil {
return nil , err
} else {
defer rows . Close ( )
rank := make ( [ ] int64 , 0 )
for rows . Next ( ) {
var tid int64
var score int64
if err := rows . Scan ( & tid , & score ) ; err != nil {
return nil , err
}
rank = append ( rank , tid )
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return rank , nil
}
}
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
2016-01-18 18:40:11 +00:00
s , _ , _ := t . HasSolved ( ed )
return s
2016-01-18 17:24:46 +00:00
}
}
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
}
}
func GetTries ( t * Team , e * Exercice ) ( [ ] time . Time , error ) {
var rows * sql . Rows
var err error
if t == nil {
if e == nil {
rows , err = DBQuery ( "SELECT time FROM exercice_tries ORDER BY time ASC" )
} else {
rows , err = DBQuery ( "SELECT time FROM exercice_tries WHERE id_exercice = ? ORDER BY time ASC" , e . Id )
}
} else {
if e == nil {
rows , err = DBQuery ( "SELECT time FROM exercice_tries WHERE id_team = ? ORDER BY time ASC" , t . Id )
} else {
rows , err = DBQuery ( "SELECT time FROM exercice_tries WHERE id_team = ? AND id_exercice = ? ORDER BY time ASC" , t . Id , e . Id )
}
}
if err != nil {
return nil , err
} else {
defer rows . Close ( )
times := make ( [ ] time . Time , 0 )
for rows . Next ( ) {
var tm time . Time
if err := rows . Scan ( & tm ) ; err != nil {
return nil , err
}
times = append ( times , tm )
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return times , nil
}
}
2016-01-18 18:40:11 +00:00
func ( t Team ) HasSolved ( e Exercice ) ( bool , time . Time , int64 ) {
2016-01-23 12:16:31 +00:00
var nb * int64
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 {
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 {
2016-01-21 04:33:40 +00:00
return false , time . Unix ( 0 , 0 ) , 0
2016-01-23 12:16:31 +00:00
} else if nb == nil {
return false , * tm , 0
2016-01-21 04:33:40 +00:00
} else {
2016-01-23 12:16:31 +00:00
return false , * tm , * nb
2016-01-21 04:33:40 +00:00
}
2016-01-23 12:16:31 +00:00
} else if DBQueryRow ( "SELECT COUNT(id_exercice) FROM exercice_solved WHERE id_exercice = ? AND time < ?" , e . Id , tm ) . Scan ( & nb ) ; nb == nil {
return true , * tm , 0
2016-01-15 11:57:35 +00:00
} else {
2016-01-23 12:16:31 +00:00
return true , * tm , * nb + 1
2016-01-15 11:57:35 +00:00
}
}
2016-03-06 17:57:08 +00:00
2016-10-13 17:52:40 +00:00
func IsSolved ( e Exercice ) ( int , time . Time ) {
var nb * int
var tm * time . Time
if DBQueryRow ( "SELECT COUNT(id_exercice), MIN(time) FROM exercice_solved WHERE id_exercice = ?" , e . Id ) . Scan ( & nb , & tm ) ; nb == nil || tm == nil {
return 0 , time . Time { }
} else {
return * nb , * tm
}
}
type statLine struct {
Tip string ` json:"tip" `
Total int ` json:"total" `
Solved int ` json:"solved" `
Tried int ` json:"tried" `
Tries int ` json:"tries" `
}
type teamStats struct {
Levels [ ] statLine ` json:"levels" `
Themes [ ] statLine ` json:"themes" `
}
func ( s * teamStats ) GetLevel ( level int ) * statLine {
level -= 1
for len ( s . Levels ) <= level {
s . Levels = append ( s . Levels , statLine {
fmt . Sprintf ( "Level %d" , ( len ( s . Levels ) + 1 ) ) ,
0 ,
0 ,
0 ,
0 ,
} )
}
return & s . Levels [ level ]
}
func ( t Team ) GetStats ( ) ( interface { } , error ) {
return GetTeamsStats ( & t )
}
func GetTeamsStats ( t * Team ) ( interface { } , error ) {
stat := teamStats { }
if themes , err := GetThemes ( ) ; err != nil {
return nil , err
} else {
for _ , theme := range themes {
total := 0
solved := 0
tried := 0
tries := 0
if exercices , err := theme . GetExercices ( ) ; err != nil {
return nil , err
} else {
for _ , exercice := range exercices {
var lvl int
if lvl , err = exercice . GetLevel ( ) ; err != nil {
return nil , err
}
sLvl := stat . GetLevel ( lvl )
total += 1
sLvl . Total += 1
if t != nil {
if b , _ , _ := t . HasSolved ( exercice ) ; b {
solved += 1
sLvl . Solved += 1
}
} else {
if n , _ := IsSolved ( exercice ) ; n > 0 {
solved += 1
sLvl . Solved += 1
}
}
try := NbTry ( t , exercice )
if try > 0 {
tried += 1
tries += try
sLvl . Tried += 1
sLvl . Tries += try
}
}
}
stat . Themes = append ( stat . Themes , statLine {
theme . Name ,
total ,
solved ,
tried ,
tries ,
} )
}
return stat , nil
}
}
2016-03-06 17:57:08 +00:00
type exportedTeam struct {
Name string ` json:"name" `
Color string ` json:"color" `
Rank int ` json:"rank" `
Points int64 ` json:"score" `
}
func ExportTeams ( ) ( interface { } , error ) {
if teams , err := GetTeams ( ) ; err != nil {
return nil , err
} else if rank , err := GetRank ( ) ; err != nil {
return nil , err
} else {
ret := map [ string ] exportedTeam { }
for _ , team := range teams {
if points , err := team . GetPoints ( ) ; err != nil {
return nil , err
} else {
ret [ fmt . Sprintf ( "%d" , team . Id ) ] = exportedTeam {
team . Name ,
fmt . Sprintf ( "#%x" , team . Color ) ,
rank [ team . Id ] ,
points ,
}
}
}
return ret , nil
}
}