214 lines
4.4 KiB
Go
214 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"srs.epita.fr/fic-server/libfic"
|
|
)
|
|
|
|
var (
|
|
noValidateChallenge bool
|
|
)
|
|
|
|
type Walker struct {
|
|
LastSync map[string]*TSValue
|
|
Exercices AirbusExercicesBindings
|
|
Teams map[string]fic.ExportedTeam
|
|
RevTeams map[string]string
|
|
TeamBindings map[string]*AirbusTeam
|
|
API AirbusAPI
|
|
Coeff float64
|
|
}
|
|
|
|
func (w *Walker) fetchTeams() error {
|
|
teams, err := w.API.GetTeams()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
w.RevTeams = map[string]string{}
|
|
w.TeamBindings = map[string]*AirbusTeam{}
|
|
|
|
for tid, team := range w.Teams {
|
|
for _, t := range teams {
|
|
if team.Name == t.Name || team.ExternalId == t.Name {
|
|
w.TeamBindings[tid] = &t
|
|
break
|
|
}
|
|
}
|
|
|
|
if _, ok := w.TeamBindings[tid]; !ok {
|
|
log.Printf("Team binding not found: %s - %s", tid, team.Name)
|
|
}
|
|
|
|
w.RevTeams[team.Name] = tid
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *Walker) treat(path string) error {
|
|
teamid := filepath.Base(filepath.Dir(path))
|
|
|
|
if _, ok := w.TeamBindings[teamid]; ok {
|
|
return w.TreatScoreGrid(path, w.TeamBindings[teamid])
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *Walker) LoadScoreState(path string) (int64, error) {
|
|
mypath := filepath.Join(filepath.Dir(path), "airbus.json")
|
|
if _, err := os.Stat(mypath); os.IsNotExist(err) {
|
|
fd, err := os.Create(mypath)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer fd.Close()
|
|
|
|
fd.Write([]byte("0"))
|
|
return 0, nil
|
|
}
|
|
|
|
fd, err := os.Open(mypath)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer fd.Close()
|
|
|
|
var ret int64
|
|
|
|
jdec := json.NewDecoder(fd)
|
|
if err := jdec.Decode(&ret); err != nil {
|
|
return 0, fmt.Errorf("an error occurs when trying to decode airbus.json: %w", err)
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (w *Walker) LoadScoreGrid(path string) ([]fic.ScoreGridRow, error) {
|
|
fd, err := os.Open(filepath.Join(filepath.Dir(path), "scores.json"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer fd.Close()
|
|
|
|
var ret []fic.ScoreGridRow
|
|
|
|
jdec := json.NewDecoder(fd)
|
|
if err := jdec.Decode(&ret); err != nil {
|
|
return nil, fmt.Errorf("an error occurs when trying to decode airbus.json: %w", err)
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (w *Walker) WalkScoreSync(path string, d os.DirEntry, err error) error {
|
|
if filepath.Base(path) == "scores.json" {
|
|
return w.treat(path)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *Walker) loadMyFile(path string) (*fic.MyTeam, error) {
|
|
fd, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer fd.Close()
|
|
|
|
var ret fic.MyTeam
|
|
|
|
jdec := json.NewDecoder(fd)
|
|
if err := jdec.Decode(&ret); err != nil {
|
|
return nil, fmt.Errorf("an error occurs when trying to decode airbus.json: %w", err)
|
|
}
|
|
|
|
return &ret, nil
|
|
}
|
|
|
|
func (w *Walker) WalkScore(path string, d os.DirEntry, err error) error {
|
|
if filepath.Base(path) == "scores.json" {
|
|
go w.treat(path)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (w *Walker) TreatScoreGrid(path string, airbusTeam *AirbusTeam) error {
|
|
// Read score grid
|
|
fdscores, err := os.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer fdscores.Close()
|
|
|
|
teamscores, err := fic.ReadScoreGrid(fdscores)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Found all new entries
|
|
maxts := &TSValue{
|
|
Time: time.Time{},
|
|
}
|
|
if ts, ok := w.LastSync[airbusTeam.Name]; ok {
|
|
maxts = ts
|
|
}
|
|
for _, row := range teamscores {
|
|
if row.Time.After(maxts.Time) {
|
|
maxts.Time = row.Time
|
|
}
|
|
if ts, ok := w.LastSync[airbusTeam.Name]; !ok || row.Time.After(ts.Time) {
|
|
if !noValidateChallenge && row.Reason == "Validation" {
|
|
err = w.API.ValidateChallengeFromUser(airbusTeam, w.Exercices[row.IdExercice])
|
|
} else {
|
|
err = w.API.AwardUser(airbusTeam, int64(row.Points*row.Coeff*w.Coeff), row.Reason)
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
maxts.Score += int64(row.Points * row.Coeff * w.Coeff)
|
|
}
|
|
}
|
|
|
|
w.LastSync[airbusTeam.Name] = maxts
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *Walker) BalanceScores() error {
|
|
for team, ts := range w.LastSync {
|
|
team_id, ok := w.RevTeams[team]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
myteam, err := w.loadMyFile(filepath.Join(TeamsDir, team_id, "my.json"))
|
|
if err != nil {
|
|
return fmt.Errorf("Unable to open %s/my.json: %w", team_id, err)
|
|
}
|
|
|
|
airbusTeam := w.TeamBindings[fmt.Sprintf("%d", myteam.Id)]
|
|
|
|
if ts.Score != myteam.Points*int64(w.Coeff) {
|
|
err := w.API.AwardUser(airbusTeam, myteam.Points*int64(w.Coeff)-ts.Score, "Équilibrage")
|
|
if err != nil {
|
|
return fmt.Errorf("Unable to open %s/my.json: %w", team, err)
|
|
}
|
|
|
|
w.LastSync[airbusTeam.Name].Score = myteam.Points * int64(w.Coeff)
|
|
w.LastSync[airbusTeam.Name].Time = time.Now()
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|