403 lines
12 KiB
JavaScript
403 lines
12 KiB
JavaScript
var tdv_sdk = {};
|
||
tdv_sdk.list = [
|
||
// --- PART 1: TRẮC NGHIỆM THÔNG THƯỜNG (Q1 - Q8) ---
|
||
{
|
||
id: "q1",
|
||
question: "Which is a sports-related subject?",
|
||
options: ["English", "Math", "P.E", "Art"],
|
||
answer: "P.E",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q2",
|
||
question: "Which day comes after Thursday?",
|
||
options: ["Wednesday", "Friday", "Monday", "Sunday"],
|
||
answer: "Friday",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q3",
|
||
question: "Which sentence is grammatically correct?",
|
||
options: [
|
||
"Jim brush his teeth every morning",
|
||
"Jim brushes his teeth every morning",
|
||
"Jim brushing his teeth every morning",
|
||
"Jim brush teeth every morning",
|
||
],
|
||
answer: "Jim brushes his teeth every morning",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q4",
|
||
question: "Which sentence is correct and complete?",
|
||
options: [
|
||
"Jim catch the bus to school",
|
||
"Jim catches the bus to school",
|
||
"Jim catching the bus to school",
|
||
"Jim catch bus to the school",
|
||
],
|
||
answer: "Jim catches the bus to school",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q5",
|
||
question: "Where can you swim?",
|
||
options: ["Skatepark", "Café", "Pool", "Market"],
|
||
answer: "Pool",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q6",
|
||
question: "I ___ play soccer on Saturdays.",
|
||
options: ["always", "never", "sometimes", "often"],
|
||
answer: "always",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q7",
|
||
question: "Which food is a fruit?",
|
||
options: ["Onion", "Melon", "Cucumber", "Soda"],
|
||
answer: "Melon",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q8",
|
||
question: "Which vehicle can fly?",
|
||
options: ["Scooter", "Plane", "Bus", "Motorcycle"],
|
||
answer: "Plane",
|
||
audio: "",
|
||
},
|
||
|
||
// --- PART 2: LISTENING (Q9 - Q18) ---
|
||
{
|
||
id: "q9",
|
||
question: "Which country is liked for the beaches?",
|
||
options: ["Vietnam", "USA", "Australia", "None"],
|
||
answer: "Australia",
|
||
text: "I love Vietnam for the food. I like Australia for the beaches.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_i_love_vietnam_for_the_food_i_like_australia_for_t_f31e1ced.mp3",
|
||
},
|
||
{
|
||
id: "q10",
|
||
question: "Who played the guitar?",
|
||
options: ["Adults", "Children", "Both adults and children", "Nobody"],
|
||
answer: "Children",
|
||
text: "Ancient Mayans: They cooked, played soccer, listened to music, and watched TV. Some children played the guitar.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_ancient_mayans_they_cooked_played_soccer_listened__598f2474.mp3",
|
||
},
|
||
{
|
||
id: "q11",
|
||
question: "What does he do just before catching the bus?",
|
||
options: [
|
||
"Take a shower",
|
||
"Get dressed",
|
||
"Eat breakfast",
|
||
"Brush his teeth",
|
||
],
|
||
answer: "Eat breakfast",
|
||
text: "Hello! My name is Jim. I wake up at 7 o’clock. I brush my teeth first. Then I take a shower.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_hi_im_jim_every_morning_i_wake_up_and_brush_my_tee_3db5a156.mp3",
|
||
},
|
||
{
|
||
id: "q12",
|
||
question: "Which activity never happens on Sunday?",
|
||
options: [
|
||
"Play soccer",
|
||
"Go swimming",
|
||
"Visit playground",
|
||
"Play in the playground",
|
||
],
|
||
answer: "Go swimming",
|
||
text: "On Saturday: go swimming and visit the café. On Sunday: play soccer in playground.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_on_saturday_go_swimming_and_visit_the_caf_on_sunda_4f96f850.mp3",
|
||
},
|
||
{
|
||
id: "q13",
|
||
question: "What does Jim do first in the morning?",
|
||
options: [
|
||
"Take a shower",
|
||
"Get dressed",
|
||
"Brush his teeth",
|
||
"Catch the bus",
|
||
],
|
||
answer: "Brush his teeth",
|
||
text: "Hello! My name is Jim. I wake up at 7 o’clock. I brush my teeth first. Then I take a shower.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_joey_hello_my_name_is_jim_i_wake_up_at_7_oclock_i_brush_bca57fd7.mp3",
|
||
},
|
||
{
|
||
id: "q14",
|
||
question: "Which activity is unique to children?",
|
||
options: ["Cook", "Play soccer", "Play the guitar", "Watch TV"],
|
||
answer: "Play the guitar",
|
||
text: "The ancient Mayans lived a long time ago... Some children played the guitar.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_the_ancient_mayans_lived_a_long_time_ago_they_cook_3aa99042.mp3",
|
||
},
|
||
{
|
||
id: "q15",
|
||
question: "Which activity happens only on Saturday?",
|
||
options: [
|
||
"Visit the café sometimes",
|
||
"Play soccer",
|
||
"Go swimming",
|
||
"Play soccer on Sunday",
|
||
],
|
||
answer: "Go swimming",
|
||
text: "On Saturdays, we go swimming at the pool... On Sundays, we play soccer in the playground.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_on_saturdays_we_go_swimming_at_the_pool_we_sometim_a76733ec.mp3",
|
||
},
|
||
{
|
||
id: "q16",
|
||
question: "Why does Jim like Australia?",
|
||
options: [
|
||
"Because of the food",
|
||
"Because of the beaches",
|
||
"Because of the mountains",
|
||
"Because of the cities",
|
||
],
|
||
answer: "Because of the beaches",
|
||
text: "Jim visited Vietnam and Australia last summer. He loves Vietnam for the food. He likes Australia for the beaches.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_jim_visited_vietnam_and_australia_last_summer_he_l_af1424aa.mp3",
|
||
},
|
||
{
|
||
id: "q17",
|
||
question: "Who cleans the house?",
|
||
options: ["Dad", "Mom", "I", "Sister"],
|
||
answer: "Mom",
|
||
text: "My dad cooks in the kitchen. My mom cleans the house. I watch TV after school.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_my_dad_cooks_in_the_kitchen_my_mom_cleans_the_hous_62017a71.mp3",
|
||
},
|
||
{
|
||
id: "q18",
|
||
question: "Which vehicle is used for long trips?",
|
||
options: ["Bus", "Scooter", "Plane", "Motorcycle"],
|
||
answer: "Plane",
|
||
text: "Children take buses... Planes and trains are used for long trips.",
|
||
audio:
|
||
"https://audio.senaai.tech/audio/en_jessie_children_take_buses_or_motorcycles_to_school_adult_526193a7.mp3",
|
||
},
|
||
|
||
// --- PART 3: TỰ LUẬN - VIẾT BẢNG (Q19 - Q24) ---
|
||
{
|
||
id: "q19",
|
||
question:
|
||
"What round or square sticky rice cake wrapped in leaves is made for Tet in Vietnam?",
|
||
options: [],
|
||
answer: "Banh Chung",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q20",
|
||
question:
|
||
"On the first day of the Lunar New Year, children often receive small envelopes with money inside. What is this gift called?",
|
||
options: [],
|
||
answer: "lucky money",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q21",
|
||
question:
|
||
"People sometimes set off loud and colorful things at midnight to chase away evil spirits. What is this activity?",
|
||
options: [],
|
||
answer: "fireworks",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q22",
|
||
question:
|
||
"Before the Lunar New Year, people buy flowers, food, and decorations at special markets. What are these markets called?",
|
||
options: [],
|
||
answer: "flower market",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q23",
|
||
question:
|
||
"During Tet, people often clean and decorate their houses to get rid of bad luck. What is this practice called?",
|
||
options: [],
|
||
answer: "house cleaning",
|
||
audio: "",
|
||
},
|
||
{
|
||
id: "q24",
|
||
question:
|
||
"On the eve of Tet, families often watch or participate in a performance of lion dance. What is this dance called?",
|
||
options: [],
|
||
answer: "lion dance",
|
||
audio: "",
|
||
},
|
||
];
|
||
tdv_sdk.currentIndex = 0;
|
||
tdv_sdk.shuffleArray = function (Array) {
|
||
for (let i = Array.length - 1; i > 0; i--) {
|
||
const j = Math.floor(Math.random() * (i + 1));
|
||
[Array[i], Array[j]] = [Array[j], Array[i]];
|
||
}
|
||
};
|
||
tdv_sdk.start = function () {
|
||
tdv_sdk.currentIndex = 0;
|
||
//tdv_sdk.shuffleArray(tdv_sdk.list);
|
||
tdv_sdk.listquestion = [];
|
||
tdv_sdk.totalquestion = 40;
|
||
for (let i = 0; i < tdv_sdk.list.length; i++) {
|
||
tdv_sdk.listquestion.push(tdv_sdk.list[i]);
|
||
}
|
||
};
|
||
tdv_sdk.loadquestion = function () {
|
||
tdv_sdk.curQuestion = tdv_sdk.listquestion[tdv_sdk.currentIndex];
|
||
tdv_sdk.correctAnswer = tdv_sdk.curQuestion.answer;
|
||
//tdv_sdk.shuffleArray(tdv_sdk.curQuestion.options);
|
||
};
|
||
tdv_sdk.getCurQuestion = function () {
|
||
return tdv_sdk.curQuestion.question;
|
||
};
|
||
tdv_sdk.getCurOptions = function (index) {
|
||
return tdv_sdk.curQuestion.options[index];
|
||
};
|
||
tdv_sdk.getCurCorrectOption = function () {
|
||
return tdv_sdk.correctAnswer;
|
||
};
|
||
tdv_sdk.getCorrectCount = function () {
|
||
return tdv_sdk.answers;
|
||
};
|
||
tdv_sdk.nextQuestion = function () {
|
||
tdv_sdk.currentIndex++;
|
||
};
|
||
tdv_sdk.getCurIndex = function () {
|
||
return tdv_sdk.currentIndex;
|
||
};
|
||
tdv_sdk.getTotalQuestion = function () {
|
||
return tdv_sdk.list.length;
|
||
};
|
||
tdv_sdk.getId = function (index) {
|
||
return tdv_sdk.list[index].id;
|
||
};
|
||
tdv_sdk.getAnswers = function (index) {
|
||
return tdv_sdk.answers[index];
|
||
};
|
||
tdv_sdk.goHome = function () {
|
||
window.location.href = "../";
|
||
};
|
||
|
||
// Biến lưu trữ đối tượng âm thanh hiện tại để có thể dừng/phát lại
|
||
tdv_sdk.currentAudioObj = null;
|
||
|
||
// Hàm phát audio của câu hỏi hiện tại
|
||
tdv_sdk.playCurrentAudio = function (speed) {
|
||
// 0. Xử lý tham số tốc độ: Nếu không truyền hoặc truyền null/undefined thì mặc định là 1.0
|
||
var playbackSpeed = speed !== undefined && speed !== null ? speed : 1.0;
|
||
|
||
// 1. Lấy thông tin câu hỏi hiện tại
|
||
var curQ = tdv_sdk.listquestion[tdv_sdk.currentIndex];
|
||
|
||
// Kiểm tra xem có link audio không
|
||
if (curQ && curQ.audio) {
|
||
var audioUrl = curQ.audio;
|
||
|
||
// 2. Nếu đang có audio nào chạy thì dừng lại trước khi phát cái mới
|
||
tdv_sdk.stopAudio();
|
||
|
||
// 3. Khởi tạo đối tượng Audio HTML5 mới
|
||
tdv_sdk.currentAudioObj = new Audio(audioUrl);
|
||
|
||
// ===> CẬP NHẬT: Thiết lập tốc độ đọc <===
|
||
// Giá trị: 1.0 là bình thường, < 1.0 là chậm, > 1.0 là nhanh
|
||
tdv_sdk.currentAudioObj.playbackRate = playbackSpeed;
|
||
|
||
// 4. Bắt lỗi nếu trình duyệt chặn Autoplay hoặc link hỏng
|
||
var playPromise = tdv_sdk.currentAudioObj.play();
|
||
if (playPromise !== undefined) {
|
||
playPromise
|
||
.then(function () {
|
||
// Audio bắt đầu phát thành công
|
||
console.log(
|
||
"Audio playing: " + audioUrl + " | Speed: " + playbackSpeed,
|
||
);
|
||
})
|
||
.catch(function (error) {
|
||
// Lỗi (thường do user chưa tương tác với game)
|
||
console.error("Audio playback failed:", error);
|
||
});
|
||
}
|
||
|
||
// (Tùy chọn) Lắng nghe sự kiện khi audio kết thúc
|
||
tdv_sdk.currentAudioObj.onended = function () {
|
||
console.log("Audio finished.");
|
||
// Nếu muốn gọi lại Construct 2 khi hết audio, bạn có thể dùng:
|
||
// c2_callFunction("OnAudioEnded");
|
||
};
|
||
} else {
|
||
console.log("No audio found for this question.");
|
||
}
|
||
};
|
||
|
||
// Hàm dừng audio (Dùng khi chuyển câu hỏi hoặc tắt tiếng)
|
||
tdv_sdk.stopAudio = function () {
|
||
if (tdv_sdk.currentAudioObj) {
|
||
tdv_sdk.currentAudioObj.pause();
|
||
tdv_sdk.currentAudioObj.currentTime = 0; // Tua về đầu
|
||
tdv_sdk.currentAudioObj = null;
|
||
}
|
||
};
|
||
|
||
// Thêm vào cuối file tdv_sdk.js
|
||
tdv_sdk.isEssay = function () {
|
||
// Nếu mảng options rỗng hoặc không tồn tại -> Là câu tự luận
|
||
if (
|
||
!tdv_sdk.curQuestion.options ||
|
||
tdv_sdk.curQuestion.options.length === 0
|
||
) {
|
||
return 1; // True (Trong C2 số 1 là true)
|
||
}
|
||
return 0; // False
|
||
};
|
||
|
||
// Kiểm tra xem câu hỏi hiện tại có audio hay không
|
||
tdv_sdk.hasAudio = function () {
|
||
var q = tdv_sdk.curQuestion;
|
||
// Kiểm tra nếu thuộc tính audio tồn tại và có độ dài > 0
|
||
if (q && q.audio && q.audio.length > 0) {
|
||
return 1; // Có audio -> Là câu nghe
|
||
}
|
||
return 0; // Không có -> Trắc nghiệm thường hoặc Tự luận
|
||
};
|
||
// Hàm tính toán scale đồng bộ cho cả 4 đáp án
|
||
tdv_sdk.getUniformAnswerScale = function () {
|
||
var opts = tdv_sdk.curQuestion.options;
|
||
|
||
// Safety check: Nếu không có options (câu tự luận) trả về 1
|
||
if (!opts || opts.length === 0) return 1.0;
|
||
|
||
// 1. Tìm độ dài của đáp án dài nhất (Max Length)
|
||
var maxLen = 0;
|
||
for (var i = 0; i < opts.length; i++) {
|
||
if (opts[i].length > maxLen) {
|
||
maxLen = opts[i].length;
|
||
}
|
||
}
|
||
|
||
// 2. Tính toán Scale dựa trên Max Length
|
||
// Công thức: Constant / maxLen
|
||
// Giải thích: Với Scale chuẩn 1.1, giả sử hiển thị đẹp cho khoảng 11-12 ký tự.
|
||
// Ta chọn hằng số khoảng 13.5.
|
||
|
||
var calculatedScale = 13.5 / maxLen;
|
||
|
||
// 3. Clamp (Kẹp) giá trị trong khoảng cho phép
|
||
// Min: 0.55 (Bé quá không đọc được)
|
||
// Max: 1.1 (Scale mặc định bạn mong muốn)
|
||
|
||
if (calculatedScale > 1.1) calculatedScale = 1.1;
|
||
if (calculatedScale < 0.65) calculatedScale = 0.65;
|
||
|
||
return calculatedScale;
|
||
};
|