Spaces:
Sleeping
Sleeping
Upload 125 files
Browse files- engine/__pycache__/router.cpython-314.pyc +0 -0
- engine/router.py +3 -1
- web/index.html +44 -35
engine/__pycache__/router.cpython-314.pyc
CHANGED
|
Binary files a/engine/__pycache__/router.cpython-314.pyc and b/engine/__pycache__/router.cpython-314.pyc differ
|
|
|
engine/router.py
CHANGED
|
@@ -270,7 +270,9 @@ async def meta():
|
|
| 270 |
# ββ μ μ νλ‘ νΈ βββββββββββββββββββββββββββββββββββββββββββββ
|
| 271 |
@app.get("/")
|
| 272 |
async def index():
|
| 273 |
-
|
|
|
|
|
|
|
| 274 |
|
| 275 |
|
| 276 |
app.mount("/static", StaticFiles(directory=ROOT / "web"), name="static")
|
|
|
|
| 270 |
# ββ μ μ νλ‘ νΈ βββββββββββββββββββββββββββββββββββββββββββββ
|
| 271 |
@app.get("/")
|
| 272 |
async def index():
|
| 273 |
+
# no-cache: λ§€ μ μλ§λ€ μ¬κ²μ¦ β λ°°ν¬ ν λΈλΌμ°μ κ° μ HTMLμ κ³μ 보μ¬μ£Όλ μ¬κ³ λ°©μ§
|
| 274 |
+
return FileResponse(ROOT / "web" / "index.html",
|
| 275 |
+
headers={"Cache-Control": "no-cache"})
|
| 276 |
|
| 277 |
|
| 278 |
app.mount("/static", StaticFiles(directory=ROOT / "web"), name="static")
|
web/index.html
CHANGED
|
@@ -69,10 +69,6 @@
|
|
| 69 |
.vn-stage::after { content: ""; position: absolute; inset: 0;
|
| 70 |
background: linear-gradient(rgba(11,14,20,.12) 0%, transparent 22%,
|
| 71 |
transparent 40%, rgba(11,14,20,.96) 82%); }
|
| 72 |
-
.vn-lead { position: absolute; top: 0; left: 0; right: 0; z-index: 1;
|
| 73 |
-
padding: 16px 22px 26px; font-size: .96rem; color: var(--text);
|
| 74 |
-
word-break: keep-all; text-shadow: 0 1px 8px rgba(0,0,0,.95);
|
| 75 |
-
background: linear-gradient(rgba(11,14,20,.82), transparent); }
|
| 76 |
.vn-stage-panel { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
|
| 77 |
padding: 0 22px 20px; text-align: center; }
|
| 78 |
.vn-stage-panel .vn-line { font-size: 1.02rem; line-height: 1.9; margin: .3em 0;
|
|
@@ -347,11 +343,10 @@ function charLines(g) { // μμ¬ μ λ°ν β μ’ νμλͺ
Β·
|
|
| 347 |
`<div class="char-line fade"><span class="spk">${esc(name)}</span>β${esc(t)}β</div>`).join('');
|
| 348 |
}
|
| 349 |
|
| 350 |
-
function vnStage(g, choices
|
| 351 |
let h = `<div class="vn-stage fade">` +
|
| 352 |
-
`<img class="vn-stage-art" src="${encodeURI(g.portrait)}" alt="${esc(g.spk)}">`
|
| 353 |
-
|
| 354 |
-
h += `<div class="vn-stage-panel"><div class="vn-name">${esc(g.spk)}</div>`;
|
| 355 |
for (const t of g.lines) h += `<div class="vn-line">β${esc(t)}β</div>`;
|
| 356 |
return h + `<div id="choice-area">${choices}</div></div></div>`;
|
| 357 |
}
|
|
@@ -377,9 +372,9 @@ function groupNarration(blocks) {
|
|
| 377 |
|
| 378 |
/* μλ² νμ΄μ§ β νλ©΄λ€ (μ€ν¬λ‘€ μλ λκΉ).
|
| 379 |
- νμ΄νμ μνΌμλ 첫 νμ΄μ§μ ν(θ©±) ν€λλ§ β μΉ΄λ μμ λͺ©μ νμνμ§ μλλ€ (μ±
μ νλ¦)
|
| 380 |
-
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
function buildScreens(step, fresh) {
|
| 384 |
const c = step.card;
|
| 385 |
let head = '';
|
|
@@ -396,42 +391,56 @@ function buildScreens(step, fresh) {
|
|
| 396 |
if (g.lines && g.portrait && !PLAYER_SPEAKERS.has(g.spk)) { stageIdx = k; break; }
|
| 397 |
}
|
| 398 |
}
|
|
|
|
| 399 |
|
| 400 |
const meas = $('page-measure');
|
| 401 |
const budget = Math.max((window.innerHeight || 900) - 190, 320);
|
|
|
|
|
|
|
| 402 |
const screens = [];
|
| 403 |
-
let
|
| 404 |
-
const
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 413 |
groups.forEach((g, k) => {
|
| 414 |
-
if (k ===
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
screens.push(vnStage(g, stageIsLast ? choices : '',
|
| 418 |
-
leadIdx >= 0 ? groups[leadIdx].block.text : null));
|
| 419 |
return;
|
| 420 |
}
|
| 421 |
const html = g.lines ? charLines(g) : block(g.block);
|
| 422 |
-
|
| 423 |
-
if (cur.trim() && meas.offsetHeight > budget) flush();
|
| 424 |
-
cur += html;
|
| 425 |
});
|
| 426 |
-
if (choices && !stageIsLast) {
|
| 427 |
const area = `<div id="choice-area">${choices}</div>`;
|
| 428 |
-
|
| 429 |
-
if (cur.trim() && meas.offsetHeight > budget) flush();
|
| 430 |
-
cur += area;
|
| 431 |
}
|
| 432 |
-
|
| 433 |
meas.innerHTML = '';
|
| 434 |
-
|
|
|
|
|
|
|
|
|
|
| 435 |
}
|
| 436 |
|
| 437 |
function choicesHtml(step) {
|
|
|
|
| 69 |
.vn-stage::after { content: ""; position: absolute; inset: 0;
|
| 70 |
background: linear-gradient(rgba(11,14,20,.12) 0%, transparent 22%,
|
| 71 |
transparent 40%, rgba(11,14,20,.96) 82%); }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
.vn-stage-panel { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
|
| 73 |
padding: 0 22px 20px; text-align: center; }
|
| 74 |
.vn-stage-panel .vn-line { font-size: 1.02rem; line-height: 1.9; margin: .3em 0;
|
|
|
|
| 343 |
`<div class="char-line fade"><span class="spk">${esc(name)}</span>β${esc(t)}β</div>`).join('');
|
| 344 |
}
|
| 345 |
|
| 346 |
+
function vnStage(g, choices) { // λ
립 νλ©΄: μ΄μ + μ΄λ¦ν + κ·Έ μΊλ¦ν°μ λμ¬ (+μ νμ§)λ§
|
| 347 |
let h = `<div class="vn-stage fade">` +
|
| 348 |
+
`<img class="vn-stage-art" src="${encodeURI(g.portrait)}" alt="${esc(g.spk)}">` +
|
| 349 |
+
`<div class="vn-stage-panel"><div class="vn-name">${esc(g.spk)}</div>`;
|
|
|
|
| 350 |
for (const t of g.lines) h += `<div class="vn-line">β${esc(t)}β</div>`;
|
| 351 |
return h + `<div id="choice-area">${choices}</div></div></div>`;
|
| 352 |
}
|
|
|
|
| 372 |
|
| 373 |
/* μλ² νμ΄μ§ β νλ©΄λ€ (μ€ν¬λ‘€ μλ λκΉ).
|
| 374 |
- νμ΄νμ μνΌμλ 첫 νμ΄μ§μ ν(θ©±) ν€λλ§ β μΉ΄λ μμ λͺ©μ νμνμ§ μλλ€ (μ±
μ νλ¦)
|
| 375 |
+
- μ€ν
μ΄μ§(μ΄μ νλ©΄)λ μ΄λ―Έμ§+κ·Έ μΊλ¦ν°μ λμ¬(+μ νμ§)λ§ β μ§λ¬Έμ μμ§ μλλ€
|
| 376 |
+
- μ§λ¬ΈΒ·λ°ν(char-line)λ μΈκ·Έλ¨ΌνΈ(μ€ν
μ΄μ§ κ²½κ³ μ¬μ΄)λ³λ‘ μ€μΈ‘ κ· ν λΆν :
|
| 377 |
+
νλ©΄ μ k = ceil(μ΄λμ΄/μμ°)λ₯Ό λ¨Όμ μ νκ³ κ· λ± κ²½κ³μμ μ λ¨ β ν λ¬Έμ₯ κ³ μ νλ©΄ λ°©μ§ */
|
| 378 |
function buildScreens(step, fresh) {
|
| 379 |
const c = step.card;
|
| 380 |
let head = '';
|
|
|
|
| 391 |
if (g.lines && g.portrait && !PLAYER_SPEAKERS.has(g.spk)) { stageIdx = k; break; }
|
| 392 |
}
|
| 393 |
}
|
| 394 |
+
const stageIsLast = stageIdx === groups.length - 1;
|
| 395 |
|
| 396 |
const meas = $('page-measure');
|
| 397 |
const budget = Math.max((window.innerHeight || 900) - 190, 320);
|
| 398 |
+
const measure = (html) => { meas.innerHTML = html; return meas.offsetHeight; };
|
| 399 |
+
|
| 400 |
const screens = [];
|
| 401 |
+
let seg = []; // νμ¬ μΈκ·Έλ¨ΌνΈμ μ λλ€ {html, h}
|
| 402 |
+
const flushSeg = () => { // μΈκ·Έλ¨ΌνΈλ₯Ό κ· ν λΆν ν΄ νλ©΄μΌλ‘
|
| 403 |
+
if (!seg.length) return;
|
| 404 |
+
const total = seg.reduce((s, u) => s + u.h, 0);
|
| 405 |
+
const k = Math.max(1, Math.ceil(total / budget));
|
| 406 |
+
const target = total / k;
|
| 407 |
+
let cur = '', acc = 0, cuts = 0;
|
| 408 |
+
seg.forEach((u, i) => {
|
| 409 |
+
cur += u.html; acc += u.h;
|
| 410 |
+
const remainUnits = seg.length - i - 1;
|
| 411 |
+
const remainCuts = (k - 1) - cuts;
|
| 412 |
+
if (cuts < k - 1 && remainUnits > 0) {
|
| 413 |
+
const boundary = target * (cuts + 1);
|
| 414 |
+
const nextAcc = acc + seg[i + 1].h;
|
| 415 |
+
if (Math.abs(acc - boundary) <= Math.abs(nextAcc - boundary)
|
| 416 |
+
|| remainUnits === remainCuts) {
|
| 417 |
+
screens.push(cur); cur = ''; cuts++;
|
| 418 |
+
}
|
| 419 |
+
}
|
| 420 |
+
});
|
| 421 |
+
if (cur) screens.push(cur);
|
| 422 |
+
seg = [];
|
| 423 |
+
};
|
| 424 |
+
|
| 425 |
groups.forEach((g, k) => {
|
| 426 |
+
if (k === stageIdx) { // μ€ν
μ΄μ§ = λ
립 νλ©΄ (μ΄λ―Έμ§+λμ¬λ§)
|
| 427 |
+
flushSeg();
|
| 428 |
+
screens.push(vnStage(g, stageIsLast ? choices : ''));
|
|
|
|
|
|
|
| 429 |
return;
|
| 430 |
}
|
| 431 |
const html = g.lines ? charLines(g) : block(g.block);
|
| 432 |
+
seg.push({html, h: measure(html)});
|
|
|
|
|
|
|
| 433 |
});
|
| 434 |
+
if (choices && !stageIsLast) {
|
| 435 |
const area = `<div id="choice-area">${choices}</div>`;
|
| 436 |
+
seg.push({html: area, h: measure(area)});
|
|
|
|
|
|
|
| 437 |
}
|
| 438 |
+
flushSeg();
|
| 439 |
meas.innerHTML = '';
|
| 440 |
+
|
| 441 |
+
if (screens.length) screens[0] = head + screens[0]; // ν(θ©±) ν€λλ 첫 νλ©΄μ
|
| 442 |
+
else screens.push(head);
|
| 443 |
+
return screens;
|
| 444 |
}
|
| 445 |
|
| 446 |
function choicesHtml(step) {
|