#!/usr/bin/env python3 import sys from os import path linesep = "\n" if len(sys.argv) != 3 or not sys.argv[1] or not sys.argv[2]: print("Usage: coldstore.py ") print("\t\t\tthe game directory where wads and luafiles reside. Usually at '$HOME/.srb2kart'.") print("\t\tthe output name for the records packed lua file. It will be saved within .") quit() if not sys.argv[2].endswith(".lua"): print("{} must end with .lua".format(sys.argv[2])) quit() game_dir = sys.argv[1] leaderboard_txt = path.join(game_dir, "luafiles", "leaderboard.txt") coldstore_txt = path.join(game_dir, "luafiles", "leaderboard.coldstore.txt") records_lua = path.join(game_dir, sys.argv[2]) def ParseScore(score): # Map Name Skin Color Time Splits Flags Stat split = score.split("\t") checksum = "" if len(split) > 8: checksum = split[8] return { "map": split[0], "name": split[1], "skin": split[2], "color": split[3], "time": int(split[4]), "splits": split[5], "flags": int(split[6]), "stat": split[7], "checksum": checksum } # Compare scores def CompareScore(a, b): return a["time"] < b["time"] F_SEP = 0xF def SameScore(a, b): return a["name"] == b["name"] and a["checksum"] == b["checksum"] and (a["flags"] & F_SEP) == (b["flags"] & F_SEP) def LoadRecordsFromFile(path): records = [] try: with open(path, "r") as f: for line in f.readlines(): line = line.strip() if line != "": records.append(ParseScore(line)) except FileNotFoundError: pass return records def AddScore(records, score): mapid = score["map"] mapTable = records.get(mapid) or [] for i in range(len(mapTable)): scoreb = mapTable[i] if SameScore(score, scoreb): if CompareScore(score, scoreb): mapTable[i] = score records[mapid] = mapTable return mapTable.append(score) records[mapid] = mapTable # load leaderboard.txt and coldstore.txt recordsList = LoadRecordsFromFile(leaderboard_txt) recordsList.extend(LoadRecordsFromFile(coldstore_txt)) # construct the map tables records = {} for score in recordsList: AddScore(records, score) # convert records to flat list recordsList = [] rejected = [] for mapTable in records.values(): for score in mapTable: scoreStr = "\t".join([str(v) for v in list(score.values())]) # only allow records with checksums if score["checksum"] != "": recordsList.append(scoreStr) else: rejected.append(scoreStr) # truncate and write records to coldstore with open(coldstore_txt, "w") as f: for score in recordsList: f.write(score + linesep) luaA = """do local AddColdStore = lb_add_coldstore_record_string local records = { """ luaB = """ } for _, str in ipairs(records) do AddColdStore(str) end end """ # pack the records.lua file with open(records_lua, "w") as f: f.write(luaA) for score in recordsList: score = score.replace("\\", "\\\\") score = score.replace("\"", "\\\"") f.write("\t\t\"{}\",{}".format(score, linesep)) f.write(luaB) # truncate and rewrite rejected scores to leaderboard.txt with open(leaderboard_txt, "w") as f: for score in rejected: f.write(score + linesep)