2021-08-30 10:46:18 +00:00
|
|
|
<script>
|
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
Card,
|
|
|
|
CardBody,
|
|
|
|
CardHeader,
|
|
|
|
CardText,
|
|
|
|
Icon,
|
|
|
|
ListGroup,
|
|
|
|
ListGroupItem,
|
2021-08-31 23:38:39 +00:00
|
|
|
Progress,
|
2021-08-31 00:54:59 +00:00
|
|
|
Spinner,
|
2021-08-30 10:46:18 +00:00
|
|
|
} from 'sveltestrap';
|
|
|
|
|
2021-09-09 16:20:03 +00:00
|
|
|
import { blake2b } from 'hash-wasm';
|
|
|
|
|
|
|
|
import { my } from '../stores/my.js';
|
|
|
|
|
2021-09-01 00:21:49 +00:00
|
|
|
import DateFormat from './DateFormat.svelte';
|
2021-08-31 00:54:59 +00:00
|
|
|
import FlagKey from './FlagKey.svelte';
|
|
|
|
import FlagMCQ from './FlagMCQ.svelte';
|
|
|
|
|
|
|
|
export let exercice = { };
|
2021-08-30 10:46:18 +00:00
|
|
|
export let flags = [];
|
|
|
|
|
2021-08-31 00:54:59 +00:00
|
|
|
export let refresh_my;
|
|
|
|
export let refresh_teams;
|
|
|
|
|
|
|
|
function waitDiff(i) {
|
|
|
|
refresh_my((my) => {
|
2021-09-08 01:34:48 +00:00
|
|
|
if (my && my.exercices[exercice.id].solved_time != exercice.solved_time) {
|
2021-08-31 00:54:59 +00:00
|
|
|
submitInProgress = false;
|
|
|
|
refresh_teams();
|
|
|
|
} else if (i > 0) {
|
|
|
|
setTimeout(waitDiff, 450, i-1);
|
2021-09-08 01:34:48 +00:00
|
|
|
} else {
|
|
|
|
timeouted = true;
|
|
|
|
submitInProgress = false;
|
2021-08-31 00:54:59 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-09-09 16:20:03 +00:00
|
|
|
export let forcesolved = false;
|
2021-08-31 00:54:59 +00:00
|
|
|
let responses = { };
|
|
|
|
async function submitFlags() {
|
|
|
|
submitInProgress = true;
|
|
|
|
sberr = "";
|
|
|
|
message = "";
|
|
|
|
|
2021-09-09 16:20:03 +00:00
|
|
|
if ($my && $my.team_id === 0) {
|
|
|
|
let allGoodResponse = true;
|
|
|
|
for (const f in flags) {
|
|
|
|
const flag = flags[f];
|
2021-08-31 00:54:59 +00:00
|
|
|
|
2021-09-09 16:20:03 +00:00
|
|
|
let soluce = "";
|
|
|
|
if (flag.type == "mcq") {
|
|
|
|
for (const c in flag.choices) {
|
|
|
|
soluce += responses.mcqs[c] ? "t" : "f";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
soluce = responses.flags[flag.id];
|
|
|
|
}
|
2021-08-31 00:54:59 +00:00
|
|
|
|
2021-09-09 16:20:03 +00:00
|
|
|
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;
|
|
|
|
}
|
2021-08-31 00:54:59 +00:00
|
|
|
|
2021-09-09 16:20:03 +00:00
|
|
|
if (exercice.tries) {
|
|
|
|
exercice.tries += 1;
|
|
|
|
} else {
|
|
|
|
exercice.tries = 1;
|
2021-08-31 00:54:59 +00:00
|
|
|
}
|
2021-09-09 16:20:03 +00:00
|
|
|
exercice.solved_time = new Date();
|
|
|
|
exercice = exercice;
|
2021-08-31 00:54:59 +00:00
|
|
|
|
2021-09-09 16:20:03 +00:00
|
|
|
submitInProgress = false;
|
|
|
|
} else {
|
|
|
|
const response = await fetch(
|
|
|
|
"submit/" + exercice.id,
|
|
|
|
{
|
|
|
|
method: "POST",
|
|
|
|
headers: {'Accept': 'application/json'},
|
|
|
|
body: JSON.stringify(responses),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
if (response.status < 300) {
|
|
|
|
const data = await response.json();
|
|
|
|
messageClass = 'text-success';
|
2021-08-31 00:54:59 +00:00
|
|
|
message = data.errmsg;
|
2021-09-09 16:20:03 +00:00
|
|
|
waitDiff(20);
|
|
|
|
} 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 !";
|
|
|
|
}
|
2021-08-31 00:54:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function resetResponses() {
|
|
|
|
responses = {
|
|
|
|
flags: { },
|
|
|
|
mcqs: { },
|
|
|
|
justifications: { },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
let last_exercice = null;
|
|
|
|
$: {
|
|
|
|
if (!last_exercice || last_exercice != exercice.id) {
|
|
|
|
last_exercice = exercice.id;
|
|
|
|
resetResponses()
|
|
|
|
}
|
2021-08-30 10:46:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let sberr = "";
|
|
|
|
let message = "";
|
2021-08-31 00:54:59 +00:00
|
|
|
let messageClass = "text-danger";
|
|
|
|
let timeouted = false;
|
|
|
|
let submitInProgress = false;
|
2021-08-30 10:46:18 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<Card class="border-danger mb-2">
|
2021-08-31 23:47:44 +00:00
|
|
|
<CardHeader class="bg-danger text-light">
|
2021-08-30 10:46:18 +00:00
|
|
|
<Icon name="flag-fill" />
|
|
|
|
Faire son rapport
|
|
|
|
</CardHeader>
|
2021-08-31 23:38:39 +00:00
|
|
|
{#if exercice.flags.length != exercice.nb_flags}
|
|
|
|
<Progress
|
|
|
|
value={exercice.flags.length}
|
|
|
|
max={exercice.nb_flags}
|
|
|
|
class="rounded-0"
|
|
|
|
barClassName="text-light"
|
|
|
|
>
|
|
|
|
{exercice.flags.length}/{exercice.nb_flags}
|
|
|
|
</Progress>
|
|
|
|
{/if}
|
2021-09-08 01:34:48 +00:00
|
|
|
{#if exercice.tries || exercice.solved_time || exercice.submitted || sberr || timeouted}
|
2021-08-31 23:47:44 +00:00
|
|
|
<ListGroup class="border-dark">
|
2021-09-08 01:34:48 +00:00
|
|
|
{#if exercice.solved_time || exercice.tries}
|
2021-08-31 23:47:44 +00:00
|
|
|
<ListGroupItem class="text-warning rounded-0">
|
2021-09-08 01:34:48 +00:00
|
|
|
{#if exercice.tries > 0}{exercice.tries} {exercice.tries==1?"tentative effectuée":"tentatives effectuées"}.{/if}
|
2021-09-01 00:21:49 +00:00
|
|
|
Dernière solution envoyée à <DateFormat date={exercice.solved_time} />.
|
2021-08-30 10:46:18 +00:00
|
|
|
</ListGroupItem>
|
|
|
|
{/if}
|
|
|
|
{#if exercice.solve_dist}
|
2021-08-31 23:47:44 +00:00
|
|
|
<ListGroupItem class="rounded-0">
|
2021-08-30 10:46:18 +00:00
|
|
|
{exercice.solve_dist} {exercice.solve_dist == 1?"réponse erronée":"réponses erronées"}.
|
|
|
|
</ListGroupItem>
|
|
|
|
{/if}
|
|
|
|
{#if exercice.submitted || sberr}
|
2021-08-31 23:47:44 +00:00
|
|
|
<ListGroupItem class="{messageClass} rounded-0">
|
2021-08-30 10:46:18 +00:00
|
|
|
{#if !sberr}
|
|
|
|
<strong>Votre solution a bien été envoyée !</strong>
|
|
|
|
{:else}
|
|
|
|
<strong>{sberr}</strong> {message}
|
|
|
|
{/if}
|
|
|
|
</ListGroupItem>
|
|
|
|
{/if}
|
2021-08-31 00:54:59 +00:00
|
|
|
{#if timeouted}
|
2021-08-31 23:47:44 +00:00
|
|
|
<ListGroupItem class="text-danger rounded-0">
|
2021-08-30 10:46:18 +00:00
|
|
|
<strong>Oops</strong>
|
|
|
|
La requête a dépassé le délai d'attente. Vous devriez réessayer dans quelques instant…
|
|
|
|
</ListGroupItem>
|
|
|
|
{/if}
|
|
|
|
</ListGroup>
|
|
|
|
{/if}
|
|
|
|
{#if !exercice.submitted || sberr}
|
|
|
|
<CardBody>
|
|
|
|
<form on:submit|preventDefault={submitFlags}>
|
2021-08-31 00:54:59 +00:00
|
|
|
{#each flags as flag ((flag.type?flag.type:"i") + flag.id)}
|
|
|
|
{#if flag.type == "mcq"}
|
|
|
|
<FlagMCQ
|
|
|
|
exercice_id={exercice.id}
|
|
|
|
{flag}
|
|
|
|
{refresh_my}
|
|
|
|
bind:values={responses.mcqs}
|
|
|
|
bind:justifications={responses.justifications}
|
|
|
|
/>
|
|
|
|
{:else}
|
|
|
|
<FlagKey
|
|
|
|
exercice_id={exercice.id}
|
|
|
|
{flag}
|
|
|
|
{refresh_my}
|
|
|
|
bind:value={responses.flags[flag.id]}
|
|
|
|
/>
|
|
|
|
{/if}
|
|
|
|
{/each}
|
|
|
|
|
2021-08-30 10:46:18 +00:00
|
|
|
<div class="form-group mt-2">
|
|
|
|
<Button
|
|
|
|
type="submit"
|
|
|
|
color="danger"
|
2021-08-31 00:54:59 +00:00
|
|
|
disabled={submitInProgress}
|
2021-08-30 10:46:18 +00:00
|
|
|
>
|
2021-08-31 00:54:59 +00:00
|
|
|
{#if submitInProgress}
|
|
|
|
<Spinner size="sm" class="me-2" />
|
|
|
|
{/if}
|
2021-08-30 10:46:18 +00:00
|
|
|
Soumettre
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
</CardBody>
|
|
|
|
{/if}
|
|
|
|
</Card>
|