Add database calls to app.py

This commit is contained in:
Em (Ethan) Ruszanowski 2024-02-27 16:28:08 -05:00
parent 1fa40e729d
commit 7e625b8de3
Signed by: em
GPG key ID: C725D6E571252B96
2 changed files with 97 additions and 151 deletions

157
app.py
View file

@ -2,14 +2,6 @@ import streamlit as st
import database as db
class Moon:
def __init__(self, name, tier, inside_max_power, outside_max_power):
self.name = name
self.tier = tier
self.inside_max_power = inside_max_power
self.outside_max_power = outside_max_power
class Creature:
def __init__(self, name, nickname, power, max_spawns, hits_to_kill):
self.name = name
@ -26,85 +18,22 @@ class Run:
self.outside_power = moon.outside_max_power
def find_spawn_list(remaining_power: int, creatures: list[Creature]) -> list[str] | None:
"""
Given a run, return all possible spawns for location.
:param creatures:
:param remaining_power: The remaining power in the current location.
:return: A list of all creatures that may still spawn or None.
"""
if remaining_power == 0:
return None
spawnable = sorted(
[creature.name for creature in creatures if creature.power <= remaining_power]
)
if spawnable:
return spawnable
else:
return None
def main():
st.set_page_config("Lethal Company Scouter", "🛰️")
moons = [
# Tier 1
Moon("Experimentation", 1, 4, 8),
Moon("Assurance", 1, 6, 8),
Moon("Vow", 1, 7, 6),
# Tier 2
Moon("Offense", 2, 12, 12),
Moon("March", 2, 14, 12),
# Tier 3
Moon("Rend", 3, 10, 6),
Moon("Dine", 3, 15, 6),
Moon("Titan", 3, 18, 7),
]
outside_creatures = [
Creature("Baboon Hawk", None, 1, 15, 6),
Creature("Circuit Bees", None, 1, 6, None),
Creature("Eyeless Dog", None, 2, 8, 12),
Creature("Forest Keeper", "Giant", 3, 3, None),
Creature("Earth Leviathan", "Worm", 2, 3, None),
# Hybrid
Creature("Outside Ghost Girl ", None, 2, 1, None),
Creature("Outside Masked", None, 1, 10, 4),
]
inside_creatures = [
Creature("Bracken", "Freddy Fazbear", 3, 1, 6),
Creature("Bunker Spider", None, 3, 1, 6),
Creature("Coil Head", None, 1, 5, None),
Creature("Hoarding Bug", "Yippee Bug", 1, 8, 3),
Creature("Hygrodere", "Goo", 1, 2, None),
Creature("Jester", None, 3, 1, None),
Creature("Nutcracker", None, 1, 10, 5),
Creature("Snare Flea", "Head. Bug.", 1, 4, 3),
Creature("Spore Lizard", None, 1, 2, None),
Creature("Thumper", None, 2, 4, 4),
# Hybrid
Creature("Inside Ghost Girl", None, 2, 1, None),
Creature("Inside Masked", None, 1, 10, 4),
]
st.markdown("# :red[Lethal Company] Scouter")
st.markdown(":rainbow[What does the scouter say about this moon's power level?]")
moon_strings = db.get_moon_list()
moon = st.selectbox(
moon_name = st.selectbox(
"Moon",
moon_strings,
db.get_moon_list(),
placeholder="Moon! Pick a moon!",
help="Pick your current moon.",
)
moon_id = db.get_moon_id_by_name(moon_name)
run = Run(db.get_moon_by_id(moon_id))
run = Run(next(m for m in moons if m.name is moon))
st.markdown(f"## {run.moon.name} ({run.moon.tier})")
st.markdown(f"## {run.moon.name} (Tier {run.moon.tier})")
st.info(f"Risk: {run.moon.risk_level} | Min scrap: {run.moon.min_scrap} "
f"| Max scrap: {run.moon.max_scrap} | Default layout: {run.moon.default_layout}")
# Begin column layout
left_column, right_column = st.columns(2)
@ -112,81 +41,9 @@ def main():
with left_column:
st.markdown("### Outside")
with st.form("outside"):
for creature in outside_creatures:
moon_max = min(
creature.max_spawns, run.moon.outside_max_power // creature.power
)
if moon_max > 0:
st.slider(
creature.name,
0,
moon_max,
key=creature.name,
help=creature.nickname,
)
else:
st.slider(
creature.name,
0,
1,
key=creature.name,
help=creature.nickname,
disabled=True,
)
run.outside_power = run.outside_power - st.session_state[creature.name]
outside_submit = st.form_submit_button("Calculate")
if outside_submit:
st.info(f"Maximum power: {run.moon.outside_max_power}")
if run.outside_power >= 0:
st.warning(f"🌳 Outside power remaining: {run.outside_power}")
st.write(find_spawn_list(run.outside_power, outside_creatures))
else:
st.error(
f"Power level exceeds maximum possible for {run.moon.name}."
)
with right_column:
st.markdown("### Inside")
with st.form("inside"):
for creature in inside_creatures:
moon_max = min(
creature.max_spawns, run.moon.inside_max_power // creature.power
)
if moon_max > 0:
st.slider(
creature.name,
0,
moon_max,
key=creature.name,
help=creature.nickname,
)
else:
st.slider(
creature.name,
0,
1,
key=creature.name,
help=creature.nickname,
disabled=True,
)
run.inside_power = run.inside_power - st.session_state[creature.name]
inside_submit = st.form_submit_button("Calculate")
if inside_submit:
st.info(f"Maximum power: {run.moon.inside_max_power}")
if run.inside_power >= 0:
st.warning(f"🏭 Inside power remaining: {run.inside_power}")
st.write(find_spawn_list(run.inside_power, inside_creatures))
else:
st.error(
f"Power level exceeds maximum possible for {run.moon.name}."
)
if __name__ == "__main__":
main()

View file

@ -2,22 +2,111 @@ import os
import sqlite3
class Moon:
def __init__(self, moon_id, name, risk_level, cost, default_layout, map_size_multiplier, min_scrap, max_scrap,
outside_max_power, inside_max_power, tier):
self.id = moon_id
self.name = name
self.risk_level = risk_level
self.cost = cost
self.default_layout = default_layout,
self.map_size_multiplier = map_size_multiplier
self.min_scrap = min_scrap
self.max_scrap = max_scrap
self.outside_max_power = outside_max_power
self.inside_max_power = inside_max_power
self.tier = tier
def get_connection() -> sqlite3.Connection:
"""Opens a connection to the SQLite3 database at the default path
or a path provided by an environment variable if one exists.
:return: A connection to the database as a sqlite3.Connection object
"""
if os.getenv("DATABASE_FILE"):
return sqlite3.connect(os.getenv("DATABASE_FILE"))
else:
return sqlite3.connect("./scouter.db")
def get_moon_id_by_name(moon_name: str) -> int | None:
"""Queries the database for a moon ID that matches the given name.
:param moon_name: Moon name as a string
:return: The moon's ID as an int or None if no moon is found
"""
with get_connection() as connection:
cursor = connection.cursor()
moon_id = cursor.execute(
"select moon_id "
"from moon "
"where moon_name = ? "
"limit 1;",
(moon_name,)
).fetchone()
if moon_id:
return moon_id[0]
else:
return None
def get_moon_list() -> list[str] | None:
"""Provides a list of all moon names from the database.
:return: All moon names as a list of strings or None if no moons are found
"""
with get_connection() as connection:
cursor = connection.cursor()
moons = cursor.execute(
"select moon_name from moon order by moon_id"
)
).fetchall()
if moons:
moons = [moon[0] for moon in moons]
return moons
else:
return None
def get_moon_by_id(moon_id: int) -> Moon | None:
"""Queries the database to create a moon object.
:param moon_id: Moon ID as int
:return: A moon object or None if no moon is found
"""
with get_connection() as connection:
connection.text_factory = str
cursor = connection.cursor()
query = """
select m.moon_id,
m.moon_name,
rl.risk_level_name,
m.cost,
l.layout_name,
m.map_size_multiplier,
m.min_scrap,
m.max_scrap,
m.outside_max_power,
m.inside_max_power,
mt.tier_name
from moon as m
join main.risk_level rl on rl.risk_level_id = m.risk_level_id
join main.layout l on l.layout_id = m.default_layout_id
join main.moon_tier mt on mt.moon_tier_id = m.moon_tier_id
where m.moon_id = ?
limit 1;"""
moon = cursor.execute(
query,
(moon_id,)
).fetchone()
if moon:
return Moon(*moon)
else:
return None
print(get_moon_by_id(3).default_layout)