/| Mario Kart PC |\

I analysed the time trial leaderboards

smile

Page :  1 

Messages 11 - Koopa Koopa
vs39474 pts ★ Legend
battle6067 pts ★ Racer
Russia
Hello everyone! 2 days ago I looked at the circuit by circuit time trial leaderboards and decided that the data given wasn't enough. So I wrote some python code (python sucks btw) that tells me everything I need to know about this game's time trials WRs.

Here is the data I got (150cc):
Spoiler [ShowHide]
Everyone with a WR and how many WRs they have:
User ID: 32396, Username: JPG  — 23 WRs
User ID: 48717, Username: Anthcny — 9 WRs
User ID: 6013, Username: Arracheur2Beuteu — 7 WRs
User ID: 3586, Username: Fways — 6 WRs
User ID: 40764, Username: Ahmad Elkhuffash — 6 WRs
User ID: 41425, Username: Hgt — 2 WRs
User ID: 5164, Username: Mudky — 1 WR
User ID: 49980, Username: ﷽ — 1 WR
User ID: 147254, Username: PlsfirehopLETSGOOOWETOOGOOD — 1 WR

Every WR sorted by duration:
SNES Bowser Castle 2: 865 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Donut Plains 2: 790 days, WR set by JPG  (User ID: 32396)
SNES Ghost Valley 3: 602 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Yoshi Falls: 582 days, WR set by JPG  (User ID: 32396)
SNES Choco Island 2: 498 days, WR set by JPG  (User ID: 32396)
SNES Vanilla Lake 2: 479 days, WR set by JPG  (User ID: 32396)
DS Airship Fortress: 473 days, WR set by Hgt (User ID: 41425)
SNES Bowser Castle 3: 432 days, WR set by Mudky (User ID: 5164)
SNES Choco Island 1: 243 days, WR set by Hgt (User ID: 41425)
DS Waluigi Pinball: 208 days, WR set by JPG  (User ID: 32396)
SNES Bowser Castle 1: 164 days, WR set by JPG  (User ID: 32396)
SNES Mario Circuit 3: 164 days, WR set by JPG  (User ID: 32396)
SNES Ghost Valley 2: 164 days, WR set by JPG  (User ID: 32396)
SNES Mario Circuit 2: 159 days, WR set by JPG  (User ID: 32396)
GBA Riverside Park: 156 days, WR set by JPG  (User ID: 32396)
DS Tick-Tock Clock: 148 days, WR set by Fways (User ID: 3586)
DS Peach Gardens: 79 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Yoshi Desert: 68 days, WR set by JPG  (User ID: 32396)
DS Wario Stadium: 61 days, WR set by JPG  (User ID: 32396)
GBA Bowser Castle IV: 51 days, WR set by JPG  (User ID: 32396)
DS Shroom Ridge: 51 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Lakeside Park: 50 days, WR set by JPG  (User ID: 32396)
GBA Ribbon Road: 47 days, WR set by JPG  (User ID: 32396)
GBA Boo Lake: 39 days, WR set by ﷽ (User ID: 49980)
DS Bowser's Castle: 38 days, WR set by PlsfirehopLETSGOOOWETOOGOOD (User ID: 147254)
SNES Donut Plains 3: 35 days, WR set by JPG  (User ID: 32396)
GBA Sunset Wilds: 30 days, WR set by Anthcny (User ID: 48717)
DS Figure 8 Circuit: 26 days, WR set by Arracheur2Beuteu (User ID: 6013)
GBA Sky Garden: 20 days, WR set by Fways (User ID: 3586)
DS Delfino Square: 20 days, WR set by Arracheur2Beuteu (User ID: 6013)
DS DK Pass: 19 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Bowser Castle II: 16 days, WR set by Arracheur2Beuteu (User ID: 6013)
SNES Ghost Valley 1: 15 days, WR set by JPG  (User ID: 32396)
GBA Bowser Castle III: 15 days, WR set by Arracheur2Beuteu (User ID: 6013)
GBA Cheep-Cheep Island: 14 days, WR set by Anthcny (User ID: 48717)
GBA Shy Guy Beach: 12 days, WR set by Anthcny (User ID: 48717)
GBA Rainbow Road: 12 days, WR set by JPG  (User ID: 32396)
SNES Mario Circuit 1: 11 days, WR set by Anthcny (User ID: 48717)
SNES Koopa Beach 2: 11 days, WR set by Arracheur2Beuteu (User ID: 6013)
GBA Peach Circuit: 11 days, WR set by Anthcny (User ID: 48717)
DS Mario Circuit: 11 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Rainbow Road: 11 days, WR set by JPG  (User ID: 32396)
SNES Koopa Beach 1: 7 days, WR set by JPG  (User ID: 32396)
SNES Mario Circuit 4: 7 days, WR set by JPG  (User ID: 32396)
GBA Mario Circuit: 7 days, WR set by JPG  (User ID: 32396)
GBA Cheese Land: 7 days, WR set by Arracheur2Beuteu (User ID: 6013)
DS Luigi's Mansion: 7 days, WR set by JPG  (User ID: 32396)
SNES Donut Plains 1: 5 days, WR set by Fways (User ID: 3586)
GBA Broken Pier: 5 days, WR set by Fways (User ID: 3586)
DS Cheep Cheep Beach: 5 days, WR set by Fways (User ID: 3586)
SNES Vanilla Lake 1: 3 days, WR set by Anthcny (User ID: 48717)
SNES Rainbow Road: 3 days, WR set by Fways (User ID: 3586)
DS Desert Hills: 3 days, WR set by Anthcny (User ID: 48717)
GBA Bowser Castle I: 2 days, WR set by Arracheur2Beuteu (User ID: 6013)
GBA Snow Land: 2 days, WR set by Anthcny (User ID: 48717)
GBA Luigi Circuit: 0 days, WR set by Anthcny (User ID: 48717)

Every username associated with a user ID in a WR:
User ID: 32396, Names: JPG , JPG, JPG , JPG, JPG , JPG , JPG , JPG , JPG , JPG, JPG , JPG , JPG , JPG, JPG, JPG, JPG, JPG, CG_JPG, JPG , JPG , JPG, JPG
User ID: 48717, Names: Anthcny, Anthcny, Anthcny, Anthcny, Anthcny, Anthcny, Anthcny, Anthcny, Anthcny
User ID: 6013, Names: Arracheur2Beuteu, Arracheur2Beuteu, Arracheur2Beuteu, K$, K$£€, K$£€, K$
User ID: 3586, Names: Fways, Fways, Fways, Fways, Fways, Fways
User ID: 40764, Names: Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash
User ID: 41425, Names: Hgt, Hgt
User ID: 5164, Name: Mudky
User ID: 49980, Name: ﷽
User ID: 147254, Name: PlsfirehopLETSGOOOWETOOGOOD

How many WRs and players with WRs each country has:
Spain (es) — 23 WRs, 1 player: JPG
France (fr) — 22 WRs, 3 players: Anthcny, Fways, Arracheur2Beuteu
United Arab Emirates (ae) — 6 WRs, 1 player: Ahmad Elkhuffash
Philippines (ph) — 2 WRs, 1 player: Hgt
Not Specified (None) — 2 WRs, 2 players: ﷽, PlsfirehopLETSGOOOWETOOGOOD
Switzerland (ch) — 1 WR, 1 player: Mudky

Every character used in a WR ranked by how frequently they're used:
https://mkpc.malahieude.net/images/sprites/sprite_daisy.png — 8 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-6668b003c653b-20442.png — 6 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-666c02e98c2c7-33344.png — 6 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-62e7d0f0b1673-15370.png — 5 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-644502011c46e-21812.png — 3 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-63e62a3fe1742-314.png — 3 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-62f231f45e543-15627.png — 2 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-60abdc6f7d599-8373.png — 2 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-6668b050e616d-20440.png — 2 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-60aa6a7cc35a6-798.png — 2 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-661579a66207e-31631.png — 2 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-5ff70428b2d85-7148.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-62d9296d0473c-15001.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-61f5aad24c543-12315.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-66269bba2722c-31964.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-60f3de65158d5-8387.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-63245ba9ed337-16505.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-5c03e0a275208-1240.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-60d8b02424ac2-944.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-621bc1c363fb8-12816.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-65a3053da0856-29168.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-6668b04058f52-20441.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-5abcedf354714-311.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-61db8e49d8ee9-12098.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-653f97d3ea31d-26429.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-60be103606c2a-8454.png — 1 time


I also just thought about the same thing for 200cc and I don't want to code anything else, so here it is separately from 150:
Spoiler [ShowHide]
Everyone with a WR and how many WRs they have:
User ID: 40764, Username: Ahmad Elkhuffash — 52 WRs
User ID: 49980, Username: 𝔧𝔧 — 2 WRs
User ID: 48717, Username: Anthcny — 1 WR
User ID: 86185, Username: ImJustLimey — 1 WR

Every WR sorted by duration:
SNES Koopa Beach 2: 872 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Mario Circuit: 830 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Donut Plains 3: 815 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Bowser Castle III: 749 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Luigi's Mansion: 740 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Bowser Castle 1: 732 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Sunset Wilds: 732 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Peach Circuit: 711 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Vanilla Lake 1: 604 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Choco Island 1: 586 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Ghost Valley 1: 566 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Shy Guy Beach: 435 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Cheep Cheep Beach: 413 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Tick-Tock Clock: 405 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Mario Circuit 4: 368 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Lakeside Park: 321 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Riverside Park: 308 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Ribbon Road: 296 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Cheep-Cheep Island: 295 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Yoshi Falls: 295 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Peach Gardens: 295 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Bowser Castle I: 294 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Bowser Castle II: 294 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Yoshi Desert: 235 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Delfino Square: 235 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Cheese Land: 192 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Bowser Castle 3: 166 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Sky Garden: 159 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Rainbow Road: 159 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Donut Plains 2: 127 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Rainbow Road: 121 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Desert Hills: 121 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Waluigi Pinball: 112 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Donut Plains 1: 103 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Snow Land: 94 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Mario Circuit: 94 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Luigi Circuit: 93 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Bowser Castle IV: 93 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Boo Lake: 77 days, WR set by 𝔧𝔧 (User ID: 49980)
DS Shroom Ridge: 68 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Vanilla Lake 2: 51 days, WR set by 𝔧𝔧 (User ID: 49980)
SNES Ghost Valley 3: 47 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Ghost Valley 2: 46 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Bowser Castle 2: 38 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Mario Circuit 2: 37 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Rainbow Road: 37 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Airship Fortress: 37 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS Wario Stadium: 37 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Mario Circuit 1: 36 days, WR set by Anthcny (User ID: 48717)
DS Figure 8 Circuit: 35 days, WR set by Ahmad Elkhuffash (User ID: 40764)
DS DK Pass: 35 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Choco Island 2: 34 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Mario Circuit 3: 34 days, WR set by Ahmad Elkhuffash (User ID: 40764)
SNES Koopa Beach 1: 26 days, WR set by ImJustLimey (User ID: 86185)
DS Bowser's Castle: 26 days, WR set by Ahmad Elkhuffash (User ID: 40764)
GBA Broken Pier: 7 days, WR set by Ahmad Elkhuffash (User ID: 40764)

Every username associated with a user ID in a WR:
User ID: 40764, Names: Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash, Ahmad Elkhuffash
User ID: 49980, Names: 𝔧𝔧, Ok Run Ig
User ID: 48717, Name: Anthcny
User ID: 86185, Name: ImJustLimey

How many WRs and players with WRs each country has:
United Arab Emirates (ae) — 52 WRs, 1 player: Ahmad Elkhuffash
Not Specified (None) — 2 WRs, 1 player: 𝔧𝔧
France (fr) — 1 WR, 1 player: Anthcny
Not Specified (mx) — 1 WR, 1 player: ImJustLimey

Every character used in a WR ranked by how frequently they're used:
https://mkpc.malahieude.net/images/sprites/sprite_daisy.png — 53 times
https://mkpc.malahieude.net/images/sprites/uploads/cp-6668b003c653b-20442.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-6644f33291338-32635.png — 1 time
https://mkpc.malahieude.net/images/sprites/uploads/cp-65dcdec01e91e-30630.png — 1 time


My favourite feature is probably "Every WR sorted by duration"

And if you want to run the code yourself, it's split into 2 parts:

main.py:
Spoiler [ShowHide]
import datetime
import mkpc_ttdata

def pluralize_word(n: int, singular: str, plural: str) -> str:
   if n == 1:
       return singular
   else:
       return plural
   
data = mkpc_ttdata.ttwrs

name_id_map = {}
characters = {}
countries = {}
dates = {}

map_id: int = 0
for item in data:
   map_id += 1
   for arr in item["list"]:
       if arr[0] == 1:
           country = arr[5]
           if country not in countries:
               countries[country] = {"players": [], "count": 0}
           countries[country]["count"] += 1

           name = arr[1]
           user_id = arr[4]
           if user_id not in name_id_map:
               name_id_map[user_id] = {"names": [], "count": 0}
               countries[country]["players"].append(name)
           name_id_map[user_id]["names"].append(name)
           name_id_map[user_id]["count"] += 1
           
           character = arr[2]
           if character not in characters:
               characters[character] = 0
           characters[character] += 1

           date_str = arr[6]
           record_date = datetime.datetime.strptime(date_str, "%m-%d-%y";)
           dates[(map_id, user_id)] = record_date


sorted_user_data = sorted(name_id_map.items(), key=lambda x: x[1]["count"], reverse=True)

print("Everyone with a WR and how many WRs they have:";)
for user_id, info in sorted_user_data:
   name = info["names"][0]
   wr_amount = info["count"]
   word = pluralize_word(wr_amount, "WR", "WRs";)
   print(f"User ID: {user_id}, Username: {name} — {wr_amount} {word}";)


time_since_records = []
current_date = datetime.datetime.now()

for (map_id, user_id), record_date in dates.items():
   time_since_record = (current_date - record_date).days
   player_name = name_id_map[user_id]["names"][0]
   time_since_records.append((map_id, time_since_record, user_id, player_name))

sorted_time_since_records = sorted(time_since_records, key=lambda x: x[1], reverse=True)

print("\nEvery WR sorted by duration:";)
for map_id, time_since_record, user_id, player_name in sorted_time_since_records:
   map_name = mkpc_ttdata.map_id_to_name(map_id)
   print(f"{map_name}: {time_since_record} days, WR set by {player_name} (User ID: {user_id})";)


print("\nEvery username associated with a user ID in a WR:";)

sorted_users = sorted(name_id_map.keys(), key=lambda user_id: len(name_id_map[user_id]["names"]), reverse=True)

for user_id in sorted_users:
   names = name_id_map[user_id]["names"]
   word = pluralize_word(len(names), "Name", "Names";)
   print(f"User ID: {user_id}, {word}: {', '.join(names)}";)


print("\nHow many WRs and players with WRs each country has:";)
sorted_countries = sorted(countries.items(), key=lambda x: x[1]["count"], reverse=True)
for country, info in sorted_countries:
   player_count = len(info["players"])

   player_word = pluralize_word(player_count, "player", "players";)
   wr_word = pluralize_word(info['count'], "WR", "WRs";)
   country_word = mkpc_ttdata.convert_country_code(country)
   print(f"{country_word} ({country}) — {info['count']} {wr_word}, {player_count} {player_word}: {', '.join(info['players'])}";)


sorted_characters = sorted(characters.items(), key=lambda x: x[1], reverse=True)
print("\nEvery character used in a WR ranked by how frequently they're used:";)
for character, count in sorted_characters:
   word = pluralize_word(count, "time", "times";)
   character_link = character
   if character == "daisy":
       character_link = f"https://mkpc.malahieude.net/images/sprites/sprite_{character}.png"
   else:
       character_link = f"https://mkpc.malahieude.net/images/sprites/uploads/{character}.png"
   
   print(f"{character_link} — {count} {word}";)


and what I called "mkpc_ttdata.py" but the purpose of that one was just to store the records string but now it's being taked directly from mkpc's servers so they can probably be combined...
Anyway, 2nd part of the code:
Spoiler [ShowHide]
import requests

def convert_country_code(country_code: str) -> str:
   countries = {
       "es": "Spain",
       "fr": "France",
       "ae": "United Arab Emirates",
       "ph": "Philippines",
       "ch": "Switzerland",
   }

   default_country = "Not Specified"

   return countries.get(country_code, default_country)

def map_id_to_name(needed_map_id) -> str:
   names =  'Mario Circuit 1','Donut Plains 1','Koopa Beach 1','Choco Island 1','Vanilla Lake 1','Ghost Valley 1','Mario Circuit 2','Bowser Castle 1','Donut Plains 2','Bowser Castle 2','Choco Island 2','Mario Circuit 3','Koopa Beach 2','Vanilla Lake 2','Ghost Valley 2','Donut Plains 3','Ghost Valley 3','Mario Circuit 4','Bowser Castle 3','Rainbow Road','Peach Circuit','Shy Guy Beach','Riverside Park','Bowser Castle I','Mario Circuit','Boo Lake','Cheese Land','Bowser Castle II','Luigi Circuit','Sky Garden','Cheep-Cheep Island','Sunset Wilds','Snow Land','Ribbon Road','Yoshi Desert','Bowser Castle III','Lakeside Park','Broken Pier','Bowser Castle IV','Rainbow Road','Figure 8 Circuit','Yoshi Falls','Cheep Cheep Beach','Luigi\'s Mansion','Desert Hills','Delfino Square','Waluigi Pinball','Shroom Ridge','DK Pass','Tick-Tock Clock','Mario Circuit','Airship Fortress','Wario Stadium','Peach Gardens','Bowser\'s Castle','Rainbow Road'
   map_id: int = 0
   map_amount = 56
   for name in names:
       map_id += 1
       if map_id == (map_amount + 1):
           break
       prefix = "DS"
       if map_id <= 40:
           prefix = "GBA"
       if map_id <= 20:
           prefix = "SNES"
       new_name = f"{prefix} {name}"
       if map_id == needed_map_id:
           return new_name
   return "???"

url = "https://mkpc.malahieude.net/api/getTtRanking.php"
data = {
   "cc": 150,
   "count": 1
}

response = requests.post(url, data=data)
if response.status_code == 200:
   ttwrs: str = response.json()
else:
   print("Couldn't get tt data. Status code:", response.status_code)


Of course, you'll have to install python to run them. But also the Requests HTTP Library for python to load the data in real time. It can be installed by typing this in cmd:
pip install requests


To specify the cc in the code you can change the cc value in the 2nd part of the script.

So that's the mkpc tt leaderboards as of 22/06/2024
Messages 141 - Buzzy Beetle Buzzy Beetle
vs61544 pts ★ Titan
battle8383 pts ★ Expert
United States
Very interesting, though there's one minor issue-

In the case of SNES BC2, there's currently a WR tie. JPG got a time of 41.741 on Feb 7, while Ahmad did the same 41.741 on the day after, February 8th. For some reason, though, Ahmad's time shows up ahead of JPG's.

On the list there it shows Ahmad's record as 865 days, which is correct. It didn't find the JPG time which has actually stood for a longer time (by one day). I'm guessing it's because MKPC shows the JPG time as "#2", instead of a tie for #1 (https://mkpc.malahieude.net/classement.php?cc=150&map=10)

This is a minor issue, though, and it's still very interesting! I'd love to see this be done analyzing the entire WR history of the game (using https://mkpc.malahieude.net/wrHistory.php?map=10&cc=150), but that may be a bit difficult to make.
Messages 11 - Koopa Koopa
vs39474 pts ★ Legend
battle6067 pts ★ Racer
Russia
Oof, I didn't think of ties... I thought mkpc just showed the longer lasting record but apparently not.
Messages 11 - Koopa Koopa
vs39474 pts ★ Legend
battle6067 pts ★ Racer
Russia
I might do the entire WR history btw
Messages 11 - Koopa Koopa
vs39474 pts ★ Legend
battle6067 pts ★ Racer
Russia
I made this script that shows data for every WR
Spoiler [ShowHide]

import re
from typing import List
import datetime
import requests
import pycountry
from bs4 import BeautifulSoup

track_names =  'SNES Mario Circuit 1', 'SNES Donut Plains 1', 'SNES Koopa Beach 1', 'SNES Choco Island 1', 'SNES Vanilla Lake 1', 'SNES Ghost Valley 1', 'SNES Mario Circuit 2', 'SNES Bowser Castle 1', 'SNES Donut Plains 2', 'SNES Bowser Castle 2', 'SNES Choco Island 2', 'SNES Mario Circuit 3', 'SNES Koopa Beach 2', 'SNES Vanilla Lake 2', 'SNES Ghost Valley 2', 'SNES Donut Plains 3', 'SNES Ghost Valley 3', 'SNES Mario Circuit 4', 'SNES Bowser Castle 3', 'SNES Rainbow Road', 'GBA Peach Circuit', 'GBA Shy Guy Beach', 'GBA Riverside Park', 'GBA Bowser Castle I', 'GBA Mario Circuit', 'GBA Boo Lake', 'GBA Cheese Land', 'GBA Bowser Castle II', 'GBA Luigi Circuit', 'GBA Sky Garden', 'GBA Cheep-Cheep Island', 'GBA Sunset Wilds', 'GBA Snow Land', 'GBA Ribbon Road', 'GBA Yoshi Desert', 'GBA Bowser Castle III', 'GBA Lakeside Park', 'GBA Broken Pier', 'GBA Bowser Castle IV', 'GBA Rainbow Road', 'DS Figure 8 Circuit', 'DS Yoshi Falls', 'DS Cheep Cheep Beach', "DS Luigi's Mansion", 'DS Desert Hills', 'DS Delfino Square', 'DS Waluigi Pinball', 'DS Shroom Ridge', 'DS DK Pass', 'DS Tick-Tock Clock', 'DS Mario Circuit', 'DS Airship Fortress', 'DS Wario Stadium', 'DS Peach Gardens', "DS Bowser's Castle", 'DS Rainbow Road'

all_tracks: bool = True
print_all_data: bool = True
if not print_all_data:
   map: int = 1
   cc: int = 150

if not all_tracks:
   print_all_data = True

url: str = "https://mkpc.malahieude.net/wrHistory.php"
last_WR_date = datetime.datetime.now()

characters = "mario", "luigi", "peach", "toad", "yoshi", "bowser", "donkey-kong", "daisy", "wario", "koopa", "waluigi", "maskass", "birdo", "roi_boo", "frere_marto", "bowser_skelet", "flora_piranha", "link", "bowser_jr", "harmonie", "diddy-kong", "skelerex", "funky-kong", "toadette"
def character_to_link(character: str) -> str:
   if character in characters:
       return f"https://mkpc.malahieude.net/images/sprites/sprite_{character}.png"
   else:
       return f"https://mkpc.malahieude.net/images/sprites/uploads/{character}.png"

is_current_WR: bool = True
records_dict: dict = {}
record_amount: int = 0
def process_records(records: List[BeautifulSoup]) -> None:
   for record in records:
       global record_amount
       record_amount += 1

       td = record.find_all('td';)

       a = td[0].find('a';)
       username: str = a.get_text(strip=True)
       user_id: str = re.findall(r'\d+', a['href'])[0]
       country_img = a.find('img';)
       if country_img:
           country: str = pycountry.countries.get(alpha_2=country_img['alt']).name # type: ignore
       else:
           country: str = 'Not Specified'

       global last_WR_date

       date: str = td[1].get_text(strip=True)
       date_in_datetime = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S" )
       time_lasted: int = (last_WR_date - date_in_datetime).days
       last_WR_date = date_in_datetime

       character: str = character_to_link(td[2].find('img';)['alt'])

       time: str = td[3].get_text(strip=True)

       global is_current_WR
       records_dict[record_amount - 1] = {
       'map': map,
       'cc': cc,
       'is_current_WR': is_current_WR,
       'time': time,
       'username': username,
       'user_id': user_id,
       'country': country,
       'date': date,
       'character': character,
       'time_lasted': time_lasted  }

       if print_all_data:
           print(f"{time} by {username} (User ID: {user_id}, Country: {country}). Date: {date}. Character: {character}. Time Lasted: {time_lasted}" )

       is_current_WR = False

def print_wr_history():
   if print_all_data:
       print(f"Every {track_names[map-1]} WR on {cc} cc (Track {map})" )
   next_url: str = url + f"?map={map}&cc={cc}"

   records: List[BeautifulSoup] = []
   while True:
       response = requests.get(next_url)

       why_did_they_call_it_soup = BeautifulSoup(response.content, 'html.parser';)
       records.extend(why_did_they_call_it_soup.find_all('tr', class_='result';))

       next_button_location = None
       for a in why_did_they_call_it_soup.find_all('a';):
           if a.get_text(strip=True) == 'Next results >':
               next_button_location = a
               break
       if next_button_location:
           next_url = url + next_button_location['href']
       else:
           break
   global last_WR_date
   global is_current_WR
   last_WR_date = datetime.datetime.now()
   is_current_WR = True
   process_records(records)

get_user_by_id_link = "https://mkpc.malahieude.net/api/getUserById.php"
username_cache = {}
def user_id_to_username(user_id: str) -> str:
   if user_id in username_cache:
       return username_cache[user_id]

   data = requests.post(get_user_by_id_link, data={"id": user_id}).json()
   if data:
       name = data["name"]
       username_cache[user_id] = name
       return name
   else:
       return "None"

if all_tracks:
   if not print_all_data:
       print("Progress: 0/112" )
   for i in range(56):
       map = i+1
       cc = 150
       print_wr_history()
       if not print_all_data:
           print(f"Progress: {(i*2)+1}/112" )
       cc = 200
       print_wr_history()
       if not print_all_data:
           print(f"Progress: {(i*2)+2}/112" )
   
   print("\nStats:" )

   print("\nTop 20 longest lasting records" )
   records_by_time_lasted = dict(sorted(records_dict.items(), key=lambda record: record[1]['time_lasted'], reverse=True))
   i = 0
   for record_key, record in records_by_time_lasted.items():
       i += 1
       is_current_WR_str: str = ''
       if record['is_current_WR']:
           is_current_WR_str = ' (the current WR)'
       else:
           is_current_WR_str = ' (no longer WR)'

       username = user_id_to_username(record["user_id"])
       print(f"{record['time']} on {track_names[record['map']-1]}, {record['cc']} cc by {username} (User ID: {record['user_id']}, Country: {record["country"]}). Lasted {record['time_lasted']} days, set on {record["date"]}{is_current_WR_str}" )
       if i == 20:
           break
   
   i = 0
   print("\nTop 20 longest lasting records (only with current WRs)" )
   for record_key, record in records_by_time_lasted.items():
       if record['is_current_WR'] == True:
           i += 1
           username = user_id_to_username(record["user_id"])
           print(f"{record['time']} on {track_names[record['map']-1]}, {record['cc']} cc by {username} (User ID: {record['user_id']}, Country: {record["country"]}). Lasted {record['time_lasted']} days, set on {record["date"]}" )
           if i == 20:
               break


   print("\nTotal world records of a player (max 20 players): " )

   user_record_count = {}
   for record_key, record in records_dict.items():
       user_id = record['user_id']
       
       if user_id in user_record_count:
           user_record_count[user_id]["count"] += 1
       else:
           user_record_count[user_id] = {
               "count" : 1,
               "id" : user_id,
               "country" : record["country"]
           }

   sorted_user_record_count = sorted(user_record_count.items(), key=lambda x: x[1]["count"], reverse=True)

   i = 0
   for user_id, data in sorted_user_record_count:
       count = data["count"]
       username = user_id_to_username(data["id"])
       print(f"{username} (User ID {data['id']}) - {count} records." )
       i += 1
       if i == 20:
           break
   
   print("\nTotal world records of a country (max 20 countries): " )

   country_record_count = {}
   for user_id, data in sorted_user_record_count:
       user_count = data["count"]
       country: str = data["country"]
       user_id: str = data["id"]
       if country in country_record_count:
           country_record_count[country]["count"] += user_count
           country_record_count[country]["user_ids"].append(user_id)
       else:
           country_record_count[country] = {
               "count" : user_count,
               "user_ids" : [user_id],
               "country" : country,
           }

   sorted_country_record_count = sorted(country_record_count.items(), key=lambda x: x[1]["count"], reverse=True)

   i = 0
   for country, data in sorted_country_record_count:
       count = data["count"]
       country_name = data["country"]
       usernames: list[str] = []
       for user_id in data["user_ids"]:
           usernames.append(user_id_to_username(user_id))
       
       print(f"{country_name} - {count} records. (Players: {str.join(", ", usernames)})" )
       i += 1
       if i == 20:
           break

else:
   print_wr_history()

import time
time.sleep(999)


but it prints every single WR and that message is too long for this forum lol (also it shows emojis in some places because the text is interpreted as an emoji and wargor should add a tag that interprets everything inside of it as normal text)

I wanted to only show the final data but it still had emojis.
So I just put it all here: https://gist.githubusercontent.com/iwtoq/ec562c798b50b2f9dc3a698400febf7d/raw/da17fb99a37672cb3c8ee73c368ab28be02266bc/mkpcttwrs.txt
And version only with the stats because why not: https://gist.githubusercontent.com/iwtoq/7b71c3cc79b2c8d27a0c7c1a233c7da7/raw/fa0212bbed37f09437ff4bb40d8a94bd81ae9bf9/mkpcttwrsstats.txt

Page :  1 

Back to The game
Back to the forum