SeaWolf-AI commited on
Commit
951b106
ยท
verified ยท
1 Parent(s): 8de1f8f

Add the season 2 intro clip, with its credit

Browse files
Files changed (4) hide show
  1. .gitattributes +1 -0
  2. app.py +10 -0
  3. assets/season2-intro.mp4 +3 -0
  4. index.html +33 -0
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ assets/season2-intro.mp4 filter=lfs diff=lfs merge=lfs -text
app.py CHANGED
@@ -243,6 +243,16 @@ def logout():
243
  return r
244
 
245
 
 
 
 
 
 
 
 
 
 
 
246
  @app.get("/api/season")
247
  def season(request: Request):
248
  return seasons.public(seasons.get(request.query_params.get("season")))
 
243
  return r
244
 
245
 
246
+ @app.get("/assets/{name}")
247
+ def asset(name: str):
248
+ """Static files for the page. Names are matched against what is actually on disk, so
249
+ a crafted name cannot walk out of the directory."""
250
+ d = os.path.join(HERE, "assets")
251
+ if name not in set(os.listdir(d) if os.path.isdir(d) else []):
252
+ raise HTTPException(404, "not found")
253
+ return FileResponse(os.path.join(d, name))
254
+
255
+
256
  @app.get("/api/season")
257
  def season(request: Request):
258
  return seasons.public(seasons.get(request.query_params.get("season")))
assets/season2-intro.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d7c030572da28908115be8fbdea9a9abb45e263bc8b60f44fb465e411cf00a46
3
+ size 5885191
index.html CHANGED
@@ -48,6 +48,12 @@
48
  border:1px solid var(--line);border-radius:20px;padding:4px 12px}
49
  .wts b{color:var(--accent)}
50
 
 
 
 
 
 
 
51
  #seasonbar{display:flex;gap:6px;margin-bottom:14px}
52
  #seasonbar button{border:1px solid var(--line);background:#fff;color:var(--muted);
53
  font:inherit;font-size:12.5px;font-weight:700;padding:7px 14px;
@@ -340,6 +346,7 @@
340
  </div>
341
  <div id="authbar"></div>
342
  <div id="langnote"></div>
 
343
  <div id="seasonbar"></div>
344
  <div id="cd"><span class="cdlab" id="cdlab"></span><span class="cdval" id="cdval">&nbsp;</span></div>
345
  <p class="eyebrow">Open Discovery Challenge</p>
@@ -511,6 +518,7 @@ const T = {
511
  },
512
  ov_pred:"์˜ˆ์ธก์น˜", ov_pf:"๋ง๋ผ๋ฆฌ์•„ ํšจ์†Œ", ov_hs:"์‚ฌ๋žŒ ํšจ์†Œ", ov_sel:"์„ ํƒ๋„",
513
  private_note:"์ œ์ถœ์ž๊ฐ€ ๋น„๊ณต๊ฐœ๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค", copy_smiles:"๋ถ„์ž์‹ ๋ณต์‚ฌ",
 
514
  season_soon:"์ค€๋น„์ค‘", season_notopen:"์ด ์‹œ์ฆŒ์€ ์•„์ง ์ ‘์ˆ˜๋ฅผ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฑ„์ ๊ธฐ ๊ฒ€์ฆ์ด ๋๋‚˜๋ฉด ๊ณต์ง€์™€ ํ•จ๊ป˜ ์—ฝ๋‹ˆ๋‹ค.",
515
  cd_label:"์‹œ์ฆŒ #1 ๋งˆ๊ฐ๊นŒ์ง€", cd_day:"์ผ", cd_over_label:"์‹œ์ฆŒ #1 ๋งˆ๊ฐ",
516
  cd_over:"๋งˆ๊ฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค", view_3d:"3D ์ž…์ฒด ๊ตฌ์กฐ๋กœ ๋ณด๊ธฐ",
@@ -793,6 +801,30 @@ const submittedDate = e => {
793
  }).format(new Date(Number(e.submitted_at) * 1000));
794
  };
795
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
796
  function renderSeasonBar(){
797
  if(!SEASONS) return;
798
  const d = t();
@@ -853,6 +885,7 @@ function applyLang(){
853
  }
854
  if(d.prize_amt) $("#prize_amt").firstChild.nodeValue = d.prize_amt + " ";
855
  renderSeasonBar();
 
856
  renderAuth();
857
  tickCountdown();
858
  if(DATA) render();
 
48
  border:1px solid var(--line);border-radius:20px;padding:4px 12px}
49
  .wts b{color:var(--accent)}
50
 
51
+ #intro{margin:0 0 16px;border-radius:14px;overflow:hidden;border:1px solid var(--line);
52
+ background:#0d1420;line-height:0;box-shadow:var(--shadow)}
53
+ #intro:empty{display:none;margin:0;border:0}
54
+ #intro video{width:100%;height:auto;display:block}
55
+ #intro .credit{line-height:1.5;font-size:11px;color:#8ea3c0;background:#0d1420;
56
+ padding:7px 12px;text-align:right}
57
  #seasonbar{display:flex;gap:6px;margin-bottom:14px}
58
  #seasonbar button{border:1px solid var(--line);background:#fff;color:var(--muted);
59
  font:inherit;font-size:12.5px;font-weight:700;padding:7px 14px;
 
346
  </div>
347
  <div id="authbar"></div>
348
  <div id="langnote"></div>
349
+ <div id="intro"></div>
350
  <div id="seasonbar"></div>
351
  <div id="cd"><span class="cdlab" id="cdlab"></span><span class="cdval" id="cdval">&nbsp;</span></div>
352
  <p class="eyebrow">Open Discovery Challenge</p>
 
518
  },
519
  ov_pred:"์˜ˆ์ธก์น˜", ov_pf:"๋ง๋ผ๋ฆฌ์•„ ํšจ์†Œ", ov_hs:"์‚ฌ๋žŒ ํšจ์†Œ", ov_sel:"์„ ํƒ๋„",
520
  private_note:"์ œ์ถœ์ž๊ฐ€ ๋น„๊ณต๊ฐœ๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค", copy_smiles:"๋ถ„์ž์‹ ๋ณต์‚ฌ",
521
+ intro_credit:"์˜์ƒ ์ œ์ž‘ํ•ด์ฃผ์‹  ์นด์นด์˜คํ†ก @๋ฆฌ์นด ๋‹˜์—๊ฒŒ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
522
  season_soon:"์ค€๋น„์ค‘", season_notopen:"์ด ์‹œ์ฆŒ์€ ์•„์ง ์ ‘์ˆ˜๋ฅผ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฑ„์ ๊ธฐ ๊ฒ€์ฆ์ด ๋๋‚˜๋ฉด ๊ณต์ง€์™€ ํ•จ๊ป˜ ์—ฝ๋‹ˆ๋‹ค.",
523
  cd_label:"์‹œ์ฆŒ #1 ๋งˆ๊ฐ๊นŒ์ง€", cd_day:"์ผ", cd_over_label:"์‹œ์ฆŒ #1 ๋งˆ๊ฐ",
524
  cd_over:"๋งˆ๊ฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค", view_3d:"3D ์ž…์ฒด ๊ตฌ์กฐ๋กœ ๋ณด๊ธฐ",
 
801
  }).format(new Date(Number(e.submitted_at) * 1000));
802
  };
803
 
804
+ // Seasons can carry an intro clip. It is written into the page only for the season it
805
+ // belongs to - emptied rather than hidden - so a reader on another season never fetches
806
+ // the file. Muted and inline because autoplay with sound is blocked everywhere; the clip
807
+ // has no audio track, so nothing is lost.
808
+ const SEASON_INTRO = {2: "assets/season2-intro.mp4"};
809
+
810
+ function renderIntro(){
811
+ const src = SEASON_INTRO[SEASON], box = $("#intro");
812
+ // clearing the marker as well as the markup: leaving it set made a return to this
813
+ // season look like "already playing" and the slot stayed empty
814
+ if(!src){ box.innerHTML = ""; delete box.dataset.src; return; }
815
+ const cred = t().intro_credit || "";
816
+ if(box.dataset.src === src && box.querySelector("video")){
817
+ // the clip is already playing; only the wording can have changed, and rewriting the
818
+ // whole block would restart the video every time the language is switched
819
+ const c = box.querySelector(".credit");
820
+ if(c) c.textContent = cred;
821
+ return;
822
+ }
823
+ box.dataset.src = src;
824
+ box.innerHTML = `<video src="${src}" autoplay loop muted playsinline preload="metadata"></video>`
825
+ + (cred ? `<div class="credit">${cred}</div>` : "");
826
+ }
827
+
828
  function renderSeasonBar(){
829
  if(!SEASONS) return;
830
  const d = t();
 
885
  }
886
  if(d.prize_amt) $("#prize_amt").firstChild.nodeValue = d.prize_amt + " ";
887
  renderSeasonBar();
888
+ renderIntro();
889
  renderAuth();
890
  tickCountdown();
891
  if(DATA) render();