challenge-sync-airbus: Do job
This commit is contained in:
parent
18b8f0f722
commit
3344e05e0d
6 changed files with 256 additions and 65 deletions
|
|
@ -1,11 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"srs.epita.fr/fic-server/libfic"
|
||||
)
|
||||
|
|
@ -15,55 +15,144 @@ var (
|
|||
)
|
||||
|
||||
type Walker struct {
|
||||
LastSync map[AirbusUserId]time.Time
|
||||
Exercices AirbusExercicesBindings
|
||||
Teams map[string]fic.ExportedTeam
|
||||
API AirbusAPI
|
||||
Coeff float64
|
||||
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) {
|
||||
mypath := filepath.Join(filepath.Dir(path), "my.json")
|
||||
if _, err := os.Stat(mypath); !os.IsNotExist(err) {
|
||||
// Read team ID
|
||||
fdmy, err := os.Open(mypath)
|
||||
if err != nil {
|
||||
log.Println("Unable to open my.json:", err)
|
||||
return
|
||||
}
|
||||
defer fdmy.Close()
|
||||
teamid := filepath.Base(filepath.Dir(path))
|
||||
|
||||
teammy, err := fic.ReadMyJSON(fdmy)
|
||||
if err != nil {
|
||||
log.Println("Unable to parse my.json:", err)
|
||||
return
|
||||
}
|
||||
|
||||
airbusTeamId := NewAirbusUserId(w.Teams[fmt.Sprintf("%d", teammy.Id)].ExternalId)
|
||||
|
||||
// Treat score grid
|
||||
/*err = w.TreatScoreGrid(path, airbusTeamId)
|
||||
if err != nil {
|
||||
log.Println("Unable to treat score grid:", err)
|
||||
return
|
||||
}*/
|
||||
|
||||
// Balance scores
|
||||
err = w.BalanceScore(int64(float64(teammy.Points)*w.Coeff), airbusTeamId)
|
||||
if err != nil {
|
||||
log.Println("Unable to balance score:", err)
|
||||
return
|
||||
}
|
||||
if _, ok := w.TeamBindings[teamid]; ok {
|
||||
w.TreatScoreGrid(path, w.TeamBindings[teamid])
|
||||
}
|
||||
}
|
||||
|
||||
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" {
|
||||
w.treat(path)
|
||||
}
|
||||
|
||||
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-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)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -71,7 +160,7 @@ func (w *Walker) WalkScore(path string, d os.DirEntry, err error) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (w *Walker) TreatScoreGrid(path string, airbusTeamId AirbusUserId) error {
|
||||
func (w *Walker) TreatScoreGrid(path string, airbusTeam *AirbusTeam) error {
|
||||
// Read score grid
|
||||
fdscores, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
@ -85,30 +174,35 @@ func (w *Walker) TreatScoreGrid(path string, airbusTeamId AirbusUserId) error {
|
|||
}
|
||||
|
||||
// Found all new entries
|
||||
maxts := w.LastSync[airbusTeamId]
|
||||
maxts := &TSValue{}
|
||||
if ts, ok := w.LastSync[airbusTeam.Name]; ok {
|
||||
maxts = ts
|
||||
}
|
||||
for _, row := range teamscores {
|
||||
if row.Time.After(maxts) {
|
||||
maxts = row.Time
|
||||
if row.Time.After(maxts.Time) {
|
||||
maxts.Time = row.Time
|
||||
}
|
||||
if row.Time.After(w.LastSync[airbusTeamId]) {
|
||||
if row.Time.After(w.LastSync[airbusTeam.Name].Time) {
|
||||
if !noValidateChallenge && row.Reason == "Validation" {
|
||||
err = w.API.ValidateChallengeFromUser(airbusTeamId, w.Exercices[row.IdExercice])
|
||||
err = w.API.ValidateChallengeFromUser(airbusTeam, w.Exercices[row.IdExercice])
|
||||
} else {
|
||||
err = w.API.AwardUser(airbusTeamId, int64(row.Points*row.Coeff*w.Coeff), row.Reason)
|
||||
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[airbusTeamId] = maxts
|
||||
w.LastSync[airbusTeam.Name] = maxts
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *Walker) BalanceScore(score int64, airbusTeamId AirbusUserId) error {
|
||||
func (w *Walker) BalanceScore(score int64, airbusTeam *AirbusTeam) error {
|
||||
// Read current score on other platform
|
||||
stats, err := w.API.GetCurrentStats()
|
||||
if err != nil {
|
||||
|
|
@ -120,9 +214,9 @@ func (w *Walker) BalanceScore(score int64, airbusTeamId AirbusUserId) error {
|
|||
return fmt.Errorf("session not found")
|
||||
}
|
||||
|
||||
other_team := my_session.GetTeam(AirbusUUID(airbusTeamId))
|
||||
other_team := my_session.GetTeam(AirbusUUID(airbusTeam.Name))
|
||||
if other_team == nil {
|
||||
return fmt.Errorf("team %q not found", airbusTeamId)
|
||||
return fmt.Errorf("team %q not found", airbusTeam.Name)
|
||||
}
|
||||
|
||||
other_score := other_team.Score
|
||||
|
|
@ -130,7 +224,7 @@ func (w *Walker) BalanceScore(score int64, airbusTeamId AirbusUserId) error {
|
|||
// Send diff to the platform
|
||||
if other_score != score {
|
||||
diff := score - other_score
|
||||
return w.API.AwardUser(airbusTeamId, diff, "Équilibrage")
|
||||
return w.API.AwardUser(airbusTeam, diff, "Équilibrage")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
Reference in a new issue