ui: Prepare ui for public interface

This commit is contained in:
nemunaire 2021-09-09 18:20:03 +02:00
commit 56d8d49304
7 changed files with 118 additions and 27 deletions

View file

@ -707,6 +707,11 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true "dev": true
}, },
"hash-wasm": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.9.0.tgz",
"integrity": "sha512-7SW7ejyfnRxuOc7ptQHSf4LDoZaWOivfzqw+5rpcQku0nHfmicPKE51ra9BiRLAmT8+gGLestr1XroUkqdjL6w=="
},
"ignore": { "ignore": {
"version": "4.0.6", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",

View file

@ -27,6 +27,7 @@
"bootstrap": "^5.1.0", "bootstrap": "^5.1.0",
"bootstrap-icons": "^1.5.0", "bootstrap-icons": "^1.5.0",
"bootswatch": "^5.1.0", "bootswatch": "^5.1.0",
"hash-wasm": "^4.9.0",
"seedrandom": "^3.0.5" "seedrandom": "^3.0.5"
} }
} }

View file

@ -12,6 +12,10 @@
Spinner, Spinner,
} from 'sveltestrap'; } from 'sveltestrap';
import { blake2b } from 'hash-wasm';
import { my } from '../stores/my.js';
import DateFormat from './DateFormat.svelte'; import DateFormat from './DateFormat.svelte';
import FlagKey from './FlagKey.svelte'; import FlagKey from './FlagKey.svelte';
import FlagMCQ from './FlagMCQ.svelte'; import FlagMCQ from './FlagMCQ.svelte';
@ -36,42 +40,89 @@
}) })
} }
export let forcesolved = false;
let responses = { }; let responses = { };
async function submitFlags() { async function submitFlags() {
submitInProgress = true; submitInProgress = true;
sberr = ""; sberr = "";
message = ""; message = "";
const response = await fetch( if ($my && $my.team_id === 0) {
"submit/" + exercice.id, let allGoodResponse = true;
{ for (const f in flags) {
method: "POST", const flag = flags[f];
headers: {'Accept': 'application/json'},
body: JSON.stringify(responses), let soluce = "";
} if (flag.type == "mcq") {
) for (const c in flag.choices) {
soluce += responses.mcqs[c] ? "t" : "f";
}
} else {
soluce = responses.flags[flag.id];
}
if (flag.ignore_case) {
soluce = soluce.toLowerCase();
}
if (flag.validator_regexp) {
let re = new RegExp(flag.validator_regexp, flag.ignore_case?'i':'');
soluce = soluce.match(re).slice(1).join("+");
}
if (await blake2b(soluce) == flag.soluce) {
flags[f].found = new Date();
} else if (!flag.found) {
allGoodResponse = false;
}
flags = flags;
}
if (allGoodResponse) {
forcesolved = true;
}
if (exercice.tries) {
exercice.tries += 1;
} else {
exercice.tries = 1;
}
exercice.solved_time = new Date();
exercice = exercice;
if (response.status < 300) {
const data = await response.json();
messageClass = 'text-success';
message = data.errmsg;
waitDiff(20);
} else {
submitInProgress = false; submitInProgress = false;
} else {
const response = await fetch(
"submit/" + exercice.id,
{
method: "POST",
headers: {'Accept': 'application/json'},
body: JSON.stringify(responses),
}
)
messageClass = 'text-danger'; if (response.status < 300) {
const data = await response.json();
let data = ""; messageClass = 'text-success';
try {
data = await response.json();
} catch(e) {
data = null;
}
if (data && data.errmsg)
message = data.errmsg; message = data.errmsg;
if (response.statys != 402) waitDiff(20);
sberr = "Oups !"; } else {
submitInProgress = false;
messageClass = 'text-danger';
let data = "";
try {
data = await response.json();
} catch(e) {
data = null;
}
if (data && data.errmsg)
message = data.errmsg;
if (response.statys != 402)
sberr = "Oups !";
}
} }
} }

View file

@ -39,6 +39,11 @@
}) })
} }
function showHint(hint) {
hint.hidden = false;
hints = hints; // Force Svelte update
}
async function openHint(hint) { async function openHint(hint) {
hints_submitted[hint.id] = true; hints_submitted[hint.id] = true;
hinterror = ""; hinterror = "";
@ -122,7 +127,7 @@
</button> </button>
{/if} {/if}
{#if !hint.file && hint.hidden} {#if !hint.file && hint.hidden}
<button type="button" ng-click="hint.hidden = false;" class="btn btn-info"> <button type="button" on:click={() => showHint(hint)} class="btn btn-info">
<Icon name="lock" aria-hidden="true" /> <Icon name="lock" aria-hidden="true" />
Afficher Afficher
</button> </button>

View file

@ -47,6 +47,7 @@
export let theme; export let theme;
export let exercice; export let exercice;
let solved = {};
export let refresh_my; export let refresh_my;
export let refresh_teams; export let refresh_teams;
@ -158,11 +159,12 @@
</Col> </Col>
{/if} {/if}
<Col lg="6" class="mb-5"> <Col lg="6" class="mb-5">
{#if !$my.exercices[exercice.id].solved_rank} {#if !$my.exercices[exercice.id].solved_rank && !solved[exercice.id]}
<ExerciceFlags <ExerciceFlags
{refresh_my} {refresh_my}
{refresh_teams} {refresh_teams}
exercice={$my.exercices[exercice.id]} exercice={$my.exercices[exercice.id]}
bind:forcesolved={solved[exercice.id]}
flags={$my.exercices[exercice.id].flags} flags={$my.exercices[exercice.id].flags}
/> />
{:else} {:else}

View file

@ -5,6 +5,8 @@
import { themesStore } from '../stores/themes.js'; import { themesStore } from '../stores/themes.js';
import { settings, time } from '../stores/settings.js'; import { settings, time } from '../stores/settings.js';
let stop_refresh = false;
let refresh_interval_settings = null; let refresh_interval_settings = null;
async function refresh_settings(cb=null, interval=null) { async function refresh_settings(cb=null, interval=null) {
if (refresh_interval_settings) if (refresh_interval_settings)
@ -12,6 +14,9 @@
if (interval === null) { if (interval === null) {
interval = Math.floor(Math.random() * 24000) + 32000; interval = Math.floor(Math.random() * 24000) + 32000;
} }
if (stop_refresh) {
return;
}
refresh_interval_settings = setInterval(refresh_settings, interval); refresh_interval_settings = setInterval(refresh_settings, interval);
if (!cb) { if (!cb) {
@ -43,6 +48,9 @@
if (interval === null) { if (interval === null) {
interval = Math.floor(Math.random() * 24000) + 32000; interval = Math.floor(Math.random() * 24000) + 32000;
} }
if (stop_refresh) {
return;
}
refresh_interval_teams = setInterval(refresh_teams, interval); refresh_interval_teams = setInterval(refresh_teams, interval);
teamsStore.update(await fetch('teams.json', {headers: {'Accept': 'application/json'}}), cb); teamsStore.update(await fetch('teams.json', {headers: {'Accept': 'application/json'}}), cb);
@ -55,6 +63,9 @@
if (interval === null) { if (interval === null) {
interval = Math.floor(Math.random() * 24000) + 32000; interval = Math.floor(Math.random() * 24000) + 32000;
} }
if (stop_refresh) {
return;
}
refresh_interval_themes = setInterval(refresh_themes, interval); refresh_interval_themes = setInterval(refresh_themes, interval);
await themesStore.update(await fetch('themes.json', {headers: {'Accept': 'application/json'}}), cb); await themesStore.update(await fetch('themes.json', {headers: {'Accept': 'application/json'}}), cb);
@ -67,6 +78,9 @@
if (interval === null) { if (interval === null) {
interval = Math.floor(Math.random() * 24000) + 24000; interval = Math.floor(Math.random() * 24000) + 24000;
} }
if (stop_refresh) {
return;
}
refresh_interval_my = setInterval(refresh_my, interval); refresh_interval_my = setInterval(refresh_my, interval);
my.update(await fetch('my.json', {headers: {'Accept': 'application/json'}}), cb); my.update(await fetch('my.json', {headers: {'Accept': 'application/json'}}), cb);
@ -79,6 +93,9 @@
if (interval === null) { if (interval === null) {
interval = Math.floor(Math.random() * 24000) + 32000; interval = Math.floor(Math.random() * 24000) + 32000;
} }
if (stop_refresh) {
return;
}
refresh_interval_issues = setInterval(refresh_issues, interval); refresh_interval_issues = setInterval(refresh_issues, interval);
issuesStore.update(await fetch('issues.json', {headers: {'Accept': 'application/json'}}), cb); issuesStore.update(await fetch('issues.json', {headers: {'Accept': 'application/json'}}), cb);
@ -88,7 +105,11 @@
await refresh_settings(); await refresh_settings();
await refresh_themes(); await refresh_themes();
refresh_teams(); refresh_teams();
refresh_my(); refresh_my((my) => {
if (my && my.team_id === 0) {
stop_refresh = true;
}
});
refresh_issues(); refresh_issues();
return { return {

View file

@ -10,6 +10,12 @@ function createMyStore() {
res_my.json().then((my) => { res_my.json().then((my) => {
for (let k in my.exercices) { for (let k in my.exercices) {
my.exercices[k].id = k; my.exercices[k].id = k;
if (my.team_id === 0 && my.exercices[k].hints) {
for (let j in my.exercices[k].hints) {
my.exercices[k].hints[j].hidden = true;
}
}
} }
update((m) => (Object.assign(m?m:{}, my))); update((m) => (Object.assign(m?m:{}, my)));