diff --git a/admin/static/js/app.js b/admin/static/js/app.js index 9ecac1a7..64baef5f 100644 --- a/admin/static/js/app.js +++ b/admin/static/js/app.js @@ -421,6 +421,7 @@ angular.module("FICApp") $rootScope.settings.start = new Date(response.start); $rootScope.settings.end = new Date(response.end); $rootScope.settings.generation = new Date(response.generation); + $rootScope.settings.activateTime = new Date(response.activateTime); }) $scope.configro = ROSettings.get(); $scope.duration = 240; @@ -430,11 +431,13 @@ angular.module("FICApp") var nStart = this.config.start; var nEnd = this.config.end; var nGen = this.config.generation; + var aTime = this.config.activateTime; this.config.$update(function() { $rootScope.newBox('success', msg); $rootScope.settings.start = new Date(nStart); $rootScope.settings.end = new Date(nEnd); $rootScope.settings.generation = new Date(nGen); + $rootScope.settings.activateTime = new Date(aTime); }, function(response) { $rootScope.newBox('danger', 'An error occurs when saving settings:', response.data.errmsg); }); @@ -456,6 +459,11 @@ angular.module("FICApp") $scope.saveSettings(); }); } + $scope.updActivateTime = function() { + var ts = Date.now() - Date.now() % 60000; + var d = new Date(ts + 120000); + this.config.activateTime = d.toISOString(); + } $scope.reset = function(type) { if (confirm("Êtes-vous sûr ?")) { $http.post("/api/reset", {"type": type}).then(function(time) { diff --git a/admin/static/views/settings.html b/admin/static/views/settings.html index 815e6ea5..4fa80130 100644 --- a/admin/static/views/settings.html +++ b/admin/static/views/settings.html @@ -83,6 +83,14 @@
+
+
+
+ +
+ +
+
diff --git a/frontend/static/js/challenge.js b/frontend/static/js/challenge.js index ffd1777b..fd38a6c4 100644 --- a/frontend/static/js/challenge.js +++ b/frontend/static/js/challenge.js @@ -84,11 +84,15 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"]) refreshSettingsInterval = $interval(refreshSettings, Math.floor(Math.random() * 24000) + 32000); $http.get("/settings.json").then(function(response) { - $rootScope.recvTime(response); + var time = $rootScope.recvTime(response); response.data.start = new Date(response.data.start); response.data.end = new Date(response.data.end); response.data.generation = new Date(response.data.generation); - $rootScope.settings = response.data; + response.data.activateTime = new Date(response.data.activateTime); + if (response.data.activateTime <= new Date(Date.now() + (time.cu - time.he))) + $rootScope.settings = response.data; + else + $rootScope.settings.activateTime = response.data.activateTime; }); } @@ -210,12 +214,15 @@ angular.module("FICApp", ["ngRoute", "ngSanitize"]) actMenu(); } - $rootScope.refresh = function(justMy) { + $rootScope.refresh = function(justMy, justSettings) { if (!justMy) { refreshSettings(); refreshThemes(); $rootScope.refreshTeams(); } + else if (justSettings) { + refreshSettings(); + } refreshMy(); } $rootScope.refresh(); diff --git a/frontend/static/js/common.js b/frontend/static/js/common.js index 4f6a457d..87e9c371 100644 --- a/frontend/static/js/common.js +++ b/frontend/static/js/common.js @@ -144,15 +144,16 @@ angular.module("FICApp") "he": (new Date()).getTime(), }; sessionStorage.userService = angular.toJson(time); + return time; } function updTime() { if (time && $rootScope.settings) { var srv_cur = new Date(Date.now() + (time.cu - time.he)); - // Refresh on start time reached - if (Math.floor($rootScope.settings.start / 1000) == Math.floor(srv_cur / 1000)) - $rootScope.refresh(true); + // 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 == 0) { diff --git a/settings/settings.go b/settings/settings.go index b29d5add..d45a46aa 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -35,6 +35,8 @@ type FICSettings struct { End time.Time `json:"end"` // Generation is a value used to regenerate static files. Generation time.Time `json:"generation"` + // ActivateTime is the time when the current file should be proceed. + ActivateTime time.Time `json:"activateTime"` // FirstBlood is the coefficient applied to each first team who solve a challenge. FirstBlood float64 `json:"firstBlood"` @@ -129,11 +131,7 @@ func LoadAndWatchSettings(settingsPath string, reload func (FICSettings)) { go func(){ for range c { log.Println("SIGHUP received, reloading settings...") - if config, err := ReadSettings(settingsPath); err != nil { - log.Println("ERROR: Unable to read challenge settings:", err) - } else { - reload(config) - } + go tryReload(settingsPath, reload) } }() @@ -152,11 +150,7 @@ func LoadAndWatchSettings(settingsPath string, reload func (FICSettings)) { case ev := <-watcher.Events: if path.Base(ev.Name) == SettingsFile && ev.Op & fsnotify.Write == fsnotify.Write { log.Println("Settings file changes, reloading it!") - if config, err := ReadSettings(settingsPath); err != nil { - log.Println("ERROR: Unable to read challenge settings:", err) - } else { - reload(config) - } + go tryReload(settingsPath, reload) } case err := <-watcher.Errors: log.Println("watcher error:", err) @@ -165,3 +159,16 @@ func LoadAndWatchSettings(settingsPath string, reload func (FICSettings)) { }() } } + +func tryReload(settingsPath string, reload func (FICSettings)) { + if config, err := ReadSettings(settingsPath); err != nil { + log.Println("ERROR: Unable to read challenge settings:", err) + } else if time.Until(config.ActivateTime) > 0 { + log.Println("Configuration reloading postponed, activating at:", config.ActivateTime) + time.Sleep(time.Until(config.ActivateTime)) + log.Println("Time to activate configuration...") + tryReload(settingsPath, reload) + } else { + reload(config) + } +}