Files
Habegger_loader_game/qr_scan.py
2025-09-22 19:18:01 +02:00

189 lines
7.0 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import cv2
from pyzbar.pyzbar import decode
import numpy as np
from PIL import ImageFont, ImageDraw, Image
import os
import subprocess
import requests
import pygetwindow as gw
import pyautogui
import time
# Nach 2 Sekunden suchen wir das Fenster
time.sleep(2)
for w in gw.getWindowsWithTitle("QR Scanner"): # oder z. B. "pygame", "Loader", etc.
w.activate()
w.maximize() # optional
pyautogui.click(w.left + 100, w.top + 100) # sicherer Klick ins Fenster
break
API_URL = "https://hag.putschgi.ch/Yb54CO5Ypybx/api/qr.php?action=verify_hash"
API_SECRET = "ddlKC6sgE4EMvsU9VQeIVeYrsPGpE104"
# Fenstergröße & Farben
window_width, window_height = 1920, 1080
# Habegger Gold
COLOR_GREEN = (0, 255, 0)
COLOR_YELLOW = (0, 255, 255)
COLOR_BACKGROUND = (45, 46, 47) # HTML-Farbe #2d2e2f
COLOR_WHITE = (255, 255, 255)
COLOR_GOLD = (131, 188, 214) # BGR für Habegger-Gold
# Font & Logo
FONT_PATH = os.path.join("fonts", "Tisa Sans Pro Regular.ttf"
"") # Alternativ: Georgia.ttf, falls vorhanden
FONT_SIZE = 48
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
logo_path = "images/habegger_logo_goldbar_whitefont.png" # Logo mit sichtbarem Text
logo_pil = Image.open(logo_path).convert("RGBA")
logo_pil.thumbnail((300, 100))
logo_pil = Image.alpha_composite(Image.new("RGBA", logo_pil.size, (0, 0, 0, 0)), logo_pil)
logo_img = np.array(logo_pil)
logo_img = cv2.cvtColor(logo_img, cv2.COLOR_RGBA2BGRA)
def draw_unicode_text(cv2_image, text, position, color=COLOR_WHITE):
img_pil = Image.fromarray(cv2_image)
draw = ImageDraw.Draw(img_pil)
draw.text(position, text, font=font, fill=color)
return np.array(img_pil)
def parse_qr_data(data):
from urllib.parse import urlparse, parse_qs
if "?code=" in data:
parsed = urlparse(data)
query = parse_qs(parsed.query)
code = query.get("code", [""])[0]
return code
return None
def start_game(mail, name):
with open("last_user.txt", "w", encoding="utf-8-sig") as f:
f.write(f"{mail}\n{name}")
subprocess.run(["python", "loader_game.py"])
# Endlosschleife für den Scanner
while True:
detected_color = COLOR_GOLD
detected_time = None
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
# Rahmenfarbe wird später im Loop anhand der Zeit gesetzt
last_display_text = ""
start_timer = None
game_started = False
while True:
success, frame = cap.read()
if not success:
break
decoded_objects = decode(frame)
if not decoded_objects:
inverted_frame = cv2.bitwise_not(frame)
decoded_objects = decode(inverted_frame)
# QR-Status zurücksetzen nach 5 Sek.
if detected_time and time.time() - detected_time >= 5.0:
detected_color = COLOR_GOLD
frame_color = COLOR_GOLD
if decoded_objects:
detected_time = time.time()
for obj in decoded_objects:
points = obj.polygon
if len(points) > 4:
hull = cv2.convexHull(np.array([point for point in points], dtype=np.float32))
points = hull.reshape(-1, 2)
for i in range(len(points)):
pt1 = tuple(points[i])
pt2 = tuple(points[(i + 1) % len(points)])
cv2.line(frame, pt1, pt2, COLOR_GREEN, 3)
data = obj.data.decode("utf-8")
code = parse_qr_data(data)
if not code:
detected_color = COLOR_YELLOW
detected_time = time.time()
last_display_text = "Kein gültiger QR-Code erkannt."
break
try:
res = requests.post(API_URL, json={"code": code, "auth": API_SECRET}, timeout=5)
print("RAW Response:", res.text)
result = res.json()
except Exception as e:
detected_color = COLOR_YELLOW
detected_time = time.time()
last_display_text = f"API Fehler: {e}"
break
if not result.get("valid"):
detected_color = COLOR_YELLOW
last_display_text = "Ungültiger Code."
elif result.get("registered"):
name = result.get("name", "Unbekannt")
detected_color = COLOR_GREEN
last_display_text = f"Hallo {name}!"
start_timer = time.time()
game_started = True
last_mail = code
last_name = name
else:
detected_color = COLOR_YELLOW
last_display_text = "QR gültig, aber nicht registriert."
detected_time = time.time()
break
if start_timer and time.time() - start_timer >= 5.0:
cap.release()
cv2.destroyAllWindows()
start_game(last_mail, last_name)
break
display_frame = np.full((window_height, window_width, 3), COLOR_BACKGROUND, dtype=np.uint8)
cam_h, cam_w = frame.shape[:2]
x_offset = (window_width - cam_w) // 2
y_offset = (window_height - cam_h) // 2
display_frame[y_offset:y_offset+cam_h, x_offset:x_offset+cam_w] = frame
display_frame = draw_unicode_text(display_frame,
"Scanne deinen QR-Code um das Spiel zu starten.",
(80, 100), COLOR_WHITE)
if last_display_text:
display_frame = draw_unicode_text(display_frame, last_display_text,
(80, window_height - 100), COLOR_WHITE)
# Kamera-Rahmen
if detected_time and time.time() - detected_time < 5.0:
current_color = detected_color
else:
current_color = COLOR_GOLD
cv2.rectangle(display_frame, (x_offset, y_offset),
(x_offset + cam_w, y_offset + cam_h), current_color, 6)
# Logo oben rechts ohne Alpha-Blending-Probleme
logo_pos = (window_width - logo_img.shape[1] - 40, 40)
overlay = np.zeros_like(display_frame, dtype=np.uint8)
overlay[logo_pos[1]:logo_pos[1]+logo_img.shape[0], logo_pos[0]:logo_pos[0]+logo_img.shape[1]] = logo_img[:, :, :3]
mask = logo_img[:, :, 3] # alpha channel
for c in range(3):
display_frame[logo_pos[1]:logo_pos[1]+logo_img.shape[0], logo_pos[0]:logo_pos[0]+logo_img.shape[1], c] = (
logo_img[:, :, c] * (mask / 255.0) + display_frame[logo_pos[1]:logo_pos[1]+logo_img.shape[0], logo_pos[0]:logo_pos[0]+logo_img.shape[1], c] * (1.0 - mask / 255.0)).astype(np.uint8)
cv2.namedWindow("QR Scanner", cv2.WINDOW_NORMAL)
cv2.setWindowProperty("QR Scanner", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.imshow("QR Scanner", display_frame)
key = cv2.waitKey(1)
if key == 27 or key == ord('q'):
cap.release()
cv2.destroyAllWindows()
exit()