snowrunner-data-extract/output.py
2026-08-16 11:44:59 +02:00

161 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)