Add world output for resources
This commit is contained in:
parent
3c409fdbff
commit
aa55a34c1c
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
import itertools
|
||||||
import re
|
import re
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
@ -15,14 +15,22 @@ from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from factorygame.data.common import chose_resource, resource_needs_update, chose_recipe
|
from factorygame.data.common import chose_resource, resource_needs_update, chose_recipe
|
||||||
from .models import Recipe, Resource
|
from .models import Recipe, Resource, ResourceFlow
|
||||||
from ..helper import prompt
|
from ..helper import prompt
|
||||||
|
|
||||||
|
WORLD_OUTPUT_PORT_NAME = "World Output"
|
||||||
|
WORLD_OUTPUT_COLOR = (0, 139, 41)
|
||||||
|
|
||||||
|
CREATE_MACHINE_PORT_NAME = "Create Machine"
|
||||||
|
|
||||||
INPUT_COLOR = (249, 169, 0)
|
INPUT_COLOR = (249, 169, 0)
|
||||||
OUTPUT_COLOR = (204, 44, 36)
|
OUTPUT_COLOR = (204, 44, 36)
|
||||||
OTHER_COLOR = (0, 83, 135)
|
OTHER_COLOR = (0, 83, 135)
|
||||||
|
|
||||||
|
|
||||||
|
graph = None
|
||||||
|
|
||||||
|
|
||||||
class NodeSlider(NodeBaseWidget):
|
class NodeSlider(NodeBaseWidget):
|
||||||
def __init__(self, name, label="", parent=None):
|
def __init__(self, name, label="", parent=None):
|
||||||
super(NodeSlider, self).__init__(parent)
|
super(NodeSlider, self).__init__(parent)
|
||||||
|
@ -58,7 +66,22 @@ class GlobalInput(BaseNode):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.add_output("Create Machine", color=OTHER_COLOR)
|
self.model.width = 240
|
||||||
|
self.set_port_deletion_allowed(True)
|
||||||
|
self.add_special_ports()
|
||||||
|
|
||||||
|
def add_special_ports(self):
|
||||||
|
self.add_output(WORLD_OUTPUT_PORT_NAME, color=WORLD_OUTPUT_COLOR)
|
||||||
|
self.add_output(CREATE_MACHINE_PORT_NAME, color=OTHER_COLOR)
|
||||||
|
|
||||||
|
def reorder_outputs(self):
|
||||||
|
self.delete_output(WORLD_OUTPUT_PORT_NAME)
|
||||||
|
self.delete_output(CREATE_MACHINE_PORT_NAME)
|
||||||
|
self.add_special_ports()
|
||||||
|
|
||||||
|
def update_x_pos(self):
|
||||||
|
min_x_pos = min(map(lambda node: node.x_pos(), filter(lambda node: node != self, graph.all_nodes())))
|
||||||
|
self.set_x_pos(min_x_pos - self.view.width - 150)
|
||||||
|
|
||||||
|
|
||||||
class Machine(BaseNode):
|
class Machine(BaseNode):
|
||||||
|
@ -82,12 +105,6 @@ class Machine(BaseNode):
|
||||||
|
|
||||||
self.set_property("name", recipe.factory.label, push_undo=False)
|
self.set_property("name", recipe.factory.label, push_undo=False)
|
||||||
|
|
||||||
def in_amount_name(resource_label: str):
|
|
||||||
return f"In {resource_label} amount"
|
|
||||||
|
|
||||||
def out_amount_name(resource_label: str):
|
|
||||||
return f"Out {resource_label} amount"
|
|
||||||
|
|
||||||
input_resources: dict[str, float] = {}
|
input_resources: dict[str, float] = {}
|
||||||
for ingredient in recipe.ingredients:
|
for ingredient in recipe.ingredients:
|
||||||
resource_label = ingredient.resource.label
|
resource_label = ingredient.resource.label
|
||||||
|
@ -97,10 +114,12 @@ class Machine(BaseNode):
|
||||||
f"{input_resources[resource_label]:.2f} / min"
|
f"{input_resources[resource_label]:.2f} / min"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
port = self.add_input(resource_label, color=INPUT_COLOR)
|
port = self.add_input(resource_label, multi_input=True, color=INPUT_COLOR)
|
||||||
port.add_accept_port_type(resource_label, PortTypeEnum.OUT.value, "factorygame.Machine")
|
port.add_accept_port_type(resource_label, PortTypeEnum.OUT.value, "factorygame.Machine")
|
||||||
port.add_accept_port_type("Create Machine", PortTypeEnum.OUT.value, "factorygame.GlobalInput")
|
port.add_accept_port_type(resource_label, PortTypeEnum.OUT.value, "factorygame.GlobalInput")
|
||||||
self._add_text_label(
|
port.add_accept_port_type(CREATE_MACHINE_PORT_NAME, PortTypeEnum.OUT.value, "factorygame.GlobalInput")
|
||||||
|
port.add_accept_port_type(WORLD_OUTPUT_PORT_NAME, PortTypeEnum.OUT.value, "factorygame.GlobalInput")
|
||||||
|
self._add_readonly_resource_text(
|
||||||
in_amount_name(resource_label),
|
in_amount_name(resource_label),
|
||||||
ingredient,
|
ingredient,
|
||||||
input_resources,
|
input_resources,
|
||||||
|
@ -119,7 +138,7 @@ class Machine(BaseNode):
|
||||||
else:
|
else:
|
||||||
port = self.add_output(resource_label, color=OUTPUT_COLOR)
|
port = self.add_output(resource_label, color=OUTPUT_COLOR)
|
||||||
port.add_accept_port_type(resource_label, PortTypeEnum.IN.value, "factorygame.Machine")
|
port.add_accept_port_type(resource_label, PortTypeEnum.IN.value, "factorygame.Machine")
|
||||||
self._add_text_label(
|
self._add_readonly_resource_text(
|
||||||
out_amount_name(resource_label), result, output_resources, resource_label, border_color=OUTPUT_COLOR
|
out_amount_name(resource_label), result, output_resources, resource_label, border_color=OUTPUT_COLOR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -137,50 +156,92 @@ class Machine(BaseNode):
|
||||||
self.add_custom_widget(slider)
|
self.add_custom_widget(slider)
|
||||||
slider.value_changed.connect(lambda name, value: set_performance(max(1, min(250, value))))
|
slider.value_changed.connect(lambda name, value: set_performance(max(1, min(250, value))))
|
||||||
|
|
||||||
def _add_text_label(self, name, flow, resource_amounts, resource_label, border_color):
|
def _add_readonly_resource_text(
|
||||||
|
self,
|
||||||
|
name: str,
|
||||||
|
flow: ResourceFlow,
|
||||||
|
resource_amounts: dict[str, float],
|
||||||
|
resource_label: str,
|
||||||
|
border_color: tuple,
|
||||||
|
):
|
||||||
resource_amounts[resource_label] = flow.amount_per_minute()
|
resource_amounts[resource_label] = flow.amount_per_minute()
|
||||||
self.add_text_input(name=name, label=name, text=f"{resource_amounts[resource_label]} / min")
|
text = f"{resource_amounts[resource_label]} / min"
|
||||||
widget = self.get_widget(name)
|
add_resource_text(node=self, name=name, text=text, border_color=border_color, readonly=True)
|
||||||
line_edit_widget: QLineEdit = widget.get_custom_widget()
|
|
||||||
|
|
||||||
|
def in_amount_name(label: str):
|
||||||
|
return f"In {label} amount"
|
||||||
|
|
||||||
|
|
||||||
|
def out_amount_name(label: str):
|
||||||
|
return f"Out {label} amount"
|
||||||
|
|
||||||
|
|
||||||
|
def add_resource_text(node: BaseNode, name: str, text: str, border_color: tuple, readonly: bool = False):
|
||||||
|
node.add_text_input(name=name, label=name, text=text)
|
||||||
|
widget = node.get_widget(name)
|
||||||
|
line_edit_widget: QLineEdit = widget.get_custom_widget()
|
||||||
|
if readonly:
|
||||||
line_edit_widget.setReadOnly(True)
|
line_edit_widget.setReadOnly(True)
|
||||||
group: _NodeGroupBox = widget.widget()
|
group: _NodeGroupBox = widget.widget()
|
||||||
group.setMaximumWidth(220)
|
group.setMaximumWidth(220)
|
||||||
group.adjustSize()
|
group.adjustSize()
|
||||||
if border_color:
|
if border_color:
|
||||||
stylesheet = line_edit_widget.styleSheet()
|
stylesheet = line_edit_widget.styleSheet()
|
||||||
match = Machine.STYLESHEET_BORDER_COLOR_REGEX.match(stylesheet)
|
match = Machine.STYLESHEET_BORDER_COLOR_REGEX.match(stylesheet)
|
||||||
stylesheet = (
|
stylesheet = (
|
||||||
stylesheet[: match.start(1)] + f"rgb({','.join(map(str, border_color))})" + stylesheet[match.end(1) :]
|
stylesheet[: match.start(1)] + f"rgb({','.join(map(str, border_color))})" + stylesheet[match.end(1) :]
|
||||||
)
|
)
|
||||||
line_edit_widget.setStyleSheet(stylesheet)
|
line_edit_widget.setStyleSheet(stylesheet)
|
||||||
line_edit_widget.update()
|
line_edit_widget.update()
|
||||||
|
|
||||||
|
|
||||||
def on_port_connected(input_port: Port, output_port: Port):
|
def on_port_connected(input_port: Port, output_port: Port):
|
||||||
global debug
|
global debug
|
||||||
if debug:
|
if debug:
|
||||||
print(f"Port {output_port} connected to {input_port}")
|
print(f"Port {output_port} connected to {input_port}")
|
||||||
if isinstance(output_port.node(), GlobalInput) and output_port.name() == "Create Machine":
|
if isinstance(output_port.node(), GlobalInput):
|
||||||
output_port.clear_connections(push_undo=False, emit_signal=False)
|
global_input_node: GlobalInput = output_port.node()
|
||||||
with Session(engine) as session:
|
resource_label = input_port.name()
|
||||||
resource_label = input_port.name()
|
if output_port.name() == CREATE_MACHINE_PORT_NAME:
|
||||||
resource = session.scalars(Resource.by_label(resource_label)).one_or_none()
|
output_port.clear_connections(push_undo=False, emit_signal=False)
|
||||||
if resource_needs_update(resource, recipe_info_timeout=timedelta(days=365)):
|
with Session(engine) as session:
|
||||||
print("Please fetch resource", resource_label, "first.")
|
resource = session.scalars(Resource.by_label(resource_label)).one_or_none()
|
||||||
return
|
if resource_needs_update(resource, recipe_info_timeout=timedelta(days=365)):
|
||||||
|
print("Please fetch resource", resource_label, "first.")
|
||||||
|
return
|
||||||
|
|
||||||
# FIXME: use some Qt UI prompt method
|
# FIXME: use some Qt UI prompt method
|
||||||
recipe = chose_recipe(session=session, resource=resource, prompt=prompt)
|
recipe = chose_recipe(session=session, resource=resource, prompt=prompt)
|
||||||
if recipe is None:
|
if recipe is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
recipe_machine = graph.create_node("factorygame.Machine", push_undo=True)
|
recipe_machine: Machine = graph.create_node("factorygame.Machine", push_undo=True)
|
||||||
recipe_machine.assign_recipe(recipe)
|
recipe_machine.assign_recipe(recipe)
|
||||||
recipe_machine.update()
|
recipe_machine.update()
|
||||||
recipe_machine.set_x_pos(input_port.node().x_pos() - recipe_machine.view.width - 100)
|
recipe_machine.set_x_pos(input_port.node().x_pos() - recipe_machine.view.width - 100)
|
||||||
recipe_machine.get_output(input_port.name()).connect_to(input_port)
|
recipe_machine.get_output(resource_label).connect_to(input_port)
|
||||||
if recipe_machine.x_pos() - (global_input.x_pos() - global_input.view.width) < 150:
|
global_input_node.update_x_pos()
|
||||||
global_input.set_x_pos(recipe_machine.x_pos() - global_input.view.width - 150)
|
elif output_port.name() == WORLD_OUTPUT_PORT_NAME:
|
||||||
|
output_port.clear_connections(push_undo=False, emit_signal=False)
|
||||||
|
for idx, port in enumerate(global_input_node.output_ports()):
|
||||||
|
if port.name() == resource_label:
|
||||||
|
port.connect_to(input_port, push_undo=True, emit_signal=False)
|
||||||
|
# FIXME: recalculate
|
||||||
|
return
|
||||||
|
if isinstance(input_port.node(), Machine):
|
||||||
|
machine_node: Machine = input_port.node()
|
||||||
|
new_output_port = global_input_node.add_output(name=resource_label, color=OUTPUT_COLOR)
|
||||||
|
add_resource_text(
|
||||||
|
node=global_input_node,
|
||||||
|
name=out_amount_name(resource_label),
|
||||||
|
text=str(machine_node.get_property(in_amount_name(resource_label))),
|
||||||
|
border_color=OUTPUT_COLOR,
|
||||||
|
)
|
||||||
|
global_input_node.reorder_outputs()
|
||||||
|
global_input_node.update_x_pos()
|
||||||
|
new_output_port.connect_to(input_port, push_undo=True, emit_signal=False)
|
||||||
|
# FIXME: recalculate
|
||||||
|
|
||||||
|
|
||||||
@click.command
|
@click.command
|
||||||
|
@ -223,13 +284,12 @@ def main(debug: bool, search: str):
|
||||||
graph.register_node(GlobalInput)
|
graph.register_node(GlobalInput)
|
||||||
graph_widget = graph.widget
|
graph_widget = graph.widget
|
||||||
graph_widget.show()
|
graph_widget.show()
|
||||||
global global_input
|
|
||||||
global_input = graph.create_node("factorygame.GlobalInput", push_undo=False)
|
global_input = graph.create_node("factorygame.GlobalInput", push_undo=False)
|
||||||
recipe_machine = graph.create_node("factorygame.Machine", push_undo=False)
|
recipe_machine = graph.create_node("factorygame.Machine", push_undo=False)
|
||||||
recipe_machine.assign_recipe(recipe)
|
recipe_machine.assign_recipe(recipe)
|
||||||
graph.auto_layout_nodes([global_input, recipe_machine])
|
graph.auto_layout_nodes([global_input, recipe_machine])
|
||||||
global_input.set_y_pos(recipe_machine.y_pos())
|
global_input.set_y_pos(recipe_machine.y_pos())
|
||||||
global_input.set_x_pos(global_input.x_pos() - global_input.model.width - 150)
|
global_input.update_x_pos()
|
||||||
graph.center_on([global_input, recipe_machine])
|
graph.center_on([global_input, recipe_machine])
|
||||||
graph.port_connected.connect(on_port_connected)
|
graph.port_connected.connect(on_port_connected)
|
||||||
app.exec_()
|
app.exec_()
|
||||||
|
|
Loading…
Reference in a new issue