Widget:WheelOfNursing: Difference between revisions

From Doc-Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
Line 9: Line 9:


[[Category:Widgets]]
[[Category:Widgets]]
</noinclude><includeonly><style>
</noinclude><includeonly><html>
#wheel-of-nursing-game {
<style>
.wheel-of-nursing-game {
     font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
     font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
     background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
     background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
Line 20: Line 21:
}
}


#wheel-of-nursing-game * {
.wheel-of-nursing-game * {
     box-sizing: border-box;
     box-sizing: border-box;
}
}


#wheel-of-nursing-game .game-container {
.wheel-of-nursing-game .game-container {
     max-width: 900px;
     max-width: 900px;
     margin: 0 auto;
     margin: 0 auto;
}
}


#wheel-of-nursing-game .sound-controls {
.wheel-of-nursing-game .sound-controls {
     position: absolute;
     position: absolute;
     top: 10px;
     top: 10px;
Line 39: Line 40:
}
}


#wheel-of-nursing-game .sound-controls button {
.wheel-of-nursing-game .sound-controls button {
     padding: 8px 12px;
     padding: 8px 12px;
     margin: 2px;
     margin: 2px;
Line 49: Line 50:
}
}


#wheel-of-nursing-game .sound-controls .on { background: #2ecc71; }
.wheel-of-nursing-game .sound-controls .on { background: #2ecc71; }
#wheel-of-nursing-game .sound-controls .off { background: #e74c3c; }
.wheel-of-nursing-game .sound-controls .off { background: #e74c3c; }


#wheel-of-nursing-game .volume-control {
.wheel-of-nursing-game .volume-control {
     margin-top: 10px;
     margin-top: 10px;
     color: #fff;
     color: #fff;
Line 58: Line 59:
}
}


#wheel-of-nursing-game .volume-control input {
.wheel-of-nursing-game .volume-control input {
     width: 100px;
     width: 100px;
     margin-left: 5px;
     margin-left: 5px;
}
}


#wheel-of-nursing-game .header {
.wheel-of-nursing-game .header {
     display: flex;
     display: flex;
     justify-content: space-between;
     justify-content: space-between;
Line 72: Line 73:
}
}


#wheel-of-nursing-game .header h1 {
.wheel-of-nursing-game .header h1 {
     color: #ffd700;
     color: #ffd700;
     font-size: 32px;
     font-size: 32px;
Line 80: Line 81:
}
}


#wheel-of-nursing-game .scores {
.wheel-of-nursing-game .scores {
     display: flex;
     display: flex;
     gap: 20px;
     gap: 20px;
}
}


#wheel-of-nursing-game .score-box {
.wheel-of-nursing-game .score-box {
     padding: 10px 20px;
     padding: 10px 20px;
     border-radius: 10px;
     border-radius: 10px;
Line 91: Line 92:
}
}


#wheel-of-nursing-game .score-box.round {
.wheel-of-nursing-game .score-box.round {
     background: rgba(255,215,0,0.2);
     background: rgba(255,215,0,0.2);
     border: 2px solid #ffd700;
     border: 2px solid #ffd700;
}
}


#wheel-of-nursing-game .score-box.total {
.wheel-of-nursing-game .score-box.total {
     background: rgba(46,204,113,0.2);
     background: rgba(46,204,113,0.2);
     border: 2px solid #2ecc71;
     border: 2px solid #2ecc71;
}
}


#wheel-of-nursing-game .score-box .label {
.wheel-of-nursing-game .score-box .label {
     font-size: 12px;
     font-size: 12px;
     color: #ffd700;
     color: #ffd700;
}
}


#wheel-of-nursing-game .score-box.total .label {
.wheel-of-nursing-game .score-box.total .label {
     color: #2ecc71;
     color: #2ecc71;
}
}


#wheel-of-nursing-game .score-box .value {
.wheel-of-nursing-game .score-box .value {
     font-size: 28px;
     font-size: 28px;
     font-weight: bold;
     font-weight: bold;
}
}


#wheel-of-nursing-game .message-box {
.wheel-of-nursing-game .message-box {
     background: rgba(255,255,255,0.1);
     background: rgba(255,255,255,0.1);
     padding: 15px 20px;
     padding: 15px 20px;
Line 124: Line 125:
}
}


#wheel-of-nursing-game .message-box .wheel-value {
.wheel-of-nursing-game .message-box .wheel-value {
     color: #ffd700;
     color: #ffd700;
     font-weight: bold;
     font-weight: bold;
Line 130: Line 131:
}
}


#wheel-of-nursing-game .puzzle-board {
.wheel-of-nursing-game .puzzle-board {
     background: linear-gradient(135deg, #1a237e 0%, #0d47a1 100%);
     background: linear-gradient(135deg, #1a237e 0%, #0d47a1 100%);
     padding: 30px;
     padding: 30px;
Line 138: Line 139:
}
}


#wheel-of-nursing-game .category {
.wheel-of-nursing-game .category {
     color: #ffd700;
     color: #ffd700;
     font-size: 14px;
     font-size: 14px;
Line 147: Line 148:
}
}


#wheel-of-nursing-game .letter-tiles {
.wheel-of-nursing-game .letter-tiles {
     display: flex;
     display: flex;
     flex-wrap: wrap;
     flex-wrap: wrap;
Line 155: Line 156:
}
}


#wheel-of-nursing-game .letter-tile {
.wheel-of-nursing-game .letter-tile {
     width: 45px;
     width: 45px;
     height: 55px;
     height: 55px;
Line 169: Line 170:
}
}


#wheel-of-nursing-game .letter-tile.revealed {
.wheel-of-nursing-game .letter-tile.revealed {
     background: #fff;
     background: #fff;
}
}


#wheel-of-nursing-game .letter-tile.hidden {
.wheel-of-nursing-game .letter-tile.hidden {
     background: #1a237e;
     background: #1a237e;
}
}


#wheel-of-nursing-game .letter-tile.space {
.wheel-of-nursing-game .letter-tile.space {
     border: none;
     border: none;
     background: transparent;
     background: transparent;
Line 183: Line 184:
}
}


#wheel-of-nursing-game .clue-box {
.wheel-of-nursing-game .clue-box {
     color: #fff;
     color: #fff;
     font-size: 16px;
     font-size: 16px;
Line 193: Line 194:
}
}


#wheel-of-nursing-game .wheel-container {
.wheel-of-nursing-game .wheel-container {
     position: relative;
     position: relative;
     width: 300px;
     width: 300px;
Line 200: Line 201:
}
}


#wheel-of-nursing-game .wheel-pointer {
.wheel-of-nursing-game .wheel-pointer {
     position: absolute;
     position: absolute;
     top: -15px;
     top: -15px;
Line 214: Line 215:
}
}


#wheel-of-nursing-game .wheel-svg {
.wheel-of-nursing-game .wheel-svg {
     width: 100%;
     width: 100%;
     height: 100%;
     height: 100%;
Line 220: Line 221:
}
}


#wheel-of-nursing-game .letter-board {
.wheel-of-nursing-game .letter-board {
     margin-bottom: 20px;
     margin-bottom: 20px;
}
}


#wheel-of-nursing-game .letter-section {
.wheel-of-nursing-game .letter-section {
     margin-bottom: 15px;
     margin-bottom: 15px;
}
}


#wheel-of-nursing-game .letter-section-label {
.wheel-of-nursing-game .letter-section-label {
     color: #ffd700;
     color: #ffd700;
     font-size: 12px;
     font-size: 12px;
Line 236: Line 237:
}
}


#wheel-of-nursing-game .letter-buttons {
.wheel-of-nursing-game .letter-buttons {
     display: flex;
     display: flex;
     flex-wrap: wrap;
     flex-wrap: wrap;
Line 243: Line 244:
}
}


#wheel-of-nursing-game .letter-btn {
.wheel-of-nursing-game .letter-btn {
     width: 36px;
     width: 36px;
     height: 36px;
     height: 36px;
Line 255: Line 256:
}
}


#wheel-of-nursing-game .letter-btn.consonant { background: #2ecc71; }
.wheel-of-nursing-game .letter-btn.consonant { background: #2ecc71; }
#wheel-of-nursing-game .letter-btn.consonant:disabled { background: #555; opacity: 0.5; cursor: not-allowed; }
.wheel-of-nursing-game .letter-btn.consonant:disabled { background: #555; opacity: 0.5; cursor: not-allowed; }
#wheel-of-nursing-game .letter-btn.consonant.inactive { background: #888; cursor: not-allowed; }
.wheel-of-nursing-game .letter-btn.consonant.inactive { background: #888; cursor: not-allowed; }


#wheel-of-nursing-game .letter-btn.vowel {
.wheel-of-nursing-game .letter-btn.vowel {
     width: 45px;
     width: 45px;
     height: 45px;
     height: 45px;
Line 265: Line 266:
     background: #e74c3c;
     background: #e74c3c;
}
}
#wheel-of-nursing-game .letter-btn.vowel:disabled { background: #555; opacity: 0.5; cursor: not-allowed; }
.wheel-of-nursing-game .letter-btn.vowel:disabled { background: #555; opacity: 0.5; cursor: not-allowed; }
#wheel-of-nursing-game .letter-btn.vowel.inactive { background: #888; cursor: not-allowed; }
.wheel-of-nursing-game .letter-btn.vowel.inactive { background: #888; cursor: not-allowed; }


#wheel-of-nursing-game .action-buttons {
.wheel-of-nursing-game .action-buttons {
     display: flex;
     display: flex;
     gap: 10px;
     gap: 10px;
Line 276: Line 277:
}
}


#wheel-of-nursing-game .action-btn {
.wheel-of-nursing-game .action-btn {
     padding: 15px 40px;
     padding: 15px 40px;
     font-size: 18px;
     font-size: 18px;
Line 286: Line 287:
}
}


#wheel-of-nursing-game .action-btn:hover:not(:disabled) {
.wheel-of-nursing-game .action-btn:hover:not(:disabled) {
     transform: scale(1.05);
     transform: scale(1.05);
}
}


#wheel-of-nursing-game .action-btn:disabled {
.wheel-of-nursing-game .action-btn:disabled {
     opacity: 0.6;
     opacity: 0.6;
     cursor: not-allowed;
     cursor: not-allowed;
}
}


#wheel-of-nursing-game .action-btn.spin {
.wheel-of-nursing-game .action-btn.spin {
     background: linear-gradient(135deg, #ffd700 0%, #ffb700 100%);
     background: linear-gradient(135deg, #ffd700 0%, #ffb700 100%);
     color: #1a237e;
     color: #1a237e;
Line 301: Line 302:
}
}


#wheel-of-nursing-game .action-btn.solve {
.wheel-of-nursing-game .action-btn.solve {
     background: #9b59b6;
     background: #9b59b6;
     color: #fff;
     color: #fff;
}
}


#wheel-of-nursing-game .action-btn.hint {
.wheel-of-nursing-game .action-btn.hint {
     background: #3498db;
     background: #3498db;
     color: #fff;
     color: #fff;
}
}


#wheel-of-nursing-game .hint-box {
.wheel-of-nursing-game .hint-box {
     margin-top: 15px;
     margin-top: 15px;
     padding: 15px;
     padding: 15px;
Line 320: Line 321:
}
}


#wheel-of-nursing-game .solve-input-container {
.wheel-of-nursing-game .solve-input-container {
     text-align: center;
     text-align: center;
     margin-bottom: 20px;
     margin-bottom: 20px;
}
}


#wheel-of-nursing-game .solve-input {
.wheel-of-nursing-game .solve-input {
     padding: 15px 20px;
     padding: 15px 20px;
     font-size: 20px;
     font-size: 20px;
Line 335: Line 336:
}
}


#wheel-of-nursing-game .solve-buttons {
.wheel-of-nursing-game .solve-buttons {
     display: flex;
     display: flex;
     gap: 10px;
     gap: 10px;
Line 341: Line 342:
}
}


#wheel-of-nursing-game .solve-btn {
.wheel-of-nursing-game .solve-btn {
     padding: 12px 30px;
     padding: 12px 30px;
     font-size: 16px;
     font-size: 16px;
Line 351: Line 352:
}
}


#wheel-of-nursing-game .solve-btn.submit { background: #2ecc71; }
.wheel-of-nursing-game .solve-btn.submit { background: #2ecc71; }
#wheel-of-nursing-game .solve-btn.cancel { background: #e74c3c; }
.wheel-of-nursing-game .solve-btn.cancel { background: #e74c3c; }


#wheel-of-nursing-game .result-screen {
.wheel-of-nursing-game .result-screen {
     text-align: center;
     text-align: center;
     margin-top: 30px;
     margin-top: 30px;
Line 361: Line 362:
}
}


#wheel-of-nursing-game .result-screen.won {
.wheel-of-nursing-game .result-screen.won {
     background: rgba(46, 204, 113, 0.2);
     background: rgba(46, 204, 113, 0.2);
     border: 3px solid #2ecc71;
     border: 3px solid #2ecc71;
}
}


#wheel-of-nursing-game .result-screen.lost {
.wheel-of-nursing-game .result-screen.lost {
     background: rgba(231, 76, 60, 0.2);
     background: rgba(231, 76, 60, 0.2);
     border: 3px solid #e74c3c;
     border: 3px solid #e74c3c;
}
}


#wheel-of-nursing-game .result-screen h2 {
.wheel-of-nursing-game .result-screen h2 {
     font-size: 32px;
     font-size: 32px;
     margin-bottom: 15px;
     margin-bottom: 15px;
Line 377: Line 378:
}
}


#wheel-of-nursing-game .result-screen.won h2 { color: #2ecc71; }
.wheel-of-nursing-game .result-screen.won h2 { color: #2ecc71; }
#wheel-of-nursing-game .result-screen.lost h2 { color: #e74c3c; }
.wheel-of-nursing-game .result-screen.lost h2 { color: #e74c3c; }


#wheel-of-nursing-game .result-screen p {
.wheel-of-nursing-game .result-screen p {
     font-size: 18px;
     font-size: 18px;
     margin-bottom: 20px;
     margin-bottom: 20px;
}
}


#wheel-of-nursing-game .result-screen .total-score {
.wheel-of-nursing-game .result-screen .total-score {
     color: #ffd700;
     color: #ffd700;
     font-weight: bold;
     font-weight: bold;
}
}


#wheel-of-nursing-game .result-buttons {
.wheel-of-nursing-game .result-buttons {
     display: flex;
     display: flex;
     gap: 15px;
     gap: 15px;
Line 396: Line 397:
}
}


#wheel-of-nursing-game .result-btn {
.wheel-of-nursing-game .result-btn {
     padding: 15px 40px;
     padding: 15px 40px;
     font-size: 18px;
     font-size: 18px;
Line 405: Line 406:
}
}


#wheel-of-nursing-game .result-btn.next {
.wheel-of-nursing-game .result-btn.next {
     background: linear-gradient(135deg, #ffd700 0%, #ffb700 100%);
     background: linear-gradient(135deg, #ffd700 0%, #ffb700 100%);
     color: #1a237e;
     color: #1a237e;
}
}


#wheel-of-nursing-game .result-btn.new-game {
.wheel-of-nursing-game .result-btn.new-game {
     background: #e74c3c;
     background: #e74c3c;
     color: #fff;
     color: #fff;
}
}


#wheel-of-nursing-game .start-screen {
.wheel-of-nursing-game .start-screen {
     display: flex;
     display: flex;
     flex-direction: column;
     flex-direction: column;
Line 424: Line 425:
}
}


#wheel-of-nursing-game .start-screen h1 {
.wheel-of-nursing-game .start-screen h1 {
     color: #ffd700;
     color: #ffd700;
     font-size: 48px;
     font-size: 48px;
Line 432: Line 433:
}
}


#wheel-of-nursing-game .start-screen p {
.wheel-of-nursing-game .start-screen p {
     font-size: 18px;
     font-size: 18px;
     max-width: 600px;
     max-width: 600px;
Line 439: Line 440:
}
}


#wheel-of-nursing-game .sound-notice {
.wheel-of-nursing-game .sound-notice {
     background: rgba(255,255,255,0.1);
     background: rgba(255,255,255,0.1);
     padding: 20px;
     padding: 20px;
Line 446: Line 447:
}
}


#wheel-of-nursing-game .sound-notice p:first-child {
.wheel-of-nursing-game .sound-notice p:first-child {
     color: #ffd700;
     color: #ffd700;
     margin-bottom: 10px;
     margin-bottom: 10px;
}
}


#wheel-of-nursing-game .sound-notice p:last-child {
.wheel-of-nursing-game .sound-notice p:last-child {
     color: #aaa;
     color: #aaa;
     font-size: 14px;
     font-size: 14px;
Line 457: Line 458:
}
}


#wheel-of-nursing-game .start-btn {
.wheel-of-nursing-game .start-btn {
     padding: 20px 60px;
     padding: 20px 60px;
     font-size: 24px;
     font-size: 24px;
Line 470: Line 471:
}
}


#wheel-of-nursing-game .start-btn:hover {
.wheel-of-nursing-game .start-btn:hover {
     transform: scale(1.05);
     transform: scale(1.05);
}
}


#wheel-of-nursing-game .hidden {
.wheel-of-nursing-game .hidden {
     display: none !important;
     display: none !important;
}
}
</style>
</style>


<div id="wheel-of-nursing-game">
<div class="wheel-of-nursing-game">
     <div class="sound-controls">
     <div class="sound-controls">
         <div>
         <div>
Line 580: Line 581:
<script>
<script>
(function() {
(function() {
    // Namespace to avoid conflicts with MediaWiki
     window.WON = window.WON || {};
     window.WON = window.WON || {};
      
      
     const QUESTIONS = [
     var QUESTIONS = [
         { category: "CARDIOVASCULAR", clue: "This class of medications ending in '-pril' treats hypertension by blocking angiotensin conversion", answer: "ACE INHIBITORS", hint: "Think lisinopril, enalapril" },
         { category: "CARDIOVASCULAR", clue: "This class of medications ending in '-pril' treats hypertension by blocking angiotensin conversion", answer: "ACE INHIBITORS", hint: "Think lisinopril, enalapril" },
         { category: "ENDOCRINE", clue: "This hormone produced by beta cells of the pancreas lowers blood glucose levels", answer: "INSULIN", hint: "Diabetic patients may inject this" },
         { category: "ENDOCRINE", clue: "This hormone produced by beta cells of the pancreas lowers blood glucose levels", answer: "INSULIN", hint: "Diabetic patients may inject this" },
Line 595: Line 595:
         { category: "MUSCULOSKELETAL", clue: "This bisphosphonate medication treats osteoporosis by inhibiting bone resorption", answer: "ALENDRONATE", hint: "Brand name Fosamax" },
         { category: "MUSCULOSKELETAL", clue: "This bisphosphonate medication treats osteoporosis by inhibiting bone resorption", answer: "ALENDRONATE", hint: "Brand name Fosamax" },
         { category: "FUNDAMENTALS", clue: "These are the six rights of medication administration: right patient, drug, dose, route, time, and this", answer: "DOCUMENTATION", hint: "Record keeping" },
         { category: "FUNDAMENTALS", clue: "These are the six rights of medication administration: right patient, drug, dose, route, time, and this", answer: "DOCUMENTATION", hint: "Record keeping" },
         { category: "FLUID & ELECTROLYTE", clue: "This electrolyte imbalance causes peaked T waves on ECG and requires immediate treatment", answer: "HYPERKALEMIA", hint: "Too much potassium" },
         { category: "FLUID AND ELECTROLYTE", clue: "This electrolyte imbalance causes peaked T waves on ECG and requires immediate treatment", answer: "HYPERKALEMIA", hint: "Too much potassium" },
         { category: "INFECTION", clue: "This antibiotic class ending in '-cillin' works by inhibiting cell wall synthesis", answer: "PENICILLINS", hint: "Amoxicillin belongs here" },
         { category: "INFECTION", clue: "This antibiotic class ending in '-cillin' works by inhibiting cell wall synthesis", answer: "PENICILLINS", hint: "Amoxicillin belongs here" },
         { category: "SENSORY", clue: "These eye drops ending in '-olol' treat glaucoma by reducing aqueous humor production", answer: "BETA BLOCKERS", hint: "Timolol is commonly used" },
         { category: "SENSORY", clue: "These eye drops ending in '-olol' treat glaucoma by reducing aqueous humor production", answer: "BETA BLOCKERS", hint: "Timolol is commonly used" },
Line 604: Line 604:
     ];
     ];


     const WHEEL_SEGMENTS = [
     var WHEEL_SEGMENTS = [
         { value: 100, color: '#e74c3c' }, { value: 200, color: '#3498db' },
         { value: 100, color: '#e74c3c' }, { value: 200, color: '#3498db' },
         { value: 300, color: '#2ecc71' }, { value: 400, color: '#f39c12' },
         { value: 300, color: '#2ecc71' }, { value: 400, color: '#f39c12' },
Line 613: Line 613:
     ];
     ];


     const CONSONANTS = 'BCDFGHJKLMNPQRSTVWXYZ'.split('');
     var CONSONANTS = 'BCDFGHJKLMNPQRSTVWXYZ'.split('');
     const VOWELS = ['A', 'E', 'I', 'O', 'U'];
     var VOWELS = ['A', 'E', 'I', 'O', 'U'];


     let currentQuestion = null;
     var currentQuestion = null;
     let revealedLetters = new Set();
     var revealedLetters = new Set();
     let totalScore = 0;
     var totalScore = 0;
     let roundScore = 0;
     var roundScore = 0;
     let wheelRotation = 0;
     var wheelRotation = 0;
     let currentWheelValue = null;
     var currentWheelValue = null;
     let gamePhase = 'start';
     var gamePhase = 'start';
     let spinning = false;
     var spinning = false;
     let usedQuestions = [];
     var usedQuestions = [];
     let hintUsed = false;
     var hintUsed = false;


     let audioContext = null;
     var audioContext = null;
     let musicGain = null;
     var musicGain = null;
     let sfxGain = null;
     var sfxGain = null;
     let musicEnabled = true;
     var musicEnabled = true;
     let sfxEnabled = true;
     var sfxEnabled = true;
     let musicPlaying = false;
     var musicPlaying = false;


     function initAudio() {
     function initAudio() {
Line 650: Line 650:
         if (!audioContext || !sfxEnabled) return;
         if (!audioContext || !sfxEnabled) return;
         gain = gain || sfxGain;
         gain = gain || sfxGain;
         const osc = audioContext.createOscillator();
         var osc = audioContext.createOscillator();
         const noteGain = audioContext.createGain();
         var noteGain = audioContext.createGain();
         osc.type = type || 'sine';
         osc.type = type || 'sine';
         osc.frequency.setValueAtTime(frequency, audioContext.currentTime);
         osc.frequency.setValueAtTime(frequency, audioContext.currentTime);
Line 664: Line 664:
     function playClick() {
     function playClick() {
         if (!audioContext || !sfxEnabled) return;
         if (!audioContext || !sfxEnabled) return;
         const osc = audioContext.createOscillator();
         var osc = audioContext.createOscillator();
         const clickGain = audioContext.createGain();
         var clickGain = audioContext.createGain();
         osc.type = 'square';
         osc.type = 'square';
         osc.frequency.setValueAtTime(800 + Math.random() * 400, audioContext.currentTime);
         osc.frequency.setValueAtTime(800 + Math.random() * 400, audioContext.currentTime);
Line 678: Line 678:
     function playWheelSpin(duration) {
     function playWheelSpin(duration) {
         if (!audioContext || !sfxEnabled) return;
         if (!audioContext || !sfxEnabled) return;
         let time = 0;
         var time = 0;
         for (let i = 0; i < 60; i++) {
         for (var i = 0; i < 60; i++) {
             const interval = 30 * Math.pow(1 + (i/60) * 3, 2);
             var interval = 30 * Math.pow(1 + (i/60) * 3, 2);
             if (time < duration) setTimeout(playClick, time);
             if (time < duration) setTimeout(playClick, time);
             time += interval;
             time += interval;
Line 688: Line 688:
     function playCorrect() {
     function playCorrect() {
         if (!sfxEnabled) return;
         if (!sfxEnabled) return;
         [523.25, 659.25, 783.99].forEach((f, i) => setTimeout(() => playNote(f, 0.2, 'sine'), i * 100));
         [523.25, 659.25, 783.99].forEach(function(f, i) { setTimeout(function() { playNote(f, 0.2, 'sine'); }, i * 100); });
     }
     }


     function playWrong() {
     function playWrong() {
         if (!audioContext || !sfxEnabled) return;
         if (!audioContext || !sfxEnabled) return;
         const osc = audioContext.createOscillator();
         var osc = audioContext.createOscillator();
         const g = audioContext.createGain();
         var g = audioContext.createGain();
         osc.type = 'sawtooth';
         osc.type = 'sawtooth';
         osc.frequency.setValueAtTime(150, audioContext.currentTime);
         osc.frequency.setValueAtTime(150, audioContext.currentTime);
Line 707: Line 707:
     function playBankrupt() {
     function playBankrupt() {
         if (!sfxEnabled) return;
         if (!sfxEnabled) return;
         [400, 350, 300, 250, 200, 150].forEach((f, i) => setTimeout(() => playNote(f, 0.15, 'sawtooth'), i * 80));
         [400, 350, 300, 250, 200, 150].forEach(function(f, i) { setTimeout(function() { playNote(f, 0.15, 'sawtooth'); }, i * 80); });
     }
     }


     function playWin() {
     function playWin() {
         if (!sfxEnabled) return;
         if (!sfxEnabled) return;
         const m = [{f:523.25,d:0.15},{f:523.25,d:0.15},{f:523.25,d:0.15},{f:523.25,d:0.4},{f:415.30,d:0.4},{f:466.16,d:0.4},{f:523.25,d:0.3},{f:466.16,d:0.15},{f:523.25,d:0.6}];
         var m = [{f:523.25,d:0.15},{f:523.25,d:0.15},{f:523.25,d:0.15},{f:523.25,d:0.4},{f:415.30,d:0.4},{f:466.16,d:0.4},{f:523.25,d:0.3},{f:466.16,d:0.15},{f:523.25,d:0.6}];
         let t = 0;
         var t = 0;
         m.forEach(n => { setTimeout(() => playNote(n.f, n.d, 'square'), t); t += n.d * 500; });
         m.forEach(function(n) { setTimeout(function() { playNote(n.f, n.d, 'square'); }, t); t += n.d * 500; });
     }
     }


     function playLose() {
     function playLose() {
         if (!sfxEnabled) return;
         if (!sfxEnabled) return;
         [392, 369.99, 349.23, 329.63, 293.66].forEach((f, i) => setTimeout(() => playNote(f, 0.3, 'sine'), i * 200));
         [392, 369.99, 349.23, 329.63, 293.66].forEach(function(f, i) { setTimeout(function() { playNote(f, 0.3, 'sine'); }, i * 200); });
     }
     }


     function playMusicNote(frequency, duration, type) {
     function playMusicNote(frequency, duration, type) {
         if (!audioContext || !musicPlaying) return;
         if (!audioContext || !musicPlaying) return;
         const osc = audioContext.createOscillator();
         var osc = audioContext.createOscillator();
         const g = audioContext.createGain();
         var g = audioContext.createGain();
         osc.type = type;
         osc.type = type;
         osc.frequency.setValueAtTime(frequency, audioContext.currentTime);
         osc.frequency.setValueAtTime(frequency, audioContext.currentTime);
Line 738: Line 738:
     function playMusicLoop() {
     function playMusicLoop() {
         if (!musicPlaying || !audioContext) return;
         if (!musicPlaying || !audioContext) return;
         const bass = [{f:130.81,d:0.5},{f:146.83,d:0.5},{f:164.81,d:0.5},{f:174.61,d:0.5},{f:196.00,d:0.5},{f:174.61,d:0.5},{f:164.81,d:0.5},{f:146.83,d:0.5}];
         var bass = [{f:130.81,d:0.5},{f:146.83,d:0.5},{f:164.81,d:0.5},{f:174.61,d:0.5},{f:196.00,d:0.5},{f:174.61,d:0.5},{f:164.81,d:0.5},{f:146.83,d:0.5}];
         const mel = [{f:523.25,d:0.25},{f:587.33,d:0.25},{f:659.25,d:0.5},{f:698.46,d:0.25},{f:783.99,d:0.75},{f:659.25,d:0.5},{f:523.25,d:0.5},{f:587.33,d:0.5}];
         var mel = [{f:523.25,d:0.25},{f:587.33,d:0.25},{f:659.25,d:0.5},{f:698.46,d:0.25},{f:783.99,d:0.75},{f:659.25,d:0.5},{f:523.25,d:0.5},{f:587.33,d:0.5}];
         let t = 0;
         var t = 0;
         bass.forEach(n => { setTimeout(() => { if(musicPlaying) playMusicNote(n.f, n.d*0.9, 'triangle'); }, t); t += n.d*500; });
         bass.forEach(function(n) { setTimeout(function() { if(musicPlaying) playMusicNote(n.f, n.d*0.9, 'triangle'); }, t); t += n.d*500; });
         let mt = 250;
         var mt = 250;
         mel.forEach(n => { setTimeout(() => { if(musicPlaying) playMusicNote(n.f, n.d*0.8, 'sine'); }, mt); mt += n.d*500; });
         mel.forEach(function(n) { setTimeout(function() { if(musicPlaying) playMusicNote(n.f, n.d*0.8, 'sine'); }, mt); mt += n.d*500; });
         setTimeout(() => { if(musicPlaying) playMusicLoop(); }, 4000);
         setTimeout(function() { if(musicPlaying) playMusicLoop(); }, 4000);
     }
     }


Line 758: Line 758:
         initAudio();
         initAudio();
         musicEnabled = !musicEnabled;
         musicEnabled = !musicEnabled;
         const btn = document.getElementById('wonMusicToggle');
         var btn = document.getElementById('wonMusicToggle');
         if (musicEnabled) { btn.textContent = '🎵 Music ON'; btn.className = 'on'; startMusic(); }
         if (musicEnabled) { btn.textContent = '🎵 Music ON'; btn.className = 'on'; startMusic(); }
         else { btn.textContent = '🔇 Music OFF'; btn.className = 'off'; stopMusic(); }
         else { btn.textContent = '🔇 Music OFF'; btn.className = 'off'; stopMusic(); }
Line 766: Line 766:
         initAudio();
         initAudio();
         sfxEnabled = !sfxEnabled;
         sfxEnabled = !sfxEnabled;
         const btn = document.getElementById('wonSfxToggle');
         var btn = document.getElementById('wonSfxToggle');
         btn.textContent = sfxEnabled ? '🔊 SFX ON' : '🔇 SFX OFF';
         btn.textContent = sfxEnabled ? '🔊 SFX ON' : '🔇 SFX OFF';
         btn.className = sfxEnabled ? 'on' : 'off';
         btn.className = sfxEnabled ? 'on' : 'off';
Line 775: Line 775:


     function drawWheel() {
     function drawWheel() {
         const svg = document.getElementById('wonWheel');
         var svg = document.getElementById('wonWheel');
         svg.innerHTML = '';
         svg.innerHTML = '';
         const segAngle = 360 / WHEEL_SEGMENTS.length;
         var segAngle = 360 / WHEEL_SEGMENTS.length;
         WHEEL_SEGMENTS.forEach((seg, i) => {
         WHEEL_SEGMENTS.forEach(function(seg, i) {
             const sa = i * segAngle, ea = (i+1) * segAngle;
             var sa = i * segAngle, ea = (i+1) * segAngle;
             const sr = (sa-90)*Math.PI/180, er = (ea-90)*Math.PI/180;
             var sr = (sa-90)*Math.PI/180, er = (ea-90)*Math.PI/180;
             const x1 = 100+90*Math.cos(sr), y1 = 100+90*Math.sin(sr);
             var x1 = 100+90*Math.cos(sr), y1 = 100+90*Math.sin(sr);
             const x2 = 100+90*Math.cos(er), y2 = 100+90*Math.sin(er);
             var x2 = 100+90*Math.cos(er), y2 = 100+90*Math.sin(er);
             const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
             var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
             path.setAttribute('d', `M 100 100 L ${x1} ${y1} A 90 90 0 0 1 ${x2} ${y2} Z`);
             path.setAttribute('d', 'M 100 100 L ' + x1 + ' ' + y1 + ' A 90 90 0 0 1 ' + x2 + ' ' + y2 + ' Z');
             path.setAttribute('fill', seg.color);
             path.setAttribute('fill', seg.color);
             path.setAttribute('stroke', '#fff');
             path.setAttribute('stroke', '#fff');
             path.setAttribute('stroke-width', '2');
             path.setAttribute('stroke-width', '2');
             svg.appendChild(path);
             svg.appendChild(path);
             const ma = ((sa+ea)/2-90)*Math.PI/180;
             var ma = ((sa+ea)/2-90)*Math.PI/180;
             const tx = 100+60*Math.cos(ma), ty = 100+60*Math.sin(ma);
             var tx = 100+60*Math.cos(ma), ty = 100+60*Math.sin(ma);
             const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
             var text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
             text.setAttribute('x', tx);
             text.setAttribute('x', tx);
             text.setAttribute('y', ty);
             text.setAttribute('y', ty);
Line 799: Line 799:
             text.setAttribute('text-anchor', 'middle');
             text.setAttribute('text-anchor', 'middle');
             text.setAttribute('dominant-baseline', 'middle');
             text.setAttribute('dominant-baseline', 'middle');
             text.setAttribute('transform', `rotate(${(sa+ea)/2}, ${tx}, ${ty})`);
             text.setAttribute('transform', 'rotate(' + ((sa+ea)/2) + ', ' + tx + ', ' + ty + ')');
             text.textContent = typeof seg.value === 'number' ? `$${seg.value}` : seg.value;
             text.textContent = typeof seg.value === 'number' ? ('$' + seg.value) : seg.value;
             svg.appendChild(text);
             svg.appendChild(text);
         });
         });
         const c = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
         var c = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
         c.setAttribute('cx', '100'); c.setAttribute('cy', '100'); c.setAttribute('r', '20');
         c.setAttribute('cx', '100'); c.setAttribute('cy', '100'); c.setAttribute('r', '20');
         c.setAttribute('fill', '#ffd700'); c.setAttribute('stroke', '#fff'); c.setAttribute('stroke-width', '3');
         c.setAttribute('fill', '#ffd700'); c.setAttribute('stroke', '#fff'); c.setAttribute('stroke-width', '3');
Line 810: Line 810:


     function renderPuzzle() {
     function renderPuzzle() {
         const cont = document.getElementById('wonLetterTiles');
         var cont = document.getElementById('wonLetterTiles');
         cont.innerHTML = '';
         cont.innerHTML = '';
         currentQuestion.answer.toUpperCase().split('').forEach(ch => {
         currentQuestion.answer.toUpperCase().split('').forEach(function(ch) {
             const tile = document.createElement('div');
             var tile = document.createElement('div');
             tile.className = 'letter-tile';
             tile.className = 'letter-tile';
             if (ch === ' ') tile.classList.add('space');
             if (ch === ' ') tile.classList.add('space');
Line 825: Line 825:


     function renderLetterButtons() {
     function renderLetterButtons() {
         const cc = document.getElementById('wonConsonants'), vc = document.getElementById('wonVowels');
         var cc = document.getElementById('wonConsonants'), vc = document.getElementById('wonVowels');
         cc.innerHTML = ''; vc.innerHTML = '';
         cc.innerHTML = ''; vc.innerHTML = '';
         CONSONANTS.forEach(l => {
         CONSONANTS.forEach(function(l) {
             const btn = document.createElement('button');
             var btn = document.createElement('button');
             btn.className = 'letter-btn consonant';
             btn.className = 'letter-btn consonant';
             btn.textContent = l;
             btn.textContent = l;
             btn.disabled = revealedLetters.has(l);
             btn.disabled = revealedLetters.has(l);
             if (gamePhase !== 'guess') btn.classList.add('inactive');
             if (gamePhase !== 'guess') btn.classList.add('inactive');
             btn.onclick = () => guessLetter(l);
             btn.onclick = function() { guessLetter(l); };
             cc.appendChild(btn);
             cc.appendChild(btn);
         });
         });
         VOWELS.forEach(v => {
         VOWELS.forEach(function(v) {
             const btn = document.createElement('button');
             var btn = document.createElement('button');
             btn.className = 'letter-btn vowel';
             btn.className = 'letter-btn vowel';
             btn.textContent = v;
             btn.textContent = v;
             btn.disabled = revealedLetters.has(v) || roundScore < 250;
             btn.disabled = revealedLetters.has(v) || roundScore < 250;
             if (gamePhase !== 'spin') btn.classList.add('inactive');
             if (gamePhase !== 'spin') btn.classList.add('inactive');
             btn.onclick = () => buyVowel(v);
             btn.onclick = function() { buyVowel(v); };
             vc.appendChild(btn);
             vc.appendChild(btn);
         });
         });
Line 848: Line 848:


     function updateUI() {
     function updateUI() {
         document.getElementById('wonRoundScore').textContent = `$${roundScore}`;
         document.getElementById('wonRoundScore').textContent = '$' + roundScore;
         document.getElementById('wonTotalScore').textContent = `$${totalScore}`;
         document.getElementById('wonTotalScore').textContent = '$' + totalScore;
         const spinBtn = document.getElementById('wonSpinBtn');
         var spinBtn = document.getElementById('wonSpinBtn');
         spinBtn.disabled = spinning || gamePhase !== 'spin';
         spinBtn.disabled = spinning || gamePhase !== 'spin';
         spinBtn.textContent = spinning ? '🎡 Spinning...' : '🎡 Spin Wheel';
         spinBtn.textContent = spinning ? '🎡 Spinning...' : '🎡 Spin Wheel';
Line 859: Line 859:
     function setMessage(msg, wv) {
     function setMessage(msg, wv) {
         document.getElementById('wonMessage').textContent = msg;
         document.getElementById('wonMessage').textContent = msg;
         const wve = document.getElementById('wonWheelValue');
         var wve = document.getElementById('wonWheelValue');
         if (wv !== null && wv !== undefined) { wve.textContent = `Current: $${wv}`; wve.classList.remove('hidden'); }
         if (wv !== null && wv !== undefined) { wve.textContent = 'Current: $' + wv; wve.classList.remove('hidden'); }
         else wve.classList.add('hidden');
         else wve.classList.add('hidden');
     }
     }
Line 874: Line 874:


     function startNewRound() {
     function startNewRound() {
         let avail = QUESTIONS.filter((_, i) => !usedQuestions.includes(i));
         var avail = QUESTIONS.filter(function(_, i) { return usedQuestions.indexOf(i) === -1; });
         if (avail.length === 0) { usedQuestions = []; avail = QUESTIONS; }
         if (avail.length === 0) { usedQuestions = []; avail = QUESTIONS; }
         const idx = QUESTIONS.indexOf(avail[Math.floor(Math.random() * avail.length)]);
         var idx = QUESTIONS.indexOf(avail[Math.floor(Math.random() * avail.length)]);
         usedQuestions.push(idx);
         usedQuestions.push(idx);
         currentQuestion = QUESTIONS[idx];
         currentQuestion = QUESTIONS[idx];
Line 903: Line 903:
         updateUI();
         updateUI();
         playWheelSpin(3000);
         playWheelSpin(3000);
         const spins = 3 + Math.random() * 3;
         var spins = 3 + Math.random() * 3;
         const segAngle = 360 / WHEEL_SEGMENTS.length;
         var segAngle = 360 / WHEEL_SEGMENTS.length;
         const randSeg = Math.floor(Math.random() * WHEEL_SEGMENTS.length);
         var randSeg = Math.floor(Math.random() * WHEEL_SEGMENTS.length);
         wheelRotation += (spins * 360) + (randSeg * segAngle);
         wheelRotation += (spins * 360) + (randSeg * segAngle);
         document.getElementById('wonWheel').style.transform = `rotate(${wheelRotation}deg)`;
         document.getElementById('wonWheel').style.transform = 'rotate(' + wheelRotation + 'deg)';
         setTimeout(() => {
         setTimeout(function() {
             const seg = WHEEL_SEGMENTS[randSeg];
             var seg = WHEEL_SEGMENTS[randSeg];
             currentWheelValue = seg.value;
             currentWheelValue = seg.value;
             spinning = false;
             spinning = false;
             if (seg.value === 'BANKRUPT') { roundScore = 0; setMessage('BANKRUPT! You lost your round earnings. Spin again!'); gamePhase = 'spin'; playBankrupt(); }
             if (seg.value === 'BANKRUPT') { roundScore = 0; setMessage('BANKRUPT! You lost your round earnings. Spin again!'); gamePhase = 'spin'; playBankrupt(); }
             else if (seg.value === 'LOSE TURN') { setMessage('Lost your turn! Spin again.'); gamePhase = 'spin'; playWrong(); }
             else if (seg.value === 'LOSE TURN') { setMessage('Lost your turn! Spin again.'); gamePhase = 'spin'; playWrong(); }
             else { setMessage(`$${seg.value}! Pick a consonant.`, seg.value); gamePhase = 'guess'; playNote(880, 0.1, 'sine'); }
             else { setMessage('$' + seg.value + '! Pick a consonant.', seg.value); gamePhase = 'guess'; playNote(880, 0.1, 'sine'); }
             updateUI();
             updateUI();
         }, 3000);
         }, 3000);
Line 921: Line 921:
     function guessLetter(letter) {
     function guessLetter(letter) {
         if (gamePhase !== 'guess' || revealedLetters.has(letter)) return;
         if (gamePhase !== 'guess' || revealedLetters.has(letter)) return;
         const ans = currentQuestion.answer.toUpperCase();
         var ans = currentQuestion.answer.toUpperCase();
         const cnt = (ans.match(new RegExp(letter, 'g')) || []).length;
         var cnt = (ans.match(new RegExp(letter, 'g')) || []).length;
         revealedLetters.add(letter);
         revealedLetters.add(letter);
         if (cnt > 0) { const e = currentWheelValue * cnt; roundScore += e; setMessage(`Yes! ${cnt} ${letter}'s for $${e}! Spin or solve.`); playCorrect(); }
         if (cnt > 0) { var e = currentWheelValue * cnt; roundScore += e; setMessage('Yes! ' + cnt + ' ' + letter + "'s for $" + e + '! Spin or solve.'); playCorrect(); }
         else { setMessage(`No ${letter}'s. Spin the wheel!`); playWrong(); }
         else { setMessage('No ' + letter + "'s. Spin the wheel!"); playWrong(); }
         gamePhase = 'spin';
         gamePhase = 'spin';
         renderPuzzle();
         renderPuzzle();
Line 935: Line 935:
         if (gamePhase !== 'spin' || revealedLetters.has(vowel) || roundScore < 250) return;
         if (gamePhase !== 'spin' || revealedLetters.has(vowel) || roundScore < 250) return;
         roundScore -= 250;
         roundScore -= 250;
         const ans = currentQuestion.answer.toUpperCase();
         var ans = currentQuestion.answer.toUpperCase();
         const cnt = (ans.match(new RegExp(vowel, 'g')) || []).length;
         var cnt = (ans.match(new RegExp(vowel, 'g')) || []).length;
         revealedLetters.add(vowel);
         revealedLetters.add(vowel);
         if (cnt > 0) { setMessage(`Yes! ${cnt} ${vowel}'s! Spin or solve.`); playCorrect(); }
         if (cnt > 0) { setMessage('Yes! ' + cnt + ' ' + vowel + "'s! Spin or solve."); playCorrect(); }
         else { setMessage(`No ${vowel}'s. Spin the wheel!`); playWrong(); }
         else { setMessage('No ' + vowel + "'s. Spin the wheel!"); playWrong(); }
         renderPuzzle();
         renderPuzzle();
         updateUI();
         updateUI();
Line 946: Line 946:


     function checkPuzzleComplete() {
     function checkPuzzleComplete() {
         const ans = currentQuestion.answer.toUpperCase();
         var ans = currentQuestion.answer.toUpperCase();
         const unique = new Set(ans.replace(/[^A-Z]/g, '').split(''));
         var unique = new Set(ans.replace(/[^A-Z]/g, '').split(''));
         if ([...unique].every(l => revealedLetters.has(l))) {
         var allRevealed = true;
        unique.forEach(function(l) { if (!revealedLetters.has(l)) allRevealed = false; });
        if (allRevealed) {
             totalScore += roundScore;
             totalScore += roundScore;
             setMessage(`Puzzle Complete! You earned $${roundScore}!`);
             setMessage('Puzzle Complete! You earned $' + roundScore + '!');
             showResult(true);
             showResult(true);
             playWin();
             playWin();
Line 966: Line 968:


     WON.submitSolve = function() {
     WON.submitSolve = function() {
         const guess = document.getElementById('wonSolveInput').value.toUpperCase().trim();
         var guess = document.getElementById('wonSolveInput').value.toUpperCase().trim();
         const ans = currentQuestion.answer.toUpperCase().trim();
         var ans = currentQuestion.answer.toUpperCase().trim();
         if (guess === ans) { totalScore += roundScore + 500; setMessage(`Correct! "${ans}" - You earned $${roundScore + 500}!`); showResult(true); playWin(); }
         if (guess === ans) { totalScore += roundScore + 500; setMessage('Correct! "' + ans + '" - You earned $' + (roundScore + 500) + '!'); showResult(true); playWin(); }
         else { setMessage(`Wrong! The answer was "${ans}".`); showResult(false); playLose(); }
         else { setMessage('Wrong! The answer was "' + ans + '".'); showResult(false); playLose(); }
         document.getElementById('wonSolveInput').value = '';
         document.getElementById('wonSolveInput').value = '';
     };
     };
Line 987: Line 989:
         document.getElementById('wonHintBox').classList.remove('hidden');
         document.getElementById('wonHintBox').classList.remove('hidden');
         document.getElementById('wonHintBtn').disabled = true;
         document.getElementById('wonHintBtn').disabled = true;
         setMessage(`Hint used (-$200): ${currentQuestion.hint}`);
         setMessage('Hint used (-$200): ' + currentQuestion.hint);
         updateUI();
         updateUI();
         playNote(600, 0.05, 'square');
         playNote(600, 0.05, 'square');
Line 998: Line 1,000:
         document.getElementById('wonActionButtons').classList.add('hidden');
         document.getElementById('wonActionButtons').classList.add('hidden');
         document.getElementById('wonSolveContainer').classList.add('hidden');
         document.getElementById('wonSolveContainer').classList.add('hidden');
         const rs = document.getElementById('wonResultScreen');
         var rs = document.getElementById('wonResultScreen');
         rs.classList.remove('hidden', 'won', 'lost');
         rs.classList.remove('hidden', 'won', 'lost');
         rs.classList.add(won ? 'won' : 'lost');
         rs.classList.add(won ? 'won' : 'lost');
         document.getElementById('wonResultTitle').textContent = won ? '🎉 Congratulations!' : '😔 Better Luck Next Time!';
         document.getElementById('wonResultTitle').textContent = won ? '🎉 Congratulations!' : '😔 Better Luck Next Time!';
         document.getElementById('wonFinalScore').textContent = `$${totalScore}`;
         document.getElementById('wonFinalScore').textContent = '$' + totalScore;
     }
     }


Line 1,011: Line 1,013:
})();
})();
</script>
</script>
</includeonly>
</html></includeonly>

Latest revision as of 00:37, 11 January 2026

This widget displays the Wheel of Nursing pharmacology game.

Usage

{{#widget:WheelOfNursing}}

Parameters

This widget does not accept any parameters.