Init
This commit is contained in:
commit
d74bf2b6da
|
@ -0,0 +1,2 @@
|
|||
.DS_Store
|
||||
assets/
|
|
@ -0,0 +1,11 @@
|
|||
image: alpine:latest
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo "Deploying"
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- main
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,8 @@
|
|||
body {
|
||||
counter-reset: section;
|
||||
}
|
||||
|
||||
.question h2::after {
|
||||
counter-increment: section;
|
||||
content: " " counter(section);
|
||||
})
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Test</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
||||
<meta content="Test Language Practice" name="application-name" />
|
||||
<meta content="Practice language skills with movies." name="description" />
|
||||
<meta content="movies, subtitles, learning" name="keywords" />
|
||||
<link href="css/bulma.min.css" rel="stylesheet" />
|
||||
<link href="css/main.css" rel="stylesheet" />
|
||||
<script src="js/strings.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section class="hero">
|
||||
<div class="hero-body">
|
||||
<p class="title">Test Language Practice</p>
|
||||
<p class="subtitle">Practice with movies</p>
|
||||
</div>
|
||||
</section>
|
||||
<script src="js/main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,67 @@
|
|||
function shuffle(arr) {
|
||||
return arr.sort(() => Math.random() - 0.5);
|
||||
}
|
||||
|
||||
function createAnswers(lang, rightIndex, answersNum = 4) {
|
||||
let answers = [strings[lang][rightIndex]];
|
||||
|
||||
function addWrongAnswer() {
|
||||
let randomIndex = Math.floor(Math.random() * strings[lang].length),
|
||||
wrongAnswer = strings[lang][randomIndex];
|
||||
return answers.includes(wrongAnswer) ? addWrongAnswer() : wrongAnswer;
|
||||
}
|
||||
|
||||
function createHtml(str, valid) {
|
||||
return `<button class="button is-rounded is-fullwidth my-2" data-valid="${valid}" onclick="solve(this)">
|
||||
${str}
|
||||
</button>`;
|
||||
}
|
||||
for (let i = 0; i < answersNum; i++) {
|
||||
answers.push(addWrongAnswer());
|
||||
}
|
||||
answers = shuffle(answers.map((e, i) => createHtml(e, i == 0)));
|
||||
return `
|
||||
<div>
|
||||
<h3 class="mt-2">Guest <code>${lang}</code> language:</h3>
|
||||
<div class="answers">
|
||||
${answers.join("")}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function solve(btn) {
|
||||
if (btn.classList.length == 4) {
|
||||
let valid = btn.dataset.valid == "true",
|
||||
element = btn.parentElement.firstElementChild,
|
||||
unwantedEls = [];
|
||||
valid ? btn.classList.add("is-success") : btn.classList.add("is-danger");
|
||||
while (element) {
|
||||
if (element != btn) {
|
||||
element.dataset.valid == "true" ? element.classList.add("is-info") : unwantedEls.push(element);
|
||||
}
|
||||
element = element.nextElementSibling;
|
||||
}
|
||||
for (unwanted of unwantedEls) {
|
||||
unwanted.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var questions = [];
|
||||
for (let i = 0; i < strings.original.length; i++) {
|
||||
let audio = `clips/clip_${('00000'+i).slice(-5)}.mp3`,
|
||||
question = "";
|
||||
for (let key of Object.keys(strings)) {
|
||||
let answers = createAnswers(key, i);
|
||||
question = key == "original" ? answers + question : question + answers;
|
||||
}
|
||||
questions.push(`
|
||||
<div class="container mb-4 question">
|
||||
<h2>Question</h2>
|
||||
<audio controls>
|
||||
<source src="${audio}" type="audio/mp4">
|
||||
</audio>
|
||||
${question}
|
||||
</div>`);
|
||||
}
|
||||
document.body.insertAdjacentHTML("beforeend", shuffle(questions).join(""));
|
|
@ -0,0 +1,4 @@
|
|||
const strings = {
|
||||
original: ['A pile of organs without the spark of self from a brain...', 'or the pump of blood from a heart.', "Just a butcher's tray for a Sunday lunch.", 'Now, who would like to reconstruct the organs?', 'And who can tell human from animal, if there is a difference?', 'Come, come.', 'You did puzzles as children, did you not?', "Is it just me, or is it devilishly hard to concentrate when the monster's talking?", 'He is an extraordinary surgeon.', 'His research is groundbreaking. His father founded this place.'],
|
||||
es: ['Un cúmulo de órganos sin la chispa del yo de un cerebro...', 'o el bombeo de sangre de un corazón.', 'Es una bandeja de carnicero para un almuerzo dominical.', 'Bueno, ¿a quién le gustaría reconstruir los órganos?', '¿Y quién puede distinguir lo humano de lo animal, si hay alguna diferencia?', 'Vamos.', 'Armaban rompecabezas cuando eran niños, ¿no?', 'Me parece a mí, ¿o es muy difícil concentrarse cuando habla el monstruo?', 'Es un cirujano extraordinario.', 'Su investigación es innovadora. Su padre fundó este lugar.'],
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
srt
|
||||
videogrep
|
|
@ -0,0 +1 @@
|
|||
videogrep --export-clips --padding 0.08 --search "." -o public/clips/clip.mp3 -i assets/*.mp4
|
|
@ -0,0 +1,19 @@
|
|||
import re
|
||||
import srt
|
||||
from pathlib import Path
|
||||
|
||||
root = Path(__file__).parent.parent
|
||||
paths = (root / "assets").glob("*.srt")
|
||||
text = ""
|
||||
|
||||
for path in paths:
|
||||
strs = []
|
||||
lang = "original" if len(path.suffixes) == 1 else path.suffixes[0][1:]
|
||||
subs = srt.parse(path.read_text())
|
||||
for sub in subs:
|
||||
strs.append(re.sub(r"<[^>]+?>", "", re.sub(r"\s+", " ", sub.content)))
|
||||
text += " %s: %s,\n" % (lang, str(strs))
|
||||
|
||||
text = "const strings = {\n%s}\n" % text
|
||||
Path(root / "public" / "js" / "strings.js").write_text(text)
|
||||
|
Loading…
Reference in New Issue