Split team.go into multiple files

This commit is contained in:
nemunaire 2016-12-27 21:12:17 +01:00
parent c64f1969d9
commit 5c377f63de
4 changed files with 249 additions and 222 deletions

109
libfic/stats.go Normal file
View File

@ -0,0 +1,109 @@
package fic
import (
"database/sql"
"time"
)
// Points
func (t Team) GetPoints() (int64, error) {
var nb *int64
err := DBQueryRow("SELECT SUM(E.gain) AS gains 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
}
}
func GetRank() (map[int64]int, error) {
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 {
return nil, err
} else {
defer rows.Close()
rank := map[int64]int{}
nteam := 0
for rows.Next() {
nteam += 1
var tid int64
var score int64
var tzzz time.Time
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
}
}
// Tries
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
}
}
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
}
}

View File

@ -1,8 +1,6 @@
package fic
import (
"database/sql"
"fmt"
"time"
)
@ -15,6 +13,8 @@ type Team struct {
Color uint32 `json:"color"`
}
// Access functions
func GetTeams() ([]Team, error) {
if rows, err := DBQuery("SELECT id_team, initial_name, name, color FROM teams"); err != nil {
return nil, err
@ -55,6 +55,9 @@ func GetTeamByInitialName(initialName string) (Team, error) {
return t, nil
}
// CRUD method
func CreateTeam(name string, color uint32) (Team, error) {
if res, err := DBExec("INSERT INTO teams (initial_name, name, color) VALUES (?, ?, ?)", name, name, color); err != nil {
return Team{}, err
@ -85,64 +88,8 @@ func (t Team) Delete() (int64, error) {
}
}
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
}
}
func GetRank() (map[int64]int, error) {
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 {
return nil, err
} else {
defer rows.Close()
rank := map[int64]int{}
nteam := 0
for rows.Next() {
nteam += 1
var tid int64
var score int64
var tzzz time.Time
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
}
}
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
}
}
// Exercice related functions
func (t Team) HasAccess(e Exercice) bool {
if e.Depend == nil || UnlockedChallenges {
@ -171,45 +118,6 @@ func NbTry(t *Team, e Exercice) int {
}
}
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
}
}
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)
@ -254,127 +162,3 @@ func (t Team) HasPartiallySolved(k Key) (*time.Time) {
DBQueryRow("SELECT MIN(time) FROM key_found WHERE id_team = ? AND id_key = ?", t.Id, k.Id).Scan(&tm)
return 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
}
}
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
}
}

36
libfic/team_export.go Normal file
View File

@ -0,0 +1,36 @@
package fic
import (
"fmt"
)
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
}
}

98
libfic/team_stats.go Normal file
View File

@ -0,0 +1,98 @@
package fic
import (
"fmt"
)
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
}
}