🎮ArcadeLab

Transportation Speaking Challenge

by PhantomDragon26
272 lines7.1 KB
▶ Play

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Transportation Speaking Challenge</title>
<style>
* { box-sizing: border-box; }
body {
  margin: 0;
  padding: 20px;
  font-family: Arial, sans-serif;
  background: linear-gradient(135deg,#dbeafe,#eff6ff);
  color: #183153;
  text-align: center;
}
.container {
  max-width: 650px;
  margin: 20px auto;
  background: white;
  padding: 25px;
  border-radius: 22px;
  box-shadow: 0 8px 25px #52749b30;
}
h1 { color: #1764a5; }
.subtitle { color: #64748b; }
.progress {
  background: #e2e8f0;
  height: 10px;
  border-radius: 20px;
  margin: 20px 0;
  overflow: hidden;
}
.bar {
  background: #22c55e;
  height: 100%;
  width: 0%;
  transition: .3s;
}
.question {
  background: #eff6ff;
  border-radius: 16px;
  padding: 22px;
  margin: 20px 0;
}
.question h2 { font-size: 22px; }
.mic {
  background: #2563eb;
  color: white;
  border: none;
  border-radius: 50px;
  padding: 17px 28px;
  font-size: 18px;
  font-weight: bold;
  cursor: pointer;
  margin: 10px;
}
.mic:disabled { background: #94a3b8; }
.next {
  background: #16a34a;
  color: white;
  border: none;
  padding: 14px 25px;
  border-radius: 12px;
  font-size: 17px;
  cursor: pointer;
  display: none;
  margin: 15px auto;
}
.answer {
  background: #f8fafc;
  border: 2px dashed #93c5fd;
  border-radius: 12px;
  padding: 15px;
  min-height: 55px;
  margin: 15px 0;
  color: #334155;
}
.feedback {
  font-weight: bold;
  min-height: 28px;
  margin: 12px;
}
.small { font-size: 14px; color: #64748b; }
</style>
</head>
<body>
<div class="container">
  <div style="font-size:48px">🚌 🚆 ✈️</div>
  <h1>Transportation Speaking Challenge</h1>
  <p class="subtitle">Year 6 English Assessment | Easy Level</p>

  <p><b>Instructions:</b> Listen to the passage carefully.
  Then, press the microphone and answer each question in English.</p>

  <div class="progress"><div class="bar" id="bar"></div></div>
  <p id="count">Question 1 of 2</p>

  <div class="question">
    <div style="font-size:35px" id="emoji">🚌</div>
    <h2 id="question">What transportation does Amir suggest?</h2>
  </div>

  <button class="mic" id="mic" onclick="startListening()">
    🎤 Start Speaking
  </button>

  <p class="small" id="status">Press the microphone to answer.</p>

  <div class="answer" id="answer">
    Your spoken answer will appear here.
  </div>

  <div class="feedback" id="feedback"></div>

  <button class="next" id="next" onclick="nextQuestion()">
    Next Question →
  </button>

  <div id="finish" style="display:none">
    <h2>🎉 Assessment Completed!</h2>
    <p id="score"></p>
    <button class="next" style="display:inline-block"
      onclick="location.reload()">Try Again</button>
  </div>
</div>

<script>
const questions = [
  {
    question: "What transportation does Amir suggest?",
    emoji: "🚌",
    check: text => /\bbus\b/i.test(text),
    success: "Excellent! Amir suggests travelling by bus."
  },
  {
    question: "Why does Amir think travelling by bus is a good choice?",
    emoji: "💡",
    check: text => {
      const t = text.toLowerCase();
      const many = /\b(many|lots of|a lot of|whole class|all the pupils|students|pupils|people)\b/.test(t);
      const cheap = /\b(cheap|cheaper|affordable|low cost|less expensive|save money|cost)\b/.test(t);
      return many && cheap;
    },
    success: "Great job! You mentioned both advantages."
  }
];

let current = 0;
let score = 0;
let recognition;
let answered = false;

function showQuestion() {
  const q = questions[current];
  document.getElementById("question").textContent = q.question;
  document.getElementById("emoji").textContent = q.emoji;
  document.getElementById("count").textContent =
    `Question ${current + 1} of 2`;
  document.getElementById("bar").style.width =
    (current / 2 * 100) + "%";
  document.getElementById("answer").textContent =
    "Your spoken answer will appear here.";
  document.getElementById("feedback").textContent = "";
  document.getElementById("status").textContent =
    "Press the microphone to answer.";
  document.getElementById("next").style.display = "none";
  document.getElementById("mic").disabled = false;
  answered = false;
}

function startListening() {
  const SpeechRecognition =
    window.SpeechRecognition || window.webkitSpeechRecognition;

  if (!SpeechRecognition) {
    document.getElementById("status").textContent =
      "Speech recognition is not supported in this browser. Try Chrome.";
    return;
  }

  recognition = new SpeechRecognition();
  recognition.lang = "en-US";
  recognition.continuous = false;
  recognition.interimResults = false;

  document.getElementById("mic").disabled = true;
  document.getElementById("status").textContent =
    "🎙️ Listening... Speak clearly in English.";

  recognition.onresult = function(event) {
    const spoken = event.results[0][0].transcript;
    document.getElementById("answer").textContent = spoken;
    checkAnswer(spoken);
  };

  recognition.onerror = function(event) {
    document.getElementById("status").textContent =
      "Microphone error: " + event.error +
      ". Please check microphone permission and try again.";
    document.getElementById("mic").disabled = false;
  };

  recognition.onend = function() {
    if (!answered) {
      document.getElementById("mic").disabled = false;
    }
  };

  try {
    recognition.start();
  } catch(e) {
    document.getElementById("status").textContent =
      "Please try pressing the microphone again.";
    document.getElementById("mic").disabled = false;
  }
}

function checkAnswer(spoken) {
  const q = questions[current];
  const correct = q.check(spoken);

  answered = true;

  if (correct) {
    score++;
    document.getElementById("feedback").textContent =
      "✅ " + q.success;
    document.getElementById("feedback").style.color = "#15803d";
  } else {
    document.getElementById("feedback").textContent =
      "Keep trying! Listen to the passage and try again.";
    document.getElementById("feedback").style.color = "#dc2626";
  }

  document.getElementById("status").textContent =
    "You can try again if your answer needs improvement.";

  if (correct) {
    document.getElementById("next").style.display = "inline-block";
    document.getElementById("mic").disabled = true;
  } else {
    document.getElementById("mic").disabled = false;
  }
}

function nextQuestion() {
  current++;

  if (current < questions.length) {
    showQuestion();
  } else {
    document.getElementById("question").style.display = "none";
    document.getElementById("emoji").style.display = "none";
    document.getElementById("mic").style.display = "none";
    document.getElementById("answer").style.display = "none";
    document.getElementById("feedback").style.display = "none";
    document.getElementById("next").style.display = "none";
    document.getElementById("count").textContent = "Completed";
    document.getElementById("bar").style.width = "100%";
    document.getElementById("finish").style.display = "block";
    document.getElementById("score").textContent =
      "Your score: " + score + " / 2";
  }
}

showQuestion();
</script>
</body>
</html>

Game Source: Transportation Speaking Challenge

Creator: PhantomDragon26

Libraries: none

Complexity: complex (272 lines, 7.1 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: transportation-speaking-challenge-phantomdragon26" to link back to the original. Then publish at arcadelab.ai/publish.