Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c65d38d034 |
405
final.html
Normal file
405
final.html
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Tech English Adventure</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Space+Grotesk:wght@500;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
*{margin:0;padding:0;box-sizing:border-box}
|
||||||
|
:root{
|
||||||
|
--bg:#f8f9fc;--card:#ffffff;--border:#e2e5ed;
|
||||||
|
--accent:#4361ee;--accent-light:#eef0ff;
|
||||||
|
--green:#16a34a;--green-bg:#f0fdf4;--green-border:#bbf7d0;
|
||||||
|
--red:#dc2626;--red-bg:#fef2f2;--red-border:#fecaca;
|
||||||
|
--text:#1a1a2e;--body:#3d3d5c;--dim:#8890a4;
|
||||||
|
--shadow:0 1px 3px rgba(0,0,0,.06),0 1px 2px rgba(0,0,0,.04);
|
||||||
|
--shadow-md:0 4px 12px rgba(0,0,0,.07),0 2px 4px rgba(0,0,0,.04);
|
||||||
|
--radius:12px;
|
||||||
|
}
|
||||||
|
html,body{height:100%;overflow:hidden}
|
||||||
|
body{
|
||||||
|
font-family:'DM Sans',system-ui,sans-serif;
|
||||||
|
background:var(--bg);color:var(--text);
|
||||||
|
display:flex;align-items:center;justify-content:center;
|
||||||
|
}
|
||||||
|
body::before{
|
||||||
|
content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
|
||||||
|
background-image:radial-gradient(circle at 1px 1px, #d8dbe5 0.6px, transparent 0);
|
||||||
|
background-size:28px 28px;opacity:.45;
|
||||||
|
}
|
||||||
|
#app{
|
||||||
|
position:relative;z-index:1;
|
||||||
|
width:100%;max-width:760px;height:100vh;
|
||||||
|
display:flex;flex-direction:column;
|
||||||
|
padding:20px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TOP BAR */
|
||||||
|
.topbar{
|
||||||
|
display:flex;justify-content:space-between;align-items:center;
|
||||||
|
padding:14px 20px;
|
||||||
|
background:var(--card);border:1px solid var(--border);
|
||||||
|
border-radius:var(--radius);box-shadow:var(--shadow);
|
||||||
|
margin-bottom:20px;flex-shrink:0;
|
||||||
|
}
|
||||||
|
.topbar h1{
|
||||||
|
font-family:'Space Grotesk',sans-serif;font-size:15px;font-weight:700;
|
||||||
|
color:var(--accent);letter-spacing:1px;
|
||||||
|
}
|
||||||
|
.stats{display:flex;gap:18px;font-size:12px;color:var(--dim);font-weight:500}
|
||||||
|
.stats span{display:flex;align-items:center;gap:5px}
|
||||||
|
.stats .val{color:var(--accent);font-weight:700;font-family:'JetBrains Mono',monospace}
|
||||||
|
.xp-bar{width:72px;height:5px;background:var(--border);border-radius:3px;overflow:hidden}
|
||||||
|
.xp-fill{height:100%;background:var(--accent);border-radius:3px;transition:width .6s ease}
|
||||||
|
|
||||||
|
/* PROGRESS */
|
||||||
|
.progress{display:flex;gap:4px;margin-bottom:20px;flex-shrink:0}
|
||||||
|
.progress .dot{flex:1;height:4px;border-radius:2px;background:var(--border);transition:background .3s ease}
|
||||||
|
.progress .dot.done{background:var(--green)}
|
||||||
|
.progress .dot.active{background:var(--accent)}
|
||||||
|
|
||||||
|
/* SCENE */
|
||||||
|
.scene-area{
|
||||||
|
flex:1;overflow-y:auto;display:flex;flex-direction:column;
|
||||||
|
scrollbar-width:thin;scrollbar-color:var(--border) transparent;
|
||||||
|
}
|
||||||
|
.scene-label{
|
||||||
|
font-family:'JetBrains Mono',monospace;font-size:11px;font-weight:600;
|
||||||
|
letter-spacing:2px;text-transform:uppercase;
|
||||||
|
color:var(--accent);background:var(--accent-light);
|
||||||
|
display:inline-block;padding:5px 12px;border-radius:6px;
|
||||||
|
margin-bottom:14px;
|
||||||
|
}
|
||||||
|
.scene-title{
|
||||||
|
font-family:'Space Grotesk',sans-serif;
|
||||||
|
font-size:clamp(22px,4vw,30px);font-weight:700;
|
||||||
|
line-height:1.25;margin-bottom:18px;color:var(--text);
|
||||||
|
}
|
||||||
|
.scene-text{
|
||||||
|
font-size:15px;line-height:1.85;color:var(--body);
|
||||||
|
margin-bottom:28px;max-width:680px;
|
||||||
|
}
|
||||||
|
.scene-text .highlight{
|
||||||
|
color:var(--accent);font-weight:600;
|
||||||
|
border-bottom:2px dotted var(--accent);cursor:help;
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
.scene-text .highlight:hover::after{
|
||||||
|
content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:0;
|
||||||
|
background:var(--text);color:#fff;
|
||||||
|
padding:6px 12px;font-size:12px;border-radius:8px;
|
||||||
|
white-space:nowrap;z-index:10;box-shadow:var(--shadow-md);
|
||||||
|
}
|
||||||
|
.scene-text .highlight:hover::before{
|
||||||
|
content:'';position:absolute;bottom:calc(100% + 2px);left:14px;
|
||||||
|
border:5px solid transparent;border-top-color:var(--text);z-index:10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CHOICES */
|
||||||
|
.choices{display:flex;flex-direction:column;gap:10px;margin-top:auto;padding-bottom:20px}
|
||||||
|
.choice-btn{
|
||||||
|
background:var(--card);border:1.5px solid var(--border);
|
||||||
|
color:var(--text);font-family:'DM Sans',sans-serif;
|
||||||
|
font-size:14px;font-weight:500;padding:16px 18px;border-radius:var(--radius);
|
||||||
|
cursor:pointer;text-align:left;
|
||||||
|
transition:all .2s ease;
|
||||||
|
display:flex;align-items:center;gap:14px;
|
||||||
|
box-shadow:var(--shadow);
|
||||||
|
}
|
||||||
|
.choice-btn .key{
|
||||||
|
font-family:'JetBrains Mono',monospace;font-size:12px;font-weight:700;
|
||||||
|
color:#fff;background:var(--accent);
|
||||||
|
width:30px;height:30px;border-radius:8px;
|
||||||
|
display:flex;align-items:center;justify-content:center;flex-shrink:0;
|
||||||
|
}
|
||||||
|
.choice-btn:hover{
|
||||||
|
border-color:var(--accent);
|
||||||
|
box-shadow:var(--shadow-md),0 0 0 3px var(--accent-light);
|
||||||
|
transform:translateY(-2px);
|
||||||
|
}
|
||||||
|
.choice-btn.correct{
|
||||||
|
border-color:var(--green);background:var(--green-bg);
|
||||||
|
box-shadow:0 0 0 3px var(--green-border);animation:pop .35s ease;
|
||||||
|
}
|
||||||
|
.choice-btn.correct .key{background:var(--green)}
|
||||||
|
.choice-btn.wrong{
|
||||||
|
border-color:var(--red);background:var(--red-bg);
|
||||||
|
box-shadow:0 0 0 3px var(--red-border);animation:shake .4s ease;
|
||||||
|
}
|
||||||
|
.choice-btn.wrong .key{background:var(--red)}
|
||||||
|
@keyframes pop{0%{transform:scale(1)}50%{transform:scale(1.015)}100%{transform:scale(1)}}
|
||||||
|
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
|
||||||
|
|
||||||
|
/* FEEDBACK */
|
||||||
|
.feedback{
|
||||||
|
margin-top:14px;padding:16px 20px;border-radius:var(--radius);
|
||||||
|
font-size:13.5px;line-height:1.7;font-weight:500;animation:fadeIn .3s ease;
|
||||||
|
}
|
||||||
|
.feedback.ok{background:var(--green-bg);border:1px solid var(--green-border);color:var(--green)}
|
||||||
|
.feedback.no{background:var(--red-bg);border:1px solid var(--red-border);color:var(--red)}
|
||||||
|
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
|
||||||
|
|
||||||
|
.next-btn{
|
||||||
|
margin-top:16px;align-self:flex-end;
|
||||||
|
background:var(--accent);color:#fff;border:none;
|
||||||
|
font-family:'DM Sans',sans-serif;font-size:13px;font-weight:700;
|
||||||
|
letter-spacing:.5px;padding:12px 28px;border-radius:10px;cursor:pointer;
|
||||||
|
transition:all .2s ease;box-shadow:0 2px 8px rgba(67,97,238,.3);
|
||||||
|
}
|
||||||
|
.next-btn:hover{transform:translateY(-2px);box-shadow:0 4px 16px rgba(67,97,238,.35)}
|
||||||
|
|
||||||
|
/* END */
|
||||||
|
.end-screen{
|
||||||
|
display:flex;flex-direction:column;align-items:center;justify-content:center;
|
||||||
|
text-align:center;flex:1;gap:16px;
|
||||||
|
}
|
||||||
|
.end-screen .grade{font-family:'Space Grotesk',sans-serif;font-size:72px;font-weight:700;color:var(--accent)}
|
||||||
|
.end-screen p{font-size:15px;color:var(--body);max-width:480px;line-height:1.7}
|
||||||
|
.end-screen .dim-text{font-size:12px;color:var(--dim)}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app">
|
||||||
|
<div class="topbar">
|
||||||
|
<h1>Tech English</h1>
|
||||||
|
<div class="stats">
|
||||||
|
<span>XP <span class="val" id="xp">0</span></span>
|
||||||
|
<span><div class="xp-bar"><div class="xp-fill" id="xpBar" style="width:0%"></div></div></span>
|
||||||
|
<span>Lv <span class="val" id="lvl">1</span></span>
|
||||||
|
<span><span class="val" id="score">0</span>/<span id="total">0</span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="progress" id="progress"></div>
|
||||||
|
<div class="scene-area" id="scene"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const GAME = [
|
||||||
|
{
|
||||||
|
chapter:"Chapter 1 — The AI Lab",
|
||||||
|
title:"Neural Network Initialization",
|
||||||
|
text:`You step into the AI research lab. The lead scientist greets you: <br><br>"We need to <span class="highlight" data-tip="train = trénovať model na dátach">train</span> our new deep learning model, but first we must choose the right <span class="highlight" data-tip="architecture = architektúra siete">architecture</span>. The dataset contains 50 million <span class="highlight" data-tip="labeled = označené, s anotáciami">labeled</span> images."<br><br>She asks: <b>"Which approach should we use for image classification?"</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"A Convolutional Neural Network (CNN) — it excels at spatial feature extraction in images.",correct:true},
|
||||||
|
{text:"A simple Recurrent Neural Network (RNN) — it processes sequences efficiently.",correct:false}
|
||||||
|
],
|
||||||
|
ok:"Excellent! CNNs use convolutional layers to detect spatial patterns like edges, textures, and shapes — making them ideal for image tasks.",
|
||||||
|
no:"Not quite. RNNs are designed for sequential data like text or time series. For images, a CNN is the standard choice because it captures spatial hierarchies of features."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 1 — The AI Lab",
|
||||||
|
title:"The Overfitting Problem",
|
||||||
|
text:`Your CNN reaches 99% accuracy on training data, but only 61% on the test set. A colleague warns:<br><br>"The model is <span class="highlight" data-tip="overfitting = preučenie, model sa naučí šum namiesto vzorov">overfitting</span>. It has memorized the training data instead of learning <span class="highlight" data-tip="generalizable = zovšeobecniteľné">generalizable</span> patterns."<br><br><b>What technique would best help reduce overfitting?</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"Increase the learning rate to make the model converge faster.",correct:false},
|
||||||
|
{text:"Apply dropout regularization and use data augmentation.",correct:true}
|
||||||
|
],
|
||||||
|
ok:"Correct! Dropout randomly disables neurons during training, forcing the network to learn robust features. Data augmentation increases effective dataset size through transformations.",
|
||||||
|
no:"Increasing the learning rate might actually make things worse — it can cause unstable training. Dropout and data augmentation are proven techniques against overfitting."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 1 — The AI Lab",
|
||||||
|
title:"Deploying the Model",
|
||||||
|
text:`The model performs well. Now you must <span class="highlight" data-tip="deploy = nasadiť do prevádzky">deploy</span> it to production. The engineering lead says:<br><br>"We need low <span class="highlight" data-tip="latency = oneskorenie, čas odozvy">latency</span> inference. The model must respond within 50 milliseconds per request."<br><br><b>What should you prioritize?</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"Use model quantization and optimize the inference pipeline with ONNX Runtime.",correct:true},
|
||||||
|
{text:"Train a larger model with more parameters for better accuracy.",correct:false}
|
||||||
|
],
|
||||||
|
ok:"Right! Quantization reduces model size and speeds up inference by using lower-precision arithmetic. ONNX Runtime is optimized for fast inference across hardware.",
|
||||||
|
no:"A larger model would increase latency, not reduce it. For real-time deployment, optimization techniques like quantization and efficient runtimes are essential."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 2 — Robotics Bay",
|
||||||
|
title:"Sensor Fusion Challenge",
|
||||||
|
text:`You enter the robotics bay. An autonomous rover sits on the test platform. The robotics engineer explains:<br><br>"The rover uses <span class="highlight" data-tip="sensor fusion = fúzia senzorov, kombinovanie dát z rôznych snímačov">sensor fusion</span> to navigate. We combine data from LiDAR, cameras, and <span class="highlight" data-tip="IMU = Inertial Measurement Unit, inerciálna meracia jednotka">IMU</span> sensors."<br><br><b>"Which algorithm is most commonly used for probabilistic sensor fusion in robotics?"</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"The Kalman Filter — it provides optimal state estimation for linear systems with Gaussian noise.",correct:true},
|
||||||
|
{text:"Binary search — it efficiently finds data points in sorted sensor arrays.",correct:false}
|
||||||
|
],
|
||||||
|
ok:"Exactly! The Kalman Filter (and its variants like EKF and UKF) is fundamental in robotics for fusing noisy sensor data into accurate state estimates.",
|
||||||
|
no:"Binary search is a data structure algorithm, not a sensor fusion technique. The Kalman Filter is the standard approach for combining uncertain sensor measurements."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 2 — Robotics Bay",
|
||||||
|
title:"Actuator Failure",
|
||||||
|
text:`An alarm sounds. The rover's left <span class="highlight" data-tip="actuator = aktuátor, pohonná jednotka">actuator</span> has failed during a test run. The system log shows:<br><br><code style="color:var(--red);background:var(--red-bg);padding:3px 8px;border-radius:6px;font-family:JetBrains Mono,monospace;font-size:13px">ERROR: Torque feedback loop — signal loss on joint_3</code><br><br>The engineer asks: <b>"What does the feedback loop do in a servo actuator?"</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"It continuously compares the desired position with the actual position and adjusts the motor output accordingly.",correct:true},
|
||||||
|
{text:"It stores previous movement commands in a database for later analysis.",correct:false}
|
||||||
|
],
|
||||||
|
ok:"Correct! A feedback loop (closed-loop control) constantly measures the actual state and corrects errors — this is fundamental to precise robotic motion.",
|
||||||
|
no:"That describes logging, not feedback control. A feedback loop actively compares the target state with the measured state in real-time to correct deviations."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 2 — Robotics Bay",
|
||||||
|
title:"Path Planning",
|
||||||
|
text:`The actuator is repaired. Now you must program the rover's <span class="highlight" data-tip="path planning = plánovanie trasy">path planning</span> module for an obstacle course.<br><br>"The environment is partially known. The rover will encounter <span class="highlight" data-tip="dynamic obstacles = dynamické prekážky, meniace sa v čase">dynamic obstacles</span> that move unpredictably."<br><br><b>Which path planning approach is best suited?</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"A hardcoded sequence of waypoints based on the initial map.",correct:false},
|
||||||
|
{text:"A reactive algorithm like D* Lite that replans in real-time as new obstacles are detected.",correct:true}
|
||||||
|
],
|
||||||
|
ok:"Perfect! D* Lite and similar algorithms efficiently update the path when the environment changes, which is essential for dynamic obstacle avoidance.",
|
||||||
|
no:"Hardcoded waypoints cannot adapt to moving obstacles. Reactive algorithms like D* Lite continuously update the path based on new sensor data."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 3 — Flight Simulation Center",
|
||||||
|
title:"Autopilot Systems",
|
||||||
|
text:`You're now at the flight simulation center. A UAV (<span class="highlight" data-tip="UAV = Unmanned Aerial Vehicle, bezpilotný lietajúci prostriedok">Unmanned Aerial Vehicle</span>) prototype is being tested.<br><br>The avionics engineer explains: "The <span class="highlight" data-tip="autopilot = autopilot, systém automatického riadenia letu">autopilot</span> uses a PID controller for altitude hold. But we're experiencing <span class="highlight" data-tip="oscillation = oscilácia, kmitanie okolo cieľovej hodnoty">oscillation</span> around the target altitude."<br><br><b>What is the most likely cause?</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"The proportional gain (Kp) is too high, causing the system to overcorrect repeatedly.",correct:true},
|
||||||
|
{text:"The UAV's battery is running low, reducing thrust capacity.",correct:false}
|
||||||
|
],
|
||||||
|
ok:"Correct! When Kp is too high, the controller overreacts to errors, creating oscillations. Tuning PID parameters is critical in flight control systems.",
|
||||||
|
no:"While low battery affects performance, the symptom described — oscillation around a setpoint — is a classic sign of excessive proportional gain in a PID controller."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 3 — Flight Simulation Center",
|
||||||
|
title:"Aerodynamic Vocabulary",
|
||||||
|
text:`The test pilot briefs you before a simulation run:<br><br>"During <span class="highlight" data-tip="takeoff = vzlet">takeoff</span>, the aircraft must generate enough <span class="highlight" data-tip="lift = vztlak">lift</span> to overcome its weight. The shape of the <span class="highlight" data-tip="airfoil = profil krídla">airfoil</span> creates a pressure difference between the upper and lower surfaces of the wing."<br><br><b>What is the primary factor that increases lift during takeoff?</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"Increasing the airspeed, which increases the pressure differential across the wing surface.",correct:true},
|
||||||
|
{text:"Reducing the aircraft's drag coefficient by retracting all control surfaces.",correct:false}
|
||||||
|
],
|
||||||
|
ok:"Right! According to Bernoulli's principle, higher airspeed creates greater pressure differential across the airfoil, generating more lift. That's why aircraft accelerate on the runway.",
|
||||||
|
no:"Retracting control surfaces would reduce the effective lift area. Lift increases primarily with airspeed — this is why a takeoff roll is necessary."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 3 — Flight Simulation Center",
|
||||||
|
title:"Communication Protocol",
|
||||||
|
text:`You're monitoring the UAV's <span class="highlight" data-tip="telemetry = telemetria, diaľkový prenos meraných dát">telemetry</span> link. The ground station receives data packets containing altitude, speed, GPS coordinates, and battery status.<br><br>Suddenly the link becomes <span class="highlight" data-tip="intermittent = prerušovaný, nestály">intermittent</span>. The signal drops every few seconds.<br><br><b>What is the best immediate response?</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"Ignore the issue and continue the mission — some packet loss is normal.",correct:false},
|
||||||
|
{text:"Switch to the redundant communication channel and initiate a return-to-home protocol.",correct:true}
|
||||||
|
],
|
||||||
|
ok:"Correct! Redundancy is a core safety principle in aerospace. Switching to a backup link and initiating RTH ensures the UAV remains under control.",
|
||||||
|
no:"In aerospace, intermittent communication is a serious safety concern. Ignoring it could lead to loss of control. Redundant systems and fail-safe protocols exist for exactly this reason."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 4 — Systems Integration",
|
||||||
|
title:"The Grand Challenge",
|
||||||
|
text:`It's time to integrate everything. Your team is building an <span class="highlight" data-tip="autonomous = autonómny, samočinný">autonomous</span> delivery drone that uses AI for navigation, robotic arms for package handling, and must comply with <span class="highlight" data-tip="airspace regulations = predpisy pre vzdušný priestor">airspace regulations</span>.<br><br>The project manager asks: <b>"What is the most critical engineering principle for this system?"</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"Making the drone as fast as possible to maximize delivery throughput.",correct:false},
|
||||||
|
{text:"Designing with redundancy, fail-safes, and graceful degradation at every subsystem level.",correct:true}
|
||||||
|
],
|
||||||
|
ok:"Excellent! Safety-critical systems require redundancy (backup components), fail-safes (safe defaults on failure), and graceful degradation (maintaining partial function). Speed is secondary to reliability.",
|
||||||
|
no:"Speed without safety is dangerous, especially in autonomous aerial systems. The correct principle is defense-in-depth: redundancy, fail-safes, and graceful degradation."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
chapter:"Chapter 4 — Systems Integration",
|
||||||
|
title:"Technical Report",
|
||||||
|
text:`Your project succeeds. Now you must write a <span class="highlight" data-tip="technical report = technická správa">technical report</span> for the stakeholders. A senior engineer reviews your draft and comments:<br><br>"Your abstract should be a <span class="highlight" data-tip="concise = stručný, výstižný">concise</span> summary of the entire project — objectives, methods, results, and conclusions — in one paragraph."<br><br><b>Which of these is a well-written opening for a technical abstract?</b>`,
|
||||||
|
choices:[
|
||||||
|
{text:"'This paper presents the design, implementation, and evaluation of an autonomous delivery UAV system integrating CNN-based navigation with redundant flight control.'",correct:true},
|
||||||
|
{text:"'In this report we will talk about our drone project and explain the cool things we did with AI and robots.'",correct:false}
|
||||||
|
],
|
||||||
|
ok:"Perfect! Technical writing requires precise, formal language. The correct abstract clearly states the scope (design, implementation, evaluation) and key technologies used.",
|
||||||
|
no:"Technical writing must be formal, precise, and specific. Words like 'cool things' and 'talk about' are too informal for an engineering report."
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let current=0, xp=0, answered=0, correct=0, locked=false;
|
||||||
|
const scene=document.getElementById('scene');
|
||||||
|
const xpEl=document.getElementById('xp'), lvlEl=document.getElementById('lvl');
|
||||||
|
const scoreEl=document.getElementById('score'), totalEl=document.getElementById('total');
|
||||||
|
const xpBar=document.getElementById('xpBar');
|
||||||
|
const progressEl=document.getElementById('progress');
|
||||||
|
|
||||||
|
totalEl.textContent=GAME.length;
|
||||||
|
GAME.forEach(()=>{const d=document.createElement('div');d.className='dot';progressEl.appendChild(d)});
|
||||||
|
|
||||||
|
function updateProgress(){
|
||||||
|
progressEl.querySelectorAll('.dot').forEach((d,i)=>{
|
||||||
|
d.className='dot';
|
||||||
|
if(i<current) d.classList.add('done');
|
||||||
|
if(i===current) d.classList.add('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateStats(){
|
||||||
|
xpEl.textContent=xp;
|
||||||
|
lvlEl.textContent=Math.floor(xp/30)+1;
|
||||||
|
scoreEl.textContent=correct;
|
||||||
|
xpBar.style.width=((xp%30)/30*100)+'%';
|
||||||
|
}
|
||||||
|
|
||||||
|
function render(){
|
||||||
|
locked=false;updateProgress();
|
||||||
|
const q=GAME[current];
|
||||||
|
scene.innerHTML=`
|
||||||
|
<div class="scene-label">${q.chapter}</div>
|
||||||
|
<div class="scene-title">${q.title}</div>
|
||||||
|
<div class="scene-text">${q.text}</div>
|
||||||
|
<div class="choices" id="choices">
|
||||||
|
${q.choices.map((c,i)=>`
|
||||||
|
<button class="choice-btn" onclick="answer(${i})">
|
||||||
|
<span class="key">${String.fromCharCode(65+i)}</span>
|
||||||
|
<span>${c.text}</span>
|
||||||
|
</button>
|
||||||
|
`).join('')}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
scene.scrollTop=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function answer(idx){
|
||||||
|
if(locked) return;
|
||||||
|
locked=true;answered++;
|
||||||
|
const q=GAME[current];
|
||||||
|
const btns=document.querySelectorAll('.choice-btn');
|
||||||
|
const isCorrect=q.choices[idx].correct;
|
||||||
|
if(isCorrect){correct++;xp+=20}else{xp+=5}
|
||||||
|
updateStats();
|
||||||
|
btns.forEach((b,i)=>{
|
||||||
|
if(i===idx) b.classList.add(isCorrect?'correct':'wrong');
|
||||||
|
if(q.choices[i].correct&&i!==idx){b.style.borderColor='var(--green)';b.style.opacity='.5'}
|
||||||
|
b.style.pointerEvents='none';
|
||||||
|
});
|
||||||
|
const fb=document.createElement('div');
|
||||||
|
fb.className='feedback '+(isCorrect?'ok':'no');
|
||||||
|
fb.innerHTML=(isCorrect?'✓ ':'✗ ')+(isCorrect?q.ok:q.no);
|
||||||
|
document.getElementById('choices').after(fb);
|
||||||
|
if(current<GAME.length-1){
|
||||||
|
const nb=document.createElement('button');
|
||||||
|
nb.className='next-btn';nb.textContent='Continue \u2192';
|
||||||
|
nb.onclick=()=>{current++;render()};
|
||||||
|
fb.after(nb);setTimeout(()=>nb.focus(),100);
|
||||||
|
} else {
|
||||||
|
const nb=document.createElement('button');
|
||||||
|
nb.className='next-btn';nb.textContent='See Results \u2192';
|
||||||
|
nb.onclick=showEnd;fb.after(nb);
|
||||||
|
}
|
||||||
|
fb.scrollIntoView({behavior:'smooth',block:'nearest'});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEnd(){
|
||||||
|
const pct=Math.round(correct/GAME.length*100);
|
||||||
|
let grade,msg;
|
||||||
|
if(pct>=90){grade='A+';msg="Outstanding! Your technical English is at a professional level. You're ready to write papers and present at conferences."}
|
||||||
|
else if(pct>=70){grade='B+';msg="Great work! You have a solid grasp of technical vocabulary. Review the terms you missed and you'll be fully fluent in engineering English."}
|
||||||
|
else if(pct>=50){grade='C';msg="Decent foundation, but there's room to grow. Revisit the highlighted terms and try again \u2014 repetition builds mastery."}
|
||||||
|
else{grade='D';msg="Keep studying! Technical English takes practice. Focus on the vocabulary highlights and give it another shot."}
|
||||||
|
progressEl.querySelectorAll('.dot').forEach(d=>d.className='dot done');
|
||||||
|
scene.innerHTML=`
|
||||||
|
<div class="end-screen">
|
||||||
|
<div class="scene-label">Mission Complete</div>
|
||||||
|
<div class="grade">${grade}</div>
|
||||||
|
<div class="scene-title" style="text-align:center">${correct} / ${GAME.length} Correct (${pct}%)</div>
|
||||||
|
<p>${msg}</p>
|
||||||
|
<p class="dim-text">Total XP earned: ${xp} \u00b7 Level ${Math.floor(xp/30)+1}</p>
|
||||||
|
<button class="next-btn" onclick="current=0;xp=0;answered=0;correct=0;updateStats();render()">Play Again \u21bb</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keydown',e=>{
|
||||||
|
if(locked) return;
|
||||||
|
if(e.key==='1'||e.key==='a'||e.key==='A') answer(0);
|
||||||
|
if(e.key==='2'||e.key==='b'||e.key==='B') answer(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
render();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user