chih.yikuan commited on
Commit
a9ffafc
·
1 Parent(s): fa8b54d

Add /report-demo route to serve HTML report template

Browse files
chatkit/Dockerfile CHANGED
@@ -45,6 +45,9 @@ RUN pip install --no-cache-dir --upgrade pip && \
45
  # Copy backend code
46
  COPY --chown=user backend/app ./app
47
 
 
 
 
48
  # Copy built frontend from Stage 1
49
  COPY --from=frontend-builder --chown=user /app/frontend/dist ./static
50
 
 
45
  # Copy backend code
46
  COPY --chown=user backend/app ./app
47
 
48
+ # Copy report template
49
+ COPY --chown=user report-template.html ./
50
+
51
  # Copy built frontend from Stage 1
52
  COPY --from=frontend-builder --chown=user /app/frontend/dist ./static
53
 
chatkit/backend/app/main.py CHANGED
@@ -25,6 +25,21 @@ from .status_tracker import get_status, subscribe, unsubscribe
25
 
26
  # Static files directory (for production deployment)
27
  STATIC_DIR = Path(__file__).parent.parent / "static"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
 
30
  @asynccontextmanager
@@ -237,6 +252,26 @@ async def serve_report_template():
237
  return Response(status_code=404, content="Report template not found")
238
 
239
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  # =============================================================================
241
  # Static File Serving (Production)
242
  # =============================================================================
 
25
 
26
  # Static files directory (for production deployment)
27
  STATIC_DIR = Path(__file__).parent.parent / "static"
28
+ # Report template path (check multiple possible locations)
29
+ # Docker: /home/user/app/report-template.html (parent.parent from app/main.py)
30
+ # Dev: project_root/report-template.html (parent.parent.parent from backend/app/main.py)
31
+ def find_report_template():
32
+ """Find report template in common locations."""
33
+ possible_paths = [
34
+ Path(__file__).parent.parent / "report-template.html", # Docker location
35
+ Path(__file__).parent.parent.parent / "report-template.html", # Dev location
36
+ ]
37
+ for path in possible_paths:
38
+ if path.exists():
39
+ return path
40
+ return None
41
+
42
+ REPORT_TEMPLATE_PATH = find_report_template()
43
 
44
 
45
  @asynccontextmanager
 
252
  return Response(status_code=404, content="Report template not found")
253
 
254
 
255
+ # =============================================================================
256
+ # Report Demo Route
257
+ # =============================================================================
258
+
259
+ @app.get("/report-demo")
260
+ async def serve_report_demo():
261
+ """Serve the HTML report template demo."""
262
+ if REPORT_TEMPLATE_PATH and REPORT_TEMPLATE_PATH.exists():
263
+ return FileResponse(
264
+ REPORT_TEMPLATE_PATH,
265
+ media_type="text/html",
266
+ headers={"Cache-Control": "public, max-age=3600"}
267
+ )
268
+ return Response(
269
+ content="Report template not found",
270
+ status_code=404,
271
+ media_type="text/plain"
272
+ )
273
+
274
+
275
  # =============================================================================
276
  # Static File Serving (Production)
277
  # =============================================================================
report-template.html ADDED
@@ -0,0 +1,1067 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="zh-TW">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Unit 1 Quiz Report | 單元一測驗報告</title>
7
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
8
+ <style>
9
+ @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@300;400;500;700&family=Playfair+Display:wght@600;700&display=swap');
10
+
11
+ :root {
12
+ --bg-primary: #0f1419;
13
+ --bg-secondary: #1a2332;
14
+ --bg-card: #212d3b;
15
+ --accent-coral: #ff6b6b;
16
+ --accent-teal: #4ecdc4;
17
+ --accent-gold: #ffd93d;
18
+ --accent-purple: #a855f7;
19
+ --text-primary: #f1f5f9;
20
+ --text-secondary: #94a3b8;
21
+ --text-muted: #64748b;
22
+ --border-color: #334155;
23
+ }
24
+
25
+ * {
26
+ margin: 0;
27
+ padding: 0;
28
+ box-sizing: border-box;
29
+ }
30
+
31
+ body {
32
+ font-family: 'Noto Sans TC', sans-serif;
33
+ background: var(--bg-primary);
34
+ color: var(--text-primary);
35
+ line-height: 1.8;
36
+ min-height: 100vh;
37
+ }
38
+
39
+ .container {
40
+ max-width: 1200px;
41
+ margin: 0 auto;
42
+ padding: 2rem;
43
+ }
44
+
45
+ /* Header */
46
+ header {
47
+ text-align: center;
48
+ padding: 4rem 2rem;
49
+ background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-primary) 100%);
50
+ border-bottom: 1px solid var(--border-color);
51
+ position: relative;
52
+ overflow: hidden;
53
+ }
54
+
55
+ header::before {
56
+ content: '';
57
+ position: absolute;
58
+ top: -50%;
59
+ left: -50%;
60
+ width: 200%;
61
+ height: 200%;
62
+ background: radial-gradient(circle at 30% 70%, rgba(78, 205, 196, 0.08) 0%, transparent 50%),
63
+ radial-gradient(circle at 70% 30%, rgba(255, 107, 107, 0.08) 0%, transparent 50%);
64
+ animation: pulse 8s ease-in-out infinite;
65
+ }
66
+
67
+ @keyframes pulse {
68
+ 0%, 100% { opacity: 1; }
69
+ 50% { opacity: 0.6; }
70
+ }
71
+
72
+ header h1 {
73
+ font-family: 'Playfair Display', serif;
74
+ font-size: 3rem;
75
+ font-weight: 700;
76
+ background: linear-gradient(135deg, var(--accent-teal), var(--accent-coral));
77
+ -webkit-background-clip: text;
78
+ -webkit-text-fill-color: transparent;
79
+ background-clip: text;
80
+ margin-bottom: 0.5rem;
81
+ position: relative;
82
+ z-index: 1;
83
+ }
84
+
85
+ header p {
86
+ color: var(--text-secondary);
87
+ font-size: 1.1rem;
88
+ position: relative;
89
+ z-index: 1;
90
+ }
91
+
92
+ /* Navigation Tabs */
93
+ .nav-tabs {
94
+ display: flex;
95
+ justify-content: center;
96
+ gap: 1rem;
97
+ padding: 1.5rem;
98
+ background: var(--bg-secondary);
99
+ border-bottom: 1px solid var(--border-color);
100
+ flex-wrap: wrap;
101
+ }
102
+
103
+ .nav-tab {
104
+ padding: 0.75rem 1.5rem;
105
+ background: var(--bg-card);
106
+ border: 1px solid var(--border-color);
107
+ border-radius: 8px;
108
+ color: var(--text-secondary);
109
+ cursor: pointer;
110
+ transition: all 0.3s ease;
111
+ font-weight: 500;
112
+ }
113
+
114
+ .nav-tab:hover, .nav-tab.active {
115
+ background: linear-gradient(135deg, var(--accent-teal), var(--accent-coral));
116
+ color: var(--bg-primary);
117
+ border-color: transparent;
118
+ transform: translateY(-2px);
119
+ }
120
+
121
+ /* Sections */
122
+ section {
123
+ padding: 3rem 0;
124
+ }
125
+
126
+ .section-title {
127
+ font-family: 'Playfair Display', serif;
128
+ font-size: 2rem;
129
+ margin-bottom: 2rem;
130
+ padding-bottom: 1rem;
131
+ border-bottom: 2px solid var(--accent-teal);
132
+ display: inline-block;
133
+ }
134
+
135
+ /* Cards */
136
+ .card {
137
+ background: var(--bg-card);
138
+ border-radius: 16px;
139
+ padding: 2rem;
140
+ margin-bottom: 2rem;
141
+ border: 1px solid var(--border-color);
142
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
143
+ }
144
+
145
+ .card:hover {
146
+ transform: translateY(-4px);
147
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
148
+ }
149
+
150
+ /* Q&A Section */
151
+ .question-card {
152
+ position: relative;
153
+ overflow: hidden;
154
+ }
155
+
156
+ .question-card::before {
157
+ content: '';
158
+ position: absolute;
159
+ top: 0;
160
+ left: 0;
161
+ width: 4px;
162
+ height: 100%;
163
+ background: linear-gradient(180deg, var(--accent-teal), var(--accent-coral));
164
+ }
165
+
166
+ .question-number {
167
+ display: inline-flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ width: 40px;
171
+ height: 40px;
172
+ background: linear-gradient(135deg, var(--accent-teal), var(--accent-coral));
173
+ border-radius: 50%;
174
+ color: var(--bg-primary);
175
+ font-weight: 700;
176
+ margin-bottom: 1rem;
177
+ }
178
+
179
+ .question-text {
180
+ font-size: 1.25rem;
181
+ font-weight: 600;
182
+ color: var(--text-primary);
183
+ margin-bottom: 1rem;
184
+ }
185
+
186
+ .answer-box {
187
+ background: var(--bg-secondary);
188
+ padding: 1rem 1.5rem;
189
+ border-radius: 8px;
190
+ margin: 1rem 0;
191
+ border-left: 3px solid var(--accent-gold);
192
+ }
193
+
194
+ .answer-box strong {
195
+ color: var(--accent-gold);
196
+ }
197
+
198
+ .explanation {
199
+ background: rgba(78, 205, 196, 0.1);
200
+ padding: 1.5rem;
201
+ border-radius: 12px;
202
+ margin-top: 1rem;
203
+ }
204
+
205
+ .explanation h4 {
206
+ color: var(--accent-teal);
207
+ margin-bottom: 0.75rem;
208
+ display: flex;
209
+ align-items: center;
210
+ gap: 0.5rem;
211
+ }
212
+
213
+ .concept-tag {
214
+ display: inline-block;
215
+ padding: 0.25rem 0.75rem;
216
+ background: rgba(168, 85, 247, 0.2);
217
+ color: var(--accent-purple);
218
+ border-radius: 20px;
219
+ font-size: 0.85rem;
220
+ margin: 0.25rem;
221
+ }
222
+
223
+ /* Statistics Section */
224
+ .stats-grid {
225
+ display: grid;
226
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
227
+ gap: 1.5rem;
228
+ margin-bottom: 2rem;
229
+ }
230
+
231
+ .stat-card {
232
+ background: var(--bg-card);
233
+ padding: 1.5rem;
234
+ border-radius: 12px;
235
+ text-align: center;
236
+ border: 1px solid var(--border-color);
237
+ }
238
+
239
+ .stat-value {
240
+ font-size: 2.5rem;
241
+ font-weight: 700;
242
+ background: linear-gradient(135deg, var(--accent-teal), var(--accent-coral));
243
+ -webkit-background-clip: text;
244
+ -webkit-text-fill-color: transparent;
245
+ background-clip: text;
246
+ }
247
+
248
+ .stat-label {
249
+ color: var(--text-secondary);
250
+ font-size: 0.9rem;
251
+ margin-top: 0.5rem;
252
+ }
253
+
254
+ .chart-container {
255
+ background: var(--bg-card);
256
+ padding: 2rem;
257
+ border-radius: 16px;
258
+ border: 1px solid var(--border-color);
259
+ }
260
+
261
+ /* Student Table */
262
+ .student-table {
263
+ width: 100%;
264
+ border-collapse: collapse;
265
+ margin-top: 1.5rem;
266
+ }
267
+
268
+ .student-table th,
269
+ .student-table td {
270
+ padding: 1rem;
271
+ text-align: left;
272
+ border-bottom: 1px solid var(--border-color);
273
+ }
274
+
275
+ .student-table th {
276
+ background: var(--bg-secondary);
277
+ color: var(--accent-teal);
278
+ font-weight: 600;
279
+ }
280
+
281
+ .student-table tr:hover {
282
+ background: rgba(78, 205, 196, 0.05);
283
+ }
284
+
285
+ .score-badge {
286
+ padding: 0.25rem 0.75rem;
287
+ border-radius: 20px;
288
+ font-weight: 600;
289
+ font-size: 0.85rem;
290
+ }
291
+
292
+ .score-high { background: rgba(78, 205, 196, 0.2); color: var(--accent-teal); }
293
+ .score-mid { background: rgba(255, 217, 61, 0.2); color: var(--accent-gold); }
294
+ .score-low { background: rgba(255, 107, 107, 0.2); color: var(--accent-coral); }
295
+
296
+ /* Teacher Section */
297
+ .insight-card {
298
+ background: linear-gradient(135deg, rgba(78, 205, 196, 0.1), rgba(168, 85, 247, 0.1));
299
+ border: 1px solid var(--accent-teal);
300
+ }
301
+
302
+ .insight-card h3 {
303
+ color: var(--accent-teal);
304
+ margin-bottom: 1rem;
305
+ display: flex;
306
+ align-items: center;
307
+ gap: 0.5rem;
308
+ }
309
+
310
+ .prompt-box {
311
+ background: var(--bg-primary);
312
+ padding: 1.5rem;
313
+ border-radius: 8px;
314
+ font-family: 'Courier New', monospace;
315
+ font-size: 0.9rem;
316
+ line-height: 1.6;
317
+ border: 1px dashed var(--border-color);
318
+ white-space: pre-wrap;
319
+ margin-top: 1rem;
320
+ }
321
+
322
+ .improvement-list {
323
+ list-style: none;
324
+ padding: 0;
325
+ }
326
+
327
+ .improvement-list li {
328
+ padding: 0.75rem 0;
329
+ padding-left: 2rem;
330
+ position: relative;
331
+ border-bottom: 1px solid var(--border-color);
332
+ }
333
+
334
+ .improvement-list li::before {
335
+ content: '▸';
336
+ position: absolute;
337
+ left: 0;
338
+ color: var(--accent-coral);
339
+ }
340
+
341
+ /* Reading Passage */
342
+ .reading-passage {
343
+ background: var(--bg-secondary);
344
+ padding: 2rem;
345
+ border-radius: 12px;
346
+ margin: 1.5rem 0;
347
+ border: 1px solid var(--border-color);
348
+ font-style: italic;
349
+ line-height: 2;
350
+ }
351
+
352
+ .reading-passage .highlight {
353
+ background: rgba(255, 217, 61, 0.3);
354
+ padding: 0.1rem 0.3rem;
355
+ border-radius: 3px;
356
+ }
357
+
358
+ /* Responsive */
359
+ @media (max-width: 768px) {
360
+ header h1 { font-size: 2rem; }
361
+ .container { padding: 1rem; }
362
+ .card { padding: 1.5rem; }
363
+ .nav-tabs { gap: 0.5rem; }
364
+ .nav-tab { padding: 0.5rem 1rem; font-size: 0.9rem; }
365
+ }
366
+
367
+ /* Scrollbar */
368
+ ::-webkit-scrollbar {
369
+ width: 8px;
370
+ }
371
+
372
+ ::-webkit-scrollbar-track {
373
+ background: var(--bg-primary);
374
+ }
375
+
376
+ ::-webkit-scrollbar-thumb {
377
+ background: var(--border-color);
378
+ border-radius: 4px;
379
+ }
380
+
381
+ ::-webkit-scrollbar-thumb:hover {
382
+ background: var(--accent-teal);
383
+ }
384
+ </style>
385
+ </head>
386
+ <body>
387
+ <header>
388
+ <div style="position: relative; z-index: 1; margin-bottom: 1rem;">
389
+ <span style="background: rgba(78, 205, 196, 0.2); color: var(--accent-teal); padding: 0.4rem 1rem; border-radius: 20px; font-size: 0.85rem; font-weight: 500;">
390
+ 📊 Generated by <strong>taboola-npo-cz-2026</strong>
391
+ </span>
392
+ </div>
393
+ <h1>Unit 1 Quiz Report</h1>
394
+ <p>單元一測驗分析報告 | My Wonderful Family 閱讀理解與寫作</p>
395
+ <div style="margin-top: 1.5rem; position: relative; z-index: 1;">
396
+ <a href="https://docs.google.com/forms/d/1WT9WrEPnV0U6_VYgEGXHc6geDtfe-Zd5BO6e_Y4ffOc/edit?ts=693672c2"
397
+ target="_blank"
398
+ style="display: inline-flex; align-items: center; gap: 0.5rem; background: var(--bg-card); color: var(--text-primary); padding: 0.75rem 1.5rem; border-radius: 8px; text-decoration: none; border: 1px solid var(--border-color); transition: all 0.3s ease;">
399
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
400
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
401
+ <polyline points="14 2 14 8 20 8"></polyline>
402
+ <line x1="16" y1="13" x2="8" y2="13"></line>
403
+ <line x1="16" y1="17" x2="8" y2="17"></line>
404
+ <polyline points="10 9 9 9 8 9"></polyline>
405
+ </svg>
406
+ 📝 原始測驗連結 Original Quiz (Google Forms)
407
+ </a>
408
+ </div>
409
+ </header>
410
+
411
+ <nav class="nav-tabs">
412
+ <a href="#qa" class="nav-tab active">📝 題目詳解</a>
413
+ <a href="#stats" class="nav-tab">📊 成績統計</a>
414
+ <a href="#teacher" class="nav-tab">👩‍🏫 教師建議</a>
415
+ </nav>
416
+
417
+ <main class="container">
418
+ <!-- Q&A Section -->
419
+ <section id="qa">
420
+ <h2 class="section-title">📝 題目與詳解 Q&A Analysis</h2>
421
+
422
+ <div class="card">
423
+ <h3 style="color: var(--accent-teal); margin-bottom: 1rem;">📖 閱讀文章 Reading Passage</h3>
424
+ <div class="reading-passage">
425
+ <strong>Title: My Wonderful Family - The Lin's</strong><br><br>
426
+ Hello! My name is <span class="highlight">Nick</span>. I am a junior high school student, and I want to tell you about my family. We live in a warm and friendly home. My family is special to me, and I love spending time with them.<br><br>
427
+ My <span class="highlight">grandfather</span> is a farmer. He grows many fruits and vegetables. I always help him on weekends. My <span class="highlight">grandmother</span> is a cook. She makes delicious food. I like her famous soup! <span class="highlight">Paul</span> is my father. He is a tall man and a nurse. He helps many people when they are sick. My mother, <span class="highlight">Lily</span>, is a doctor. She is a kind and beautiful woman. I admire her very much.<br><br>
428
+ I have a sister named <span class="highlight">Bella</span>. She is my English teacher and <span class="highlight">helps me with my homework</span>. Sometimes we learn new words together. My brother, <span class="highlight">Eddie</span>, is in senior high school. He studies hard and <span class="highlight">wants to be a teacher one day</span>. We play games together after school, and I always have fun with him.<br><br>
429
+ Also, We have a cute pet pig named <span class="highlight">Abby</span>. She is small and loves to play in the garden. We feed her fruits and vegetables. Abby makes us all very happy.<br><br>
430
+ My family is full of love and joy. We enjoy spending time together, helping each other, and having fun. Everyone in my family has special jobs and interests, but we are always there for one another. I feel lucky to have such a wonderful family.
431
+ </div>
432
+ </div>
433
+
434
+ <!-- Question 1 -->
435
+ <div class="card question-card">
436
+ <div class="question-number">1</div>
437
+ <div class="question-text">How many people in Lin's family?<br>林家有幾個人?</div>
438
+
439
+ <div class="answer-box">
440
+ <strong>正確答案 Correct Answer:</strong> There are seven (7) people. / 有七個人
441
+ </div>
442
+
443
+ <div style="margin: 1rem 0;">
444
+ <span class="concept-tag">🎯 細節理解 Detail Comprehension</span>
445
+ <span class="concept-tag">🔢 數數技巧 Counting Skills</span>
446
+ <span class="concept-tag">👨‍👩‍👧‍👦 家庭成員辨識</span>
447
+ </div>
448
+
449
+ <div class="explanation">
450
+ <h4>📚 詳解 Detailed Explanation</h4>
451
+ <p><strong>這題測試什麼?</strong></p>
452
+ <p>這題主要測試學生的<strong>細節閱讀能力</strong>與<strong>資訊整合能力</strong>。學生需要仔細閱讀全文,找出所有家庭成員並正確計數。這是基礎閱讀理解中「找尋特定資訊」(scanning) 的技巧。</p>
453
+
454
+ <p style="margin-top: 1rem;"><strong>解題關鍵:</strong></p>
455
+ <p>林家成員共 7 人:</p>
456
+ <ol style="margin-left: 1.5rem; margin-top: 0.5rem;">
457
+ <li><strong>Nick</strong> - 敘述者本人 (國中生)</li>
458
+ <li><strong>Grandfather</strong> - 爺爺 (農夫)</li>
459
+ <li><strong>Grandmother</strong> - 奶奶 (廚師)</li>
460
+ <li><strong>Paul</strong> - 爸爸 (護士)</li>
461
+ <li><strong>Lily</strong> - 媽媽 (醫生)</li>
462
+ <li><strong>Bella</strong> - 姊姊 (英文老師)</li>
463
+ <li><strong>Eddie</strong> - 哥哥 (高中生)</li>
464
+ </ol>
465
+ <p style="margin-top: 0.5rem; color: var(--text-secondary);">※ 注意:寵物豬 Abby 不算在「人」的數量中</p>
466
+
467
+ <p style="margin-top: 1rem;"><strong>常見錯誤:</strong></p>
468
+ <ul style="margin-left: 1.5rem;">
469
+ <li>回答「六人」- 可能漏數了 Nick 本人或某位家庭成員</li>
470
+ <li>回答「五人」- 可能只數了核心家庭(父母+子女三人)</li>
471
+ <li>把寵物 Abby 也算進去</li>
472
+ </ul>
473
+ </div>
474
+ </div>
475
+
476
+ <!-- Question 2 -->
477
+ <div class="card question-card">
478
+ <div class="question-number">2</div>
479
+ <div class="question-text">Who doesn't have name in the reading?<br>文章中誰沒有名字?</div>
480
+
481
+ <div class="answer-box">
482
+ <strong>正確答案 Correct Answer:</strong> Nick's grandparents (grandfather and grandmother) / 尼克的祖父母
483
+ </div>
484
+
485
+ <div style="margin: 1rem 0;">
486
+ <span class="concept-tag">🔍 推論能力 Inference</span>
487
+ <span class="concept-tag">📖 細節對比 Detail Comparison</span>
488
+ <span class="concept-tag">🧠 批判思考</span>
489
+ </div>
490
+
491
+ <div class="explanation">
492
+ <h4>📚 詳解 Detailed Explanation</h4>
493
+ <p><strong>這題測試什麼?</strong></p>
494
+ <p>這題測試學生的<strong>細節辨識能力</strong>與<strong>對比分析能力</strong>。學生需要注意文章中提到的每個人物,並辨別哪些人有具體姓名、哪些人只用稱謂稱呼。這屬於較高層次的閱讀技巧。</p>
495
+
496
+ <p style="margin-top: 1rem;"><strong>解題關鍵:</strong></p>
497
+ <p>文章中有名字的人物:</p>
498
+ <ul style="margin-left: 1.5rem; margin-top: 0.5rem;">
499
+ <li>Nick (敘述者)</li>
500
+ <li>Paul (爸爸)</li>
501
+ <li>Lily (媽媽)</li>
502
+ <li>Bella (姊姊)</li>
503
+ <li>Eddie (哥哥)</li>
504
+ <li>Abby (寵物豬)</li>
505
+ </ul>
506
+ <p style="margin-top: 0.5rem;"><strong>沒有名字的人物:Grandfather 和 Grandmother</strong></p>
507
+ <p>文章只用 "My grandfather" 和 "My grandmother" 來稱呼,沒有給予具體名字。</p>
508
+
509
+ <p style="margin-top: 1rem;"><strong>常見錯誤:</strong></p>
510
+ <ul style="margin-left: 1.5rem;">
511
+ <li>回答「Nick's pet」- Abby 是有名字的</li>
512
+ <li>混淆「稱謂」和「名字」的概念</li>
513
+ </ul>
514
+ </div>
515
+ </div>
516
+
517
+ <!-- Question 3 -->
518
+ <div class="card question-card">
519
+ <div class="question-number">3</div>
520
+ <div class="question-text">Who wants to become a teacher? (Name only)<br>誰想成為老師?(只寫名字)</div>
521
+
522
+ <div class="answer-box">
523
+ <strong>正確答案 Correct Answer:</strong> Eddie
524
+ </div>
525
+
526
+ <div style="margin: 1rem 0;">
527
+ <span class="concept-tag">🎯 特定資訊搜尋 Scanning</span>
528
+ <span class="concept-tag">📖 關鍵句辨識</span>
529
+ <span class="concept-tag">🔮 未來式理解</span>
530
+ </div>
531
+
532
+ <div class="explanation">
533
+ <h4>📚 詳解 Detailed Explanation</h4>
534
+ <p><strong>這題測試什麼?</strong></p>
535
+ <p>這題測試學生的<strong>關鍵字搜尋能力</strong> (Scanning) 以及對<strong>未來願望表達方式</strong>的理解。學生需要找到包含 "wants to be a teacher" 或類似表達的句子。</p>
536
+
537
+ <p style="margin-top: 1rem;"><strong>解題關鍵:</strong></p>
538
+ <p>關鍵句:<em>"My brother, Eddie, is in senior high school. He studies hard and <strong>wants to be a teacher one day</strong>."</em></p>
539
+ <p style="margin-top: 0.5rem;">注意這裡的 "wants to be" 表示「想要成為」,是表達未來願望的常見用法。</p>
540
+
541
+ <p style="margin-top: 1rem;"><strong>容易混淆的地方:</strong></p>
542
+ <ul style="margin-left: 1.5rem;">
543
+ <li><strong>Bella</strong> 是「現在」已經是英文老師 ("She <strong>is</strong> my English teacher")</li>
544
+ <li><strong>Eddie</strong> 是「想要」將來成為老師 ("He <strong>wants to be</strong> a teacher one day")</li>
545
+ </ul>
546
+ <p style="margin-top: 0.5rem; color: var(--accent-coral);">⚠️ 題目問的是「想要成為」(wants to become),而不是「已經是」(is),所以答案是 Eddie,不是 Bella!</p>
547
+ </div>
548
+ </div>
549
+
550
+ <!-- Question 4 -->
551
+ <div class="card question-card">
552
+ <div class="question-number">4</div>
553
+ <div class="question-text">Nick is struggling with his homework. According to the reading, who can help him?<br>Nick 正在為功課煩惱。根據文章,誰可以幫助他?</div>
554
+
555
+ <div class="answer-box">
556
+ <strong>正確答案 Correct Answer:</strong> His sister (Bella) / 他的姊姊(Bella)
557
+ </div>
558
+
559
+ <div style="margin: 1rem 0;">
560
+ <span class="concept-tag">🔍 應用推論 Application</span>
561
+ <span class="concept-tag">📖 情境理解 Context</span>
562
+ <span class="concept-tag">🔗 資訊連結 Connecting Information</span>
563
+ </div>
564
+
565
+ <div class="explanation">
566
+ <h4>📚 詳解 Detailed Explanation</h4>
567
+ <p><strong>這題測試什麼?</strong></p>
568
+ <p>這題測試學生的<strong>應用理解能力</strong>。學生需要將文章中的資訊應用到新的情境(Nick 需要功課幫助),這是較高層次的閱讀理解。</p>
569
+
570
+ <p style="margin-top: 1rem;"><strong>解題關鍵:</strong></p>
571
+ <p>關鍵句:<em>"I have a sister named Bella. She is my English teacher and <strong>helps me with my homework</strong>."</em></p>
572
+ <p style="margin-top: 0.5rem;">文章明確提到 Bella 會幫助 Nick 做功課。</p>
573
+
574
+ <p style="margin-top: 1rem;"><strong>常見錯誤:</strong></p>
575
+ <ul style="margin-left: 1.5rem;">
576
+ <li>回答「His grandparents」- 文章沒有提到祖父母幫忙功課</li>
577
+ <li>回答「His brother」- Eddie 是和 Nick 一起玩遊戲,不是幫忙功課</li>
578
+ <li>回答「His parents」- 雖然父母���護士和醫生,但文章沒提到他們幫功課</li>
579
+ </ul>
580
+
581
+ <p style="margin-top: 1rem;"><strong>學習重點:</strong></p>
582
+ <p>這題強調 "according to the reading"(根據文章),提醒學生答案必須來自文章內容,不能用自己的推測或生活經驗作答。</p>
583
+ </div>
584
+ </div>
585
+
586
+ <!-- Question 5 - Writing -->
587
+ <div class="card question-card">
588
+ <div class="question-number">5</div>
589
+ <div class="question-text">Can you introduce me your family?<br>你可以介紹你的家庭嗎?(寫作題)</div>
590
+
591
+ <div class="answer-box">
592
+ <strong>評分標準 Scoring Criteria:</strong><br>
593
+ • 至少介紹兩位家庭成員(包含自己)<br>
594
+ • 描述家庭生活或文化特色<br>
595
+ • 字數控制在 80 字以內<br>
596
+ • 可用 AI 輔助修改,但不可用 Google 翻譯
597
+ </div>
598
+
599
+ <div style="margin: 1rem 0;">
600
+ <span class="concept-tag">✍️ 寫作表達 Writing</span>
601
+ <span class="concept-tag">👨‍👩‍👧‍👦 家庭介紹 Family Introduction</span>
602
+ <span class="concept-tag">📝 段落組織 Organization</span>
603
+ </div>
604
+
605
+ <div class="explanation">
606
+ <h4>📚 詳解 Detailed Explanation</h4>
607
+ <p><strong>這題測試什麼?</strong></p>
608
+ <p>這題測試學生的<strong>英文寫作能力</strong>,包括:</p>
609
+ <ul style="margin-left: 1.5rem; margin-top: 0.5rem;">
610
+ <li><strong>句子結構</strong>:能否正確使用主詞+動詞+受詞的基本句型</li>
611
+ <li><strong>家庭詞彙</strong>:father, mother, brother, sister, grandparents 等</li>
612
+ <li><strong>職業詞彙</strong>:student, teacher, farmer, nurse, doctor 等</li>
613
+ <li><strong>描述能力</strong>:描述家庭成員的特質或家庭文化</li>
614
+ </ul>
615
+
616
+ <p style="margin-top: 1rem;"><strong>範例解析:</strong></p>
617
+ <div style="background: var(--bg-secondary); padding: 1rem; border-radius: 8px; margin-top: 0.5rem;">
618
+ <p><em>"Hi, my name is May. There are four people in my family. I have a younger brother, and he is a police officer. My mom is a school nurse, and my dad is retired. My family is pretty noisy. We argue sometimes, but we still love each other very much."</em></p>
619
+ </div>
620
+ <p style="margin-top: 0.5rem;"><strong>範例優點:</strong></p>
621
+ <ul style="margin-left: 1.5rem;">
622
+ <li>✅ 清楚的開頭自我介紹</li>
623
+ <li>✅ 說明家庭人數</li>
624
+ <li>✅ 介紹家人及其職業</li>
625
+ <li>✅ 描述家庭特色(noisy, argue, love)</li>
626
+ <li>✅ 字數適中,約 60 字</li>
627
+ </ul>
628
+ </div>
629
+ </div>
630
+ </section>
631
+
632
+ <!-- Statistics Section -->
633
+ <section id="stats">
634
+ <h2 class="section-title">📊 成績統計 Statistics</h2>
635
+
636
+ <div class="stats-grid">
637
+ <div class="stat-card">
638
+ <div class="stat-value">12</div>
639
+ <div class="stat-label">參與人數 Total Students</div>
640
+ </div>
641
+ <div class="stat-card">
642
+ <div class="stat-value">20.8</div>
643
+ <div class="stat-label">平均分數 Average Score</div>
644
+ </div>
645
+ <div class="stat-card">
646
+ <div class="stat-value">30</div>
647
+ <div class="stat-label">最高分 Highest</div>
648
+ </div>
649
+ <div class="stat-card">
650
+ <div class="stat-value">0</div>
651
+ <div class="stat-label">最低分 Lowest</div>
652
+ </div>
653
+ </div>
654
+
655
+ <div class="chart-container">
656
+ <h3 style="margin-bottom: 1.5rem; color: var(--accent-teal);">📈 分數分佈 Score Distribution</h3>
657
+ <canvas id="scoreChart" height="100"></canvas>
658
+ </div>
659
+
660
+ <div class="chart-container" style="margin-top: 2rem;">
661
+ <h3 style="margin-bottom: 1.5rem; color: var(--accent-teal);">🎯 各題答對率 Question Accuracy Rate</h3>
662
+ <canvas id="questionChart" height="100"></canvas>
663
+ </div>
664
+
665
+ <div class="card" style="margin-top: 2rem;">
666
+ <h3 style="color: var(--accent-teal); margin-bottom: 1rem;">📋 學生成績明細 Student Details</h3>
667
+ <div style="overflow-x: auto;">
668
+ <table class="student-table">
669
+ <thead>
670
+ <tr>
671
+ <th>姓名 Name</th>
672
+ <th>班級 Class</th>
673
+ <th>分數 Score</th>
674
+ <th>Q1</th>
675
+ <th>Q2</th>
676
+ <th>Q3</th>
677
+ <th>Q4</th>
678
+ </tr>
679
+ </thead>
680
+ <tbody>
681
+ <tr>
682
+ <td>梁X邦</td>
683
+ <td>901</td>
684
+ <td><span class="score-badge score-high">30/70</span></td>
685
+ <td>✅</td>
686
+ <td>✅</td>
687
+ <td>✅</td>
688
+ <td>✅</td>
689
+ </tr>
690
+ <tr>
691
+ <td>李X恩</td>
692
+ <td>902</td>
693
+ <td><span class="score-badge score-high">30/70</span></td>
694
+ <td>✅</td>
695
+ <td>✅</td>
696
+ <td>✅</td>
697
+ <td>✅</td>
698
+ </tr>
699
+ <tr>
700
+ <td>謝X駿</td>
701
+ <td>902</td>
702
+ <td><span class="score-badge score-high">30/70</span></td>
703
+ <td>❌</td>
704
+ <td>✅</td>
705
+ <td>✅</td>
706
+ <td>✅</td>
707
+ </tr>
708
+ <tr>
709
+ <td>江X吟</td>
710
+ <td>901</td>
711
+ <td><span class="score-badge score-mid">20/70</span></td>
712
+ <td>✅</td>
713
+ <td>✅</td>
714
+ <td>❌</td>
715
+ <td>✅</td>
716
+ </tr>
717
+ <tr>
718
+ <td>賴X妤</td>
719
+ <td>901</td>
720
+ <td><span class="score-badge score-mid">20/70</span></td>
721
+ <td>✅</td>
722
+ <td>✅</td>
723
+ <td>❌</td>
724
+ <td>✅</td>
725
+ </tr>
726
+ <tr>
727
+ <td>陳X琳</td>
728
+ <td>902</td>
729
+ <td><span class="score-badge score-mid">20/70</span></td>
730
+ <td>❌</td>
731
+ <td>✅</td>
732
+ <td>❌</td>
733
+ <td>✅</td>
734
+ </tr>
735
+ <tr>
736
+ <td>郭X榕</td>
737
+ <td>902</td>
738
+ <td><span class="score-badge score-mid">20/70</span></td>
739
+ <td>❌</td>
740
+ <td>❌</td>
741
+ <td>✅</td>
742
+ <td>✅</td>
743
+ </tr>
744
+ <tr>
745
+ <td>黃X臻</td>
746
+ <td>901</td>
747
+ <td><span class="score-badge score-mid">20/70</span></td>
748
+ <td>✅</td>
749
+ <td>✅</td>
750
+ <td>❌</td>
751
+ <td>✅</td>
752
+ </tr>
753
+ <tr>
754
+ <td>王X芯</td>
755
+ <td>901</td>
756
+ <td><span class="score-badge score-mid">20/70</span></td>
757
+ <td>✅</td>
758
+ <td>✅</td>
759
+ <td>❌</td>
760
+ <td>✅</td>
761
+ </tr>
762
+ <tr>
763
+ <td>蕭X翔</td>
764
+ <td>901</td>
765
+ <td><span class="score-badge score-mid">20/70</span></td>
766
+ <td>❌</td>
767
+ <td>✅</td>
768
+ <td>✅</td>
769
+ <td>❌</td>
770
+ </tr>
771
+ <tr>
772
+ <td>X婕</td>
773
+ <td>901</td>
774
+ <td><span class="score-badge score-mid">20/70</span></td>
775
+ <td>❌</td>
776
+ <td>✅</td>
777
+ <td>✅</td>
778
+ <td>❌</td>
779
+ </tr>
780
+ <tr>
781
+ <td>消X好</td>
782
+ <td>901</td>
783
+ <td><span class="score-badge score-mid">20/70</span></td>
784
+ <td>❌</td>
785
+ <td>✅</td>
786
+ <td>❌</td>
787
+ <td>✅</td>
788
+ </tr>
789
+ <tr>
790
+ <td>許X彥</td>
791
+ <td>902</td>
792
+ <td><span class="score-badge score-low">0/70</span></td>
793
+ <td>❌</td>
794
+ <td>❌</td>
795
+ <td>❌</td>
796
+ <td>❌</td>
797
+ </tr>
798
+ </tbody>
799
+ </table>
800
+ </div>
801
+ </div>
802
+ </section>
803
+
804
+ <!-- Teacher Section -->
805
+ <section id="teacher">
806
+ <h2 class="section-title">👩‍🏫 教師分析與建議 Teacher Insights</h2>
807
+
808
+ <div class="card insight-card">
809
+ <h3>📊 整體表現分析 Overall Performance Analysis</h3>
810
+ <p>本次測驗共 12 位學生參加,平均分數為 <strong>20.8/70</strong>(約 30%),顯示學生在閱讀理解方面仍有較大進步空間。</p>
811
+
812
+ <div style="margin-top: 1.5rem;">
813
+ <h4 style="color: var(--accent-gold); margin-bottom: 0.75rem;">🔍 各題表現分析:</h4>
814
+ <ul class="improvement-list">
815
+ <li>
816
+ <strong>Q1(家庭人數)- 答對率約 42%</strong><br>
817
+ <span style="color: var(--text-secondary);">問題:學生計數能力不足,容易漏數或多數家庭成員。部分學生混淆「人」與「寵物」的概念。</span>
818
+ </li>
819
+ <li>
820
+ <strong>Q2(沒有名字的人)- 答對率約 83%</strong><br>
821
+ <span style="color: var(--text-secondary);">表現最佳的題目。大部分學生能正確辨識祖父母沒有具體名字。</span>
822
+ </li>
823
+ <li>
824
+ <strong>Q3(想成為老師的人)- 答對率約 50%</strong><br>
825
+ <span style="color: var(--text-secondary);">問題:學生混淆「現在是」(is) 和「想要成為」(wants to be) 的差異。許多人誤答 Bella。</span>
826
+ </li>
827
+ <li>
828
+ <strong>Q4(誰能幫忙功課)- 答對率約 83%</strong><br>
829
+ <span style="color: var(--text-secondary);">大部分學生能正確找到關鍵句並回答。少數學生未根據文章回答。</span>
830
+ </li>
831
+ </ul>
832
+ </div>
833
+ </div>
834
+
835
+ <div class="card insight-card">
836
+ <h3>🎯 教學改進建議 Teaching Recommendations</h3>
837
+
838
+ <ul class="improvement-list">
839
+ <li>
840
+ <strong>加強「細節閱讀」訓練</strong><br>
841
+ 建議在課堂上練習「畫重點」技巧,讓學生在閱讀時標記人物、數字、職業等關鍵資訊。
842
+ </li>
843
+ <li>
844
+ <strong>區分時態與語態</strong><br>
845
+ 針對 Q3 的錯誤,需要加強 "is"(現在式)vs "wants to be"(未來願望)的教學。可設計對比練習讓學生辨別。
846
+ </li>
847
+ <li>
848
+ <strong>強調「根據文章回答」</strong><br>
849
+ 提醒學生看到 "according to the reading" 時,答案必須來自文章,不能憑自己的想像或生活經驗作答。
850
+ </li>
851
+ <li>
852
+ <strong>計數策略教學</strong><br>
853
+ 教導學生在回答「有幾個」類型的問題時,可以先在文章中圈出所有相關的人/物,再逐一計數。
854
+ </li>
855
+ <li>
856
+ <strong>寫作範例分析</strong><br>
857
+ 在課堂上一起分析範例文章的結構,讓學生了解如何組織自我介紹段落。
858
+ </li>
859
+ </ul>
860
+ </div>
861
+
862
+ <div class="card insight-card">
863
+ <h3>🤖 下次出題 Prompt 建議 Next Exam Generation Prompt</h3>
864
+ <p style="margin-bottom: 1rem;">以下是給 AI 生成下次測驗的建議指令,可根據學生弱點調整題型:</p>
865
+
866
+ <div class="prompt-box">
867
+ 請幫我生成一份英文閱讀測驗,針對國中生程度,主題為「家庭與日常生活」。
868
+
869
+ 【文章要求】
870
+ - 長度:150-200 字
871
+ - 難度:國中一年級程度
872
+ - 內容:包含人物介紹、職業、日常活動
873
+ - 確保文章中有些人物有名字、有些人物只有稱謂
874
+
875
+ 【題型要求】
876
+ 1. 計數題(例:文中有幾個人/動物/物品?)
877
+ - 設計時確保答案需要仔細閱讀全文才能得出
878
+
879
+ 2. 細節辨識題(例:誰沒有被提到名字?)
880
+ - 測試學生對細節的注意力
881
+
882
+ 3. 時態辨別題 ⭐ 重點加強
883
+ - 設計「現在是什麼」vs「想要成為什麼」的對比問題
884
+ - 例如:Who IS a teacher? vs Who WANTS TO BE a teacher?
885
+
886
+ 4. 應用推論題
887
+ - 給一個情境,讓學生從文章找出相關資訊
888
+ - 題目需包含 "according to the reading" 提示語
889
+
890
+ 5. 簡答/寫作題
891
+ - 與閱讀主題相關的個人表達
892
+ - 字數限制 60-80 字
893
+ - 提供中文說明和範例
894
+
895
+ 【額外要求】
896
+ - 提供標準答案和評分標準
897
+ - 每題標註測試的閱讀技能
898
+ - 題目需有中英對照
899
+ - 避免使用過於困難的生字
900
+ </div>
901
+ </div>
902
+
903
+ <div class="card insight-card">
904
+ <h3>📝 個別輔導建議 Individual Support</h3>
905
+
906
+ <div style="margin-top: 1rem;">
907
+ <h4 style="color: var(--accent-coral); margin-bottom: 0.5rem;">🔴 需要特別關注的學生:</h4>
908
+ <p><strong>許X彥 (0/70)</strong> - 所有選擇題皆答錯,建議:</p>
909
+ <ul style="margin-left: 1.5rem; margin-top: 0.5rem;">
910
+ <li>一對一確認是否理解題目要求</li>
911
+ <li>檢視是否有閱讀理解的基礎困難</li>
912
+ <li>提供額外的閱讀練習材料</li>
913
+ </ul>
914
+ </div>
915
+
916
+ <div style="margin-top: 1.5rem;">
917
+ <h4 style="color: var(--accent-gold); margin-bottom: 0.5rem;">🟡 需要加強的學生(20/70):</h4>
918
+ <p>大部分學生落在這個分數段,共同的弱點是 Q1(計數題)和 Q3(時態辨別)。建議進行全班性的複習。</p>
919
+ </div>
920
+
921
+ <div style="margin-top: 1.5rem;">
922
+ <h4 style="color: var(--accent-teal); margin-bottom: 0.5rem;">🟢 表現優良的學生(30/70):</h4>
923
+ <p><strong>梁X邦、李X恩、謝X駿</strong> - 可以作為小老師協助同儕學習,或給予進階閱讀材料。</p>
924
+ </div>
925
+ </div>
926
+ </section>
927
+ </main>
928
+
929
+ <footer style="text-align: center; padding: 2rem; color: var(--text-muted); border-top: 1px solid var(--border-color);">
930
+ <p>Unit 1 Quiz Report | Generated by <strong style="color: var(--accent-teal);">taboola-npo-cz-2026</strong> | 慈中英文課 | 2025</p>
931
+ <p style="margin-top: 0.5rem; font-size: 0.85rem;">
932
+ <a href="https://docs.google.com/forms/d/1WT9WrEPnV0U6_VYgEGXHc6geDtfe-Zd5BO6e_Y4ffOc/edit?ts=693672c2"
933
+ target="_blank"
934
+ style="color: var(--text-secondary); text-decoration: none;">
935
+ 📝 View Original Quiz
936
+ </a>
937
+ </p>
938
+ </footer>
939
+
940
+ <script>
941
+ // Score Distribution Chart
942
+ const scoreCtx = document.getElementById('scoreChart').getContext('2d');
943
+ new Chart(scoreCtx, {
944
+ type: 'bar',
945
+ data: {
946
+ labels: ['0分', '10分', '20分', '30分', '40分+'],
947
+ datasets: [{
948
+ label: '學生人數',
949
+ data: [1, 0, 9, 3, 0],
950
+ backgroundColor: [
951
+ 'rgba(255, 107, 107, 0.7)',
952
+ 'rgba(255, 159, 64, 0.7)',
953
+ 'rgba(255, 217, 61, 0.7)',
954
+ 'rgba(78, 205, 196, 0.7)',
955
+ 'rgba(168, 85, 247, 0.7)'
956
+ ],
957
+ borderColor: [
958
+ 'rgba(255, 107, 107, 1)',
959
+ 'rgba(255, 159, 64, 1)',
960
+ 'rgba(255, 217, 61, 1)',
961
+ 'rgba(78, 205, 196, 1)',
962
+ 'rgba(168, 85, 247, 1)'
963
+ ],
964
+ borderWidth: 2,
965
+ borderRadius: 8
966
+ }]
967
+ },
968
+ options: {
969
+ responsive: true,
970
+ plugins: {
971
+ legend: {
972
+ display: false
973
+ }
974
+ },
975
+ scales: {
976
+ y: {
977
+ beginAtZero: true,
978
+ ticks: {
979
+ stepSize: 1,
980
+ color: '#94a3b8'
981
+ },
982
+ grid: {
983
+ color: 'rgba(51, 65, 85, 0.5)'
984
+ }
985
+ },
986
+ x: {
987
+ ticks: {
988
+ color: '#94a3b8'
989
+ },
990
+ grid: {
991
+ display: false
992
+ }
993
+ }
994
+ }
995
+ }
996
+ });
997
+
998
+ // Question Accuracy Chart
999
+ const questionCtx = document.getElementById('questionChart').getContext('2d');
1000
+ new Chart(questionCtx, {
1001
+ type: 'doughnut',
1002
+ data: {
1003
+ labels: ['Q1 家庭人數 (42%)', 'Q2 沒有名字 (83%)', 'Q3 想當老師 (50%)', 'Q4 幫忙功課 (83%)'],
1004
+ datasets: [{
1005
+ data: [42, 83, 50, 83],
1006
+ backgroundColor: [
1007
+ 'rgba(255, 107, 107, 0.8)',
1008
+ 'rgba(78, 205, 196, 0.8)',
1009
+ 'rgba(255, 217, 61, 0.8)',
1010
+ 'rgba(168, 85, 247, 0.8)'
1011
+ ],
1012
+ borderColor: '#1a2332',
1013
+ borderWidth: 3
1014
+ }]
1015
+ },
1016
+ options: {
1017
+ responsive: true,
1018
+ plugins: {
1019
+ legend: {
1020
+ position: 'bottom',
1021
+ labels: {
1022
+ color: '#f1f5f9',
1023
+ padding: 20,
1024
+ font: {
1025
+ size: 12
1026
+ }
1027
+ }
1028
+ }
1029
+ }
1030
+ }
1031
+ });
1032
+
1033
+ // Smooth scroll for navigation
1034
+ document.querySelectorAll('.nav-tab').forEach(tab => {
1035
+ tab.addEventListener('click', function(e) {
1036
+ e.preventDefault();
1037
+ const target = document.querySelector(this.getAttribute('href'));
1038
+ target.scrollIntoView({ behavior: 'smooth' });
1039
+
1040
+ document.querySelectorAll('.nav-tab').forEach(t => t.classList.remove('active'));
1041
+ this.classList.add('active');
1042
+ });
1043
+ });
1044
+
1045
+ // Update active tab on scroll
1046
+ window.addEventListener('scroll', () => {
1047
+ const sections = document.querySelectorAll('section');
1048
+ let current = '';
1049
+
1050
+ sections.forEach(section => {
1051
+ const sectionTop = section.offsetTop;
1052
+ if (scrollY >= sectionTop - 200) {
1053
+ current = section.getAttribute('id');
1054
+ }
1055
+ });
1056
+
1057
+ document.querySelectorAll('.nav-tab').forEach(tab => {
1058
+ tab.classList.remove('active');
1059
+ if (tab.getAttribute('href') === '#' + current) {
1060
+ tab.classList.add('active');
1061
+ }
1062
+ });
1063
+ });
1064
+ </script>
1065
+ </body>
1066
+ </html>
1067
+