Initial Commit
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
*.egg
|
||||||
|
*.egg-info/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
.eggs/
|
||||||
|
|
||||||
|
# Virtual environment
|
||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
env/
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
|
||||||
|
# pytest
|
||||||
|
.pytest_cache/
|
||||||
|
.cache/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
*.whl
|
||||||
|
*.tar.gz
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import random
|
||||||
|
from fastapi import FastAPI, Request
|
||||||
|
from fastapi.responses import HTMLResponse
|
||||||
|
from fastapi.templating import Jinja2Templates
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
app = FastAPI(title="MileageDraw")
|
||||||
|
|
||||||
|
templates = Jinja2Templates(directory="templates")
|
||||||
|
|
||||||
|
# Prize Probabilities:
|
||||||
|
# 1st Prize: 20%
|
||||||
|
# 2nd Prize: 30%
|
||||||
|
# 3rd Prize: 50%
|
||||||
|
PRIZES = [
|
||||||
|
{"rank": 1, "name": "1st Prize", "miles": 10000, "probability": 0.10},
|
||||||
|
{"rank": 2, "name": "2nd Prize", "miles": 5000, "probability": 0.30},
|
||||||
|
{"rank": 3, "name": "3rd Prize", "miles": 2000, "probability": 0.60},
|
||||||
|
]
|
||||||
|
|
||||||
|
class DrawResult(BaseModel):
|
||||||
|
rank: int
|
||||||
|
name: str
|
||||||
|
miles: int
|
||||||
|
|
||||||
|
@app.get("/", response_class=HTMLResponse)
|
||||||
|
async def index(request: Request):
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
request=request, name="index.html"
|
||||||
|
)
|
||||||
|
|
||||||
|
@app.post("/api/draw", response_model=DrawResult)
|
||||||
|
async def draw_prize():
|
||||||
|
rand_val = random.random()
|
||||||
|
cumulative = 0.0
|
||||||
|
for prize in PRIZES:
|
||||||
|
cumulative += prize["probability"]
|
||||||
|
if rand_val <= cumulative:
|
||||||
|
return DrawResult(
|
||||||
|
rank=prize["rank"],
|
||||||
|
name=prize["name"],
|
||||||
|
miles=prize["miles"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fallback in case of floating point precision issues
|
||||||
|
last = PRIZES[-1]
|
||||||
|
return DrawResult(
|
||||||
|
rank=last["rank"],
|
||||||
|
name=last["name"],
|
||||||
|
miles=last["miles"]
|
||||||
|
)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import uvicorn
|
||||||
|
uvicorn.run("main:app", host="0.0.0.0", port=10000, reload=True)
|
||||||
|
|
||||||
|
# import random
|
||||||
|
# def sum(L, n):
|
||||||
|
# if n == 0:
|
||||||
|
# return L[0]
|
||||||
|
# else:
|
||||||
|
# return L[n] + sum(L, n-1)
|
||||||
|
|
||||||
|
# L = [random.randint(1, 100) for _ in range(10)]
|
||||||
|
# print(L)
|
||||||
|
|
||||||
|
# s = sum(L, len(L)-1)
|
||||||
|
# print(s)
|
||||||
|
|
||||||
@@ -0,0 +1,305 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="dark" lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
|
<title>MileageDraw - Win Big Today</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Spline+Sans:wght@300;400;500;600;700&display=swap" rel="stylesheet"/>
|
||||||
|
<script id="tailwind-config">
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: "class",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
"primary": "#2b4bee",
|
||||||
|
"accent": "#fbbf24",
|
||||||
|
"background-light": "#f6f6f8",
|
||||||
|
"background-dark": "#101322",
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
"display": ["Spline Sans", "sans-serif"]
|
||||||
|
},
|
||||||
|
borderRadius: {"DEFAULT": "0.25rem", "lg": "0.5rem", "xl": "0.75rem", "full": "9999px"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-background-light dark:bg-background-dark font-display text-slate-900 dark:text-slate-100 min-h-screen">
|
||||||
|
<div class="relative flex h-auto min-h-screen w-full flex-col bg-background-light dark:bg-background-dark overflow-x-hidden">
|
||||||
|
<div class="layout-container flex h-full grow flex-col">
|
||||||
|
<!-- Navigation Bar -->
|
||||||
|
<header class="flex items-center justify-between whitespace-nowrap border-b border-solid border-slate-200 dark:border-slate-800 px-6 lg:px-20 py-4 bg-background-light dark:bg-background-dark sticky top-0 z-50">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="text-primary size-8">
|
||||||
|
<span class="material-symbols-outlined text-4xl">redeem</span>
|
||||||
|
</div>
|
||||||
|
<h2 class="text-slate-900 dark:text-white text-xl font-bold leading-tight tracking-tight">MileageDraw</h2>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-1 justify-end items-center gap-6 lg:gap-10">
|
||||||
|
<nav class="hidden md:flex items-center gap-8">
|
||||||
|
<a class="text-slate-600 dark:text-slate-300 hover:text-primary dark:hover:text-primary text-sm font-semibold transition-colors" href="#">Home</a>
|
||||||
|
<a class="text-slate-600 dark:text-slate-300 hover:text-primary dark:hover:text-primary text-sm font-semibold transition-colors" href="#">My Prizes</a>
|
||||||
|
<a class="text-slate-600 dark:text-slate-300 hover:text-primary dark:hover:text-primary text-sm font-semibold transition-colors" href="#">How to Play</a>
|
||||||
|
</nav>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<button class="flex min-w-[120px] cursor-pointer items-center justify-center rounded-xl h-10 px-5 bg-primary/10 border border-primary/20 text-primary text-sm font-bold">
|
||||||
|
<span class="material-symbols-outlined text-sm mr-2">account_balance_wallet</span>
|
||||||
|
<span class="truncate" id="user-miles">15,400 Miles</span>
|
||||||
|
</button>
|
||||||
|
<div class="bg-center bg-no-repeat aspect-square bg-cover rounded-full size-10 border-2 border-primary/30" data-alt="User profile avatar circle" style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuASf-yBhfIyds7eDugHWDN-bVo-aoZM14xRSjRn1GNH4vvCCYuu6gLziV5Evf5W0hqHxLrhmsM7tMWPhL-PjDqctgWRBCEnW3zELC5v2BZrvEhgo7NB55Oo3YJ0-2C3fZmMgCxSC5SuwkcGmCvlEJiijE0RYtDZ7XenI3RD5Lt1VaEmPQ82FSB26oCxEJJ5I-hy02TTYa_npKImAXIOfm-x5Mh8evuGz0MoqoPTOSTuU3LxrHouNtN65FJ4KP4YUzBeSvC1b60St8_D");'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main class="flex-1 flex flex-col items-center px-4 lg:px-20 py-10 max-w-7xl mx-auto w-full">
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8 w-full items-center">
|
||||||
|
<!-- Left Side: Prize Board -->
|
||||||
|
<div class="lg:col-span-3 flex flex-col gap-4 order-2 lg:order-1">
|
||||||
|
<div class="bg-slate-50 dark:bg-slate-900/50 p-6 rounded-2xl border border-slate-200 dark:border-slate-800 backdrop-blur-sm">
|
||||||
|
<h3 class="text-lg font-bold mb-6 flex items-center gap-2">
|
||||||
|
<span class="material-symbols-outlined text-accent">military_tech</span>
|
||||||
|
Prize Pool
|
||||||
|
</h3>
|
||||||
|
<div class="space-y-6">
|
||||||
|
<div class="relative pl-4 border-l-4 border-accent">
|
||||||
|
<p class="text-xs uppercase tracking-wider text-slate-500 dark:text-slate-400 font-bold">1st Prize</p>
|
||||||
|
<p class="text-2xl font-black text-slate-900 dark:text-white">10,000 <span class="text-sm font-normal text-slate-500">Miles</span></p>
|
||||||
|
</div>
|
||||||
|
<div class="relative pl-4 border-l-4 border-slate-400">
|
||||||
|
<p class="text-xs uppercase tracking-wider text-slate-500 dark:text-slate-400 font-bold">2nd Prize</p>
|
||||||
|
<p class="text-2xl font-black text-slate-900 dark:text-white">5,000 <span class="text-sm font-normal text-slate-500">Miles</span></p>
|
||||||
|
</div>
|
||||||
|
<div class="relative pl-4 border-l-4 border-orange-400">
|
||||||
|
<p class="text-xs uppercase tracking-wider text-slate-500 dark:text-slate-400 font-bold">3rd Prize</p>
|
||||||
|
<p class="text-2xl font-black text-slate-900 dark:text-white">2,000 <span class="text-sm font-normal text-slate-500">Miles</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-primary/5 p-6 rounded-2xl border border-primary/20">
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400 leading-relaxed italic">
|
||||||
|
"Thousands of users have already claimed their rewards this month. Will you be next?"
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Center: Mystery Box -->
|
||||||
|
<div class="lg:col-span-6 flex flex-col items-center justify-center gap-8 order-1 lg:order-2">
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="text-4xl lg:text-5xl font-black text-slate-900 dark:text-white mb-2 tracking-tight">Try Your Luck!</h1>
|
||||||
|
<p class="text-slate-600 dark:text-slate-400 text-lg">Open the Mystery Box to win huge rewards</p>
|
||||||
|
</div>
|
||||||
|
<div class="relative group w-full max-w-md aspect-square flex items-center justify-center">
|
||||||
|
<!-- Background Glow Effect -->
|
||||||
|
<div class="absolute inset-0 bg-primary/20 blur-[100px] rounded-full scale-75 group-hover:bg-primary/30 transition-all duration-500" id="box-glow"></div>
|
||||||
|
<!-- Mystery Box Container -->
|
||||||
|
<div class="relative w-full h-full bg-gradient-to-br from-slate-800 to-slate-950 rounded-3xl border-4 border-accent/30 shadow-2xl flex flex-col items-center justify-center overflow-hidden transition-all duration-300" id="mystery-box-container">
|
||||||
|
<!-- Box Illustration -->
|
||||||
|
<div class="flex flex-col items-center transition-all duration-500" id="mystery-box-content">
|
||||||
|
<span class="material-symbols-outlined text-[160px] text-accent drop-shadow-[0_0_20px_rgba(251,191,36,0.5)]">featured_seasonal_and_gifts</span>
|
||||||
|
<div class="mt-4 flex gap-2">
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent animate-pulse"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent/50 animate-pulse delay-75"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent/20 animate-pulse delay-150"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Sparkle elements -->
|
||||||
|
<span class="material-symbols-outlined absolute top-10 left-10 text-accent/40 text-2xl" id="sparkle-1">auto_awesome</span>
|
||||||
|
<span class="material-symbols-outlined absolute bottom-12 right-12 text-accent/40 text-4xl" id="sparkle-2">auto_awesome</span>
|
||||||
|
<span class="material-symbols-outlined absolute top-20 right-16 text-accent/40 text-xl" id="sparkle-3">auto_awesome</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center gap-4 w-full">
|
||||||
|
<button id="draw-btn" class="w-full max-w-xs flex cursor-pointer items-center justify-center rounded-2xl h-16 px-8 bg-primary hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed text-white text-xl font-black shadow-lg shadow-primary/40 transition-all active:scale-95 group">
|
||||||
|
<span class="mr-3" id="draw-btn-text">DRAW NOW</span>
|
||||||
|
<span class="material-symbols-outlined group-hover:translate-x-1 transition-transform" id="draw-btn-icon">arrow_forward</span>
|
||||||
|
</button>
|
||||||
|
<p class="text-xs text-slate-500 font-medium">Cost: 500 Miles per draw</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Right Side: Recent Winners -->
|
||||||
|
<div class="lg:col-span-3 flex flex-col gap-4 order-3">
|
||||||
|
<div class="bg-slate-50 dark:bg-slate-900/50 p-6 rounded-2xl border border-slate-200 dark:border-slate-800">
|
||||||
|
<h3 class="text-sm font-bold text-slate-500 uppercase tracking-widest mb-4">Live Winners</h3>
|
||||||
|
<div class="space-y-4" id="recent-winners-list">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-primary/20 flex items-center justify-center overflow-hidden">
|
||||||
|
<img alt="" class="w-full h-full object-cover" src="https://lh3.googleusercontent.com/aida-public/AB6AXuCNyWQdRGCg_-tNwAu4-0oRfpGbiWSPp5prILJ1oalpRniDZ1DQL7yiiiDxVsiNuFMgCiKBVvFQRXrjlinRU-iZI_YM0XcDO2BuaK6YVIUwvn7DWhqUMcYYSA9EDn9vknhh9Sii2sb8KQkpoNsJdu25N8vJIcRuFAAioW3NFk-UPNLBfIPsRe1LxmgaxR6s_EIO6RfaV49lqaDiNOODXxKWtL-kl6oczKoBh7P0-DRwgdVJ2hjHlY3Dt33RCg91dSaBBPffcqIO8Qky"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm font-bold">Alice W.</p>
|
||||||
|
<p class="text-xs text-primary font-bold">+2,000 Miles</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-primary/20 flex items-center justify-center overflow-hidden">
|
||||||
|
<img alt="" class="w-full h-full object-cover" src="https://lh3.googleusercontent.com/aida-public/AB6AXuBTj1uufe8nMOFogBsc_4yK_47l2_5Pry-ZcyRdCdSMrBSxqOL13JewG1pyncXBAvV1zv1JDdfvampMOylwjHEwwIbgF4W2yFQas-Ra0mjUk0g62ExYQTtgxXeE5wGFAMYHCBjg56C-y2Os4yh2oKfsTKeQzpoDZc9IYaaALg2ACfWKFZtsV_XAXShAntlb5IOji7F7p7jxcGRhnY9fvN6mOYHcGLriek1Ql4tOh6aNQMjOIeOQ_UiUjeGsfKC5Sn7iP3Z7oyyh5da7"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm font-bold">James K.</p>
|
||||||
|
<p class="text-xs text-accent font-bold">+10,000 Miles</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-primary/20 flex items-center justify-center overflow-hidden">
|
||||||
|
<img alt="" class="w-full h-full object-cover" src="https://lh3.googleusercontent.com/aida-public/AB6AXuCAB6XTgSBN_5iUE-8cN8bDKhHWZa8Vpo7NWgd8yJQmRnp_WjwCWbviTPKsDs2VpkPSSlUI9msh7kPgUx7UAxd9sGwy9XnRrqDeVtmVDFWWzXHBMmEr5Vh6UWS_L6ziv3CrZXf1_uFGYHrQusuJAX9Z_vpPq7cn7FgdUvlgBrcpBsqNT8VpGtRAHHhHhCi4QLX_lhvEdW5sXf9DILmez-bjHHv__qMEq0irhH1VAX2ve5ZejhD7cSt3362RekobZa3U0DRpS3wVKLSj"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm font-bold">Elena R.</p>
|
||||||
|
<p class="text-xs text-slate-400 font-bold">+500 Miles</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gradient-to-br from-primary to-blue-700 p-6 rounded-2xl text-white shadow-xl">
|
||||||
|
<h4 class="font-bold text-lg mb-1">Double Odds!</h4>
|
||||||
|
<p class="text-sm text-white/80">Active for the next 24 minutes. Draw now to increase your chances.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Footer Info -->
|
||||||
|
<div class="mt-20 w-full border-t border-slate-200 dark:border-slate-800 pt-8 flex flex-col md:flex-row justify-between items-center gap-6">
|
||||||
|
<div class="flex gap-12 text-sm text-slate-500 font-medium">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="material-symbols-outlined text-primary">verified_user</span>
|
||||||
|
Provably Fair
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="material-symbols-outlined text-primary">speed</span>
|
||||||
|
Instant Payouts
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="material-symbols-outlined text-primary">support_agent</span>
|
||||||
|
24/7 Support
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-slate-400">© 2024 MileageDraw Games. Please play responsibly.</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const drawBtn = document.getElementById("draw-btn");
|
||||||
|
const drawBtnText = document.getElementById("draw-btn-text");
|
||||||
|
const drawBtnIcon = document.getElementById("draw-btn-icon");
|
||||||
|
const mysteryBoxContent = document.getElementById("mystery-box-content");
|
||||||
|
const boxContainer = document.getElementById("mystery-box-container");
|
||||||
|
const userMilesDisplay = document.getElementById("user-miles");
|
||||||
|
|
||||||
|
let userMiles = 15400; // Starting fake balance
|
||||||
|
|
||||||
|
const originalBoxHtml = `
|
||||||
|
<span class="material-symbols-outlined text-[160px] text-accent drop-shadow-[0_0_20px_rgba(251,191,36,0.5)]">featured_seasonal_and_gifts</span>
|
||||||
|
<div class="mt-4 flex gap-2">
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent animate-pulse"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent/50 animate-pulse delay-75"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent/20 animate-pulse delay-150"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
function updateMilesDisplay(miles) {
|
||||||
|
userMilesDisplay.textContent = miles.toLocaleString() + " Miles";
|
||||||
|
}
|
||||||
|
|
||||||
|
drawBtn.addEventListener("click", async () => {
|
||||||
|
if (userMiles < 500) {
|
||||||
|
alert("Not enough miles!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deduct cost and update UI
|
||||||
|
userMiles -= 500;
|
||||||
|
updateMilesDisplay(userMiles);
|
||||||
|
|
||||||
|
// Reset UI if it was previously revealing a prize
|
||||||
|
mysteryBoxContent.innerHTML = originalBoxHtml;
|
||||||
|
|
||||||
|
// Disable button while drawing
|
||||||
|
drawBtn.disabled = true;
|
||||||
|
drawBtnText.textContent = "DRAWING...";
|
||||||
|
drawBtnIcon.textContent = "refresh";
|
||||||
|
drawBtnIcon.classList.add("animate-spin");
|
||||||
|
drawBtnIcon.classList.remove("group-hover:translate-x-1");
|
||||||
|
|
||||||
|
// Add some animation to the box
|
||||||
|
boxContainer.classList.add("animate-pulse");
|
||||||
|
mysteryBoxContent.classList.add("animate-bounce");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/draw", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Network error");
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
|
||||||
|
// Wait for a short fake delay to build suspense
|
||||||
|
await new Promise(r => setTimeout(r, 1200));
|
||||||
|
|
||||||
|
// Stop animations
|
||||||
|
boxContainer.classList.remove("animate-pulse");
|
||||||
|
mysteryBoxContent.classList.remove("animate-bounce");
|
||||||
|
|
||||||
|
// Display result in the box with a pop-in effect
|
||||||
|
let prizeColorClass = "text-slate-400"; // 3rd prize fallback
|
||||||
|
let bgGlow = "from-slate-700 to-slate-900";
|
||||||
|
if (result.rank === 1) {
|
||||||
|
prizeColorClass = "text-accent";
|
||||||
|
bgGlow = "from-yellow-900 via-slate-900 to-slate-950";
|
||||||
|
} else if (result.rank === 2) {
|
||||||
|
prizeColorClass = "text-slate-200";
|
||||||
|
bgGlow = "from-slate-600 via-slate-800 to-slate-900";
|
||||||
|
} else if (result.rank === 3) {
|
||||||
|
prizeColorClass = "text-orange-400";
|
||||||
|
bgGlow = "from-orange-900 via-slate-900 to-slate-950";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update user balance
|
||||||
|
userMiles += result.miles;
|
||||||
|
updateMilesDisplay(userMiles);
|
||||||
|
|
||||||
|
mysteryBoxContent.innerHTML = `
|
||||||
|
<div class="flex flex-col items-center text-center animate-[pulse_1s_ease-in-out]">
|
||||||
|
<span class="material-symbols-outlined text-[100px] ${prizeColorClass} drop-shadow-[0_0_20px_rgba(255,255,255,0.2)]">emoji_events</span>
|
||||||
|
<h2 class="text-4xl font-black text-white mt-4 tracking-tighter">${result.name}</h2>
|
||||||
|
<p class="text-2xl font-bold ${prizeColorClass} mt-3">+${result.miles.toLocaleString()} Miles</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Change box container background conditionally
|
||||||
|
boxContainer.className = `relative w-full h-full bg-gradient-to-br ${bgGlow} rounded-3xl border-4 border-${result.rank === 1 ? 'accent' : (result.rank === 2 ? 'slate-400' : 'orange-400')}/40 shadow-2xl flex flex-col items-center justify-center overflow-hidden transition-all duration-500`;
|
||||||
|
|
||||||
|
// Setup button for "DRAW AGAIN"
|
||||||
|
drawBtnText.textContent = "DRAW AGAIN";
|
||||||
|
drawBtnIcon.textContent = "replay";
|
||||||
|
drawBtnIcon.classList.remove("animate-spin");
|
||||||
|
drawBtnIcon.classList.add("group-hover:-rotate-180");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error drawing prize:", error);
|
||||||
|
alert("An error occurred while drawing the prize. Please try again.");
|
||||||
|
|
||||||
|
// Reset button
|
||||||
|
drawBtnText.textContent = "DRAW NOW";
|
||||||
|
drawBtnIcon.textContent = "arrow_forward";
|
||||||
|
drawBtnIcon.classList.remove("animate-spin");
|
||||||
|
drawBtnIcon.classList.add("group-hover:translate-x-1");
|
||||||
|
|
||||||
|
boxContainer.classList.remove("animate-pulse");
|
||||||
|
mysteryBoxContent.classList.remove("animate-bounce");
|
||||||
|
} finally {
|
||||||
|
// Re-enable button
|
||||||
|
drawBtn.disabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
print(datetime.date.today())
|
||||||
|
print(datetime.time().hour)
|
||||||
|
print(datetime.datetime.now())
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
PRIZES = [
|
||||||
|
{"rank": 1, "name": "1st Prize", "miles": 10000, "probability": 0.20},
|
||||||
|
{"rank": 2, "name": "2nd Prize", "miles": 5000, "probability": 0.30},
|
||||||
|
{"rank": 3, "name": "3rd Prize", "miles": 2000, "probability": 0.50},
|
||||||
|
]
|
||||||
|
|
||||||
|
def draw_prize():
|
||||||
|
rand_val = random.random()
|
||||||
|
cumulative = 0.0
|
||||||
|
for prize in PRIZES:
|
||||||
|
cumulative += prize["probability"]
|
||||||
|
if rand_val <= cumulative:
|
||||||
|
return prize
|
||||||
|
return PRIZES[-1]
|
||||||
|
|
||||||
|
counts = {1: 0, 2: 0, 3: 0}
|
||||||
|
trials = 100000
|
||||||
|
|
||||||
|
for _ in range(trials):
|
||||||
|
res = draw_prize()
|
||||||
|
counts[res["rank"]] += 1
|
||||||
|
|
||||||
|
print("Results for 100,000 trials:")
|
||||||
|
for rank, count in counts.items():
|
||||||
|
print(f"Rank {rank}: {count/trials*100:.2f}%")
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html class="dark" lang="en"><head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
|
<title>MileageDraw - Win Big Today</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Spline+Sans:wght@300;400;500;600;700&display=swap" rel="stylesheet"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<script id="tailwind-config">
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: "class",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
"primary": "#2b4bee",
|
||||||
|
"accent": "#fbbf24",
|
||||||
|
"background-light": "#f6f6f8",
|
||||||
|
"background-dark": "#101322",
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
"display": ["Spline Sans", "sans-serif"]
|
||||||
|
},
|
||||||
|
borderRadius: {"DEFAULT": "0.25rem", "lg": "0.5rem", "xl": "0.75rem", "full": "9999px"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-background-light dark:bg-background-dark font-display text-slate-900 dark:text-slate-100 min-h-screen">
|
||||||
|
<div class="relative flex h-auto min-h-screen w-full flex-col bg-background-light dark:bg-background-dark overflow-x-hidden">
|
||||||
|
<div class="layout-container flex h-full grow flex-col">
|
||||||
|
<!-- Navigation Bar -->
|
||||||
|
<header class="flex items-center justify-between whitespace-nowrap border-b border-solid border-slate-200 dark:border-slate-800 px-6 lg:px-20 py-4 bg-background-light dark:bg-background-dark sticky top-0 z-50">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="text-primary size-8">
|
||||||
|
<span class="material-symbols-outlined text-4xl">redeem</span>
|
||||||
|
</div>
|
||||||
|
<h2 class="text-slate-900 dark:text-white text-xl font-bold leading-tight tracking-tight">MileageDraw</h2>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-1 justify-end items-center gap-6 lg:gap-10">
|
||||||
|
<nav class="hidden md:flex items-center gap-8">
|
||||||
|
<a class="text-slate-600 dark:text-slate-300 hover:text-primary dark:hover:text-primary text-sm font-semibold transition-colors" href="#">Home</a>
|
||||||
|
<a class="text-slate-600 dark:text-slate-300 hover:text-primary dark:hover:text-primary text-sm font-semibold transition-colors" href="#">My Prizes</a>
|
||||||
|
<a class="text-slate-600 dark:text-slate-300 hover:text-primary dark:hover:text-primary text-sm font-semibold transition-colors" href="#">How to Play</a>
|
||||||
|
</nav>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<button class="flex min-w-[120px] cursor-pointer items-center justify-center rounded-xl h-10 px-5 bg-primary/10 border border-primary/20 text-primary text-sm font-bold">
|
||||||
|
<span class="material-symbols-outlined text-sm mr-2">account_balance_wallet</span>
|
||||||
|
<span class="truncate">15,400 Miles</span>
|
||||||
|
</button>
|
||||||
|
<div class="bg-center bg-no-repeat aspect-square bg-cover rounded-full size-10 border-2 border-primary/30" data-alt="User profile avatar circle" style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuASf-yBhfIyds7eDugHWDN-bVo-aoZM14xRSjRn1GNH4vvCCYuu6gLziV5Evf5W0hqHxLrhmsM7tMWPhL-PjDqctgWRBCEnW3zELC5v2BZrvEhgo7NB55Oo3YJ0-2C3fZmMgCxSC5SuwkcGmCvlEJiijE0RYtDZ7XenI3RD5Lt1VaEmPQ82FSB26oCxEJJ5I-hy02TTYa_npKImAXIOfm-x5Mh8evuGz0MoqoPTOSTuU3LxrHouNtN65FJ4KP4YUzBeSvC1b60St8_D");'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main class="flex-1 flex flex-col items-center px-4 lg:px-20 py-10 max-w-7xl mx-auto w-full">
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8 w-full items-center">
|
||||||
|
<!-- Left Side: Prize Board -->
|
||||||
|
<div class="lg:col-span-3 flex flex-col gap-4 order-2 lg:order-1">
|
||||||
|
<div class="bg-slate-50 dark:bg-slate-900/50 p-6 rounded-2xl border border-slate-200 dark:border-slate-800 backdrop-blur-sm">
|
||||||
|
<h3 class="text-lg font-bold mb-6 flex items-center gap-2">
|
||||||
|
<span class="material-symbols-outlined text-accent">military_tech</span>
|
||||||
|
Prize Pool
|
||||||
|
</h3>
|
||||||
|
<div class="space-y-6">
|
||||||
|
<div class="relative pl-4 border-l-4 border-accent">
|
||||||
|
<p class="text-xs uppercase tracking-wider text-slate-500 dark:text-slate-400 font-bold">1st Prize</p>
|
||||||
|
<p class="text-2xl font-black text-slate-900 dark:text-white">10,000 <span class="text-sm font-normal text-slate-500">Miles</span></p>
|
||||||
|
</div>
|
||||||
|
<div class="relative pl-4 border-l-4 border-slate-400">
|
||||||
|
<p class="text-xs uppercase tracking-wider text-slate-500 dark:text-slate-400 font-bold">2nd Prize</p>
|
||||||
|
<p class="text-2xl font-black text-slate-900 dark:text-white">5,000 <span class="text-sm font-normal text-slate-500">Miles</span></p>
|
||||||
|
</div>
|
||||||
|
<div class="relative pl-4 border-l-4 border-orange-400">
|
||||||
|
<p class="text-xs uppercase tracking-wider text-slate-500 dark:text-slate-400 font-bold">3rd Prize</p>
|
||||||
|
<p class="text-2xl font-black text-slate-900 dark:text-white">2,000 <span class="text-sm font-normal text-slate-500">Miles</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-primary/5 p-6 rounded-2xl border border-primary/20">
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400 leading-relaxed italic">
|
||||||
|
"Thousands of users have already claimed their rewards this month. Will you be next?"
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Center: Mystery Box -->
|
||||||
|
<div class="lg:col-span-6 flex flex-col items-center justify-center gap-8 order-1 lg:order-2">
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="text-4xl lg:text-5xl font-black text-slate-900 dark:text-white mb-2 tracking-tight">Try Your Luck!</h1>
|
||||||
|
<p class="text-slate-600 dark:text-slate-400 text-lg">Open the Mystery Box to win huge rewards</p>
|
||||||
|
</div>
|
||||||
|
<div class="relative group cursor-pointer w-full max-w-md aspect-square flex items-center justify-center">
|
||||||
|
<!-- Background Glow Effect -->
|
||||||
|
<div class="absolute inset-0 bg-primary/20 blur-[100px] rounded-full scale-75 group-hover:bg-primary/30 transition-all duration-500"></div>
|
||||||
|
<!-- Mystery Box Container -->
|
||||||
|
<div class="relative w-full h-full bg-gradient-to-br from-slate-800 to-slate-950 rounded-3xl border-4 border-accent/30 shadow-2xl flex flex-col items-center justify-center overflow-hidden">
|
||||||
|
<!-- Box Illustration (Simulated with Material Symbols and Gradients) -->
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<span class="material-symbols-outlined text-[160px] text-accent drop-shadow-[0_0_20px_rgba(251,191,36,0.5)]">featured_seasonal_and_gifts</span>
|
||||||
|
<div class="mt-4 flex gap-2">
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent animate-pulse"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent/50 animate-pulse delay-75"></div>
|
||||||
|
<div class="w-3 h-3 rounded-full bg-accent/20 animate-pulse delay-150"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Sparkle elements -->
|
||||||
|
<span class="material-symbols-outlined absolute top-10 left-10 text-accent/40 text-2xl">auto_awesome</span>
|
||||||
|
<span class="material-symbols-outlined absolute bottom-12 right-12 text-accent/40 text-4xl">auto_awesome</span>
|
||||||
|
<span class="material-symbols-outlined absolute top-20 right-16 text-accent/40 text-xl">auto_awesome</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center gap-4 w-full">
|
||||||
|
<button class="w-full max-w-xs flex cursor-pointer items-center justify-center rounded-2xl h-16 px-8 bg-primary hover:bg-primary/90 text-white text-xl font-black shadow-lg shadow-primary/40 transition-all active:scale-95 group">
|
||||||
|
<span class="mr-3">DRAW NOW</span>
|
||||||
|
<span class="material-symbols-outlined group-hover:translate-x-1 transition-transform">arrow_forward</span>
|
||||||
|
</button>
|
||||||
|
<p class="text-xs text-slate-500 font-medium">Cost: 500 Miles per draw</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Right Side: Recent Winners -->
|
||||||
|
<div class="lg:col-span-3 flex flex-col gap-4 order-3">
|
||||||
|
<div class="bg-slate-50 dark:bg-slate-900/50 p-6 rounded-2xl border border-slate-200 dark:border-slate-800">
|
||||||
|
<h3 class="text-sm font-bold text-slate-500 uppercase tracking-widest mb-4">Live Winners</h3>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-primary/20 flex items-center justify-center overflow-hidden">
|
||||||
|
<img alt="" class="w-full h-full object-cover" data-alt="User avatar of Alice" src="https://lh3.googleusercontent.com/aida-public/AB6AXuCNyWQdRGCg_-tNwAu4-0oRfpGbiWSPp5prILJ1oalpRniDZ1DQL7yiiiDxVsiNuFMgCiKBVvFQRXrjlinRU-iZI_YM0XcDO2BuaK6YVIUwvn7DWhqUMcYYSA9EDn9vknhh9Sii2sb8KQkpoNsJdu25N8vJIcRuFAAioW3NFk-UPNLBfIPsRe1LxmgaxR6s_EIO6RfaV49lqaDiNOODXxKWtL-kl6oczKoBh7P0-DRwgdVJ2hjHlY3Dt33RCg91dSaBBPffcqIO8Qky"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm font-bold">Alice W.</p>
|
||||||
|
<p class="text-xs text-primary font-bold">+2,000 Miles</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-primary/20 flex items-center justify-center overflow-hidden">
|
||||||
|
<img alt="" class="w-full h-full object-cover" data-alt="User avatar of Bob" src="https://lh3.googleusercontent.com/aida-public/AB6AXuBTj1uufe8nMOFogBsc_4yK_47l2_5Pry-ZcyRdCdSMrBSxqOL13JewG1pyncXBAvV1zv1JDdfvampMOylwjHEwwIbgF4W2yFQas-Ra0mjUk0g62ExYQTtgxXeE5wGFAMYHCBjg56C-y2Os4yh2oKfsTKeQzpoDZc9IYaaALg2ACfWKFZtsV_XAXShAntlb5IOji7F7p7jxcGRhnY9fvN6mOYHcGLriek1Ql4tOh6aNQMjOIeOQ_UiUjeGsfKC5Sn7iP3Z7oyyh5da7"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm font-bold">James K.</p>
|
||||||
|
<p class="text-xs text-accent font-bold">+10,000 Miles</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-primary/20 flex items-center justify-center overflow-hidden">
|
||||||
|
<img alt="" class="w-full h-full object-cover" data-alt="User avatar of Carla" src="https://lh3.googleusercontent.com/aida-public/AB6AXuCAB6XTgSBN_5iUE-8cN8bDKhHWZa8Vpo7NWgd8yJQmRnp_WjwCWbviTPKsDs2VpkPSSlUI9msh7kPgUx7UAxd9sGwy9XnRrqDeVtmVDFWWzXHBMmEr5Vh6UWS_L6ziv3CrZXf1_uFGYHrQusuJAX9Z_vpPq7cn7FgdUvlgBrcpBsqNT8VpGtRAHHhHhCi4QLX_lhvEdW5sXf9DILmez-bjHHv__qMEq0irhH1VAX2ve5ZejhD7cSt3362RekobZa3U0DRpS3wVKLSj"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm font-bold">Elena R.</p>
|
||||||
|
<p class="text-xs text-slate-400 font-bold">+500 Miles</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gradient-to-br from-primary to-blue-700 p-6 rounded-2xl text-white shadow-xl">
|
||||||
|
<h4 class="font-bold text-lg mb-1">Double Odds!</h4>
|
||||||
|
<p class="text-sm text-white/80">Active for the next 24 minutes. Draw now to increase your chances.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Footer Info -->
|
||||||
|
<div class="mt-20 w-full border-t border-slate-200 dark:border-slate-800 pt-8 flex flex-col md:flex-row justify-between items-center gap-6">
|
||||||
|
<div class="flex gap-12 text-sm text-slate-500 font-medium">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="material-symbols-outlined text-primary">verified_user</span>
|
||||||
|
Provably Fair
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="material-symbols-outlined text-primary">speed</span>
|
||||||
|
Instant Payouts
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="material-symbols-outlined text-primary">support_agent</span>
|
||||||
|
24/7 Support
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-slate-400">© 2024 MileageDraw Games. Please play responsibly.</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body></html>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 360 KiB |
Reference in New Issue
Block a user