Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/app/connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def nodes_in_bfs_order(self):
# create the dictionary
for node in self.canvas:
# create node
nodes_list[node["id"]] = Node(node["id"], node["queueType"], node["priorityFunction"], node["numberOfActors"],
nodes_list[node["id"]] = Node(node["id"], node["queueType"], node["priorityFunction"], node["numberOfActors"], node["distributionFunction"],
process_name=node["elementType"], distribution_name=node["distribution"],
distribution_parameters=node["distributionParameters"], output_process_ids=node["children"], rules=[],
priority_type=node["priorityType"])
Expand Down
42 changes: 39 additions & 3 deletions backend/app/models/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from flask import Flask
import os
import random
import numpy as np


app = Flask(__name__)

Expand All @@ -20,7 +22,7 @@ class Node:
node_dict = {}
environment = os.environ.get("DEV_ENV")
'''rules is a list of Rule Objects'''
def __init__(self, id, queue_type, priority_function, num_actors,
def __init__(self, id, queue_type, priority_function, num_actors, distribution_function,
process_name=None, distribution_name=None,
distribution_parameters=None, output_process_ids=None, rules=[], priority_type=""):

Expand All @@ -36,6 +38,12 @@ def __init__(self, id, queue_type, priority_function, num_actors,
self.priority_type = None
else:
self.priority_type = priority_type

if distribution_function == "":
self.distribution_function = None
else:
self.distribution_function = distribution_function

self.queue = self._set_queue()

# create num actors and resource dict based on num actors
Expand All @@ -50,6 +58,24 @@ def __init__(self, id, queue_type, priority_function, num_actors,
Node.node_dict[self.id] = self
self.node_rules = rules[:]

if self.distribution_name == "define_your_own":
self._parse_d_func()

def _parse_d_func(self):
"""
Helper function to help fix spacing and remove empty lines
Assign self.d_func to be the parse string
"""
split = self.distribution_function.split("\n")
new_split = []
for line in split:
line = line.strip()
if line:
new_split.append(line + "\n")
self.distribution_function = "".join(new_split)
app.logger.info("parsed distribution_function func")
app.logger.info(self.distribution_function)

def set_id(self, id):
self.id = id

Expand Down Expand Up @@ -114,9 +140,19 @@ def _set_queue(self):
else:
raise Exception("This type of queue is not implemented yet")

def generate_finish_time(self):
def generate_finish_time(self, patient):
if self.get_distribution_name() is None:
duration = 0
elif self.distribution_name == "define_your_own":
app.logger.info("d_type define your own")
app.logger.info(self.distribution_function)
duration = 0
l = locals()
# executes input code string
# need to pass in locals and globals to mutate _p_value
exec(self.distribution_function, globals(), l)
app.logger.info(l['duration'])
duration = l['duration']
else:
duration = Distributions.class_distributions[self.get_distribution_name()](
*self.get_distribution_parameters())
Expand Down Expand Up @@ -349,7 +385,7 @@ def insert_patient_to_resource_and_heap(self, patient, resource):
finish_time = patient.get_start_time()
duration = finish_time - GlobalTime.time
else:
finish_time, duration = self.generate_finish_time()
finish_time, duration = self.generate_finish_time(patient)
resource.insert_patient(patient, self.id, finish_time, duration)
# record event of patient joining resource
self.add_patient_join_resource_event(patient, resource)
Expand Down
4 changes: 2 additions & 2 deletions backend/app/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def run(self) -> None:
node_rules = rule_creator.create_rules(type="node", node_rules= node["nodeRules"], node_id=node["id"], canvas=canvas)

# create node
nodes_list[node["id"]] = Node(node["id"], node["queueType"], node["priorityFunction"], node["numberOfActors"],
nodes_list[node["id"]] = Node(node["id"], node["queueType"], node["priorityFunction"], node["numberOfActors"], node["distributionFunction"],
process_name=node["elementType"], distribution_name=node["distribution"],
distribution_parameters=node["distributionParameters"], output_process_ids=node["children"], rules=node_rules,
priority_type=node["priorityType"])
Expand All @@ -93,7 +93,7 @@ def run(self) -> None:

# create patient_loader node when reception is found
if node["elementType"] == "reception":
nodes_list[-1] = Node(-1, "queue", None, 1, process_name="patient_loader",
nodes_list[-1] = Node(-1, "queue", None, 1, None, process_name="patient_loader",
distribution_name="fixed", distribution_parameters=[0],
output_process_ids=[node["id"]], priority_type="")

Expand Down
6 changes: 3 additions & 3 deletions backend/test.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
patient_id,time,patient_acuity,patient_admitted,xray,pxray
1,2019-01-01 00:00:00.958845,1,TRUE,0,1
2,2019-01-01 00:00:00.958845,1,TRUE,0,1
3,2019-01-01 00:00:00.958845,1,TRUE,0,1
1,2019-01-01 00:00:00.958845,1,TRUE,1,0
2,2019-01-01 00:00:00.958845,1,TRUE,1,0
3,2019-01-01 00:00:00.958845,1,TRUE,1,1
3 changes: 2 additions & 1 deletion frontend/src/components/JSONEntrySidebarContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const nodeSchema = {
"elementType": { "type": "string"},
"distribution": {"type": "string"},
"distributionParameters": {"type": "array", "items": {"type": "integer"}},
"distributionFunction": { "type": "string"},
"numberOfActors": { "type": "integer"},
"queueType": { "type": "string"},
"priorityFunction": { "type": "string"},
Expand Down Expand Up @@ -104,7 +105,7 @@ export class JSONEntrySidebarContent extends Component {
validatedJSON[i].patients = []
validatedJSON[i].processing = []
}
const requiredKeys = ["id", "elementType", "distribution", "distributionParameters", "numberOfActors", "queueType", "priorityFunction", "children", "priorityType"];
const requiredKeys = ["id", "elementType", "distribution", "distributionParameters", "distributionFunction", "numberOfActors", "queueType", "priorityFunction", "children", "priorityType"];
// console.log(this.state.valid);

for (let i = 0; i < validatedJSON.length; i++) {
Expand Down
52 changes: 45 additions & 7 deletions frontend/src/components/NodeSidebarContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ export class NodeSidebarContent extends React.Component {
new_node.priorityType = ""
}

if(new_node.distribution !== "define_your_own"){
new_node.distributionFunction = ""
}

if(new_node.distribution === "define_your_own"){
new_node.distributionParameters = []
}

// Empty the text inside the "other" field
if (name === "elementType" && value === "other") {
this.setState({ tempText: "" });
Expand Down Expand Up @@ -280,16 +288,46 @@ export class NodeSidebarContent extends React.Component {
<option value="wald">Wald</option>
<option value="weibull">Weibull</option>
<option value="zipf">Zipf</option>
<option value="define_your_own">Define Your Own</option>
</select>
{this.state.node.distribution === 'define_your_own' &&
<div>
<label>Custom</label><br/><br/>
<div style={{color: 'green', marginLeft: '20px'}}>
"""<br/>
Set a custom duration for the patient at this node<br/><br/>
Attributes available:<br/>
patient.get_acuity() <br/> Returns a integer value of the patient's acuity<br/><br/>
patient.get_start_time() <br/> Returns the number of minutes it took for patient to enter the simulation
after the simulation started.<br/><br/>
patient.get_attribute(attribute) <br/> Returns the value of the attribute for the patient as indicated by the uploaded CSV
<br/><br/>
"""
</div>
<br/>
<div style={{marginLeft: '20px'}}>
duration = 0<br/>
<div style={{color: 'grey'}}> # Set duration to the amount of time you want the patient to take<br/>
# DO NOT RETURN ANYTHING IN THE CODE <br/></div>
</div>
<textarea
type="text"
name="distributionFunction"
style={{marginLeft: '20px', width: '80%', fontSize: '15px'}}
value={this.state.node.distributionFunction} onChange={this.handleInputChange}></textarea>
</div>
}
</div>

<div className="input-container"> {/* could indicate what parameters required */}
<label>Distribution Parameters</label><br/>
<input
type="text"
name="distributionParameters"
value={this.state.node.distributionParameters} onChange={this.handleInputChange}></input>
</div>
{this.state.node.distribution !== 'define_your_own' &&
<div className="input-container"> {/* could indicate what parameters required */}
<label>Distribution Parameters</label><br/>
<input
type="text"
name="distributionParameters"
value={this.state.node.distributionParameters} onChange={this.handleInputChange}></input>
</div>
}


<div className="input-container">
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/models/ProcessNode.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class ProcessNode {
constructor(id, elementType, distribution, distributionParameters,
constructor(id, elementType, distribution, distributionParameters, distributionFunction,
numberOfActors, queueType, priorityFunction, children = [],
patients = {}, priorityType, processing = {}, predictedChildren = [],
nodeRules = [], resourceRules = []) {
Expand All @@ -8,6 +8,7 @@ class ProcessNode {
this.elementType = elementType;
this.distribution = distribution;
this.distributionParameters = distributionParameters;
this.distributionFunction = distributionFunction;
this.numberOfActors = numberOfActors;
this.queueType = queueType;
this.priorityFunction = priorityFunction;
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/redux/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ const initialState = {
linkBeingBuilt: [], // the ID's of 2 nodes between which a link is being constructed.
nodeCount: 5, // max ID of any node
nodes: [
new ProcessNode(0, "reception", "fixed", [5], 1,
new ProcessNode(0, "reception", "fixed", [5], "", 1,
"priority queue", "", [1], [], "acuity", [], []),
new ProcessNode(1, "triage", "fixed", [3], 2,
new ProcessNode(1, "triage", "fixed", [3], "", 2,
"priority queue", "", [2, 3], [], "acuity", [], []),
new ProcessNode(2, "doctor", "fixed", [10], 3,
new ProcessNode(2, "doctor", "fixed", [10], "", 3,
"priority queue", "", [3], [], "acuity", [], []),
new ProcessNode(3, "x-ray", "binomial", [1, 1], 2,
new ProcessNode(3, "x-ray", "binomial", [1, 1], "", 2,
"priority queue", "", [], [], "acuity", [], [])
],
// Intial state of the acuity colors
Expand Down