anycoder-c3c7d790 / index.html
Wavetype's picture
Upload folder using huggingface_hub
fdeec57 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GODS RODS - FANTASY RALLY</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Rajdhani:wght@400;500;700&display=swap"
rel="stylesheet">
<style>
:root {
--neon-cyan: #00ffff;
--neon-purple: #a855f7;
--neon-pink: #ff00ff;
--dark-bg: #050505;
--dark-overlay: rgba(5, 5, 5, 0.92);
--card-bg: #0a0a0a;
--border-glow-cyan: 0 0 10px rgba(0, 255, 255, 0.5);
--border-glow-purple: 0 0 10px rgba(168, 85, 247, 0.5);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Rajdhani', sans-serif;
color: #e0e0e0;
background: var(--dark-bg);
min-height: 100vh;
overflow-x: hidden;
}
/* Custom Scrollbar */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: #111;
}
::-webkit-scrollbar-thumb {
background: var(--neon-cyan);
border-radius: 3px;
}
/* Header */
.main-header {
background: linear-gradient(180deg, rgba(0, 0, 0, 0.95) 0%, rgba(0, 0, 0, 0.8) 100%);
border-bottom: 2px solid var(--neon-cyan);
padding: 15px 30px;
display: flex;
justify-content: space-between;
align-items: center;
position: sticky;
top: 0;
z-index: 1000;
backdrop-filter: blur(10px);
}
.logo-section {
display: flex;
align-items: center;
gap: 15px;
}
.logo-icon {
width: 40px;
height: 40px;
border: 2px solid var(--neon-cyan);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
animation: logoSpin 10s linear infinite;
}
@keyframes logoSpin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.header-title {
font-family: 'Orbitron', sans-serif;
font-size: 1.2rem;
color: var(--neon-cyan);
text-shadow: var(--border-glow-cyan);
letter-spacing: 3px;
}
.anycoder-link {
font-family: 'Orbitron', sans-serif;
font-size: 0.75rem;
color: var(--neon-purple);
text-decoration: none;
padding: 8px 15px;
border: 1px solid var(--neon-purple);
border-radius: 4px;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 1px;
}
.anycoder-link:hover {
background: var(--neon-purple);
color: #000;
box-shadow: var(--border-glow-purple);
}
/* Navigation */
.main-nav {
background: rgba(0, 0, 0, 0.95);
padding: 12px 20px;
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 8px;
border-bottom: 1px solid #222;
}
.nav-btn {
font-family: 'Orbitron', sans-serif;
background: transparent;
color: #888;
border: 1px solid transparent;
padding: 8px 16px;
font-size: 0.7rem;
cursor: pointer;
transition: all 0.3s ease;
letter-spacing: 2px;
text-transform: uppercase;
position: relative;
overflow: hidden;
}
.nav-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(0, 255, 255, 0.1), transparent);
transition: left 0.5s ease;
}
.nav-btn:hover::before {
left: 100%;
}
.nav-btn:hover,
.nav-btn.active {
color: var(--neon-cyan);
border-color: var(--neon-cyan);
text-shadow: var(--border-glow-cyan);
}
/* Main Container */
#app {
min-height: calc(100vh - 120px);
position: relative;
}
/* Global Background */
.global-bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:
linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)),
url('https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=1920&q=80');
background-size: cover;
background-position: center;
background-attachment: fixed;
z-index: -1;
}
/* Page Container */
.page {
display: none;
min-height: calc(100vh - 120px);
padding: 40px 20px;
animation: fadeIn 0.5s ease;
}
.page.active {
display: block;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Landing Page */
.landing-page {
display: flex;
height: calc(100vh - 120px);
position: relative;
}
.landing-page.active {
display: flex;
}
.landing-half {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.5s ease;
position: relative;
overflow: hidden;
}
.landing-half::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(45deg, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.4));
z-index: 1;
}
.left-side {
background: url('https://images.unsplash.com/photo-1603584173870-7f23fdae1b7a?w=1920&q=80');
background-size: cover;
background-position: center;
border-right: 3px solid var(--neon-cyan);
}
.right-side {
background: url('https://images.unsplash.com/photo-1533106958155-d2d7069fbd94?w=1920&q=80');
background-size: cover;
background-position: center;
}
.landing-half:hover {
filter: brightness(1.3);
}
.landing-half:hover .landing-content {
transform: scale(1.1);
}
.landing-content {
position: relative;
z-index: 2;
text-align: center;
transition: transform 0.5s ease;
}
.landing-content h1 {
font-family: 'Orbitron', sans-serif;
font-size: clamp(2rem, 5vw, 4rem);
letter-spacing: 5px;
margin-bottom: 20px;
}
.neon-text-cyan {
color: var(--neon-cyan);
text-shadow: 0 0 20px var(--neon-cyan), 0 0 40px var(--neon-cyan);
}
.neon-text-purple {
color: var(--neon-purple);
text-shadow: 0 0 20px var(--neon-purple), 0 0 40px var(--neon-purple);
}
.landing-content p {
font-family: 'Orbitron', sans-serif;
font-size: 1rem;
letter-spacing: 3px;
opacity: 0.8;
}
/* Content Wrapper */
.content-wrapper {
max-width: 1400px;
margin: 0 auto;
text-align: center;
}
.page-title {
font-family: 'Orbitron', sans-serif;
font-size: clamp(1.5rem, 3vw, 2.5rem);
letter-spacing: 4px;
margin-bottom: 40px;
padding: 20px;
border: 1px solid;
border-image: linear-gradient(90deg, transparent, currentColor, transparent) 1;
}
.center-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 50vh;
gap: 20px;
}
/* Buttons */
.action-btn {
font-family: 'Orbitron', sans-serif;
padding: 15px 40px;
border: none;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
margin: 10px;
letter-spacing: 2px;
text-transform: uppercase;
position: relative;
overflow: hidden;
}
.action-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.action-btn:hover::before {
width: 300px;
height: 300px;
}
.cyan-btn {
background: var(--neon-cyan);
color: #000;
}
.cyan-btn:hover {
box-shadow: 0 0 30px var(--neon-cyan);
transform: translateY(-3px);
}
.purple-btn {
background: linear-gradient(135deg, var(--neon-purple), #7c3aed);
color: #fff;
}
.purple-btn:hover {
box-shadow: 0 0 30px var(--neon-purple);
transform: translateY(-3px);
}
.pulse-button {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(168, 85, 247, 0.7);
}
70% {
box-shadow: 0 0 0 20px rgba(168, 85, 247, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(168, 85, 247, 0);
}
}
/* Garage Grid */
.garage-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 25px;
margin-top: 40px;
}
.gr-block {
background: var(--card-bg);
border: 1px solid #333;
border-radius: 8px;
overflow: hidden;
transition: all 0.3s ease;
position: relative;
}
.gr-block::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: linear-gradient(90deg, var(--neon-cyan), var(--neon-purple));
transform: scaleX(0);
transform-origin: left;
transition: transform 0.3s ease;
}
.gr-block:hover::before {
transform: scaleX(1);
}
.gr-block:hover {
transform: translateY(-5px);
border-color: var(--neon-cyan);
box-shadow: 0 10px 40px rgba(0, 255, 255, 0.2);
}
.car-img {
width: 100%;
height: 200px;
object-fit: cover;
background: #111;
}
.car-info {
padding: 15px;
border-top: 1px solid #333;
font-family: 'Orbitron', sans-serif;
font-size: 0.85rem;
color: var(--neon-cyan);
letter-spacing: 1px;
}
/* Empty State */
.empty-state {
padding: 60px 20px;
text-align: center;
}
.empty-state p {
font-family: 'Orbitron', sans-serif;
color: #666;
margin-bottom: 30px;
font-size: 0.9rem;
letter-spacing: 2px;
}
/* Race Track */
.race-track-container {
max-width: 1000px;
margin: 0 auto;
}
.race-status {
font-family: 'Orbitron', sans-serif;
font-size: 1.5rem;
margin-bottom: 30px;
padding: 15px 30px;
border: 2px solid var(--neon-purple);
display: inline-block;
}
.race-track {
background: rgba(0, 0, 0, 0.6);
padding: 30px;
border: 2px solid var(--neon-purple);
border-radius: 10px;
margin: 30px 0;
position: relative;
overflow: hidden;
}
.race-track::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: repeating-linear-gradient(90deg,
transparent,
transparent 49px,
rgba(255, 255, 255, 0.1) 50px);
}
.race-lane {
height: 70px;
border-bottom: 1px solid #222;
position: relative;
display: flex;
align-items: center;
}
.race-lane:last-child {
border-bottom: none;
}
.lane-number {
position: absolute;
left: 10px;
font-family: 'Orbitron', sans-serif;
color: #444;
font-size: 0.8rem;
}
.finish-line {
position: absolute;
right: 50px;
top: 0;
height: 100%;
width: 20px;
background: repeating-linear-gradient(0deg,
#fff 0px,
#fff 10px,
#000 10px,
#000 20px);
opacity: 0.5;
}
.car-sprite {
position: absolute;
font-size: 2.5rem;
transition: left 0.1s linear;
filter: drop-shadow(0 0 15px var(--neon-purple));
z-index: 2;
}
.race-controls {
margin: 30px 0;
}
/* Race Footer */
.race-footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0.98));
border-top: 2px solid var(--neon-purple);
padding: 20px 0;
z-index: 100;
}
.footer-tabs {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 30px;
font-family: 'Orbitron', sans-serif;
font-size: 0.7rem;
letter-spacing: 2px;
}
.footer-tabs span {
color: var(--neon-purple);
cursor: pointer;
padding: 10px 15px;
border: 1px solid transparent;
transition: all 0.3s ease;
}
.footer-tabs span:hover {
color: #fff;
border-color: var(--neon-purple);
text-shadow: var(--border-glow-purple);
}
/* Placeholder Box */
.placeholder-box {
padding: 80px 50px;
border: 2px dashed #333;
color: #555;
font-family: 'Orbitron', sans-serif;
letter-spacing: 3px;
font-size: 1rem;
background: rgba(0, 0, 0, 0.5);
position: relative;
}
.placeholder-box::after {
content: '';
position: absolute;
top: -1px;
left: -1px;
right: -1px;
bottom: -1px;
border: 2px solid var(--neon-cyan);
opacity: 0;
transition: opacity 0.3s ease;
}
.placeholder-box:hover::after {
opacity: 1;
}
/* Input */
.dark-input {
background: #111;
border: 2px solid var(--neon-cyan);
color: white;
padding: 18px 30px;
width: 100%;
max-width: 400px;
text-align: center;
font-family: 'Orbitron', sans-serif;
font-size: 0.9rem;
letter-spacing: 2px;
transition: all 0.3s ease;
}
.dark-input:focus {
outline: none;
box-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
}
.dark-input::placeholder {
color: #555;
}
/* Loading Animation */
.loading-dots::after {
content: '';
animation: dots 1.5s infinite;
}
@keyframes dots {
0%,
20% {
content: '.';
}
40% {
content: '..';
}
60%,
100% {
content: '...';
}
}
/* Responsive */
@media (max-width: 768px) {
.main-header {
flex-direction: column;
gap: 15px;
padding: 15px;
}
.main-nav {
gap: 5px;
padding: 10px;
}
.nav-btn {
padding: 6px 10px;
font-size: 0.6rem;
}
.landing-page {
flex-direction: column;
height: auto;
}
.landing-half {
height: 50vh;
border-right: none;
border-bottom: 3px solid;
}
.left-side {
border-bottom-color: var(--neon-cyan);
}
.right-side {
border-bottom: none;
}
.footer-tabs {
gap: 15px;
font-size: 0.6rem;
}
.footer-tabs span {
padding: 5px 8px;
}
.race-track {
padding: 15px;
}
.race-lane {
height: 50px;
}
.car-sprite {
font-size: 1.8rem;
}
.garage-grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
}
}
/* Scanline Effect */
.scanlines {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
background: repeating-linear-gradient(0deg,
rgba(0, 0, 0, 0.1),
rgba(0, 0, 0, 0.1) 1px,
transparent 1px,
transparent 2px);
opacity: 0.3;
}
/* Glitch Effect on Title */
.glitch {
position: relative;
}
.glitch::before,
.glitch::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.glitch::before {
animation: glitch-1 2s infinite linear alternate-reverse;
clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%);
color: var(--neon-cyan);
opacity: 0.8;
}
.glitch::after {
animation: glitch-2 3s infinite linear alternate-reverse;
clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%);
color: var(--neon-purple);
opacity: 0.8;
}
@keyframes glitch-1 {
0% {
transform: translate(0);
}
20% {
transform: translate(-3px, 3px);
}
40% {
transform: translate(-3px, -3px);
}
60% {
transform: translate(3px, 3px);
}
80% {
transform: translate(3px, -3px);
}
100% {
transform: translate(0);
}
}
@keyframes glitch-2 {
0% {
transform: translate(0);
}
20% {
transform: translate(3px, -3px);
}
40% {
transform: translate(3px, 3px);
}
60% {
transform: translate(-3px, -3px);
}
80% {
transform: translate(-3px, 3px);
}
100% {
transform: translate(0);
}
}
/* Pre-builds Grid */
.prebuilds-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-top: 30px;
width: 100%;
max-width: 1000px;
}
.prebuild-card {
background: var(--card-bg);
border: 1px solid #333;
padding: 20px;
transition: all 0.3s ease;
cursor: pointer;
}
.prebuild-card:hover {
border-color: var(--neon-cyan);
box-shadow: 0 0 20px rgba(0, 255, 255, 0.2);
}
.prebuild-card h3 {
font-family: 'Orbitron', sans-serif;
color: var(--neon-cyan);
margin-bottom: 10px;
}
.prebuild-card p {
color: #666;
font-size: 0.85rem;
}
/* Backend Status */
.backend-status {
font-family: 'Orbitron', sans-serif;
font-size: 0.7rem;
padding: 8px 15px;
border: 1px solid #333;
border-radius: 4px;
display: flex;
align-items: center;
gap: 8px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #22c55e;
animation: statusPulse 2s infinite;
}
.status-dot.offline {
background: #ef4444;
animation: none;
}
@keyframes statusPulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
/* Toast Notifications */
.toast-container {
position: fixed;
top: 150px;
right: 20px;
z-index: 10000;
display: flex;
flex-direction: column;
gap: 10px;
}
.toast {
background: var(--card-bg);
border: 1px solid var(--neon-cyan);
padding: 15px 25px;
font-family: 'Orbitron', sans-serif;
font-size: 0.8rem;
color: var(--neon-cyan);
animation: slideIn 0.3s ease, fadeOut 0.3s ease 2.7s;
max-width: 300px;
}
.toast.error {
border-color: #ef4444;
color: #ef4444;
}
.toast.success {
border-color: #22c55e;
color: #22c55e;
}
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
/* Stats Panel */
.stats-panel {
display: flex;
justify-content: center;
gap: 30px;
margin-bottom: 30px;
flex-wrap: wrap;
}
.stat-item {
background: var(--card-bg);
border: 1px solid #333;
padding: 15px 25px;
text-align: center;
}
.stat-item .value {
font-family: 'Orbitron', sans-serif;
font-size: 1.5rem;
color: var(--neon-cyan);
}
.stat-item .label {
font-size: 0.7rem;
color: #666;
letter-spacing: 2px;
}
</style>
</head>
<body>
<div class="global-bg"></div>
<div class="scanlines"></div>
<div class="toast-container" id="toast-container"></div>
<header class="main-header">
<div class="logo-section">
<div class="logo-icon"></div>
<span class="header-title">GODS RODS</span>
</div>
<div style="display: flex; align-items: center; gap: 15px;">
<div class="backend-status">
<div class="status-dot" id="backend-dot"></div>
<span id="backend-text">LOCAL STORAGE</span>
</div>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with
anycoder</a>
</div>
</header>
<nav class="main-nav">
<button class="nav-btn active" data-page="landing">HOME</button>
<button class="nav-btn" data-page="garage">GARAGE</button>
<button class="nav-btn" data-page="race">NO-LIMIT-RACE</button>
<button class="nav-btn" data-page="rim-designer">RIM DESIGNER</button>
<button class="nav-btn" data-page="rim-forge">RIM FORGE</button>
<button class="nav-btn" data-page="batch-seed">BATCH SEED</button>
<button class="nav-btn" data-page="garage-3d">3D GARAGE</button>
<button class="nav-btn" data-page="objects-3d">3D OBJECTS</button>
</nav>
<div id="app">
<!-- Landing Page -->
<div id="landing" class="page landing-page active">
<div class="landing-half left-side" onclick="navigateTo('garage')">
<div class="landing-content">
<h1 class="neon-text-cyan">GODS RODS</h1>
<p>VIEW GARAGE</p>
</div>
</div>
<div class="landing-half right-side" onclick="navigateTo('race')">
<div class="landing-content">
<h1 class="neon-text-purple">FANTASY RALLY</h1>
<p>ENTER THE RACE</p>
</div>
</div>
</div>
<!-- Garage Page -->
<div id="garage" class="page">
<div class="content-wrapper">
<h2 class="page-title neon-text-cyan">GARAGE PROTOCOL</h2>
<div class="stats-panel">
<div class="stat-item">
<div class="value" id="total-cars">0</div>
<div class="label">TOTAL UNITS</div>
</div>
<div class="stat-item">
<div class="value" id="total-races">0</div>
<div class="label">RACES COMPLETED</div>
</div>
</div>
<div class="empty-state" id="garage-empty">
<p class="font-orb">3D MODULE OFFLINE - INITIALIZING NEW STORAGE</p>
<button onclick="generateCar()" class="action-btn cyan-btn">GENERATE UNIT</button>
</div>
<div class="garage-grid" id="garage-grid"></div>
</div>
</div>
<!-- Race Page -->
<div id="race" class="page">
<div class="content-wrapper">
<div class="race-track-container">
<h2 class="page-title neon-text-purple" id="race-status">NO LIMIT RACE</h2>
<div class="race-track">
<div class="finish-line"></div>
<div class="race-lane"><span class="lane-number">01</span>
<div class="car-sprite" id="car-0" style="left: 0%">🏎️</div>
</div>
<div class="race-lane"><span class="lane-number">02</span>
<div class="car-sprite" id="car-1" style="left: 0%">🏎️</div>
</div>
<div class="race-lane"><span class="lane-number">03</span>
<div class="car-sprite" id="car-2" style="left: 0%">🏎️</div>
</div>
<div class="race-lane"><span class="lane-number">04</span>
<div class="car-sprite" id="car-3" style="left: 0%">🏎️</div>
</div>
</div>
<div class="race-controls">
<button onclick="startRace()" id="race-btn" class="action-btn purple-btn pulse-button">INITIALIZE RACE</button>
</div>
</div>
</div>
<footer class="race-footer">
<div class="footer-tabs">
<span>LEADERBOARD</span>
<span>BETTING</span>
<span>UPGRADES</span>
<span>SPONSORS</span>
<span>REPLAYS</span>
</div>
</footer>
</div>
<!-- Rim Designer -->
<div id="rim-designer" class="page">
<div class="content-wrapper center-content">
<h2 class="page-title neon-text-cyan">RIM DESIGNER</h2>
<div class="placeholder-box">SYSTEM INITIALIZING...</div>
</div>
</div>
<!-- Rim Forge -->
<div id="rim-forge" class="page">
<div class="content-wrapper center-content">
<h2 class="page-title neon-text-purple">RIM FORGE</h2>
<div class="placeholder-box">FORGE OFFLINE</div>
</div>
</div>
<!-- Batch Seed -->
<div id="batch-seed" class="page">
<div class="content-wrapper center-content">
<h2 class="page-title">BATCH SEEDER</h2>
<input type="text" placeholder="ENTER SEED MASK..." class="dark-input" id="seed-input">
<button onclick="batchGenerate()" class="action-btn cyan-btn">GENERATE BATCH</button>
</div>
</div>
<!-- 3D Garage -->
<div id="garage-3d" class="page">
<div class="content-wrapper center-content">
<h2 class="page-title neon-text-cyan">3D GARAGE</h2>
<div class="placeholder-box">3D RENDER ENGINE DISCONNECTED</div>
</div>
</div>
<!-- 3D Objects -->
<div id="objects-3d" class="page">
<div class="content-wrapper">
<h2 class="page-title">ASSET LIBRARY</h2>
<div class="center-content" style="margin-top: 50px;">
<button class="action-btn cyan-btn" style="font-size: 1.5rem; padding: 25px 50px;" onclick="showPrebuilds()">PRE-BUILDS</button>
<p style="margin-top: 30px; font-family: 'Orbitron', sans-serif; color: #666;">ACCESSING 3D
MODELS<span class="loading-dots"></span></p>
</div>
<div class="prebuilds-grid" id="prebuilds-grid" style="display: none;"></div>
</div>
</div>
</div>
<script>
// ============================================
// BACKEND SIMULATION - LOCAL STORAGE DATABASE
// ============================================
const DB_KEY = 'godsrods_database';
const STATS_KEY = 'godsrods_stats';
// Initialize database structure
function initDatabase() {
const existing = localStorage.getItem(DB_KEY);
if (!existing) {
const initialData = {
users: {},
garage: [],
rims: [],
raceHistory: []
};
localStorage.setItem(DB_KEY, JSON.stringify(initialData));
return initialData;
}
return JSON.parse(existing);
}
// Get database
function getDB() {
return initDatabase();
}
// Save database
function saveDB(data) {
localStorage.setItem(DB_KEY, JSON.stringify(data));
}
// Get stats
function getStats() {
const stats = localStorage.getItem(STATS_KEY);
if (!stats) {
return { totalCars: 0, totalRaces: 0 };
}
return JSON.parse(stats);
}
// Save stats
function saveStats(stats) {
localStorage.setItem(STATS_KEY, JSON.stringify(stats));
}
// ============================================
// API LAYER - Simulated Backend Endpoints
// ============================================
const API = {
// GET /api/get_garage/:user_id
async getGarage(userId) {
try {
const db = getDB();
const userGarage = db.garage.filter(car => car.user_id === userId);
return { success: true, data: userGarage };
} catch (error) {
return { success: false, error: error.message };
}
},
// POST /api/add_car
async addCar(userId, carData) {
try {
const db = getDB();
const newCar = {
id: Date.now(),
user_id: userId,
car_data: carData,
created_at: new Date().toISOString()
};
db.garage.push(newCar);
saveDB(db);
// Update stats
const stats = getStats();
stats.totalCars = (stats.totalCars || 0) + 1;
saveStats(stats);
return { success: true, data: newCar };
} catch (error) {
return { success: false, error: error.message };
}
},
// POST /api/add_rim
async addRim(userId, rimData) {
try {
const db = getDB();
const newRim = {
id: Date.now(),
user_id: userId,
rim_data: rimData,
created_at: new Date().toISOString()
};
db.rims.push(newRim);
saveDB(db);
return { success: true, data: newRim };
} catch (error) {
return { success: false, error: error.message };
}
},
// POST /api/race_result
async saveRaceResult(userId, result) {
try {
const db = getDB();
const raceRecord = {
id: Date.now(),
user_id: userId,
winner: result.winner,
positions: result.positions,
timestamp: new Date().toISOString()
};
db.raceHistory.push(raceRecord);
saveDB(db);
// Update stats
const stats = getStats();
stats.totalRaces = (stats.totalRaces || 0) + 1;
saveStats(stats);
return { success: true, data: raceRecord };
} catch (error) {
return { success: false, error: error.message };
}
},
// DELETE /api/delete_car/:carId
async deleteCar(userId, carId) {
try {
const db = getDB();
db.garage = db.garage.filter(car => car.id !== carId || car.user_id !== userId);
saveDB(db);
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
},
// GET /api/stats/:userId
async getUserStats(userId) {
try {
const db = getDB();
const userCars = db.garage.filter(car => car.user_id === userId).length;
const userRaces = db.raceHistory.filter(race => race.user_id === userId).length;
return {
success: true,
data: {
totalCars: userCars,
totalRaces: userRaces
}
};
} catch (error) {
return { success: false, error: error.message };
}
}
};
// ============================================
// UI STATE
// ============================================
const USER_SESSION_ID = "SESSION_" + Math.random().toString(36).substr(2, 9);
let garage = [];
let racing = false;
let carPositions = [0, 0, 0, 0];
let raceInterval = null;
// Toast notification system
function showToast(message, type = 'info') {
const container = document.getElementById('toast-container');
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.textContent = message;
container.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
}
// ============================================
// NAVIGATION
// ============================================
function navigateTo(pageId) {
document.querySelectorAll('.page').forEach(page => {
page.classList.remove('active');
});
document.getElementById(pageId).classList.add('active');
document.querySelectorAll('.nav-btn').forEach(btn => {
btn.classList.remove('active');
if (btn.dataset.page === pageId) {
btn.classList.add('active');
}
});
if (pageId === 'garage') {
fetchGarage();
updateStats();
}
}
document.querySelectorAll('.nav-btn').forEach(btn => {
btn.addEventListener('click', () => {
navigateTo(btn.dataset.page);
});
});
// ============================================
// GARAGE FUNCTIONS
// ============================================
async function fetchGarage() {
const result = await API.getGarage(USER_SESSION_ID);
if (result.success) {
garage = result.data.reverse();
} else {
// Fallback demo data
garage = [
{ id: 1, car_data: 'CYBER-X7', created_at: new Date().toISOString() },
{ id: 2, car_data: 'NEON-STORM', created_at: new Date().toISOString() },
{ id: 3, car_data: 'PHANTOM-GT', created_at: new Date().toISOString() }
];
}
renderGarage();
}
function renderGarage() {
const grid = document.getElementById('garage-grid');
const empty = document.getElementById('garage-empty');
if (garage.length === 0) {
empty.style.display = 'block';
grid.innerHTML = '';
return;
}
empty.style.display = 'none';
grid.innerHTML = garage.map(car => `
<div class="gr-block">
<img src="https://image.pollinations.ai/prompt/cyberpunk%20car%20${car.car_data}?seed=${car.id}&width=400&height=300&nologo=true"
class="car-img"
onerror="this.src='https://images.unsplash.com/photo-1617788138017-80ad40651399?w=400&h=300&fit=crop'"
alt="${car.car_data}">
<div class="car-info">${car.car_data}</div>
</div>
`).join('');
}
async function generateCar() {
const btn = document.querySelector('#garage-empty .action-btn');
const originalText = btn.textContent;
btn.textContent = 'GENERATING...';
btn.disabled = true;
const seed = Math.floor(Math.random() * 1000000);
const newCarID = `UNIT-${seed.toString(16).toUpperCase()}`;
const result = await API.addCar(USER_SESSION_ID, newCarID);
if (result.success) {
showToast(`UNIT ${newCarID} SAVED TO DATABASE`, 'success');
await fetchGarage();
updateStats();
} else {
// Demo fallback
garage.unshift({
id: Date.now(),
car_data: newCarID,
created_at: new Date().toISOString()
});
renderGarage();
updateStats();
showToast(`UNIT ${newCarID