commit 775264076bf07a11abfb8818f8c74c71ca8919aa Author: sandro Date: Sun Aug 9 09:39:56 2026 +0200 Initialer Commit diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000..16a231f Binary files /dev/null and b/__pycache__/app.cpython-312.pyc differ diff --git a/__pycache__/dl_csv.cpython-312.pyc b/__pycache__/dl_csv.cpython-312.pyc new file mode 100644 index 0000000..7840905 Binary files /dev/null and b/__pycache__/dl_csv.cpython-312.pyc differ diff --git a/app.py b/app.py new file mode 100644 index 0000000..bcc28ac --- /dev/null +++ b/app.py @@ -0,0 +1,67 @@ +from fastapi.middleware.cors import CORSMiddleware +import csv +import re +import urllib.request +from fastapi import FastAPI +import uvicorn +import dl_csv +import json + +app = FastAPI() + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # Erlaubt Zugriffe von allen Quellen/IPs im Netzwerk + allow_credentials=True, + allow_methods=["*"], # Erlaubt alle HTTP-Methoden (GET, POST, etc.) + allow_headers=["*"], # Erlaubt alle Header +) + +@app.get("/ninjiapi/all") +def get_everything(): + try: + return dl_csv.read_data() + + except Exception as e: + return {"success": False, "error": str(e)} + +@app.get("/ninjiapi/user/{username}") +def get_by_user(username: str): + try: + data = dl_csv.read_data() + for player in data["leaderboard"]: + if player["player"].lower() == username.lower(): + return player + return username + "not found" + + except Exception as e: + return {"success": False, "error": str(e)} + +@app.get("/ninjiapi/division/{division}") +def get_all_by_division(division: str): + try: + data = dl_csv.read_data() + return_data = [] + for player in data["leaderboard"]: + if player["division"].lower() == division.lower(): + return_data.append(player) + if not return_data == {}: + return return_data + return username + "not found" + + except Exception as e: + return {"success": False, "error": str(e)} + +@app.get("/ninjiapi/division/user/{username}") +def get_all_by_my_division(username: str): + try: + division = get_by_user(username)["division"] + return get_all_by_division(division) + + except Exception as e: + return {"success": False, "error": str(e)} + + +if __name__ == "__main__": + # bindet an 0.0.0.0, damit es im gesamten Netzwerk erreichbar ist + uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True) diff --git a/data.json b/data.json new file mode 100644 index 0000000..244be70 --- /dev/null +++ b/data.json @@ -0,0 +1 @@ +{"title": "SMW NINJI S7L4", "details": {"game": "SMW NINJI", "season": 7, "level": 4}, "meta": {"median": "33.29", "runners": 144, "submissions": 1104, "communityBest": {"total": "30.08", "p1": "14.40", "p2": "15.68"}, "deadline": ""}, "leaderboardCount": 144, "leaderboard": [{"division": "Champion", "divisionRank": 0, "overallRank": 1, "player": "SakayaLive", "part1": "14.42", "part2": "15.82", "totalTime": "30.24", "isOnline": false}, {"division": "Master", "divisionRank": 1, "overallRank": 2, "player": "Haipeee", "part1": "14.42", "part2": "15.88", "totalTime": "30.30", "isOnline": false}, {"division": "Master", "divisionRank": 2, "overallRank": 3, "player": "SMokiWuff", "part1": "14.62", "part2": "15.90", "totalTime": "30.52", "isOnline": false}, {"division": "Master", "divisionRank": 3, "overallRank": 4, "player": "HBRbotinator", "part1": "14.46", "part2": "16.08", "totalTime": "30.54", "isOnline": false}, {"division": "Master", "divisionRank": 4, "overallRank": 5, "player": "Fransen86", "part1": "14.50", "part2": "16.08", "totalTime": "30.58", "isOnline": false}, {"division": "Master", "divisionRank": 4, "overallRank": 5, "player": "RedPandaa_", "part1": "14.58", "part2": "16.00", "totalTime": "30.58", "isOnline": false}, {"division": "Diamond", "divisionRank": 1, "overallRank": 7, "player": "Ticknaldo", "part1": "14.76", "part2": "15.88", "totalTime": "30.64", "isOnline": false}, {"division": "Diamond", "divisionRank": 1, "overallRank": 7, "player": "newgasm", "part1": "14.62", "part2": "16.02", "totalTime": "30.64", "isOnline": false}, {"division": "Diamond", "divisionRank": 3, "overallRank": 9, "player": "Berndl_64", "part1": "14.62", "part2": "16.04", "totalTime": "30.66", "isOnline": false}, {"division": "Diamond", "divisionRank": 4, "overallRank": 10, "player": "iamtheratio", "part1": "14.68", "part2": "16.08", "totalTime": "30.76", "isOnline": false}, {"division": "Diamond", "divisionRank": 5, "overallRank": 11, "player": "Dennsen86", "part1": "14.64", "part2": "16.16", "totalTime": "30.80", "isOnline": false}, {"division": "Diamond", "divisionRank": 6, "overallRank": 12, "player": "NitroSplint", "part1": "14.58", "part2": "16.30", "totalTime": "30.88", "isOnline": false}, {"division": "Diamond", "divisionRank": 7, "overallRank": 13, "player": "Kapostel", "part1": "14.80", "part2": "16.14", "totalTime": "30.94", "isOnline": false}, {"division": "Diamond", "divisionRank": 7, "overallRank": 13, "player": "JLoops_", "part1": "14.68", "part2": "16.26", "totalTime": "30.94", "isOnline": false}, {"division": "Diamond", "divisionRank": 9, "overallRank": 15, "player": "Nathanmg", "part1": "15.02", "part2": "16.04", "totalTime": "31.06", "isOnline": false}, {"division": "Diamond", "divisionRank": 10, "overallRank": 16, "player": "Holiday_From_Real", "part1": "15.04", "part2": "16.04", "totalTime": "31.08", "isOnline": false}, {"division": "Diamond", "divisionRank": 11, "overallRank": 17, "player": "Yuri_Zahard", "part1": "14.80", "part2": "16.30", "totalTime": "31.10", "isOnline": false}, {"division": "Diamond", "divisionRank": 12, "overallRank": 18, "player": "Krisbyte", "part1": "14.96", "part2": "16.18", "totalTime": "31.14", "isOnline": false}, {"division": "Diamond", "divisionRank": 13, "overallRank": 19, "player": "MTheOrdinaryGamer", "part1": "14.76", "part2": "16.40", "totalTime": "31.16", "isOnline": false}, {"division": "Diamond", "divisionRank": 14, "overallRank": 20, "player": "SeiphSewell24", "part1": "15.02", "part2": "16.18", "totalTime": "31.20", "isOnline": false}, {"division": "Diamond", "divisionRank": 15, "overallRank": 21, "player": "RayaRoentgen", "part1": "15.08", "part2": "16.22", "totalTime": "31.30", "isOnline": false}, {"division": "Diamond", "divisionRank": 15, "overallRank": 21, "player": "vipersigns", "part1": "15.00", "part2": "16.30", "totalTime": "31.30", "isOnline": false}, {"division": "Diamond", "divisionRank": 15, "overallRank": 21, "player": "MSpeedruns", "part1": "14.96", "part2": "16.34", "totalTime": "31.30", "isOnline": false}, {"division": "Diamond", "divisionRank": 18, "overallRank": 24, "player": "jinrokhzenobi", "part1": "15.10", "part2": "16.34", "totalTime": "31.44", "isOnline": false}, {"division": "Diamond", "divisionRank": 18, "overallRank": 24, "player": "Sonofsolaire", "part1": "15.04", "part2": "16.40", "totalTime": "31.44", "isOnline": false}, {"division": "Diamond", "divisionRank": 20, "overallRank": 26, "player": "shell_don_koopa", "part1": "15.04", "part2": "16.42", "totalTime": "31.46", "isOnline": false}, {"division": "Diamond", "divisionRank": 21, "overallRank": 27, "player": "Flowty83", "part1": "15.04", "part2": "16.46", "totalTime": "31.50", "isOnline": false}, {"division": "Diamond", "divisionRank": 22, "overallRank": 28, "player": "LuckwurstJoe", "part1": "14.94", "part2": "16.58", "totalTime": "31.52", "isOnline": false}, {"division": "Diamond", "divisionRank": 23, "overallRank": 29, "player": "Pyradante", "part1": "15.06", "part2": "16.50", "totalTime": "31.56", "isOnline": false}, {"division": "Diamond", "divisionRank": 23, "overallRank": 29, "player": "Deathmask666GER", "part1": "15.12", "part2": "16.44", "totalTime": "31.56", "isOnline": false}, {"division": "Diamond", "divisionRank": 23, "overallRank": 29, "player": "nikmik0108", "part1": "15.10", "part2": "16.46", "totalTime": "31.56", "isOnline": false}, {"division": "Diamond", "divisionRank": 26, "overallRank": 32, "player": "DerPlebsident", "part1": "15.40", "part2": "16.18", "totalTime": "31.58", "isOnline": false}, {"division": "Diamond", "divisionRank": 27, "overallRank": 33, "player": "sugarfalcon", "part1": "14.98", "part2": "16.64", "totalTime": "31.62", "isOnline": false}, {"division": "Diamond", "divisionRank": 28, "overallRank": 34, "player": "GussBradyGaming", "part1": "15.16", "part2": "16.54", "totalTime": "31.70", "isOnline": false}, {"division": "Platin", "divisionRank": 1, "overallRank": 35, "player": "DixyNL", "part1": "15.28", "part2": "16.44", "totalTime": "31.72", "isOnline": false}, {"division": "Platin", "divisionRank": 1, "overallRank": 35, "player": "danny_90", "part1": "15.18", "part2": "16.54", "totalTime": "31.72", "isOnline": false}, {"division": "Platin", "divisionRank": 3, "overallRank": 37, "player": "Stormsn", "part1": "15.22", "part2": "16.58", "totalTime": "31.80", "isOnline": false}, {"division": "Platin", "divisionRank": 3, "overallRank": 37, "player": "ElectricEagle1", "part1": "15.40", "part2": "16.40", "totalTime": "31.80", "isOnline": false}, {"division": "Platin", "divisionRank": 5, "overallRank": 39, "player": "hchris3", "part1": "15.54", "part2": "16.30", "totalTime": "31.84", "isOnline": false}, {"division": "Platin", "divisionRank": 5, "overallRank": 39, "player": "everygamegam3r", "part1": "15.40", "part2": "16.44", "totalTime": "31.84", "isOnline": false}, {"division": "Platin", "divisionRank": 7, "overallRank": 41, "player": "nonprophet__", "part1": "15.64", "part2": "16.22", "totalTime": "31.86", "isOnline": false}, {"division": "Platin", "divisionRank": 8, "overallRank": 42, "player": "P0werjuicer", "part1": "15.50", "part2": "16.52", "totalTime": "32.02", "isOnline": false}, {"division": "Platin", "divisionRank": 9, "overallRank": 43, "player": "Nayfal", "part1": "15.66", "part2": "16.40", "totalTime": "32.06", "isOnline": false}, {"division": "Platin", "divisionRank": 10, "overallRank": 44, "player": "NoSuperman89", "part1": "15.44", "part2": "16.64", "totalTime": "32.08", "isOnline": false}, {"division": "Platin", "divisionRank": 11, "overallRank": 45, "player": "StelioKonttos", "part1": "15.36", "part2": "16.74", "totalTime": "32.10", "isOnline": false}, {"division": "Platin", "divisionRank": 12, "overallRank": 46, "player": "AchSteff", "part1": "15.38", "part2": "16.76", "totalTime": "32.14", "isOnline": false}, {"division": "Platin", "divisionRank": 13, "overallRank": 47, "player": "ABG_Armin", "part1": "15.62", "part2": "16.54", "totalTime": "32.16", "isOnline": false}, {"division": "Platin", "divisionRank": 14, "overallRank": 48, "player": "BotNoUser", "part1": "15.48", "part2": "16.72", "totalTime": "32.20", "isOnline": false}, {"division": "Platin", "divisionRank": 15, "overallRank": 49, "player": "sir_vilrin", "part1": "15.54", "part2": "16.74", "totalTime": "32.28", "isOnline": false}, {"division": "Platin", "divisionRank": 16, "overallRank": 50, "player": "IxionXVII", "part1": "15.46", "part2": "16.90", "totalTime": "32.36", "isOnline": false}, {"division": "Platin", "divisionRank": 16, "overallRank": 50, "player": "silberpappel87", "part1": "15.60", "part2": "16.76", "totalTime": "32.36", "isOnline": false}, {"division": "Platin", "divisionRank": 18, "overallRank": 52, "player": "StepsDerSteher", "part1": "15.84", "part2": "16.54", "totalTime": "32.38", "isOnline": false}, {"division": "Platin", "divisionRank": 19, "overallRank": 53, "player": "Namefaker89", "part1": "15.70", "part2": "16.70", "totalTime": "32.40", "isOnline": false}, {"division": "Platin", "divisionRank": 20, "overallRank": 54, "player": "NotJohnMcDonald", "part1": "15.82", "part2": "16.64", "totalTime": "32.46", "isOnline": false}, {"division": "Platin", "divisionRank": 21, "overallRank": 55, "player": "Heisenknut308", "part1": "16.02", "part2": "16.46", "totalTime": "32.48", "isOnline": false}, {"division": "Platin", "divisionRank": 22, "overallRank": 56, "player": "Raptor0155", "part1": "15.50", "part2": "17.04", "totalTime": "32.54", "isOnline": false}, {"division": "Platin", "divisionRank": 22, "overallRank": 56, "player": "olllo1000", "part1": "15.66", "part2": "16.88", "totalTime": "32.54", "isOnline": false}, {"division": "Platin", "divisionRank": 24, "overallRank": 58, "player": "DerJan_85", "part1": "15.74", "part2": "16.82", "totalTime": "32.56", "isOnline": false}, {"division": "Platin", "divisionRank": 24, "overallRank": 58, "player": "Jole_12", "part1": "15.72", "part2": "16.84", "totalTime": "32.56", "isOnline": false}, {"division": "Platin", "divisionRank": 26, "overallRank": 60, "player": "BigLenko", "part1": "15.36", "part2": "17.32", "totalTime": "32.68", "isOnline": false}, {"division": "Platin", "divisionRank": 27, "overallRank": 61, "player": "Laffi_1HP", "part1": "15.62", "part2": "17.08", "totalTime": "32.70", "isOnline": false}, {"division": "Platin", "divisionRank": 28, "overallRank": 62, "player": "lGiygasl", "part1": "15.76", "part2": "16.98", "totalTime": "32.74", "isOnline": false}, {"division": "Gold", "divisionRank": 1, "overallRank": 63, "player": "oldskoolotto", "part1": "15.86", "part2": "16.90", "totalTime": "32.76", "isOnline": false}, {"division": "Gold", "divisionRank": 2, "overallRank": 64, "player": "eru_the_small", "part1": "15.88", "part2": "17.04", "totalTime": "32.92", "isOnline": false}, {"division": "Gold", "divisionRank": 3, "overallRank": 65, "player": "HerrBoesch", "part1": "16.04", "part2": "16.90", "totalTime": "32.94", "isOnline": false}, {"division": "Gold", "divisionRank": 4, "overallRank": 66, "player": "TechnoHail", "part1": "15.48", "part2": "17.50", "totalTime": "32.98", "isOnline": false}, {"division": "Gold", "divisionRank": 5, "overallRank": 67, "player": "kalyrix", "part1": "16.06", "part2": "17.02", "totalTime": "33.08", "isOnline": false}, {"division": "Gold", "divisionRank": 6, "overallRank": 68, "player": "liluu_pan", "part1": "16.24", "part2": "16.88", "totalTime": "33.12", "isOnline": false}, {"division": "Gold", "divisionRank": 7, "overallRank": 69, "player": "Spaceinvaderin", "part1": "16.32", "part2": "16.84", "totalTime": "33.16", "isOnline": false}, {"division": "Gold", "divisionRank": 8, "overallRank": 70, "player": "JohannesKriechhammer", "part1": "16.10", "part2": "17.12", "totalTime": "33.22", "isOnline": false}, {"division": "Gold", "divisionRank": 9, "overallRank": 71, "player": "HousemeisterHD", "part1": "15.82", "part2": "17.42", "totalTime": "33.24", "isOnline": false}, {"division": "Gold", "divisionRank": 10, "overallRank": 72, "player": "Azrael_S90", "part1": "16.22", "part2": "17.06", "totalTime": "33.28", "isOnline": false}, {"division": "Gold", "divisionRank": 11, "overallRank": 73, "player": "CrazySkar86", "part1": "16.06", "part2": "17.24", "totalTime": "33.30", "isOnline": false}, {"division": "Gold", "divisionRank": 11, "overallRank": 73, "player": "moshok", "part1": "16.12", "part2": "17.18", "totalTime": "33.30", "isOnline": false}, {"division": "Gold", "divisionRank": 13, "overallRank": 75, "player": "macii85", "part1": "16.44", "part2": "16.90", "totalTime": "33.34", "isOnline": false}, {"division": "Gold", "divisionRank": 14, "overallRank": 76, "player": "MaxpowerBlue", "part1": "16.36", "part2": "17.00", "totalTime": "33.36", "isOnline": false}, {"division": "Gold", "divisionRank": 15, "overallRank": 77, "player": "MajorDuke", "part1": "16.00", "part2": "17.40", "totalTime": "33.40", "isOnline": false}, {"division": "Gold", "divisionRank": 16, "overallRank": 78, "player": "janb209", "part1": "16.02", "part2": "17.40", "totalTime": "33.42", "isOnline": false}, {"division": "Gold", "divisionRank": 17, "overallRank": 79, "player": "gandhiboy_", "part1": "15.78", "part2": "17.66", "totalTime": "33.44", "isOnline": false}, {"division": "Gold", "divisionRank": 18, "overallRank": 80, "player": "RatzeFatz", "part1": "15.86", "part2": "17.64", "totalTime": "33.50", "isOnline": false}, {"division": "Gold", "divisionRank": 18, "overallRank": 80, "player": "DonPascaletti", "part1": "16.24", "part2": "17.26", "totalTime": "33.50", "isOnline": false}, {"division": "Gold", "divisionRank": 20, "overallRank": 82, "player": "broke_artist_tv", "part1": "16.38", "part2": "17.28", "totalTime": "33.66", "isOnline": false}, {"division": "Gold", "divisionRank": 21, "overallRank": 83, "player": "Arcadeschokolade", "part1": "16.50", "part2": "17.22", "totalTime": "33.72", "isOnline": false}, {"division": "Gold", "divisionRank": 21, "overallRank": 83, "player": "Cruckel", "part1": "16.34", "part2": "17.38", "totalTime": "33.72", "isOnline": false}, {"division": "Gold", "divisionRank": 23, "overallRank": 85, "player": "fanzocker", "part1": "16.24", "part2": "17.50", "totalTime": "33.74", "isOnline": false}, {"division": "Gold", "divisionRank": 23, "overallRank": 85, "player": "Toppi_TV", "part1": "16.20", "part2": "17.54", "totalTime": "33.74", "isOnline": false}, {"division": "Gold", "divisionRank": 25, "overallRank": 87, "player": "babooza91", "part1": "15.90", "part2": "17.88", "totalTime": "33.78", "isOnline": false}, {"division": "Gold", "divisionRank": 26, "overallRank": 88, "player": "AndreTheKey", "part1": "15.90", "part2": "17.90", "totalTime": "33.80", "isOnline": false}, {"division": "Gold", "divisionRank": 27, "overallRank": 89, "player": "AGrubica", "part1": "16.30", "part2": "17.52", "totalTime": "33.82", "isOnline": false}, {"division": "Silver", "divisionRank": 1, "overallRank": 90, "player": "marsellluswalllace", "part1": "16.24", "part2": "17.62", "totalTime": "33.86", "isOnline": false}, {"division": "Silver", "divisionRank": 1, "overallRank": 90, "player": "rinhoo76", "part1": "16.16", "part2": "17.70", "totalTime": "33.86", "isOnline": false}, {"division": "Silver", "divisionRank": 3, "overallRank": 92, "player": "Michael___TV", "part1": "16.26", "part2": "17.64", "totalTime": "33.90", "isOnline": false}, {"division": "Silver", "divisionRank": 4, "overallRank": 93, "player": "MrMoeZockt", "part1": "16.46", "part2": "17.46", "totalTime": "33.92", "isOnline": false}, {"division": "Silver", "divisionRank": 5, "overallRank": 94, "player": "Loeffler11", "part1": "16.86", "part2": "17.12", "totalTime": "33.98", "isOnline": false}, {"division": "Silver", "divisionRank": 6, "overallRank": 95, "player": "Flash406", "part1": "16.04", "part2": "17.96", "totalTime": "34.00", "isOnline": false}, {"division": "Silver", "divisionRank": 7, "overallRank": 96, "player": "DaveStateGaming_", "part1": "16.26", "part2": "17.86", "totalTime": "34.12", "isOnline": false}, {"division": "Silver", "divisionRank": 8, "overallRank": 97, "player": "Tsubasa_242", "part1": "16.54", "part2": "17.70", "totalTime": "34.24", "isOnline": false}, {"division": "Silver", "divisionRank": 9, "overallRank": 98, "player": "Paddy___W", "part1": "16.72", "part2": "17.54", "totalTime": "34.26", "isOnline": false}, {"division": "Silver", "divisionRank": 10, "overallRank": 99, "player": "x_cloudius_x", "part1": "17.16", "part2": "17.16", "totalTime": "34.32", "isOnline": false}, {"division": "Silver", "divisionRank": 11, "overallRank": 100, "player": "Rubberducky500", "part1": "17.12", "part2": "17.62", "totalTime": "34.74", "isOnline": false}, {"division": "Silver", "divisionRank": 12, "overallRank": 101, "player": "Teto", "part1": "16.94", "part2": "17.84", "totalTime": "34.78", "isOnline": false}, {"division": "Silver", "divisionRank": 12, "overallRank": 101, "player": "Jlpeazy", "part1": "17.44", "part2": "17.34", "totalTime": "34.78", "isOnline": false}, {"division": "Silver", "divisionRank": 14, "overallRank": 103, "player": "finalsilent", "part1": "17.20", "part2": "17.64", "totalTime": "34.84", "isOnline": false}, {"division": "Silver", "divisionRank": 15, "overallRank": 104, "player": "JoachimTheKante", "part1": "16.46", "part2": "18.42", "totalTime": "34.88", "isOnline": false}, {"division": "Silver", "divisionRank": 16, "overallRank": 105, "player": "TooOld2BeGaming", "part1": "17.60", "part2": "17.42", "totalTime": "35.02", "isOnline": false}, {"division": "Silver", "divisionRank": 17, "overallRank": 106, "player": "JaDeKi", "part1": "16.70", "part2": "18.38", "totalTime": "35.08", "isOnline": false}, {"division": "Silver", "divisionRank": 17, "overallRank": 106, "player": "AnnaLavellan", "part1": "17.40", "part2": "17.68", "totalTime": "35.08", "isOnline": false}, {"division": "Silver", "divisionRank": 19, "overallRank": 108, "player": "jacomile", "part1": "17.32", "part2": "17.96", "totalTime": "35.28", "isOnline": false}, {"division": "Silver", "divisionRank": 20, "overallRank": 109, "player": "seneida", "part1": "16.68", "part2": "18.76", "totalTime": "35.44", "isOnline": false}, {"division": "Silver", "divisionRank": 21, "overallRank": 110, "player": "ViperSpielt", "part1": "16.98", "part2": "18.54", "totalTime": "35.52", "isOnline": false}, {"division": "Silver", "divisionRank": 22, "overallRank": 111, "player": "nemesis8bit", "part1": "17.38", "part2": "18.16", "totalTime": "35.54", "isOnline": false}, {"division": "Silver", "divisionRank": 23, "overallRank": 112, "player": "Franzbroetchen86", "part1": "17.50", "part2": "18.18", "totalTime": "35.68", "isOnline": false}, {"division": "Silver", "divisionRank": 24, "overallRank": 113, "player": "Falanyeldi", "part1": "17.70", "part2": "18.14", "totalTime": "35.84", "isOnline": false}, {"division": "Silver", "divisionRank": 24, "overallRank": 113, "player": "Dergl", "part1": "17.36", "part2": "18.48", "totalTime": "35.84", "isOnline": false}, {"division": "Silver", "divisionRank": 26, "overallRank": 115, "player": "MaMuhle", "part1": "17.12", "part2": "18.74", "totalTime": "35.86", "isOnline": false}, {"division": "Silver", "divisionRank": 27, "overallRank": 116, "player": "Oelsardine", "part1": "18.06", "part2": "18.00", "totalTime": "36.06", "isOnline": false}, {"division": "Silver", "divisionRank": 28, "overallRank": 117, "player": "Willows_Wanders", "part1": "18.26", "part2": "18.04", "totalTime": "36.30", "isOnline": false}, {"division": "Bronze", "divisionRank": 1, "overallRank": 118, "player": "MrrKessko", "part1": "18.16", "part2": "18.16", "totalTime": "36.32", "isOnline": false}, {"division": "Bronze", "divisionRank": 2, "overallRank": 119, "player": "Littlebeast_81", "part1": "18.32", "part2": "18.12", "totalTime": "36.44", "isOnline": false}, {"division": "Bronze", "divisionRank": 3, "overallRank": 120, "player": "the_real_sutefan", "part1": "17.88", "part2": "18.76", "totalTime": "36.64", "isOnline": false}, {"division": "Bronze", "divisionRank": 4, "overallRank": 121, "player": "doomed2mors", "part1": "17.64", "part2": "19.02", "totalTime": "36.66", "isOnline": false}, {"division": "Bronze", "divisionRank": 4, "overallRank": 121, "player": "CyberScouter", "part1": "17.76", "part2": "18.90", "totalTime": "36.66", "isOnline": false}, {"division": "Bronze", "divisionRank": 6, "overallRank": 123, "player": "mikeeeeee83", "part1": "18.06", "part2": "18.72", "totalTime": "36.78", "isOnline": false}, {"division": "Bronze", "divisionRank": 7, "overallRank": 124, "player": "Chomper89", "part1": "18.14", "part2": "19.06", "totalTime": "37.20", "isOnline": false}, {"division": "Bronze", "divisionRank": 8, "overallRank": 125, "player": "jansenMcCloud", "part1": "18.24", "part2": "19.00", "totalTime": "37.24", "isOnline": false}, {"division": "Bronze", "divisionRank": 9, "overallRank": 126, "player": "stephness36", "part1": "19.08", "part2": "18.18", "totalTime": "37.26", "isOnline": false}, {"division": "Bronze", "divisionRank": 10, "overallRank": 127, "player": "chrischicken1992", "part1": "18.86", "part2": "18.54", "totalTime": "37.40", "isOnline": false}, {"division": "Bronze", "divisionRank": 11, "overallRank": 128, "player": "dwr1986", "part1": "18.86", "part2": "18.56", "totalTime": "37.42", "isOnline": false}, {"division": "Bronze", "divisionRank": 12, "overallRank": 129, "player": "II_Morrison_II", "part1": "18.14", "part2": "19.70", "totalTime": "37.84", "isOnline": false}, {"division": "Bronze", "divisionRank": 13, "overallRank": 130, "player": "nels0n1", "part1": "19.04", "part2": "19.04", "totalTime": "38.08", "isOnline": false}, {"division": "Bronze", "divisionRank": 14, "overallRank": 131, "player": "HerrBlutgraf", "part1": "19.52", "part2": "18.92", "totalTime": "38.44", "isOnline": false}, {"division": "Bronze", "divisionRank": 15, "overallRank": 132, "player": "DarkOrchid1986", "part1": "18.16", "part2": "20.34", "totalTime": "38.50", "isOnline": false}, {"division": "Bronze", "divisionRank": 16, "overallRank": 133, "player": "doctor8bit", "part1": "19.60", "part2": "18.98", "totalTime": "38.58", "isOnline": false}, {"division": "Bronze", "divisionRank": 17, "overallRank": 134, "player": "Inyu1", "part1": "18.66", "part2": "20.18", "totalTime": "38.84", "isOnline": false}, {"division": "Bronze", "divisionRank": 18, "overallRank": 135, "player": "cheezy089", "part1": "19.84", "part2": "19.36", "totalTime": "39.20", "isOnline": false}, {"division": "Bronze", "divisionRank": 19, "overallRank": 136, "player": "badetuch86", "part1": "18.86", "part2": "20.44", "totalTime": "39.30", "isOnline": false}, {"division": "Bronze", "divisionRank": 20, "overallRank": 137, "player": "TheDestinOfficial", "part1": "19.00", "part2": "20.56", "totalTime": "39.56", "isOnline": false}, {"division": "Bronze", "divisionRank": 21, "overallRank": 138, "player": "dante77232", "part1": "21.34", "part2": "19.50", "totalTime": "40.84", "isOnline": false}, {"division": "Bronze", "divisionRank": 22, "overallRank": 139, "player": "filnn", "part1": "21.64", "part2": "20.14", "totalTime": "41.78", "isOnline": false}, {"division": "Bronze", "divisionRank": 23, "overallRank": 140, "player": "Yogi_Tronimal", "part1": "21.36", "part2": "21.34", "totalTime": "42.70", "isOnline": false}, {"division": "Bronze", "divisionRank": 24, "overallRank": 141, "player": "Patsche1312", "part1": "22.88", "part2": "20.84", "totalTime": "43.72", "isOnline": false}, {"division": "Bronze", "divisionRank": 25, "overallRank": 142, "player": "griestopf_88", "part1": "27.88", "part2": "25.28", "totalTime": "53.16", "isOnline": false}, {"division": "Bronze", "divisionRank": 26, "overallRank": 143, "player": "1ndUbio", "part1": "31.28", "part2": "23.54", "totalTime": "54.82", "isOnline": false}, {"division": "Bronze", "divisionRank": 27, "overallRank": 144, "player": "Musikmalin", "part1": "31.60", "part2": "26.16", "totalTime": "57.76", "isOnline": false}]} \ No newline at end of file diff --git a/dennsen86 b/dennsen86 new file mode 100644 index 0000000..1eb0bf0 --- /dev/null +++ b/dennsen86 @@ -0,0 +1 @@ +[{"division":"Master","divisionRank":1,"overallRank":2,"player":"Dennsen86","part1":"14.64","part2":"16.16","totalTime":"30.80","isOnline":false},{"division":"Master","divisionRank":2,"overallRank":3,"player":"RedPandaa_","part1":"14.68","part2":"16.14","totalTime":"30.82","isOnline":false},{"division":"Master","divisionRank":3,"overallRank":4,"player":"Haipeee","part1":"14.70","part2":"16.14","totalTime":"30.84","isOnline":false},{"division":"Master","divisionRank":4,"overallRank":5,"player":"Berndl_64","part1":"14.86","part2":"16.04","totalTime":"30.90","isOnline":false},{"division":"Master","divisionRank":4,"overallRank":5,"player":"Fransen86","part1":"14.72","part2":"16.18","totalTime":"30.90","isOnline":false}] \ No newline at end of file diff --git a/dl_csv.py b/dl_csv.py new file mode 100644 index 0000000..be878ad --- /dev/null +++ b/dl_csv.py @@ -0,0 +1,155 @@ +import csv +import re +import urllib.request +import json +import os +import time + +SPREADSHEET_ID = "1bsO07WG6ymV4UzHZyB0ayrKCn2zv67SpFaeE4Zmghcc" +GID = "1669168528" +CSV_URL = f"https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/gviz/tq?tqx=out:csv&gid={GID}" + + +def parse_title(title_str): + match = re.search(r"(.+?)\s+S(\d+)L(\d+)", title_str, re.IGNORECASE) + if match: + return { + "game": match.group(1).strip(), + "season": int(match.group(2)), + "level": int(match.group(3)), + } + return {"raw": title_str.strip()} + + +def parse_meta(meta_str): + median_m = re.search(r"Median:\s*([\d,\.]+)", meta_str) + runners_m = re.search(r"Runners:\s*(\d+)", meta_str) + subs_m = re.search(r"Submissions:\s*(\d+)", meta_str) + best_m = re.search( + r"Community Best:\s*([\d,\.]+)\s*\((?:P1:\s*([\d,\.]+)\s*\|\s*P2:\s*([\d,\.]+))\)", + meta_str, + ) + + return { + "median": median_m.group(1).replace(",", ".") if median_m else None, + "runners": int(runners_m.group(1)) if runners_m else 0, + "submissions": int(subs_m.group(1)) if subs_m else None, + "communityBest": ( + { + "total": best_m.group(1).replace(",", "."), + "p1": best_m.group(2).replace(",", ".") if best_m.group(2) else None, + "p2": best_m.group(3).replace(",", ".") if best_m.group(3) else None, + } + if best_m + else None + ), + } + + +def parse_csv_data(reader): + rows = list(reader) + if not rows or len(rows) < 4: + return {"error": "Keine ausreichenden Daten gefunden"} + + # Zeile 1 (Index 0): Titel aus Spalte B (Index 1) + raw_title = rows[0][1] if len(rows[0]) > 1 else "" + title_parsed = parse_title(raw_title) + + # Zeile 2 (Index 1): Meta Info aus Spalte B (Index 1) + meta_b2 = rows[1][1] if len(rows[1]) > 1 else "" + deadline = rows[1][8] if len(rows[1]) > 8 else "" # Falls Deadline in Spalte I steht + + # Ab Zeile 4 (Index 3): Spieler-Leaderboard + leaderboard = [] + for row in rows[3:]: + # Nur wenn ein Spielername in Spalte F (Index 5) existiert + if len(row) > 5 and row[5].strip(): + player_name = row[5].strip() + division = row[0].strip() if len(row) > 0 else "" + match division: + case "C": + division = "Champion" + case "M": + division = "Master" + case "D": + division = "Diamond" + case "P": + division = "Platin" + case "G": + division = "Gold" + case "S": + division = "Silver" + case "B": + division = "Bronze" + rank_div = row[2].strip() if len(row) > 2 else "" + + # Rang säubern, z. B. "(1)" -> 1 + rank_overall_raw = row[3].strip() if len(row) > 3 else "" + rank_overall_clean = re.sub(r"[^\d]", "", rank_overall_raw) + + part1 = row[6].strip() if len(row) > 6 else "" + part2 = row[7].strip() if len(row) > 7 else "" + total_time = row[8].strip() if len(row) > 8 else "" + online_str = row[9].strip().lower() #if len(row) > 9 else "" + leaderboard.append({ + "division": division, + "divisionRank": int(rank_div) if rank_div.isdigit() else 0, + "overallRank": int(rank_overall_clean) if rank_overall_clean.isdigit() else None, + "player": player_name, + "part1": part1, + "part2": part2, + "totalTime": total_time, + "isOnline": online_str in ["on", "online", "true", "1", "ja"], + }) + + return { + "title": raw_title.strip(), + "details": title_parsed, + "meta": { + **parse_meta(meta_b2), + "deadline": deadline, + }, + "leaderboardCount": len(leaderboard), + "leaderboard": leaderboard, + } + + +def update_data(): + try: + req = urllib.request.Request(CSV_URL, headers={"User-Agent": "Mozilla/5.0"}) + response = urllib.request.urlopen(req) + lines = [line.decode("utf-8") for line in response.readlines()] + + reader = csv.reader(lines) + parsed_data = parse_csv_data(reader) + with open("data.json", "w") as f: + f.write(json.dumps(parsed_data)) + return parsed_data + + except Exception as e: + return {"success": False, "error": str(e)} + + +def read_data(): + file_path = "data.json" + max_age_seconds = 60 # 1 Minute Cache-Dauer + + # Prüfen, ob die Datei existiert und wie alt sie ist + if os.path.exists(file_path): + # Mtime = Letzte Änderungszeit der Datei in Sekunden seit Epoch + file_age = time.time() - os.path.getmtime(file_path) + + if file_age > max_age_seconds: + update_data() + else: + # Falls die Datei noch gar nicht existiert, direkt initial Daten holen + update_data() + + # Nach dem potenziellen Update die Datei einlesen + with open(file_path, "r", encoding="utf-8") as f: + return json.load(f) + + +if __name__ == "__main__": + # bindet an 0.0.0.0, damit es im gesamten Netzwerk erreichbar ist + read_data() diff --git a/html/chroma.html b/html/chroma.html new file mode 100644 index 0000000..e01632a --- /dev/null +++ b/html/chroma.html @@ -0,0 +1,276 @@ + + + + + + Ninji Leaderboard Ticker + + + + +
+
+
+ + + + diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..168b102 --- /dev/null +++ b/html/index.html @@ -0,0 +1,276 @@ + + + + + + Ninji Leaderboard Ticker + + + + +
+
+
+ + + +