bep40 commited on
Commit
dbadb8f
·
1 Parent(s): a32730c

Fix crash vao hang (R3F Gold) + day leo + bang chuyen can dung; cache-bust v8

Browse files
Files changed (2) hide show
  1. patch_3d.mjs +94 -9
  2. patch_backend.mjs +2 -2
patch_3d.mjs CHANGED
@@ -200,11 +200,98 @@ function NatureGround() {
200
  </>
201
  )
202
  }` ],
203
- /* Wire NatureGround vào HomeScene */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  [ ` <CaveExterior />
205
  <group position={layout.stele} rotation-y={layout.steleRotY}>`,
206
  ` <CaveExterior />
207
  <NatureGround />
 
208
  <group position={layout.stele} rotation-y={layout.steleRotY}>` ],
209
  /* Bảng chuyên cần attendance trên bia đá */
210
  [ `/* ---- Camera rig + layout (MA gốc) ---- */`,
@@ -293,8 +380,6 @@ patchFile('frontend/cave3d.js', [
293
  CÚP VÀNG TRUNG TÂM (trophy) — trước vòng huyền thoại, kỷ vật MU
294
  ========================================================================= */
295
  function Trophy() {
296
- const gold = new THREE.MeshStandardMaterial({ color: '#c9a24e', metalness: 0.85, roughness: 0.25 })
297
- const darkGold = new THREE.MeshStandardMaterial({ color: '#8a6a2c', metalness: 0.7, roughness: 0.35 })
298
  return (
299
  <group position={[0, 0, 0]} rotation-y={0.5}>
300
  <mesh position={[0, 0.12, 0]} castShadow>
@@ -303,27 +388,27 @@ function Trophy() {
303
  </mesh>
304
  <mesh position={[0, 0.34, 0]} castShadow>
305
  <cylinderGeometry args={[0.55, 0.7, 0.2, 8]} />
306
- <darkGold />
307
  </mesh>
308
  <mesh position={[0, 0.85, 0]} castShadow>
309
  <cylinderGeometry args={[0.42, 0.5, 0.85, 10]} />
310
- <gold />
311
  </mesh>
312
  <mesh position={[0, 1.32, 0]} castShadow>
313
  <torusGeometry args={[0.5, 0.09, 8, 18]} />
314
- <gold />
315
  </mesh>
316
  <mesh position={[-0.42, 0.85, 0]} rotation-z={0.3}>
317
  <torusGeometry args={[0.26, 0.07, 8, 14, Math.PI]} />
318
- <gold />
319
  </mesh>
320
  <mesh position={[0.42, 0.85, 0]} rotation-z={-0.3}>
321
  <torusGeometry args={[0.26, 0.07, 8, 14, Math.PI]} />
322
- <gold />
323
  </mesh>
324
  <mesh position={[0, 1.62, 0]} castShadow>
325
  <sphereGeometry args={[0.2, 14, 14]} />
326
- <gold />
327
  </mesh>
328
  <pointLight position={[0, 2.6, 0]} color="#ffd76a" intensity={18} distance={9} decay={1.6} />
329
  </group>
 
200
  </>
201
  )
202
  }` ],
203
+ /* Dây leo quanh vòm cửa + bảng chuyên cần đứng — vines/board như gốc */
204
+ [ `function GroundGeom() {`,
205
+ `function Vines() {
206
+ const strands = useMemo(() => {
207
+ const out = []
208
+ const rand = mulberry(13)
209
+ for (let i = 0; i < 26; i++) {
210
+ const a = Math.PI + (i - 13) * 0.12
211
+ const r = 4.9
212
+ const x = Math.sin(a) * r * 1.15 + 1.2, z = Math.cos(a) * r - 1.5
213
+ const len = 1.6 + rand() * 2.2
214
+ out.push({ x, z, len, sway: rand() * Math.PI * 2, leaf: rand() * 5 })
215
+ }
216
+ return out
217
+ }, [])
218
+ return (
219
+ <group>
220
+ {strands.map((v, i) => (
221
+ <group key={i} position={[v.x, 3.4 - v.len / 2, v.z]}>
222
+ <mesh>
223
+ <cylinderGeometry args={[0.035, 0.05, v.len, 4]} />
224
+ <meshLambertMaterial color="#3d5a22" flatShading />
225
+ </mesh>
226
+ <mesh position={[0, -v.len / 2 + 0.1, 0]} rotation-x={0.5}>
227
+ <sphereGeometry args={[0.1, 5, 5]} />
228
+ <meshLambertMaterial color="#4c7a2e" flatShading />
229
+ </mesh>
230
+ </group>
231
+ ))}
232
+ </group>
233
+ )
234
+ }
235
+ function AttendanceBoard() {
236
+ const [rows, setRows] = React.useState(null)
237
+ React.useEffect(() => {
238
+ let alive = true
239
+ fetch('/api/attendance').then(r => r.ok ? r.json() : Promise.reject()).then(d => {
240
+ if (alive && d && d.rows) setRows(d.rows)
241
+ }).catch(() => {
242
+ if (!alive) return
243
+ const r = []
244
+ for (let i = 0; i < 5; i++) {
245
+ const row = []
246
+ for (let j = 0; j < 10; j++) row.push(Math.random() > 0.35 ? { name: '', number: 0 } : null)
247
+ r.push(row)
248
+ }
249
+ setRows(r)
250
+ })
251
+ return () => { alive = false }
252
+ }, [])
253
+ const tex = React.useMemo(() => {
254
+ const c = document.createElement('canvas'); c.width = 640; c.height = 320
255
+ const g = c.getContext('2d')
256
+ g.fillStyle = '#7a5f42'; g.fillRect(0, 0, 640, 320)
257
+ g.strokeStyle = '#4a3522'; g.lineWidth = 4; g.strokeRect(4, 4, 632, 312)
258
+ g.fillStyle = '#3a2a18'; g.font = '700 26px "Be Vietnam Pro", sans-serif'; g.textAlign = 'center'
259
+ g.fillText('CHUYÊN CẦN THÁNG NÀY', 320, 36)
260
+ for (let r = 0; r < 5; r++) for (let c = 0; c < 10; c++) {
261
+ const x = 16 + c * 61, y = 50 + r * 50
262
+ g.fillStyle = '#5a442c'; g.fillRect(x, y, 56, 42)
263
+ if (rows && rows[r] && rows[r][c]) {
264
+ g.fillStyle = '#c8102e'; g.fillRect(x + 3, y + 3, 50, 36)
265
+ g.fillStyle = '#fff'; g.font = '600 18px "Be Vietnam Pro", sans-serif'
266
+ g.fillText('✓', x + 28, y + 27)
267
+ } else { g.fillStyle = '#8a6f4e'; g.fillRect(x + 3, y + 3, 50, 36) }
268
+ }
269
+ const t = new THREE.CanvasTexture(c); t.colorSpace = THREE.SRGBColorSpace
270
+ return t
271
+ }, [rows])
272
+ if (!rows) return null
273
+ return (
274
+ <mesh position={[0, 1.45, 0.02]} castShadow>
275
+ <planeGeometry args={[2.9, 1.45]} />
276
+ <meshStandardMaterial map={tex} roughness={0.85} />
277
+ </mesh>
278
+ )
279
+ }
280
+ function GroundGeom() {` ],
281
+ /* Wire AttendanceBoard vào PostAndPlaque (trụ bảng) */
282
+ [ ` <meshStandardMaterial map={tex} alphaTest={0.5} side={THREE.DoubleSide} roughness={0.85} />
283
+ </mesh>
284
+ )}`,
285
+ ` <meshStandardMaterial map={tex} alphaTest={0.5} side={THREE.DoubleSide} roughness={0.85} />
286
+ </mesh>
287
+ )}
288
+ <AttendanceBoard />` ],
289
+ /* Wire NatureGround + Vines vào HomeScene */
290
  [ ` <CaveExterior />
291
  <group position={layout.stele} rotation-y={layout.steleRotY}>`,
292
  ` <CaveExterior />
293
  <NatureGround />
294
+ <Vines />
295
  <group position={layout.stele} rotation-y={layout.steleRotY}>` ],
296
  /* Bảng chuyên cần attendance trên bia đá */
297
  [ `/* ---- Camera rig + layout (MA gốc) ---- */`,
 
380
  CÚP VÀNG TRUNG TÂM (trophy) — trước vòng huyền thoại, kỷ vật MU
381
  ========================================================================= */
382
  function Trophy() {
 
 
383
  return (
384
  <group position={[0, 0, 0]} rotation-y={0.5}>
385
  <mesh position={[0, 0.12, 0]} castShadow>
 
388
  </mesh>
389
  <mesh position={[0, 0.34, 0]} castShadow>
390
  <cylinderGeometry args={[0.55, 0.7, 0.2, 8]} />
391
+ <meshStandardMaterial color="#8a6a2c" metalness={0.7} roughness={0.35} flatShading />
392
  </mesh>
393
  <mesh position={[0, 0.85, 0]} castShadow>
394
  <cylinderGeometry args={[0.42, 0.5, 0.85, 10]} />
395
+ <meshStandardMaterial color="#c9a24e" metalness={0.85} roughness={0.25} flatShading />
396
  </mesh>
397
  <mesh position={[0, 1.32, 0]} castShadow>
398
  <torusGeometry args={[0.5, 0.09, 8, 18]} />
399
+ <meshStandardMaterial color="#c9a24e" metalness={0.85} roughness={0.25} flatShading />
400
  </mesh>
401
  <mesh position={[-0.42, 0.85, 0]} rotation-z={0.3}>
402
  <torusGeometry args={[0.26, 0.07, 8, 14, Math.PI]} />
403
+ <meshStandardMaterial color="#c9a24e" metalness={0.85} roughness={0.25} flatShading />
404
  </mesh>
405
  <mesh position={[0.42, 0.85, 0]} rotation-z={-0.3}>
406
  <torusGeometry args={[0.26, 0.07, 8, 14, Math.PI]} />
407
+ <meshStandardMaterial color="#c9a24e" metalness={0.85} roughness={0.25} flatShading />
408
  </mesh>
409
  <mesh position={[0, 1.62, 0]} castShadow>
410
  <sphereGeometry args={[0.2, 14, 14]} />
411
+ <meshStandardMaterial color="#c9a24e" metalness={0.85} roughness={0.25} flatShading />
412
  </mesh>
413
  <pointLight position={[0, 2.6, 0]} color="#ffd76a" intensity={18} distance={9} decay={1.6} />
414
  </group>
patch_backend.mjs CHANGED
@@ -19,7 +19,7 @@ if (!s.includes(oldVer)) {
19
  console.error('PATCH FAILED: VERSION_ID marker not found')
20
  process.exit(1)
21
  }
22
- s = s.replace(oldVer, 'VERSION_ID = "v7"')
23
 
24
  // IMPORTANT: phải chèn TRƯỚC catch-all @app.get("/{path:path}") (serve_static) —
25
  // nếu chèn sau, FastAPI match route theo thứ tự đăng ký → GET /api/logs bị
@@ -83,4 +83,4 @@ async def api_attendance():
83
  `
84
  s = s.slice(0, idx) + inject + s.slice(idx)
85
  fs.writeFileSync(path, s)
86
- console.log(`patched backend.py ok: VERSION_ID=v7, /api/log + /api/logs + /api/attendance (marker [${used}])`)
 
19
  console.error('PATCH FAILED: VERSION_ID marker not found')
20
  process.exit(1)
21
  }
22
+ s = s.replace(oldVer, 'VERSION_ID = "v8"')
23
 
24
  // IMPORTANT: phải chèn TRƯỚC catch-all @app.get("/{path:path}") (serve_static) —
25
  // nếu chèn sau, FastAPI match route theo thứ tự đăng ký → GET /api/logs bị
 
83
  `
84
  s = s.slice(0, idx) + inject + s.slice(idx)
85
  fs.writeFileSync(path, s)
86
+ console.log(`patched backend.py ok: VERSION_ID=v8, /api/log + /api/logs + /api/attendance (marker [${used}])`)