Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Aviator Game Phases Visualization</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
@keyframes pulse-glow { | |
0% { opacity: 0.7; } | |
50% { opacity: 1; box-shadow: 0 0 15px #10B981; } | |
100% { opacity: 0.7; } | |
} | |
.glowing-line { | |
animation: pulse-glow 2s infinite; | |
} | |
.tooltip { | |
position: absolute; | |
background: rgba(0, 0, 0, 0.8); | |
color: white; | |
padding: 8px 12px; | |
border-radius: 6px; | |
font-size: 14px; | |
pointer-events: none; | |
z-index: 100; | |
transform: translate(-50%, -100%); | |
opacity: 0; | |
transition: opacity 0.3s; | |
min-width: 180px; | |
} | |
.tooltip:after { | |
content: ""; | |
position: absolute; | |
top: 100%; | |
left: 50%; | |
margin-left: -5px; | |
border-width: 5px; | |
border-style: solid; | |
border-color: rgba(0, 0, 0, 0.8) transparent transparent transparent; | |
} | |
.cashout-animation { | |
animation: cashout-pulse 1.5s ease-out; | |
} | |
@keyframes cashout-pulse { | |
0% { transform: scale(1); opacity: 1; } | |
50% { transform: scale(1.5); opacity: 0.8; } | |
100% { transform: scale(2); opacity: 0; } | |
} | |
.game-container { | |
transition: all 0.5s ease; | |
} | |
.highlight-game { | |
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.5); | |
transform: translateY(-5px); | |
} | |
.plane-marker { | |
position: absolute; | |
font-size: 24px; | |
transform: translate(-50%, -50%) rotate(0deg); | |
z-index: 10; | |
transition: left 0.1s linear, top 0.1s linear; | |
} | |
.win-message { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
background: rgba(16, 185, 129, 0.9); | |
color: white; | |
padding: 20px 30px; | |
border-radius: 10px; | |
font-size: 28px; | |
font-weight: bold; | |
text-align: center; | |
z-index: 100; | |
opacity: 0; | |
transition: opacity 0.5s; | |
box-shadow: 0 0 20px rgba(16, 185, 129, 0.7); | |
width: 80%; | |
max-width: 500px; | |
} | |
.lose-message { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
background: rgba(239, 68, 68, 0.9); | |
color: white; | |
padding: 15px 25px; | |
border-radius: 8px; | |
font-size: 24px; | |
font-weight: bold; | |
text-align: center; | |
z-index: 100; | |
opacity: 0; | |
transition: opacity 0.5s; | |
box-shadow: 0 0 15px rgba(239, 68, 68, 0.7); | |
width: 70%; | |
max-width: 400px; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-900 text-white min-h-screen"> | |
<div class="container mx-auto px-4 py-12"> | |
<!-- Header with meaning text --> | |
<div class="text-center mb-12"> | |
<h1 class="text-4xl font-bold mb-6 bg-gradient-to-r from-red-500 via-yellow-500 to-green-500 bg-clip-text text-transparent"> | |
Aviator Game Phases Analysis | |
</h1> | |
<div class="text-2xl font-semibold mb-4"> | |
<span class="text-red-400">3 losses in a row.</span> | |
<span class="mx-4">But on the 4th — </span> | |
<span class="text-green-400 font-bold">X94.</span> | |
</div> | |
<p class="text-xl text-gray-300 max-w-2xl mx-auto"> | |
Would you have waited? <span class="text-yellow-400 font-medium">We know when to wait.</span> | |
</p> | |
</div> | |
<!-- Main chart container --> | |
<div class="bg-gray-800 rounded-xl p-6 shadow-xl mb-8 relative"> | |
<div class="flex justify-between items-center mb-6"> | |
<h2 class="text-xl font-semibold">Game Phases Pattern</h2> | |
<button id="replayBtn" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded-lg flex items-center transition"> | |
<i class="fas fa-redo mr-2"></i> Replay Sequence | |
</button> | |
</div> | |
<div class="relative h-96"> | |
<canvas id="gameChart"></canvas> | |
<!-- Plane marker --> | |
<div id="planeMarker" class="plane-marker hidden"> | |
<i class="fas fa-plane text-blue-400"></i> | |
</div> | |
<!-- Cashout marker --> | |
<div id="cashoutMarker" class="absolute hidden flex-col items-center"> | |
<div class="bg-green-500 text-white px-3 py-1 rounded-full text-sm font-bold mb-1 flex items-center"> | |
<i class="fas fa-coins mr-1"></i> CASHOUT | |
</div> | |
<div class="w-3 h-3 bg-green-500 rounded-full"></div> | |
</div> | |
<!-- Win message --> | |
<div id="winMessage" class="win-message"> | |
WON $470<br>with 94x multiplier! | |
<div class="text-xl mt-2">🔥 Hot phase detected! 🔥</div> | |
</div> | |
<!-- Lose messages --> | |
<div id="loseMessage1" class="lose-message">LOST!</div> | |
<div id="loseMessage2" class="lose-message">LOST!</div> | |
<div id="loseMessage3" class="lose-message">LOST!</div> | |
<!-- Tooltip element --> | |
<div id="chartTooltip" class="tooltip"></div> | |
</div> | |
<!-- Game result indicators --> | |
<div class="grid grid-cols-4 gap-4 mt-6"> | |
<div id="game1" class="game-container bg-gray-700 p-3 rounded-lg"> | |
<div class="flex justify-between items-center mb-2"> | |
<span class="font-medium">Game 1</span> | |
<span class="text-red-400 font-bold">- $5</span> | |
</div> | |
<p class="text-sm text-gray-300">Bet $5 — Lost at 1.34x</p> | |
</div> | |
<div id="game2" class="game-container bg-gray-700 p-3 rounded-lg"> | |
<div class="flex justify-between items-center mb-2"> | |
<span class="font-medium">Game 2</span> | |
<span class="text-red-400 font-bold">- $5</span> | |
</div> | |
<p class="text-sm text-gray-300">Bet $5 — Lost at 1.12x</p> | |
</div> | |
<div id="game3" class="game-container bg-gray-700 p-3 rounded-lg"> | |
<div class="flex justify-between items-center mb-2"> | |
<span class="font-medium">Game 3</span> | |
<span class="text-red-400 font-bold">- $5</span> | |
</div> | |
<p class="text-sm text-gray-300">Bet $5 — Lost at 1.86x</p> | |
</div> | |
<div id="game4" class="game-container bg-gray-700 p-3 rounded-lg"> | |
<div class="flex justify-between items-center mb-2"> | |
<span class="font-medium">Game 4</span> | |
<span class="text-green-400 font-bold">+ $470</span> | |
</div> | |
<p class="text-sm text-green-300 font-medium">Phase: <span class="text-yellow-400">🔥 Hot. Here it is.</span></p> | |
</div> | |
</div> | |
</div> | |
<!-- Key takeaways --> | |
<div class="grid md:grid-cols-3 gap-6 mt-8"> | |
<div class="bg-gray-800 p-6 rounded-xl border-l-4 border-red-500"> | |
<div class="flex items-center mb-3"> | |
<div class="bg-red-500 p-2 rounded-full mr-3"> | |
<i class="fas fa-exclamation-triangle text-white"></i> | |
</div> | |
<h3 class="text-lg font-semibold">Bad Phases</h3> | |
</div> | |
<p class="text-gray-300">Games 1-3 show losing streaks where most players lose money by cashing out too late or not recognizing the pattern.</p> | |
</div> | |
<div class="bg-gray-800 p-6 rounded-xl border-l-4 border-yellow-500"> | |
<div class="flex items-center mb-3"> | |
<div class="bg-yellow-500 p-2 rounded-full mr-3"> | |
<i class="fas fa-lightbulb text-white"></i> | |
</div> | |
<h3 class="text-lg font-semibold">Recognizable Pattern</h3> | |
</div> | |
<p class="text-gray-300">The game follows a predictable algorithm - after several losses comes a big win phase that can be anticipated.</p> | |
</div> | |
<div class="bg-gray-800 p-6 rounded-xl border-l-4 border-green-500"> | |
<div class="flex items-center mb-3"> | |
<div class="bg-green-500 p-2 rounded-full mr-3"> | |
<i class="fas fa-chart-line text-white"></i> | |
</div> | |
<h3 class="text-lg font-semibold">Generosity Phase</h3> | |
</div> | |
<p class="text-gray-300">Game 4 demonstrates the "hot phase" where multipliers skyrocket - our system identifies these moments for optimal betting.</p> | |
</div> | |
</div> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// Chart configuration | |
const ctx = document.getElementById('gameChart').getContext('2d'); | |
// Game data | |
const games = [ | |
{ // Game 1 | |
label: 'Game 1 (Loss)', | |
data: [ | |
{x: 0, y: 1}, | |
{x: 2, y: 1.1}, | |
{x: 3, y: 1.2}, | |
{x: 3.4, y: 1.34}, | |
{x: 3.5, y: 1} | |
], | |
borderColor: 'rgba(239, 68, 68, 1)', | |
backgroundColor: 'rgba(239, 68, 68, 0.1)', | |
borderWidth: 2, | |
tension: 0.3, | |
pointRadius: 0, | |
pointHoverRadius: 6, | |
pointBackgroundColor: 'rgba(239, 68, 68, 1)', | |
segment: { | |
borderColor: ctx => ctx.p0.parsed.y > ctx.p1.parsed.y ? 'rgba(239, 68, 68, 0.5)' : undefined, | |
borderDash: ctx => ctx.p0.parsed.y > ctx.p1.parsed.y ? [6, 6] : undefined | |
} | |
}, | |
{ // Game 2 | |
label: 'Game 2 (Loss)', | |
data: [ | |
{x: 10, y: 1}, | |
{x: 11, y: 1.05}, | |
{x: 11.5, y: 1.1}, | |
{x: 11.8, y: 1.12}, | |
{x: 12, y: 1} | |
], | |
borderColor: 'rgba(239, 68, 68, 1)', | |
backgroundColor: 'rgba(239, 68, 68, 0.1)', | |
borderWidth: 2, | |
tension: 0.3, | |
pointRadius: 0, | |
pointHoverRadius: 6, | |
pointBackgroundColor: 'rgba(239, 68, 68, 1)', | |
segment: { | |
borderColor: ctx => ctx.p0.parsed.y > ctx.p1.parsed.y ? 'rgba(239, 68, 68, 0.5)' : undefined, | |
borderDash: ctx => ctx.p0.parsed.y > ctx.p1.parsed.y ? [6, 6] : undefined | |
} | |
}, | |
{ // Game 3 | |
label: 'Game 3 (Loss)', | |
data: [ | |
{x: 20, y: 1}, | |
{x: 21, y: 1.3}, | |
{x: 22, y: 1.5}, | |
{x: 22.5, y: 1.7}, | |
{x: 22.8, y: 1.86}, | |
{x: 23, y: 1} | |
], | |
borderColor: 'rgba(239, 68, 68, 1)', | |
backgroundColor: 'rgba(239, 68, 68, 0.1)', | |
borderWidth: 2, | |
tension: 0.3, | |
pointRadius: 0, | |
pointHoverRadius: 6, | |
pointBackgroundColor: 'rgba(239, 68, 68, 1)', | |
segment: { | |
borderColor: ctx => ctx.p0.parsed.y > ctx.p1.parsed.y ? 'rgba(239, 68, 68, 0.5)' : undefined, | |
borderDash: ctx => ctx.p0.parsed.y > ctx.p1.parsed.y ? [6, 6] : undefined | |
} | |
}, | |
{ // Game 4 (Win) | |
label: 'Game 4 (Win)', | |
data: [ | |
{x: 30, y: 1}, | |
{x: 31, y: 2}, | |
{x: 32, y: 5}, | |
{x: 33, y: 10}, | |
{x: 34, y: 25}, | |
{x: 35, y: 50}, | |
{x: 36, y: 75}, | |
{x: 36.5, y: 85}, | |
{x: 37, y: 90}, | |
{x: 37.5, y: 93}, | |
{x: 37.8, y: 94.2}, | |
{x: 38, y: 1} | |
], | |
borderColor: 'rgba(16, 185, 129, 1)', | |
backgroundColor: 'rgba(16, 185, 129, 0.1)', | |
borderWidth: 3, | |
tension: 0.3, | |
pointRadius: 0, | |
pointHoverRadius: 6, | |
pointBackgroundColor: 'rgba(16, 185, 129, 1)', | |
segment: { | |
borderColor: ctx => ctx.p0.parsed.y > ctx.p1.parsed.y ? 'rgba(239, 68, 68, 0.5)' : undefined, | |
borderDash: ctx => ctx.p0.parsed.y > ctx.p1.parsed.y ? [6, 6] : undefined | |
} | |
} | |
]; | |
// Create chart | |
const chart = new Chart(ctx, { | |
type: 'line', | |
data: { | |
datasets: games | |
}, | |
options: { | |
responsive: true, | |
maintainAspectRatio: false, | |
animation: { | |
duration: 0 // We'll handle animations manually | |
}, | |
scales: { | |
x: { | |
type: 'linear', | |
position: 'bottom', | |
min: 0, | |
max: 40, | |
ticks: { | |
callback: function(value) { | |
if (value % 10 === 0) { | |
return `${value % 10}s`; | |
} | |
return ''; | |
}, | |
color: 'rgba(255, 255, 255, 0.7)' | |
}, | |
grid: { | |
color: 'rgba(255, 255, 255, 0.1)', | |
drawTicks: false | |
}, | |
title: { | |
display: true, | |
text: 'Time (seconds)', | |
color: 'rgba(255, 255, 255, 0.8)' | |
} | |
}, | |
y: { | |
type: 'logarithmic', | |
min: 1, | |
max: 100, | |
ticks: { | |
callback: function(value) { | |
if ([1, 2, 5, 10, 25, 50, 100].includes(value)) { | |
return `${value}x`; | |
} | |
}, | |
color: 'rgba(255, 255, 255, 0.7)' | |
}, | |
grid: { | |
color: function(context) { | |
return [1, 2, 5, 10, 25, 50, 100].includes(context.tick.value) ? | |
'rgba(255, 255, 255, 0.2)' : | |
'rgba(255, 255, 255, 0.05)'; | |
}, | |
lineWidth: function(context) { | |
return [1, 10, 100].includes(context.tick.value) ? 2 : 1; | |
}, | |
drawTicks: false | |
}, | |
title: { | |
display: true, | |
text: 'Multiplier', | |
color: 'rgba(255, 255, 255, 0.8)' | |
} | |
} | |
}, | |
plugins: { | |
legend: { | |
display: false | |
}, | |
tooltip: { | |
enabled: false, | |
external: function(context) { | |
const tooltip = document.getElementById('chartTooltip'); | |
if (context.tooltip.opacity === 0) { | |
tooltip.style.opacity = 0; | |
return; | |
} | |
const dataPoint = context.tooltip.dataPoints[0]; | |
const dataset = games[dataPoint.datasetIndex]; | |
const point = dataset.data[dataPoint.dataIndex]; | |
let outcome = 'In Progress'; | |
let color = 'text-blue-400'; | |
if (dataset.label.includes('Loss')) { | |
outcome = 'Loss'; | |
color = 'text-red-400'; | |
} else if (point.x >= 37.8 && point.y >= 94) { | |
outcome = 'Win'; | |
color = 'text-green-400'; | |
} | |
tooltip.innerHTML = ` | |
<div class="mb-1"><strong>Time:</strong> ${point.x.toFixed(1)}s</div> | |
<div class="mb-1"><strong>Multiplier:</strong> ${point.y.toFixed(2)}x</div> | |
<div class="${color} font-semibold"><strong>Outcome:</strong> ${outcome}</div> | |
`; | |
const chartRect = context.chart.canvas.getBoundingClientRect(); | |
tooltip.style.left = chartRect.left + context.tooltip.caretX + 'px'; | |
tooltip.style.top = chartRect.top + context.tooltip.caretY + 'px'; | |
tooltip.style.opacity = 1; | |
} | |
} | |
}, | |
interaction: { | |
intersect: false, | |
mode: 'index' | |
} | |
} | |
}); | |
// Animation variables | |
let currentGame = 0; | |
let animationInterval; | |
let isAnimating = false; | |
// DOM elements | |
const replayBtn = document.getElementById('replayBtn'); | |
const planeMarker = document.getElementById('planeMarker'); | |
const cashoutMarker = document.getElementById('cashoutMarker'); | |
const winMessage = document.getElementById('winMessage'); | |
const loseMessage1 = document.getElementById('loseMessage1'); | |
const loseMessage2 = document.getElementById('loseMessage2'); | |
const loseMessage3 = document.getElementById('loseMessage3'); | |
const gameContainers = [ | |
document.getElementById('game1'), | |
document.getElementById('game2'), | |
document.getElementById('game3'), | |
document.getElementById('game4') | |
]; | |
// Highlight current game | |
function highlightGame(index) { | |
gameContainers.forEach((container, i) => { | |
if (i === index) { | |
container.classList.add('highlight-game'); | |
} else { | |
container.classList.remove('highlight-game'); | |
} | |
}); | |
} | |
// Show lose message | |
function showLoseMessage(gameNumber) { | |
const message = document.getElementById(`loseMessage${gameNumber}`); | |
message.style.opacity = 1; | |
setTimeout(() => { | |
message.style.opacity = 0; | |
}, 1500); | |
} | |
// Show win message | |
function showWinMessage() { | |
winMessage.style.opacity = 1; | |
setTimeout(() => { | |
winMessage.style.opacity = 0; | |
}, 3000); | |
} | |
// Animate chart | |
function animateChart() { | |
if (isAnimating) return; | |
isAnimating = true; | |
currentGame = 0; | |
// Reset chart | |
chart.options.scales.x.min = 0; | |
chart.options.scales.x.max = 10; | |
chart.update(); | |
// Hide markers and messages | |
planeMarker.classList.add('hidden'); | |
cashoutMarker.classList.add('hidden'); | |
winMessage.style.opacity = 0; | |
loseMessage1.style.opacity = 0; | |
loseMessage2.style.opacity = 0; | |
loseMessage3.style.opacity = 0; | |
// Start animation sequence | |
playNextGame(); | |
} | |
// Play next game in sequence | |
function playNextGame() { | |
if (currentGame >= games.length) { | |
isAnimating = false; | |
return; | |
} | |
highlightGame(currentGame); | |
const game = games[currentGame]; | |
const isWinGame = game.label.includes('Win'); | |
let currentPoint = 0; | |
let crashPointReached = false; | |
// Adjust x-axis range based on game | |
if (currentGame === 0) { | |
chart.options.scales.x.min = 0; | |
chart.options.scales.x.max = 10; | |
} else if (currentGame === 1) { | |
chart.options.scales.x.min = 10; | |
chart.options.scales.x.max = 20; | |
} else if (currentGame === 2) { | |
chart.options.scales.x.min = 20; | |
chart.options.scales.x.max = 30; | |
} else if (currentGame === 3) { | |
chart.options.scales.x.min = 30; | |
chart.options.scales.x.max = 40; | |
} | |
chart.update(); | |
// Show plane marker | |
planeMarker.classList.remove('hidden'); | |
// Animate points one by one | |
const gameInterval = setInterval(() => { | |
if (currentPoint >= game.data.length) { | |
clearInterval(gameInterval); | |
// Hide plane at the end | |
planeMarker.classList.add('hidden'); | |
// If win game, show cashout marker and win message | |
if (isWinGame) { | |
const lastPoint = game.data[game.data.length - 2]; // Second to last point (before crash) | |
const canvasPos = chart.scales.x.getPixelForValue(lastPoint.x); | |
const canvasYPos = chart.scales.y.getPixelForValue(lastPoint.y); | |
cashoutMarker.style.left = `${canvasPos}px`; | |
cashoutMarker.style.top = `${canvasYPos}px`; | |
cashoutMarker.classList.remove('hidden'); | |
cashoutMarker.classList.add('cashout-animation'); | |
setTimeout(() => { | |
cashoutMarker.classList.remove('cashout-animation'); | |
}, 1500); | |
showWinMessage(); | |
// Pause before next game (but this is the last game) | |
setTimeout(() => { | |
currentGame++; | |
isAnimating = false; | |
}, 3000); | |
} else { | |
// For lose games, show lose message | |
showLoseMessage(currentGame + 1); | |
// Pause before next game | |
setTimeout(() => { | |
currentGame++; | |
playNextGame(); | |
}, 2000); // 2 second pause after each lose game | |
} | |
return; | |
} | |
// Update plane position | |
const point = game.data[currentPoint]; | |
const canvasPos = chart.scales.x.getPixelForValue(point.x); | |
const canvasYPos = chart.scales.y.getPixelForValue(point.y); | |
planeMarker.style.left = `${canvasPos}px`; | |
planeMarker.style.top = `${canvasYPos}px`; | |
// Rotate plane slightly based on direction | |
if (currentPoint > 0) { | |
const prevPoint = game.data[currentPoint - 1]; | |
const angle = Math.atan2( | |
chart.scales.y.getPixelForValue(point.y) - chart.scales.y.getPixelForValue(prevPoint.y), | |
chart.scales.x.getPixelForValue(point.x) - chart.scales.x.getPixelForValue(prevPoint.x) | |
) * 180 / Math.PI; | |
planeMarker.style.transform = `translate(-50%, -50%) rotate(${angle}deg)`; | |
} | |
// Check if we've reached the crash point | |
if (!crashPointReached && currentPoint > 0 && | |
game.data[currentPoint].y < game.data[currentPoint - 1].y) { | |
crashPointReached = true; | |
} | |
currentPoint++; | |
}, isWinGame ? 100 : 200); // Faster animation for win game | |
} | |
// Initial animation after a delay | |
setTimeout(animateChart, 1000); | |
// Replay button | |
replayBtn.addEventListener('click', animateChart); | |
// Make the winning line glow | |
setTimeout(() => { | |
const winDataset = chart.data.datasets[3]; | |
winDataset.borderWidth = 4; | |
winDataset.borderColor = 'rgba(16, 185, 129, 0.8)'; | |
chart.update(); | |
// Add glowing effect to the line | |
const meta = chart.getDatasetMeta(3); | |
if (meta) { | |
const ctx = meta.dataset._ctx; | |
ctx.shadowColor = 'rgba(16, 185, 129, 0.6)'; | |
ctx.shadowBlur = 15; | |
ctx.shadowOffsetX = 0; | |
ctx.shadowOffsetY = 0; | |
chart.draw(); | |
} | |
}, 500); | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=timoon811/aviatorpreland" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |