SpecMonitor / index.html
tuhbooh's picture
Update index.html
a73c196 verified
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Professional Hardware Diagnostic - Ultra Accuracy</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;700;900&display=swap');
body {
font-family: 'Inter', sans-serif;
background-color: #ffffff;
color: #111111;
overflow-y: auto;
overflow-x: hidden;
}
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
min-height: 100vh;
padding: 8vh 0;
}
.score-container {
display: flex;
align-items: baseline;
justify-content: center;
min-height: 12rem;
margin-bottom: 0.5rem;
}
.main-number {
font-size: clamp(6rem, 22vw, 16rem);
font-weight: 900;
line-height: 1;
letter-spacing: -0.06em;
font-variant-numeric: tabular-nums;
}
.unit {
font-size: clamp(1.2rem, 4vw, 2.5rem);
font-weight: 400;
color: #aaaaaa;
margin-left: 10px;
}
.status-text {
font-size: 11px;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 0.4em;
color: #bbbbbb;
margin-bottom: 2rem;
height: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
}
.progress-bar {
position: fixed;
top: 0; left: 0;
height: 4px;
background: #000;
width: 0%;
transition: width 0.4s cubic-bezier(0.1, 0.5, 0.5, 1);
z-index: 100;
}
.grid-label {
font-size: 10px;
color: #94a3b8;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 0.1em;
}
.result-item {
opacity: 0;
transform: translateY(20px);
transition: all 0.8s cubic-bezier(0.2, 1, 0.3, 1);
}
.result-item.show {
opacity: 1;
transform: translateY(0);
}
.loader {
width: 20px; height: 20px;
border: 2px solid #f1f5f9;
border-top: 2px solid #000;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
.detail-value {
font-size: 1.5rem;
font-weight: 700;
color: #0f172a;
}
</style>
</head>
<body>
<div id="progress" class="progress-bar"></div>
<div class="wrapper">
<main class="text-center w-full max-w-5xl px-8">
<div id="status" class="status-text">Đang khởi tạo môi trường tin cậy...</div>
<div class="score-container">
<span id="score" class="main-number">0</span>
<span id="unit-label" class="unit opacity-0">INDEX</span>
</div>
<div id="loading-box" class="h-10 flex flex-col justify-center items-center gap-2">
<div class="loader"></div>
<span id="sub-status" class="text-[9px] text-gray-400 font-bold uppercase tracking-widest">Warming up</span>
</div>
<div id="results-grid" class="mt-20 grid grid-cols-2 md:grid-cols-3 gap-y-16 gap-x-8">
<div class="result-item">
<div class="grid-label mb-2">Computational (CPU)</div>
<div id="res-cpu" class="detail-value">--</div>
<div class="text-[9px] text-gray-400 mt-1 font-bold">POINTS</div>
</div>
<div class="result-item border-x border-gray-100">
<div class="grid-label mb-2">Memory (RAM)</div>
<div id="res-ram" class="detail-value">--</div>
<div class="text-[9px] text-gray-400 mt-1 font-bold">POINTS</div>
</div>
<div class="result-item">
<div class="grid-label mb-2">Storage (I/O)</div>
<div id="res-disk" class="detail-value">--</div>
<div class="text-[9px] text-gray-400 mt-1 font-bold">POINTS</div>
</div>
<div class="result-item">
<div class="grid-label mb-2">Graphics (GPU)</div>
<div id="res-gpu" class="detail-value">--</div>
<div class="text-[9px] text-gray-400 mt-1 font-bold">POINTS</div>
</div>
<div class="result-item border-x border-gray-100">
<div class="grid-label mb-2">Network (RTT)</div>
<div id="res-net" class="detail-value">--</div>
<div class="text-[9px] text-gray-400 mt-1 font-bold">MS</div>
</div>
<div class="result-item">
<div class="grid-label mb-2">Reliability</div>
<div id="res-lat" class="detail-value">--</div>
<div class="text-[9px] text-gray-400 mt-1 font-bold">STABILITY %</div>
</div>
</div>
<div class="mt-20 h-12 flex items-center justify-center">
<button id="retry-btn" onclick="location.reload()" class="px-14 py-4 bg-black text-white text-[10px] font-black tracking-[0.5em] rounded-full hover:bg-gray-800 transition-all hidden shadow-2xl active:scale-95">
RE-BENCHMARK
</button>
</div>
</main>
</div>
<canvas id="gpuCanvas" width="500" height="500" class="hidden"></canvas>
<script>
const scoreEl = document.getElementById('score');
const statusEl = document.getElementById('status');
const subStatusEl = document.getElementById('sub-status');
const progressEl = document.getElementById('progress');
const unitEl = document.getElementById('unit-label');
const loadingBox = document.getElementById('loading-box');
const retryBtn = document.getElementById('retry-btn');
const items = document.querySelectorAll('.result-item');
const DB_NAME = "UltraReliable_v8";
let totalScore = 0;
// Cơ chế dọn dẹp triệt để
async function fullCleanup() {
return new Promise(r => {
const req = indexedDB.deleteDatabase(DB_NAME);
req.onsuccess = req.onerror = () => r();
});
}
function animateValue(target) {
let start = totalScore;
const duration = 1500;
const startTime = performance.now();
function step(now) {
const prog = Math.min((now - startTime) / duration, 1);
const ease = 1 - Math.pow(1 - prog, 4);
const val = Math.floor(start + (target - start) * ease);
scoreEl.innerText = val.toLocaleString();
if (prog < 1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
totalScore = target;
}
async function run() {
await fullCleanup();
// 1. CPU MATRIX BENCHMARK (Độ chính xác cao)
statusEl.innerText = "Đang đo Computational Power...";
subStatusEl.innerText = "Matrix multiplication (512x512)";
progressEl.style.width = "20%";
const cpuResult = await runCPUBenchmark();
document.getElementById('res-cpu').innerText = cpuResult.score.toLocaleString();
items[0].classList.add('show');
animateValue(cpuResult.score);
// 2. RAM THROUGHPUT (Đo 3 vòng lấy trung bình)
statusEl.innerText = "Đang phân tích Memory Bandwidth...";
subStatusEl.innerText = "64-bit array traversal";
progressEl.style.width = "40%";
const ramScore = await runRAMBenchmark();
document.getElementById('res-ram').innerText = ramScore.toLocaleString();
items[1].classList.add('show');
animateValue(totalScore + ramScore);
// 3. STORAGE I/O (Benchmark & Clean)
statusEl.innerText = "Kiểm tra tốc độ đọc/ghi ổ đĩa...";
subStatusEl.innerText = "IndexedDB Blobs (50MB)";
progressEl.style.width = "60%";
const diskScore = await runDiskBenchmark();
document.getElementById('res-disk').innerText = diskScore.toLocaleString();
items[2].classList.add('show');
animateValue(totalScore + diskScore);
// 4. GRAPHICS (GPU Render Peak)
statusEl.innerText = "Tính toán khả năng xử lý đồ họa...";
subStatusEl.innerText = "Canvas 2D Stress Test";
progressEl.style.width = "80%";
const gpuScore = await runGPUBenchmark();
document.getElementById('res-gpu').innerText = gpuScore.toLocaleString();
items[3].classList.add('show');
// 5. NETWORK & RELIABILITY
statusEl.innerText = "Phân tích độ ổn định hệ thống...";
subStatusEl.innerText = "Measuring Jitter & Latency";
const net = await getNetwork();
const reliability = await getReliability();
document.getElementById('res-net').innerText = net;
document.getElementById('res-lat').innerText = reliability;
items[4].classList.add('show');
items[5].classList.add('show');
progressEl.style.width = "100%";
statusEl.innerText = "Tất cả dữ liệu tạm thời đã được dọn sạch";
loadingBox.style.display = 'none';
unitEl.classList.remove('opacity-0');
retryBtn.classList.remove('hidden');
animateValue(totalScore + gpuScore + (parseFloat(reliability) * 25));
}
// --- THUẬT TOÁN SIÊU CHÍNH XÁC ---
async function runCPUBenchmark() {
const size = 512;
const a = new Float64Array(size * size).fill(Math.random());
const b = new Float64Array(size * size).fill(Math.random());
const c = new Float64Array(size * size);
let samples = [];
for(let loop=0; loop<3; loop++) {
const start = performance.now();
// Phép nhân ma trận truyền thống (O(n^3))
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
let sum = 0;
for (let k = 0; k < size; k++) {
sum += a[i * size + k] * b[k * size + j];
}
c[i * size + j] = sum;
}
}
const end = performance.now();
samples.push(size**3 / (end - start));
}
const avg = samples.reduce((a,b)=>a+b)/samples.length;
// Quy đổi sang điểm số chuẩn hóa
return { score: Math.round(avg * 0.05) };
}
async function runRAMBenchmark() {
const size = 32 * 1024 * 1024; // 32MB
const arr = new BigUint64Array(size);
const start = performance.now();
for(let i=0; i<size; i++) arr[i] = BigInt(i);
const end = performance.now();
const gbps = (size * 8) / ((end - start) / 1000) / 1e9;
return Math.round(gbps * 600);
}
async function runDiskBenchmark() {
return new Promise(r => {
const req = indexedDB.open(DB_NAME, 1);
req.onupgradeneeded = e => e.target.result.createObjectStore("data");
req.onsuccess = e => {
const db = e.target.result;
const blob = new Uint8Array(50 * 1024 * 1024).fill(7);
const start = performance.now();
const tx = db.transaction("data", "readwrite");
tx.objectStore("data").put(blob, "test");
tx.oncomplete = async () => {
const mbps = 50 / ((performance.now() - start) / 1000);
db.close();
await fullCleanup(); // Dọn dẹp ngay lập tức
r(Math.round(mbps * 12));
};
};
});
}
async function runGPUBenchmark() {
return new Promise(r => {
const canvas = document.getElementById('gpuCanvas');
const ctx = canvas.getContext('2d');
let frames = 0;
const startTime = performance.now();
function draw() {
ctx.clearRect(0, 0, 500, 500);
for(let i=0; i<30000; i++) {
ctx.fillStyle = `rgb(${i%255},0,0)`;
ctx.fillRect(Math.random()*500, Math.random()*500, 2, 2);
}
frames++;
if(performance.now() - startTime < 2000) requestAnimationFrame(draw);
else r(Math.round((frames/2) * 250));
}
draw();
});
}
async function getNetwork() {
const start = performance.now();
try {
await fetch('https://www.google.com/favicon.ico', { mode: 'no-cors', cache: 'no-cache' });
return Math.round(performance.now() - start);
} catch {
return "--";
}
}
async function getReliability() {
let samples = [];
for(let i=0; i<20; i++) {
const s = performance.now();
// Test micro-task latency
await new Promise(res => setTimeout(res, 0));
samples.push(performance.now() - s);
}
const avg = samples.reduce((a,b)=>a+b)/samples.length;
const variance = samples.reduce((a,b)=> a + Math.pow(b-avg, 2), 0) / samples.length;
const stdDev = Math.sqrt(variance);
// Stability tính bằng 100% trừ đi tỉ lệ biến thiên
const stability = Math.max(0, 100 - (stdDev / avg * 100));
return stability.toFixed(1);
}
window.onload = () => setTimeout(run, 1200);
</script>
</body>
</html>