feat: adds efficiency calculation for rigs and back pack (WIP). UX cleaned up, graphic added to landing page.

This commit is contained in:
serversdwn
2026-03-29 04:56:36 +00:00
parent 90f2601c1d
commit b5a5755b6f
11 changed files with 682 additions and 236 deletions

77
app.py
View File

@@ -1,7 +1,7 @@
from flask import Flask, render_template, request, redirect, url_for, jsonify
import sqlite3
app = Flask(__name__)
app = Flask(__name__, static_folder="assets", static_url_path="/assets")
DB_PATH = "tarkov.db"
@@ -436,24 +436,62 @@ LOADOUT_SLOT_FILTERS = [
def _sort_col(sort):
return {
"weight_asc": "weight_kg ASC NULLS LAST",
"weight_desc": "weight_kg DESC NULLS LAST",
"name_asc": "name ASC",
"name_desc": "name DESC",
"class_desc": "armor_class DESC NULLS LAST, weight_kg ASC NULLS LAST",
"class_asc": "armor_class ASC NULLS LAST, weight_kg ASC NULLS LAST",
"capacity_desc": "capacity DESC NULLS LAST, weight_kg ASC NULLS LAST",
"capacity_asc": "capacity ASC NULLS LAST, weight_kg ASC NULLS LAST",
"weight_asc": "weight_kg ASC NULLS LAST",
"weight_desc": "weight_kg DESC NULLS LAST",
"name_asc": "name ASC",
"name_desc": "name DESC",
"class_desc": "armor_class DESC NULLS LAST, weight_kg ASC NULLS LAST",
"class_asc": "armor_class ASC NULLS LAST, weight_kg ASC NULLS LAST",
"capacity_desc": "capacity DESC NULLS LAST, weight_kg ASC NULLS LAST",
"capacity_asc": "capacity ASC NULLS LAST, weight_kg ASC NULLS LAST",
# carry_efficiency sorts are handled in Python after query; fall back to weight
"efficiency_desc": "weight_kg ASC NULLS LAST",
"efficiency_asc": "weight_kg ASC NULLS LAST",
}.get(sort, "weight_kg ASC NULLS LAST")
def _carry_efficiency(weight_kg, slot_count):
"""Return (slots_per_kg, kg_per_slot) or (None, None) if inputs are invalid."""
if not weight_kg or not slot_count:
return None, None
try:
w = float(weight_kg)
s = int(slot_count)
except (TypeError, ValueError):
return None, None
if w <= 0 or s <= 0:
return None, None
return round(s / w, 2), round(w / s, 3)
def _enrich_with_efficiency(rows):
"""Attach slots_per_kg and kg_per_slot to each sqlite3.Row (returns plain dicts)."""
enriched = []
for row in rows:
d = dict(row)
d["slots_per_kg"], d["kg_per_slot"] = _carry_efficiency(
d.get("weight_kg"), d.get("capacity")
)
enriched.append(d)
return enriched
def _sort_enriched(rows, sort):
"""Sort a list of enriched dicts by carry efficiency when requested."""
if sort == "efficiency_desc":
return sorted(rows, key=lambda r: (r["slots_per_kg"] is None, -(r["slots_per_kg"] or 0)))
if sort == "efficiency_asc":
return sorted(rows, key=lambda r: (r["slots_per_kg"] is None, r["slots_per_kg"] or 0))
return rows
@app.route("/loadout")
def loadout():
conn = get_db()
tab = request.args.get("tab", "guns")
sort = request.args.get("sort", "weight_asc")
guns = armor = helmets = headwear = backpacks = rigs = plates = []
guns = armor = helmets = headwear = backpacks = rigs = armored_rigs = plates = []
builder_guns = builder_armor = builder_helmets = builder_rigs = builder_backpacks = []
requires = request.args.getlist("requires") # list of slot_nameids that must exist
min_class = request.args.get("min_class", 0, type=int)
@@ -523,21 +561,34 @@ def loadout():
""", (min_class, min_class)).fetchall()
elif tab == "backpacks":
backpacks = conn.execute(f"""
rows = conn.execute(f"""
SELECT * FROM gear_items
WHERE category = 'backpack'
AND (? = 0 OR capacity >= ?)
ORDER BY {sort_frag}
""", (min_capacity, min_capacity)).fetchall()
backpacks = _sort_enriched(_enrich_with_efficiency(rows), sort)
elif tab == "rigs":
rigs = conn.execute(f"""
rows = conn.execute(f"""
SELECT * FROM gear_items
WHERE category = 'rig'
AND armor_class IS NULL
AND (? = 0 OR capacity >= ?)
ORDER BY {sort_frag}
""", (min_capacity, min_capacity)).fetchall()
rigs = _sort_enriched(_enrich_with_efficiency(rows), sort)
elif tab == "armored_rigs":
rows = conn.execute(f"""
SELECT * FROM gear_items
WHERE category = 'rig'
AND armor_class IS NOT NULL
AND (? = 0 OR capacity >= ?)
AND (? = 0 OR armor_class >= ?)
ORDER BY {sort_frag}
""", (min_capacity, min_capacity, min_class, min_class)).fetchall()
armored_rigs = _sort_enriched(_enrich_with_efficiency(rows), sort)
elif tab == "plates":
plates = conn.execute(f"""
@@ -563,7 +614,7 @@ def loadout():
"loadout.html",
tab=tab, sort=sort,
guns=guns, armor=armor, helmets=helmets, headwear=headwear,
backpacks=backpacks, rigs=rigs, plates=plates,
backpacks=backpacks, rigs=rigs, armored_rigs=armored_rigs, plates=plates,
slot_filters=LOADOUT_SLOT_FILTERS,
requires=requires,
min_class=min_class, min_capacity=min_capacity,