This commit is contained in:
Stefan Harmuth 2026-08-16 11:44:59 +02:00
parent d8f3909c31
commit 1780362b90
4 changed files with 1927 additions and 0 deletions

1751
loader.py Normal file

File diff suppressed because it is too large Load Diff

15
main.py Normal file
View File

@ -0,0 +1,15 @@
from __future__ import annotations
from loader import InitialPakLoader
from output import create_html
import logging
import sys
def main():
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
pak = InitialPakLoader()
create_html(pak=pak, destination_directory="output/")
if __name__ == "__main__":
main()

160
output.py Normal file
View File

@ -0,0 +1,160 @@
from __future__ import annotations
import os
from loader import InitialPakLoader, LanguageLoader, SnowrunnerGameObjectType, SnowrunnerClass, GameData
from logging import getLogger
logger = getLogger(__name__)
def get_head(language: LanguageLoader, category: str, name: str | None = None) -> str:
return f"""<!DOCTYPE html>\n<html lang='{language.Ident}'>\n""" + (
f"""
<head>
<title>SnowRunnerDB - {category}"""
+ (f""" - {name}""" if name is not None else "")
+ f"""</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id='navi_lang'></div>
<div id='categories'>
<ul id='navi_cat'>
<li><a href="/{language.Name}/trucks/">Trucks</a></li>
</ul>
</div>
<div id='content'>
"""
)
def get_footer():
return f"""
</div>
</body>\n</html>\n
"""
def write_html(
file_path: str | os.PathLike, language: LanguageLoader, content: str, category: str, name: str | None = None
):
with open(file_path, "w") as f:
f.write(get_head(language=language, category=category, name=name))
f.write(content)
f.write(get_footer())
def write_trucks(pak: InitialPakLoader, destination_directory: str, language: LanguageLoader):
index_table = ""
truck_types = {}
for reference, truck in pak.get_sorted_object_list(SnowrunnerGameObjectType.TRUCK, language):
if truck.Type != "Truck":
continue
if truck.TruckData.TruckType not in truck_types:
truck_types[truck.TruckData.TruckType] = [(reference, truck)]
else:
truck_types[truck.TruckData.TruckType].append((reference, truck))
truck_file = os.path.join(destination_directory, reference + ".html")
truck_content = f" <h1>{truck.get_translated_ui_name(language)}</h1>"
# Engines
truck_content += f" <h2>Engines</h2>\n"
engines = [x for y in truck.TruckData.Engines for x in y.Engines]
truck_content += f" <table>\n"
truck_content += f" <tr><th>Name</th><th>Price</th><th>Torque</th><th>Base Fuel Consumption</th><th>Unlock By</th></tr>\n"
# Power2Weight
# Power2Fuel
for engine in sorted(engines, key=lambda x: x.Torque):
truck_content += (
f" <tr>"
f"<td>{engine.get_translated_ui_name(language)}</td>"
f"<td>{engine.GameData.Price}</th>"
f"<td>{engine.Torque}</td>"
f"<td>{engine.FuelConsumption}</td>"
f"<td>{engine.GameData.get_unlock_str()}</td>"
f"</tr>\n"
)
truck_content += f" </table>\n"
# Gearboxes
truck_content += f" <h2>Gearboxes</h2>\n"
# Suspensions
truck_content += f" <h2>Suspensions</h2>\n"
# Winches
truck_content += f" <h2>Winches</h2>\n"
# Wheels
truck_content += f" <h2>Wheels</h2>\n"
wheel_cat = {}
scales = set()
for cw in truck.TruckData.CompatibleWheels:
scales.add(cw.get_size_in_inches())
damage_cap = cw.TruckWheels.DamageCapacity
width = int(cw.TruckWheels.Width * cw.Scale * 100)
mass = cw.TruckWheels.Mass
# FIXME: cw.TruckWheels.GameData.ReadMassScale (affects the truck mass for dualies)
for tt in cw.TruckWheels.TruckTires.TruckTire:
if tt.Mass > 0:
mass = tt.Mass
if tt.Width > 0:
width = int(tt.Width * cw.Scale * 100)
cat = tt.WheelFriction.get_translated_ui_name(language)
if cat not in wheel_cat:
wheel_cat[cat] = {}
wheel_cat[cat][tt.UiName] = (damage_cap, width, mass, tt)
# Mud_Performance=
# Truck_Weight / (Tire_Count×(Tire_Diameter×Width×Softness)) * Tire_Mud_Rating
for cat in sorted(wheel_cat):
truck_content += f" <h3>{cat}</h3>\n"
truck_content += f" <table>\n"
truck_content += f" <tr><th colspan='4'>&nbsp;</th><th colspan='3'>Friction</th></tr>\n"
truck_content += f" <tr><th>Name</th><th>Price</th><th>Mass</th><th>Width</th><th>Asphalt</th><th>Off-Road</th><th>Mud</th></tr>\n"
for damage_cap, width, mass, tt in sorted(
wheel_cat[cat].values(), key=lambda v: v[3].get_translated_ui_name(language)
):
truck_content += f" <tr><td>{tt.get_translated_ui_name(language)}</td><td>{tt.GameData.Price}</td><td>{mass}kg</td><td>{width}cm</td><td>{tt.WheelFriction.BodyFrictionAsphalt}</td><td>{tt.WheelFriction.BodyFriction}</td><td>{tt.WheelFriction.SubstanceFriction}</td></tr>\n"
truck_content += f" </table>\n"
scales = ", ".join(['%d"' % x for x in sorted(scales)])
truck_content += f" <h4>Available Tire Sizes: {scales}</h4>\n"
write_html(
truck_file,
language=language,
content=truck_content,
category="Trucks",
name=truck.get_translated_ui_name(language),
)
index_content = " <h1>Trucks</h1>\n"
for truck_type in sorted(truck_types):
index_content += f" <h2>{truck_type}</h2>\n"
index_content += f" <table>\n"
index_content += f" <tr><th>Name</th></tr>\n"
for reference, truck in sorted(truck_types[truck_type], key=lambda v: v[1].get_translated_ui_name(language)):
index_content += f" <tr><td><a href='{reference}.html'>{truck.get_translated_ui_name(language)}</a></th></tr>\n"
index_content += f" </table>\n"
write_html(
os.path.join(destination_directory, "index.html"), language=language, content=index_content, category="Trucks"
)
def create_html(pak: InitialPakLoader, destination_directory: str = "output/"):
if not os.path.exists(destination_directory):
os.mkdir(destination_directory)
logger.info("Writing HTML Output")
for language_name, language_data in pak.languages.items():
logger.info(f" - {language_name}")
language_path = os.path.join(destination_directory, language_name)
if not os.path.exists(language_path):
os.mkdir(language_path)
write_trucks(pak=pak, destination_directory=language_path, language=language_data)

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
charset-normalizer