admin: Start compute flag stats
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
nemunaire 2025-01-24 23:49:00 +01:00
parent 57c3cd8fd6
commit a5fd04672b
3 changed files with 52 additions and 1 deletions

View File

@ -62,6 +62,7 @@ func declareExercicesRoutes(router *gin.RouterGroup) {
apiFlagsRoutes.POST("/try", tryExerciceFlag)
apiFlagsRoutes.DELETE("/", deleteExerciceFlag)
apiFlagsRoutes.GET("/dependancies", showExerciceFlagDeps)
apiFlagsRoutes.GET("/statistics", showExerciceFlagStats)
apiFlagsRoutes.GET("/choices/", listFlagChoices)
apiFlagsChoicesRoutes := apiExercicesRoutes.Group("/choices/:cid")
apiFlagsChoicesRoutes.Use(FlagChoiceHandler)
@ -852,6 +853,34 @@ func showExerciceFlagDeps(c *gin.Context) {
c.JSON(http.StatusOK, deps)
}
func showExerciceFlagStats(c *gin.Context) {
exercice := c.MustGet("exercice").(*fic.Exercice)
flag := c.MustGet("flag-key").(*fic.FlagKey)
history, err := exercice.GetHistory()
if err != nil {
log.Println("Unable to getExerciceHistory:", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when retrieving exercice history"})
return
}
var completed, tries, nteams int64
for _, hline := range history {
if hline["kind"].(string) == "flag_found" {
if *hline["secondary"].(*int) == flag.Id {
completed += 1
}
}
}
c.JSON(http.StatusOK, gin.H{
"completed": completed,
"tries": tries,
"nteams": nteams,
})
}
func tryExerciceFlag(c *gin.Context) {
flag := c.MustGet("flag-key").(*fic.FlagKey)
@ -1048,7 +1077,11 @@ func updateExerciceQuiz(c *gin.Context) {
if cur.Id == next.Id {
seen = true
log.Println("ici", cur.Label, cur.Response, next.Response)
if cur.Label != next.Label || cur.Response != next.Response {
log.Println("1", cur.Label, cur.Response, next.Response)
cur.Label = next.Label
cur.Response = next.Response
if _, err := cur.Update(); err != nil {

View File

@ -348,6 +348,9 @@ angular.module("FICApp")
.factory("ExerciceFlagDeps", function ($resource) {
return $resource("api/exercices/:exerciceId/flags/:flagId/dependancies", { exerciceId: '@idExercice', flagId: '@id' })
})
.factory("ExerciceFlagStats", function ($resource) {
return $resource("api/exercices/:exerciceId/flags/:flagId/statistics", { exerciceId: '@idExercice', flagId: '@id' })
})
.factory("ExerciceMCQFlag", function ($resource) {
return $resource("api/exercices/:exerciceId/quiz/:mcqId", { exerciceId: '@idExercice', mcqId: '@id' }, {
update: { method: 'PUT' }
@ -2345,6 +2348,12 @@ angular.module("FICApp")
}
})
.controller("ExerciceFlagStatsController", function ($scope, $routeParams, ExerciceFlagStats) {
$scope.init = function (flag) {
$scope.stats = ExerciceFlagStats.get({ exerciceId: $routeParams.exerciceId, flagId: flag.id });
}
})
.controller("ExerciceMCQFlagsController", function ($scope, ExerciceMCQFlag, $routeParams, $rootScope) {
$scope.quiz = ExerciceMCQFlag.query({ exerciceId: $routeParams.exerciceId });

View File

@ -73,12 +73,21 @@
</div>
<div class="col-4">
<div ng-controller="ExerciceFlagDepsController" ng-init="init(flag)">
Dépendances&nbsp;:
<strong>Dépendances&nbsp;:</strong>
<ul ng-if="deps.length > 0">
<dependancy ng-repeat="dep in deps" dep="dep"></dependancy>
</ul>
<span ng-if="deps.length == 0"> sans</span>
</div>
<hr>
<div ng-controller="ExerciceFlagStatsController" ng-init="init(flag)">
<strong>Statistiques</strong>
<ul>
<li>Validés : {{ stats["completed"] }}</li>
<li>Tentés : {{ stats["tries"] }}</li>
<li>Équipes : {{ stats["nteams"] }}</li>
</ul>
</div>
</div>
<div class="col-4" ng-controller="ExerciceFlagChoicesController">
<div class="btn-toolbar justify-content-end mb-2" role="toolbar">