Kaynağa Gözat

small changes

Brayden 7 ay önce
ebeveyn
işleme
5382664c01
4 değiştirilmiş dosya ile 185 ekleme ve 55 silme
  1. 184 55
      GUI.py
  2. BIN
      __pycache__/dobluetooth.cpython-312.pyc
  3. 1 0
      all_scores.txt
  4. BIN
      ding.mp3

+ 184 - 55
GUI.py

@@ -7,6 +7,17 @@ import threading
 import tkinter as tk
 import dobluetooth
 import math
+import pygame
+
+# Initialize pygame and mixer specifically for MP3
+pygame.init()
+pygame.mixer.init(frequency=44100, size=-16, channels=2, buffer=2048)
+try:
+    stop_sound = pygame.mixer.Sound("ding.mp3")
+    print("Successfully loaded sound file")
+except Exception as e:
+    print(f"Warning: Could not load sound file: {str(e)}")
+    stop_sound = None
 
 # If on Windows, allow STA for Bleak
 if platform.system() == "Windows":
@@ -33,62 +44,192 @@ currentScore.set(0)
 
 names = []
 scores = []
+nameEntry = None
+enterButton = None
+statusLabel = None
+dinger = None
+bell_image = None  # Store the image reference
 
-highestScore = 100
+highestScore = 0
 highScoreName = ""
 
 punch_on = False
+current_dinger_y = 900
+
+def move_dinger_step(start_y, target_y, steps_left, total_steps):
+    global current_dinger_y
+    if steps_left > 0:
+        # Calculate progress (0 to 1)
+        progress = (total_steps - steps_left) / total_steps
+        
+        # Calculate the current position directly between start and target
+        new_y = start_y + (target_y - start_y) * progress
+        
+        # Update position
+        current_dinger_y = new_y
+        dinger.place_configure(y=int(new_y))
+        
+        # Schedule next step
+        app.after(10, lambda: move_dinger_step(start_y, target_y, steps_left - 1, total_steps))
+    else:
+        # Ensure we end up exactly at target
+        current_dinger_y = target_y
+        dinger.place_configure(y=int(target_y))
+
+def update_dinger_position(final_score=None):
+    global current_dinger_y
+    start_y = current_dinger_y  # Remember where we're starting from
+    
+    if final_score is None:
+        target_y = 900  # Bottom position
+    else:
+        # Calculate target position based on score
+        max_movement = 600
+        score_threshold = 100
+
+        # Calculate new position
+        movement = (final_score / score_threshold) * max_movement
+        movement = min(movement, max_movement)
+        target_y = 900 - movement  # Calculate from top position
+        target_y = max(100, min(target_y, 900))  # Ensure within bounds
+    
+    # Start the animation
+    move_dinger_step(start_y, target_y, 60, 60)
 
-# Punch control
 def startPunch():
     global punch_on
     punch_on = True
-    print("STARTED PUNCH")
+    updateStatusLabel()
+    update_dinger_position()
 
 def stopPunch():
-    global punch_on, highestScore
+    global punch_on
     punch_on = False
-    print("STOPPED PUNCH")
-
-    if currentScore.get() > highestScore:
-        highestScore = currentScore.get()
+    updateStatusLabel()
+    update_dinger_position(currentScore.get())
+    if stop_sound:
         try:
-            with open("scores.txt", "w") as f:  # Fixed mode from "rw" to "w"
-                f.write(f"{highestScore} {highScoreName}")
+            stop_sound.play()
         except Exception as e:
-            print("Error writing to file:", e)
-
-        scores.append(highestScore)
-        names.append(highScoreName)
+            print(f"Error playing sound: {str(e)}")
 
 def resetPunch():
     global currentScore
     currentScore.set(0)
-    print("reset punch")
+    update_dinger_position(0)
 
-dinger = ctk.CTkLabel(width=40, height=30, text="", fg_color="gray77", master=app)
-dinger.place(x=1405, y=900)
+def load_scores():
+    global names, scores, highestScore, highScoreName
+    try:
+        with open("all_scores.txt", "r") as f:
+            lines = f.readlines()
+            for line in lines:
+                name, score = line.strip().split(",")
+                score = float(score)
+                names.append(name)
+                scores.append(score)
+                if score > highestScore:
+                    highestScore = score
+                    highScoreName = name
+    except FileNotFoundError:
+        # Create the file if it doesn't exist
+        with open("all_scores.txt", "w") as f:
+            pass
+
+def save_new_score(name, score):
+    with open("all_scores.txt", "a") as f:
+        f.write(f"{name},{score}\n")
+
+def updateStatusLabel():
+    global statusLabel
+    if punch_on:
+        statusLabel.configure(text="RECORDING", fg_color="green", text_color="white")
+    else:
+        statusLabel.configure(text="NOT RECORDING", fg_color="gray70", text_color="black")
+
+def submitScore():
+    global highestScore, highScoreName
+    # Get the name from the entry field
+    entered_name = nameEntry.get().strip()
+    if entered_name:  # Only proceed if a name was entered
+        current_score = currentScore.get()
+        names.append(entered_name)
+        scores.append(current_score)
+        
+        # Save the new score to file
+        save_new_score(entered_name, current_score)
+        
+        if current_score > highestScore:
+            highestScore = current_score
+            highScoreName = entered_name
+
+        # Clear the entry field after recording
+        nameEntry.delete(0, 'end')
+        
+        # Refresh the leaderboard display
+        placeLeaderboard()
 
 # Leaderboard & UI setup
 def placeLeaderboard():
+    global nameEntry, enterButton, statusLabel, dinger, bell_image
     canvas.create_rectangle(0, 0, 500, 500, fill="grey20", width=2)
 
+    # Get top 5 scores
+    score_pairs = list(zip(names, scores))
+    score_pairs.sort(key=lambda x: x[1], reverse=True)
+    top_5_pairs = score_pairs[:5]
+
     intx = 0
     inty = 60
-    for i in range(len(names)):
-        label1 = ctk.CTkLabel(width=124, height=39, text_color="white", text=names[i], font=("Arial", 15), master=app)
+    for name, score in top_5_pairs:
+        label1 = ctk.CTkLabel(width=124, height=39, text_color="white", text=name, font=("Arial", 15), master=app)
         label1.place(x=intx, y=inty)
-        label2 = ctk.CTkLabel(width=124, height=39, text_color="white", text=scores[i], font=("Arial", 15), master=app)
+        label2 = ctk.CTkLabel(width=124, height=39, text_color="white", text=f"{score:.2f}", font=("Arial", 15), master=app)
         label2.place(x=intx + 125, y=inty)
         inty += 40
 
     ctk.CTkLabel(width=249, height=39, text_color="white", text="Leaderboard", font=("Arial", 50), master=app).place(x=0, y=0)
-    ctk.CTkButton(width=0, height=150, text="START", fg_color="green", corner_radius=50, font=("Arial", 50),
-                  text_color="gray99", master=app, command=startPunch).place(x=50, y=300)
-    ctk.CTkButton(width=0, height=150, text="STOP", fg_color="orange2", corner_radius=50, font=("Arial", 50),
-                  text_color="gray99", master=app, command=stopPunch).place(x=50, y=500)
-    ctk.CTkButton(width=0, height=150, text="RESET", fg_color="red1", corner_radius=50, font=("Arial", 50),
-                  text_color="gray99", master=app, command=resetPunch).place(x=50, y=700)
+    
+    # Create status indicator
+    statusLabel = ctk.CTkLabel(
+        master=app,
+        width=120,
+        height=40,
+        text="NOT RECORDING",
+        fg_color="gray70",
+        text_color="black",
+        corner_radius=10,
+        font=("Arial", 16)
+    )
+    statusLabel.place(x=50, y=450)
+    
+    ctk.CTkButton(master=app,
+                  width=120,
+                  height=80,
+                  text="START",
+                  fg_color="green",
+                  text_color="gray99",
+                  corner_radius=25,
+                  font=("Arial", 30),
+                  command=startPunch).place(x=50, y=500)
+    ctk.CTkButton(master=app,
+                  width=120,
+                  height=80,
+                  text="STOP",
+                  fg_color="orange2",
+                  text_color="gray99",
+                  corner_radius=25,
+                  font=("Arial", 30),
+                  command=stopPunch).place(x=50, y=600)
+    ctk.CTkButton(master=app,
+                  width=120,
+                  height=80,
+                  text="RESET",
+                  fg_color="red1",
+                  text_color="gray99",
+                  corner_radius=25,
+                  font=("Arial", 30),
+                  command=resetPunch).place(x=50, y=700)
 
     ctk.CTkLabel(width=50, height=20, text_color="white", text="Current Score", font=("Arial", 50), master=app).place(x=350, y=20)
     ctk.CTkLabel(width=50, height=20, text_color="white", textvariable=currentScore, font=("Arial", 50), master=app).place(x=500, y=100)
@@ -96,12 +237,23 @@ def placeLeaderboard():
     nameEntry = ctk.CTkEntry(width=300, height=50, master=app, font=("Arial", 50))
     nameEntry.place(x=370, y=200)
 
-    ctk.CTkButton(width=50, height=50, text="ENTER", fg_color="green", font=("Arial", 20),
-                  text_color="gray99", master=app).place(x=670, y=205)
+    enterButton = ctk.CTkButton(width=50, height=50, text="ENTER", fg_color="green", font=("Arial", 20),
+                  text_color="gray99", master=app, command=submitScore)
+    enterButton.place(x=670, y=205)
+
+    # Load and display the bell image
+    bell_image = Image.open("./BellDrawing.png")
+    photo = ImageTk.PhotoImage(bell_image)
+    image_label = ctk.CTkLabel(image=photo, text="", width=10, master=app)
+    image_label.image = photo  # Keep a reference to prevent garbage collection
+    image_label.place(x=800, y=0)
 
-    image = Image.open("./BellDrawing.png")
-    photo = ImageTk.PhotoImage(image)
-    ctk.CTkLabel(image=photo, text="", width=10, master=app).place(x=800, y=0)
+    # Create the dinger after the image (so it appears on top)
+    dinger = ctk.CTkLabel(width=40, height=30, text="", fg_color="gray77", master=app)
+    dinger.place(x=1005, y=900)
+    
+    # Start updating dinger position
+    update_dinger_position()
 
 # BLE thread setup
 def ble_thread_func():
@@ -114,30 +266,6 @@ def start_ble_thread():
     thread = threading.Thread(target=ble_thread_func, daemon=True)
     thread.start()
 
-def update_dinger_position():
-    global dinger
-    score = currentScore.get()
-
-    # Example logic: map score (0–100) to y-position (900 to 300)
-    # You can adjust the ranges to suit your needs
-    max_score = 100
-    min_y = 300
-    max_y = 900
-
-    # Clamp score between 0 and max_score
-    score = min(max(score, 0), max_score)
-
-    # Calculate the new y position
-    new_y = max_y - int((score / max_score) * (max_y - min_y))
-
-    # Move the label
-    dinger.place_configure(y=new_y)
-
-    # Call this again after a short delay
-    app.after(100, update_dinger_position)
-
-
-# Data processing loop in background thread
 def data_loop():
     last_data = None
     last_value = 0.00
@@ -178,6 +306,7 @@ def start_data_loop_thread():
     thread.start()
 
 # Run UI setup
+load_scores()  # Load existing scores before setting up UI
 placeLeaderboard()
 
 # Start threads after UI initializes

BIN
__pycache__/dobluetooth.cpython-312.pyc


+ 1 - 0
all_scores.txt

@@ -0,0 +1 @@
+

BIN
ding.mp3