Implement Score API Client and User Profile Integration

- Added ScoreAPIClient for communication with the Mice Game Score API, including methods for user signup, score submission, and leaderboard retrieval.
- Developed a simple profile manager demo to showcase user profile management and API integration.
- Created a test script for the Score API to validate all endpoints and functionality.
- Introduced UserProfileIntegration to manage user profiles, including local storage and API synchronization.
- Added a JSON file for user profiles with sample data for testing and demonstration purposes.
This commit is contained in:
2025-08-21 17:02:41 +02:00
parent 265af1832d
commit cbb60a19d9
17 changed files with 4923 additions and 36 deletions
+25 -7
View File
@@ -6,17 +6,35 @@ class Scoring:
# ==================== SCORING ====================
def save_score(self):
# Save to traditional scores.txt file
with open("scores.txt", "a") as f:
f.write(f"{datetime.datetime.now()} - {self.points}\n")
player_name = getattr(self, 'profile_integration', None)
if player_name and hasattr(player_name, 'get_profile_name'):
name = player_name.get_profile_name()
device_id = player_name.get_device_id()
f.write(f"{datetime.datetime.now()} - {self.points} - {name} - {device_id}\n")
else:
f.write(f"{datetime.datetime.now()} - {self.points} - Guest\n")
def read_score(self):
table = []
with open("scores.txt") as f:
rows = f.read().splitlines()
for row in rows:
table.append(row.split(" - "))
table.sort(key=lambda x: int(x[1]), reverse=True)
return table[:3]
try:
with open("scores.txt") as f:
rows = f.read().splitlines()
for row in rows:
parts = row.split(" - ")
if len(parts) >= 2:
# Handle both old format (date - score) and new format (date - score - name - device)
if len(parts) >= 4:
table.append([parts[0], parts[1], parts[2], parts[3]]) # date, score, name, device
elif len(parts) >= 3:
table.append([parts[0], parts[1], parts[2], "Unknown"]) # date, score, name, unknown device
else:
table.append([parts[0], parts[1], "Guest", "Unknown"]) # date, score, guest, unknown device
table.sort(key=lambda x: int(x[1]), reverse=True)
except FileNotFoundError:
pass
return table[:5] # Return top 5 scores instead of 3
def add_point(self, value):
self.points += value
+35 -15
View File
@@ -200,32 +200,52 @@ class GameWindow:
self.target_size[0] - 100, self.target_size[1] - 100,
"win", filling=(255, 255, 255))
# Draw main text
self.draw_text(text, self.fonts[self.target_size[1]//20], "center", sdl2.ext.Color(0, 0, 0))
# Calculate layout positions to avoid overlaps
title_y = self.target_size[1] // 4 # Title at 1/4 of screen height
# Draw subtitle if provided
if subtitle := kwargs.get("subtitle"):
self.draw_text(subtitle, self.fonts[self.target_size[1]//30],
("center", self.target_size[1] // 2 + 50), sdl2.ext.Color(0, 0, 0))
# Draw main text (title)
self.draw_text(text, self.fonts[self.target_size[1]//20],
("center", title_y), sdl2.ext.Color(0, 0, 0))
# Draw image if provided
# Draw image if provided - position it below title
image_bottom_y = title_y + 60 # Default position if no image
if image := kwargs.get("image"):
image_size = self.get_image_size(image)
image_y = title_y + 50
self.draw_image(self.target_size[0] // 2 - image_size[0] // 2 - self.w_offset,
self.target_size[1] // 2 - image_size[1] * 2 - self.h_offset,
image_y - self.h_offset,
image, "win")
image_bottom_y = image_y + image_size[1] + 20
# Draw scores if provided
# Draw subtitle if provided - handle multi-line text, position below image
if subtitle := kwargs.get("subtitle"):
subtitle_lines = subtitle.split('\n')
base_y = image_bottom_y + 20
line_height = 25 # Fixed line height for consistent spacing
for i, line in enumerate(subtitle_lines):
if line.strip(): # Only draw non-empty lines
self.draw_text(line.strip(), self.fonts[self.target_size[1]//35],
("center", base_y + i * line_height), sdl2.ext.Color(0, 0, 0))
# Draw scores if provided - position at bottom
if scores := kwargs.get("scores"):
sprite = self.factory.from_text("Scores:", color=sdl2.ext.Color(0, 0, 0),
fontmanager=self.fonts[self.target_size[1]//20])
sprite.position = (self.target_size[0] // 2 - 50, self.target_size[1] // 2 + 30)
scores_start_y = self.target_size[1] * 3 // 4 # Bottom quarter of screen
sprite = self.factory.from_text("High Scores:", color=sdl2.ext.Color(0, 0, 0),
fontmanager=self.fonts[self.target_size[1]//25])
sprite.position = (self.target_size[0] // 2 - sprite.size[0] // 2, scores_start_y)
self.renderer.copy(sprite, dstrect=sprite.position)
for i, score in enumerate(scores[:5]):
score_text = " - ".join(score)
self.draw_text(score_text, self.fonts[self.target_size[1]//40],
("center", self.target_size[1] // 2 + 50 + 30 * (i + 1)),
if len(score) >= 4: # New format: date, score, name, device
score_text = f"{score[2]}: {score[1]} pts ({score[3]})"
elif len(score) >= 3: # Medium format: date, score, name
score_text = f"{score[2]}: {score[1]} pts"
else: # Old format: date, score
score_text = f"Guest: {score[1]} pts"
self.draw_text(score_text, self.fonts[self.target_size[1]//45],
("center", scores_start_y + 30 + 25 * (i + 1)),
sdl2.ext.Color(0, 0, 0))
def start_dialog(self, **kwargs):