mirror of
https://github.com/Coldsmiles/infstarweb.git
synced 2026-04-23 02:30:41 +08:00
Add play time tracking to player stats and update leaderboard
This commit is contained in:
15
stats.html
15
stats.html
@@ -326,6 +326,17 @@
|
|||||||
<div class="lb-top-player">加载中...</div>
|
<div class="lb-top-player">加载中...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 5. Play Time -->
|
||||||
|
<div class="lb-card" style="border-top: 4px solid #9b59b6;">
|
||||||
|
<div class="lb-header">
|
||||||
|
<div class="lb-icon"><i class="fas fa-crown"></i></div>
|
||||||
|
<div class="lb-title">尊者</div>
|
||||||
|
</div>
|
||||||
|
<div class="lb-content" id="lb-playtime">
|
||||||
|
<div class="lb-top-player">加载中...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Search & Grid -->
|
<!-- Search & Grid -->
|
||||||
@@ -374,6 +385,10 @@
|
|||||||
<span class="stat-label"><i class="fas fa-skull"></i> 死亡次数</span>
|
<span class="stat-label"><i class="fas fa-skull"></i> 死亡次数</span>
|
||||||
<span class="stat-value" id="modal-deaths">0</span>
|
<span class="stat-value" id="modal-deaths">0</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-row">
|
||||||
|
<span class="stat-label"><i class="fas fa-crown"></i> 游玩时间</span>
|
||||||
|
<span class="stat-value" id="modal-playtime">0 秒</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ function renderLeaderboards() {
|
|||||||
if (key === 'walk_fmt') valA = a.stats.walk_raw;
|
if (key === 'walk_fmt') valA = a.stats.walk_raw;
|
||||||
if (key === 'walk_fmt') valB = b.stats.walk_raw;
|
if (key === 'walk_fmt') valB = b.stats.walk_raw;
|
||||||
|
|
||||||
|
// Special case for play_time which has raw sorting value
|
||||||
|
if (key === 'play_time_fmt') valA = a.stats.play_time_raw;
|
||||||
|
if (key === 'play_time_fmt') valB = b.stats.play_time_raw;
|
||||||
|
|
||||||
return valB - valA;
|
return valB - valA;
|
||||||
})
|
})
|
||||||
.slice(0, 4); // Top 4
|
.slice(0, 4); // Top 4
|
||||||
@@ -136,6 +140,10 @@ function renderLeaderboards() {
|
|||||||
// 4. Deaths (stats.deaths)
|
// 4. Deaths (stats.deaths)
|
||||||
const topDeaths = getTop('deaths');
|
const topDeaths = getTop('deaths');
|
||||||
renderCard('lb-deaths', topDeaths, p => p.stats.deaths);
|
renderCard('lb-deaths', topDeaths, p => p.stats.deaths);
|
||||||
|
|
||||||
|
// 5. Play Time (stats.play_time_raw)
|
||||||
|
const topPlayTime = getTop('play_time_fmt'); // uses play_time_raw internally
|
||||||
|
renderCard('lb-playtime', topPlayTime, p => p.stats.play_time_fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPlayerGrid(reset = false) {
|
function renderPlayerGrid(reset = false) {
|
||||||
@@ -220,6 +228,7 @@ function openModal(player) {
|
|||||||
document.getElementById('modal-placed').innerText = player.stats.placed.toLocaleString();
|
document.getElementById('modal-placed').innerText = player.stats.placed.toLocaleString();
|
||||||
document.getElementById('modal-mined').innerText = player.stats.mined.toLocaleString();
|
document.getElementById('modal-mined').innerText = player.stats.mined.toLocaleString();
|
||||||
document.getElementById('modal-deaths').innerText = player.stats.deaths;
|
document.getElementById('modal-deaths').innerText = player.stats.deaths;
|
||||||
|
document.getElementById('modal-playtime').innerText = player.stats.play_time_fmt;
|
||||||
|
|
||||||
modal.style.display = "flex";
|
modal.style.display = "flex";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,9 @@ from tqdm import tqdm # Add tqdm for progress bars
|
|||||||
|
|
||||||
BASE_URL = "http://x2.sjcmc.cn:15960/stats/"
|
BASE_URL = "http://x2.sjcmc.cn:15960/stats/"
|
||||||
STATS_DIR = "stats"
|
STATS_DIR = "stats"
|
||||||
IMAGE_DIR = os.path.join(STATS_DIR, "images")
|
|
||||||
|
|
||||||
# Ensure directories exist
|
# Ensure directories exist
|
||||||
os.makedirs(STATS_DIR, exist_ok=True)
|
os.makedirs(STATS_DIR, exist_ok=True)
|
||||||
os.makedirs(IMAGE_DIR, exist_ok=True)
|
|
||||||
|
|
||||||
print("Fetching file list...")
|
print("Fetching file list...")
|
||||||
try:
|
try:
|
||||||
@@ -114,6 +112,24 @@ def process_player(filename):
|
|||||||
|
|
||||||
walk_fmt = format_dist(walk_cm)
|
walk_fmt = format_dist(walk_cm)
|
||||||
|
|
||||||
|
# Play Time (1 tick = 1/20 second)
|
||||||
|
play_time_ticks = custom.get('minecraft:play_time', 0)
|
||||||
|
|
||||||
|
def format_time(ticks):
|
||||||
|
seconds = ticks / 20
|
||||||
|
if seconds < 60:
|
||||||
|
return f"{seconds:.3f} 秒"
|
||||||
|
minutes = seconds / 60
|
||||||
|
if minutes < 60:
|
||||||
|
return f"{minutes:.3f} 分钟"
|
||||||
|
hours = minutes / 60
|
||||||
|
if hours < 24:
|
||||||
|
return f"{hours:.3f} 小时"
|
||||||
|
days = hours / 24
|
||||||
|
return f"{days:.3f} 天"
|
||||||
|
|
||||||
|
play_time_fmt = format_time(play_time_ticks)
|
||||||
|
|
||||||
# Mined
|
# Mined
|
||||||
mined = stats.get('minecraft:mined', {})
|
mined = stats.get('minecraft:mined', {})
|
||||||
total_mined = sum(mined.values())
|
total_mined = sum(mined.values())
|
||||||
@@ -133,7 +149,9 @@ def process_player(filename):
|
|||||||
'walk_cm': walk_cm,
|
'walk_cm': walk_cm,
|
||||||
'total_mined': total_mined,
|
'total_mined': total_mined,
|
||||||
'total_placed': total_placed,
|
'total_placed': total_placed,
|
||||||
'total_deaths': total_deaths
|
'total_deaths': total_deaths,
|
||||||
|
'play_time_fmt': play_time_fmt,
|
||||||
|
'play_time_ticks': play_time_ticks
|
||||||
}
|
}
|
||||||
|
|
||||||
# Save
|
# Save
|
||||||
@@ -149,7 +167,9 @@ def process_player(filename):
|
|||||||
'walk_raw': walk_cm,
|
'walk_raw': walk_cm,
|
||||||
'mined': total_mined,
|
'mined': total_mined,
|
||||||
'placed': total_placed,
|
'placed': total_placed,
|
||||||
'deaths': total_deaths
|
'deaths': total_deaths,
|
||||||
|
'play_time_fmt': play_time_fmt,
|
||||||
|
'play_time_raw': play_time_ticks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user