Compare commits
10
Commits
362b1b4b3a
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97bcceaf75 | ||
|
|
1a4d47d97e | ||
|
|
8470347b7a | ||
|
|
627cc1727e | ||
|
|
ebd4277685 | ||
|
|
e4aa7c5f13 | ||
|
|
450eeb1a6b | ||
|
|
bb7eb65bb3 | ||
|
|
6bd2c2f2d9 | ||
|
|
255d0d3a29 |
No files matched your search
@@ -1,3 +1,5 @@
|
||||
# Pokémon GO Level Calculator
|
||||
|
||||
Click here to browse to [https://justinoros.github.io/pogo/index.html](https://justinoros.github.io/pogo/index.html)
|
||||
Click to browse to [https://justinoros.github.io/pogo](https://justinoros.github.io/pogo)
|
||||
|
||||
This calculator was originally designed to estimate your level after reaching the level cap but can also be used to estimate how long it will take a player to reach the next level as well as max level.
|
||||
+144
-84
@@ -17,37 +17,67 @@
|
||||
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<style>
|
||||
body { font-family: 'Inter', sans-serif; }
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
position: relative;
|
||||
background: url('pogo-wallpaper.jpg') no-repeat center center fixed;
|
||||
background-size: cover;
|
||||
transition: background-color 0.4s, color 0.4s;
|
||||
}
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
background-image: radial-gradient(circle at 1px 1px, rgba(0,0,0,0.05) 1px, transparent 0);
|
||||
background-size: 20px 20px;
|
||||
opacity: 0.5;
|
||||
opacity: 0.8;
|
||||
z-index: -1;
|
||||
transition: background 0.4s, opacity 0.4s;
|
||||
}
|
||||
.cursor-pointer { cursor: pointer; }
|
||||
#edit-xp {
|
||||
display: inline-block;
|
||||
transform: scaleX(-1);
|
||||
.dark body::before {
|
||||
background: rgba(0,0,0,0.7);
|
||||
background-image: radial-gradient(circle at 1px 1px, rgba(255,255,255,0.08) 1px, transparent 0);
|
||||
opacity: 0.9;
|
||||
}
|
||||
.dark-mode {
|
||||
background-color: #0f172a;
|
||||
color: #f1f5f9;
|
||||
}
|
||||
.dark-mode .bg-white { background-color: #1e293b !important; }
|
||||
.dark-mode .text-slate-900 { color: #f1f5f9 !important; }
|
||||
.dark-mode .text-slate-500,
|
||||
.dark-mode .text-slate-600 { color: #cbd5e1 !important; }
|
||||
.dark-mode .border-slate-200 { border-color: #334155 !important; }
|
||||
.dark-mode input { background-color: #334155; color: #f1f5f9; }
|
||||
.dark-mode #progress-bar { background-color: #38bdf8 !important; }
|
||||
.dark-mode #theme-toggle { color: #facc15; }
|
||||
#theme-toggle {
|
||||
position: absolute;
|
||||
top: 0.75rem;
|
||||
right: 0.75rem;
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
#theme-toggle:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
#edit-xp { display: inline-block; transform: scaleX(-1); }
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-slate-50 flex items-center justify-center min-h-screen p-4">
|
||||
<body class="flex items-center justify-center min-h-screen p-4 transition-colors duration-500">
|
||||
|
||||
<div class="w-full max-w-md bg-white rounded-2xl shadow-xl p-6 md:p-8 border border-slate-200 text-center">
|
||||
|
||||
<div id="main-card" class="relative w-full max-w-md bg-white rounded-2xl shadow-xl p-6 md:p-8 border border-slate-200 text-center">
|
||||
<div id="theme-toggle">☀️</div>
|
||||
<img src="pogo.png" alt="Pokémon GO" class="mx-auto mb-4 w-32 h-auto">
|
||||
|
||||
<h1 class="text-2xl md:text-3xl font-bold text-slate-900 mb-4">Pokémon GO Level Calculator</h1>
|
||||
<p class="text-slate-500 mb-6">Enter your total XP to see your level</p>
|
||||
|
||||
|
||||
<div class="flex gap-2 mb-4 justify-center">
|
||||
<input type="text" id="xp-input" placeholder="e.g., 123,456,789"
|
||||
class="flex-1 px-4 py-3 border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400 text-center text-lg">
|
||||
|
||||
<button id="calculate-btn"
|
||||
class="w-12 h-12 bg-green-500 hover:bg-green-600 text-white font-bold rounded-lg transition-transform transform hover:scale-105">
|
||||
GO!
|
||||
@@ -76,84 +106,73 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const xpThresholds = [
|
||||
0, 1000, 3000, 6000, 10000, 15000, 21000, 28000, 36000, 45000,
|
||||
55000, 65000, 75000, 85000, 100000, 120000, 140000, 160000, 185000, 210000,
|
||||
260000, 335000, 435000, 560000, 710000, 900000, 1100000, 1350000, 1650000, 2000000,
|
||||
2500000, 3000000, 3750000, 4750000, 6000000, 7500000, 9500000, 12000000, 15000000, 20000000,
|
||||
26000000, 33500000, 42500000, 43500000, 66500000, 82000000, 100000000, 121000000, 146000000, 176000000,
|
||||
206000000, 236000000, 266000000, 296000000, 326000000, 356000000, 386000000, 416000000, 446000000, 476000000,
|
||||
506000000, 536000000, 566000000, 596000000, 626000000, 656000000, 686000000, 716000000, 746000000, 776000000,
|
||||
806000000, 836000000, 866000000, 896000000, 926000000, 956000000, 986000000, 1016000000, 1046000000, 1076000000,
|
||||
];
|
||||
<script>
|
||||
let xpThresholds = [];
|
||||
let avgXpPerDay = 15000;
|
||||
let currentXp = 0;
|
||||
let currentLevel = 1;
|
||||
|
||||
let avgXpPerDay = 15000;
|
||||
let currentXp = 0;
|
||||
let currentLevel = 1;
|
||||
async function loadXPThresholds() {
|
||||
try {
|
||||
const response = await fetch('levels.csv');
|
||||
const text = await response.text();
|
||||
|
||||
function calculateLevel(xp) {
|
||||
let level = 1;
|
||||
for (let i = 0; i < xpThresholds.length; i++) {
|
||||
if (xp >= xpThresholds[i]) {
|
||||
level = i + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return level;
|
||||
xpThresholds = text
|
||||
.trim()
|
||||
.split('\n')
|
||||
.map(line => {
|
||||
const parts = line.split(',');
|
||||
return parseInt(parts[1].replace(/,/g, ''), 10);
|
||||
});
|
||||
|
||||
console.log("Loaded XP thresholds (cumulative):", xpThresholds);
|
||||
} catch (error) {
|
||||
alert("Failed to load levels.csv. Please ensure it's in the same folder as index.html.");
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateLevel(xp) {
|
||||
let level = 1;
|
||||
for (let i = 0; i < xpThresholds.length; i++) {
|
||||
if (xp >= xpThresholds[i]) level = i + 1;
|
||||
else break;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
function formatDays(days) {
|
||||
if (days > 365) return (days / 365).toFixed(1) + ' years';
|
||||
return days.toLocaleString() + ' days';
|
||||
}
|
||||
|
||||
function updateExtraInfo() {
|
||||
const maxLevel = xpThresholds.length;
|
||||
const maxXp = xpThresholds[maxLevel - 1];
|
||||
|
||||
if (currentXp >= maxXp) {
|
||||
document.getElementById('extra-info').innerHTML = `
|
||||
<p class="text-green-600 font-semibold text-lg">
|
||||
🎉 Congratulations! You're max level!
|
||||
</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
function formatDays(days) {
|
||||
if (days > 365) {
|
||||
return (days / 365).toFixed(1) + ' years';
|
||||
}
|
||||
return days.toLocaleString() + ' days';
|
||||
}
|
||||
let nextLevelXp = (currentLevel < xpThresholds.length) ? xpThresholds[currentLevel] : currentXp;
|
||||
let xpToNext = Math.max(0, nextLevelXp - currentXp);
|
||||
let xpTo40 = Math.max(0, xpThresholds[39] - currentXp);
|
||||
let xpTo80 = Math.max(0, xpThresholds[79] - currentXp);
|
||||
|
||||
function updateExtraInfo() {
|
||||
let nextLevelXp = (currentLevel < xpThresholds.length) ? xpThresholds[currentLevel] : currentXp;
|
||||
let xpToNext = Math.max(0, nextLevelXp - currentXp);
|
||||
let xpTo40 = Math.max(0, xpThresholds[39] - currentXp); // Level 40
|
||||
let xpTo80 = Math.max(0, xpThresholds[79] - currentXp);
|
||||
let daysNext = Math.ceil(xpToNext / avgXpPerDay);
|
||||
let days40 = Math.ceil(xpTo40 / avgXpPerDay);
|
||||
let days80 = Math.ceil(xpTo80 / avgXpPerDay);
|
||||
|
||||
let daysNext = Math.ceil(xpToNext / avgXpPerDay);
|
||||
let days40 = Math.ceil(xpTo40 / avgXpPerDay);
|
||||
let days80 = Math.ceil(xpTo80 / avgXpPerDay);
|
||||
const nextText = currentLevel < 40
|
||||
? `If you average ${avgXpPerDay.toLocaleString()} XP per day, you will reach the next level in ${formatDays(daysNext)}, level 40 in ${formatDays(days40)}, and level 80 in ${formatDays(days80)}.`
|
||||
: `If you average ${avgXpPerDay.toLocaleString()} XP per day, you will reach the next level in ${formatDays(daysNext)} and level 80 in ${formatDays(days80)}.`;
|
||||
|
||||
const nextText = currentLevel < 40
|
||||
? `If you average ${avgXpPerDay.toLocaleString()} XP per day, you will reach the next level in ${formatDays(daysNext)}, level 40 in ${formatDays(days40)}, and level 80 in ${formatDays(days80)}.`
|
||||
: `If you average ${avgXpPerDay.toLocaleString()} XP per day, you will reach the next level in ${formatDays(daysNext)} and level 80 in ${formatDays(days80)}.`;
|
||||
|
||||
document.getElementById('extra-info').innerHTML = `<p>${nextText} <span id="edit-xp" class="ml-1 text-blue-500 cursor-pointer">✏️</span></p>`;
|
||||
}
|
||||
|
||||
document.getElementById('calculate-btn').addEventListener('click', () => {
|
||||
let xp = document.getElementById('xp-input').value.replace(/,/g,'').trim();
|
||||
if (!xp || isNaN(xp)) {
|
||||
alert('Please enter a valid number for XP.');
|
||||
return;
|
||||
}
|
||||
currentXp = parseInt(xp, 10);
|
||||
|
||||
currentLevel = calculateLevel(currentXp);
|
||||
let nextLevelXp = (currentLevel < xpThresholds.length) ? xpThresholds[currentLevel] : currentXp;
|
||||
let currentLevelXp = xpThresholds[currentLevel - 1];
|
||||
let progress = (currentXp - currentLevelXp) / (nextLevelXp - currentLevelXp) * 100;
|
||||
|
||||
document.getElementById('progress-bar').style.width = progress + '%';
|
||||
document.getElementById('level-text').textContent = `Level ${currentLevel}`;
|
||||
document.getElementById('level-left').textContent = currentLevel;
|
||||
document.getElementById('level-right').textContent = (currentLevel < xpThresholds.length) ? currentLevel + 1 : currentLevel;
|
||||
|
||||
document.getElementById('result').classList.remove('hidden');
|
||||
|
||||
updateExtraInfo();
|
||||
});
|
||||
|
||||
document.getElementById('xp-input').addEventListener('input', (e)=>{
|
||||
e.target.value = e.target.value.replace(/[^0-9,]/g,'');
|
||||
});
|
||||
document.getElementById('extra-info').innerHTML = `
|
||||
<p>${nextText} <span id="edit-xp" class="ml-1 text-blue-500 cursor-pointer">✏️</span></p>`;
|
||||
|
||||
document.getElementById('edit-xp').addEventListener('click', () => {
|
||||
let newVal = prompt("Enter your average XP per day:", avgXpPerDay);
|
||||
@@ -162,7 +181,48 @@
|
||||
updateExtraInfo();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
||||
document.getElementById('calculate-btn').addEventListener('click', () => {
|
||||
if (xpThresholds.length === 0) {
|
||||
alert('Level data not loaded yet. Please wait a moment and try again.');
|
||||
return;
|
||||
}
|
||||
|
||||
let xp = document.getElementById('xp-input').value.replace(/,/g, '').trim();
|
||||
if (!xp || isNaN(xp)) {
|
||||
alert('Please enter a valid number for XP.');
|
||||
return;
|
||||
}
|
||||
|
||||
currentXp = parseInt(xp, 10);
|
||||
currentLevel = calculateLevel(currentXp);
|
||||
|
||||
let nextLevelXp = (currentLevel < xpThresholds.length) ? xpThresholds[currentLevel] : currentXp;
|
||||
let currentLevelXp = xpThresholds[currentLevel - 1];
|
||||
let progress = (currentXp - currentLevelXp) / (nextLevelXp - currentLevelXp) * 100;
|
||||
|
||||
document.getElementById('progress-bar').style.width = progress + '%';
|
||||
document.getElementById('level-text').textContent = `Level ${currentLevel}`;
|
||||
document.getElementById('level-left').textContent = currentLevel;
|
||||
document.getElementById('level-right').textContent = (currentLevel < xpThresholds.length) ? currentLevel + 1 : currentLevel;
|
||||
|
||||
document.getElementById('result').classList.remove('hidden');
|
||||
updateExtraInfo();
|
||||
});
|
||||
|
||||
document.getElementById('xp-input').addEventListener('input', (e) => {
|
||||
e.target.value = e.target.value.replace(/[^0-9,]/g, '');
|
||||
});
|
||||
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
themeToggle.addEventListener('click', () => {
|
||||
document.body.classList.toggle('dark-mode');
|
||||
themeToggle.textContent = document.body.classList.contains('dark-mode') ? '🌙' : '☀️';
|
||||
});
|
||||
|
||||
window.addEventListener('DOMContentLoaded', loadXPThresholds);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
1,0
|
||||
2,2500
|
||||
3,3000
|
||||
4,3500
|
||||
5,4000
|
||||
6,5000
|
||||
7,6000
|
||||
8,7000
|
||||
9,8000
|
||||
10,9000
|
||||
11,10000
|
||||
12,12000
|
||||
13,14000
|
||||
14,16000
|
||||
15,18000
|
||||
16,21000
|
||||
17,24500
|
||||
18,28000
|
||||
19,31500
|
||||
20,35000
|
||||
21,42000
|
||||
22,49000
|
||||
23,56000
|
||||
24,63000
|
||||
25,70000
|
||||
26,83000
|
||||
27,96000
|
||||
28,109000
|
||||
29,122000
|
||||
30,135000
|
||||
31,158000
|
||||
32,181000
|
||||
33,204000
|
||||
34,227000
|
||||
35,250000
|
||||
36,290000
|
||||
37,330000
|
||||
38,370000
|
||||
39,410000
|
||||
40,450000
|
||||
41,520000
|
||||
42,590000
|
||||
43,660000
|
||||
44,730000
|
||||
45,800000
|
||||
46,900000
|
||||
47,1000000
|
||||
48,1100000
|
||||
49,1200000
|
||||
50,1300000
|
||||
51,1440000
|
||||
52,1580000
|
||||
53,1720000
|
||||
54,1860000
|
||||
55,2000000
|
||||
56,2200000
|
||||
57,2400000
|
||||
58,2600000
|
||||
59,2800000
|
||||
60,3000000
|
||||
61,3350000
|
||||
62,3700000
|
||||
63,4050000
|
||||
64,4400000
|
||||
65,4750000
|
||||
66,5250000
|
||||
67,5750000
|
||||
68,6250000
|
||||
69,6750000
|
||||
70,7250000
|
||||
71,8000000
|
||||
72,8750000
|
||||
73,9500000
|
||||
74,10250000
|
||||
75,11000000
|
||||
76,12000000
|
||||
77,13000000
|
||||
78,14000000
|
||||
79,15000000
|
||||
80,16000000
|
||||
|
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
Reference in new issue
Block a user