From 977caccc1f60e0cec8d69957b55e7152c00cde9f Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Sun, 17 Mar 2024 10:19:35 +0100 Subject: [PATCH] admin: Add ability to append element to exercice history --- admin/api/exercice.go | 21 +++++++ admin/api/settings.go | 1 + admin/static/js/app.js | 55 +++++++++++++++++- admin/static/views/exercice-flags.html | 58 ++++++++++++++++++- admin/static/views/exercice.html | 77 +++++++++++++++++++++++++- libfic/exercice_history.go | 28 ++++++++++ 6 files changed, 237 insertions(+), 3 deletions(-) diff --git a/admin/api/exercice.go b/admin/api/exercice.go index cb6822b7..9c0ce004 100644 --- a/admin/api/exercice.go +++ b/admin/api/exercice.go @@ -35,6 +35,7 @@ func declareExercicesRoutes(router *gin.RouterGroup) { apiExercicesRoutes.GET("/stats.json", getExerciceStats) apiExercicesRoutes.GET("/history.json", getExerciceHistory) + apiExercicesRoutes.PUT("/history.json", appendExerciceHistory) apiExercicesRoutes.PATCH("/history.json", updateExerciceHistory) apiExercicesRoutes.DELETE("/history.json", delExerciceHistory) @@ -476,6 +477,26 @@ type uploadedExerciceHistory struct { Coeff float32 } +func appendExerciceHistory(c *gin.Context) { + exercice := c.MustGet("exercice").(*fic.Exercice) + + var uh uploadedExerciceHistory + err := c.ShouldBindJSON(&uh) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) + return + } + + err = exercice.AppendHistoryItem(uh.IdTeam, uh.Kind, uh.Secondary) + if err != nil { + log.Println("Unable to appendExerciceHistory:", err.Error()) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during history moditication."}) + return + } + + c.JSON(http.StatusOK, uh) +} + func updateExerciceHistory(c *gin.Context) { exercice := c.MustGet("exercice").(*fic.Exercice) diff --git a/admin/api/settings.go b/admin/api/settings.go index 732240b8..d8406f8e 100644 --- a/admin/api/settings.go +++ b/admin/api/settings.go @@ -325,6 +325,7 @@ func ApplySettings(config *settings.Settings) { fic.SubmissionCostBase = config.SubmissionCostBase fic.HintCoefficient = config.HintCurCoefficient fic.WChoiceCoefficient = config.WChoiceCurCoefficient + fic.ExerciceCurrentCoefficient = config.ExerciceCurCoefficient fic.GlobalScoreCoefficient = config.GlobalScoreCoefficient fic.SubmissionCostBase = config.SubmissionCostBase fic.SubmissionUniqueness = config.SubmissionUniqueness diff --git a/admin/static/js/app.js b/admin/static/js/app.js index 176aafb3..f13646d4 100644 --- a/admin/static/js/app.js +++ b/admin/static/js/app.js @@ -1908,6 +1908,54 @@ angular.module("FICApp") }); } } + $scope.selectedTeam = ""; + $scope.validateForTeam = function() { + var flagid = $("#validationModal").data("flagid"); + if (!flagid) return; + var target = { + team_id: parseInt($("#tteam").val().replace(/number:/, '')), + kind: $("#validationModal").data("kind"), + secondary: flagid, + }; + $http({ + url: "api/exercices/" + $scope.exercice.id + "/history.json", + method: "PUT", + data: target + }).then(function(response) { + $rootScope.staticFilesNeedUpdate++; + $("#validationModal").modal('hide'); + $scope.addToast('success', 'Flag validé avec succès'); + }, function(response) { + $scope.addToast('danger', 'An error occurs when trying to validate flag for team:', response.data.errmsg); + }); + } + $scope.historyAppend = function() { + var secondary = null; + if ($("#historyEvent").val() == "hint") + secondary = parseInt($("#historySecondaryHint").val().replace(/number:/, '')); + else if ($("#historyEvent").val() == "wchoices" || $("#historyEvent").val() == "flag_found") + secondary = parseInt($("#historySecondaryFlag").val().replace(/number:/, '')); + else if ($("#historyEvent").val() == "mcq_found") + secondary = parseInt($("#historySecondaryQuiz").val().replace(/number:/, '')); + + var target = { + team_id: parseInt($("#tteam").val().replace(/number:/, '')), + kind: $("#historyEvent").val(), + secondary: secondary, + }; + $http({ + url: "api/exercices/" + $scope.exercice.id + "/history.json", + method: "PUT", + data: target + }).then(function(response) { + $rootScope.staticFilesNeedUpdate++; + $("#appendHistoryModal").modal('hide'); + $scope.addToast('success', 'Événement ajouté avec succès'); + $scope.refreshHistory(); + }, function(response) { + $scope.addToast('danger', 'An error occurs when trying to add event in history:', response.data.errmsg); + }); + } }) .controller("SubmissionsStatsController", function($scope, $http, $interval) { @@ -1983,7 +2031,12 @@ angular.module("FICApp") }) .controller("ExerciceHistoryController", function($scope, ExerciceHistory, $routeParams, $http, $rootScope) { - $scope.history = ExerciceHistory.query({ exerciceId: $routeParams.exerciceId }); + $scope.history = []; + $scope.refreshHistory = function() { + $scope.history = ExerciceHistory.query({ exerciceId: $routeParams.exerciceId }); + } + $scope.$parent.refreshHistory = $scope.refreshHistory; + $scope.refreshHistory(); $scope.updHistory = function() { var target = { team_id: $("#updHistory").data("idteam"), diff --git a/admin/static/views/exercice-flags.html b/admin/static/views/exercice-flags.html index af95c170..93329067 100644 --- a/admin/static/views/exercice-flags.html +++ b/admin/static/views/exercice-flags.html @@ -82,9 +82,12 @@
+ + + + diff --git a/admin/static/views/exercice.html b/admin/static/views/exercice.html index 4890c783..a96d251a 100644 --- a/admin/static/views/exercice.html +++ b/admin/static/views/exercice.html @@ -307,7 +307,12 @@
-

Historique

+
+

Historique

+
+ +
+
@@ -379,3 +384,73 @@ $('#historycoeff').focus(); }); + + + + diff --git a/libfic/exercice_history.go b/libfic/exercice_history.go index ff78242a..63dab2dd 100644 --- a/libfic/exercice_history.go +++ b/libfic/exercice_history.go @@ -1,7 +1,9 @@ package fic import ( + "encoding/binary" "fmt" + "math/rand" "time" ) @@ -56,6 +58,32 @@ func (e *Exercice) GetHistory() ([]map[string]interface{}, error) { return hist, nil } +// AppendHistoryItem sets values an entry from the history. +func (e *Exercice) AppendHistoryItem(tId int64, kind string, secondary *int64) error { + team, err := GetTeam(tId) + if err != nil { + return err + } + + if kind == "tries" { + bid := make([]byte, 5) + binary.LittleEndian.PutUint32(bid, rand.Uint32()) + return (&Exercice{Id: e.Id}).NewTry(team, bid) + } else if kind == "hint" && secondary != nil { + return team.OpenHint(&EHint{Id: *secondary}) + } else if kind == "wchoices" && secondary != nil { + return team.DisplayChoices(&FlagKey{Id: int(*secondary)}) + } else if kind == "flag_found" && secondary != nil { + return (&FlagKey{Id: int(*secondary)}).FoundBy(team) + } else if kind == "mcq_found" && secondary != nil { + return (&MCQ{Id: int(*secondary)}).FoundBy(team) + } else if kind == "solved" { + return (&Exercice{Id: e.Id}).Solved(team) + } else { + return nil + } +} + // UpdateHistoryItem sets values an entry from the history. func (e *Exercice) UpdateHistoryItem(coeff float32, tId int64, kind string, h time.Time, secondary *int64) (interface{}, error) { if kind == "hint" && secondary != nil {