initial commit

This commit is contained in:
Weetile 2025-03-06 21:53:12 +00:00
commit a09ee6bf4d
2 changed files with 628 additions and 0 deletions

2
Dockerfile Normal file
View File

@ -0,0 +1,2 @@
FROM httpd:alpine
COPY ./ /usr/local/apache2/htdocs/

626
index.html Normal file
View File

@ -0,0 +1,626 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Poker Board</title>
<style>
:root {
--background: #121212;
--card: #1e1e1e;
--primary: #d32f2f;
--text: #ffffff;
--accent: #00c853;
}
body {
font-family: 'Arial', sans-serif;
background-color: var(--background);
color: var(--text);
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23222222' fill-opacity='0.4'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.header {
width: 100%;
text-align: center;
background-color: var(--card);
padding: 20px 0;
border-bottom: 4px solid var(--primary);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
}
.logo {
font-size: 2.5rem;
font-weight: bold;
margin: 0;
color: var(--primary);
letter-spacing: 1px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
.content {
display: flex;
flex-direction: column;
align-items: center;
width: 90%;
max-width: 1200px;
margin: 30px 0;
}
.main-sections {
display: flex;
width: 100%;
gap: 30px;
margin-bottom: 30px;
align-items: center; /* Vertically center the sections */
}
.chip-values {
background-color: var(--card);
border-radius: 10px;
padding: 30px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
border: 1px solid #333;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center; /* Center content vertically */
}
.section-title {
text-align: center;
font-size: 1.8rem;
margin-top: 0;
margin-bottom: 25px;
color: var(--accent);
border-bottom: 2px solid var(--accent);
padding-bottom: 10px;
}
.chips {
display: flex;
justify-content: center;
flex-wrap: nowrap;
gap: 15px;
max-width: 100%;
overflow-x: auto; /* Allow horizontal scrolling if needed */
}
.chip {
text-align: center;
font-size: 1.2rem;
padding: 10px;
border-radius: 50%;
width: 75px; /* Slightly smaller to ensure fit */
height: 75px;
min-width: 75px; /* Prevent shrinking */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 4px solid #444;
}
.chip-color {
font-weight: bold;
font-size: 1.4rem;
}
.chip-value {
font-size: 2rem;
font-weight: bold;
}
.white-chip {
background-color: #f5f5f5;
color: #000;
}
.blue-chip {
background-color: #1976d2;
color: white;
}
.red-chip {
background-color: #d32f2f;
color: white;
}
.green-chip {
background-color: #388e3c;
color: white;
}
.black-chip {
background-color: #212121;
color: white;
border-color: #555;
}
.timer-section {
background-color: var(--card);
border-radius: 10px;
padding: 30px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
border: 1px solid #333;
flex: 1;
}
.timer-display {
font-size: 5rem;
font-weight: bold;
text-align: center;
margin: 20px 0;
font-family: 'Courier New', monospace;
color: var(--accent);
text-shadow: 0 0 10px rgba(0, 200, 83, 0.5);
}
.blind-levels {
font-size: 2.5rem;
text-align: center;
margin: 20px 0;
font-weight: bold;
}
.current-level {
color: var(--primary);
font-size: 3.2rem; /* Increased size as requested */
}
.next-level {
color: #888;
font-size: 1.8rem;
}
.timer-controls {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 30px;
flex-wrap: wrap;
}
button {
background-color: var(--primary);
color: white;
border: none;
border-radius: 5px;
padding: 12px 25px;
font-size: 1.2rem;
cursor: pointer;
transition: all 0.3s;
font-weight: bold;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
button:hover {
background-color: #b71c1c;
transform: translateY(-2px);
}
button:active {
transform: translateY(1px);
}
.reset {
background-color: #333;
}
.reset:hover {
background-color: #444;
}
#remove-time {
background-color: #d81b60;
}
#remove-time:hover {
background-color: #ad1457;
}
footer {
margin-top: auto;
width: 100%;
background-color: var(--card);
padding: 15px 0;
text-align: center;
font-size: 0.9rem;
color: #888;
border-top: 2px solid var(--primary);
}
/* Card suit animation for background elements */
.card-suits {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: -1;
overflow: hidden;
}
.suit {
position: absolute;
opacity: 0.04;
font-size: 100px;
animation: float 15s infinite linear;
}
@keyframes float {
0% {
transform: translateY(100vh) rotate(0deg);
}
100% {
transform: translateY(-100px) rotate(360deg);
}
}
/* Announcement section styles */
.announcement-section {
background-color: var(--card);
border-radius: 10px;
padding: 30px;
margin-top: 30px;
margin-bottom: 30px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
width: 100%;
border: 1px solid #333;
}
.announcement-form {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.announcement-input {
flex: 1;
padding: 12px;
font-size: 1.1rem;
border-radius: 5px;
border: 1px solid #444;
background-color: #333;
color: white;
}
.announcement-list {
display: flex;
flex-direction: column;
gap: 15px;
}
.announcement-item {
background-color: rgba(255, 255, 255, 0.1);
padding: 15px;
border-radius: 5px;
font-size: 1.8rem;
font-weight: bold;
display: flex;
justify-content: space-between;
align-items: center;
border-left: 5px solid var(--primary);
}
.delete-announcement {
background-color: rgba(0, 0, 0, 0.3);
color: white;
border: none;
border-radius: 50%;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 1.2rem;
transition: all 0.2s;
}
.delete-announcement:hover {
background-color: var(--primary);
transform: scale(1.1);
}
#add-announcement {
background-color: var(--accent);
}
#add-announcement:hover {
background-color: #00a844;
}
</style>
</head>
<body>
<!-- Background animation -->
<div class="card-suits" id="card-suits"></div>
<div class="header">
<h1 class="logo">Poker Board</h1>
</div>
<div class="content">
<div class="main-sections">
<div class="chip-values">
<h2 class="section-title">CHIP VALUES</h2>
<div class="chips">
<div class="chip white-chip">
<div class="chip-color">White</div>
<div class="chip-value">5</div>
</div>
<div class="chip blue-chip">
<div class="chip-color">Blue</div>
<div class="chip-value">10</div>
</div>
<div class="chip red-chip">
<div class="chip-color">Red</div>
<div class="chip-value">25</div>
</div>
<div class="chip green-chip">
<div class="chip-color">Green</div>
<div class="chip-value">100</div>
</div>
<div class="chip black-chip">
<div class="chip-color">Black</div>
<div class="chip-value">200</div>
</div>
</div>
</div>
<div class="timer-section">
<h2 class="section-title">BLINDS TIMER</h2>
<div class="blind-levels">
<div class="current-level" id="current-blinds">10 / 20</div>
<div class="next-level">Next: <span id="next-blinds">20 / 40</span></div>
</div>
<div class="timer-display" id="timer">30:00</div>
<div class="timer-controls">
<button id="start-pause">START</button>
<button id="reset" class="reset">RESET</button>
<button id="add-time">+5 MIN</button>
<button id="remove-time">-5 MIN</button>
</div>
</div>
</div>
<div class="announcement-section">
<h2 class="section-title">ANNOUNCEMENTS</h2>
<div class="announcement-form">
<input type="text" id="announcement-input" class="announcement-input" placeholder="Enter announcement...">
<button id="add-announcement">ADD</button>
</div>
<div class="announcement-list" id="announcement-list">
<!-- Announcements will be added here -->
</div>
</div>
</div>
<footer>
<a href="https://git.weetile.uk" style="color: inherit;">Otto Helen-Goldring © 2025</a>
</footer>
<script>
// Timer variables
let timerDuration = 30 * 60; // 30 minutes in seconds
let timeRemaining = timerDuration;
let timerInterval = null;
let isTimerRunning = false;
// Blind levels
let currentBlinds = { small: 10, big: 20 };
let blindLevels = [];
// Generate blind levels
function generateBlindLevels() {
blindLevels = [];
let small = 10;
let big = 20;
for (let i = 0; i < 20; i++) {
blindLevels.push({ small, big });
small *= 2;
big *= 2;
}
}
// Format time as MM:SS
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
// Update timer display
function updateTimerDisplay() {
document.getElementById('timer').textContent = formatTime(timeRemaining);
}
// Update blinds display
function updateBlindsDisplay() {
document.getElementById('current-blinds').textContent = `${currentBlinds.small} / ${currentBlinds.big}`;
// Find current level index
const currentLevelIndex = blindLevels.findIndex(level =>
level.small === currentBlinds.small && level.big === currentBlinds.big);
// Calculate next level
if (currentLevelIndex < blindLevels.length - 1) {
const nextLevel = blindLevels[currentLevelIndex + 1];
document.getElementById('next-blinds').textContent = `${nextLevel.small} / ${nextLevel.big}`;
} else {
document.getElementById('next-blinds').textContent = 'Max Level';
}
}
// Start or pause the timer
function toggleTimer() {
const button = document.getElementById('start-pause');
if (isTimerRunning) {
// Pause the timer
clearInterval(timerInterval);
button.textContent = 'RESUME';
isTimerRunning = false;
} else {
// Start the timer
timerInterval = setInterval(function() {
if (timeRemaining > 0) {
timeRemaining--;
updateTimerDisplay();
} else {
// Time's up, move to next blind level
incrementBlinds();
resetTimer();
}
}, 1000);
button.textContent = 'PAUSE';
isTimerRunning = true;
}
}
// Reset the timer
function resetTimer() {
clearInterval(timerInterval);
timeRemaining = timerDuration;
updateTimerDisplay();
document.getElementById('start-pause').textContent = 'START';
isTimerRunning = false;
}
// Increment blinds to next level
function incrementBlinds() {
const currentLevelIndex = blindLevels.findIndex(level =>
level.small === currentBlinds.small && level.big === currentBlinds.big);
if (currentLevelIndex < blindLevels.length - 1) {
currentBlinds = blindLevels[currentLevelIndex + 1];
updateBlindsDisplay();
// Add visual feedback for blind increase
const blindsElement = document.getElementById('current-blinds');
blindsElement.style.transition = 'transform 0.5s, color 0.5s';
blindsElement.style.transform = 'scale(1.2)';
blindsElement.style.color = '#ff5252';
setTimeout(() => {
blindsElement.style.transform = 'scale(1)';
blindsElement.style.color = '';
}, 1500);
}
}
// Add 5 minutes to the timer
function addTime() {
timeRemaining += 5 * 60; // Add 5 minutes
updateTimerDisplay();
}
// Remove 5 minutes from the timer
function removeTime() {
if (timeRemaining > 5 * 60) {
timeRemaining -= 5 * 60; // Remove 5 minutes
} else {
timeRemaining = 0;
}
updateTimerDisplay();
}
// Create floating suit symbols for background
function createSuitSymbols() {
const suits = ['♠', '♥', '♦', '♣'];
const container = document.getElementById('card-suits');
for (let i = 0; i < 20; i++) {
const suit = document.createElement('div');
suit.className = 'suit';
suit.textContent = suits[Math.floor(Math.random() * suits.length)];
// Random position and animation properties
suit.style.left = `${Math.random() * 100}%`;
suit.style.animationDuration = `${15 + Math.random() * 20}s`;
suit.style.animationDelay = `${Math.random() * 15}s`;
container.appendChild(suit);
}
}
// Add announcement to the list
function addAnnouncement() {
const input = document.getElementById('announcement-input');
const text = input.value.trim();
if (text) {
const announcementList = document.getElementById('announcement-list');
// Create announcement item
const item = document.createElement('div');
item.className = 'announcement-item';
// Add announcement text
const span = document.createElement('span');
span.textContent = text;
item.appendChild(span);
// Add delete button
const deleteBtn = document.createElement('button');
deleteBtn.className = 'delete-announcement';
deleteBtn.textContent = '×';
deleteBtn.addEventListener('click', function() {
item.style.opacity = '0';
item.style.transition = 'opacity 0.3s';
setTimeout(() => {
announcementList.removeChild(item);
}, 300);
});
item.appendChild(deleteBtn);
// Add to list with animation
item.style.opacity = '0';
announcementList.appendChild(item);
setTimeout(() => {
item.style.opacity = '1';
item.style.transition = 'opacity 0.3s';
}, 10);
// Clear input
input.value = '';
}
}
// Initialize the app
function init() {
generateBlindLevels();
updateTimerDisplay();
updateBlindsDisplay();
createSuitSymbols();
// Timer control event listeners
document.getElementById('start-pause').addEventListener('click', toggleTimer);
document.getElementById('reset').addEventListener('click', resetTimer);
document.getElementById('add-time').addEventListener('click', addTime);
document.getElementById('remove-time').addEventListener('click', removeTime);
// Announcement event listeners
document.getElementById('add-announcement').addEventListener('click', addAnnouncement);
// Allow Enter key to submit announcement
document.getElementById('announcement-input').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
addAnnouncement();
}
});
}
// Start the app
window.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>