Untitled
unknown
plain_text
10 months ago
16 kB
13
Indexable
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Shofar! Tashlich! High-Ho — Rosh Hashanah Game</title>
<style>
:root{
--bg:#f8fafc; --card:#ffffff; --muted:#64748b; --accent:#f59e0b;
--green:#10b981; --red:#ef4444; --blue:#3b82f6;
}
*{box-sizing:border-box;font-family:Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial;}
body{margin:0;background:linear-gradient(180deg,#f1f5f9 0%,var(--bg) 100%);color:#0f172a;padding:28px;}
.wrap{max-width:1000px;margin:0 auto;background:var(--card);border-radius:14px;padding:20px;box-shadow:0 10px 30px rgba(2,6,23,.08);}
header{display:flex;gap:12px;align-items:center;justify-content:space-between;}
h1{margin:0;font-size:20px;}
.meta{font-size:13px;color:var(--muted);text-align:right;}
.controls{display:flex;gap:8px;flex-wrap:wrap;margin:16px 0;}
button{border:0;padding:8px 12px;border-radius:8px;background:#eef2ff;cursor:pointer;font-weight:600;}
.btn-green{background:linear-gradient(90deg,#bbf7d0,#86efac);color:#064e3b;}
.btn-red{background:linear-gradient(90deg,#fecaca,#fda4af);color:#7f1d1d;}
.btn-blue{background:linear-gradient(90deg,#bfdbfe,#93c5fd);color:#1e3a8a;}
.card{background:var(--card);border-radius:12px;padding:16px;margin-bottom:12px;border:1px solid #eef2ff;}
.q-area{min-height:120px;}
.prompt {margin-top:12px;padding:12px;border-radius:10px;}
.prompt.good{background:#ecfdf5;color:#064e3b;}
.prompt.bad{background:#fff1f2;color:#7f1d1d;}
.history{max-height:160px;overflow:auto;margin-top:8px;font-size:13px;color:var(--muted);}
input[type=number]{padding:8px;border-radius:8px;border:1px solid #e6eef8;width:110px;}
.footer{font-size:13px;color:var(--muted);margin-top:8px;}
.small{font-size:13px;color:var(--muted);}
.grid{display:grid;grid-template-columns:1fr 320px;gap:12px;}
@media (max-width:860px){.grid{grid-template-columns:1fr;}}
.chip{display:inline-block;background:#f1f5f9;padding:6px 8px;border-radius:999px;font-weight:600;margin-right:6px;font-size:13px;}
.round-buttons button{background:#f8fafc;}
.muted{color:var(--muted);}
</style>
</head>
<body>
<div class="wrap" role="application" aria-label="Rosh Hashanah Game">
<header>
<div>
<h1>Shofar! Tashlich! High-Ho — Rosh Hashanah Game</h1>
<div class="small muted">Two-day quiz-play: learn, laugh, and toss symbolic tashlich tokens.</div>
</div>
<div class="meta" id="meta">
Day: <strong id="dayLabel">1</strong> · Round: <strong id="roundLabel">A</strong><br>
Score: <strong id="score">0</strong> · Tashlich tokens: <strong id="tokens">3</strong>
</div>
</header>
<div class="controls">
<button id="toggleDay">Toggle Day</button>
<div class="round-buttons" style="display:flex;gap:6px;">
<button data-round="A">Round A</button>
<button data-round="B">Round B</button>
<button data-round="C">Round C</button>
<button data-round="D">Round D</button>
<button data-round="E">Round E</button>
</div>
<div style="margin-left:auto;display:flex;gap:8px;">
<button id="resetGame" style="background:linear-gradient(90deg,#fff7ed,#ffedd5);">Reset Game</button>
<button id="nextQ" class="btn-blue">Next Q</button>
</div>
</div>
<div class="grid">
<main>
<div class="card">
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:12px;">
<div>
<div class="chip">Question (<span id="qpts">—</span> pts)</div>
<div class="q-area" id="questionText" aria-live="polite">Select a round to start.</div>
</div>
<div style="min-width:220px;">
<div style="display:flex;flex-direction:column;gap:8px;">
<button id="markCorrect" class="btn-green">Mark Correct</button>
<button id="markWrong" class="btn-red">Mark Wrong</button>
<button id="showAns" style="background:#eef2ff">Show answer</button>
</div>
</div>
</div>
<div id="promptContainer" style="margin-top:12px;"></div>
<details style="margin-top:12px;">
<summary style="cursor:pointer">Answer / Explanation</summary>
<div id="answerText" style="margin-top:8px;padding:8px;background:#fbfdff;border-radius:8px;color:var(--muted)"></div>
</details>
</div>
<div class="card">
<strong>Mini-games & ideas</strong>
<ul class="small">
<li>Tashlich Toss — toss tokens into a bucket for bonus points.</li>
<li>Shofar Imitation — imitate Tekiah / Shevarim / Teruah for points.</li>
<li>Machzor Read — pick a short excerpt and read dramatically for extra points.</li>
</ul>
</div>
<div class="card">
<strong>Quick script for the quizmaster</strong>
<p class="small muted">Read the question; players answer; mark correct/wrong; read the shuffled prompt in a silly voice; hand out tashlich tokens when earned.</p>
</div>
</main>
<aside>
<div class="card">
<strong>History</strong>
<div class="history" id="history"></div>
</div>
<div class="card">
<strong>Game Controls</strong>
<div style="margin-top:8px;">
<label class="small muted">Tashlich tokens:</label>
<div style="display:flex;gap:8px;align-items:center;margin-top:6px;">
<button id="tokMinus">-</button>
<div id="tokenVal" style="min-width:50px;text-align:center;font-weight:700;">3</div>
<button id="tokPlus">+</button>
</div>
<div style="margin-top:12px;">
<label class="small muted">Set score:</label>
<div style="margin-top:6px;display:flex;gap:8px;align-items:center;">
<input id="scoreInput" type="number" value="0" min="0" />
<button id="applyScore">Apply</button>
</div>
</div>
</div>
</div>
<div class="card">
<strong>Prompts</strong>
<div class="small muted" style="margin-top:6px;">Right answers & playful roasts are randomized from clean lists (no threats).</div>
<div style="margin-top:8px;">
<div class="small"><strong>Right:</strong> Good job my cookie · Permission to marry my daughter · If you're cooking I'm eating · Hi Gabriel · Hi Carlos · Whopper... · Hi Ashira · Correct my sunshine · 1+1=2 · Claim an extra tashlich token</div>
<div class="small" style="margin-top:8px;"><strong>Wrong:</strong> Goodbye Gabriel · Goodbye Carlos · Goodbye Ashira · That was easy bro — you silly goose · WRONG — sorry · Playful roast · Better luck next time · You owe apple & honey</div>
</div>
</div>
</aside>
</div>
<div class="footer">Tip: for kids/family remove the roasts and replace with encouraging prompts. Want a printable card deck? Ask and I'll generate one.</div>
</div>
<script>
(() => {
// Questions deck
const questions = [
{ q: "Rosh Hashanah signifies what?", a: "The Jewish New Year — a time of reflection and renewal.", pts: 10, day:1, round:"A" },
{ q: "Name one traditional food eaten with honey.", a: "Apple (or challah dipped in honey).", pts: 10, day:1, round:"B" },
{ q: "What is tashlich?", a: "A ritual of symbolically casting away sins by tossing pieces of bread into flowing water.", pts: 15, day:1, round:"B", bonusToken:true },
{ q: "Name the three basic shofar sounds called during Rosh Hashanah services.", a: "Tekiah, Shevarim, Teruah.", pts: 15, day:2, round:"C" },
{ q: "Which Torah story is often read on Rosh Hashanah (the Akedah)?", a: "The Binding of Isaac (Genesis 22).", pts: 20, day:2, round:"C" },
{ q: "What is a machzor?", a: "A special prayerbook for the High Holy Days.", pts: 10, day:2, round:"D" },
{ q: "If Rosh Hashanah starts at sundown on Sept 24 and ends at sunset on Sept 26, how many days does it last?", a: "Two days (from sundown to sundown).", pts: 10, day:2, round:"E" },
];
// Cleaned prompts
const congrats = [
"Good job, my cookie.",
"I give you permission to marry my daughter.",
"If you are cooking then I am eating.",
"Hi Gabriel.",
"Hi Carlos.",
"Whopper whopper whopper whopper junior double triple whopper.",
"Hi Ashira.",
"Correct, my sunshine!",
"1 + 1 = 2.",
"Nice — claim an extra tashlich token!"
];
const wrongs = [
"Goodbye Gabriel.",
"Goodbye Carlos.",
"Goodbye Ashira.",
"That question was easy bro — how did you get it wrong, you silly goose?",
"WRONG — sorry for being harsh.",
"You are a disappointment (playful roast).",
"I would say 'better luck next time' but you haven't got a question right so I've lost all hope in you (roast).",
"Uh oh — you owe the table an apple & honey for moral support."
];
// UI elements
const dayLabel = document.getElementById('dayLabel');
const roundLabel = document.getElementById('roundLabel');
const scoreEl = document.getElementById('score');
const tokensEl = document.getElementById('tokens');
const questionText = document.getElementById('questionText');
const answerText = document.getElementById('answerText');
const qpts = document.getElementById('qpts');
const promptContainer = document.getElementById('promptContainer');
const historyEl = document.getElementById('history');
const tokenVal = document.getElementById('tokenVal');
// Buttons
const toggleDayBtn = document.getElementById('toggleDay');
const nextQBtn = document.getElementById('nextQ');
const markCorrectBtn = document.getElementById('markCorrect');
const markWrongBtn = document.getElementById('markWrong');
const showAnsBtn = document.getElementById('showAns');
const resetBtn = document.getElementById('resetGame');
const tokMinus = document.getElementById('tokMinus');
const tokPlus = document.getElementById('tokPlus');
const scoreInput = document.getElementById('scoreInput');
const applyScoreBtn = document.getElementById('applyScore');
// Round buttons
document.querySelectorAll('.round-buttons button').forEach(btn => {
btn.addEventListener('click', () => {
setRound(btn.dataset.round);
});
});
// Game state
let day = 1;
let round = 'A';
let score = 0;
let tokens = 3;
let currentIndex = -1;
let history = [];
function updateMeta(){
dayLabel.textContent = day;
roundLabel.textContent = round;
scoreEl.textContent = score;
tokensEl.textContent = tokens;
tokenVal.textContent = tokens;
qpts.textContent = (currentQuestion() ? currentQuestion().pts : '—');
}
function shufflePick(arr){
return arr[Math.floor(Math.random()*arr.length)];
}
function currentQuestion(){
if(currentIndex >= 0 && currentIndex < questions.length){
const q = questions[currentIndex];
if(q.day === day && q.round === round) return q;
}
return null;
}
function findFirstIndexFor(dayX, roundX){
return questions.findIndex(q => q.day === dayX && q.round === roundX);
}
function setRound(r){
round = r;
roundLabel.textContent = round;
const idx = findFirstIndexFor(day, round);
currentIndex = idx >= 0 ? idx : -1;
renderQuestion();
}
function toggleDay(){
day = (day === 1 ? 2 : 1);
const idx = findFirstIndexFor(day, round);
currentIndex = idx >= 0 ? idx : -1;
renderQuestion();
}
function nextQuestion(){
if(currentIndex < 0){
// pick first for this day/round
const idx = findFirstIndexFor(day, round);
currentIndex = idx >= 0 ? idx : -1;
renderQuestion();
return;
}
let i = currentIndex + 1;
while(i < questions.length && (questions[i].day !== day || questions[i].round !== round)) i++;
if(i >= questions.length){
// wrap to first for this day/round
const idx = findFirstIndexFor(day, round);
currentIndex = idx >= 0 ? idx : -1;
} else currentIndex = i;
renderQuestion();
}
function markCorrect(){
const q = currentQuestion();
if(!q) return;
score += q.pts || 0;
if(q.bonusToken) tokens += 1;
const p = shufflePick(congrats);
history.push({ q: q.q, correct: true, pts: q.pts, prompt: p});
renderPrompt(true, p);
renderHistory();
updateMeta();
}
function markWrong(){
const q = currentQuestion();
if(!q) return;
const p = shufflePick(wrongs);
history.push({ q: q.q, correct: false, pts: 0, prompt: p});
renderPrompt(false, p);
renderHistory();
}
function renderPrompt(good, text){
promptContainer.innerHTML = '';
const div = document.createElement('div');
div.className = 'prompt ' + (good ? 'good' : 'bad');
div.innerHTML = '<strong>' + (good ? 'Congrats!' : 'Oops!') + '</strong><div style="margin-top:8px;">' + escapeHtml(text) + '</div>';
promptContainer.appendChild(div);
}
function renderQuestion(){
answerText.textContent = '';
promptContainer.innerHTML = '';
if(currentQuestion()){
questionText.textContent = currentQuestion().q;
answerText.textContent = currentQuestion().a;
} else {
questionText.textContent = 'No question for this day/round. Use the Round buttons to select a different round or toggle the day.';
answerText.textContent = '';
}
updateMeta();
}
function renderHistory(){
historyEl.innerHTML = '';
if(history.length === 0) historyEl.textContent = 'No history yet.';
else {
// show most recent first
history.slice().reverse().forEach(h => {
const d = document.createElement('div');
d.style.marginBottom = '8px';
d.innerHTML = '<div style="font-weight:700;">Q: ' + escapeHtml(h.q) + '</div><div style="font-size:13px;color:#475569;">' + (h.correct ? '+' + h.pts + ' pts' : '0 pts') + ' — <em>' + escapeHtml(h.prompt) + '</em></div>';
historyEl.appendChild(d);
});
}
}
function resetGame(){
day = 1; round = 'A'; score = 0; tokens = 3; currentIndex = findFirstIndexFor(1,'A'); history = [];
renderQuestion(); renderHistory();
}
function escapeHtml(str){
return String(str).replaceAll('&','&').replaceAll('<','<').replaceAll('>','>').replaceAll('"','"');
}
// Event listeners
toggleDayBtn.addEventListener('click', () => { toggleDay(); });
nextQBtn.addEventListener('click', () => { nextQuestion(); });
markCorrectBtn.addEventListener('click', () => { markCorrect(); });
markWrongBtn.addEventListener('click', () => { markWrong(); });
showAnsBtn.addEventListener('click', () => {
const ans = currentQuestion() ? currentQuestion().a : 'No answer.';
answerText.textContent = ans;
});
resetBtn.addEventListener('click', () => { if(confirm('Reset the game?')) resetGame(); });
tokMinus.addEventListener('click', () => { tokens = Math.max(0, tokens - 1); updateMeta(); });
tokPlus.addEventListener('click', () => { tokens = tokens + 1; updateMeta(); });
applyScoreBtn.addEventListener('click', () => { const val = Number(scoreInput.value); if(!Number.isNaN(val)) { score = val; updateMeta(); }});
document.getElementById('scoreInput').addEventListener('change', () => {
// keep input in sync with score
scoreInput.value = score;
});
// init
currentIndex = findFirstIndexFor(day, round);
renderQuestion();
renderHistory();
updateMeta();
})();
</script>
</body>
</html>Editor is loading...
Leave a Comment