File: /var/www/html/wp-content/themes/elearning-education/page-BYD_Tang_DMi_HV_Stucture.php
<?php
/*
Template Name: BYD Tang DMi Game
*/
// 加载WordPress头部
get_header();
?>
<?php
// WordPress集成:检查用户登录
if (!is_user_logged_in()) {
echo '<div class="login-prompt"><p>请先<a href="' . wp_login_url(get_permalink()) . '">登录</a>以玩游戏并保存成绩。</p></div>';
} else {
// 获取当前用户ID和学生信息
$current_user = wp_get_current_user();
$user_id = $current_user->ID;
global $wpdb;
// 从wp_edu_students获取student_id和name
$student_row = $wpdb->get_row($wpdb->prepare("SELECT student_id, name FROM {$wpdb->prefix}edu_students WHERE user_id = %d", $user_id));
$student_id = $student_row ? $student_row->student_id : $user_id;
$student_name = $student_row ? $student_row->name : $current_user->display_name;
// 游戏ID:BYD为7(更新)
$game_id = 7;
?>
<style>
/* 同前,保持不变 */
.game-container {
background-color: #ffffff;
padding: 25px;
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
width: 95%;
max-width: 950px;
text-align: center;
margin: 20px auto;
display: block;
}
h1 {
color: #333;
margin-bottom: 20px;
}
.info-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
background-color: #e9ecef;
border-radius: 8px;
margin-bottom: 20px;
font-size: 1.2em;
}
.timer-container { color: #1a73e8; font-weight: bold; }
#timer { display: inline-block; min-width: 50px; }
.results-container { color: #555; font-weight: 500; }
#diagram-wrapper {
position: relative;
width: 100%;
margin: 0 auto;
background-color: #030D19;
overflow: hidden;
}
.diagram-svg {
width: 100%;
height: auto;
display: block;
}
/* SVG 元素样式 - 同前 */
.axle-bg { fill: #030D19; }
.wheel { fill: #7a7a7a; }
.axle { fill: #b0b0b0; }
.component-box {
fill: #fbe5d6;
stroke: #b1a091;
stroke-width: 1;
}
.battery { fill: #fbe5d6; }
.motor-symbol {
fill: none;
stroke: #888;
stroke-width: 2;
}
.component-label {
font-size: 17px;
text-anchor: middle;
fill: #333;
font-family: sans-serif;
}
.wiring .wire {
fill: none;
stroke: #ed7d31;
stroke-width: 3;
stroke-linecap: round;
stroke-linejoin: round;
}
.drop-zone {
position: absolute;
border: 2px dashed #aaa;
background-color: #fbd7bb;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.8vw;
font-weight: bold;
color: #333;
transition: background-color 0.3s, border-color 0.3s;
overflow: hidden;
box-sizing: border-box;
z-index: 10;
text-shadow: 1px 1px 2px rgba(0,0,0,0.2);
}
/* BYD Drop Zones 定位 - 同前 */
#drop-1 { top: 17.6%; left: 1.5%; width: 6.5%; height: 8%; }
#drop-2 { top: 22.6%; left: 21.5%; width: 5.5%; height: 6%; }
#drop-3 { top: 23.6%; left: 40.5%; width: 8.5%; height: 9%; }
#drop-4 { top: 46.0%; left: 21.4%; width: 8%; height: 10%; }
#drop-5 { top: 43.7%; left: 8%; width: 11%; height: 18%; }
#drop-6 { top: 36%; left: 33%; width: 32%; height: 26%; }
#drop-7 { top: 66.3%; left: 20.6%; width: 6.5%; height: 8%; }
#drop-8 { top: 11.3%; left: 80%; width: 5%; height: 6%; }
#drop-9 { top: 21.3%; left: 71.2%; width: 8%; height: 9%; }
#drop-10 { top: 21.5%; left: 85.5%; width: 7%; height: 8%; }
#drop-11 { top: 66.3%; left: 79%; width: 6.3%; height: 6.7%; }
/* 拖拽样式 - 同前 */
.drop-zone.drag-over { background-color: rgba(144, 238, 144, 0.7); border-color: #28a745; }
.drop-zone.correct { background-color: rgba(40, 167, 69, 0.8); border: 2px solid #1a5d2a; color: white; }
.drop-zone.incorrect { background-color: rgba(220, 53, 69, 0.8); border: 2px solid #8d1c27; color: white; }
#answer-bank { margin-top: 25px; padding: 15px; background-color: #f8f9fa; border-radius: 8px; border: 1px solid #dee2e6; }
.answers { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 10px; min-height: 50px; padding: 10px; border: 2px dashed transparent; transition: background-color 0.3s, border-color 0.3s; }
.answers.drag-over { background-color: #e9ecef; border-color: #007bff; }
.draggable {
padding: 10px 15px;
background-color: #007bff;
color: white;
border-radius: 6px;
cursor: grab;
transition: transform 0.2s, box-shadow 0.2s;
user-select: none;
font-size: 0.9em;
flex-shrink: 0;
}
.draggable.dragging { opacity: 0.5; cursor: grabbing; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); transform: scale(1.05); }
.drop-zone .draggable {
width: 100%;
height: 100%;
padding: 2px;
font-size: 13px;
line-height: 1.2;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
box-sizing: border-box;
cursor: grab;
background-color: #6c757d !important;
border: none;
border-radius: 0;
color: white;
}
.drop-zone.correct .draggable,
.drop-zone.incorrect .draggable {
cursor: default;
background-color: transparent !important;
color: white;
}
#submit-btn { margin-top: 25px; padding: 12px 30px; font-size: 1.1em; font-weight: bold; color: white; background-color: #28a745; border: none; border-radius: 8px; cursor: pointer; transition: background-color 0.3s; }
#submit-btn:hover { background-color: #218838; }
#submit-btn:disabled { background-color: #6c757d; cursor: not-allowed; }
/* 登录提示样式 - 同前 */
.login-prompt {
background-color: #fff3cd;
border: 1px solid #ffeaa7;
color: #856404;
padding: 15px;
border-radius: 8px;
margin: 20px auto;
text-align: left;
max-width: 950px;
}
</style>
<div class="game-container">
<!-- 更新标题:基于game_id=7 -->
<h1>BYD-2017唐DM-i 4WD高压系统 闯关游戏 BYD Tang DM-i 4WD HV System Game</h1>
<div class="info-bar">
<div class="timer-container">
用时Time: <span id="timer">00:00</span>
</div>
<div id="results" class="results-container">
玩家:<?php echo esc_html($student_name); ?> | 请将答案拖拽到对应的数字上 Please drag the answers to the corresponding numbers
</div>
</div>
<div id="diagram-wrapper">
<!-- BYD SVG - 完整补全 -->
<svg viewBox="0 0 950 600" preserveAspectRatio="xMidYMid meet" class="diagram-svg">
<!-- 背景和车轴框架 -->
<rect class="axle-bg" x="0" y="0" width="180" height="600" />
<rect class="axle-bg" x="770" y="0" width="180" height="600" />
<!-- 车轮和车轴 -->
<g class="wheel-assembly">
<!-- 左侧 -->
<rect class="wheel" x="50" y="20" width="80" height="40" rx="15"/>
<rect class="axle" x="85" y="60" width="10" height="480"/>
<rect class="wheel" x="50" y="540" width="80" height="40" rx="15"/>
<!-- 右侧 -->
<rect class="wheel" x="820" y="20" width="80" height="40" rx="15"/>
<rect class="axle" x="855" y="60" width="10" height="480"/>
<rect class="wheel" x="820" y="540" width="80" height="40" rx="15"/>
</g>
<!-- 主要部件 -->
<g class="components">
<!-- 发动机 -->
<rect class="component-box" id="component-5" x="105" y="215" width="65" height="50"/>
<text class="component-label" x="138" y="244">发动机</text>
<!-- 减速器 -->
<rect class="component-box battery" id="component-6" x="800" y="177" width="90" height="70"/>
<text class="component-label" x="845" y="215">减速器</text>
</g>
<!-- 电路连接线 - 完整路径(基于原BYD HTML补全) -->
<g class="wiring">
<path class="wire" d="M 65 140 H 210" />
<path class="wire" d="M 65 145 H 210" />
<path class="wire" d="M 55 160 H 210" />
<path class="wire" d="M 60 165 H 210" />
<path class="wire" d="M 55 160 V 420" />
<path class="wire" d="M 60 165 V 415" />
<path class="wire" d="M 60 415 H 200" />
<path class="wire" d="M 55 420 H 200" />
<path class="wire" d="M 245 150 H 390" />
<path class="wire" d="M 245 160 H 390" />
<path class="wire" d="M 420 170 V 230" />
<path class="wire" d="M 430 170 V 230" />
<path class="wire" d="M 238 290 V 180 H 400" />
<path class="wire" d="M 248 290 V 190 H 400" />
<path class="wire" d="M 205 300 H 170" />
<path class="wire" d="M 205 305 H 170" />
<path class="wire" d="M 205 310 H 170" />
<path class="wire" d="M 420 155 H 680" />
<path class="wire" d="M 420 165 H 680" />
<path class="wire" d="M 420 175 H 650 V 410 H 790" />
<path class="wire" d="M 420 185 H 640 V 420 H 790" />
<path class="wire" d="M 720 150 H 810" />
<path class="wire" d="M 720 155 H 810" />
<path class="wire" d="M 720 160 H 810" />
<path class="wire" d="M 810 80 H 910 V 420 H 810" />
<path class="wire" d="M 810 90 H 900 V 420 H 810" />
</g>
</svg>
<!-- Drop Zones - 同前,11个 -->
<div class="drop-zone" id="drop-1" data-answer="ACP">1</div>
<div class="drop-zone" id="drop-2" data-answer="PDU2">2</div>
<div class="drop-zone" id="drop-3" data-answer="PDU">3</div>
<div class="drop-zone" id="drop-4" data-answer="IPUF(含DCDC)">4</div>
<div class="drop-zone" id="drop-5" data-answer="变速器(含电机)">5</div>
<div class="drop-zone" id="drop-6" data-answer="动力电池">6</div>
<div class="drop-zone" id="drop-7" data-answer="PTC">7</div>
<div class="drop-zone" id="drop-8" data-answer="交流充电口">8</div>
<div class="drop-zone" id="drop-9" data-answer="IPUR">9</div>
<div class="drop-zone" id="drop-10" data-answer="后电机">10</div>
<div class="drop-zone" id="drop-11" data-answer="OBC">11</div>
</div>
<div id="answer-bank">
<h3>备选答案区 (请拖拽) Answer Bank (Please Drag)</h3>
<div class="answers">
<!-- 正确答案 - 同前 -->
<div class="draggable" draggable="true" data-id="ans-1">ACP</div>
<div class="draggable" draggable="true" data-id="ans-2">PDU2</div>
<div class="draggable" draggable="true" data-id="ans-3">PDU</div>
<div class="draggable" draggable="true" data-id="ans-4">IPUF(含DCDC)</div>
<div class="draggable" draggable="true" data-id="ans-5">变速器(含电机)</div>
<div class="draggable" draggable="true" data-id="ans-6">动力电池</div>
<div class="draggable" draggable="true" data-id="ans-7">PTC</div>
<div class="draggable" draggable="true" data-id="ans-8">交流充电口</div>
<div class="draggable" draggable="true" data-id="ans-9">IPUR</div>
<div class="draggable" draggable="true" data-id="ans-10">后电机</div>
<div class="draggable" draggable="true" data-id="ans-11">OBC</div>
<!-- 干扰项 - 同前 -->
<div class="draggable" draggable="true" data-id="dist-1">二合一(OBC、DCDC)</div>
<div class="draggable" draggable="true" data-id="dist-2">IPU</div>
<div class="draggable" draggable="true" data-id="dist-3">前电机</div>
</div>
</div>
<button id="submit-btn">提交答案 Answer Submit</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.6.0/dist/confetti.browser.min.js"></script>
<script>
// WordPress集成:AJAX - 更新gameId=7
const ajaxUrl = '<?php echo admin_url("admin-ajax.php"); ?>';
const nonce = '<?php echo wp_create_nonce("save_game_score"); ?>';
const studentId = '<?php echo esc_js($student_id); ?>';
const studentName = '<?php echo esc_js($student_name); ?>';
const gameId = <?php echo intval($game_id); ?>; // 更新为7
console.log('BYD Tang DMi Game init:', { ajaxUrl, nonce, studentId, gameId });
document.addEventListener('DOMContentLoaded', () => {
// --- 状态变量 ---
let timerInterval;
let seconds = 0;
let gameEnded = false;
let draggedItem = null;
let confettiInstance = null;
// --- DOM 元素 ---
const draggables = document.querySelectorAll('.draggable');
const dropZones = document.querySelectorAll('.drop-zone');
const answerBankContainer = document.querySelector('.answers');
const submitBtn = document.getElementById('submit-btn');
const timerDisplay = document.getElementById('timer');
const resultsDisplay = document.getElementById('results');
// --- 计时器功能 ---
const startTimer = () => {
const startTime = Date.now();
timerInterval = setInterval(() => {
if (gameEnded) return;
seconds = Math.floor((Date.now() - startTime) / 1000);
const mins = Math.floor(seconds / 60).toString().padStart(2, '0');
const secs = (seconds % 60).toString().padStart(2, '0');
timerDisplay.textContent = `${mins}:${secs}`;
}, 1000);
};
const stopTimer = () => {
clearInterval(timerInterval);
};
// --- 随机化答案功能 ---
const shuffleAnswers = () => {
const answersArray = Array.from(draggables);
for (let i = answersArray.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[answersArray[i], answersArray[j]] = [answersArray[j], answersArray[i]];
}
answerBankContainer.innerHTML = '';
answersArray.forEach(answer => answerBankContainer.appendChild(answer));
};
// --- 拖放事件处理 ---
function handleDragStart(e) {
if (gameEnded) return;
draggedItem = e.target;
e.dataTransfer.setData('text/plain', draggedItem.dataset.id);
setTimeout(() => {
if (draggedItem) draggedItem.classList.add('dragging');
}, 0);
}
function handleDragEnd() {
if (draggedItem) {
draggedItem.classList.remove('dragging');
}
draggedItem = null;
}
function handleDragOver(e) {
e.preventDefault();
if (gameEnded) return;
const targetZone = e.target.closest('.drop-zone');
if (targetZone && targetZone.children.length === 0) {
targetZone.classList.add('drag-over');
} else if (e.target.closest('.answers')) {
answerBankContainer.classList.add('drag-over');
}
}
function handleDragLeave(e) {
if (gameEnded) return;
const targetZone = e.target.closest('.drop-zone');
if (targetZone) {
targetZone.classList.remove('drag-over');
} else if (e.target.closest('.answers')) {
answerBankContainer.classList.remove('drag-over');
}
}
function handleDrop(e) {
e.preventDefault();
if (gameEnded || !draggedItem) return;
const targetZone = e.target.closest('.drop-zone');
const targetBank = e.target.closest('.answers');
if (targetZone && targetZone.children.length === 0) {
targetZone.classList.remove('drag-over');
targetZone.appendChild(draggedItem);
targetZone.style.color = 'transparent';
} else if (targetBank && draggedItem.parentElement !== answerBankContainer) {
targetBank.classList.remove('drag-over');
const originalZone = draggedItem.parentElement;
if (originalZone && originalZone.classList.contains('drop-zone')) {
originalZone.style.color = '';
originalZone.classList.remove('correct', 'incorrect');
}
targetBank.appendChild(draggedItem);
}
if (draggedItem) draggedItem.classList.remove('dragging');
draggedItem = null;
}
// --- 烟花效果函数 ---
function startConfetti() {
if (typeof confetti === 'undefined') return;
if (confettiInstance) confettiInstance.destroy();
confettiInstance = confetti.create(null, { resize: true, useWorker: true });
confettiInstance({ particleCount: 200, spread: 160, origin: { y: 0.6 } });
}
// 保存成绩 - 同前
const saveScore = (score, time, errors) => {
const payload = {
action: 'save_game_score',
nonce: nonce,
student_id: studentId,
game_id: gameId, // 现在为7
score: score,
time: time,
errors: JSON.stringify(errors)
};
console.log('Sending AJAX payload:', payload);
fetch(ajaxUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(payload)
})
.then(response => {
if (!response.ok) throw new Error('Network response not ok');
return response.json();
})
.then(data => {
console.log('AJAX response data:', data);
if (data.success) {
console.log('成绩保存成功');
resultsDisplay.innerHTML += '<br><small style="color: green;">成绩已保存!</small>';
} else {
console.error('保存失败:', data.data);
}
})
.catch(error => {
console.error('AJAX错误:', error);
});
};
// 游戏逻辑 - 同前,总题数=11,消息保持BYD相关
const checkAnswers = () => {
console.log('checkAnswers called');
gameEnded = true;
stopTimer();
submitBtn.disabled = true;
let score = 0;
const totalQuestions = dropZones.length; // 11
const errors = [];
dropZones.forEach((zone, index) => {
const answerElement = zone.querySelector('.draggable');
const zoneNumber = index + 1;
if (answerElement) {
const droppedAnswer = answerElement.textContent.trim();
const correctAnswer = zone.dataset.answer;
if (droppedAnswer === correctAnswer) {
zone.classList.add('correct');
score++;
} else {
zone.classList.add('incorrect');
errors.push({ zone: zoneNumber, expected: correctAnswer, actual: droppedAnswer });
}
} else {
zone.classList.add('incorrect');
errors.push({ zone: zoneNumber, expected: zone.dataset.answer, actual: '未放置' });
}
zone.classList.remove('drag-over');
});
const percentageScore = Math.round((score / totalQuestions) * 100);
const finalTime = timerDisplay.textContent;
let message = "";
if (percentageScore === 100) {
message = `🎉 太棒了!满分100分!您的知识渊博,就像唐DM-i 4WD一样强大!`; // 轻微调整以匹配标题
startConfetti();
} else if (percentageScore >= 90) {
message = `👍 非常出色!您对高压系统了如指掌,继续保持!`;
startConfetti();
} else if (percentageScore >= 60) {
message = `😊 表现不错!您已经掌握了大部分知识,再接再厉!`;
} else if (percentageScore >= 40) {
message = `🙂 继续努力!您对高压系统有了初步了解,多加练习会更好!`;
} else {
message = `😔 还需要一些时间!不要气馁,多学习高压系统知识,下次一定能通过!`;
}
resultsDisplay.innerHTML = `<strong>${message}</strong> <br> 用时: <strong>${finalTime}</strong> | 分数: <strong>${percentageScore}%</strong>`;
console.log('Calling saveScore with:', { percentageScore, finalTime, errors });
saveScore(percentageScore, finalTime, errors);
};
// --- 初始化 ---
draggables.forEach(draggable => {
draggable.addEventListener('dragstart', handleDragStart);
draggable.addEventListener('dragend', handleDragEnd);
});
dropZones.forEach(zone => {
zone.addEventListener('dragover', handleDragOver);
zone.addEventListener('dragleave', handleDragLeave);
zone.addEventListener('drop', handleDrop);
});
answerBankContainer.addEventListener('dragover', handleDragOver);
answerBankContainer.addEventListener('dragleave', handleDragLeave);
answerBankContainer.addEventListener('drop', handleDrop);
submitBtn.addEventListener('click', checkAnswers);
shuffleAnswers();
startTimer();
});
</script>
<?php } ?>
<?php get_footer(); ?>