This commit is contained in:
Ramiro 2024-04-11 14:05:48 -07:00
commit d74bf2b6da
20 changed files with 142 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.DS_Store
assets/

11
.gitlab-ci.yml Normal file
View 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

Binary file not shown.

BIN
public/clips/clip_00001.mp3 Normal file

Binary file not shown.

BIN
public/clips/clip_00002.mp3 Normal file

Binary file not shown.

BIN
public/clips/clip_00003.mp3 Normal file

Binary file not shown.

BIN
public/clips/clip_00004.mp3 Normal file

Binary file not shown.

BIN
public/clips/clip_00005.mp3 Normal file

Binary file not shown.

BIN
public/clips/clip_00006.mp3 Normal file

Binary file not shown.

BIN
public/clips/clip_00007.mp3 Normal file

Binary file not shown.

BIN
public/clips/clip_00008.mp3 Normal file

Binary file not shown.

BIN
public/clips/clip_00009.mp3 Normal file

Binary file not shown.

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
View File

@ -0,0 +1,8 @@
body {
counter-reset: section;
}
.question h2::after {
counter-increment: section;
content: " " counter(section);
})

27
public/index.html Normal file
View 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
View 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
View 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
View File

@ -0,0 +1,2 @@
srt
videogrep

1
scripts/cut_video.sh Normal file
View 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
View 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)