feat: auto LLM feedback runner + problem link + 5xx retry
- Add SubmissionFeedbackRunner: async background queue for auto LLM feedback
- Enqueue feedback generation after each submission in submitProblem()
- Register runner in main.cc with CSP_FEEDBACK_AUTO_RUN env var
- Add problem_title to GET /api/v1/submissions/{id} response
- Frontend: clickable problem link on submission detail page
- Enhance LLM prompt with richer analysis dimensions
- Add 5xx/connection error retry (max 5 attempts) in Python LLM script
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
这个提交包含在:
@@ -1,619 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Minecraft Code Editor</title>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/remixicon/4.6.0/remixicon.min.css" rel="stylesheet">
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'DelaGothicOne';
|
||||
src: url('https://assets-persist.lovart.ai/agent-static-assets/DelaGothicOne-Regular.ttf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'MiSans';
|
||||
src: url('https://assets-persist.lovart.ai/agent-static-assets/MiSans-Regular.ttf');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'PixelCode';
|
||||
src: local('Courier New'), monospace; /* Fallback for code */
|
||||
}
|
||||
|
||||
:root {
|
||||
--mc-wood-light: #A07F53;
|
||||
--mc-wood-dark: #765637;
|
||||
--mc-stone: #757575;
|
||||
--mc-stone-dark: #3b3b3b;
|
||||
--mc-obsidian: #18181F;
|
||||
--mc-grass: #7CB342;
|
||||
--mc-grass-dark: #558B2F;
|
||||
--mc-gold: #FFB300;
|
||||
--mc-gold-dark: #FF8F00;
|
||||
--mc-diamond: #00BCD4;
|
||||
--mc-redstone: #F44336;
|
||||
--mc-text-shadow: 2px 2px 0px #000;
|
||||
--mc-border-light: rgba(255, 255, 255, 0.4);
|
||||
--mc-border-dark: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 1920px;
|
||||
height: 1080px; /* Fixed height for preview, though body usually auto */
|
||||
background-color: #121212;
|
||||
font-family: 'MiSans', sans-serif;
|
||||
color: white;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Minecraft Texture Classes */
|
||||
.bg-wood {
|
||||
background-color: var(--mc-wood-dark);
|
||||
background-image:
|
||||
linear-gradient(90deg, rgba(0,0,0,0.1) 50%, transparent 50%),
|
||||
linear-gradient(rgba(0,0,0,0.1) 50%, transparent 50%);
|
||||
background-size: 4px 4px;
|
||||
box-shadow: inset 0 0 40px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.bg-stone {
|
||||
background-color: var(--mc-stone);
|
||||
background-image:
|
||||
radial-gradient(circle at 2px 2px, rgba(255,255,255,0.1) 1px, transparent 1px),
|
||||
radial-gradient(circle at 10px 10px, rgba(0,0,0,0.1) 2px, transparent 2px);
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
|
||||
.bg-obsidian {
|
||||
background-color: #1a1a24;
|
||||
background-image:
|
||||
repeating-linear-gradient(45deg, rgba(255,255,255,0.02) 0px, rgba(255,255,255,0.02) 1px, transparent 1px, transparent 10px),
|
||||
repeating-linear-gradient(-45deg, rgba(255,255,255,0.02) 0px, rgba(255,255,255,0.02) 1px, transparent 1px, transparent 10px);
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
h1, h2, h3, .mc-font {
|
||||
font-family: 'DelaGothicOne', cursive;
|
||||
letter-spacing: 1px;
|
||||
text-shadow: 2px 2px 0 rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
/* 3D Button Style */
|
||||
.mc-btn {
|
||||
border: 4px solid #000;
|
||||
border-top-color: rgba(255,255,255,0.5);
|
||||
border-left-color: rgba(255,255,255,0.5);
|
||||
border-bottom-color: rgba(0,0,0,0.5);
|
||||
border-right-color: rgba(0,0,0,0.5);
|
||||
padding: 8px 16px;
|
||||
font-family: 'DelaGothicOne', cursive;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
transition: transform 0.1s;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.mc-btn:active {
|
||||
border-top-color: rgba(0,0,0,0.5);
|
||||
border-left-color: rgba(0,0,0,0.5);
|
||||
border-bottom-color: rgba(255,255,255,0.5);
|
||||
border-right-color: rgba(255,255,255,0.5);
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
.btn-green { background-color: var(--mc-grass); color: white; text-shadow: 1px 1px 0 #000; }
|
||||
.btn-gold { background-color: var(--mc-gold); color: #3e2723; text-shadow: none; }
|
||||
.btn-stone { background-color: var(--mc-stone); color: white; }
|
||||
.btn-icon { padding: 8px; }
|
||||
|
||||
/* Scrollbar */
|
||||
::-webkit-scrollbar { width: 12px; height: 12px; }
|
||||
::-webkit-scrollbar-track { background: #2b2b2b; }
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #555;
|
||||
border: 2px solid #2b2b2b;
|
||||
border-top-color: #777;
|
||||
border-left-color: #777;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
.navbar {
|
||||
height: 60px;
|
||||
background-color: #212121;
|
||||
border-bottom: 4px solid #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 24px;
|
||||
gap: 20px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
.nav-logo { font-size: 24px; color: var(--mc-grass); }
|
||||
.nav-item { color: #aaa; text-decoration: none; font-family: 'DelaGothicOne'; font-size: 14px; }
|
||||
.nav-item:hover { color: white; text-decoration: underline; }
|
||||
|
||||
/* Main Layout */
|
||||
.main-container {
|
||||
display: flex;
|
||||
height: calc(100vh - 60px);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Left Panel */
|
||||
.left-panel {
|
||||
width: 40%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: 4px solid #000;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.problem-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 32px;
|
||||
}
|
||||
|
||||
.paper-card {
|
||||
background-color: #FDF5E6; /* Old Lace */
|
||||
color: #333;
|
||||
padding: 24px;
|
||||
border: 4px solid #333;
|
||||
box-shadow: 8px 8px 0 rgba(0,0,0,0.3);
|
||||
margin-bottom: 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.paper-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -4px; left: -4px; right: -4px; bottom: -4px;
|
||||
border: 2px solid #5d4037;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.difficulty-badge {
|
||||
background-color: var(--mc-grass);
|
||||
color: white;
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
border: 2px solid #33691E;
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
font-family: 'DelaGothicOne';
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.code-block-display {
|
||||
background-color: #263238;
|
||||
color: #eceff1;
|
||||
padding: 12px;
|
||||
border-left: 4px solid var(--mc-grass);
|
||||
font-family: 'PixelCode', monospace;
|
||||
margin: 10px 0;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.panel-footer {
|
||||
height: 70px;
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 24px;
|
||||
border-top: 4px solid #3e2723;
|
||||
}
|
||||
|
||||
/* Right Panel */
|
||||
.right-panel {
|
||||
width: 60%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
height: 56px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
border-bottom: 4px solid #000;
|
||||
}
|
||||
|
||||
.toolbar-group {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.code-editor-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.line-numbers {
|
||||
width: 48px;
|
||||
background-color: #121217;
|
||||
color: #546e7a;
|
||||
text-align: right;
|
||||
padding: 16px 8px;
|
||||
font-family: 'PixelCode', monospace;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
user-select: none;
|
||||
border-right: 2px solid #333;
|
||||
}
|
||||
|
||||
.code-area {
|
||||
flex: 1;
|
||||
background-color: transparent;
|
||||
color: #d4d4d4;
|
||||
padding: 16px;
|
||||
font-family: 'PixelCode', monospace;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
overflow: auto;
|
||||
white-space: pre;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Syntax Highlighting Colors */
|
||||
.token-keyword { color: #cc7832; font-weight: bold; }
|
||||
.token-type { color: #e0c46c; }
|
||||
.token-string { color: #6a8759; }
|
||||
.token-comment { color: #808080; font-style: italic; }
|
||||
.token-number { color: #6897bb; }
|
||||
|
||||
.status-bar {
|
||||
height: 32px;
|
||||
background-color: #2d2d2d;
|
||||
border-top: 2px solid #444;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
font-size: 12px;
|
||||
gap: 20px;
|
||||
color: #aaa;
|
||||
font-family: 'PixelCode', monospace;
|
||||
}
|
||||
|
||||
.combo-counter {
|
||||
color: var(--mc-gold);
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* Test Panel */
|
||||
.test-panel {
|
||||
height: 220px;
|
||||
border-top: 4px solid #000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: height 0.3s;
|
||||
}
|
||||
.test-panel.collapsed { height: 40px; }
|
||||
|
||||
.test-header {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
background-color: rgba(0,0,0,0.2);
|
||||
border-bottom: 2px solid #444;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab-btn {
|
||||
padding: 6px 16px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #aaa;
|
||||
cursor: pointer;
|
||||
font-family: 'DelaGothicOne';
|
||||
font-size: 12px;
|
||||
}
|
||||
.tab-btn.active { color: white; border-bottom: 2px solid var(--mc-grass); }
|
||||
|
||||
.test-content {
|
||||
flex: 1;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.test-case-item {
|
||||
flex: 1;
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
border: 2px solid #444;
|
||||
padding: 12px;
|
||||
font-family: 'PixelCode', monospace;
|
||||
font-size: 14px;
|
||||
}
|
||||
.test-case-status { display: flex; justify-content: space-between; margin-bottom: 8px; font-weight: bold; }
|
||||
.status-pass { color: var(--mc-grass); }
|
||||
.status-fail { color: var(--mc-redstone); }
|
||||
|
||||
/* XP Overlay */
|
||||
.xp-overlay {
|
||||
position: absolute;
|
||||
top: 50%; left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 64px;
|
||||
color: #B9F6CA;
|
||||
text-shadow: 4px 4px 0 #1B5E20;
|
||||
font-family: 'DelaGothicOne';
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
@keyframes xpFloat {
|
||||
0% { opacity: 0; transform: translate(-50%, -20%); }
|
||||
20% { opacity: 1; transform: translate(-50%, -50%); }
|
||||
80% { opacity: 1; transform: translate(-50%, -60%); }
|
||||
100% { opacity: 0; transform: translate(-50%, -100%); }
|
||||
}
|
||||
|
||||
.animate-xp { animation: xpFloat 2s ease-out forwards; }
|
||||
|
||||
/* Confetti */
|
||||
.confetti {
|
||||
position: absolute;
|
||||
width: 8px; height: 8px;
|
||||
background: var(--mc-diamond);
|
||||
animation: fall 3s linear forwards;
|
||||
z-index: 99;
|
||||
}
|
||||
@keyframes fall {
|
||||
to { transform: translateY(100vh) rotate(720deg); }
|
||||
}
|
||||
|
||||
/* Select styling */
|
||||
.mc-select {
|
||||
background: var(--mc-stone-dark);
|
||||
border: 2px solid #000;
|
||||
color: white;
|
||||
padding: 4px 8px;
|
||||
font-family: 'PixelCode', monospace;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Top Navigation -->
|
||||
<nav class="navbar bg-stone">
|
||||
<div class="nav-logo mc-font"><i class="ri-box-3-fill"></i> MINECODE</div>
|
||||
<a href="#" class="nav-item">Problems</a>
|
||||
<a href="#" class="nav-item">Contest</a>
|
||||
<a href="#" class="nav-item">Discuss</a>
|
||||
<div style="flex:1"></div>
|
||||
<div class="nav-item" style="color:var(--mc-gold)">LVL 24</div>
|
||||
<img src="https://api.dicebear.com/7.x/pixel-art/svg?seed=Steve" alt="User" style="width: 32px; height: 32px; border: 2px solid white;">
|
||||
</nav>
|
||||
|
||||
<div class="main-container">
|
||||
|
||||
<!-- Left Panel: Problem -->
|
||||
<aside class="left-panel bg-wood">
|
||||
<div class="problem-content">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom: 20px;">
|
||||
<h1 style="font-size: 28px; color: #3E2723;">1. Two Sum</h1>
|
||||
<span class="difficulty-badge">EASY</span>
|
||||
</div>
|
||||
|
||||
<div class="paper-card">
|
||||
<p style="margin-bottom: 16px; line-height: 1.6;">
|
||||
Given an array of integers <code>nums</code> and an integer <code>target</code>, return <i>indices</i> of the two numbers such that they add up to <code>target</code>.
|
||||
</p>
|
||||
<p style="line-height: 1.6;">
|
||||
You may assume that each input would have <strong>exactly one solution</strong>, and you may not use the same element twice.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 24px;">
|
||||
<h3 style="color:#3E2723; margin-bottom:10px;">Example 1:</h3>
|
||||
<div class="code-block-display">Input: nums = [2,7,11,15], target = 9
|
||||
Output: [0,1]
|
||||
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 24px;">
|
||||
<h3 style="color:#3E2723; margin-bottom:10px;">Example 2:</h3>
|
||||
<div class="code-block-display">Input: nums = [3,2,4], target = 6
|
||||
Output: [1,2]</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 24px;">
|
||||
<h3 style="color:#3E2723; margin-bottom:10px; display:flex; align-items:center;">
|
||||
<i class="ri-book-mark-fill" style="margin-right:8px;"></i> Hints
|
||||
</h3>
|
||||
<div style="background: rgba(0,0,0,0.1); padding: 10px; border: 2px dashed #5D4037; color: #3E2723;">
|
||||
Try using a Hash Map to store visited numbers.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-footer">
|
||||
<button class="mc-btn btn-stone"><i class="ri-star-fill"></i> Bookmark</button>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<button class="mc-btn btn-stone btn-icon"><i class="ri-share-forward-fill"></i></button>
|
||||
<button class="mc-btn btn-stone btn-icon"><i class="ri-file-list-3-fill"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Right Panel: Editor -->
|
||||
<main class="right-panel">
|
||||
<!-- Toolbar -->
|
||||
<div class="toolbar bg-stone">
|
||||
<div class="toolbar-group">
|
||||
<select class="mc-select">
|
||||
<option>C++</option>
|
||||
<option>Java</option>
|
||||
<option>Python</option>
|
||||
</select>
|
||||
<button class="mc-btn btn-stone btn-icon" style="padding:4px 8px;"><i class="ri-settings-3-fill"></i></button>
|
||||
<div style="color:#bbb; font-size:12px;">Size: 14px</div>
|
||||
</div>
|
||||
<div class="toolbar-group">
|
||||
<button class="mc-btn btn-green" onclick="runCode()"><i class="ri-play-fill"></i> Run</button>
|
||||
<button class="mc-btn btn-gold" onclick="submitCode()"><i class="ri-upload-cloud-2-fill"></i> Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Code Editor -->
|
||||
<div class="code-editor-wrapper bg-obsidian">
|
||||
<div class="line-numbers">
|
||||
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11
|
||||
</div>
|
||||
<div class="code-area" contenteditable="true" spellcheck="false">
|
||||
<span class="token-keyword">class</span> Solution {
|
||||
<span class="token-keyword">public</span>:
|
||||
<span class="token-type">vector</span><<span class="token-type">int</span>> twoSum(<span class="token-type">vector</span><<span class="token-type">int</span>>& nums, <span class="token-type">int</span> target) {
|
||||
<span class="token-type">unordered_map</span><<span class="token-type">int</span>, <span class="token-type">int</span>> hash;
|
||||
|
||||
<span class="token-keyword">for</span> (<span class="token-type">int</span> i = <span class="token-number">0</span>; i < nums.size(); i++) {
|
||||
<span class="token-type">int</span> complement = target - nums[i];
|
||||
|
||||
<span class="token-keyword">if</span> (hash.find(complement) != hash.end()) {
|
||||
<span class="token-keyword">return</span> {hash[complement], i};
|
||||
}
|
||||
hash[nums[i]] = i;
|
||||
}
|
||||
<span class="token-keyword">return</span> {};
|
||||
}
|
||||
};</div>
|
||||
</div>
|
||||
|
||||
<!-- Status Bar -->
|
||||
<div class="status-bar">
|
||||
<span>Ready</span>
|
||||
<span style="border-left: 1px solid #555; height: 16px;"></span>
|
||||
<span><i class="ri-time-fill"></i> 0ms</span>
|
||||
<span><i class="ri-sd-card-mini-fill"></i> 0KB</span>
|
||||
<div style="flex:1"></div>
|
||||
<div class="combo-counter"><i class="ri-fire-fill"></i> COMBO x5</div>
|
||||
</div>
|
||||
|
||||
<!-- Test Panel -->
|
||||
<div class="test-panel bg-stone" id="testPanel">
|
||||
<div class="test-header" onclick="toggleTestPanel()">
|
||||
<i class="ri-terminal-box-fill" style="margin-right: 10px; color: #ccc;"></i>
|
||||
<span class="mc-font" style="font-size: 14px; color: #eee; flex:1">Test Console</span>
|
||||
<i class="ri-arrow-up-s-line" id="toggleIcon"></i>
|
||||
</div>
|
||||
<div style="background: rgba(0,0,0,0.4); padding: 0 16px; display: flex; border-bottom: 2px solid #444;">
|
||||
<button class="tab-btn active">Test Cases</button>
|
||||
<button class="tab-btn">Result</button>
|
||||
</div>
|
||||
<div class="test-content">
|
||||
<div class="test-case-item">
|
||||
<div class="test-case-status">Case 1 <i class="ri-checkbox-circle-fill status-pass"></i></div>
|
||||
<div style="color: #888; font-size: 12px; margin-bottom: 4px;">Input</div>
|
||||
<div style="color: #fff; margin-bottom: 8px;">nums = [2,7,11,15], target = 9</div>
|
||||
<div style="color: #888; font-size: 12px; margin-bottom: 4px;">Expected</div>
|
||||
<div style="color: #fff;">[0,1]</div>
|
||||
</div>
|
||||
<div class="test-case-item">
|
||||
<div class="test-case-status">Case 2 <i class="ri-checkbox-circle-fill status-pass"></i></div>
|
||||
<div style="color: #888; font-size: 12px; margin-bottom: 4px;">Input</div>
|
||||
<div style="color: #fff; margin-bottom: 8px;">nums = [3,2,4], target = 6</div>
|
||||
<div style="color: #888; font-size: 12px; margin-bottom: 4px;">Expected</div>
|
||||
<div style="color: #fff;">[1,2]</div>
|
||||
</div>
|
||||
<div class="test-case-item" style="border-color: #F44336; opacity: 0.8;">
|
||||
<div class="test-case-status">Case 3 <i class="ri-close-circle-fill status-fail"></i></div>
|
||||
<div style="color: #888; font-size: 12px; margin-bottom: 4px;">Input</div>
|
||||
<div style="color: #fff; margin-bottom: 8px;">nums = [3,3], target = 6</div>
|
||||
<div style="color: #888; font-size: 12px; margin-bottom: 4px;">Expected</div>
|
||||
<div style="color: #fff;">[0,1]</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- XP Animation Overlay -->
|
||||
<div id="xpDisplay" class="xp-overlay">+50 XP</div>
|
||||
|
||||
<script>
|
||||
function toggleTestPanel() {
|
||||
const panel = document.getElementById('testPanel');
|
||||
const icon = document.getElementById('toggleIcon');
|
||||
panel.classList.toggle('collapsed');
|
||||
|
||||
if(panel.classList.contains('collapsed')) {
|
||||
icon.classList.remove('ri-arrow-down-s-line');
|
||||
icon.classList.add('ri-arrow-up-s-line');
|
||||
} else {
|
||||
icon.classList.remove('ri-arrow-up-s-line');
|
||||
icon.classList.add('ri-arrow-down-s-line');
|
||||
}
|
||||
}
|
||||
|
||||
function runCode() {
|
||||
// Simulate running code
|
||||
const btn = document.querySelector('.btn-green');
|
||||
btn.innerHTML = '<i class="ri-loader-4-line ri-spin"></i> Running...';
|
||||
setTimeout(() => {
|
||||
btn.innerHTML = '<i class="ri-play-fill"></i> Run';
|
||||
document.getElementById('testPanel').classList.remove('collapsed');
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function submitCode() {
|
||||
const btn = document.querySelector('.btn-gold');
|
||||
const originalContent = btn.innerHTML;
|
||||
btn.innerHTML = '<i class="ri-loader-4-line ri-spin"></i> ...';
|
||||
|
||||
setTimeout(() => {
|
||||
btn.innerHTML = originalContent;
|
||||
showXP();
|
||||
createConfetti();
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
function showXP() {
|
||||
const xp = document.getElementById('xpDisplay');
|
||||
xp.classList.remove('animate-xp');
|
||||
void xp.offsetWidth; // trigger reflow
|
||||
xp.classList.add('animate-xp');
|
||||
}
|
||||
|
||||
function createConfetti() {
|
||||
const colors = ['#F44336', '#2196F3', '#FFEB3B', '#4CAF50', '#FF9800'];
|
||||
for(let i=0; i<50; i++) {
|
||||
const conf = document.createElement('div');
|
||||
conf.className = 'confetti';
|
||||
conf.style.left = Math.random() * 100 + 'vw';
|
||||
conf.style.top = '-10px';
|
||||
conf.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
|
||||
conf.style.animationDuration = (Math.random() * 2 + 2) + 's';
|
||||
document.body.appendChild(conf);
|
||||
|
||||
setTimeout(() => conf.remove(), 4000);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,905 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=1920, initial-scale=1.0">
|
||||
<title>Minecraft Contest Page</title>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/remixicon/4.6.0/remixicon.min.css" rel="stylesheet">
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
|
||||
|
||||
:root {
|
||||
--mc-bg-dark: #1D1D1D;
|
||||
--mc-obsidian: #141019;
|
||||
--mc-stone: #757575;
|
||||
--mc-wood: #8B6914; /* Oak wood plank approximation */
|
||||
--mc-wood-dark: #5C4033;
|
||||
--mc-grass: #7CB342;
|
||||
--mc-grass-dark: #558B2F;
|
||||
--mc-gold: #FFB300;
|
||||
--mc-redstone: #E53935;
|
||||
--mc-diamond: #40C4FF;
|
||||
--mc-white: #FFFFFF;
|
||||
--mc-text-shadow: 2px 2px 0px #000;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
background-color: #121212;
|
||||
background-image:
|
||||
linear-gradient(45deg, #1a1a1a 25%, transparent 25%, transparent 75%, #1a1a1a 75%, #1a1a1a),
|
||||
linear-gradient(45deg, #1a1a1a 25%, transparent 25%, transparent 75%, #1a1a1a 75%, #1a1a1a);
|
||||
background-size: 40px 40px;
|
||||
background-position: 0 0, 20px 20px;
|
||||
color: var(--mc-white);
|
||||
width: 1920px;
|
||||
margin: 0 auto;
|
||||
overflow-x: hidden;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* --- Utilities --- */
|
||||
.pixel-border {
|
||||
box-shadow:
|
||||
-4px 0 0 0 black,
|
||||
4px 0 0 0 black,
|
||||
0 -4px 0 0 black,
|
||||
0 4px 0 0 black,
|
||||
inset -4px -4px 0 0 rgba(0,0,0,0.5),
|
||||
inset 4px 4px 0 0 rgba(255,255,255,0.2);
|
||||
border: 4px solid transparent;
|
||||
}
|
||||
|
||||
.text-shadow {
|
||||
text-shadow: var(--mc-text-shadow);
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* --- Navigation --- */
|
||||
.navbar {
|
||||
height: 80px;
|
||||
background-color: #333;
|
||||
border-bottom: 4px solid #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 40px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 24px;
|
||||
color: var(--mc-grass);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: #ccc;
|
||||
text-decoration: none;
|
||||
margin-left: 30px;
|
||||
padding: 10px;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
.nav-links a.active {
|
||||
color: var(--mc-gold);
|
||||
text-shadow: 2px 2px 0 #5C4033;
|
||||
}
|
||||
|
||||
/* --- Banner --- */
|
||||
.banner {
|
||||
height: 350px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background: linear-gradient(180deg, #2a0e36 0%, #46142e 100%); /* Nether-ish */
|
||||
background-image: url('https://images.unsplash.com/photo-1628151015968-3a4429e9ef04?q=80&w=2072&auto=format&fit=crop'); /* Pixel art background placeholder */
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: 6px solid #000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.banner-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.6);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.banner-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.live-badge {
|
||||
background-color: var(--mc-redstone);
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
margin-bottom: 20px;
|
||||
animation: pulse 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(229, 57, 53, 0.7); }
|
||||
70% { transform: scale(1.05); box-shadow: 0 0 0 10px rgba(229, 57, 53, 0); }
|
||||
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(229, 57, 53, 0); }
|
||||
}
|
||||
|
||||
.contest-title {
|
||||
font-size: 42px;
|
||||
color: var(--mc-gold);
|
||||
margin-bottom: 20px;
|
||||
-webkit-text-stroke: 2px #5C4033;
|
||||
text-shadow: 4px 4px 0 #000;
|
||||
}
|
||||
|
||||
.countdown {
|
||||
font-size: 36px;
|
||||
color: #fff;
|
||||
margin-bottom: 30px;
|
||||
letter-spacing: 4px;
|
||||
text-shadow: 3px 3px 0 #000;
|
||||
}
|
||||
|
||||
.join-btn {
|
||||
background-color: var(--mc-grass);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 20px 40px;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
transition: transform 0.1s, background-color 0.2s;
|
||||
position: relative;
|
||||
box-shadow: 0 6px 0 #558B2F, 0 10px 10px rgba(0,0,0,0.3);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.join-btn:hover {
|
||||
background-color: #8BC34A;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 0 #558B2F, 0 12px 12px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.join-btn:active {
|
||||
transform: translateY(4px);
|
||||
box-shadow: 0 2px 0 #558B2F, 0 4px 4px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.participants-count {
|
||||
margin-top: 20px;
|
||||
font-size: 14px;
|
||||
color: #ccc;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.player-head {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: #555;
|
||||
display: inline-block;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
/* --- Main Layout --- */
|
||||
.container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 40px;
|
||||
gap: 40px;
|
||||
max-width: 1800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.left-col {
|
||||
flex: 0 0 70%;
|
||||
}
|
||||
|
||||
.right-col {
|
||||
flex: 0 0 30%;
|
||||
}
|
||||
|
||||
/* --- Tab Nav --- */
|
||||
.tabs {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
gap: 10px;
|
||||
}
|
||||
.tab {
|
||||
background-color: #555;
|
||||
padding: 15px 30px;
|
||||
color: #aaa;
|
||||
cursor: pointer;
|
||||
border-bottom: none;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.tab.active {
|
||||
background-color: var(--mc-wood);
|
||||
color: #fff;
|
||||
top: 0;
|
||||
padding-bottom: 19px;
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
box-shadow:
|
||||
-4px 0 0 0 black,
|
||||
4px 0 0 0 black,
|
||||
0 -4px 0 0 black;
|
||||
}
|
||||
|
||||
/* --- Wood Panel Style --- */
|
||||
.wood-panel {
|
||||
background-color: var(--mc-wood);
|
||||
border: 4px solid #000;
|
||||
padding: 20px;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: inset 0 0 0 4px rgba(255,255,255,0.1), 8px 8px 0 rgba(0,0,0,0.5);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wood-texture {
|
||||
/* Simulating wood grain with linear gradients */
|
||||
background-image:
|
||||
linear-gradient(90deg, rgba(0,0,0,0.05) 1px, transparent 1px),
|
||||
linear-gradient(rgba(0,0,0,0.05) 1px, transparent 1px);
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
|
||||
/* --- Contest Cards --- */
|
||||
.contest-card {
|
||||
background-color: #6D4C41; /* Darker wood */
|
||||
margin-bottom: 20px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
transition: transform 0.2s;
|
||||
position: relative;
|
||||
border: 4px solid #3E2723;
|
||||
}
|
||||
|
||||
.contest-card:hover {
|
||||
transform: translateX(10px);
|
||||
background-color: #795548;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background-color: #3E2723;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 30px;
|
||||
color: var(--mc-gold);
|
||||
border: 4px solid #000;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.card-info h3 {
|
||||
color: #fff;
|
||||
margin-bottom: 10px;
|
||||
font-size: 18px;
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
}
|
||||
|
||||
.card-details {
|
||||
font-size: 12px;
|
||||
color: #D7CCC8;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.stars { color: var(--mc-gold); }
|
||||
|
||||
.card-action .btn-small {
|
||||
background-color: var(--mc-stone);
|
||||
border: 2px solid #000;
|
||||
padding: 10px 20px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: 12px;
|
||||
box-shadow: 0 4px 0 #424242;
|
||||
}
|
||||
.card-action .btn-small:hover {
|
||||
background-color: #9E9E9E;
|
||||
margin-top: -2px;
|
||||
box-shadow: 0 6px 0 #424242;
|
||||
}
|
||||
|
||||
/* --- Leaderboard --- */
|
||||
.leaderboard-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.live-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: var(--mc-grass);
|
||||
border-radius: 50%; /* Minecraft has no circles, but for indicator */
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
box-shadow: 0 0 10px var(--mc-grass);
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
|
||||
@keyframes blink { 50% { opacity: 0.5; } }
|
||||
|
||||
.leaderboard-table {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 8px;
|
||||
}
|
||||
|
||||
.leaderboard-table th {
|
||||
text-align: left;
|
||||
padding: 15px;
|
||||
color: #3E2723;
|
||||
font-size: 14px;
|
||||
border-bottom: 4px solid #3E2723;
|
||||
}
|
||||
|
||||
.leaderboard-table td {
|
||||
background-color: #5D4037;
|
||||
padding: 15px;
|
||||
color: #fff;
|
||||
border-top: 4px solid #3E2723;
|
||||
border-bottom: 4px solid #3E2723;
|
||||
}
|
||||
|
||||
.leaderboard-table tr td:first-child { border-left: 4px solid #3E2723; }
|
||||
.leaderboard-table tr td:last-child { border-right: 4px solid #3E2723; }
|
||||
|
||||
.rank-1 td { background-color: #FFECB3; color: #5D4037; border-color: #FFB300 !important; }
|
||||
.rank-2 td { background-color: #F5F5F5; color: #5D4037; border-color: #BDBDBD !important; }
|
||||
.rank-3 td { background-color: #D7CCC8; color: #5D4037; border-color: #8D6E63 !important; }
|
||||
|
||||
.current-user td {
|
||||
background-color: #DCEDC8;
|
||||
color: #33691E;
|
||||
border-color: #7CB342 !important;
|
||||
}
|
||||
|
||||
.medal-icon { margin-right: 5px; }
|
||||
|
||||
/* --- Right Column --- */
|
||||
.info-card {
|
||||
background-color: #424242;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
border: 4px solid #000;
|
||||
box-shadow: 8px 8px 0 rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.info-header {
|
||||
font-size: 18px;
|
||||
margin-bottom: 20px;
|
||||
color: var(--mc-gold);
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
border-bottom: 4px solid #000;
|
||||
padding-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.stat-val { color: var(--mc-diamond); }
|
||||
|
||||
.medals-display {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-top: 15px;
|
||||
justify-content: center;
|
||||
background: #212121;
|
||||
padding: 10px;
|
||||
border: 2px solid #000;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
position: relative;
|
||||
}
|
||||
.timeline-line {
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 20px;
|
||||
bottom: -20px;
|
||||
width: 2px;
|
||||
background: #666;
|
||||
z-index: 0;
|
||||
}
|
||||
.timeline-item:last-child .timeline-line { display: none; }
|
||||
|
||||
.timeline-dot {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: var(--mc-gold);
|
||||
border: 2px solid #000;
|
||||
z-index: 1;
|
||||
margin-right: 15px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
font-size: 12px;
|
||||
}
|
||||
.timeline-date { color: #888; font-size: 10px; margin-bottom: 4px; }
|
||||
.timeline-rank { color: #fff; }
|
||||
|
||||
.collapsible-content {
|
||||
max-height: 500px; /* arbitrary large */
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease-out;
|
||||
}
|
||||
.collapsed .collapsible-content {
|
||||
max-height: 0;
|
||||
}
|
||||
.toggle-btn {
|
||||
cursor: pointer;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/* --- Animations --- */
|
||||
@keyframes shine {
|
||||
0% { background-position: -100px; }
|
||||
40%, 100% { background-position: 140px; }
|
||||
}
|
||||
|
||||
.rank-1 {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Light ray effect using psuedo elements not easy on tr, applied to td */
|
||||
.rank-1 td {
|
||||
background: linear-gradient(120deg, #FFECB3 0%, #FFECB3 40%, #FFF9C4 50%, #FFECB3 60%, #FFECB3 100%);
|
||||
background-size: 200% 100%;
|
||||
animation: shine-gold 3s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes shine-gold {
|
||||
0% { background-position: 200% 0; }
|
||||
100% { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.container { flex-direction: column; }
|
||||
.left-col, .right-col { flex: 1 1 100%; }
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar pixel-border">
|
||||
<div class="logo text-shadow"><i class="ri-sword-fill"></i> ALGO CRAFT</div>
|
||||
<div class="nav-links">
|
||||
<a href="#" class="active">CONTESTS</a>
|
||||
<a href="#">PROBLEMS</a>
|
||||
<a href="#">DISCUSS</a>
|
||||
<a href="#">STORE</a>
|
||||
</div>
|
||||
<div style="display:flex; align-items:center; gap:10px;">
|
||||
<div style="width:32px; height:32px; background:#ddd; border:2px solid #000;">
|
||||
<img src="https://api.dicebear.com/7.x/pixel-art/svg?seed=Felix" alt="User" style="width:100%; height:100%;">
|
||||
</div>
|
||||
<span>STEVE_DEV</span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="banner">
|
||||
<div class="banner-overlay"></div>
|
||||
<div class="banner-content">
|
||||
<div class="live-badge pixel-border">LIVE NOW</div>
|
||||
<h1 class="contest-title">WEEKLY ALGO CHALLENGE #42</h1>
|
||||
<div class="countdown" id="countdown">02:45:30</div>
|
||||
|
||||
<button class="join-btn pixel-border">
|
||||
JOIN CONTEST
|
||||
</button>
|
||||
|
||||
<div class="participants-count">
|
||||
<div class="player-head"></div>
|
||||
<div class="player-head"></div>
|
||||
<div class="player-head"></div>
|
||||
<span>1,234 Crafters Online</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- Left Column -->
|
||||
<div class="left-col">
|
||||
<div class="tabs">
|
||||
<div class="tab active pixel-border" onclick="switchTab('ongoing')">ONGOING</div>
|
||||
<div class="tab pixel-border" onclick="switchTab('upcoming')">UPCOMING</div>
|
||||
<div class="tab pixel-border" onclick="switchTab('finished')">FINISHED</div>
|
||||
</div>
|
||||
|
||||
<div class="wood-panel pixel-border wood-texture" id="contest-list">
|
||||
<!-- Contest Cards -->
|
||||
<div class="contest-card pixel-border">
|
||||
<div class="flex-center">
|
||||
<div class="card-icon pixel-border"><i class="ri-trophy-fill"></i></div>
|
||||
<div class="card-info">
|
||||
<h3>Weekly Challenge #42</h3>
|
||||
<div class="card-details">
|
||||
<span><i class="ri-time-line"></i> Ends in 2h</span>
|
||||
<span><i class="ri-star-fill stars"></i><i class="ri-star-fill stars"></i><i class="ri-star-fill stars"></i></span>
|
||||
<span style="color:#4DB6AC">500 XP</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<button class="btn-small">ENTER</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="contest-card pixel-border">
|
||||
<div class="flex-center">
|
||||
<div class="card-icon pixel-border"><i class="ri-sword-fill" style="color:#CFD8DC"></i></div>
|
||||
<div class="card-info">
|
||||
<h3>Bi-Weekly Rumble #15</h3>
|
||||
<div class="card-details">
|
||||
<span><i class="ri-calendar-line"></i> Sat, 14:00</span>
|
||||
<span><i class="ri-star-fill stars"></i><i class="ri-star-fill stars"></i><i class="ri-star-line"></i></span>
|
||||
<span style="color:#4DB6AC">350 XP</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<button class="btn-small">REGISTER</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="contest-card pixel-border">
|
||||
<div class="flex-center">
|
||||
<div class="card-icon pixel-border"><i class="ri-vip-diamond-fill" style="color:var(--mc-diamond)"></i></div>
|
||||
<div class="card-info">
|
||||
<h3>Diamond League Qualifiers</h3>
|
||||
<div class="card-details">
|
||||
<span><i class="ri-calendar-line"></i> Sun, 10:00</span>
|
||||
<span><i class="ri-star-fill stars"></i><i class="ri-star-fill stars"></i><i class="ri-star-fill stars"></i><i class="ri-star-fill stars"></i></span>
|
||||
<span style="color:#4DB6AC">1000 XP + BADGE</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<button class="btn-small">REGISTER</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Leaderboard -->
|
||||
<div class="wood-panel pixel-border wood-texture">
|
||||
<div class="leaderboard-title">
|
||||
<h2 class="text-shadow" style="color:#3E2723">LEADERBOARD</h2>
|
||||
<div style="font-size: 12px; color: #3E2723; display: flex; align-items: center;">
|
||||
<span class="live-dot"></span> UPDATING LIVE
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="leaderboard-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>PLAYER</th>
|
||||
<th>SCORE</th>
|
||||
<th>TIME</th>
|
||||
<th>STATUS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="leaderboard-body">
|
||||
<!-- JS will populate -->
|
||||
<tr class="rank-1 pixel-border">
|
||||
<td><i class="ri-vip-crown-fill" style="color:#F57F17"></i> 1</td>
|
||||
<td>Notch_Real</td>
|
||||
<td>400</td>
|
||||
<td>00:45:12</td>
|
||||
<td><span style="color:green">AC</span></td>
|
||||
</tr>
|
||||
<tr class="rank-2">
|
||||
<td><i class="ri-medal-fill" style="color:#757575"></i> 2</td>
|
||||
<td>Alex_Pro</td>
|
||||
<td>380</td>
|
||||
<td>00:52:30</td>
|
||||
<td><span style="color:green">AC</span></td>
|
||||
</tr>
|
||||
<tr class="rank-3">
|
||||
<td><i class="ri-medal-fill" style="color:#8D6E63"></i> 3</td>
|
||||
<td>CreeperAwMan</td>
|
||||
<td>350</td>
|
||||
<td>01:05:00</td>
|
||||
<td><span style="color:green">AC</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Enderman_tp</td>
|
||||
<td>320</td>
|
||||
<td>01:10:22</td>
|
||||
<td><span style="color:green">AC</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>RedstoneEng</td>
|
||||
<td>300</td>
|
||||
<td>01:15:45</td>
|
||||
<td><span style="color:green">AC</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td>Miner64</td>
|
||||
<td>280</td>
|
||||
<td>01:20:10</td>
|
||||
<td><span style="color:green">AC</span></td>
|
||||
</tr>
|
||||
<tr class="current-user">
|
||||
<td>7</td>
|
||||
<td>STEVE_DEV (YOU)</td>
|
||||
<td>250</td>
|
||||
<td>01:30:00</td>
|
||||
<td><span style="color:orange">WA (1)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>8</td>
|
||||
<td>ZombieBoi</td>
|
||||
<td>200</td>
|
||||
<td>01:35:12</td>
|
||||
<td><span style="color:green">AC</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Right Column -->
|
||||
<div class="right-col">
|
||||
|
||||
<!-- Stats Card -->
|
||||
<div class="info-card pixel-border">
|
||||
<div class="info-header">
|
||||
<span>MY STATS</span>
|
||||
<i class="ri-bar-chart-fill"></i>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Participated:</span>
|
||||
<span class="stat-val">24</span>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Best Rank:</span>
|
||||
<span class="stat-val">#3 🥉</span>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Total Points:</span>
|
||||
<span class="stat-val">1,250</span>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Rating:</span>
|
||||
<span class="stat-val" style="color:var(--mc-gold)">1650 (Diamond II)</span>
|
||||
</div>
|
||||
|
||||
<div class="medals-display pixel-border">
|
||||
<div style="text-align:center">
|
||||
<i class="ri-medal-fill" style="color:var(--mc-gold); font-size:20px"></i>
|
||||
<div style="font-size:10px">2</div>
|
||||
</div>
|
||||
<div style="text-align:center">
|
||||
<i class="ri-medal-fill" style="color:#BDBDBD; font-size:20px"></i>
|
||||
<div style="font-size:10px">5</div>
|
||||
</div>
|
||||
<div style="text-align:center">
|
||||
<i class="ri-medal-fill" style="color:#8D6E63; font-size:20px"></i>
|
||||
<div style="font-size:10px">8</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rules Card -->
|
||||
<div class="info-card pixel-border" id="rules-card">
|
||||
<div class="info-header">
|
||||
<span>RULES</span>
|
||||
<i class="ri-book-open-fill toggle-btn" onclick="toggleRules()"></i>
|
||||
</div>
|
||||
<div class="collapsible-content" id="rules-content">
|
||||
<ul style="padding-left: 20px; font-size: 12px; line-height: 1.8; color:#ccc;">
|
||||
<li>Duration: 3 Hours</li>
|
||||
<li>Penalty: +5 mins per WA</li>
|
||||
<li>Languages: Java, C++, Python</li>
|
||||
<li>Plagiarism check is ACTIVE</li>
|
||||
<li>Do not break obsidian blocks</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Past Results -->
|
||||
<div class="info-card pixel-border">
|
||||
<div class="info-header">
|
||||
<span>HISTORY</span>
|
||||
<i class="ri-history-line"></i>
|
||||
</div>
|
||||
|
||||
<div class="timeline">
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-line"></div>
|
||||
<div class="timeline-dot"></div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-date">2023-10-15</div>
|
||||
<div class="timeline-rank">Weekly #41 - Rank #15</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-line"></div>
|
||||
<div class="timeline-dot" style="background:#BDBDBD"></div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-date">2023-10-08</div>
|
||||
<div class="timeline-rank">Weekly #40 - Rank #2 🥈</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-line"></div>
|
||||
<div class="timeline-dot" style="background:#8D6E63"></div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-date">2023-10-01</div>
|
||||
<div class="timeline-rank">Weekly #39 - Rank #3 🥉</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-line"></div>
|
||||
<div class="timeline-dot" style="background:#555"></div>
|
||||
<div class="timeline-content">
|
||||
<div class="timeline-date">2023-09-24</div>
|
||||
<div class="timeline-rank">Weekly #38 - Rank #45</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// --- Countdown Timer ---
|
||||
let totalSeconds = 2 * 3600 + 45 * 60 + 30; // 2h 45m 30s
|
||||
const countdownEl = document.getElementById('countdown');
|
||||
|
||||
function updateCountdown() {
|
||||
const h = Math.floor(totalSeconds / 3600);
|
||||
const m = Math.floor((totalSeconds % 3600) / 60);
|
||||
const s = totalSeconds % 60;
|
||||
|
||||
countdownEl.textContent =
|
||||
`${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
|
||||
|
||||
if (totalSeconds > 0) {
|
||||
totalSeconds--;
|
||||
}
|
||||
}
|
||||
setInterval(updateCountdown, 1000);
|
||||
updateCountdown();
|
||||
|
||||
// --- Tabs Functionality ---
|
||||
function switchTab(tabName) {
|
||||
const tabs = document.querySelectorAll('.tab');
|
||||
tabs.forEach(t => t.classList.remove('active'));
|
||||
// Find the clicked tab (simple logic for this demo)
|
||||
event.target.classList.add('active');
|
||||
|
||||
// In a real app, this would filter the card list
|
||||
const list = document.getElementById('contest-list');
|
||||
list.style.opacity = '0.5';
|
||||
setTimeout(() => {
|
||||
list.style.opacity = '1';
|
||||
// Mock content change
|
||||
if(tabName === 'finished') {
|
||||
// Just a visual cue that something changed
|
||||
list.innerHTML = `<div style="text-align:center; padding:40px; color:#aaa">Loading Archive...</div>`;
|
||||
setTimeout(() => {
|
||||
list.innerHTML = `
|
||||
<div class="contest-card pixel-border" style="opacity:0.7">
|
||||
<div class="flex-center">
|
||||
<div class="card-icon pixel-border" style="background:#555; color:#aaa"><i class="ri-trophy-line"></i></div>
|
||||
<div class="card-info">
|
||||
<h3 style="color:#aaa">Weekly Challenge #41</h3>
|
||||
<div class="card-details">
|
||||
<span>Ended: 2 days ago</span>
|
||||
<span>Winner: Herobrine</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<button class="btn-small">VIEW</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}, 500);
|
||||
} else if(tabName === 'ongoing') {
|
||||
// Reset to initial HTML (simplified)
|
||||
location.reload();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
|
||||
// --- Toggle Rules ---
|
||||
function toggleRules() {
|
||||
const card = document.getElementById('rules-card');
|
||||
card.classList.toggle('collapsed');
|
||||
}
|
||||
|
||||
// --- Real-time Leaderboard Simulation ---
|
||||
function simulateLeaderboard() {
|
||||
const rows = document.querySelectorAll('#leaderboard-body tr:not(.current-user)');
|
||||
// Randomly swap two rows to simulate rank changes
|
||||
const idx1 = Math.floor(Math.random() * 3); // Only top 3 change mostly
|
||||
const idx2 = Math.floor(Math.random() * 3);
|
||||
|
||||
if (idx1 !== idx2) {
|
||||
// Flash effect
|
||||
rows[idx1].style.backgroundColor = '#fff';
|
||||
setTimeout(() => {
|
||||
rows[idx1].style.backgroundColor = ''; // revert to CSS class style
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
setInterval(simulateLeaderboard, 10000);
|
||||
|
||||
// --- LocalStorage Logic ---
|
||||
// Save visit timestamp
|
||||
localStorage.setItem('last_visit_mc_contest', new Date().toISOString());
|
||||
|
||||
// --- Firework/Hover Effects for Top 3 ---
|
||||
const topRanks = document.querySelectorAll('.rank-1, .rank-2, .rank-3');
|
||||
topRanks.forEach(row => {
|
||||
row.addEventListener('mouseenter', () => {
|
||||
// Add a subtle scale effect
|
||||
row.style.transform = "scale(1.02)";
|
||||
row.style.transition = "transform 0.2s";
|
||||
row.style.zIndex = "10";
|
||||
row.style.boxShadow = "0 0 15px rgba(255, 215, 0, 0.5)";
|
||||
});
|
||||
row.addEventListener('mouseleave', () => {
|
||||
row.style.transform = "scale(1)";
|
||||
row.style.boxShadow = "none";
|
||||
row.style.zIndex = "1";
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,605 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>CSP Learning Platform - Minecraft Login</title>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/remixicon/4.6.0/remixicon.min.css" rel="stylesheet">
|
||||
<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=Press+Start+2P&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--mc-dirt-side: #79553a;
|
||||
--mc-dirt-top: #5c3f2b;
|
||||
--mc-grass-top: #70b348;
|
||||
--mc-grass-side: #5a9139;
|
||||
--mc-stone: #7d7d7d;
|
||||
--mc-wood: #a0744b;
|
||||
--mc-wood-dark: #6e4e34;
|
||||
--mc-wood-light: #bca07e;
|
||||
--mc-diamond: #29B6F6;
|
||||
--mc-redstone: #E53935;
|
||||
--mc-gold: #FFD700;
|
||||
--mc-sky: #cceeff;
|
||||
--bg-sky-top: #87CEEB;
|
||||
--bg-sky-bottom: #E0F7FA;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 1920px;
|
||||
min-height: 1080px;
|
||||
background: linear-gradient(to bottom, var(--bg-sky-top), var(--bg-sky-bottom));
|
||||
overflow-x: hidden;
|
||||
position: relative;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Pixel Cloud Background Decoration */
|
||||
.clouds {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
background-image:
|
||||
radial-gradient(circle at 15% 20%, white 20px, transparent 21px),
|
||||
radial-gradient(circle at 85% 30%, white 30px, transparent 31px),
|
||||
radial-gradient(circle at 50% 10%, rgba(255,255,255,0.8) 40px, transparent 41px);
|
||||
background-size: 800px 400px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* Top Nav */
|
||||
.navbar {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 40px;
|
||||
border-bottom: 4px solid rgba(0, 0, 0, 0.2);
|
||||
backdrop-filter: blur(4px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
text-shadow: 4px 4px 0px #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.logo i {
|
||||
color: var(--mc-grass-top);
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
/* Main Container */
|
||||
.main-container {
|
||||
margin-top: 140px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* Wooden Card */
|
||||
.login-card {
|
||||
width: 480px;
|
||||
background-color: var(--mc-wood);
|
||||
border: 4px solid #000;
|
||||
box-shadow:
|
||||
8px 8px 0px rgba(0,0,0,0.5),
|
||||
inset 4px 4px 0px var(--mc-wood-light),
|
||||
inset -4px -4px 0px var(--mc-wood-dark);
|
||||
padding: 32px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Wood Grain Texture CSS Pattern */
|
||||
.login-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
right: 4px;
|
||||
bottom: 4px;
|
||||
background-image:
|
||||
repeating-linear-gradient(45deg,
|
||||
rgba(0,0,0,0.05) 0px,
|
||||
rgba(0,0,0,0.05) 2px,
|
||||
transparent 2px,
|
||||
transparent 8px
|
||||
);
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.content-layer {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
.tabs {
|
||||
display: flex;
|
||||
margin-bottom: 24px;
|
||||
border-bottom: 4px solid var(--mc-wood-dark);
|
||||
}
|
||||
|
||||
.tab-btn {
|
||||
flex: 1;
|
||||
padding: 12px 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s;
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
}
|
||||
|
||||
.tab-btn.active {
|
||||
color: #fff;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
border-top: 4px solid var(--mc-wood-light);
|
||||
border-left: 4px solid var(--mc-wood-light);
|
||||
border-right: 4px solid var(--mc-wood-dark);
|
||||
}
|
||||
|
||||
/* Form Elements */
|
||||
.form-group {
|
||||
margin-bottom: 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
z-index: 2;
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 16px 16px 16px 48px;
|
||||
background-color: #333;
|
||||
border: 4px solid #000;
|
||||
border-right-color: #555;
|
||||
border-bottom-color: #555;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
outline: none;
|
||||
box-shadow: inset 4px 4px 0px #000;
|
||||
}
|
||||
|
||||
input::placeholder {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.toggle-password {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
cursor: pointer;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
font-size: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.custom-checkbox {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #333;
|
||||
border: 2px solid #000;
|
||||
margin-right: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: inset 2px 2px 0 #000;
|
||||
}
|
||||
|
||||
.custom-checkbox i {
|
||||
display: none;
|
||||
font-size: 14px;
|
||||
color: var(--mc-grass-top);
|
||||
}
|
||||
|
||||
.checkbox-group.checked .custom-checkbox i {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Password Strength */
|
||||
.strength-meter {
|
||||
height: 8px;
|
||||
background-color: #000;
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.strength-bar {
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
transition: width 0.3s, background-color 0.3s;
|
||||
}
|
||||
|
||||
.strength-text {
|
||||
font-size: 8px;
|
||||
margin-top: 4px;
|
||||
text-align: right;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
/* Button */
|
||||
.btn-minecraft {
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
background-color: var(--mc-grass-top);
|
||||
border: 4px solid #000;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
text-shadow: 2px 2px 0px #000;
|
||||
box-shadow:
|
||||
inset 4px 4px 0px rgba(255,255,255,0.3),
|
||||
inset -4px -4px 0px rgba(0,0,0,0.3),
|
||||
4px 4px 0px #000;
|
||||
transition: transform 0.1s, box-shadow 0.1s;
|
||||
}
|
||||
|
||||
.btn-minecraft:active {
|
||||
transform: translate(4px, 4px);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn-minecraft:hover {
|
||||
background-color: #7bc453;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
.links {
|
||||
margin-top: 24px;
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.link-diamond {
|
||||
color: var(--mc-diamond);
|
||||
text-decoration: none;
|
||||
text-shadow: 1px 1px 0 #000;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.link-diamond:hover {
|
||||
border-bottom-color: var(--mc-diamond);
|
||||
}
|
||||
|
||||
/* Error Message */
|
||||
.error-msg {
|
||||
color: var(--mc-redstone);
|
||||
font-size: 10px;
|
||||
margin-top: 8px;
|
||||
text-shadow: 1px 1px 0 #000;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Floating XP Orbs */
|
||||
.xp-orb {
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-color: #bcfc03;
|
||||
border: 2px solid #6c8f02;
|
||||
transform: rotate(45deg);
|
||||
box-shadow: 0 0 10px #bcfc03;
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.orb-1 { top: -40px; left: -40px; animation-delay: 0s; background-color: #bcfc03; }
|
||||
.orb-2 { bottom: -30px; right: -30px; animation-delay: 1.5s; background-color: #64ffda; border-color: #009688; }
|
||||
.orb-3 { top: 50%; right: -60px; animation-delay: 0.8s; width: 16px; height: 16px; }
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: rotate(45deg) translateY(0); }
|
||||
50% { transform: rotate(45deg) translateY(-20px); }
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background-color: rgba(0,0,0,0.6);
|
||||
backdrop-filter: blur(4px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
border-top: 4px solid rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.online-players {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.player-head {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-color: #333;
|
||||
border: 2px solid #fff;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.player-head:nth-child(2) { background-color: #AA0000; }
|
||||
.player-head:nth-child(3) { background-color: #00AA00; }
|
||||
.player-head:nth-child(4) { background-color: #0000AA; }
|
||||
|
||||
/* Grass Block Floor Decoration */
|
||||
.grass-floor {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background-image:
|
||||
linear-gradient(to right, var(--mc-grass-side) 50%, var(--mc-grass-top) 50%),
|
||||
linear-gradient(to bottom, transparent 50%, var(--mc-dirt-side) 50%);
|
||||
background-size: 40px 40px, 100% 40px;
|
||||
z-index: 5;
|
||||
display: none; /* Hidden to keep clean look, or show for immersion */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar">
|
||||
<div class="logo">
|
||||
<i class="ri-box-3-fill"></i>
|
||||
CSP Learning Platform
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="clouds"></div>
|
||||
|
||||
<div class="main-container">
|
||||
<div class="login-card">
|
||||
<!-- Decorative Orbs -->
|
||||
<div class="xp-orb orb-1"></div>
|
||||
<div class="xp-orb orb-2"></div>
|
||||
<div class="xp-orb orb-3"></div>
|
||||
|
||||
<div class="content-layer">
|
||||
<div class="tabs">
|
||||
<button class="tab-btn active" onclick="switchTab('login')">Login</button>
|
||||
<button class="tab-btn" onclick="switchTab('register')">Register</button>
|
||||
</div>
|
||||
|
||||
<form id="authForm" onsubmit="handleLogin(event)">
|
||||
<div class="form-group">
|
||||
<div class="input-wrapper">
|
||||
<i class="ri-user-smile-fill input-icon"></i>
|
||||
<input type="text" id="username" placeholder="Username" autocomplete="off">
|
||||
</div>
|
||||
<div id="username-error" class="error-msg">Username must be at least 3 chars!</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-wrapper">
|
||||
<i class="ri-lock-fill input-icon"></i>
|
||||
<input type="password" id="password" placeholder="Password" oninput="checkStrength()">
|
||||
<i class="ri-eye-off-fill toggle-password" onclick="togglePassword()"></i>
|
||||
</div>
|
||||
<div class="strength-meter">
|
||||
<div class="strength-bar" id="strength-bar"></div>
|
||||
</div>
|
||||
<div class="strength-text" id="strength-text"></div>
|
||||
<div id="password-error" class="error-msg">Password must be at least 6 chars!</div>
|
||||
</div>
|
||||
|
||||
<div class="checkbox-group" onclick="toggleRemember(this)">
|
||||
<div class="custom-checkbox">
|
||||
<i class="ri-check-fill"></i>
|
||||
</div>
|
||||
<span>Remember me</span>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn-minecraft" id="submit-btn">Login</button>
|
||||
</form>
|
||||
|
||||
<div class="links">
|
||||
<a href="#" class="link-diamond">Forgot password?</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="online-players">
|
||||
<span>Online Players: <span style="color: var(--mc-gold);">12,002</span></span>
|
||||
<div class="player-head"></div>
|
||||
<div class="player-head"></div>
|
||||
<div class="player-head"></div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
let isLogin = true;
|
||||
let rememberMe = false;
|
||||
|
||||
function switchTab(tab) {
|
||||
const btns = document.querySelectorAll('.tab-btn');
|
||||
const submitBtn = document.getElementById('submit-btn');
|
||||
const form = document.getElementById('authForm');
|
||||
|
||||
// Clear errors
|
||||
document.querySelectorAll('.error-msg').forEach(el => el.style.display = 'none');
|
||||
|
||||
if (tab === 'login') {
|
||||
isLogin = true;
|
||||
btns[0].classList.add('active');
|
||||
btns[1].classList.remove('active');
|
||||
submitBtn.innerText = 'Login';
|
||||
} else {
|
||||
isLogin = false;
|
||||
btns[0].classList.remove('active');
|
||||
btns[1].classList.add('active');
|
||||
submitBtn.innerText = 'Register';
|
||||
}
|
||||
}
|
||||
|
||||
function togglePassword() {
|
||||
const pwdInput = document.getElementById('password');
|
||||
const icon = document.querySelector('.toggle-password');
|
||||
if (pwdInput.type === 'password') {
|
||||
pwdInput.type = 'text';
|
||||
icon.classList.remove('ri-eye-off-fill');
|
||||
icon.classList.add('ri-eye-fill');
|
||||
} else {
|
||||
pwdInput.type = 'password';
|
||||
icon.classList.remove('ri-eye-fill');
|
||||
icon.classList.add('ri-eye-off-fill');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleRemember(el) {
|
||||
el.classList.toggle('checked');
|
||||
rememberMe = !rememberMe;
|
||||
}
|
||||
|
||||
function checkStrength() {
|
||||
const pwd = document.getElementById('password').value;
|
||||
const bar = document.getElementById('strength-bar');
|
||||
const text = document.getElementById('strength-text');
|
||||
|
||||
if (pwd.length === 0) {
|
||||
bar.style.width = '0%';
|
||||
bar.style.backgroundColor = 'transparent';
|
||||
text.innerText = '';
|
||||
return;
|
||||
}
|
||||
|
||||
let strength = 0;
|
||||
if (pwd.length >= 6) strength++;
|
||||
if (pwd.match(/[a-z]/) && pwd.match(/[0-9]/)) strength++;
|
||||
if (pwd.length > 8 && pwd.match(/[^a-zA-Z0-9]/)) strength++;
|
||||
|
||||
if (strength === 1) {
|
||||
bar.style.width = '33%';
|
||||
bar.style.backgroundColor = '#E53935'; // Weak
|
||||
text.innerText = 'Weak';
|
||||
text.style.color = '#E53935';
|
||||
} else if (strength === 2) {
|
||||
bar.style.width = '66%';
|
||||
bar.style.backgroundColor = '#FFD700'; // Medium
|
||||
text.innerText = 'Medium';
|
||||
text.style.color = '#FFD700';
|
||||
} else {
|
||||
bar.style.width = '100%';
|
||||
bar.style.backgroundColor = '#7CB342'; // Strong
|
||||
text.innerText = 'Strong';
|
||||
text.style.color = '#7CB342';
|
||||
}
|
||||
}
|
||||
|
||||
function handleLogin(e) {
|
||||
e.preventDefault();
|
||||
const user = document.getElementById('username').value;
|
||||
const pass = document.getElementById('password').value;
|
||||
const userErr = document.getElementById('username-error');
|
||||
const passErr = document.getElementById('password-error');
|
||||
|
||||
let isValid = true;
|
||||
|
||||
// Reset errors
|
||||
userErr.style.display = 'none';
|
||||
passErr.style.display = 'none';
|
||||
|
||||
if (user.length < 3) {
|
||||
userErr.style.display = 'block';
|
||||
isValid = false;
|
||||
}
|
||||
if (pass.length < 6) {
|
||||
passErr.style.display = 'block';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!isValid) return;
|
||||
|
||||
// Mock login check
|
||||
if (isLogin) {
|
||||
if (user === 'test' && pass === 'whoami139') {
|
||||
// Success
|
||||
const token = 'mock_token_' + Date.now();
|
||||
localStorage.setItem('authToken', token);
|
||||
if(rememberMe) localStorage.setItem('savedUser', user);
|
||||
|
||||
// Simulate redirect with a nice alert or console log since we are in a static file context
|
||||
// In a real app: window.location.href = 'problem-library.html';
|
||||
const btn = document.getElementById('submit-btn');
|
||||
btn.innerText = 'Connecting...';
|
||||
btn.style.backgroundColor = '#FFD700'; // Gold color loading
|
||||
|
||||
setTimeout(() => {
|
||||
// We just reload or show success for this demo
|
||||
btn.innerText = 'Success!';
|
||||
btn.style.backgroundColor = '#7CB342';
|
||||
// Simulating redirect
|
||||
// window.location.href = 'problem-library.html';
|
||||
console.log("Redirecting to problem-library.html");
|
||||
}, 1000);
|
||||
} else {
|
||||
// Wrong credentials
|
||||
// Create a generic error message for demo
|
||||
passErr.innerText = 'Invalid username or password!';
|
||||
passErr.style.display = 'block';
|
||||
}
|
||||
} else {
|
||||
// Register logic mock
|
||||
alert(`Registered user: ${user}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,849 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Minecraft Problem Library</title>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/remixicon/4.6.0/remixicon.min.css" rel="stylesheet">
|
||||
<style>
|
||||
/* Font Loading */
|
||||
@font-face {
|
||||
font-family: 'Press Start 2P';
|
||||
src: url('https://fonts.gstatic.com/s/pressstart2p/v15/e3t4euO8T-267oIAQAu6jDQyK3nVivM.woff2') format('woff2');
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MiSans-Regular';
|
||||
src: url('https://assets-persist.lovart.ai/agent-static-assets/MiSans-Regular.ttf');
|
||||
}
|
||||
|
||||
:root {
|
||||
--mc-dirt-dark: #5e4032;
|
||||
--mc-dirt-light: #866043;
|
||||
--mc-grass-side: #7CB342;
|
||||
--mc-grass-top: #558B2F;
|
||||
--mc-stone: #757575;
|
||||
--mc-stone-light: #9E9E9E;
|
||||
--mc-wood-dark: #4E342E;
|
||||
--mc-wood-light: #795548;
|
||||
--mc-plank: #A1887F;
|
||||
--mc-text-shadow: 2px 2px 0 #000;
|
||||
--mc-bg: #1e1e1e;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'MiSans-Regular', sans-serif;
|
||||
background-color: #121212;
|
||||
color: white;
|
||||
width: 1920px;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
background-image:
|
||||
linear-gradient(rgba(0,0,0,0.7), rgba(0,0,0,0.7)),
|
||||
url('https://images.unsplash.com/photo-1587573088697-b4f9d17102dd?q=80&w=2669&auto=format&fit=crop'); /* Minecraft-like texture bg */
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Minecraft Button Utility */
|
||||
.mc-btn {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 12px;
|
||||
padding: 12px 20px;
|
||||
border: 4px solid #000;
|
||||
background: #9E9E9E;
|
||||
color: #fff;
|
||||
text-shadow: 2px 2px #333;
|
||||
cursor: pointer;
|
||||
box-shadow: inset -4px -4px 0px #555, inset 4px 4px 0px #DDD;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
transition: transform 0.1s;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.mc-btn:active {
|
||||
box-shadow: inset -4px -4px 0px #DDD, inset 4px 4px 0px #555;
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
.mc-btn.green {
|
||||
background: #7CB342;
|
||||
box-shadow: inset -4px -4px 0px #33691E, inset 4px 4px 0px #AED581;
|
||||
}
|
||||
.mc-btn.green:active {
|
||||
box-shadow: inset -4px -4px 0px #AED581, inset 4px 4px 0px #33691E;
|
||||
}
|
||||
|
||||
/* Top Navigation */
|
||||
.top-nav {
|
||||
height: 70px;
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
border-bottom: 4px solid #3e3e3e;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 40px;
|
||||
justify-content: space-between;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.nav-brand {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 20px;
|
||||
color: #FFEB3B;
|
||||
text-shadow: var(--mc-text-shadow);
|
||||
margin-right: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 12px;
|
||||
color: #ccc;
|
||||
text-decoration: none;
|
||||
padding: 10px 20px;
|
||||
border: 2px solid transparent;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.nav-item:hover, .nav-item.active {
|
||||
color: #fff;
|
||||
background: rgba(255,255,255,0.1);
|
||||
border: 2px solid #fff;
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 2px solid #fff;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
/* Layout Container */
|
||||
.container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
max-width: 1920px;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
width: 280px;
|
||||
background-color: #5D4037; /* Dark Wood */
|
||||
border-right: 4px solid #3E2723;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
background-image: repeating-linear-gradient(
|
||||
45deg,
|
||||
rgba(255,255,255,0.05) 0px,
|
||||
rgba(255,255,255,0.05) 2px,
|
||||
transparent 2px,
|
||||
transparent 10px
|
||||
);
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
list-style: none;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
display: block;
|
||||
padding: 15px;
|
||||
background: #8D6E63; /* Plank color */
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 10px;
|
||||
border: 4px solid #3E2723;
|
||||
box-shadow: inset 2px 2px 0 rgba(255,255,255,0.2);
|
||||
transition: transform 0.1s;
|
||||
}
|
||||
|
||||
.menu-link:hover {
|
||||
transform: scale(1.02);
|
||||
background: #A1887F;
|
||||
}
|
||||
|
||||
.menu-link.active {
|
||||
background: #7CB342;
|
||||
border-color: #33691E;
|
||||
}
|
||||
|
||||
.daily-quest-panel {
|
||||
background: #263238;
|
||||
border: 4px solid #000;
|
||||
padding: 15px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.quest-title {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 12px;
|
||||
color: #FFEB3B;
|
||||
margin-bottom: 10px;
|
||||
text-shadow: 1px 1px #000;
|
||||
}
|
||||
|
||||
.quest-progress {
|
||||
height: 20px;
|
||||
background: #37474F;
|
||||
border: 2px solid #000;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.quest-bar {
|
||||
height: 100%;
|
||||
width: 60%;
|
||||
background: #29B6F6;
|
||||
box-shadow: inset 0 -2px 0 rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.quest-text {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 10px;
|
||||
margin-top: 8px;
|
||||
text-align: right;
|
||||
color: #B0BEC5;
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: 40px;
|
||||
background: rgba(0,0,0,0.4);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 32px;
|
||||
color: #fff;
|
||||
text-shadow: 4px 4px 0 #000;
|
||||
}
|
||||
|
||||
/* Stats Cards */
|
||||
.stats-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: #546E7A; /* Stone Blue */
|
||||
border: 4px solid #263238;
|
||||
padding: 20px;
|
||||
position: relative;
|
||||
box-shadow: 6px 6px 0 rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.stat-card::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
right: 4px;
|
||||
bottom: 4px;
|
||||
border: 2px dashed rgba(255,255,255,0.1);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 10px;
|
||||
color: #CFD8DC;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 24px;
|
||||
color: #fff;
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
}
|
||||
|
||||
/* Filters */
|
||||
.filter-section {
|
||||
background: #3E2723;
|
||||
border: 4px solid #000;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.category-tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.tab-btn {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 10px;
|
||||
padding: 10px 15px;
|
||||
background: #5D4037;
|
||||
border: 2px solid #8D6E63;
|
||||
color: #D7CCC8;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.tab-btn.active {
|
||||
background: #7CB342;
|
||||
color: white;
|
||||
border-color: #AED581;
|
||||
box-shadow: 0 4px 0 #33691E;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.filter-controls {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.mc-select {
|
||||
font-family: 'MiSans-Regular', sans-serif; /* Readable font for dropdown */
|
||||
font-size: 14px;
|
||||
padding: 8px;
|
||||
background: #D7CCC8;
|
||||
border: 3px solid #5D4037;
|
||||
color: #3E2723;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.mc-input {
|
||||
font-family: 'MiSans-Regular', sans-serif;
|
||||
font-size: 14px;
|
||||
padding: 8px 12px;
|
||||
background: #212121;
|
||||
border: 3px solid #616161;
|
||||
color: #fff;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.mc-search-btn {
|
||||
background: #FFB74D;
|
||||
border: 3px solid #E65100;
|
||||
color: #3E2723;
|
||||
padding: 0 15px;
|
||||
cursor: pointer;
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Problem Table */
|
||||
.problem-table-container {
|
||||
background: #8D6E63; /* Plank */
|
||||
border: 4px solid #3E2723;
|
||||
padding: 10px;
|
||||
box-shadow: 8px 8px 0 rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.problem-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.problem-table th {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 10px;
|
||||
text-align: left;
|
||||
padding: 15px;
|
||||
background: #5D4037;
|
||||
color: #FFCC80;
|
||||
border-bottom: 4px solid #3E2723;
|
||||
}
|
||||
|
||||
.problem-table td {
|
||||
padding: 12px 15px;
|
||||
border-bottom: 2px solid #5D4037;
|
||||
color: #3E2723;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.problem-table tr:hover td {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.problem-table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
.status-solved { color: #2E7D32; }
|
||||
.status-locked { color: #616161; }
|
||||
.status-attempted { color: #F57F17; }
|
||||
|
||||
.difficulty-stars {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}
|
||||
.star {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tag-badge {
|
||||
background: #3E2723;
|
||||
color: #D7CCC8;
|
||||
padding: 2px 6px;
|
||||
font-size: 12px;
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.table-btn {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 8px;
|
||||
padding: 6px 10px;
|
||||
border: 2px solid #000;
|
||||
background: #FFB74D;
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
box-shadow: inset -2px -2px 0 #E65100, inset 2px 2px 0 #FFE0B2;
|
||||
}
|
||||
|
||||
.table-btn:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* Pagination */
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.page-info {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 10px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Right Floating Panel */
|
||||
.right-panel {
|
||||
width: 260px;
|
||||
padding: 20px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.task-card {
|
||||
background: #F5F5F5; /* Paper */
|
||||
border: 4px solid #424242;
|
||||
padding: 15px;
|
||||
box-shadow: 4px 4px 0 rgba(0,0,0,0.5);
|
||||
position: sticky;
|
||||
top: 100px;
|
||||
}
|
||||
|
||||
.task-card::before {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 10px;
|
||||
background: #B71C1C; /* Red tape */
|
||||
width: 40px;
|
||||
margin: -25px auto 15px;
|
||||
box-shadow: 1px 1px 2px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.task-header {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 12px;
|
||||
color: #212121;
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
border-bottom: 2px dashed #9E9E9E;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.task-list {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.task-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 13px;
|
||||
color: #424242;
|
||||
}
|
||||
|
||||
.mc-checkbox {
|
||||
appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 2px solid #000;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mc-checkbox:checked {
|
||||
background: #7CB342;
|
||||
}
|
||||
|
||||
.mc-checkbox:checked::after {
|
||||
content: '✔';
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
left: 1px;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.xp-reward {
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
font-size: 8px;
|
||||
color: #F57F17;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 1200px) {
|
||||
.stats-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="top-nav">
|
||||
<div class="nav-brand">
|
||||
<i class="ri-book-3-fill" style="color: #8D6E63; font-size: 24px;"></i>
|
||||
CRAFT CODE
|
||||
</div>
|
||||
<div class="nav-links">
|
||||
<a href="#" class="nav-item">HOME</a>
|
||||
<a href="#" class="nav-item active">PROBLEMS</a>
|
||||
<a href="#" class="nav-item">CONTEST</a>
|
||||
<a href="#" class="nav-item">LEADERBOARD</a>
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<img src="https://api.dicebear.com/7.x/pixel-art/svg?seed=Felix" alt="User" class="user-avatar">
|
||||
<div style="font-family: 'Press Start 2P'; font-size: 10px; color: #fff;">Steve</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<!-- Sidebar -->
|
||||
<aside class="sidebar">
|
||||
<ul class="sidebar-menu">
|
||||
<li class="menu-item"><a href="#" class="menu-link active">ALL PROBLEMS</a></li>
|
||||
<li class="menu-item"><a href="#" class="menu-link">ALGORITHMS</a></li>
|
||||
<li class="menu-item"><a href="#" class="menu-link">DATA STRUCTURES</a></li>
|
||||
<li class="menu-item"><a href="#" class="menu-link">MATH</a></li>
|
||||
<li class="menu-item"><a href="#" class="menu-link">STRINGS</a></li>
|
||||
<li class="menu-item"><a href="#" class="menu-link">DYNAMIC PROG</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="daily-quest-panel">
|
||||
<div class="quest-title">DAILY QUEST</div>
|
||||
<div class="quest-progress">
|
||||
<div class="quest-bar"></div>
|
||||
</div>
|
||||
<div class="quest-text">3/5 COMPLETED</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<div class="page-header">
|
||||
<i class="ri-book-read-line" style="font-size: 32px; color: #FFD54F;"></i>
|
||||
<h1 class="page-title">PROBLEM LIBRARY</h1>
|
||||
</div>
|
||||
|
||||
<div class="stats-row">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">TOTAL PROBLEMS</div>
|
||||
<div class="stat-value">1,556</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">COMPLETED</div>
|
||||
<div class="stat-value" style="color: #7CB342;">128</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">PASS RATE</div>
|
||||
<div class="stat-value" style="color: #FFB74D;">85%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-section">
|
||||
<div class="category-tabs">
|
||||
<button class="tab-btn active" onclick="switchTab(this)">CSP-J</button>
|
||||
<button class="tab-btn" onclick="switchTab(this)">CSP-S</button>
|
||||
<button class="tab-btn" onclick="switchTab(this)">NOIP</button>
|
||||
</div>
|
||||
|
||||
<div class="filter-controls">
|
||||
<select class="mc-select">
|
||||
<option>All Difficulty</option>
|
||||
<option>1 Star</option>
|
||||
<option>2 Stars</option>
|
||||
<option>3 Stars</option>
|
||||
<option>4 Stars</option>
|
||||
<option>5 Stars</option>
|
||||
</select>
|
||||
<select class="mc-select">
|
||||
<option>All Tags</option>
|
||||
<option>Array</option>
|
||||
<option>Stack</option>
|
||||
<option>Queue</option>
|
||||
</select>
|
||||
<input type="text" class="mc-input" id="searchInput" placeholder="Search problems...">
|
||||
<button class="mc-search-btn" onclick="filterTable()">
|
||||
<i class="ri-search-2-line"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="problem-table-container">
|
||||
<table class="problem-table" id="problemTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50">STS</th>
|
||||
<th width="60">ID</th>
|
||||
<th>TITLE</th>
|
||||
<th width="100">RATE</th>
|
||||
<th width="100">DIFF</th>
|
||||
<th width="150">TAGS</th>
|
||||
<th width="80">ACT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Data rows will be populated by JS -->
|
||||
<tr>
|
||||
<td><i class="ri-checkbox-circle-fill status-solved status-icon"></i></td>
|
||||
<td>1001</td>
|
||||
<td>A+B Problem</td>
|
||||
<td>95%</td>
|
||||
<td>
|
||||
<div class="difficulty-stars">
|
||||
<i class="ri-star-fill star" style="color:#7CB342"></i>
|
||||
<i class="ri-star-line star" style="color:#757575"></i>
|
||||
<i class="ri-star-line star" style="color:#757575"></i>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="tag-badge">Math</span></td>
|
||||
<td><a href="#" class="table-btn">SOLVE</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i class="ri-lock-fill status-locked status-icon"></i></td>
|
||||
<td>1002</td>
|
||||
<td>Fibonacci Sequence</td>
|
||||
<td>45%</td>
|
||||
<td>
|
||||
<div class="difficulty-stars">
|
||||
<i class="ri-star-fill star" style="color:#FFB74D"></i>
|
||||
<i class="ri-star-fill star" style="color:#FFB74D"></i>
|
||||
<i class="ri-star-line star" style="color:#757575"></i>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="tag-badge">DP</span></td>
|
||||
<td><a href="#" class="table-btn">SOLVE</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<button class="mc-btn">PREV</button>
|
||||
<div class="page-info">PAGE 1 / 32</div>
|
||||
<button class="mc-btn green">NEXT</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Right Panel -->
|
||||
<aside class="right-panel">
|
||||
<div class="task-card">
|
||||
<div class="task-header">DAILY TASKS</div>
|
||||
<ul class="task-list">
|
||||
<li class="task-item">
|
||||
<input type="checkbox" class="mc-checkbox" checked>
|
||||
<span>Login Daily</span>
|
||||
<span class="xp-reward">+10XP</span>
|
||||
</li>
|
||||
<li class="task-item">
|
||||
<input type="checkbox" class="mc-checkbox" checked>
|
||||
<span>Solve 1 Easy</span>
|
||||
<span class="xp-reward">+20XP</span>
|
||||
</li>
|
||||
<li class="task-item">
|
||||
<input type="checkbox" class="mc-checkbox">
|
||||
<span>Solve 1 Medium</span>
|
||||
<span class="xp-reward">+50XP</span>
|
||||
</li>
|
||||
<li class="task-item">
|
||||
<input type="checkbox" class="mc-checkbox">
|
||||
<span>Submit 5 times</span>
|
||||
<span class="xp-reward">+15XP</span>
|
||||
</li>
|
||||
<li class="task-item">
|
||||
<input type="checkbox" class="mc-checkbox">
|
||||
<span>Review Code</span>
|
||||
<span class="xp-reward">+30XP</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Sample Data Generation
|
||||
const problems = [
|
||||
{ id: '1001', title: 'A+B Problem', rate: '98%', diff: 1, tags: ['Math'], status: 'solved' },
|
||||
{ id: '1002', title: 'Knapsack Problem', rate: '45%', diff: 3, tags: ['DP', 'Math'], status: 'attempted' },
|
||||
{ id: '1003', title: 'Binary Tree Traversal', rate: '60%', diff: 2, tags: ['Tree', 'DFS'], status: 'locked' },
|
||||
{ id: '1004', title: 'Shortest Path (Dijkstra)', rate: '32%', diff: 4, tags: ['Graph'], status: 'locked' },
|
||||
{ id: '1005', title: 'String Matching (KMP)', rate: '28%', diff: 5, tags: ['String'], status: 'locked' },
|
||||
{ id: '1006', title: 'Counting Sort', rate: '75%', diff: 2, tags: ['Sort'], status: 'solved' },
|
||||
{ id: '1007', title: 'N-Queens', rate: '40%', diff: 3, tags: ['Backtrack'], status: 'locked' },
|
||||
{ id: '1008', title: 'Union Find', rate: '55%', diff: 3, tags: ['DS'], status: 'attempted' },
|
||||
{ id: '1009', title: 'Segment Tree Range Sum', rate: '20%', diff: 5, tags: ['Tree'], status: 'locked' },
|
||||
{ id: '1010', title: 'Prim MST', rate: '35%', diff: 4, tags: ['Graph'], status: 'locked' }
|
||||
];
|
||||
|
||||
function getStatusIcon(status) {
|
||||
if (status === 'solved') return '<i class="ri-checkbox-circle-fill status-solved status-icon"></i>';
|
||||
if (status === 'attempted') return '<i class="ri-record-circle-fill status-attempted status-icon"></i>';
|
||||
return '<i class="ri-lock-fill status-locked status-icon"></i>';
|
||||
}
|
||||
|
||||
function getStars(count) {
|
||||
let html = '<div class="difficulty-stars">';
|
||||
const colors = ['#7CB342', '#29B6F6', '#FFB74D', '#FF7043', '#D32F2F']; // Color coding
|
||||
const color = colors[count - 1] || '#757575';
|
||||
|
||||
for(let i=0; i<5; i++) {
|
||||
if(i < count) {
|
||||
html += `<i class="ri-star-fill star" style="color:${color}"></i>`;
|
||||
} else {
|
||||
html += `<i class="ri-star-line star" style="color:#757575"></i>`;
|
||||
}
|
||||
}
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderTable(data) {
|
||||
const tbody = document.querySelector('#problemTable tbody');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
data.forEach(p => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td>${getStatusIcon(p.status)}</td>
|
||||
<td>${p.id}</td>
|
||||
<td style="cursor:pointer;" onclick="window.location.href='code-editor.html?id=${p.id}'">${p.title}</td>
|
||||
<td>${p.rate}</td>
|
||||
<td>${getStars(p.diff)}</td>
|
||||
<td>${p.tags.map(t => `<span class="tag-badge">${t}</span>`).join('')}</td>
|
||||
<td><a href="code-editor.html?id=${p.id}" class="table-btn">SOLVE</a></td>
|
||||
`;
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
// Tab Switching Logic
|
||||
function switchTab(element) {
|
||||
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
|
||||
element.classList.add('active');
|
||||
// Mock data change
|
||||
const shuffled = [...problems].sort(() => 0.5 - Math.random());
|
||||
renderTable(shuffled);
|
||||
}
|
||||
|
||||
// Filter Logic
|
||||
function filterTable() {
|
||||
const term = document.getElementById('searchInput').value.toLowerCase();
|
||||
const filtered = problems.filter(p =>
|
||||
p.title.toLowerCase().includes(term) ||
|
||||
p.id.includes(term) ||
|
||||
p.tags.some(t => t.toLowerCase().includes(term))
|
||||
);
|
||||
renderTable(filtered);
|
||||
}
|
||||
|
||||
// Real-time search
|
||||
document.getElementById('searchInput').addEventListener('input', filterTable);
|
||||
|
||||
// Sidebar Active State
|
||||
document.querySelectorAll('.menu-link').forEach(link => {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
document.querySelectorAll('.menu-link').forEach(l => l.classList.remove('active'));
|
||||
link.classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize
|
||||
renderTable(problems);
|
||||
|
||||
// Save checkbox state to localStorage
|
||||
document.querySelectorAll('.mc-checkbox').forEach((box, index) => {
|
||||
const saved = localStorage.getItem(`task-${index}`);
|
||||
if(saved !== null) {
|
||||
box.checked = saved === 'true';
|
||||
}
|
||||
|
||||
box.addEventListener('change', () => {
|
||||
localStorage.setItem(`task-${index}`, box.checked);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,896 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Minecraft Profile Center</title>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/remixicon/4.6.0/remixicon.min.css" rel="stylesheet">
|
||||
<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=Press+Start+2P&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color: #1a1a1a;
|
||||
--text-color: #ffffff;
|
||||
--minecraft-green: #59a228;
|
||||
--minecraft-dark-green: #376318;
|
||||
--wood-light: #a07449;
|
||||
--wood-dark: #634329;
|
||||
--wood-border: #3d2919;
|
||||
--gold: #fcc201;
|
||||
--purple: #aa00aa;
|
||||
--iron: #c6c6c6;
|
||||
--diamond: #3fd2ea;
|
||||
--red: #aa0000;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #2c2c2c;
|
||||
background-image:
|
||||
linear-gradient(45deg, #252525 25%, transparent 25%),
|
||||
linear-gradient(-45deg, #252525 25%, transparent 25%),
|
||||
linear-gradient(45deg, transparent 75%, #252525 75%),
|
||||
linear-gradient(-45deg, transparent 75%, #252525 75%);
|
||||
background-size: 40px 40px;
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
color: var(--text-color);
|
||||
width: 1920px;
|
||||
overflow-x: hidden;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Utility Classes */
|
||||
.flex { display: flex; }
|
||||
.flex-col { flex-direction: column; }
|
||||
.items-center { align-items: center; }
|
||||
.justify-center { justify-content: center; }
|
||||
.justify-between { justify-content: space-between; }
|
||||
.gap-2 { gap: 8px; }
|
||||
.gap-4 { gap: 16px; }
|
||||
.w-full { width: 100%; }
|
||||
.h-full { height: 100%; }
|
||||
|
||||
/* Minecraft UI Components */
|
||||
.mc-btn {
|
||||
background-color: #7d7d7d;
|
||||
border: 4px solid #000;
|
||||
border-top-color: #dedede;
|
||||
border-left-color: #dedede;
|
||||
border-right-color: #555;
|
||||
border-bottom-color: #555;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mc-btn:active, .mc-btn.active {
|
||||
background-color: #555;
|
||||
border-top-color: #333;
|
||||
border-left-color: #333;
|
||||
border-right-color: #dedede;
|
||||
border-bottom-color: #dedede;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.mc-card {
|
||||
background-color: #c6c6c6;
|
||||
border: 4px solid #000;
|
||||
border-top-color: #fff;
|
||||
border-left-color: #fff;
|
||||
border-right-color: #555;
|
||||
border-bottom-color: #555;
|
||||
padding: 4px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.mc-card-inner {
|
||||
background-color: #8b8b8b;
|
||||
border: 4px solid #373737;
|
||||
border-right-color: #fff;
|
||||
border-bottom-color: #fff;
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mc-wood-panel {
|
||||
background-color: var(--wood-light);
|
||||
background-image:
|
||||
linear-gradient(90deg, rgba(0,0,0,0.1) 50%, transparent 50%),
|
||||
linear-gradient(rgba(0,0,0,0.1) 50%, transparent 50%);
|
||||
background-size: 8px 8px;
|
||||
border: 4px solid var(--wood-border);
|
||||
box-shadow: inset 4px 4px 0 var(--wood-dark), inset -4px -4px 0 var(--wood-dark);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* Top Nav */
|
||||
nav {
|
||||
background: rgba(0,0,0,0.8);
|
||||
padding: 20px 40px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
border-bottom: 4px solid #555;
|
||||
}
|
||||
|
||||
.nav-brand { font-size: 24px; color: var(--diamond); text-shadow: 2px 2px #000; }
|
||||
.nav-links { gap: 20px; }
|
||||
|
||||
/* Main Container */
|
||||
.container {
|
||||
padding: 40px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* User Info Card */
|
||||
.user-hero {
|
||||
display: grid;
|
||||
grid-template-columns: 200px 1fr 400px;
|
||||
gap: 40px;
|
||||
margin-bottom: 40px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
background: #000;
|
||||
border: 4px solid #fff;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.user-details h1 {
|
||||
font-size: 32px;
|
||||
margin: 0 0 10px 0;
|
||||
text-shadow: 3px 3px 0 #000;
|
||||
}
|
||||
|
||||
.badge-lv {
|
||||
display: inline-block;
|
||||
background: var(--gold);
|
||||
color: #000;
|
||||
padding: 8px 12px;
|
||||
border: 2px solid #fff;
|
||||
margin-right: 10px;
|
||||
box-shadow: 4px 4px 0 rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.title-banner {
|
||||
display: inline-block;
|
||||
background: var(--purple);
|
||||
padding: 8px 16px;
|
||||
border: 2px solid #d369d3;
|
||||
text-shadow: 2px 2px #000;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.xp-bar-container {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
background: #333;
|
||||
border: 2px solid #fff;
|
||||
margin-top: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.xp-bar-fill {
|
||||
height: 100%;
|
||||
background: var(--minecraft-green);
|
||||
width: 0%; /* JS will animate */
|
||||
transition: width 1.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.xp-bar-fill::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background-image: linear-gradient(
|
||||
45deg,
|
||||
rgba(255, 255, 255, 0.2) 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0.2) 75%,
|
||||
transparent 75%,
|
||||
transparent
|
||||
);
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
|
||||
.xp-text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 10px;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px #000;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: rgba(0,0,0,0.3);
|
||||
border: 2px solid rgba(255,255,255,0.2);
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-val { font-size: 20px; color: var(--gold); margin-bottom: 5px; }
|
||||
.stat-label { font-size: 10px; color: #ccc; }
|
||||
|
||||
/* 3 Columns Layout */
|
||||
.main-content {
|
||||
display: grid;
|
||||
grid-template-columns: 25% 50% 25%;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* Column Styles */
|
||||
.col-card {
|
||||
background: #c6c6c6;
|
||||
border: 4px solid #555;
|
||||
padding: 4px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.col-card-inner {
|
||||
background: #222;
|
||||
border: 2px solid #000;
|
||||
padding: 15px;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
border-bottom: 2px solid #555;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 15px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* Pie Chart Simulation */
|
||||
.pie-chart-wrap {
|
||||
position: relative;
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
margin: 20px auto;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(
|
||||
var(--minecraft-green) 0% 50%,
|
||||
var(--gold) 50% 80%,
|
||||
var(--red) 80% 100%
|
||||
);
|
||||
border: 4px solid #000;
|
||||
box-shadow: 4px 4px 0 rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
/* Activity Grid */
|
||||
.activity-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
gap: 4px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.activity-cell {
|
||||
width: 100%;
|
||||
padding-top: 100%;
|
||||
background: #333;
|
||||
position: relative;
|
||||
}
|
||||
.activity-cell[data-level="1"] { background: #1a4d1a; }
|
||||
.activity-cell[data-level="2"] { background: #2b7a2b; }
|
||||
.activity-cell[data-level="3"] { background: #40b340; }
|
||||
.activity-cell[data-level="4"] { background: #5cd65c; }
|
||||
|
||||
/* Achievement Wall */
|
||||
.achievement-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 15px;
|
||||
padding: 20px;
|
||||
background: url('https://www.transparenttextures.com/patterns/wood-pattern.png') #634329;
|
||||
border: 8px solid #3d2919;
|
||||
box-shadow: inset 0 0 20px #000;
|
||||
}
|
||||
|
||||
.achievement-slot {
|
||||
aspect-ratio: 1;
|
||||
background: rgba(0,0,0,0.3);
|
||||
border: 2px solid #3d2919;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
transition: transform 0.2s;
|
||||
cursor: pointer;
|
||||
}
|
||||
.achievement-slot:hover {
|
||||
transform: scale(1.1);
|
||||
background: rgba(255,255,255,0.1);
|
||||
z-index: 10;
|
||||
}
|
||||
.achievement-icon {
|
||||
font-size: 32px;
|
||||
filter: drop-shadow(2px 2px 0 #000);
|
||||
}
|
||||
.locked { filter: grayscale(1) brightness(0.5); }
|
||||
|
||||
.tooltip {
|
||||
position: absolute;
|
||||
bottom: 120%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #111;
|
||||
border: 2px solid #fff;
|
||||
padding: 8px;
|
||||
font-size: 10px;
|
||||
width: 150px;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.2s;
|
||||
z-index: 20;
|
||||
}
|
||||
.achievement-slot:hover .tooltip { opacity: 1; }
|
||||
|
||||
/* Learning Path */
|
||||
.path-row { margin-bottom: 15px; }
|
||||
.path-label { font-size: 12px; margin-bottom: 5px; display: flex; justify-content: space-between; }
|
||||
.path-track {
|
||||
height: 16px;
|
||||
background: #000;
|
||||
border: 2px solid #555;
|
||||
position: relative;
|
||||
}
|
||||
.path-fill {
|
||||
height: 100%;
|
||||
background: var(--diamond);
|
||||
width: 0;
|
||||
transition: width 1s ease-out;
|
||||
position: relative;
|
||||
}
|
||||
.path-fill::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0; right: 0; bottom: 0;
|
||||
width: 4px;
|
||||
background: #fff;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Leaderboard */
|
||||
.leaderboard-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
border-bottom: 2px solid #333;
|
||||
font-size: 12px;
|
||||
}
|
||||
.leaderboard-item.highlight {
|
||||
background: rgba(255, 215, 0, 0.2);
|
||||
border: 2px solid var(--gold);
|
||||
}
|
||||
.rank { width: 30px; text-align: center; font-weight: bold; }
|
||||
.user { flex-grow: 1; padding-left: 10px; }
|
||||
.score { color: var(--gold); }
|
||||
|
||||
/* Daily Tasks */
|
||||
.task-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px dashed #444;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.checkbox-custom {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #777;
|
||||
background: #000;
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.checked .checkbox-custom::after {
|
||||
content: '✓';
|
||||
color: var(--minecraft-green);
|
||||
font-size: 14px;
|
||||
}
|
||||
.task-xp { margin-left: auto; color: #888; font-size: 10px; }
|
||||
|
||||
/* Treasure Chest */
|
||||
.treasure-box {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.chest-icon {
|
||||
font-size: 64px;
|
||||
color: var(--gold);
|
||||
filter: drop-shadow(0 0 10px var(--gold));
|
||||
animation: bounce 2s infinite;
|
||||
}
|
||||
@keyframes bounce {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
.chest-glow {
|
||||
position: absolute;
|
||||
top: 50%; left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100px; height: 100px;
|
||||
background: radial-gradient(circle, rgba(255,215,0,0.4) 0%, transparent 70%);
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
@keyframes pulse {
|
||||
0% { transform: translate(-50%, -50%) scale(1); opacity: 0.5; }
|
||||
50% { transform: translate(-50%, -50%) scale(1.5); opacity: 0.8; }
|
||||
100% { transform: translate(-50%, -50%) scale(1); opacity: 0.5; }
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0; left: 0; w-full; h-full;
|
||||
width: 100%; height: 100%;
|
||||
background: rgba(0,0,0,0.8);
|
||||
z-index: 1000;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.modal-content {
|
||||
background: #c6c6c6;
|
||||
border: 4px solid #fff;
|
||||
padding: 4px;
|
||||
width: 400px;
|
||||
text-align: center;
|
||||
}
|
||||
.modal-inner {
|
||||
background: #222;
|
||||
border: 4px solid #555;
|
||||
padding: 30px;
|
||||
color: #fff;
|
||||
}
|
||||
.reward-icon { font-size: 48px; margin: 20px 0; display: block; }
|
||||
.close-btn {
|
||||
background: var(--red);
|
||||
border: 2px solid #fff;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
margin-top: 20px;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="flex justify-between items-center">
|
||||
<div class="nav-brand"><i class="ri-code-box-line"></i> CRAFTCODE</div>
|
||||
<div class="nav-links flex">
|
||||
<a href="#" class="mc-btn">Home</a>
|
||||
<a href="#" class="mc-btn">Problems</a>
|
||||
<a href="#" class="mc-btn active">Profile</a>
|
||||
<a href="#" class="mc-btn">Shop</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<!-- User Hero Section -->
|
||||
<div class="mc-wood-panel user-hero">
|
||||
<div class="avatar-container">
|
||||
<!-- Using a pixelated avatar placeholder -->
|
||||
<img src="https://api.dicebear.com/7.x/pixel-art/svg?seed=Steve&backgroundColor=b6e3f4" alt="Avatar" class="avatar-img">
|
||||
</div>
|
||||
|
||||
<div class="user-details flex flex-col justify-center">
|
||||
<div class="flex items-center">
|
||||
<h1>CodeMaster2024</h1>
|
||||
</div>
|
||||
<div style="color: #ddd; font-size: 14px; margin-bottom: 10px;">Passionate problem solver</div>
|
||||
<div class="flex items-center">
|
||||
<div class="badge-lv"><i class="ri-shield-star-fill"></i> Lv.25</div>
|
||||
<div class="title-banner">Algorithm Expert</div>
|
||||
</div>
|
||||
|
||||
<div class="xp-bar-container">
|
||||
<div class="xp-bar-fill" id="mainXP" data-width="84.5%"></div>
|
||||
<div class="xp-text">8,450 / 10,000 XP</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-val">128</div>
|
||||
<div class="stat-label">Problems</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-val">456</div>
|
||||
<div class="stat-label">Submits</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-val">85%</div>
|
||||
<div class="stat-label">Acceptance</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-val">15🔥</div>
|
||||
<div class="stat-label">Streak</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Three Column Content -->
|
||||
<div class="main-content">
|
||||
<!-- Left Column -->
|
||||
<div class="left-col">
|
||||
<div class="col-card">
|
||||
<div class="col-card-inner">
|
||||
<div class="card-header">Difficulty Stats</div>
|
||||
<div class="pie-chart-wrap"></div>
|
||||
<div class="flex justify-center gap-4" style="font-size: 10px; margin-top: 10px;">
|
||||
<span style="color:var(--minecraft-green)">Easy</span>
|
||||
<span style="color:var(--gold)">Med</span>
|
||||
<span style="color:var(--red)">Hard</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-card">
|
||||
<div class="col-card-inner">
|
||||
<div class="card-header">Activity Log</div>
|
||||
<div style="font-size: 10px; color: #aaa; text-align: center; margin-bottom: 5px;">Last 30 Days</div>
|
||||
<div class="activity-grid" id="activityGrid">
|
||||
<!-- Generated by JS -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-card">
|
||||
<div class="col-card-inner">
|
||||
<div class="card-header">Timeline</div>
|
||||
<div class="flex flex-col gap-2" style="font-size: 10px; color: #ccc;">
|
||||
<div style="border-left: 2px solid #555; padding-left: 8px;">
|
||||
<div style="color: var(--minecraft-green)">Solved "Two Sum"</div>
|
||||
<div style="font-size: 8px; color: #888;">2 hours ago</div>
|
||||
</div>
|
||||
<div style="border-left: 2px solid #555; padding-left: 8px;">
|
||||
<div style="color: var(--red)">Failed "Dijkstra"</div>
|
||||
<div style="font-size: 8px; color: #888;">5 hours ago</div>
|
||||
</div>
|
||||
<div style="border-left: 2px solid #555; padding-left: 8px;">
|
||||
<div style="color: var(--gold)">Badge Unlocked</div>
|
||||
<div style="font-size: 8px; color: #888;">1 day ago</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Center Column -->
|
||||
<div class="center-col">
|
||||
<div class="col-card">
|
||||
<div class="col-card-inner">
|
||||
<div class="card-header">Achievement Wall</div>
|
||||
<div class="achievement-grid">
|
||||
<!-- 15 Slots: 5x3 -->
|
||||
<!-- Row 1 -->
|
||||
<div class="achievement-slot">
|
||||
<i class="ri-sword-fill achievement-icon" style="color: #cd7f32;"></i>
|
||||
<div class="tooltip">
|
||||
<div style="color: var(--gold)">Novice Slayer</div>
|
||||
<div style="margin-top:4px; color:#aaa">Solve 10 Easy</div>
|
||||
<div style="color: var(--minecraft-green)">+50 XP</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-slot">
|
||||
<i class="ri-sword-fill achievement-icon" style="color: #eee;"></i>
|
||||
<div class="tooltip">
|
||||
<div style="color: var(--gold)">Iron Will</div>
|
||||
<div style="margin-top:4px; color:#aaa">Solve 50 Medium</div>
|
||||
<div style="color: var(--minecraft-green)">+200 XP</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-sword-fill achievement-icon" style="color: var(--diamond);"></i>
|
||||
<div class="tooltip">LOCKED: Diamond Blade</div>
|
||||
</div>
|
||||
<div class="achievement-slot">
|
||||
<i class="ri-trophy-fill achievement-icon" style="color: var(--gold);"></i>
|
||||
<div class="tooltip">
|
||||
<div style="color: var(--gold)">Champion</div>
|
||||
<div style="margin-top:4px; color:#aaa">Win a Contest</div>
|
||||
<div style="color: var(--minecraft-green)">+1000 XP</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-slot">
|
||||
<i class="ri-book-3-fill achievement-icon" style="color: #a0522d;"></i>
|
||||
<div class="tooltip">
|
||||
<div style="color: var(--gold)">Scholar</div>
|
||||
<div style="margin-top:4px; color:#aaa">Read 100 Articles</div>
|
||||
<div style="color: var(--minecraft-green)">+100 XP</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Row 2 -->
|
||||
<div class="achievement-slot">
|
||||
<i class="ri-flask-fill achievement-icon" style="color: #ff69b4;"></i>
|
||||
<div class="tooltip">
|
||||
<div style="color: var(--gold)">Alchemist</div>
|
||||
<div style="margin-top:4px; color:#aaa">Optimize 10 times</div>
|
||||
<div style="color: var(--minecraft-green)">+150 XP</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-fire-fill achievement-icon" style="color: orange;"></i>
|
||||
<div class="tooltip">LOCKED: Inferno</div>
|
||||
</div>
|
||||
<div class="achievement-slot">
|
||||
<i class="ri-flashlight-fill achievement-icon" style="color: yellow;"></i>
|
||||
<div class="tooltip">
|
||||
<div style="color: var(--gold)">Speedster</div>
|
||||
<div style="margin-top:4px; color:#aaa">Solve in 5 mins</div>
|
||||
<div style="color: var(--minecraft-green)">+50 XP</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-star-fill achievement-icon" style="color: cyan;"></i>
|
||||
<div class="tooltip">LOCKED: Star Player</div>
|
||||
</div>
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-map-pin-user-fill achievement-icon" style="color: var(--minecraft-green);"></i>
|
||||
<div class="tooltip">LOCKED: Explorer</div>
|
||||
</div>
|
||||
|
||||
<!-- Row 3 -->
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-shield-fill achievement-icon" style="color: gray;"></i>
|
||||
<div class="tooltip">LOCKED: Guardian</div>
|
||||
</div>
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-hammer-fill achievement-icon" style="color: #ddd;"></i>
|
||||
<div class="tooltip">LOCKED: Builder</div>
|
||||
</div>
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-bug-fill achievement-icon" style="color: var(--red);"></i>
|
||||
<div class="tooltip">LOCKED: Bug Hunter</div>
|
||||
</div>
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-compass-3-fill achievement-icon" style="color: gold;"></i>
|
||||
<div class="tooltip">LOCKED: Navigator</div>
|
||||
</div>
|
||||
<div class="achievement-slot locked">
|
||||
<i class="ri-vip-crown-fill achievement-icon" style="color: var(--purple);"></i>
|
||||
<div class="tooltip">LOCKED: King</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-card">
|
||||
<div class="col-card-inner">
|
||||
<div class="card-header">Learning Path</div>
|
||||
<div class="path-row">
|
||||
<div class="path-label">
|
||||
<span>Basics</span>
|
||||
<span>100%</span>
|
||||
</div>
|
||||
<div class="path-track"><div class="path-fill" data-width="100%"></div></div>
|
||||
</div>
|
||||
<div class="path-row">
|
||||
<div class="path-label">
|
||||
<span>Algorithms</span>
|
||||
<span>75%</span>
|
||||
</div>
|
||||
<div class="path-track"><div class="path-fill" data-width="75%"></div></div>
|
||||
</div>
|
||||
<div class="path-row">
|
||||
<div class="path-label">
|
||||
<span>Data Structures</span>
|
||||
<span>60%</span>
|
||||
</div>
|
||||
<div class="path-track"><div class="path-fill" data-width="60%"></div></div>
|
||||
</div>
|
||||
<div class="path-row">
|
||||
<div class="path-label">
|
||||
<span>Advanced DP</span>
|
||||
<span>40%</span>
|
||||
</div>
|
||||
<div class="path-track"><div class="path-fill" data-width="40%"></div></div>
|
||||
</div>
|
||||
<div class="path-row">
|
||||
<div class="path-label">
|
||||
<span>Contest Prep</span>
|
||||
<span>20%</span>
|
||||
</div>
|
||||
<div class="path-track"><div class="path-fill" data-width="20%"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column -->
|
||||
<div class="right-col">
|
||||
<div class="col-card">
|
||||
<div class="col-card-inner">
|
||||
<div class="card-header">Leaderboard</div>
|
||||
<div class="leaderboard-item">
|
||||
<div class="rank">1</div>
|
||||
<div class="user">Notch <i class="ri-vip-crown-fill" style="color:gold"></i></div>
|
||||
<div class="score">99k</div>
|
||||
</div>
|
||||
<div class="leaderboard-item">
|
||||
<div class="rank">2</div>
|
||||
<div class="user">Jeb_ <i class="ri-medal-fill" style="color:silver"></i></div>
|
||||
<div class="score">85k</div>
|
||||
</div>
|
||||
<div class="leaderboard-item">
|
||||
<div class="rank">3</div>
|
||||
<div class="user">Alex <i class="ri-medal-fill" style="color:#cd7f32"></i></div>
|
||||
<div class="score">72k</div>
|
||||
</div>
|
||||
<div class="leaderboard-item">
|
||||
<div class="rank">4</div>
|
||||
<div class="user">Herobrine</div>
|
||||
<div class="score">66k</div>
|
||||
</div>
|
||||
<div class="leaderboard-item highlight">
|
||||
<div class="rank">5</div>
|
||||
<div class="user">CodeMaster</div>
|
||||
<div class="score">50k</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-card">
|
||||
<div class="col-card-inner">
|
||||
<div class="card-header">Daily Quests</div>
|
||||
<div class="task-item checked">
|
||||
<div class="checkbox-custom"></div>
|
||||
<div>Login</div>
|
||||
<div class="task-xp">10XP</div>
|
||||
</div>
|
||||
<div class="task-item checked">
|
||||
<div class="checkbox-custom"></div>
|
||||
<div>Solve 1 Easy</div>
|
||||
<div class="task-xp">20XP</div>
|
||||
</div>
|
||||
<div class="task-item checked">
|
||||
<div class="checkbox-custom"></div>
|
||||
<div>Review Code</div>
|
||||
<div class="task-xp">15XP</div>
|
||||
</div>
|
||||
<div class="task-item">
|
||||
<div class="checkbox-custom"></div>
|
||||
<div>Solve 1 Hard</div>
|
||||
<div class="task-xp">100XP</div>
|
||||
</div>
|
||||
<div class="task-item">
|
||||
<div class="checkbox-custom"></div>
|
||||
<div>Forum Post</div>
|
||||
<div class="task-xp">30XP</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-card">
|
||||
<div class="col-card-inner" style="display:flex; justify-content:center; align-items:center;">
|
||||
<div class="treasure-box" id="chestBtn">
|
||||
<div class="chest-glow"></div>
|
||||
<i class="ri-treasure-map-line chest-icon"></i>
|
||||
<div style="margin-top:10px; font-size: 10px; color: var(--gold);">Daily Reward</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reward Modal -->
|
||||
<div class="modal" id="rewardModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-inner">
|
||||
<h2>CHEST OPENED!</h2>
|
||||
<i class="ri-diamond-fill reward-icon" style="color: var(--diamond);"></i>
|
||||
<p>You found <span style="color:var(--gold); font-size: 20px;">500 XP</span></p>
|
||||
<p style="font-size: 10px; color: #aaa; margin-top: 10px;">Rare Item Found: Diamond Boots</p>
|
||||
<button class="close-btn" id="closeModal">CLAIM</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Animate XP Bar
|
||||
const xpBar = document.getElementById('mainXP');
|
||||
setTimeout(() => {
|
||||
xpBar.style.width = xpBar.getAttribute('data-width');
|
||||
}, 500);
|
||||
|
||||
// Animate Learning Paths
|
||||
const paths = document.querySelectorAll('.path-fill');
|
||||
paths.forEach(path => {
|
||||
setTimeout(() => {
|
||||
path.style.width = path.getAttribute('data-width');
|
||||
}, 800);
|
||||
});
|
||||
|
||||
// Activity Grid Generator
|
||||
const activityGrid = document.getElementById('activityGrid');
|
||||
for(let i=0; i<30; i++) {
|
||||
const cell = document.createElement('div');
|
||||
cell.className = 'activity-cell';
|
||||
// Random activity level 0-4
|
||||
const level = Math.random() > 0.3 ? Math.floor(Math.random() * 5) : 0;
|
||||
if(level > 0) cell.setAttribute('data-level', level);
|
||||
|
||||
// Add tooltip on hover
|
||||
cell.title = `Day ${30-i}: ${level*2} submissions`;
|
||||
activityGrid.appendChild(cell);
|
||||
}
|
||||
|
||||
// Task Checkbox Logic
|
||||
const tasks = document.querySelectorAll('.task-item');
|
||||
tasks.forEach(task => {
|
||||
task.addEventListener('click', () => {
|
||||
task.classList.toggle('checked');
|
||||
// Add simple sound effect logic here if audio was allowed
|
||||
});
|
||||
});
|
||||
|
||||
// Treasure Chest Logic
|
||||
const chestBtn = document.getElementById('chestBtn');
|
||||
const modal = document.getElementById('rewardModal');
|
||||
const closeBtn = document.getElementById('closeModal');
|
||||
|
||||
chestBtn.addEventListener('click', () => {
|
||||
modal.style.display = 'flex';
|
||||
});
|
||||
|
||||
closeBtn.addEventListener('click', () => {
|
||||
modal.style.display = 'none';
|
||||
});
|
||||
|
||||
// Close modal on outside click
|
||||
modal.addEventListener('click', (e) => {
|
||||
if(e.target === modal) {
|
||||
modal.style.display = 'none';
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
在新工单中引用
屏蔽一个用户