ddnet/scripts/import_file_score.py
heinrich5991 17402cc43f Rename all variables for strict camel-casing of abbreviations
This is the strict version, ID → Id, UI → Ui, except DDNet which stays
DDNet.

This would fix #7750.

Done using a naive rename script (for bash, use `shopt -s globstar`):

```fish
sed -i \
	-e 's/\([a-z]_\?\)ID/\1Id/g' \
	-e 's/\([^ ]\)\<UI\>/\1Ui/g' \
	-e 's/UI()/Ui()/g' \
	-e 's/\<CUI\>/CUi/g' \
	-e 's/\([\ta-z.(&]\|[,=|] \)ID\>/\1Id/g' \
	-e 's/\<ID\>\([^ ").]\)/Id\1/g' \
	-e 's/\<ID\([0-9]\)/Id\1/g' \
	-e 's/\<ID\>\( [<=>:+*/-]\)/Id\1/g' \
	-e 's/int ID/int Id/g' \
	-e 's/\([a-z]_\?\)GPU/\1Gpu/g' \
	-e 's/\([a-z]_\?\)IP/\1Ip/g' \
	-e 's/\([a-z]_\?\)CID/\1Cid/g' \
	-e 's/\([a-z]_\?\)MySQL/\1Mysql/g' \
	-e 's/MySql/Mysql/g' \
	-e 's/\([a-xz]_\?\)SQL/\1Sql/g' \
	-e 's/DPMode/DpMode/g' \
	-e 's/TTWGraphics/TTwGraphics/g' \
	\
	-e 's/Ipointer/IPointer/g' \
	-e 's/\.vendorId/.vendorID/g' \
	-e 's/\.windowId/.windowID/g' \
	-e 's/SDL_GetWindowFromId/SDL_GetWindowFromID/g' \
	-e 's/SDL_AudioDeviceId/SDL_AudioDeviceID/g' \
	-e 's/SDL_JoystickId/SDL_JoystickID/g' \
	-e 's/SDL_JoystickInstanceId/SDL_JoystickInstanceID/g' \
	-e 's/AVCodecId/AVCodecID/g' \
	src/**/*.cpp src/**/*.h {datasrc,scripts}/**/*.py
git checkout -- src/engine/external
```

I like this option because it presents clear rules.

Still needs fixups because of the naive replacement, I'd do this if we
want this merged.
2024-03-05 15:44:09 +01:00

85 lines
3.1 KiB
Python
Executable file

#!/usr/bin/env python3
from collections import namedtuple
from decimal import Decimal
import argparse
import os.path
import re
import sqlite3
import sys
def chunks(l, n):
for i in range(0, len(l), n):
yield l[i:i+n]
class Record(namedtuple('Record', 'name time checkpoints')):
@staticmethod
def parse(lines):
if len(lines) != 3:
raise ValueError("wrong amount of lines for record")
name = lines[0]
time = Decimal(lines[1])
checkpoints_str = lines[2].split(' ')
if len(checkpoints_str) != 26 or checkpoints_str[25] != "":
raise ValueError(f"wrong amount of checkpoint times: {len(checkpoints_str)}")
checkpoints_str = checkpoints_str[:25]
checkpoints = tuple(Decimal(c) for c in checkpoints_str)
return Record(name=name, time=time, checkpoints=checkpoints)
def unparse(self):
return "\n".join([self.name, str(self.time), " ".join([str(cp) for cp in self.checkpoints] + [""]), ""])
def read_records(file):
contents = file.read().splitlines()
return [Record.parse(c) for c in chunks(contents, 3)]
MAP_RE=re.compile(r"^(?P<map>.*)_record\.dtb$")
def main():
p = argparse.ArgumentParser(description="Merge multiple DDNet race database files", formatter_class=argparse.ArgumentDefaultsHelpFormatter)
p.add_argument("--out", default="ddnet-server.sqlite", help="Output SQLite database")
p.add_argument("in_", metavar="IN", nargs='+', help="Text score databases to import; must have the format MAPNAME_record.dtb")
p.add_argument("--dry-run", "-n", action='store_true', help="Don't write out the resulting SQLite database")
p.add_argument("--stats", action='store_true', help="Display some stats at the end of the import process")
args = p.parse_args()
records = {}
for in_ in args.in_:
match = MAP_RE.match(os.path.basename(in_))
if not match:
raise ValueError(f"Invalid text score database name, does not end in '_record.dtb': {in_}")
m = match.group("map")
if m in records:
raise ValueError(f"Two text score databases refer to the same map: {in_}")
with open(in_, encoding="utf-8") as f:
records[m] = read_records(f)
if not args.dry_run:
conn = sqlite3.connect(args.out)
c = conn.cursor()
c.execute("CREATE TABLE IF NOT EXISTS record_race ("
"Map VARCHAR(128) COLLATE BINARY NOT NULL, "
"Name VARCHAR(16) COLLATE BINARY NOT NULL, "
"Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
"Time FLOAT DEFAULT 0, "
"Server CHAR(4), " +
"".join(f"cp{i + 1} FLOAT DEFAULT 0, " for i in range(25)) +
"GameId VARCHAR(64), "
"DDNet7 BOOL DEFAULT FALSE"
");")
c.executemany(
"INSERT INTO record_race (Map, Name, Time, Server, " +
"".join(f"cp{i + 1}, " for i in range(25)) +
"GameId, DDNet7) " +
f"VALUES ({','.join('?' * 31)})",
[(map, r.name, float(r.time), "TEXT", *[float(c) for c in r.checkpoints], None, False) for map, record in records.items() for r in record]
)
conn.commit()
conn.close()
if args.stats:
print(f"Number of imported text databases: {len(records)}", file=sys.stderr)
print(f"Number of imported ranks: {sum(len(r) for r in records.values())}", file=sys.stderr)
if __name__ == '__main__':
sys.exit(main())