Files
silent-fh/src/highscore.py
T
2026-05-08 17:41:45 +02:00

137 lines
4.1 KiB
Python

import json
import pygame
from src.settings import HIGHSCORE_COLOR_FONT, HIGHSCORE_COLOR_TABLE
class Highscore:
def __init__(self):
# fix path to json file with highscores
self.path = "src/highscore.json"
self.font_title = pygame.font.SysFont("Arial", 28, bold=True)
self.font_score = pygame.font.SysFont("Arial", 18, bold=True)
# check if file already exists, otherwise create it
try:
with open(self.path, "r") as f:
pass
except FileNotFoundError:
self.save_scores([])
def load_scores(self):
"""
Will load the highscore json file.
:return: All scores form json file.
"""
with open(self.path, "r") as f:
return json.load(f)
def save_scores(self, scores):
"""
Write score data into json file. File will be overwritten.
:param scores: Scores to store in json highscore file.
:return: None.
"""
# save scores to file
with open(self.path, "w") as file:
json.dump(scores, file, indent=4)
def add_score(self, player_name, score_ects, time_survived, won):
"""
Add a new score to the list of existing scores from highscore file. The
number of entries is limited to 50.
:param player_name: Name of the player.
:param score_ects: Scored ECTS in game.
:param time_survived: Time survived in game.
:param won: Game won/lose.
:return: None.
"""
# load existing scores from file
scores = self.load_scores()
# assign values from new score and append to existing scores
new_score = {
"name": player_name,
"ects": score_ects,
"time": time_survived,
"won": won
}
scores.append(new_score)
# sort by ects descending
scores.sort(key=lambda score: score["ects"], reverse=True)
# keep only top 50 elements
scores = scores[:50]
self.save_scores(scores)
def get_top_scores(self):
"""
Get top 5 scores from highscore file.
:return: Return top 5 scores as list.
"""
scores = self.load_scores()
scores.sort(key=lambda score: score["ects"], reverse=True)
return scores[:5]
def get_top_scores_formatted(self):
"""
Get top 5 scores from highscore file in nice format.
:return: Return top 5 scores as formatted string in list.
"""
top_scores = self.get_top_scores()
formatted_scores = []
for index, score in enumerate(top_scores):
result = "PASSED" if score["won"] else "FAILED"
line = (
f"{index + 1}. {score['name']} | "
f"ECTS: {score['ects']} | "
f"Time: {score['time']} | "
f"Result: {result}"
)
formatted_scores.append(line)
return formatted_scores
def draw(self, screen, x, y):
# draw box background
box_rect = pygame.Rect(x, y, 500, 300)
pygame.draw.rect(screen, HIGHSCORE_COLOR_TABLE, box_rect, border_radius=12)
pygame.draw.rect(screen, HIGHSCORE_COLOR_TABLE, box_rect, border_radius=12)
# title
title = self.font_title.render(
"ECTS Leaderboard",
True,
HIGHSCORE_COLOR_FONT
)
screen.blit(title, (x + 20, y + 20))
# Get highscore lines
highscore_lines = self.get_top_scores_formatted()
if len(highscore_lines) == 0:
no_scores_text = self.font_score.render(
"No students ranked yet.",
True,
HIGHSCORE_COLOR_FONT
)
screen.blit(no_scores_text, (x + 20, y + 70))
return
# Draw scores
score_y = y + 70
for line in highscore_lines:
score_text = self.font_score.render(
line,
True,
HIGHSCORE_COLOR_FONT
)
screen.blit(score_text, (x + 20, score_y))
score_y += 35