xvai-loi 0.1.78 → 0.1.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/co.txt +1 -1
  2. package/package.json +1 -1
  3. package/xvai-loi.js +138 -85
package/co.txt CHANGED
@@ -1 +1 @@
1
- xvaiLoi112357
1
+ xvaiLoi120014
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xvai-loi",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
4
4
  "description": "Loi dung video (Edit Video Tu Dong) nap vao tool Google Flow qua o cam engine/oCam.ts",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
package/xvai-loi.js CHANGED
@@ -9681,6 +9681,91 @@ function moNhanh(g, W4, H2, ve, r, them = "") {
9681
9681
  g.restore();
9682
9682
  }
9683
9683
 
9684
+ // flow-src/engine/khuon.ts
9685
+ var KHUON_TOPN = {
9686
+ ten: "Top N chi\u1EC1u s\xE2u (Captions)",
9687
+ tram: { phut: 18.3, tyLe: 0.7, phan: [0.83, 0.81, 0.46], daiTV: 2.1, video: 0.33, nhanVat: ["Vietnamese people in a real everyday setting.", "Close-up of an object, hands or a place that shows the idea, no faces."] },
9688
+ // cảnh trám / phút, % thời lượng, 3 phần đầu/giữa/cuối, độ dài trung vị (s), tỉ lệ clip động; nhanVat: xen kẽ ảnh có người / cận vật-tay-nơi (đối thủ trộn web, stock, 3D — B06-1027: toàn ảnh người → 'không thấy mặt' 12 % < 15)
9689
+ chu: { phut: [8, 18], caoMin: 0.042 },
9690
+ // caoMin: nét chữ nhấn (kể cả dấu) / H — đối thủ trung vị 0,042 (đo tay 23 dòng); chữ bị ép ngang thấp hơn → 2 dòng
9691
+ icon: { phut: 11.5 },
9692
+ cat: { moi10s: [4, 6], manhNguoi: 1.2, heChu: 0 },
9693
+ // manhNguoi: mẩu người nói kẹp giữa 2 cảnh ngắn hơn thì lấp (trước 0,6 — VD-236); heChu: khe giữa 2 cảnh liền cùng có chữ (trước 0,06 → chớp 2 khung người nói = 2 cú cắt thừa; bàn thử 13 video 12/10 00:0x: 0,06 → 0 cắt TB 5,44 → 4,39/10 s, chồng chữ 0/13 — cảnh trước đã hết theo giờ PHIM nhờ bT)
9694
+ nguoi: { phongToiDa: 1.8, matToiDa: 0.55 },
9695
+ // matToiDa: hộp đầu (tóc→cằm) cao hơn 0,55 H thì KHÔNG dùng ô người / chia (không vừa ô) // MỌI ô người (PIP, thẻ, chia) phóng khung gốc tối đa 1,8× (độ nét) — trước: PIP 1,6, thẻ 1,3 (B05-1027: thẻ hiện cả người nhỏ)
9696
+ lietKe: { xenKe: 2 },
9697
+ // video liệt kê: cứ thẻ bước thứ 2 → ảnh toàn khung + tiêu đề (đối thủ đổi kiểu, không lặp 1 khuôn thẻ)
9698
+ soTrenAnh: { phanDau: 1 / 3, toiDa: 2 },
9699
+ // cảnh CON SỐ ở 1/3 đầu → số đè lên ẢNH minh hoạ (đối thủ 1/3 đầu 83 % trám; số trên người nói không tính trám)
9700
+ bien: { dau: 1.5, cuoi: 2.5, ctaAnh: true }
9701
+ // không đặt ảnh trám ở 1,5 s đầu (móc; bàn thử 13 video: 3 → 1,5 s nâng 1/3 đầu T2 63→87, B05 23→42, B08 25→45, không video nào tụt) và 2,5 s cuối; vùng CTA VẪN có ảnh (đối thủ CTA 8,7 s vẫn trám)
9702
+ };
9703
+ var HU3 = /^(và|với|là|thì|mà|nhưng|rồi|cái|những|các|một|này|đó|chúng|ta|tôi|mình|bạn|em|anh|chị|của|cho|để|nên|vì|cũng|đã|đang|sẽ|có|không|được|rất|ạ|nhé|nha|à|ơi|lại|ra|vào|đi|nó|họ|hãy|chỉ|cần|phải|mới|khi|nếu|vậy|thế|như|từ|trong|về|bị|hết|luôn|sau|trước)$/i;
9704
+ var sach2 = (x) => String(x || "").replace(/[.,!?;:…"“”]/g, "");
9705
+ function lapAnhTheoKhuon(kb, ws, K = KHUON_TOPN, toiDa = 12) {
9706
+ const W4 = (ws || []).filter((w) => w && w.text && w.t1 > w.t0);
9707
+ if (!kb || !Array.isArray(kb.canh) || W4.length < 20) return 0;
9708
+ const lo = (x) => String(x || "").toLocaleLowerCase("vi").replace(/[^\p{L}\p{N}\s]/gu, "").trim(), wl = W4.map((w) => lo(w.text));
9709
+ const timTu = (tu) => {
9710
+ const q = lo(tu).split(/\s+/).filter(Boolean).slice(0, 3);
9711
+ if (!q.length) return -1;
9712
+ for (let i = 0; i + q.length <= wl.length; i++) {
9713
+ let ok = true;
9714
+ for (let j = 0; j < q.length; j++) if (wl[i + j] !== q[j]) {
9715
+ ok = false;
9716
+ break;
9717
+ }
9718
+ if (ok) return i;
9719
+ }
9720
+ return -1;
9721
+ };
9722
+ const g = 60 / K.tram.phut, t0 = W4[0].t0 + K.bien.dau, t1 = W4[W4.length - 1].t1 - K.bien.cuoi;
9723
+ {
9724
+ let doi = 0;
9725
+ const tDau = t0 + (t1 - t0) * K.soTrenAnh.phanDau;
9726
+ for (const c of kb.canh) {
9727
+ if (doi >= K.soTrenAnh.toiDa || !c || c.kieu !== "so" || !c.tu) continue;
9728
+ const i = timTu(c.tu);
9729
+ if (i < 0 || W4[i].t0 < t0 || W4[i].t0 > tDau) continue;
9730
+ const cau = W4.slice(Math.max(0, i - 5), i + 10).map((w) => w.text).join(" ");
9731
+ c.kieu = "anh";
9732
+ c.soAnh = 1;
9733
+ c.en = 'Cinematic photorealistic vertical photo that illustrates the meaning of this Vietnamese sentence: "' + cau + '". ' + K.tram.nhanVat[doi % 2] + " Natural light, no text, no captions.";
9734
+ doi++;
9735
+ }
9736
+ }
9737
+ const moc = kb.canh.filter(
9738
+ (c) => c && c.tu && /^(anh|ds)$/.test(String(c.kieu))
9739
+ /* 'so' vẽ thành chữ to trên người / ô tròn (cut/tron) — không phải trám */
9740
+ ).map((c) => timTu(c.tu)).filter((i) => i >= 0).map((i) => W4[i].t0).filter((t) => t > t0 && t < t1).sort((a, b) => a - b);
9741
+ let noi2 = 0;
9742
+ for (let i = 0; i < W4.length; i++) {
9743
+ if (W4[i].t0 < t0 || W4[i].t1 > t1) continue;
9744
+ noi2 += W4[i].t1 - W4[i].t0 + (i + 1 < W4.length ? Math.min(0.4, Math.max(0, W4[i + 1].t0 - W4[i].t1)) : 0);
9745
+ }
9746
+ const mocDu = kb.canh.filter((c) => c && c.tu && /^(anh|ds|vat)$/.test(String(c.kieu))).map((c) => timTu(c.tu)).filter((i) => i >= 0 && W4[i].t0 > t0 && W4[i].t0 < t1).length;
9747
+ if (mocDu / Math.max(1e-6, noi2 / 60) >= 0.9 * K.tram.phut) return 0;
9748
+ const pts = [t0, ...moc, t1];
9749
+ let them = 0;
9750
+ for (let k = 0; k + 1 < pts.length && them < toiDa; k++) {
9751
+ const a0 = pts[k], b0 = pts[k + 1];
9752
+ if (b0 - a0 < 1.6 * g) continue;
9753
+ const n = Math.max(1, Math.round((b0 - a0) / g) - 1);
9754
+ for (let m = 1; m <= n && them < toiDa; m++) {
9755
+ const tm = a0 + (b0 - a0) * m / (n + 1), i0 = W4.findIndex((w) => w.t0 >= tm);
9756
+ if (i0 < 0) continue;
9757
+ const nd = [];
9758
+ for (let i2 = i0; i2 < Math.min(W4.length, i0 + 8) && nd.length < 3; i2++) if (!HU3.test(sach2(W4[i2].text))) nd.push(i2);
9759
+ if (nd.length < 2) continue;
9760
+ const i = nd[0], tu = W4.slice(i, i + 3).map((w) => sach2(w.text)).join(" "), cau = W4.slice(Math.max(0, i - 5), i + 10).map((w) => w.text).join(" ");
9761
+ if (timTu(tu) !== i) continue;
9762
+ kb.canh.push({ tu, kieu: "anh", chu: " ", chu2: "", khuon: 1, en: 'Cinematic photorealistic vertical photo that illustrates the meaning of this Vietnamese sentence: "' + cau + '". ' + (them % 2 ? K.tram.nhanVat[1] : K.tram.nhanVat[0]) + " Natural light, no text, no captions." });
9763
+ them++;
9764
+ }
9765
+ }
9766
+ return them;
9767
+ }
9768
+
9684
9769
  // flow-src/engine/boCuc.ts
9685
9770
  var BC = {
9686
9771
  tren: 0.1,
@@ -9782,7 +9867,7 @@ function datKhoiChu(g, kc, coThanh, coTach, vungTruoc, choThu = false, WH = 9 /
9782
9867
  }
9783
9868
  const yc = y0 + h / 2, vung2 = !mat ? "tu-do" : hop4[3] <= dinh ? "tren-dau" : lop === "sau" ? "sau-dau" : hop4[2] < mat[0] || hop4[0] > mat[2] ? cx < tam2 ? "canh-trai" : "canh-phai" : yc > 0.6 ? "duoi" : "nguc";
9784
9869
  const uu = { "tren-dau": 0, "sau-dau": 0.12, "canh-trai": 0.1, "canh-phai": 0.1, nguc: 0.22, duoi: 0.3, "tu-do": 0.1 };
9785
- const diem2 = 100 * (1 - (uu[vung2] ?? 0.2)) * (0.35 + 0.65 * k) - 25 * (lop === "truoc" ? Math.max(0, p - 0.6) : p);
9870
+ const diem2 = (100 * (1 - (uu[vung2] ?? 0.2)) * (0.35 + 0.65 * k) - 25 * (lop === "truoc" ? Math.max(0, p - 0.6) : p)) * (kc.px && 0.92 * kc.px * k < KHUON_TOPN.chu.caoMin ? 0.6 : 1);
9786
9871
  ung.push({ x: cx, y: yc, k, lop, vung: vung2, diem: diem2 });
9787
9872
  };
9788
9873
  for (let k = 1; k >= BC.kMin - 1e-6; k -= 0.05) for (let y0 = top; y0 <= BC.duoi; y0 += 0.01) {
@@ -9817,88 +9902,6 @@ function datKhoiChu(g, kc, coThanh, coTach, vungTruoc, choThu = false, WH = 9 /
9817
9902
  return ra;
9818
9903
  }
9819
9904
 
9820
- // flow-src/engine/khuon.ts
9821
- var KHUON_TOPN = {
9822
- ten: "Top N chi\u1EC1u s\xE2u (Captions)",
9823
- tram: { phut: 18.3, tyLe: 0.7, phan: [0.83, 0.81, 0.46], daiTV: 2.1, video: 0.33, nhanVat: ["Vietnamese people in a real everyday setting.", "Close-up of an object, hands or a place that shows the idea, no faces."] },
9824
- // cảnh trám / phút, % thời lượng, 3 phần đầu/giữa/cuối, độ dài trung vị (s), tỉ lệ clip động; nhanVat: xen kẽ ảnh có người / cận vật-tay-nơi (đối thủ trộn web, stock, 3D — B06-1027: toàn ảnh người → 'không thấy mặt' 12 % < 15)
9825
- chu: { phut: [8, 18], caoMin: 0.042 },
9826
- // caoMin: nét chữ nhấn (kể cả dấu) / H — đối thủ trung vị 0,042 (đo tay 23 dòng); chữ bị ép ngang thấp hơn → 2 dòng icon: { phut: 11.5 }, cat: { moi10s: [4, 6], manhNguoi: 1.2, heChu: 0 }, // manhNguoi: mẩu người nói kẹp giữa 2 cảnh ngắn hơn thì lấp (trước 0,6 — VD-236); heChu: khe giữa 2 cảnh liền cùng có chữ (trước 0,06 → chớp 2 khung người nói = 2 cú cắt thừa; bàn thử 13 video 12/10 00:0x: 0,06 → 0 cắt TB 5,44 → 4,39/10 s, chồng chữ 0/13 — cảnh trước đã hết theo giờ PHIM nhờ bT)
9827
- nguoi: { phongToiDa: 1.8, matToiDa: 0.55 },
9828
- // matToiDa: hộp đầu (tóc→cằm) cao hơn 0,55 H thì KHÔNG dùng ô người / chia (không vừa ô) // MỌI ô người (PIP, thẻ, chia) phóng khung gốc tối đa 1,8× (độ nét) — trước: PIP 1,6, thẻ 1,3 (B05-1027: thẻ hiện cả người nhỏ)
9829
- lietKe: { xenKe: 2 },
9830
- // video liệt kê: cứ thẻ bước thứ 2 → ảnh toàn khung + tiêu đề (đối thủ đổi kiểu, không lặp 1 khuôn thẻ)
9831
- soTrenAnh: { phanDau: 1 / 3, toiDa: 2 },
9832
- // cảnh CON SỐ ở 1/3 đầu → số đè lên ẢNH minh hoạ (đối thủ 1/3 đầu 83 % trám; số trên người nói không tính trám)
9833
- bien: { dau: 1.5, cuoi: 2.5, ctaAnh: true }
9834
- // không đặt ảnh trám ở 1,5 s đầu (móc; bàn thử 13 video: 3 → 1,5 s nâng 1/3 đầu T2 63→87, B05 23→42, B08 25→45, không video nào tụt) và 2,5 s cuối; vùng CTA VẪN có ảnh (đối thủ CTA 8,7 s vẫn trám)
9835
- };
9836
- var HU3 = /^(và|với|là|thì|mà|nhưng|rồi|cái|những|các|một|này|đó|chúng|ta|tôi|mình|bạn|em|anh|chị|của|cho|để|nên|vì|cũng|đã|đang|sẽ|có|không|được|rất|ạ|nhé|nha|à|ơi|lại|ra|vào|đi|nó|họ|hãy|chỉ|cần|phải|mới|khi|nếu|vậy|thế|như|từ|trong|về|bị|hết|luôn|sau|trước)$/i;
9837
- var sach2 = (x) => String(x || "").replace(/[.,!?;:…"“”]/g, "");
9838
- function lapAnhTheoKhuon(kb, ws, K = KHUON_TOPN, toiDa = 12) {
9839
- const W4 = (ws || []).filter((w) => w && w.text && w.t1 > w.t0);
9840
- if (!kb || !Array.isArray(kb.canh) || W4.length < 20) return 0;
9841
- const lo = (x) => String(x || "").toLocaleLowerCase("vi").replace(/[^\p{L}\p{N}\s]/gu, "").trim(), wl = W4.map((w) => lo(w.text));
9842
- const timTu = (tu) => {
9843
- const q = lo(tu).split(/\s+/).filter(Boolean).slice(0, 3);
9844
- if (!q.length) return -1;
9845
- for (let i = 0; i + q.length <= wl.length; i++) {
9846
- let ok = true;
9847
- for (let j = 0; j < q.length; j++) if (wl[i + j] !== q[j]) {
9848
- ok = false;
9849
- break;
9850
- }
9851
- if (ok) return i;
9852
- }
9853
- return -1;
9854
- };
9855
- const g = 60 / K.tram.phut, t0 = W4[0].t0 + K.bien.dau, t1 = W4[W4.length - 1].t1 - K.bien.cuoi;
9856
- {
9857
- let doi = 0;
9858
- const tDau = t0 + (t1 - t0) * K.soTrenAnh.phanDau;
9859
- for (const c of kb.canh) {
9860
- if (doi >= K.soTrenAnh.toiDa || !c || c.kieu !== "so" || !c.tu) continue;
9861
- const i = timTu(c.tu);
9862
- if (i < 0 || W4[i].t0 < t0 || W4[i].t0 > tDau) continue;
9863
- const cau = W4.slice(Math.max(0, i - 5), i + 10).map((w) => w.text).join(" ");
9864
- c.kieu = "anh";
9865
- c.soAnh = 1;
9866
- c.en = 'Cinematic photorealistic vertical photo that illustrates the meaning of this Vietnamese sentence: "' + cau + '". ' + K.tram.nhanVat[doi % 2] + " Natural light, no text, no captions.";
9867
- doi++;
9868
- }
9869
- }
9870
- const moc = kb.canh.filter(
9871
- (c) => c && c.tu && /^(anh|ds)$/.test(String(c.kieu))
9872
- /* 'so' vẽ thành chữ to trên người / ô tròn (cut/tron) — không phải trám */
9873
- ).map((c) => timTu(c.tu)).filter((i) => i >= 0).map((i) => W4[i].t0).filter((t) => t > t0 && t < t1).sort((a, b) => a - b);
9874
- let noi2 = 0;
9875
- for (let i = 0; i < W4.length; i++) {
9876
- if (W4[i].t0 < t0 || W4[i].t1 > t1) continue;
9877
- noi2 += W4[i].t1 - W4[i].t0 + (i + 1 < W4.length ? Math.min(0.4, Math.max(0, W4[i + 1].t0 - W4[i].t1)) : 0);
9878
- }
9879
- const mocDu = kb.canh.filter((c) => c && c.tu && /^(anh|ds|vat)$/.test(String(c.kieu))).map((c) => timTu(c.tu)).filter((i) => i >= 0 && W4[i].t0 > t0 && W4[i].t0 < t1).length;
9880
- if (mocDu / Math.max(1e-6, noi2 / 60) >= 0.9 * K.tram.phut) return 0;
9881
- const pts = [t0, ...moc, t1];
9882
- let them = 0;
9883
- for (let k = 0; k + 1 < pts.length && them < toiDa; k++) {
9884
- const a0 = pts[k], b0 = pts[k + 1];
9885
- if (b0 - a0 < 1.6 * g) continue;
9886
- const n = Math.max(1, Math.round((b0 - a0) / g) - 1);
9887
- for (let m = 1; m <= n && them < toiDa; m++) {
9888
- const tm = a0 + (b0 - a0) * m / (n + 1), i0 = W4.findIndex((w) => w.t0 >= tm);
9889
- if (i0 < 0) continue;
9890
- const nd = [];
9891
- for (let i2 = i0; i2 < Math.min(W4.length, i0 + 8) && nd.length < 3; i2++) if (!HU3.test(sach2(W4[i2].text))) nd.push(i2);
9892
- if (nd.length < 2) continue;
9893
- const i = nd[0], tu = W4.slice(i, i + 3).map((w) => sach2(w.text)).join(" "), cau = W4.slice(Math.max(0, i - 5), i + 10).map((w) => w.text).join(" ");
9894
- if (timTu(tu) !== i) continue;
9895
- kb.canh.push({ tu, kieu: "anh", chu: " ", chu2: "", khuon: 1, en: 'Cinematic photorealistic vertical photo that illustrates the meaning of this Vietnamese sentence: "' + cau + '". ' + (them % 2 ? K.tram.nhanVat[1] : K.tram.nhanVat[0]) + " Natural light, no text, no captions." });
9896
- them++;
9897
- }
9898
- }
9899
- return them;
9900
- }
9901
-
9902
9905
  // flow-src/engine/veCuongMe.ts
9903
9906
  var luoiAnhCache = /* @__PURE__ */ new Map();
9904
9907
  var matAnhCache = /* @__PURE__ */ new Map();
@@ -10268,7 +10271,7 @@ function datChuNhan(g, W4, H2, F, giant, chu22, pxG, pxC, kieuG, maxW, tren = 0.
10268
10271
  g.restore();
10269
10272
  return w;
10270
10273
  })));
10271
- return { nd, c: datKhoiChu(nc, { h: nd / H2, w: wb / W4 }, tren >= 0.1, coTach, vungCu, choThu, W4 / H2) };
10274
+ return { nd, c: datKhoiChu(nc, { h: nd / H2, w: wb / W4, px: aa2.px / H2 }, tren >= 0.1, coTach, vungCu, choThu, W4 / H2) };
10272
10275
  };
10273
10276
  let A2 = thu2(a, giant), txtA = giant, aa = a;
10274
10277
  if (String(giant || "").indexOf(String.fromCharCode(10)) >= 0 && A2.c.k < 0.85) {
@@ -10279,6 +10282,32 @@ function datChuNhan(g, W4, H2, F, giant, chu22, pxG, pxC, kieuG, maxW, tren = 0.
10279
10282
  aa = a1;
10280
10283
  }
10281
10284
  }
10285
+ {
10286
+ const ws3 = String(txtA || "").split(/\s+/).filter(Boolean);
10287
+ if (0.92 * aa.px * A2.c.k / H2 < KHUON_TOPN.chu.caoMin && ws3.length >= 4) {
10288
+ g.save();
10289
+ g.font = "900 " + pxG.toFixed(1) + "px " + FBc;
10290
+ const tw = (x) => g.measureText(x).width, mt = tw(ws3.join(" ")) / 3, d3 = [];
10291
+ let cur = "";
10292
+ for (const w of ws3) {
10293
+ const nx = cur ? cur + " " + w : w;
10294
+ if (cur && tw(nx) > mt * 1.15 && d3.length < 2) {
10295
+ d3.push(cur);
10296
+ cur = w;
10297
+ } else cur = nx;
10298
+ }
10299
+ d3.push(cur);
10300
+ g.restore();
10301
+ if (d3.length === 3) {
10302
+ const g3 = d3.join(String.fromCharCode(10)), a3 = do1(g3, pxG, kieuG), B3 = thu2(a3, g3);
10303
+ if (B3.c.k * a3.px > A2.c.k * aa.px * 1.05) {
10304
+ A2 = B3;
10305
+ txtA = g3;
10306
+ aa = a3;
10307
+ }
10308
+ }
10309
+ }
10310
+ }
10282
10311
  const c = A2.c, k2 = c.k, hG2 = aa.h * k2, hC2 = b.h * k2, y02 = c.y * H2 - A2.nd * k2 / 2;
10283
10312
  if (k2 <= 0) return ghiCho({ yG: 0.5, yC: 0.5, pxG: 0.01, pxC: 0.01, truoc: true, txt: " ", vung: c.vung });
10284
10313
  vungCu = { x: c.x, y: c.y };
@@ -12974,6 +13003,30 @@ function lapCuongMe(o) {
12974
13003
  });
12975
13004
  }
12976
13005
  }
13006
+ {
13007
+ const coC = (x) => x.bo !== "phong" && !!String(x.giant || x.chu || x.tieu || "").trim(), C2 = sp.filter(coC).sort((p, q) => p.f - q.f), tran = Math.floor(0.9 * KHUON_TOPN.chu.phut[1] * tong / 60);
13008
+ let nT = 0;
13009
+ while (C2.length > tran) {
13010
+ let j = -1, m = 1e9;
13011
+ for (let k = 0; k < C2.length; k++) {
13012
+ const x = C2[k];
13013
+ if (x.bo !== "anh" || x.f < 3 || x.khoa) continue;
13014
+ const g = Math.min(k > 0 ? x.f - C2[k - 1].f : 1e9, k + 1 < C2.length ? C2[k + 1].f - x.f : 1e9);
13015
+ if (g < m) {
13016
+ m = g;
13017
+ j = k;
13018
+ }
13019
+ }
13020
+ if (j < 0) break;
13021
+ ghiL("doi", C2[j], "khuon chu.phut: bo chu " + String(C2[j].chu || C2[j].giant || "").slice(0, 20));
13022
+ C2[j].chu = "";
13023
+ C2[j].chu2 = "";
13024
+ C2[j].giant = "";
13025
+ C2.splice(j, 1);
13026
+ nT++;
13027
+ }
13028
+ G4.__tiaChu = nT;
13029
+ }
12977
13030
  G4.__lichSp = sp.map((s, i) => ({ i, id: s.id, yChu: s.yChu, coChu: s.coChu, fx: s.fx, stX: s.stX, stY: s.stY, f: +s.f.toFixed(2), d: +s.d.toFixed(2), bo: s.bo, giant: s.giant || "", chu: s.chu || "", chu2: s.chu2 || "", st: s.st || "", ten: s.ten || "", tieu: s.tieu || "", khoa: s.khoa ? 1 : 0 }));
12978
13031
  }
12979
13032
  const thanhO = (t) => coBuoc && t >= f1 - 0.1 && t < hetMuc;
@@ -20860,7 +20913,7 @@ function datCauLenh(a) {
20860
20913
  on2 = true;
20861
20914
  window.addEventListener("message", async (ev) => {
20862
20915
  const d = ev.data;
20863
- if (!d || d.xvaiLoi112357 !== true) return;
20916
+ if (!d || d.xvaiLoi120014 !== true) return;
20864
20917
  const o = String(ev.origin || "");
20865
20918
  if (!(o.indexOf("https://flow.google.com") === 0 || o.indexOf("https://labs.google") === 0)) return;
20866
20919
  const tra = (kq) => {