Init
This commit is contained in:
commit
d74bf2b6da
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.DS_Store
|
||||
assets/
|
11
.gitlab-ci.yml
Normal file
11
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
image: alpine:latest
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo "Deploying"
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
- main
|
BIN
public/clips/clip_00000.mp3
Normal file
BIN
public/clips/clip_00000.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00001.mp3
Normal file
BIN
public/clips/clip_00001.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00002.mp3
Normal file
BIN
public/clips/clip_00002.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00003.mp3
Normal file
BIN
public/clips/clip_00003.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00004.mp3
Normal file
BIN
public/clips/clip_00004.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00005.mp3
Normal file
BIN
public/clips/clip_00005.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00006.mp3
Normal file
BIN
public/clips/clip_00006.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00007.mp3
Normal file
BIN
public/clips/clip_00007.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00008.mp3
Normal file
BIN
public/clips/clip_00008.mp3
Normal file
Binary file not shown.
BIN
public/clips/clip_00009.mp3
Normal file
BIN
public/clips/clip_00009.mp3
Normal file
Binary file not shown.
1
public/css/bulma.min.css
vendored
Normal file
1
public/css/bulma.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
public/css/main.css
Normal file
8
public/css/main.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
body {
|
||||
counter-reset: section;
|
||||
}
|
||||
|
||||
.question h2::after {
|
||||
counter-increment: section;
|
||||
content: " " counter(section);
|
||||
})
|
27
public/index.html
Normal file
27
public/index.html
Normal file
|
@ -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>
|
67
public/js/main.js
Normal file
67
public/js/main.js
Normal file
|
@ -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(""));
|
4
public/js/strings.js
Normal file
4
public/js/strings.js
Normal file
|
@ -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.'],
|
||||
}
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
srt
|
||||
videogrep
|
1
scripts/cut_video.sh
Normal file
1
scripts/cut_video.sh
Normal file
|
@ -0,0 +1 @@
|
|||
videogrep --export-clips --padding 0.08 --search "." -o public/clips/clip.mp3 -i assets/*.mp4
|
19
scripts/parse_subs.py
Normal file
19
scripts/parse_subs.py
Normal file
|
@ -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 a new issue