Lashtw commited on
Commit
cbde804
·
verified ·
1 Parent(s): c7f8731

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +79 -38
index.html CHANGED
@@ -399,24 +399,17 @@
399
  {
400
  id: 405, q: "49 - (y-1)^2",
401
  a: [
402
- // 基本正解: (8-y)(y+6) 及其變體
403
  "(8-y)(y+6)", "(y+6)(8-y)",
404
  "(6+y)(8-y)", "(8-y)(6+y)",
405
  "(-y+8)(y+6)", "(y+6)(-y+8)",
406
  "(-y+8)(6+y)", "(6+y)(-y+8)",
407
-
408
- // 負負得正系列: (-y-6)(y-8)
409
  "(-y-6)(y-8)", "(y-8)(-y-6)",
410
  "(-6-y)(y-8)", "(y-8)(-6-y)",
411
  "(-y-6)(-8+y)", "(-8+y)(-y-6)",
412
-
413
- // 提出負號系列 1: -(y-8)(y+6)
414
  "-(y-8)(y+6)", "-(y+6)(y-8)",
415
  "-(y-8)(6+y)", "-(6+y)(y-8)",
416
  "-(-8+y)(y+6)", "-(y+6)(-8+y)",
417
  "-(-8+y)(6+y)", "-(6+y)(-8+y)",
418
-
419
- // 提出負號系列 2: -(8-y)(-y-6)
420
  "-(8-y)(-y-6)", "-(-y-6)(8-y)",
421
  "-(8-y)(-6-y)", "-(-6-y)(8-y)"
422
  ],
@@ -476,13 +469,20 @@
476
  return { q: "未知題目", category: "未知", id: pid };
477
  };
478
 
 
 
 
 
 
 
 
479
  // --- Components ---
480
 
481
  const NameModal = ({ onSubmit }) => {
482
  const [name, setName] = useState("");
483
  const [roomId, setRoomId] = useState("");
484
 
485
- // 新增:檢查網址參數是否有 room
486
  useEffect(() => {
487
  const params = new URLSearchParams(window.location.search);
488
  const roomParam = params.get('room');
@@ -544,12 +544,12 @@
544
  const TeacherDashboard = ({ onClose, allData }) => {
545
  const [activeTab, setActiveTab] = useState('room'); // room, list, analysis
546
  const [roomCode, setRoomCode] = useState("");
547
- const [manualRoomInput, setManualRoomInput] = useState(""); // 新增:手動輸入的狀態
548
- const [roomHistory, setRoomHistory] = useState([]); // 新增:房間歷史紀錄
549
  const [selectedStudent, setSelectedStudent] = useState(null);
550
- const [showLargeQr, setShowLargeQr] = useState(false); // 新增:控制大圖顯示狀態
551
 
552
- // 新增:載入歷史紀錄
553
  useEffect(() => {
554
  const savedHistory = localStorage.getItem('teacher_room_history');
555
  if (savedHistory) {
@@ -559,7 +559,7 @@
559
  }
560
  }, []);
561
 
562
- // 新增:切換房間並保存到歷史
563
  const switchRoom = (code) => {
564
  setRoomCode(code);
565
  setManualRoomInput(code); // 同步更新輸入框
@@ -577,14 +577,14 @@
577
  switchRoom(code);
578
  };
579
 
580
- // 新增:手動加入房間
581
  const handleManualJoin = () => {
582
  if (manualRoomInput.trim()) {
583
  switchRoom(manualRoomInput.trim());
584
  }
585
  };
586
 
587
- // 新增:產生帶參數的網址與 QR Code 連結 (size 參數可調整)
588
  const getQrUrl = (size = "150x150") => {
589
  const baseUrl = window.location.origin + window.location.pathname;
590
  const fullUrl = `${baseUrl}?room=${roomCode}`;
@@ -854,8 +854,8 @@
854
  </div>
855
  </div>
856
  </div>
857
- );
858
- };
859
 
860
  // Teacher Login Modal
861
  const TeacherLoginModal = ({ onClose, onLogin }) => {
@@ -1034,27 +1034,39 @@
1034
  const [chestOpen, setChestOpen] = useState(false);
1035
  const [combo, setCombo] = useState(0);
1036
 
1037
- // State: Persistence (User Data) - Using Lazy Init to fix rotation data loss
1038
  const [userData, setUserData] = useState(() => {
 
 
 
 
 
 
 
 
 
1039
  const defaultData = {
1040
  score: 0,
1041
  name: "",
1042
- roomId: "", // Added Room ID
1043
- mistakes: {}, // Added Mistake Tracking { problemId: count }
1044
  unlockedItems: ['title_novice', 'scroll_default'],
1045
  equippedTitle: 'title_novice',
1046
  equippedScroll: 'scroll_default',
1047
  completedLevels: []
1048
  };
1049
- try {
1050
- const saved = localStorage.getItem('factoring_game_data_v5'); // Bumped version to v5 for structure change
1051
- if (saved) {
1052
  const parsed = JSON.parse(saved);
1053
- return { ...defaultData, ...parsed, completedLevels: parsed.completedLevels || [], mistakes: parsed.mistakes || {} };
 
 
 
1054
  }
1055
- } catch (e) {
1056
- console.error("Load error", e);
1057
  }
 
 
1058
  return defaultData;
1059
  });
1060
 
@@ -1086,21 +1098,49 @@
1086
  }
1087
  }, []);
1088
 
1089
- // ★★★ 新增:檢查網址是否帶有新的房間代碼 (解決共用載具問題) ★★★
1090
- useEffect(() => {
1091
- const params = new URLSearchParams(window.location.search);
1092
- const roomParam = params.get('room');
1093
 
1094
- // 如果網址有房間代碼,且跟目前儲存的不一樣,就更新它
1095
- if (roomParam && roomParam !== userData.roomId) {
1096
- setUserData(prev => ({ ...prev, roomId: roomParam }));
1097
- showNotification(`已加入房間:${roomParam}`, "success");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1098
  }
1099
- }, []);
 
1100
 
1101
- // Save Data
1102
  useEffect(() => {
1103
- localStorage.setItem('factoring_game_data_v5', JSON.stringify(userData));
 
1104
  }, [userData]);
1105
 
1106
  // --- Firebase Logic ---
@@ -1347,7 +1387,8 @@
1347
  return <TeacherDashboard onClose={() => setGameState('menu')} allData={leaderboardData} />;
1348
  }
1349
 
1350
- if (showNameModal) return <div className="relative min-h-screen"><div className="palace-bg"></div><div className="palace-overlay"></div><NameModal onSubmit={(name, roomId) => { setUserData(p => ({...p, name, roomId})); setShowNameModal(false); }} /></div>;
 
1351
  if (showTeacherLogin) return <TeacherLoginModal onClose={() => setShowTeacherLogin(false)} onLogin={() => { setShowTeacherLogin(false); setGameState('teacher_dashboard'); }} />;
1352
 
1353
  if (gameState === 'leaderboard') {
 
399
  {
400
  id: 405, q: "49 - (y-1)^2",
401
  a: [
 
402
  "(8-y)(y+6)", "(y+6)(8-y)",
403
  "(6+y)(8-y)", "(8-y)(6+y)",
404
  "(-y+8)(y+6)", "(y+6)(-y+8)",
405
  "(-y+8)(6+y)", "(6+y)(-y+8)",
 
 
406
  "(-y-6)(y-8)", "(y-8)(-y-6)",
407
  "(-6-y)(y-8)", "(y-8)(-6-y)",
408
  "(-y-6)(-8+y)", "(-8+y)(-y-6)",
 
 
409
  "-(y-8)(y+6)", "-(y+6)(y-8)",
410
  "-(y-8)(6+y)", "-(6+y)(y-8)",
411
  "-(-8+y)(y+6)", "-(y+6)(-8+y)",
412
  "-(-8+y)(6+y)", "-(6+y)(-8+y)",
 
 
413
  "-(8-y)(-y-6)", "-(-y-6)(8-y)",
414
  "-(8-y)(-6-y)", "-(-6-y)(8-y)"
415
  ],
 
469
  return { q: "未知題目", category: "未知", id: pid };
470
  };
471
 
472
+ // --- Storage Key Helper ---
473
+ // 新增:根據房間 ID 取得對應的 localStorage key
474
+ const getStorageKey = (roomId) => {
475
+ // 如果有房間代碼,使用專屬的 key;如果是空的(公開區),使用舊的 key 以保持相容性
476
+ return roomId ? `factoring_save_room_${roomId}` : 'factoring_game_data_v5';
477
+ };
478
+
479
  // --- Components ---
480
 
481
  const NameModal = ({ onSubmit }) => {
482
  const [name, setName] = useState("");
483
  const [roomId, setRoomId] = useState("");
484
 
485
+ // 檢查網址參數是否有 room
486
  useEffect(() => {
487
  const params = new URLSearchParams(window.location.search);
488
  const roomParam = params.get('room');
 
544
  const TeacherDashboard = ({ onClose, allData }) => {
545
  const [activeTab, setActiveTab] = useState('room'); // room, list, analysis
546
  const [roomCode, setRoomCode] = useState("");
547
+ const [manualRoomInput, setManualRoomInput] = useState("");
548
+ const [roomHistory, setRoomHistory] = useState([]);
549
  const [selectedStudent, setSelectedStudent] = useState(null);
550
+ const [showLargeQr, setShowLargeQr] = useState(false);
551
 
552
+ // 載入歷史紀錄
553
  useEffect(() => {
554
  const savedHistory = localStorage.getItem('teacher_room_history');
555
  if (savedHistory) {
 
559
  }
560
  }, []);
561
 
562
+ // 切換房間並保存到歷史
563
  const switchRoom = (code) => {
564
  setRoomCode(code);
565
  setManualRoomInput(code); // 同步更新輸入框
 
577
  switchRoom(code);
578
  };
579
 
580
+ // 手動加入房間
581
  const handleManualJoin = () => {
582
  if (manualRoomInput.trim()) {
583
  switchRoom(manualRoomInput.trim());
584
  }
585
  };
586
 
587
+ // 產生帶參數的網址與 QR Code 連結 (size 參數可調整)
588
  const getQrUrl = (size = "150x150") => {
589
  const baseUrl = window.location.origin + window.location.pathname;
590
  const fullUrl = `${baseUrl}?room=${roomCode}`;
 
854
  </div>
855
  </div>
856
  </div>
857
+ );
858
+ };
859
 
860
  // Teacher Login Modal
861
  const TeacherLoginModal = ({ onClose, onLogin }) => {
 
1034
  const [chestOpen, setChestOpen] = useState(false);
1035
  const [combo, setCombo] = useState(0);
1036
 
1037
+ // ★★★ 改良的資料初始化邏輯:支援多房間存檔 ★★★
1038
  const [userData, setUserData] = useState(() => {
1039
+ // 1. 取得網址中的房間參數
1040
+ const params = new URLSearchParams(window.location.search);
1041
+ const urlRoomId = params.get('room') || "";
1042
+
1043
+ // 2. 計算該房間對應的儲存 Key
1044
+ const storageKey = getStorageKey(urlRoomId);
1045
+ const saved = localStorage.getItem(storageKey);
1046
+
1047
+ // 預設資料結構
1048
  const defaultData = {
1049
  score: 0,
1050
  name: "",
1051
+ roomId: urlRoomId, // 初始化時就綁定正確的 roomId
1052
+ mistakes: {},
1053
  unlockedItems: ['title_novice', 'scroll_default'],
1054
  equippedTitle: 'title_novice',
1055
  equippedScroll: 'scroll_default',
1056
  completedLevels: []
1057
  };
1058
+
1059
+ if (saved) {
1060
+ try {
1061
  const parsed = JSON.parse(saved);
1062
+ // 合併以確保新舊欄位都存在,並強制更新 roomId 為當前網址的 ID
1063
+ return { ...defaultData, ...parsed, roomId: urlRoomId };
1064
+ } catch (e) {
1065
+ console.error("Load error", e);
1066
  }
 
 
1067
  }
1068
+
1069
+ // 如果沒有存檔(新房間),回傳預設值(相當於開新帳號)
1070
  return defaultData;
1071
  });
1072
 
 
1098
  }
1099
  }, []);
1100
 
1101
+ // ★★★ 新增:處理手動輸入房間代碼後的切換邏輯 ★★★
1102
+ // 這部分是為了 NameModal 提交後的行為
1103
+ const handleJoinRoom = (name, newRoomId) => {
1104
+ const targetRoomId = newRoomId.trim();
1105
 
1106
+ // 只有當房間代碼真的改變時,才進行切換
1107
+ if (targetRoomId !== userData.roomId) {
1108
+ const newKey = getStorageKey(targetRoomId);
1109
+ const saved = localStorage.getItem(newKey);
1110
+ let newData;
1111
+
1112
+ if (saved) {
1113
+ // 載入該房間的舊進度
1114
+ newData = JSON.parse(saved);
1115
+ // 確保名字更新為使用者剛輸入的
1116
+ newData.name = name;
1117
+ showNotification(`已切換至房間:${targetRoomId}`, "success");
1118
+ } else {
1119
+ // 該房間沒有紀錄,建立新帳號
1120
+ newData = {
1121
+ score: 0,
1122
+ name: name,
1123
+ roomId: targetRoomId,
1124
+ mistakes: {},
1125
+ unlockedItems: ['title_novice', 'scroll_default'],
1126
+ equippedTitle: 'title_novice',
1127
+ equippedScroll: 'scroll_default',
1128
+ completedLevels: []
1129
+ };
1130
+ showNotification(`已加入新房間:${targetRoomId}`, "success");
1131
+ }
1132
+ setUserData(newData);
1133
+ } else {
1134
+ // 房間沒變,只更新名字
1135
+ setUserData(prev => ({ ...prev, name, roomId: targetRoomId }));
1136
  }
1137
+ setShowNameModal(false);
1138
+ };
1139
 
1140
+ // Save Data (Modified to use dynamic key based on current userData.roomId)
1141
  useEffect(() => {
1142
+ const key = getStorageKey(userData.roomId);
1143
+ localStorage.setItem(key, JSON.stringify(userData));
1144
  }, [userData]);
1145
 
1146
  // --- Firebase Logic ---
 
1387
  return <TeacherDashboard onClose={() => setGameState('menu')} allData={leaderboardData} />;
1388
  }
1389
 
1390
+ // 使用修改後的 handleJoinRoom 替換原本的直接 setUserData
1391
+ if (showNameModal) return <div className="relative min-h-screen"><div className="palace-bg"></div><div className="palace-overlay"></div><NameModal onSubmit={handleJoinRoom} /></div>;
1392
  if (showTeacherLogin) return <TeacherLoginModal onClose={() => setShowTeacherLogin(false)} onLogin={() => { setShowTeacherLogin(false); setGameState('teacher_dashboard'); }} />;
1393
 
1394
  if (gameState === 'leaderboard') {