340 lines
10 KiB
JavaScript
340 lines
10 KiB
JavaScript
var alertNbLines = true;
|
|
|
|
function treatFlagKey(flag) {
|
|
if (flag.values !== undefined) {
|
|
if (flag.separator) {
|
|
for (var i = flag.values.length - 1; i >= 0; i--) {
|
|
if (flag.nb_lines && (flag.values[i] == undefined || !flag.values[i].length)) {
|
|
if (alertNbLines) {
|
|
alertNbLines = false;
|
|
if (!confirm("Lorsque plusieurs flags sont attendus pour une même question, ceux-ci ne sont pas validés un par un. Ils ne sont validés qu'une fois tous les champs remplis correctement. (Sauf mention contraire, l'ordre n'importe pas)"))
|
|
console.log(flag.values[9999].length); // Launch exception here to avoid form validation
|
|
}
|
|
}
|
|
else if (!flag.values[i].length) {
|
|
flag.values.splice(i, 1);
|
|
}
|
|
}
|
|
|
|
if (flag.ignore_order)
|
|
flag.value = flag.values.slice().sort().join(flag.separator) + flag.separator;
|
|
else
|
|
flag.value = flag.values.join(flag.separator) + flag.separator;
|
|
|
|
if (flag.values.length == 0)
|
|
flag.values = [""];
|
|
}
|
|
else
|
|
flag.value = flag.values[0];
|
|
}
|
|
|
|
if (flag.found == null && flag.soluce !== undefined) {
|
|
if (flag.value && flag.soluce) {
|
|
if (flag.ignore_case)
|
|
flag.value = flag.value.toLowerCase();
|
|
if (flag.capture_regexp) {
|
|
var re = new RegExp(flag.capture_regexp, flag.ignore_case?'ui':'u');
|
|
var match = re.exec(flag.value);
|
|
match.shift();
|
|
flag.value = match.join("+");
|
|
}
|
|
|
|
if (flag.soluce == b2sum(flag.value))
|
|
flag.found = new Date();
|
|
}
|
|
}
|
|
return flag.found !== undefined && flag.found !== false;
|
|
}
|
|
|
|
String.prototype.capitalize = function() {
|
|
return this
|
|
.toLowerCase()
|
|
.replace(
|
|
/(^|\s|-)([a-z])/g,
|
|
function(m,p1,p2) { return p1+p2.toUpperCase(); }
|
|
);
|
|
}
|
|
|
|
Array.prototype.inArray = function(v) {
|
|
return this.reduce(function(presence, current) {
|
|
return presence || current == v;
|
|
}, false);
|
|
}
|
|
|
|
angular.module("FICApp")
|
|
.directive('autofocus', ['$timeout', function($timeout) {
|
|
return {
|
|
restrict: 'A',
|
|
link : function($scope, $element) {
|
|
$timeout(function() {
|
|
$element[0].focus();
|
|
});
|
|
}
|
|
}
|
|
}])
|
|
.directive('autocarousel', ['$timeout', function($timeout) {
|
|
return {
|
|
restrict: 'A',
|
|
link : function($scope, $element) {
|
|
$timeout(function() {
|
|
$($element[0]).carousel();
|
|
});
|
|
}
|
|
}
|
|
}]);
|
|
|
|
angular.module("FICApp")
|
|
.filter("escapeURL", function() {
|
|
return function(input) {
|
|
return encodeURIComponent(input);
|
|
}
|
|
})
|
|
.filter("stripHTML", function() {
|
|
return function(input) {
|
|
if (!input)
|
|
return input;
|
|
return input.replace(
|
|
/(<([^>]+)>)/ig,
|
|
""
|
|
);
|
|
}
|
|
})
|
|
.filter("capitalize", function() {
|
|
return function(input) {
|
|
return input.capitalize();
|
|
}
|
|
})
|
|
.filter("rankTitle", function() {
|
|
var itms = {
|
|
"rank": "Rang",
|
|
"name": "Équipe",
|
|
"score": "Score",
|
|
};
|
|
return function(input) {
|
|
if (itms[input] != undefined) {
|
|
return itms[input];
|
|
} else {
|
|
return input;
|
|
}
|
|
}
|
|
})
|
|
.filter("time", function() {
|
|
return function(input) {
|
|
input = Math.floor(input);
|
|
if (input == undefined) {
|
|
return "--";
|
|
} else if (input >= 10) {
|
|
return input;
|
|
} else {
|
|
return "0" + input;
|
|
}
|
|
}
|
|
})
|
|
.filter("timer", function() {
|
|
return function(input) {
|
|
input = Math.floor(input / 1000);
|
|
var res = ""
|
|
|
|
if (input >= 3600) {
|
|
res += Math.floor(input / 3600) + ":";
|
|
input = input % 3600;
|
|
}
|
|
if (res || input >= 60) {
|
|
if (res && Math.floor(input / 60) <= 9)
|
|
res += "0";
|
|
res += Math.floor(input / 60) + "'";
|
|
input = input % 60;
|
|
}
|
|
|
|
return res + (input>9?input:"0"+input) + '"';
|
|
}
|
|
})
|
|
.filter("since", function() {
|
|
return function(passed) {
|
|
if (passed < 120000) {
|
|
return "Il y a " + Math.floor(passed/1000) + " secondes";
|
|
} else {
|
|
return "Il y a " + Math.floor(passed/60000) + " minutes";
|
|
}
|
|
}
|
|
})
|
|
.filter("size", function() {
|
|
var units = [
|
|
"o",
|
|
"kio",
|
|
"Mio",
|
|
"Gio",
|
|
"Tio",
|
|
"Pio",
|
|
"Eio",
|
|
"Zio",
|
|
"Yio",
|
|
]
|
|
return function(input) {
|
|
var res = input;
|
|
var unit = 0;
|
|
while (res > 1024) {
|
|
unit += 1;
|
|
res = res / 1024;
|
|
}
|
|
return (Math.round(res * 100) / 100) + " " + units[unit];
|
|
}
|
|
})
|
|
|
|
.filter("coeff", function() {
|
|
return function(input) {
|
|
if (input > 1) {
|
|
return "+" + Math.floor((input - 1) * 100) + " %"
|
|
} else if (input < 1) {
|
|
return "-" + Math.floor((1 - input) * 100) + " %"
|
|
} else {
|
|
return "";
|
|
}
|
|
}
|
|
})
|
|
|
|
.filter("objectLength", function() {
|
|
return function(input) {
|
|
if (input !== undefined)
|
|
return Object.keys(input).length;
|
|
else
|
|
return "";
|
|
}
|
|
})
|
|
|
|
.filter("bto16", function() {
|
|
return function(input) {
|
|
const raw = atob(input);
|
|
let result = '';
|
|
for (let i = 0; i < raw.length; i++) {
|
|
const hex = raw.charCodeAt(i).toString(16);
|
|
result += (hex.length === 2 ? hex : '0' + hex);
|
|
}
|
|
return result;
|
|
}
|
|
});
|
|
|
|
angular.module("FICApp")
|
|
.component('flagKey', {
|
|
bindings: {
|
|
kid: '=',
|
|
key: '=',
|
|
settings: '=',
|
|
wantchoices: '=',
|
|
},
|
|
controller: function() {
|
|
this.additem = function(key) {
|
|
this.key.values.push("");
|
|
};
|
|
},
|
|
template: `
|
|
<div class="form-group">
|
|
<label for="sol_{{ $ctrl.kid }}_0" ng-class="{'text-light': !$ctrl.key.found}">{{ $ctrl.key.label }} :</label>
|
|
<span ng-if="$ctrl.key.found && $ctrl.key.value" ng-bind="$ctrl.key.value"></span>
|
|
<div class="input-group" ng-repeat="v in $ctrl.key.values track by $index" ng-class="{'mt-1': !$first}" ng-if="!$ctrl.key.found">
|
|
<input type="text" class="form-control flag" id="sol_{{ $ctrl.kid }}_{{ $index }}" autocomplete="off" name="sol_{{ $ctrl.kid }}_{{ $index }}" ng-model="$ctrl.key.values[$index]" ng-if="!$ctrl.key.choices && !$ctrl.key.multiline" placeholder="{{ $ctrl.key.placeholder }}" title="{{ $ctrl.key.placeholder }}">
|
|
<textarea class="form-control flag" id="sol_{{ $ctrl.kid }}_{{ $index }}" autocomplete="off" name="sol_{{ $ctrl.kid }}_{{ $index }}" ng-model="$ctrl.key.values[$index]" ng-if="!$ctrl.key.choices && $ctrl.key.multiline" placeholder="{{ $ctrl.key.placeholder }}" title="{{ $ctrl.key.placeholder }}"></textarea>
|
|
<select class="custom-select" id="sol_{{ $ctrl.kid }}" name="sol_{{ $ctrl.kid }}" ng-model="$ctrl.key.values[$index]" ng-if="$ctrl.key.choices" ng-options="l as v for (l, v) in $ctrl.key.choices"></select>
|
|
<div class="input-group-append" ng-if="$ctrl.key.choices_cost">
|
|
<button class="btn btn-success" type="button" ng-click="$ctrl.wantchoices($ctrl.kid)" ng-class="{disabled: $ctrl.key.wcsubmitted}" title="Cliquez pour échanger ce champ de texte par une liste de choix. L'opération vous coûtera {{ $ctrl.key.choices_cost * $ctrl.settings.wchoiceCurrentCoefficient }} points.">
|
|
<span class="glyphicon glyphicon-tasks" aria-hidden="true"></span>
|
|
Liste de propositions (<ng-pluralize count="$ctrl.key.choices_cost * $ctrl.settings.wchoiceCurrentCoefficient" when="{'one': '{} point', 'other': '{} points'}"></ng-pluralize>)
|
|
</button>
|
|
</div>
|
|
<div class="input-group-append" ng-if="$ctrl.key.separator && !$ctrl.key.nb_lines && $last">
|
|
<button class="btn btn-success" type="button" ng-click="$ctrl.additem(key)" title="Ajouter un élément.">
|
|
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<small class="form-text text-muted" ng-if="!$ctrl.key.found && $ctrl.key.help.length > 0" ng-bind-html="$ctrl.key.help"></small>
|
|
<span class="glyphicon glyphicon-ok form-control-feedback text-success" aria-hidden="true" ng-if="$ctrl.key.found" title="Flag trouvé à {{ $ctrl.key.found | date:'mediumTime'}}"></span>
|
|
</div>
|
|
`
|
|
});
|
|
|
|
angular.module("FICApp")
|
|
.run(function($rootScope) {
|
|
$rootScope.recvTime = function(response) {
|
|
time = {
|
|
"cu": Math.floor(response.headers("x-fic-time") * 1000),
|
|
"he": (new Date()).getTime(),
|
|
};
|
|
sessionStorage.time = angular.toJson(time);
|
|
return time;
|
|
}
|
|
})
|
|
|
|
.controller("CountdownController", function($scope, $rootScope, $interval) {
|
|
var time;
|
|
if (sessionStorage.time)
|
|
time = angular.fromJson(sessionStorage.time);
|
|
|
|
$scope.time = {};
|
|
|
|
$rootScope.getSrvTime = function() {
|
|
if (time && time.cu && time.he)
|
|
return new Date(Date.now() + (time.cu - time.he));
|
|
else
|
|
return undefined;
|
|
}
|
|
|
|
function updTime() {
|
|
if (time && $rootScope.settings && $rootScope.settings.end) {
|
|
var srv_cur = new Date(Date.now() + (time.cu - time.he));
|
|
|
|
// Refresh on start/activate time reached
|
|
if (Math.floor($rootScope.settings.start / 1000) == Math.floor(srv_cur / 1000) ||Math.floor($rootScope.settings.activateTime / 1000) == Math.floor(srv_cur / 1000))
|
|
$rootScope.refresh(true, true);
|
|
|
|
var remain = 0;
|
|
if ($rootScope.settings.start === undefined || $rootScope.settings.start == 0) {
|
|
$scope.time = {};
|
|
return
|
|
} else if ($rootScope.settings.start > srv_cur) {
|
|
$scope.startIn = Math.floor(($rootScope.settings.start - srv_cur) / 1000);
|
|
remain = $rootScope.settings.end - $rootScope.settings.start;
|
|
} else if ($rootScope.settings.end > srv_cur) {
|
|
$scope.startIn = 0;
|
|
remain = $rootScope.settings.end - srv_cur;
|
|
}
|
|
|
|
$rootScope.timeProgression = 1 - remain / ($rootScope.settings.end - $rootScope.settings.start);
|
|
$rootScope.timeRemaining = remain;
|
|
|
|
if ($rootScope.settings.activateTime) {
|
|
var now = new Date();
|
|
var actTime = new Date($rootScope.settings.activateTime);
|
|
|
|
if (actTime > now)
|
|
$rootScope.activateTimeCountDown = actTime - now;
|
|
else
|
|
$rootScope.activateTimeCountDown = null;
|
|
} else {
|
|
$rootScope.activateTimeCountDown = null;
|
|
}
|
|
|
|
remain = remain / 1000;
|
|
|
|
if (remain < 0) {
|
|
remain = 0;
|
|
$scope.time.end = true;
|
|
$scope.time.expired = true;
|
|
} else if (remain < 60) {
|
|
$scope.time.end = false;
|
|
$scope.time.expired = true;
|
|
} else {
|
|
$scope.time.end = false;
|
|
$scope.time.expired = false;
|
|
}
|
|
|
|
$scope.time.remaining = remain;
|
|
$scope.time.hours = Math.floor(remain / 3600);
|
|
$scope.time.minutes = Math.floor((remain % 3600) / 60);
|
|
$scope.time.seconds = Math.floor(remain % 60);
|
|
}
|
|
}
|
|
updTime();
|
|
$interval(updTime, 1000);
|
|
})
|