Improve public screen page

This commit is contained in:
nemunaire 2017-12-17 20:44:23 +01:00
parent 612c80366f
commit 11a3fc9a49
7 changed files with 223 additions and 102 deletions

View file

@ -384,6 +384,7 @@ angular.module("FICApp")
$scope.types = { $scope.types = {
"welcome": "Messages de bienvenue", "welcome": "Messages de bienvenue",
"countdown": "Compte à rebours",
"message": "Message", "message": "Message",
"panel": "Boîte", "panel": "Boîte",
"exercice": "Exercice", "exercice": "Exercice",
@ -391,16 +392,18 @@ angular.module("FICApp")
"rank": "Classement", "rank": "Classement",
}; };
$scope.welcome_types = { $scope.welcome_types = {
"init": "Accueil des équipes", "teams": "Accueil des équipes",
"public": "Accueil du public", "public": "Accueil du public",
"countdown": "Compte à rebours lancement",
}; };
$scope.panel_types = { $scope.colors = {
"panel-default": "Default", "primary": "Primaire",
"panel-info": "Info", "secondary": "Secondaire",
"panel-success": "Success", "info": "Info",
"panel-warning": "Warning", "success": "Success",
"panel-danger": "Danger", "warning": "Warning",
"danger": "Danger",
"light": "Clair",
"dark": "Foncé",
}; };
$scope.rank_types = { $scope.rank_types = {
"general": "Classement général", "general": "Classement général",
@ -415,6 +418,50 @@ angular.module("FICApp")
$scope.someUpdt = true; $scope.someUpdt = true;
$scope.scenes = []; $scope.scenes = [];
}; };
$scope.presetScene = function(scene) {
$scope.someUpdt = true;
if (scene == "registration")
$scope.scenes = [
{
type: "welcome",
params: { kind: "teams" },
},
{
type: "welcome",
params: { kind: "public", notitle: true },
},
];
else if (scene == "welcome")
$scope.scenes = [
{
type: "welcome",
params: { kind: "public" },
},
];
else if (scene == "start")
$scope.scenes = [
{
type: "welcome",
params: { kind: "public" },
},
{
type: "countdown",
params: { color: "success", end: null, lead: "Go, go, go !", title: "Le challenge forensic va bientôt commencer !" },
},
];
else if (scene == "summary") {
$scope.scenes = [
{
type: "table",
params: { kind: "levels", themes: $scope.themes.map(function(z, i) { return z.id; }), total: true },
},
{
type: "rank",
params: { limit: 5, which: "general" },
},
];
}
};
$scope.saveScenes = function() { $scope.saveScenes = function() {
$scope.someUpdt = false; $scope.someUpdt = false;
var prms = Scene.update($scope.scenes); var prms = Scene.update($scope.scenes);

View file

@ -1,133 +1,175 @@
<form ng-submit="saveScenes()" class="form-horizontal"> <form ng-submit="saveScenes()" class="form-horizontal">
<h2>Interface publique<a ng-click="clearScene()" class="pull-right btn btn-danger"><span class="glyphicon glyphicon-remove-sign" aria-hidden="true"></span> Vider la scène</a><a ng-click="addScene()" class="pull-right btn btn-primary" style="margin-right: 10px"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter un élément</a><button type="submit" style="margin-right: 10px" class="pull-right btn btn-success"><span class="glyphicon glyphicon-save" aria-hidden="true"></span> Publier cette scène</button> <h2>
Interface publique
<div class="float-right dropdown">
<button class="btn btn-secondary dropdown-toggle mr-sm-2" type="button" data-toggle="dropdown">
Charger scène
</button>
<div class="dropdown-menu">
<a class="dropdown-item" ng-click="presetScene('registration')">Enregistrement équipes</a>
<a class="dropdown-item" ng-click="presetScene('welcome')">Accueil public</a>
<a class="dropdown-item" ng-click="presetScene('start')">Lancement</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" ng-click="presetScene('summary')">Résumé</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" ng-click="clearScene()">Scène vide</a>
</div>
</div>
<button ng-click="addScene()" class="float-right btn btn-primary mr-sm-2"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter un élément</button>
<button type="submit" class="float-right btn btn-success mr-sm-2"><span class="glyphicon glyphicon-save" aria-hidden="true"></span> Publier cette scène</button>
</h2> </h2>
<div style="clear:both"></div>
<div class="alert alert-info" ng-if="!scenes.length"> <div class="alert alert-info" ng-if="!scenes.length">
<strong ng-if="!someUpdt">Aucun contenu n'est actuellement affiché.</strong> <strong ng-if="!someUpdt">Aucun contenu n'est actuellement affiché.</strong>
<strong ng-if="someUpdt">Aucun contenu à afficher.</strong> <strong ng-if="someUpdt">Aucun contenu à afficher.</strong>
</div> </div>
<div class="well" ng-repeat="scene in scenes">
<div class="form-group"> <div class="card" ng-repeat="scene in scenes">
<div class="col-sm-offset-2 col-sm-6"> <div class="card-body">
<div class="checkbox">
<label> <div class="form-group row">
<input type="checkbox" ng-model="scene.params.hide"> Masquer temporairement <label for="type" class="col-sm-2 col-form-label col-form-label-sm">Type de scène</label>
<div class="col-sm-6">
<select class="custom-select custom-select-sm" id="type" ng-model="scene.type" ng-options="k as v for (k, v) in types"></select>
</div>
<div class="col-sm-4 form-inline">
<div class="form-check mb-2 mr-sm-2 mb-sm-0">
<label class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" ng-model="scene.params.hide">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Masquer</span>
</label> </label>
</div> </div>
</div> <button ng-click="upScene(scene)" class="btn btn-sm btn-light mb-2 mr-sm-2 mb-sm-0"><span class="glyphicon glyphicon-chevron-up" aria-hidden="true"></span></button>
<div class="col-sm-2"> <button ng-click="downScene(scene)" class="btn btn-sm btn-light mb-2 mr-sm-2 mb-sm-0"><span class="glyphicon glyphicon-chevron-down" aria-hidden="true"></span></button>
<a ng-click="upScene(scene)" class="pull-right btn btn-default"><span class="glyphicon glyphicon-chevron-up" aria-hidden="true"></span> Up</a> <button ng-click="delScene(scene)" class="btn btn-sm btn-warning mb-2 mr-sm-2 mb-sm-0"><span class="glyphicon glyphicon-minus" aria-hidden="true"></span> Supprimer</button>
<a ng-click="downScene(scene)" class="pull-right btn btn-default"><span class="glyphicon glyphicon-chevron-down" aria-hidden="true"></span> Down</a>
</div>
<div class="col-sm-2">
<a ng-click="delScene(scene)" class="pull-right btn btn-warning"><span class="glyphicon glyphicon-minus" aria-hidden="true"></span> Supprimer</a>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group row" ng-if="scene.type == 'welcome'">
<label for="type" class="col-sm-2 control-label">Type de scène</label> <label for="wtype" class="col-sm-2 col-form-label col-form-label-sm">Sorte</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="type" ng-model="scene.type" ng-options="k as v for (k, v) in types"></select> <select class="custom-select custom-select-sm" id="wtype" ng-model="scene.params.kind" ng-options="k as v for (k, v) in welcome_types"></select>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'welcome'"> <div class="form-group row" ng-if="scene.type == 'panel' || scene.type == 'countdown'">
<label for="wtype" class="col-sm-2 control-label">Sorte</label> <label for="ptype" class="col-sm-2 col-form-label col-form-label-sm">Couleur du cadre</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="wtype" ng-model="scene.params.kind" ng-options="k as v for (k, v) in welcome_types"></select> <select class="custom-select custom-select-sm" id="ptype" ng-model="scene.params.color" ng-options="k as v for (k, v) in colors"></select>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'panel'"> <div class="form-group row" ng-if="scene.type == 'message' || scene.type == 'panel' || scene.type == 'countdown'">
<label for="ptype" class="col-sm-2 control-label">Type de cadre</label> <label for="mtitle" class="col-sm-2 col-form-label col-form-label-sm">Titre</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="ptype" ng-model="scene.params.kind" ng-options="k as v for (k, v) in panel_types"></select> <input type="text" id="mtitle" ng-model="scene.params.title" class="form-control form-control-sm">
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'message' || scene.type == 'panel'"> <div class="form-group row" ng-if="scene.type == 'message' || scene.type == 'panel' || scene.type == 'countdown'">
<label for="mtitle" class="col-sm-2 control-label">Titre</label> <label for="mlead" class="col-sm-2 col-form-label col-form-label-sm" ng-if="scene.type != 'countdown'">Lead</label>
<label for="mlead" class="col-sm-2 col-form-label col-form-label-sm" ng-if="scene.type == 'countdown'">Message final</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" id="mtitle" ng-model="scene.params.title" class="form-control"> <input type="text" id="mlead" ng-model="scene.params.lead" class="form-control form-control-sm">
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'message'"> <div class="form-group row" ng-if="scene.type == 'message' || scene.type == 'panel'">
<label for="mlead" class="col-sm-2 control-label">Lead</label> <label for="mcnt" class="col-sm-2 col-form-label col-form-label-sm">Contenu HTML</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" id="mlead" ng-model="scene.params.lead" class="form-control"> <textarea class="form-control form-control-sm" id="mcnt" ng-model="scene.params.html"></textarea>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'message' || scene.type == 'panel'"> <div class="form-group row" ng-if="scene.type == 'exercice'">
<label for="mcnt" class="col-sm-2 control-label">Contenu HTML</label> <label for="eex" class="col-sm-2 col-form-label col-form-label-sm">Exercice</label>
<div class="col-sm-10"> <div class="col-sm-10">
<textarea class="form-control" id="mcnt" ng-model="scene.params.html"></textarea> <select class="custom-select custom-select-sm" id="eex" ng-model="scene.params.exercice" ng-options="ex.id as ex.title for ex in exercices">
</div>
</div>
<div class="form-group" ng-if="scene.type == 'exercice'">
<label for="eex" class="col-sm-2 control-label">Exercice</label>
<div class="col-sm-10">
<select class="form-control" id="eex" ng-model="scene.params.exercice" ng-options="ex.id as ex.title for ex in exercices">
</select> </select>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'rank'"> <div class="form-group row" ng-if="scene.type == 'countdown'">
<label for="rtype" class="col-sm-2 control-label">Sorte</label> <label for="cend" class="col-sm-2 col-form-label col-form-label-sm">Date de fin</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="rtype" ng-model="scene.params.which" ng-options="k as v for (k, v) in rank_types"></select> <input type="text" id="cend" ng-model="scene.params.end" class="form-control form-control-sm">
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'rank'"> <div class="form-group row" ng-if="scene.type == 'rank'">
<label for="rlimit" class="col-sm-2 control-label">Nombre d'éléments</label> <label for="rtype" class="col-sm-2 col-form-label col-form-label-sm">Sorte</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" id="rlimit" ng-model="scene.params.limit" class="form-control" integer> <select class="custom-select custom-select-sm" id="rtype" ng-model="scene.params.which" ng-options="k as v for (k, v) in rank_types"></select>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'rank'"> <div class="form-group row" ng-if="scene.type == 'rank'">
<label for="begin" class="col-sm-2 control-label">Début du classement (à partir de 0)</label> <label for="rlimit" class="col-sm-2 col-form-label col-form-label-sm">Nombre d'éléments</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" id="rbegin" ng-model="scene.params.begin" class="form-control" integer> <input type="text" id="rlimit" ng-model="scene.params.limit" class="form-control form-control-sm" integer>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'table'"> <div class="form-group row" ng-if="scene.type == 'rank'">
<label for="ttable" class="col-sm-2 control-label">Quelle table ?</label> <label for="begin" class="col-sm-2 col-form-label col-form-label-sm">Début du classement (à partir de 0)</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="ttable" ng-model="scene.params.kind" ng-options="k as v for (k, v) in table_types"> <input type="text" id="rbegin" ng-model="scene.params.begin" class="form-control form-control-sm" integer>
</div>
</div>
<div class="form-group row" ng-if="scene.type == 'table'">
<label for="ttable" class="col-sm-2 col-form-label col-form-label-sm">Quelle table ?</label>
<div class="col-sm-10">
<select class="custom-select custom-select-sm" id="ttable" ng-model="scene.params.kind" ng-options="k as v for (k, v) in table_types">
</select> </select>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'table'"> <div class="form-group row" ng-if="scene.type == 'table'">
<label for="ttheme" class="col-sm-2 control-label">Thèmes à afficher</label> <label for="ttheme" class="col-sm-2 col-form-label col-form-label-sm">Thèmes à afficher</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="ttheme" multiple="1" ng-model="scene.params.themes" ng-options="th.id as th.name for th in themes"> <select class="custom-select custom-select-sm" id="ttheme" multiple="1" ng-model="scene.params.themes" ng-options="th.id as th.name for th in themes">
</select> </select>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'table' && scene.params.kind == 'teams'"> <div class="form-group row" ng-if="scene.type == 'table' && scene.params.kind == 'teams'">
<label for="tteams" class="col-sm-2 control-label">Équipes à afficher</label> <label for="tteams" class="col-sm-2 col-form-label col-form-label-sm">Équipes à afficher</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="form-control" id="tteams" multiple="1" ng-model="scene.params.teams" ng-options="t.id as (t.rank + 'e - ' + t.name) for t in teams"> <select class="custom-select custom-select-sm" id="tteams" multiple="1" ng-model="scene.params.teams" ng-options="t.id as (t.rank + 'e - ' + t.name) for t in teams">
</select> </select>
</div> </div>
</div> </div>
<div class="form-group" ng-if="scene.type == 'table'"> <div class="form-group row" ng-if="scene.type == 'table'">
<div class="col-sm-offset-2 col-sm-6"> <div class="col-sm-2"></div>
<div class="checkbox"> <div class="col-sm-10">
<label> <div class="form-check">
<input type="checkbox" ng-model="scene.params.total"> Ligne de total <label class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" ng-model="scene.params.total">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Ligne de total</span>
</label> </label>
</div> </div>
</div> </div>
</div> </div>
<div class="form-group row" ng-if="scene.type == 'welcome'">
<div class="col-sm-2"></div>
<div class="col-sm-10">
<div class="form-check">
<label class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" ng-model="scene.params.notitle">
<span class="custom-control-indicator"></span>
<span class="custom-control-description">Masquer le titre</span>
</label>
</div>
</div>
</div>
</div>
</div> </div>
</form> </form>

View file

@ -25,6 +25,12 @@ body {
overflow-y: scroll; overflow-y: scroll;
} }
.bg-public {
background-image: url('../img/logo-epita-bw.png');
background-repeat: no-repeat;
background-size: cover;
}
.beautiful { .beautiful {
font-family: "Linux Biolinum",Helvetica,Arial,sans-serif; font-family: "Linux Biolinum",Helvetica,Arial,sans-serif;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

View file

@ -29,6 +29,7 @@ angular.module("FICApp")
}) })
.filter("time", function() { .filter("time", function() {
return function(input) { return function(input) {
input = Math.floor(input);
if (input == undefined) { if (input == undefined) {
return "--"; return "--";
} else if (input >= 10) { } else if (input >= 10) {

View file

@ -38,7 +38,7 @@ angular.module("FICApp")
if (time.st > 0 && time.st <= srv_cur) { if (time.st > 0 && time.st <= srv_cur) {
remain = time.st + time.du - srv_cur; remain = time.st + time.du - srv_cur;
} else if (time.st > 0) { } else if (time.st > 0) {
$rootScope.startIn = Math.floor(time.st - srv_cur); $rootScope.startAt = time.st;
} }
if (remain < 0) { if (remain < 0) {
remain = 0; remain = 0;
@ -109,6 +109,26 @@ angular.module("FICApp")
refreshEvents() refreshEvents()
$interval(refreshEvents, 2100); $interval(refreshEvents, 2100);
}) })
.controller("CountdownController", function($scope, $interval) {
$scope.duration = 0;
$scope.init = function(end) {
console.log(end);
console.log(Date.parse(end)/1000);
$scope.initT(Date.parse(end)/1000);
}
$scope.initT = function(end) {
var time = angular.fromJson(sessionStorage.userService);
var srv_cur = (Date.now() + (time.cu * 1000 - time.he)) / 1000;
$scope.duration += Math.floor(end - srv_cur);
}
var stop = $interval(function() {
$scope.duration -= 1;
if ($scope.duration < -10)
$interval.cancel(stop);
}, 1000);
})
.controller("DataController", function($scope, $http, $rootScope, $interval) { .controller("DataController", function($scope, $http, $rootScope, $interval) {
var refreshScene = function() { var refreshScene = function() {
$http.get("/public.json").then(function(response) { $http.get("/public.json").then(function(response) {

View file

@ -14,7 +14,7 @@
<link href="/css/fic.css" type="text/css" rel="stylesheet" media="screen"> <link href="/css/fic.css" type="text/css" rel="stylesheet" media="screen">
<script src="/js/angular.min.js"></script> <script src="/js/angular.min.js"></script>
</head> </head>
<body class="bg-light" style="overflow: hidden;" class="container-fluid" ng-controller="DataController"> <body class="bg-light bg-public" style="overflow: hidden;" class="container-fluid" ng-controller="DataController">
<div class="row" style="margin:10px 0"> <div class="row" style="margin:10px 0">
<div class="col-8"> <div class="col-8">
<noscript> <noscript>
@ -25,9 +25,9 @@
<div ng-repeat="(k,s) in scene" class="repeatedd-item" style="margin-bottom: 15px;"> <div ng-repeat="(k,s) in scene" class="repeatedd-item" style="margin-bottom: 15px;">
<div class="card" ng-if="s.type == 'welcome' && !s.params.hide && s.params.kind == 'init'"> <div class="card" ng-if="s.type == 'welcome' && !s.params.hide && s.params.kind == 'teams'">
<div class="card-body"> <div class="card-body">
<h1>Bienvenue au challenge forensic&nbsp;!</h1> <h1 ng-if="!s.params.notitle">Bienvenue au challenge forensic&nbsp;!</h1>
<p class="lead text-justify"> <p class="lead text-justify">
Avant de vous installer, venez récupérer votre clef USB auprès Avant de vous installer, venez récupérer votre clef USB auprès
de notre équipe. Elle contient le certificat qui vous permettra de notre équipe. Elle contient le certificat qui vous permettra
@ -42,17 +42,19 @@
</div> </div>
</div> </div>
<div class="card border-success" ng-if="s.type == 'welcome' && !s.params.hide && s.params.kind == 'countdown'"> <div class="card border-{{s.params.color}}" ng-if="s.type == 'countdown' && !s.params.hide">
<div class="card-header bg-success text-white"> <div class="card-header bg-{{s.params.color}} text-white" ng-if="s.params.title">
<h3 style="margin:0"><strong>Le {{ settings.title }} est sur le point de commencer&nbsp;!</strong></h3> <h3 style="margin:0"><strong ng-bind="s.params.title"></strong></h3>
</div>
<div ng-controller="CountdownController" ng-init="s.params.end?init(s.params.end):initT(startAt)">
<div class="card-body text-center" style="font-size: 450%;" ng-if="duration > 0">{{ duration / 60 | time }} <span class="point">:</span> {{ duration % 60 | time }}</div>
<div class="card-body text-center" style="font-size: 450%;" ng-if="!duration || duration <= 0">{{ s.params.lead }}</div>
</div> </div>
<div class="card-body text-center" style="font-size: 450%;" ng-if="startIn">{{ startIn }}</div>
<div class="card-body text-center" style="font-size: 450%;" ng-if="!startIn">Go, go, go&nbsp;!</div>
</div> </div>
<div class="card" ng-if="s.type == 'welcome' && !s.params.hide && s.params.kind == 'public'"> <div class="card" ng-if="s.type == 'welcome' && !s.params.hide && s.params.kind == 'public'">
<div class="card-body"> <div class="card-body">
<h1>Bienvenue au challenge forensic&nbsp;!</h1> <h1 ng-if="!s.params.notitle">Bienvenue au challenge forensic&nbsp;!</h1>
<p class="lead text-justify"> <p class="lead text-justify">
Durant ce challenge, les équipes doivent <strong>remonter des scénarii Durant ce challenge, les équipes doivent <strong>remonter des scénarii
d'attaques</strong> auxquels nos systèmes d'information <strong>font faces d'attaques</strong> auxquels nos systèmes d'information <strong>font faces
@ -72,18 +74,21 @@
<div class="card" ng-if="s.type == 'message' && !s.params.hide"> <div class="card" ng-if="s.type == 'message' && !s.params.hide">
<div class="card-body"> <div class="card-body">
<h1 ng-if="s.params.title"><strong>{{ s.params.title }}</strong></h1> <h1 ng-if="s.params.title"><strong ng-bind="s.params.title"></strong></h1>
<p ng-if="s.params.lead" class="lead text-justify">{{ s.params.lead }}</p> <p ng-if="s.params.lead" class="lead text-justify" ng-bind="s.params.lead"></p>
<p ng-bind-html="s.params.html" ng-if="s.params.html"></p> <p ng-bind-html="s.params.html" ng-if="s.params.html"></p>
<p ng-if="s.params.text">{{ s.params.text }}</p> <p ng-if="s.params.text" ng-bind="s.params.text"></p>
</div> </div>
</div> </div>
<div class="card" ng-if="s.type == 'panel' && !s.params.hide"> <div class="card border-{{ s.params.color }}" ng-if="s.type == 'panel' && !s.params.hide">
<div class="card-header {{ s.params.kind }}" ng-if="s.params.title"> <div class="card-header bg-{{ s.params.color }} text-white" ng-if="s.params.title">
<h3 style="margin:0">{{ s.params.title }}</h3> <h3 style="margin:0" ng-bind="s.params.title"></h3>
</div>
<div class="card-body" ng-if="s.params.text || s.params.lead">
<h4 ng-if="s.params.lead" class="card-title text-justify" ng-bind="s.params.lead"></h4>
<p class="card-text" ng-bind="s.params.text"></p>
</div> </div>
<div class="card-body" ng-if="s.params.text">{{ s.params.text }}</div>
<div class="card-body" ng-if="s.params.html" ng-bind-html="s.params.html"></div> <div class="card-body" ng-if="s.params.html" ng-bind-html="s.params.html"></div>
</div> </div>
@ -105,16 +110,16 @@
</div> </div>
</div> </div>
<div class="card" ng-if="s.type == 'table' && !s.params.hide"> <div ng-if="s.type == 'table' && !s.params.hide">
<table class="table table-bordered table-striped table-sm"> <table class="table table-striped table-sm">
<thead> <thead>
<tr> <tr class="text-light">
<th class="frotated"></th> <th class="frotated"></th>
<th class="rotated" ng-repeat="(tid,th) in themes" ng-if="s.params.themes.indexOf(tid-0) !== -1"><div><span>{{ th.name }}</span></div></th> <th class="rotated" ng-repeat="(tid,th) in themes" ng-if="s.params.themes.indexOf(tid-0) !== -1"><div class="bg-dark"><span>{{ th.name }}</span></div></th>
</tr> </tr>
</thead> </thead>
<tbody ng-if="s.params.kind == 'levels'"> <tbody class="table-bordered bg-secondary text-dark" ng-if="s.params.kind == 'levels'">
<tr ng-repeat="lvl in [1,2,3,4,5]"> <tr ng-repeat="lvl in [1,2,3,4,5,6,7,8,9,10]">
<th class="text-center"><nobr>Niveau {{ lvl }}</nobr></th> <th class="text-center"><nobr>Niveau {{ lvl }}</nobr></th>
<td ng-repeat="(tid,th) in themes" class="text-center" ng-if="s.params.themes.indexOf(tid-0) !== -1"> <td ng-repeat="(tid,th) in themes" class="text-center" ng-if="s.params.themes.indexOf(tid-0) !== -1">
<span ng-repeat="exercice in th.exercices" ng-if="$index == lvl-1 && (exercice.tried || lvl == 1)" ng-class="{'text-primary': exercice.solved == 0, 'text-success': exercice.solved >= 1, 'text-bold': exercice.solved >= 1, 'text-warning': exercice.solved == 0 && exercice.tried}"> <span ng-repeat="exercice in th.exercices" ng-if="$index == lvl-1 && (exercice.tried || lvl == 1)" ng-class="{'text-primary': exercice.solved == 0, 'text-success': exercice.solved >= 1, 'text-bold': exercice.solved >= 1, 'text-warning': exercice.solved == 0 && exercice.tried}">
@ -124,7 +129,7 @@
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tbody ng-if="s.params.kind == 'teams'"> <tbody class="table-bordered bg-secondary text-dark" ng-if="s.params.kind == 'teams'">
<tr ng-repeat="team in rank | orderBy: 'rank' | limitTo: s.params.limit: s.params.begin" ng-if="s.params.teams.indexOf(team.id-0) !== -1" ng-controller="TeamController"> <tr ng-repeat="team in rank | orderBy: 'rank' | limitTo: s.params.limit: s.params.begin" ng-if="s.params.teams.indexOf(team.id-0) !== -1" ng-controller="TeamController">
<th class="text-center">{{ team.rank }}<sup ng-if="team.rank == 1">er</sup><sup ng-if="team.rank > 1">e</sup><br><span style="text-overflow: ellipsis; display: inline-block; width: 82px;overflow: hidden;">{{ team.name }}</span></th> <th class="text-center">{{ team.rank }}<sup ng-if="team.rank == 1">er</sup><sup ng-if="team.rank > 1">e</sup><br><span style="text-overflow: ellipsis; display: inline-block; width: 82px;overflow: hidden;">{{ team.name }}</span></th>
<td ng-repeat="(tid,th) in themes" class="text-center" ng-if="mystats && s.params.themes.indexOf(tid-0) !== -1"> <td ng-repeat="(tid,th) in themes" class="text-center" ng-if="mystats && s.params.themes.indexOf(tid-0) !== -1">
@ -135,12 +140,12 @@
</tbody> </tbody>
<tfoot ng-if="s.params.total" ng-init="team={id:0}"> <tfoot ng-if="s.params.total" ng-init="team={id:0}">
<tr ng-controller="TeamController"> <tr ng-controller="TeamController">
<td class="text-right"> <td class="text-right text-dark">
<span ng-if="s.params.kind == 'levels'">Résolus</span> <span ng-if="s.params.kind == 'levels'">Résolus</span>
<span ng-if="s.params.kind == 'teams'">Total résolus</span><br> <span ng-if="s.params.kind == 'teams'">Total résolus</span><br>
Tentatives Tentatives
</td> </td>
<td ng-repeat="(tid,th) in themes" class="text-center" ng-if="mystats && s.params.themes.indexOf(tid-0) !== -1"> <td class="table-bordered bg-dark" ng-repeat="(tid,th) in themes" class="text-center" ng-if="mystats && s.params.themes.indexOf(tid-0) !== -1">
<strong>{{ mystats.themes[tid].solved }}</strong><br> <strong>{{ mystats.themes[tid].solved }}</strong><br>
{{ mystats.themes[tid].tries }} {{ mystats.themes[tid].tries }}
</td> </td>
@ -151,7 +156,7 @@
<div class="card" ng-if="s.type == 'rank' && !s.params.hide"> <div class="card" ng-if="s.type == 'rank' && !s.params.hide">
<table class="table table-bordered table-striped table-sm"> <table class="table table-bordered table-striped table-sm">
<thead> <thead class="thead-dark">
<tr> <tr>
<th class="text-right">Place</th> <th class="text-right">Place</th>
<th>Équipe</th> <th>Équipe</th>
@ -204,7 +209,7 @@
<div style="position: fixed; bottom: 0; right: 0; width: 33vw; height: 14vh" class="bg-primary"> <div style="position: fixed; bottom: 0; right: 0; width: 33vw; height: 14vh" class="bg-primary">
<div class="carousel slide" id="carousel-logos" data-ride="carousel" data-interval="10500"> <div class="carousel slide" id="carousel-logos" data-ride="carousel" data-interval="10500">
<div class="carousel-inner"> <div class="carousel-inner">
<div class="carousel-item active"> <div class="carousel-item">
<div class="carousel-caption"> <div class="carousel-caption">
<a href="http://www.epita.fr/"><img src="/img/epita.png" alt="Epita" style="max-height:14vh"></a> <a href="http://www.epita.fr/"><img src="/img/epita.png" alt="Epita" style="max-height:14vh"></a>
<img src="/img/rcc.png" alt="Réserve Citoyenne Cyberdéfense" style="height:14vh"> <img src="/img/rcc.png" alt="Réserve Citoyenne Cyberdéfense" style="height:14vh">
@ -212,7 +217,7 @@
</div> </div>
<div class="carousel-item"> <div class="carousel-item">
<div class="carousel-caption"> <div class="carousel-caption">
<h2>Bienvenue au challenge forensic&nbsp;!</h2> <h2 style="margin: 17px">Bienvenue au challenge forensic&nbsp;!</h2>
</div> </div>
</div> </div>
<div class="carousel-item"> <div class="carousel-item">
@ -252,9 +257,9 @@
</p> </p>
</div> </div>
</div> </div>
<div class="carousel-item"> <div class="carousel-item active">
<div class="carousel-caption" style="padding: 3px 25px; width: 32vw;"> <div class="carousel-caption">
<table class="table table-bordered table-sm table-striped"> <table class="table table-sm table-striped">
<tbody> <tbody>
<tr> <tr>
<td>11&nbsp;h</td> <td>11&nbsp;h</td>