395 lines
11 KiB
Python
395 lines
11 KiB
Python
from dateutil.parser import parse
|
|
from dataclasses import dataclass
|
|
import sqlite3 as sql
|
|
import PySimpleGUI as sg
|
|
from ImguiWindow import ImguiWindow, load_texture
|
|
import glfw
|
|
import imgui as im
|
|
import random
|
|
import datetime
|
|
|
|
def get_bank():
|
|
cursor = conn.cursor()
|
|
cursor.execute("""
|
|
SELECT resource.name,balance FROM bank_account
|
|
INNER JOIN resource ON resource.id = bank_account.resource_id
|
|
WHERE user_id = ?
|
|
""", (world.current_user_id,))
|
|
bank = {name: balance for name,balance in cursor.fetchall()}
|
|
cursor.close()
|
|
return bank
|
|
|
|
def get_store_items():
|
|
cursor = conn.cursor()
|
|
cursor.execute("""
|
|
SELECT store_item.id,store_item.name,resource.name,price,claim_amount FROM store_item
|
|
INNER JOIN resource ON resource.id = currency
|
|
""")
|
|
items = {item[0]:item[1:] for item in cursor.fetchall()}
|
|
cursor.close()
|
|
return items
|
|
|
|
def get_moons():
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT id,created_at FROM staking_source")
|
|
|
|
staking_sources = {}
|
|
for i,(sid,ts) in enumerate(cursor.fetchall()):
|
|
cursor.execute("""
|
|
SELECT name,supply,staking_event.created_at
|
|
FROM resource_well
|
|
INNER JOIN resource ON resource.id = resource_well.resource_id
|
|
LEFT JOIN staking_event ON staking_event.well_id = resource_well.id
|
|
WHERE resource_well.source_id = ?;
|
|
""", (sid,))
|
|
wells = {name: (supply,timestamp) for name,supply,timestamp in cursor.fetchall()}
|
|
stakes = get_active_stakes(sid)
|
|
staking_sources[sid] = (ts,wells,stakes)
|
|
|
|
cursor.close()
|
|
return staking_sources
|
|
|
|
def get_inventory():
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("""
|
|
SELECT inventory_item.id,store_item_id, COUNT(upgrade_event.id) as upgrades
|
|
FROM inventory_item
|
|
LEFT JOIN upgrade_event ON inventory_item.id = upgrade_event.inventory_item_id
|
|
WHERE inventory_item.user_id = ?
|
|
GROUP BY inventory_item.id;
|
|
""", (world.current_user_id,))
|
|
|
|
inventory = {item[0]:item[1:] for item in cursor.fetchall()}
|
|
|
|
cursor.close()
|
|
return inventory
|
|
|
|
# An active stake is basically defined as one that has yet to be claimed
|
|
def get_active_stakes(source_id):
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("""
|
|
SELECT staking_event.id, staking_event.source_id, staking_event.well_id,
|
|
staking_event.inventory_item_id, staking_event.duration_in_mins,
|
|
staking_event.created_at
|
|
FROM staking_event
|
|
LEFT JOIN claim_event ON staking_event.id = claim_event.staking_event_id
|
|
WHERE staking_event.source_id = ? AND claim_event.staking_event_id IS NULL;
|
|
""", (source_id,))
|
|
|
|
active_stakes = {item[0]:item[1:] for item in cursor.fetchall()}
|
|
|
|
cursor.close()
|
|
return active_stakes
|
|
|
|
|
|
def get_stakes(source_id):
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("""
|
|
SELECT staking_event.id,well_id,staking_event.source_id,
|
|
inventory_item_id,duration_in_mins,staking_event.created_at
|
|
FROM staking_event
|
|
INNER JOIN staking_source on staking_event.source_id = staking_source.id
|
|
WHERE staking_event.source_id = ? AND staking_source.user_id = ?;
|
|
""", (source_id, world.current_user_id))
|
|
|
|
# (id, ( wellId, sourceId, invId, duration, created ))
|
|
stakes = {item[0]:item[1:] for item in cursor.fetchall()}
|
|
|
|
cursor.close()
|
|
return stakes
|
|
|
|
def mint():
|
|
cursor = conn.cursor()
|
|
rand_hash = "%010x" % random.randrange(16 ** 16)
|
|
|
|
cursor.execute('BEGIN')
|
|
source_id = -1
|
|
try:
|
|
cursor.execute("""
|
|
INSERT INTO staking_source (user_id, address) VALUES (?, ?)
|
|
""", (world.current_user_id, f"0x{rand_hash}"))
|
|
|
|
source_id = cursor.lastrowid
|
|
for id,_ in world.resources:
|
|
init_supply = random.randint(50, 200)
|
|
cursor.execute("""
|
|
INSERT INTO resource_well (source_id, resource_id, supply) VALUES (?, ?, ?)
|
|
""", (source_id, id, init_supply))
|
|
|
|
conn.commit()
|
|
except sql.Error as error:
|
|
print(error)
|
|
conn.rollback()
|
|
finally:
|
|
cursor.close()
|
|
|
|
world.staking_sources = get_moons()
|
|
return source_id
|
|
|
|
def buy_item(item_id):
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("""
|
|
INSERT INTO inventory_item (user_id, store_item_id)
|
|
VALUES (?, ?)
|
|
""", (world.current_user_id, item_id))
|
|
|
|
item_id = cursor.lastrowid
|
|
conn.commit()
|
|
cursor.close()
|
|
world.inventory = get_inventory()
|
|
return item_id
|
|
|
|
def mine(source_id, resource, item_id):
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("""
|
|
INSERT INTO staking_event (source_id, well_id, inventory_item_id, duration_in_mins)
|
|
VALUES (?, (SELECT id FROM resource_well WHERE resource_id = ? AND source_id = ?), ?, ?)
|
|
""", (source_id, world.resource_to_id[resource], source_id, item_id, 3))
|
|
|
|
conn.commit()
|
|
world.staking_sources = get_moons()
|
|
cursor.close()
|
|
|
|
def claim(staking_event_id):
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("""
|
|
INSERT INTO claim_event (claim_amount, staking_event_id)
|
|
VALUES (?, ?)
|
|
""", (10, staking_event_id))
|
|
|
|
conn.commit()
|
|
world.staking_sources = get_moons()
|
|
cursor.close()
|
|
|
|
|
|
def upgrade(a,b,user_data):
|
|
()
|
|
|
|
def destroy(source_id):
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("DELETE FROM staking_source WHERE id = ?", (source_id,))
|
|
|
|
conn.commit()
|
|
cursor.close()
|
|
world.staking_sources = get_moons()
|
|
|
|
def sell(item_id):
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("DELETE FROM inventory_item WHERE user_id = ? AND id = ?",
|
|
(world.current_user_id, item_id))
|
|
|
|
conn.commit()
|
|
cursor.close()
|
|
world.inventory = get_inventory()
|
|
|
|
def sell_all():
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("DELETE FROM inventory_item WHERE user_id = ?", (current_user_id,))
|
|
|
|
conn.commit()
|
|
cursor.close()
|
|
world.inventory = get_inventory()
|
|
|
|
def draw_dashboard():
|
|
im.text(f"Current User: {world.current_user}")
|
|
for _ in range(10):
|
|
im.spacing()
|
|
for name,balance in world.bank.items():
|
|
im.text(f"{name.capitalize()}: {balance}")
|
|
|
|
def draw_store():
|
|
for id,(name,resource,price,claim) in world.store.items():
|
|
owned = False
|
|
for (store_item_id,_) in world.inventory.values():
|
|
if id == store_item_id:
|
|
owned = True
|
|
im.text(f"{name}: Mine {claim} {resource.capitalize()}")
|
|
|
|
if owned:
|
|
im.text_disabled(f"Buy {price} {resource[0:3]}")
|
|
else:
|
|
im.push_id(f"Buy{id}")
|
|
if im.button(f"Buy {price} {resource[0:3]}"):
|
|
buy_item(id)
|
|
im.pop_id()
|
|
for _ in range(5):
|
|
im.spacing()
|
|
|
|
def draw_inventory():
|
|
for id,(sid,tier) in world.inventory.items():
|
|
im.text(f"{id} - {world.store[sid][0]} - Tier {tier+1}")
|
|
im.push_id(f"Upgrade{id}")
|
|
if im.button("Upgrade"):
|
|
print("Upgrade")
|
|
im.pop_id()
|
|
im.same_line()
|
|
im.push_id(f"Sell{id}")
|
|
if im.button("Sell"):
|
|
sell(id)
|
|
im.pop_id()
|
|
for _ in range(5):
|
|
im.spacing()
|
|
|
|
def draw_moons():
|
|
if im.button("Mint"):
|
|
mint()
|
|
|
|
im.begin_child("Moons")
|
|
im.columns(3, 'fileLlist')
|
|
im.set_column_width(0, 250)
|
|
im.set_column_width(1, 600)
|
|
im.separator()
|
|
im.text("Moon")
|
|
im.next_column()
|
|
im.text("Resources")
|
|
im.next_column()
|
|
im.text("Active Stakes")
|
|
im.next_column()
|
|
im.separator()
|
|
|
|
for source_id,(ts,wells,stakes) in world.staking_sources.items():
|
|
im.image(world.moon_img_tex_id, 240, 200)
|
|
im.push_id(f"Destroy{id}")
|
|
if im.button("Destroy"):
|
|
destroy(source_id)
|
|
im.pop_id()
|
|
|
|
im.next_column()
|
|
|
|
for name,(supply,ts) in wells.items():
|
|
im.text(f"{name.capitalize()}: {supply}")
|
|
items = [(item[0], world.store[item[1][0]][0]) for item in world.inventory.items()]
|
|
for item_id,item_name in items:
|
|
im.push_id(f"Mine{id}{name}")
|
|
if im.button(item_name):
|
|
mine(source_id, name, item_id)
|
|
im.pop_id()
|
|
im.same_line()
|
|
im.spacing()
|
|
|
|
im.next_column()
|
|
for stake_id,(source_id,wid,invId,dur,start) in stakes.items():
|
|
start_time = parse(start)
|
|
now = datetime.datetime.utcnow().replace(microsecond=0)
|
|
delta = now - start_time
|
|
im.push_id(f"Claim{stake_id}")
|
|
if delta > datetime.timedelta(minutes=dur):
|
|
if im.button("Claim"):
|
|
claim(stake_id)
|
|
else:
|
|
im.text_disabled("Claim")
|
|
im.pop_id()
|
|
im.text(f"{world.store[world.inventory[invId][0]][0]}: {delta}")
|
|
|
|
im.next_column()
|
|
|
|
im.separator()
|
|
|
|
im.columns(1)
|
|
im.end_child()
|
|
|
|
def draw_panels():
|
|
screen_width, screen_height = glfw.get_video_mode(glfw.get_primary_monitor())[0]
|
|
|
|
# TODO: We probably don't need to create a "Main" window...
|
|
im.set_next_window_size(screen_width, screen_height)
|
|
|
|
# Set the next window position to (0, 0) to make the window cover the entire screen
|
|
im.set_next_window_position(0, 0)
|
|
|
|
f = im.WINDOW_NO_TITLE_BAR | im.WINDOW_NO_RESIZE | im.WINDOW_NO_MOVE | im.WINDOW_NO_COLLAPSE
|
|
im.begin("Main", flags=f)
|
|
im.end()
|
|
|
|
# Dashboard
|
|
im.set_next_window_position(0, 0)
|
|
im.set_next_window_size(400, 450)
|
|
f = im.WINDOW_NO_RESIZE | im.WINDOW_NO_MOVE
|
|
im.begin("Dashboard", flags=f)
|
|
|
|
draw_dashboard()
|
|
|
|
im.end()
|
|
|
|
# Store
|
|
im.set_next_window_position(402, 0)
|
|
im.set_next_window_size(500, 450)
|
|
f = im.WINDOW_NO_RESIZE | im.WINDOW_NO_MOVE
|
|
im.begin("Store", flags=f)
|
|
|
|
draw_store()
|
|
|
|
im.end()
|
|
|
|
# Inventory
|
|
im.set_next_window_position(902, 0)
|
|
im.set_next_window_size(500, 450)
|
|
f = im.WINDOW_NO_RESIZE | im.WINDOW_NO_MOVE
|
|
im.begin("Inventory", flags=f)
|
|
|
|
draw_inventory()
|
|
|
|
im.end()
|
|
|
|
# Moons
|
|
im.set_next_window_position(0, 452)
|
|
im.set_next_window_size(1400, 540)
|
|
f = im.WINDOW_NO_RESIZE | im.WINDOW_NO_MOVE | im.WINDOW_ALWAYS_VERTICAL_SCROLLBAR
|
|
im.begin("Moons", flags=f)
|
|
|
|
draw_moons()
|
|
|
|
im.end()
|
|
|
|
@dataclass
|
|
class World:
|
|
current_user = "Joe"
|
|
current_user_id = 1
|
|
moon_img_tex_id = -1
|
|
bank = dict()
|
|
resources = []
|
|
id_to_resource = dict()
|
|
resource_to_id = dict()
|
|
store = dict()
|
|
inventory = dict()
|
|
staking_sources = dict()
|
|
stakes = dict()
|
|
|
|
world = World()
|
|
|
|
conn = sql.connect("mm.db", check_same_thread=False)
|
|
conn.execute('PRAGMA foreign_keys = ON')
|
|
|
|
world.current_user = "Joe"
|
|
world.current_user_id = 1
|
|
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("SELECT id,name FROM resource")
|
|
world.resources = cursor.fetchall()
|
|
cursor.close()
|
|
|
|
world.id_to_resource = {id: name for id, name in world.resources}
|
|
world.resource_to_id = {name: id for id, name in world.resources}
|
|
world.bank = get_bank()
|
|
world.store = get_store_items()
|
|
world.inventory = get_inventory()
|
|
world.staking_sources = get_moons()
|
|
|
|
def imgui_init():
|
|
world.moon_img_tex_id = texture_id = load_texture("moon.png")
|
|
|
|
imguiWindow = ImguiWindow(imgui_init, draw_panels, "Moon Miner Test", 1400, 1000)
|
|
|
|
conn.close()
|