871 lines
32 KiB
HTML
871 lines
32 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Guess the Price – Fortnite Skin Preise raten</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=Outfit:wght@300;400;600;800&family=Space+Grotesk:wght@400;700&display=swap" rel="stylesheet">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<style>
|
||
@font-face {
|
||
font-family: "FortniteFont";
|
||
src: url("Fortnite.ttf") format("truetype");
|
||
font-weight: normal; font-style: normal; font-display: swap;
|
||
}
|
||
:root {
|
||
--bg-main: #060409;
|
||
--bg-surface: rgba(18, 12, 28, 0.55);
|
||
--bg-surface-solid: #120c1c;
|
||
--border-light: rgba(255, 255, 255, 0.08);
|
||
--text-primary: #f8fafc;
|
||
--text-secondary: #94a3b8;
|
||
--text-muted: #64748b;
|
||
--color-accent: #c5ff26;
|
||
--color-purple: #8b5cf6;
|
||
--color-cyan: #06b6d4;
|
||
--color-yes: #22c55e;
|
||
--color-no: #ef4444;
|
||
--font-sans: "Outfit", sans-serif;
|
||
--font-mono: "Space Grotesk", sans-serif;
|
||
--font-display: "FortniteFont", "Space Grotesk", sans-serif;
|
||
--shadow-cyan: 0 0 20px rgba(6, 182, 212, 0.3);
|
||
--transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
--transition-bounce: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||
}
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body {
|
||
font-family: var(--font-sans);
|
||
background-color: var(--bg-main);
|
||
color: var(--text-primary);
|
||
overflow-x: hidden;
|
||
min-height: 100vh;
|
||
display: flex;
|
||
justify-content: center;
|
||
position: relative;
|
||
}
|
||
.stars-bg {
|
||
position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
|
||
background-image:
|
||
radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 40px),
|
||
radial-gradient(white, rgba(255,255,255,.15) 1px, transparent 30px),
|
||
radial-gradient(white, rgba(255,255,255,.1) 2px, transparent 40px);
|
||
background-size: 550px 550px, 350px 350px, 250px 250px;
|
||
background-position: 0 0, 40px 60px, 130px 270px;
|
||
opacity: .12; z-index: -2; pointer-events: none;
|
||
}
|
||
.nebula-bg {
|
||
position: fixed; top: -20%; left: -10%; width: 140vw; height: 140vh;
|
||
background:
|
||
radial-gradient(circle at 30% 20%, rgba(6,182,212,.16) 0%, transparent 42%),
|
||
radial-gradient(circle at 70% 60%, rgba(139,92,246,.13) 0%, transparent 45%),
|
||
radial-gradient(circle at 50% 85%, rgba(197,255,38,.05) 0%, transparent 35%);
|
||
filter: blur(80px); z-index: -1; pointer-events: none;
|
||
}
|
||
.app-container {
|
||
width: 100%;
|
||
max-width: 900px;
|
||
min-height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 1.5rem;
|
||
position: relative;
|
||
z-index: 10;
|
||
}
|
||
|
||
/* HEADER */
|
||
.app-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 1rem 0 1.5rem;
|
||
border-bottom: 1px solid var(--border-light);
|
||
margin-bottom: 1.75rem;
|
||
gap: 1rem;
|
||
}
|
||
.logo {
|
||
font-family: var(--font-mono);
|
||
font-weight: 800;
|
||
font-size: 1.6rem;
|
||
letter-spacing: -.05em;
|
||
user-select: none;
|
||
}
|
||
.logo-accent { color: var(--text-primary); }
|
||
.logo-main {
|
||
color: var(--color-cyan);
|
||
text-shadow: 0 0 10px rgba(6,182,212,.5);
|
||
}
|
||
.btn-home {
|
||
background: #ffffff0d;
|
||
color: var(--text-primary);
|
||
border: 1px solid var(--border-light);
|
||
padding: 0.5rem 1rem;
|
||
font-size: 0.8rem;
|
||
font-weight: 700;
|
||
border-radius: 30px;
|
||
cursor: pointer;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: .5rem;
|
||
transition: var(--transition-smooth);
|
||
text-transform: uppercase;
|
||
letter-spacing: .05em;
|
||
}
|
||
.btn-home:hover {
|
||
background: #ffffff1a;
|
||
border-color: var(--color-cyan);
|
||
box-shadow: var(--shadow-cyan);
|
||
}
|
||
|
||
/* HUD */
|
||
.game-hud {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
background: #0003;
|
||
border: 1px solid var(--border-light);
|
||
border-radius: 16px;
|
||
padding: 0.9rem 1.25rem;
|
||
margin-bottom: 1.5rem;
|
||
backdrop-filter: blur(8px);
|
||
gap: 1rem;
|
||
flex-wrap: wrap;
|
||
}
|
||
.hud-stat {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: .2rem;
|
||
min-width: 70px;
|
||
}
|
||
.hud-stat .label {
|
||
font-size: .7rem;
|
||
font-weight: 600;
|
||
color: var(--text-muted);
|
||
text-transform: uppercase;
|
||
letter-spacing: .08em;
|
||
}
|
||
.hud-stat .value {
|
||
font-family: var(--font-mono);
|
||
font-size: 1.35rem;
|
||
font-weight: 700;
|
||
}
|
||
.value-score { color: var(--color-cyan); }
|
||
.value-streak { color: var(--color-accent); }
|
||
.value-acc { color: var(--color-purple); }
|
||
.hud-divider { width: 1px; align-self: stretch; background: var(--border-light); }
|
||
|
||
/* CARD */
|
||
.card-container {
|
||
display: flex;
|
||
justify-content: center;
|
||
flex-grow: 1;
|
||
}
|
||
.price-card {
|
||
background: var(--bg-surface);
|
||
backdrop-filter: blur(16px);
|
||
border: 1px solid var(--border-light);
|
||
border-radius: 24px;
|
||
width: 100%;
|
||
max-width: 980px;
|
||
padding: 1.75rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 1.25rem;
|
||
box-shadow: 0 20px 40px #0006;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.price-card::before {
|
||
content: "";
|
||
position: absolute; top: 0; left: 0; width: 100%; height: 4px;
|
||
background: linear-gradient(90deg, var(--color-cyan), var(--color-purple));
|
||
}
|
||
|
||
/* Querformat: Bild links, Antworten rechts */
|
||
.play-area {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
|
||
gap: 1.75rem;
|
||
align-items: stretch;
|
||
}
|
||
.stage-col {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 1rem;
|
||
}
|
||
.answer-col {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
gap: .75rem;
|
||
}
|
||
|
||
.card-top {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
|
||
gap: 1.75rem;
|
||
align-items: center;
|
||
min-height: 44px;
|
||
}
|
||
.card-top-right {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: .75rem;
|
||
}
|
||
.round-tag {
|
||
font-family: var(--font-mono);
|
||
font-size: .8rem;
|
||
font-weight: 700;
|
||
color: var(--text-muted);
|
||
letter-spacing: .05em;
|
||
}
|
||
.rarity-tag {
|
||
font-size: .75rem;
|
||
font-weight: 800;
|
||
text-transform: uppercase;
|
||
letter-spacing: .06em;
|
||
padding: .35rem .8rem;
|
||
border-radius: 99px;
|
||
opacity: 0;
|
||
transition: opacity .35s ease;
|
||
border: 1px solid transparent;
|
||
}
|
||
.rarity-tag.revealed { opacity: 1; }
|
||
|
||
.image-stage {
|
||
width: 100%;
|
||
flex: 1 1 auto;
|
||
min-height: 340px;
|
||
background: radial-gradient(circle at 50% 40%, #1a1030, #09060f 75%);
|
||
border-radius: 18px;
|
||
overflow: hidden;
|
||
position: relative;
|
||
border: 2px solid rgba(255,255,255,.08);
|
||
box-shadow: inset 0 0 20px #000a;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding: .5rem;
|
||
transition: box-shadow .4s ease, border-color .4s ease;
|
||
}
|
||
.image-stage.reveal-glow {
|
||
border-color: var(--reveal-color, var(--color-cyan));
|
||
box-shadow: inset 0 0 20px #000a, 0 0 30px 2px var(--reveal-glow, rgba(6,182,212,.4));
|
||
}
|
||
.image-stage img {
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
width: auto;
|
||
height: auto;
|
||
object-fit: contain;
|
||
filter: drop-shadow(0 8px 20px rgba(0,0,0,.5));
|
||
}
|
||
.image-fallback {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 1rem;
|
||
color: var(--text-muted);
|
||
}
|
||
.image-fallback i { font-size: 3rem; color: var(--color-purple); }
|
||
.image-fallback span { font-size: .85rem; }
|
||
|
||
.skin-name {
|
||
font-size: 1.5rem;
|
||
font-weight: 800;
|
||
text-align: center;
|
||
line-height: 1.2;
|
||
}
|
||
.skin-set {
|
||
font-size: .85rem;
|
||
color: var(--text-secondary);
|
||
text-align: center;
|
||
margin-top: -0.25rem;
|
||
}
|
||
.skin-set .set-pill {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: .4rem;
|
||
background: #ffffff08;
|
||
border: 1px solid var(--border-light);
|
||
padding: .25rem .7rem;
|
||
border-radius: 99px;
|
||
}
|
||
|
||
.prompt {
|
||
font-size: 1rem;
|
||
text-transform: uppercase;
|
||
font-weight: 700;
|
||
letter-spacing: .06em;
|
||
color: var(--text-secondary);
|
||
text-align: left;
|
||
margin-bottom: .25rem;
|
||
}
|
||
|
||
/* PRICE BUTTONS — untereinander, rechts neben dem Bild */
|
||
.price-grid {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: .6rem;
|
||
}
|
||
.price-btn {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
gap: .85rem;
|
||
padding: .95rem 1.1rem;
|
||
border-radius: 14px;
|
||
border: 1px solid var(--border-light);
|
||
background: #ffffff08;
|
||
color: var(--text-primary);
|
||
cursor: pointer;
|
||
transition: var(--transition-bounce);
|
||
font-family: var(--font-sans);
|
||
text-align: left;
|
||
}
|
||
.price-btn:hover:not(:disabled) {
|
||
transform: translateX(4px);
|
||
border-color: var(--color-cyan);
|
||
background: #06b6d414;
|
||
box-shadow: var(--shadow-cyan);
|
||
}
|
||
.price-btn:disabled { cursor: default; }
|
||
.price-btn .vb-key {
|
||
width: 28px;
|
||
height: 28px;
|
||
flex-shrink: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 50%;
|
||
background: #ffffff0d;
|
||
border: 1px solid var(--border-light);
|
||
font-family: var(--font-mono);
|
||
font-size: .8rem;
|
||
font-weight: 700;
|
||
color: var(--text-muted);
|
||
}
|
||
.price-btn .vbucks {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: .4rem;
|
||
font-family: var(--font-mono);
|
||
font-size: 1.15rem;
|
||
font-weight: 700;
|
||
color: var(--text-primary);
|
||
}
|
||
.price-btn .vbucks img { width: 18px; height: 18px; }
|
||
.price-btn .euro {
|
||
margin-left: auto;
|
||
font-family: var(--font-mono);
|
||
font-size: 1.15rem;
|
||
font-weight: 700;
|
||
color: var(--color-accent);
|
||
}
|
||
.price-btn.correct {
|
||
border-color: var(--color-yes);
|
||
background: #22c55e1f;
|
||
box-shadow: 0 0 22px rgba(34,197,94,.45);
|
||
}
|
||
.price-btn.correct .vbucks, .price-btn.correct .euro { color: var(--color-yes); }
|
||
.price-btn.wrong {
|
||
border-color: var(--color-no);
|
||
background: #ef44441f;
|
||
box-shadow: 0 0 22px rgba(239,68,68,.4);
|
||
}
|
||
.price-btn.wrong .vbucks, .price-btn.wrong .euro { color: var(--color-no); }
|
||
.price-btn.dimmed { opacity: .4; }
|
||
|
||
/* FEEDBACK BAR */
|
||
.feedback-bar {
|
||
display: none;
|
||
flex-direction: column;
|
||
gap: 1rem;
|
||
background: #ffffff06;
|
||
border: 1px solid var(--border-light);
|
||
border-radius: 16px;
|
||
padding: 1.25rem;
|
||
animation: slideUp .35s ease;
|
||
}
|
||
.feedback-bar.active { display: flex; }
|
||
@keyframes slideUp { from { opacity: 0; transform: translateY(12px);} to {opacity:1; transform: translateY(0);} }
|
||
.feedback-head {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: .75rem;
|
||
font-size: 1.2rem;
|
||
font-weight: 800;
|
||
}
|
||
.feedback-head i { font-size: 1.5rem; }
|
||
.feedback-correct .feedback-head { color: var(--color-yes); }
|
||
.feedback-wrong .feedback-head { color: var(--color-no); }
|
||
.reveal-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: .75rem;
|
||
}
|
||
.reveal-box {
|
||
background: #0004;
|
||
border: 1px solid var(--border-light);
|
||
border-radius: 12px;
|
||
padding: .9rem 1rem;
|
||
text-align: center;
|
||
}
|
||
.reveal-box .rl {
|
||
font-size: .7rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: .06em;
|
||
color: var(--text-muted);
|
||
font-weight: 700;
|
||
margin-bottom: .3rem;
|
||
}
|
||
.reveal-box .rv {
|
||
font-family: var(--font-mono);
|
||
font-size: 1.35rem;
|
||
font-weight: 700;
|
||
}
|
||
.rv-vbucks { color: var(--color-cyan); display:flex; align-items:center; justify-content:center; gap:.35rem; }
|
||
.rv-vbucks img { width: 18px; height: 18px; }
|
||
.rv-euro { color: var(--color-accent); }
|
||
.euro-note {
|
||
font-size: .8rem;
|
||
color: var(--text-secondary);
|
||
text-align: center;
|
||
line-height: 1.5;
|
||
}
|
||
.euro-note strong { color: var(--text-primary); }
|
||
|
||
.btn-next-top {
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: .5rem;
|
||
padding: .55rem 1.1rem;
|
||
border-radius: 10px;
|
||
border: none;
|
||
cursor: pointer;
|
||
background: var(--color-cyan);
|
||
color: #001014;
|
||
box-shadow: var(--shadow-cyan);
|
||
font-family: var(--font-sans);
|
||
font-weight: 700;
|
||
font-size: .8rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: .05em;
|
||
white-space: nowrap;
|
||
transition: var(--transition-bounce);
|
||
position: fixed;
|
||
top: 18px;
|
||
right: 22px;
|
||
z-index: 250;
|
||
}
|
||
.btn-next-top.active { display: inline-flex; animation: slideUp .3s ease; }
|
||
.btn-next-top:hover { transform: translateY(-2px); box-shadow: 0 0 30px rgba(6,182,212,.6); }
|
||
|
||
footer {
|
||
margin-top: 1.5rem;
|
||
padding-top: 1rem;
|
||
color: var(--text-muted);
|
||
font-size: .8rem;
|
||
text-align: center;
|
||
border-top: 1px solid var(--border-light);
|
||
}
|
||
footer kbd {
|
||
font-family: var(--font-mono);
|
||
background: #ffffff0d;
|
||
border: 1px solid var(--border-light);
|
||
border-radius: 5px;
|
||
padding: .1rem .4rem;
|
||
font-size: .75rem;
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
@media (max-width: 820px) {
|
||
.play-area { grid-template-columns: 1fr; }
|
||
.image-stage { min-height: 260px; }
|
||
.reveal-grid { grid-template-columns: 1fr; }
|
||
.hud-divider { display: none; }
|
||
.btn-next-top {
|
||
top: 12px;
|
||
right: 12px;
|
||
font-size: .74rem;
|
||
padding: .5rem .9rem;
|
||
}
|
||
}
|
||
|
||
/* ===== FORTNITE-MENÜ-LOOK ===== */
|
||
.logo, .skin-name, .btn-home, .btn-next-top, .label,
|
||
h1, h2, h3 {
|
||
font-family: var(--font-display);
|
||
}
|
||
.logo, .skin-name, h1, h2 {
|
||
text-transform: uppercase;
|
||
font-weight: 400;
|
||
letter-spacing: .02em;
|
||
}
|
||
.btn-home, .btn-next-top {
|
||
text-transform: uppercase;
|
||
font-weight: 400;
|
||
letter-spacing: .05em;
|
||
}
|
||
.btn-home:hover { filter: brightness(1.1); }
|
||
.btn-next-top:hover { filter: brightness(1.1); }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="stars-bg"></div>
|
||
<div class="nebula-bg"></div>
|
||
|
||
<div class="app-container">
|
||
<!-- HEADER -->
|
||
<header class="app-header">
|
||
<button class="btn-home" onclick="location.href='index.html'">
|
||
<i class="fa-solid fa-house"></i> Hauptmenü
|
||
</button>
|
||
<div class="logo">
|
||
<span class="logo-accent">GUESS THE</span>
|
||
<span class="logo-main">PRICE</span>
|
||
</div>
|
||
<button class="btn-home" onclick="location.href='collab_game.html'">
|
||
<i class="fa-solid fa-globe"></i> Collab-Spiel
|
||
</button>
|
||
</header>
|
||
|
||
<!-- HUD -->
|
||
<div class="game-hud">
|
||
<div class="hud-stat">
|
||
<span class="label">Runde</span>
|
||
<span class="value" id="hud-round" style="color:var(--text-primary)">1</span>
|
||
</div>
|
||
<div class="hud-divider"></div>
|
||
<div class="hud-stat">
|
||
<span class="label">Richtig</span>
|
||
<span class="value value-score" id="hud-score">0</span>
|
||
</div>
|
||
<div class="hud-divider"></div>
|
||
<div class="hud-stat">
|
||
<span class="label">Serie</span>
|
||
<span class="value value-streak" id="hud-streak">0</span>
|
||
</div>
|
||
<div class="hud-divider"></div>
|
||
<div class="hud-stat">
|
||
<span class="label">Beste Serie</span>
|
||
<span class="value value-streak" id="hud-best" style="opacity:.75">0</span>
|
||
</div>
|
||
<div class="hud-divider"></div>
|
||
<div class="hud-stat">
|
||
<span class="label">Trefferquote</span>
|
||
<span class="value value-acc" id="hud-acc">–</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- CARD -->
|
||
<div class="card-container">
|
||
<div class="price-card">
|
||
<div class="card-top">
|
||
<span class="round-tag" id="round-tag">Skin #1</span>
|
||
<div class="card-top-right">
|
||
<button class="btn-next-top" id="btn-next">
|
||
Nächster Skin <i class="fa-solid fa-arrow-right"></i>
|
||
</button>
|
||
<span class="rarity-tag" id="rarity-tag">Epic</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="play-area">
|
||
<!-- LINKS: Skin-Bild + Name -->
|
||
<div class="stage-col">
|
||
<div class="image-stage" id="image-stage">
|
||
<img id="skin-image" src="" alt="Skin" style="display:none;">
|
||
<div class="image-fallback" id="image-fallback">
|
||
<i class="fa-solid fa-user-astronaut"></i>
|
||
<span>Bild wird geladen…</span>
|
||
</div>
|
||
</div>
|
||
<h2 class="skin-name" id="skin-name">Skin-Name</h2>
|
||
<div class="skin-set" id="skin-set"></div>
|
||
</div>
|
||
|
||
<!-- RECHTS: Preise untereinander -->
|
||
<div class="answer-col">
|
||
<p class="prompt" id="prompt">Was kostet dieser Skin?</p>
|
||
<div class="price-grid" id="price-grid">
|
||
<!-- Buttons via JS -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- FEEDBACK -->
|
||
<div class="feedback-bar" id="feedback-bar">
|
||
<div class="feedback-head" id="feedback-head">
|
||
<i class="fa-solid fa-circle-check"></i>
|
||
<span id="feedback-title">Richtig!</span>
|
||
</div>
|
||
<div class="reveal-grid">
|
||
<div class="reveal-box">
|
||
<div class="rl">Echter Preis</div>
|
||
<div class="rv rv-vbucks">
|
||
<img src="https://fortnite-api.com/images/vbuck.png" alt="V" onerror="this.style.display='none'">
|
||
<span id="reveal-vbucks">1500</span>
|
||
</div>
|
||
</div>
|
||
<div class="reveal-box">
|
||
<div class="rl">In echtem Geld</div>
|
||
<div class="rv rv-euro" id="reveal-euro">13,49 €</div>
|
||
</div>
|
||
</div>
|
||
<p class="euro-note" id="euro-note"></p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<footer>
|
||
Tipp: Nutze die Tasten <kbd>1</kbd>–<kbd>5</kbd> zum Tippen und <kbd>Enter</kbd> für weiter ·
|
||
Umrechnung: 1.000 V-Bucks ≈ 8,99 €
|
||
</footer>
|
||
</div>
|
||
|
||
<!-- Skin-Datenbank -->
|
||
<script src="skins.js"></script>
|
||
<script>
|
||
// ---- Konfiguration ----
|
||
const EUR_PER_1000_VBUCKS = 8.99; // kleinstes Bundle
|
||
const RECENT_WINDOW = 50; // frühestens nach 50 Skins Wiederholung
|
||
const TIERS = [500, 800, 1200, 1500, 2000];
|
||
// Gewichtung: Common (500) seltener, Rest gleich
|
||
const TIER_WEIGHTS = { 500: 16, 800: 21, 1200: 21, 1500: 21, 2000: 21 };
|
||
const TIER_COLORS = {
|
||
500: { c: "#8a94a6", g: "rgba(138,148,166,.4)", name: "Common" },
|
||
800: { c: "#4ade80", g: "rgba(74,222,128,.4)", name: "Uncommon" },
|
||
1200: { c: "#38bdf8", g: "rgba(56,189,248,.4)", name: "Rare" },
|
||
1500: { c: "#b13afe", g: "rgba(177,58,254,.4)", name: "Epic" },
|
||
2000: { c: "#ff8a1e", g: "rgba(255,138,30,.45)", name: "Legendary" }
|
||
};
|
||
|
||
// ---- Datenaufbereitung ----
|
||
const DATA = (typeof SKINS !== "undefined" && Array.isArray(SKINS)) ? SKINS : [];
|
||
DATA.forEach((s, i) => { s._id = i; });
|
||
const byTier = {};
|
||
TIERS.forEach(t => byTier[t] = []);
|
||
DATA.forEach(s => { if (byTier[s.price]) byTier[s.price].push(s); });
|
||
// Falls eine Kategorie leer ist, aus Gewichtung entfernen
|
||
const activeTiers = TIERS.filter(t => byTier[t].length > 0);
|
||
|
||
// ---- Zustand ----
|
||
const recentQueue = [];
|
||
const recentSet = new Set();
|
||
let current = null;
|
||
let round = 0;
|
||
let score = 0;
|
||
let attempts = 0;
|
||
let streak = 0;
|
||
let best = 0;
|
||
let answered = false;
|
||
|
||
// ---- Hilfsfunktionen ----
|
||
function euroStr(vbucks) {
|
||
const eur = vbucks / 1000 * EUR_PER_1000_VBUCKS;
|
||
return eur.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' });
|
||
}
|
||
function vbStr(vbucks) {
|
||
return vbucks.toLocaleString('de-DE');
|
||
}
|
||
function pickTier() {
|
||
const total = activeTiers.reduce((a, t) => a + (TIER_WEIGHTS[t] || 0), 0);
|
||
let r = Math.random() * total;
|
||
for (const t of activeTiers) {
|
||
r -= (TIER_WEIGHTS[t] || 0);
|
||
if (r < 0) return t;
|
||
}
|
||
return activeTiers[activeTiers.length - 1];
|
||
}
|
||
function pickSkin() {
|
||
const tier = pickTier();
|
||
let pool = byTier[tier].filter(s => !recentSet.has(s._id));
|
||
if (pool.length === 0) pool = DATA.filter(s => !recentSet.has(s._id));
|
||
if (pool.length === 0) pool = DATA;
|
||
const skin = pool[Math.floor(Math.random() * pool.length)];
|
||
recentQueue.push(skin._id);
|
||
recentSet.add(skin._id);
|
||
if (recentQueue.length > RECENT_WINDOW) {
|
||
recentSet.delete(recentQueue.shift());
|
||
}
|
||
return skin;
|
||
}
|
||
|
||
// ---- DOM ----
|
||
const el = {
|
||
grid: document.getElementById('price-grid'),
|
||
img: document.getElementById('skin-image'),
|
||
fallback: document.getElementById('image-fallback'),
|
||
stage: document.getElementById('image-stage'),
|
||
name: document.getElementById('skin-name'),
|
||
set: document.getElementById('skin-set'),
|
||
roundTag: document.getElementById('round-tag'),
|
||
rarityTag: document.getElementById('rarity-tag'),
|
||
prompt: document.getElementById('prompt'),
|
||
feedback: document.getElementById('feedback-bar'),
|
||
fHead: document.getElementById('feedback-head'),
|
||
fTitle: document.getElementById('feedback-title'),
|
||
revVbucks: document.getElementById('reveal-vbucks'),
|
||
revEuro: document.getElementById('reveal-euro'),
|
||
euroNote: document.getElementById('euro-note'),
|
||
btnNext: document.getElementById('btn-next'),
|
||
hudRound: document.getElementById('hud-round'),
|
||
hudScore: document.getElementById('hud-score'),
|
||
hudStreak: document.getElementById('hud-streak'),
|
||
hudBest: document.getElementById('hud-best'),
|
||
hudAcc: document.getElementById('hud-acc')
|
||
};
|
||
|
||
// Preis-Buttons einmalig bauen
|
||
const priceButtons = {};
|
||
TIERS.forEach(price => {
|
||
const btn = document.createElement('button');
|
||
btn.className = 'price-btn';
|
||
btn.dataset.price = price;
|
||
btn.innerHTML =
|
||
'<span class="vb-key">' + (TIERS.indexOf(price) + 1) + '</span>' +
|
||
'<span class="vbucks"><img src="https://fortnite-api.com/images/vbuck.png" alt="V" onerror="this.style.display=\'none\'">' + vbStr(price) + '</span>' +
|
||
'<span class="euro">' + euroStr(price) + '</span>';
|
||
btn.addEventListener('click', () => onGuess(price));
|
||
el.grid.appendChild(btn);
|
||
priceButtons[price] = btn;
|
||
});
|
||
|
||
function updateHud() {
|
||
el.hudRound.textContent = round;
|
||
el.hudScore.textContent = score;
|
||
el.hudStreak.textContent = streak;
|
||
el.hudBest.textContent = best;
|
||
el.hudAcc.textContent = attempts ? Math.round(score / attempts * 100) + '%' : '–';
|
||
}
|
||
|
||
function loadRound() {
|
||
answered = false;
|
||
round++;
|
||
current = pickSkin();
|
||
|
||
// Reset Buttons
|
||
Object.values(priceButtons).forEach(b => {
|
||
b.className = 'price-btn';
|
||
b.disabled = false;
|
||
});
|
||
|
||
// Bild
|
||
el.img.style.display = 'none';
|
||
el.fallback.style.display = 'flex';
|
||
el.fallback.querySelector('span').textContent = 'Bild wird geladen…';
|
||
el.img.onload = () => { el.img.style.display = 'block'; el.fallback.style.display = 'none'; };
|
||
el.img.onerror = () => {
|
||
el.img.style.display = 'none';
|
||
el.fallback.style.display = 'flex';
|
||
el.fallback.querySelector('span').textContent = current.name;
|
||
};
|
||
el.img.src = current.image || '';
|
||
|
||
// Texte
|
||
el.name.textContent = current.name;
|
||
el.roundTag.textContent = 'Skin #' + round;
|
||
if (current.set) {
|
||
el.set.innerHTML = '<span class="set-pill"><i class="fa-solid fa-layer-group"></i> ' + current.set + '</span>';
|
||
} else {
|
||
el.set.innerHTML = '';
|
||
}
|
||
|
||
// Rarity versteckt (Hard Mode)
|
||
el.rarityTag.className = 'rarity-tag';
|
||
el.rarityTag.textContent = '';
|
||
el.stage.classList.remove('reveal-glow');
|
||
el.prompt.textContent = 'Was kostet dieser Skin?';
|
||
|
||
// Feedback aus, Next-Button verstecken
|
||
el.feedback.className = 'feedback-bar';
|
||
el.btnNext.classList.remove('active');
|
||
updateHud();
|
||
}
|
||
|
||
function onGuess(guessPrice) {
|
||
if (answered) return;
|
||
answered = true;
|
||
attempts++;
|
||
const actual = current.price;
|
||
const correct = guessPrice === actual;
|
||
if (correct) { score++; streak++; best = Math.max(best, streak); }
|
||
else { streak = 0; }
|
||
|
||
// Buttons markieren
|
||
Object.values(priceButtons).forEach(b => {
|
||
b.disabled = true;
|
||
const p = Number(b.dataset.price);
|
||
if (p === actual) b.classList.add('correct');
|
||
else if (p === guessPrice) b.classList.add('wrong');
|
||
else b.classList.add('dimmed');
|
||
});
|
||
|
||
// Rarity enthüllen
|
||
const tc = TIER_COLORS[actual] || TIER_COLORS[1500];
|
||
el.rarityTag.textContent = current.rarity || tc.name;
|
||
el.rarityTag.style.color = tc.c;
|
||
el.rarityTag.style.borderColor = tc.c;
|
||
el.rarityTag.style.background = tc.g.replace('.4', '.12');
|
||
el.rarityTag.classList.add('revealed');
|
||
el.stage.style.setProperty('--reveal-color', tc.c);
|
||
el.stage.style.setProperty('--reveal-glow', tc.g);
|
||
el.stage.classList.add('reveal-glow');
|
||
|
||
// Feedback-Inhalt
|
||
el.feedback.className = 'feedback-bar active ' + (correct ? 'feedback-correct' : 'feedback-wrong');
|
||
el.fHead.querySelector('i').className = correct ? 'fa-solid fa-circle-check' : 'fa-solid fa-circle-xmark';
|
||
if (correct) {
|
||
el.fTitle.textContent = streak >= 3 ? ('Richtig! ' + streak + 'er-Serie 🔥') : 'Richtig!';
|
||
} else {
|
||
el.fTitle.textContent = 'Daneben!';
|
||
}
|
||
el.revVbucks.textContent = vbStr(actual);
|
||
el.revEuro.textContent = euroStr(actual);
|
||
|
||
const diff = Math.abs(guessPrice - actual);
|
||
let note;
|
||
if (correct) {
|
||
note = 'Dieser <strong>' + (current.rarity || tc.name) + '</strong>-Skin kostet <strong>' +
|
||
vbStr(actual) + ' V-Bucks</strong> – das sind rund <strong>' + euroStr(actual) + '</strong> echtes Geld.';
|
||
} else {
|
||
note = 'Tatsächlich ein <strong>' + (current.rarity || tc.name) + '</strong>-Skin für <strong>' +
|
||
vbStr(actual) + ' V-Bucks</strong> (' + euroStr(actual) + '). Du lagst um ' +
|
||
vbStr(diff) + ' V-Bucks daneben.';
|
||
}
|
||
el.euroNote.innerHTML = note;
|
||
|
||
// Top quick-next button sofort einblenden (ohne Scrollen erreichbar)
|
||
el.btnNext.classList.add('active');
|
||
|
||
updateHud();
|
||
}
|
||
|
||
// ---- Steuerung ----
|
||
el.btnNext.addEventListener('click', loadRound);
|
||
document.addEventListener('keydown', (e) => {
|
||
if (!answered && ['1','2','3','4','5'].includes(e.key)) {
|
||
const idx = Number(e.key) - 1;
|
||
if (TIERS[idx] !== undefined) onGuess(TIERS[idx]);
|
||
} else if (answered && (e.key === 'Enter' || e.key === ' ')) {
|
||
e.preventDefault();
|
||
loadRound();
|
||
}
|
||
});
|
||
|
||
// ---- Start ----
|
||
if (DATA.length === 0) {
|
||
el.name.textContent = 'Keine Skin-Daten gefunden';
|
||
el.set.innerHTML = '<span class="set-pill">skins.js konnte nicht geladen werden</span>';
|
||
el.prompt.textContent = 'Bitte skins.js prüfen';
|
||
} else {
|
||
loadRound();
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|