From fe4da5ac5fe56ccf4c07e95e3260e6682fbcf46d Mon Sep 17 00:00:00 2001 From: rnarducci Date: Tue, 30 Nov 2021 15:41:39 -0600 Subject: [PATCH 01/42] Thesis Work Nailing down specifics of implementation, setting up entry and arrays and starting from assigning patients to the triage nurse. --- .../assign-patient-to-triage-nurse-thesis.js | 72 +++++++ .../assign-patient-to-triage-nurse.js | 22 -- src/people/thesis/greeter-nurse-thesis.js | 198 ++++++++---------- src/people/thesis/notes.md | 18 +- src/people/thesis/patient-thesis.js | 101 +++------ src/people/thesis/task-thesis.js | 14 ++ src/support/hospital.js | 3 +- 7 files changed, 207 insertions(+), 221 deletions(-) create mode 100644 src/behavior/assign-patient-to-triage-nurse-thesis.js create mode 100644 src/people/thesis/task-thesis.js diff --git a/src/behavior/assign-patient-to-triage-nurse-thesis.js b/src/behavior/assign-patient-to-triage-nurse-thesis.js new file mode 100644 index 0000000..45efc3e --- /dev/null +++ b/src/behavior/assign-patient-to-triage-nurse-thesis.js @@ -0,0 +1,72 @@ +import PatientTempState from "../support/patient-temp-state.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree"; +import FollowInstructions from "./follow-instructions.js"; + + +class AssignPatientToTriageNurseThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + + let self = this; + let me= ()=>Hospital.agents.find(a=>a.id == myIndex);; + + this.tree = builder + .sequence("Assign Patient To Triage Nurse") + .do("Assign Patient", (t) => { + // let agent = Hospital.agents.find(a => a.id == self.index); + // let simulationAgent = t.crowd.find(a => a.id == self.index); + // let myLocation = new Vector3(simulationAgent.location.x, simulationAgent.location.y, simulationAgent.location.z); + + // let closestTriageNurses = Hospital.agents.filter(a=>a.medicalStaffType == "Nurse" && a.medicalStaffSubclass == "Triage Nurse" && a.getCurrentPatient() == null && a.inSimulation == true); + + + // // DISTANCETO NOT WORKING NOW FOR SOME REASON??? + // //let closestTriageNursesSorted = closestTriageNurses.sort((a,b)=>Vector3.subtract(a.location, myLocation).length() - Vector3.subtract(b.location, myLocation).length()); + // let closestTriageNursesSorted = closestTriageNurses.sort((a,b)=>Vector3.subtract(a.location, myLocation).lengthSquared() - Vector3.subtract(b.location, myLocation).lengthSquared()); + + // //let closestTriageNursesSorted = closestTriageNurses.sort((a,b)=>a.location.distanceTo(myLocation) - b.location.distanceTo(myLocation)); + // let closestTriageNurse = closestTriageNursesSorted[0]; + + // if(closestTriageNurse == null) { + // return fluentBehaviorTree.BehaviorTreeStatus.Failure; + // } + + // //let myPatient = me().getCurrentPatient(); + // let myPatient = me().triageList[0]; + + // // This should work for multiple triage nurses as long as inactive triage nurses wait at TriageNursePlace + // if (closestTriageNurse.getBusy() || myPatient.getPermanentRoom() == null || myPatient.getInstructor() != me()) + // { + // return fluentBehaviorTree.BehaviorTreeStatus.Failure; + // } + // else + // { + // closestTriageNurse.setCurrentPatient(myPatient); + // myPatient.setInstructor(closestTriageNurse); + // myPatient.setPatientTempState(PatientTempState.FOLLOWING); + // me().setCurrentPatient(null); + + // if (me().triageList[me().triageList.length - 1] == myPatient) { + // me().triageList.pop(); + // } + // else if (me().triageList[0] == myPatient) { + // me().triageList.shift(); + // } + // //hospital.addComment(me, myPatient, "Follow that nurse."); + + // return fluentBehaviorTree.BehaviorTreeStatus.Success; + // } + + + }) + .end() + .build(); + } + + +} + +export default AssignPatientToTriageNurseThesis; \ No newline at end of file diff --git a/src/behavior/assign-patient-to-triage-nurse.js b/src/behavior/assign-patient-to-triage-nurse.js index ad0b14e..37b182b 100644 --- a/src/behavior/assign-patient-to-triage-nurse.js +++ b/src/behavior/assign-patient-to-triage-nurse.js @@ -20,19 +20,6 @@ class AssignPatientToTriageNurse { let simulationAgent = t.crowd.find(a => a.id == self.index); let myLocation = new Vector3(simulationAgent.location.x, simulationAgent.location.y, simulationAgent.location.z); - /* - List people = hospital.activePeople; - IMedicalStaff closestTriageNurse = (IMedicalStaff) people.stream() - .filter(i->i instanceof IMedicalStaff - && ((IMedicalStaff)i).getMedicalStaffType() == MedicalStaffClass.NURSE - && ((IMedicalStaff)i).getDoctorType() == MedicalStaffSubclass.TRIAGE_NURSE - &&((IMedicalStaff)i).getCurrentPatient() == null) - .sorted((a,b)->(int)(a.getLocation().distanceTo(myLocation) - b.getLocation().distanceTo(myLocation))) - .findFirst() - .orElse(null); - if(closestTriageNurse == null || closestTriageNurse.getLocation().distanceTo(myLocation) > 3) - return Status.RUNNING; //No triage nurse is available or close enough - */ let closestTriageNurses = Hospital.agents.filter(a=>a.medicalStaffType == "Nurse" && a.medicalStaffSubclass == "Triage Nurse" && a.getCurrentPatient() == null && a.inSimulation == true); @@ -53,11 +40,6 @@ class AssignPatientToTriageNurse { // This should work for multiple triage nurses as long as inactive triage nurses wait at TriageNursePlace if (closestTriageNurse.getBusy() || myPatient.getPermanentRoom() == null || myPatient.getInstructor() != me()) { - - // TELL THE PATIENT TO GO TO THE WAITING ROOM - //Hospital.patientToDoList.push(new GoToLazy(myPatient.id, () => Hospital.locations.find(l=> l.name == "Waiting Room").location).tree); - Hospital.patientToDoList.push(0); - return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else @@ -75,10 +57,6 @@ class AssignPatientToTriageNurse { } //hospital.addComment(me, myPatient, "Follow that nurse."); - // TELL THE PATIENT TO FOLLOW INSTRUCTIONS - //Hospital.patientToDoList.push(new FollowInstructions(myPatient.id).tree); - Hospital.patientToDoList.push(1); - return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) diff --git a/src/people/thesis/greeter-nurse-thesis.js b/src/people/thesis/greeter-nurse-thesis.js index 1fb7100..e9eef61 100644 --- a/src/people/thesis/greeter-nurse-thesis.js +++ b/src/people/thesis/greeter-nurse-thesis.js @@ -1,4 +1,4 @@ -import AssignPatientToTriageNurse from "../../behavior/assign-patient-to-triage-nurse.js"; +import AssignPatientToTriageNurseThesis from "../../behavior/assign-patient-to-triage-nurse-thesis.js"; import ComputerAssignPatientRoom from "../../behavior/computer-assign-patient-room.js" import ComputerEnterPatient from "../../behavior/computer-enter-patient.js"; import ComputerScorePatient from "../../behavior/computer-score-patient.js"; @@ -11,123 +11,89 @@ import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" class greeterNurseThesis { - constructor(myIndex) { - this.index = myIndex; - - const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); - - let self = this;//Since we need to reference this in anonymous functions, we need a reference - let me= ()=>Hospital.agents.find(a=>a.id == myIndex); - let myGoal = Hospital.locations.find(l => l.name == "Check In"); - if (!myGoal) throw new Exception("We couldn't find a location called Check In"); - - //this.goTo = new GoTo(self.index, myGoal.location); - let numRequiredToFail = 1; - let numRequiredToSucceed = 2; - - this.tree = builder - .sequence("Greeter Nurse Behaviors") - // - // IMPLEMENT A NEW SHIFT CHANGE BEHAVIOR? - // - .splice(new GoTo(self.index, myGoal.location).tree) - // Once the greeter nurse has arrived, run in parallel - .parallel("look and book", numRequiredToFail, numRequiredToSucceed) - .sequence("Check in Patients") - .splice(new LookForArrivingPatient(myIndex).tree) - .splice(new TakeTime(30, 90).tree) - .splice(new ComputerEnterPatient(myIndex).tree) - .splice(new TakeTime(30, 90).tree) - .splice(new ComputerScorePatient(myIndex).tree) - .splice(new TakeTime(30, 90).tree) - .splice(new ComputerAssignPatientRoom(myIndex).tree) - .end() - .splice(new AssignPatientToTriageNurse(myIndex).tree) - .end() - - // --------------------------------------------------------------------- - // .selector("Check for arrival") - // .condition("Clock in", async (t) => me().onTheClock) - // .do("SHIFT CHANGE", (t) => { - // // SHIFT CHANGE - // if (me().onTheClock == false) { - // me().onTheClock = true; - // Hospital.activeGreeter.push(me()); - // if (Hospital.activeGreeter[0] != me() && Hospital.activeGreeter.length > 1) { - // for (let i = 0; i < Hospital.activeGreeter.length; i++) { - // if (!Hospital.activeGreeter[i].replacement) { - // Hospital.activeGreeter[i].replacement = true; - // //Hospital.activeGreeter.shift(); - // Hospital.activeGreeter.splice(i, 1); - // break; - // } - // } - // } - // } - - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // }) - // .end() - - // // SHIFT CHANGE SEQUENCE OF BEHAVIORS - // .selector("Check for Replacement") - // .condition("Replacement is Here", async (t) => !me().replacement) - // .sequence("Exit Procedure") - // .splice(new GoTo(self.index, Hospital.locations.find(l => l.name == "Main Entrance").location).tree) - // .do("Leave Simulation", (t) => { - // me().inSimulation = false; - // return fluentBehaviorTree.BehaviorTreeStatus.Running; - // }) - // .end() - // .end() - - // .splice(new GoTo(self.index, myGoal.location).tree) - - // // waits for patient to be nearby, and be in ARRIVED state - // // .splice(new LookForArrivingPatient(myIndex).tree) - - // // .splice(new TakeTime(30, 90).tree) // seconds: uniform, 30, 90 - - // // .splice(new ComputerEnterPatient(myIndex).tree) - - // // .splice(new TakeTime(30, 60).tree) // seconds: uniform, 30, 60 - - // // .splice(new ComputerScorePatient(myIndex).tree) - - // // .splice(new TakeTime(30, 60).tree) // seconds: uniform, 30, 60 - - // // .splice(new ComputerAssignPatientRoom(myIndex).tree) - - // //.untilFail("Assign Patient to Triage Nurse successfully") - // //.inverter("invert result") - // //.splice(new AssignPatientToTriageNurse(myIndex).tree) - // //.end() - // //.end() - - // // Once the greeter nurse has arrived, run in parallel - // .parallel("look and book", numRequiredToFail, numRequiredToSucceed) - // .sequence("Check in Patients") - // .splice(new LookForArrivingPatient(myIndex).tree) - // .splice(new TakeTime(30, 90).tree) - // .splice(new ComputerEnterPatient(myIndex).tree) - // .splice(new TakeTime(30, 90).tree) - // .splice(new ComputerScorePatient(myIndex).tree) - // .splice(new TakeTime(30, 90).tree) - // .splice(new ComputerAssignPatientRoom(myIndex).tree) - // .end() - // .splice(new AssignPatientToTriageNurse(myIndex).tree) - // .end() - + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + let myGoal = Hospital.locations.find(l => l.name == "Check In"); + if (!myGoal) throw new Exception("We couldn't find a location called Check In"); + + //this.goTo = new GoTo(self.index, myGoal.location); + let numRequiredToFail = 1; + let numRequiredToSucceed = 2; + + this.tree = builder + .sequence("Greeter Nurse Behaviors") + // ----------------------------------------------- + // + // POTENTIALLY CHANGE CLOCK IN AND OUT BEHAVIORS + // + // ----------------------------------------------- + .selector("Check for arrival") + .condition("Clock in", async (t) => me().onTheClock) + .do("SHIFT CHANGE", (t) => { + // SHIFT CHANGE + if (me().onTheClock == false) { + me().onTheClock = true; + Hospital.activeGreeter.push(me()); + if (Hospital.activeGreeter[0] != me() && Hospital.activeGreeter.length > 1) { + for (let i = 0; i < Hospital.activeGreeter.length; i++) { + if (!Hospital.activeGreeter[i].replacement) { + Hospital.activeGreeter[i].replacement = true; + //Hospital.activeGreeter.shift(); + Hospital.activeGreeter.splice(i, 1); + break; + } + } + } + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + // SHIFT CHANGE SEQUENCE OF BEHAVIORS + .selector("Check for Replacement") + .condition("Replacement is Here", async (t) => !me().replacement) + .sequence("Exit Procedure") + .splice(new GoTo(self.index, Hospital.locations.find(l => l.name == "Main Entrance").location).tree) + .do("Leave Simulation", (t) => { + me().inSimulation = false; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + }) .end() - .build(); - } - - async update( crowd, msec) { - //this.toReturn = null;//Set the default return value to null (don't change destination) - await this.tree.tick({ crowd, msec }) //Call the behavior tree - //return this.toReturn; //Return what the behavior tree set the return value to - } + .end() + // ----------------------------------------------- + + // GO TO DESK + .splice(new GoTo(self.index, myGoal.location).tree) + + // Once the greeter nurse has arrived, run in parallel + .parallel("look and book", numRequiredToFail, numRequiredToSucceed) + .sequence("Check in Patients") + .splice(new LookForArrivingPatient(myIndex).tree) + .splice(new TakeTime(30, 90).tree) + .splice(new ComputerEnterPatient(myIndex).tree) + .splice(new TakeTime(30, 90).tree) + .splice(new ComputerScorePatient(myIndex).tree) + .splice(new TakeTime(30, 90).tree) + .splice(new ComputerAssignPatientRoom(myIndex).tree) + .end() + .splice(new AssignPatientToTriageNurseThesis(myIndex).tree) + .end() + + .end() + .build(); + } + async update( crowd, msec) { + //this.toReturn = null;//Set the default return value to null (don't change destination) + await this.tree.tick({ crowd, msec }) //Call the behavior tree + //return this.toReturn; //Return what the behavior tree set the return value to } + +} export default greeterNurseThesis; \ No newline at end of file diff --git a/src/people/thesis/notes.md b/src/people/thesis/notes.md index 4749c1a..bd9bd45 100644 --- a/src/people/thesis/notes.md +++ b/src/people/thesis/notes.md @@ -1,10 +1,10 @@ # Thesis Overhaul Notes The basis of these code changes boil down to this: -- The agents should have an initial behavior (or two), probably dictating that they go -to their assigned place and wait for an event. This needs to be retained as the device -to give them new behaviors comes from each agent they interact with not an overseer. -- The patient goes to the front desk, and should be given a new behavior, to go to the waiting room or to follow the triage nurse. -- The greeter nurse's behaviors will likely remain somewhat unchanged. The greeter's behaviors are always constant and aside from shift changes, I think the greeter nurse will be a lynchpin in the system. The greeter will dole out the first few behaviors to the patient and the triage nurse. +- The roaming and spontaneous agents will probably receive the bulk of these changes. The agents with set behaviors that don't move probably will recieve minimal changes (greeter, xray, ct). The patient will likely receive little to no changes. +- Every other agent will likely have a queue of actions they pull from from the hospital computer. It might be worth also limiting the agents to a couple rooms, like Dr. Zeger suggested and also having "rover nurses". +- Basically implement a priority queue + behavior queue from the computer +- Will need to pass the information of what behavior they should perform and its details. The behaviors themselves will need to be already instantiated so they work. +- To do this, will probably just need a lot of behaviors that check if it is in the queue, and if it is not then go to the next behavior. # What I've Learned About Our Codebase - There cannot be an operation in .splice(HERE). It can accept a variable or an array value, but you cannot pull a value from an array in another file (like Hospital.sampleArray[number]) or even get a value from an operation and plug it into an existing array. This means to send behaviors back and forth, you must initialize it into the file, and then use that variable. @@ -12,9 +12,7 @@ to give them new behaviors comes from each agent they interact with not an overs - even getting the number and doing like testArray[tempValue] doesn't work. It must just be a number. # Questions -- How should I instantiate the behaviors? - 1. At the top of the agent's behavior tree file - 2. At the moment it is being passed from one agent to another (e.g. the greeter nurse instantiates a GoToLazy behavior then passes it to the patient) - 3. Instantiate all possible behaviors and put them in hospital.js, and reference the behavior in the behaviors list that needs to be pushed into the agent to do list from there - 4. Use responsibilities? +- Should probably have some sort of format/object for what goes in the ToDo arrays: +{taskname/ID/#, importance/severity, timestep it was entered?, potential patient it concerns, potential location?} +- the arrays should probably be sorted every so often (by importance and time)? diff --git a/src/people/thesis/patient-thesis.js b/src/people/thesis/patient-thesis.js index bd11fa8..b145a76 100644 --- a/src/people/thesis/patient-thesis.js +++ b/src/people/thesis/patient-thesis.js @@ -3,8 +3,7 @@ import GoToLazy from "../../behavior/go-to-lazy.js"; // import LOG import Stop from "../../behavior/stop.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" - - +import PatientTempState from "../support/patient-temp-state.js"; class patientThesis { @@ -24,79 +23,39 @@ class patientThesis { if (!myGoal) throw new exception("We couldn't find a location called " + goToName); let wait = Hospital.locations.find(l=> l.name == "Waiting Room"); - - //let test = "new GoToLazy(" + myIndex + ", () => " + myGoal.location + ")"; - HALF WORKS - //let test = "new GoToLazy(myIndex, () => myGoal.location)"; - HALF WORKS - //let test = new GoToLazy(myIndex, () => myGoal.location).tree; - WORKS - let testArray = []; - let test = new GoToLazy(myIndex, () => Hospital.locations.find(l=> l.name == "Waiting Room").location).tree; - testArray.push(test); - let test1 = new FollowInstructions(myIndex).tree; - testArray.push(test1); - let tempvalue = 5; - let currentBehavior; this.tree = builder - .sequence("Patient Actions") - - // STARTING BEHAVIORS - .splice(new GoToLazy(myIndex, () => myGoal.location).tree) - - .splice(new Stop(myIndex).tree) - - // PROBABLY MAKE THIS BEHAVIOR INTO ITS OWN FILE - // in the patient's case, they need to stay in this block indefinitely - // otherwise they'll head back to the check in area - .parallel("Stay in this block", 2, 2) - .selector("Check for tasks (jumps out at first success)") - .condition("has tasks", async (t) => Hospital.patientToDoList.length == 0) - .do("Test", async function (t) { - // console.log(Hospital.patientToDoList.shift()); - // console.log(testArray[1]); - //console.log(testArray[Hospital.patientToDoList.shift()]); - //tempvalue = Hospital.patientToDoList.shift(); - //console.log(tempvalue); - //currentBehavior = testArray[Hospital.patientToDoList.shift()]; - currentBehavior = test1; - console.log(currentBehavior); - return fluentBehaviorTree.BehaviorTreeStatus.Failure; - }) - //.splice(Hospital.patientToDoList.shift()) - //.splice(new FollowInstructions(myIndex).tree) - //.splice(testArray[Hospital.patientToDoList.shift()]) - .splice(currentBehavior) - .end() - .do("Stay Here", async function (t) { - return fluentBehaviorTree.BehaviorTreeStatus.Running; + // PATIENT BEHAVIOR TREE + .sequence("Patient Tree") + // NEW TREE SETUP. FIND DOABLE ACTION THEN START OVER WHEN IT IS DONE. + .selector("Patient Actions") + .sequence("Check In") + .condition("Just Arrived", async (t) => me().getPatientTempState() == PatientTempState.ARRIVED) + // GO TO CHECK IN COUNTER + .splice(new GoToLazy(myIndex, () => myGoal.location).tree) + // STAY STILL WHILE BEING CHECKED IN + .splice(new Stop(myIndex).tree) + // Make patient go to the Waiting Room after being checked in + .do("Waiting Room", async function (t) { + if (goToName == "Ambulance Entrance") { + wait = myGoal; + } + else if(me().getPermanentRoom() == null) { + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } + else if (me().getInstructor().MedicalStaffSubclass == "Greeter Nurse") { + wait = Hospital.locations.find(l=> l.name == "Waiting Room"); + } + else { + wait = myGoal; + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; }) + // GO TO WAITING ROOM OR STAY WHERE YOU ARE + .splice(new GoToLazy(myIndex, () => wait.location).tree) .end() - - // --------------------------------------------------------------------- - // // Make patient go to the Waiting Room after being checked in - // .do("Waiting Room", async function (t) { - // if (goToName == "Ambulance Entrance") { - // wait = myGoal; - // } - // else if(me().getPermanentRoom() == null) { - // return fluentBehaviorTree.BehaviorTreeStatus.Running; - // } - // else if (me().getInstructor().MedicalStaffSubclass == "Greeter Nurse") { - // wait = Hospital.locations.find(l=> l.name == "Waiting Room"); - // } - // else { - // wait = myGoal; - // } - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // }) - - // .splice(new GoToLazy(myIndex, () => wait.location).tree) - - // .splice(new FollowInstructions(myIndex).tree) - // .do("Done following instructions", async function (t) { - // console.log("Done following instructions") - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // }) - + // PHYSICALLY FOLLOW NURSES AND STAY IN HOSPITAL ROOM + .splice(new FollowInstructions(myIndex).tree) .end() .build(); } diff --git a/src/people/thesis/task-thesis.js b/src/people/thesis/task-thesis.js new file mode 100644 index 0000000..becdfad --- /dev/null +++ b/src/people/thesis/task-thesis.js @@ -0,0 +1,14 @@ +class task { + taskID; + severity; + entryTime; + waitingTime; + patient; + location; + + constructor() { + + } +} + +export default task; \ No newline at end of file diff --git a/src/support/hospital.js b/src/support/hospital.js index 2bc696a..a9222fd 100644 --- a/src/support/hospital.js +++ b/src/support/hospital.js @@ -40,8 +40,7 @@ class Hospital{ static CT2Agents = 0; // USING THIS FOR AGENT BEHAVIORS - static patientToDoList = []; - static triageToDoList = []; + static triageTaskList = []; static getFPS(){return 60;} From 42e0558a80e672529d7042955b6f14fb9b9547ee Mon Sep 17 00:00:00 2001 From: Narducky Date: Thu, 9 Dec 2021 14:34:50 -0600 Subject: [PATCH 02/42] Adding Tasks to Triage/Greeter/Patient Working on adding tasks/task queue. Figuring out how to make changes flexible to change back for testing. Working on janitor next. Might need to take higher level consideration or diagram of how this priority queueing will look. --- src/people/thesis/notes.md => notes.md | 0 .../assign-patient-to-triage-nurse-thesis.js | 59 ++----- src/behavior/follow-instructions.js | 4 + src/index.js | 6 +- .../{thesis => }/greeter-nurse-thesis.js | 14 +- src/people/janitorial-thesis.js | 104 +++++++++++++ src/people/medical-agent-thesis.js | 146 ++++++++++++++++++ src/people/medical-agent.js | 4 - src/people/patient-agent-thesis.js | 78 ++++++++++ src/people/patient-agent.js | 2 - src/people/{thesis => }/patient-thesis.js | 6 +- src/people/thesis/task-thesis.js | 14 -- .../{thesis => }/triage-nurse-thesis.js | 32 ++-- src/support/hospital.js | 1 + src/support/task-thesis.js | 20 +++ 15 files changed, 397 insertions(+), 93 deletions(-) rename src/people/thesis/notes.md => notes.md (100%) rename src/people/{thesis => }/greeter-nurse-thesis.js (86%) create mode 100644 src/people/janitorial-thesis.js create mode 100644 src/people/medical-agent-thesis.js create mode 100644 src/people/patient-agent-thesis.js rename src/people/{thesis => }/patient-thesis.js (94%) delete mode 100644 src/people/thesis/task-thesis.js rename src/people/{thesis => }/triage-nurse-thesis.js (83%) create mode 100644 src/support/task-thesis.js diff --git a/src/people/thesis/notes.md b/notes.md similarity index 100% rename from src/people/thesis/notes.md rename to notes.md diff --git a/src/behavior/assign-patient-to-triage-nurse-thesis.js b/src/behavior/assign-patient-to-triage-nurse-thesis.js index 45efc3e..8dd8929 100644 --- a/src/behavior/assign-patient-to-triage-nurse-thesis.js +++ b/src/behavior/assign-patient-to-triage-nurse-thesis.js @@ -1,6 +1,7 @@ import PatientTempState from "../support/patient-temp-state.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree"; import FollowInstructions from "./follow-instructions.js"; +import task from "../support/task-thesis.js"; class AssignPatientToTriageNurseThesis { @@ -11,56 +12,22 @@ class AssignPatientToTriageNurseThesis { const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); let self = this; - let me= ()=>Hospital.agents.find(a=>a.id == myIndex);; + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); this.tree = builder .sequence("Assign Patient To Triage Nurse") .do("Assign Patient", (t) => { - // let agent = Hospital.agents.find(a => a.id == self.index); - // let simulationAgent = t.crowd.find(a => a.id == self.index); - // let myLocation = new Vector3(simulationAgent.location.x, simulationAgent.location.y, simulationAgent.location.z); - - // let closestTriageNurses = Hospital.agents.filter(a=>a.medicalStaffType == "Nurse" && a.medicalStaffSubclass == "Triage Nurse" && a.getCurrentPatient() == null && a.inSimulation == true); - - - // // DISTANCETO NOT WORKING NOW FOR SOME REASON??? - // //let closestTriageNursesSorted = closestTriageNurses.sort((a,b)=>Vector3.subtract(a.location, myLocation).length() - Vector3.subtract(b.location, myLocation).length()); - // let closestTriageNursesSorted = closestTriageNurses.sort((a,b)=>Vector3.subtract(a.location, myLocation).lengthSquared() - Vector3.subtract(b.location, myLocation).lengthSquared()); - - // //let closestTriageNursesSorted = closestTriageNurses.sort((a,b)=>a.location.distanceTo(myLocation) - b.location.distanceTo(myLocation)); - // let closestTriageNurse = closestTriageNursesSorted[0]; - - // if(closestTriageNurse == null) { - // return fluentBehaviorTree.BehaviorTreeStatus.Failure; - // } - - // //let myPatient = me().getCurrentPatient(); - // let myPatient = me().triageList[0]; - - // // This should work for multiple triage nurses as long as inactive triage nurses wait at TriageNursePlace - // if (closestTriageNurse.getBusy() || myPatient.getPermanentRoom() == null || myPatient.getInstructor() != me()) - // { - // return fluentBehaviorTree.BehaviorTreeStatus.Failure; - // } - // else - // { - // closestTriageNurse.setCurrentPatient(myPatient); - // myPatient.setInstructor(closestTriageNurse); - // myPatient.setPatientTempState(PatientTempState.FOLLOWING); - // me().setCurrentPatient(null); - - // if (me().triageList[me().triageList.length - 1] == myPatient) { - // me().triageList.pop(); - // } - // else if (me().triageList[0] == myPatient) { - // me().triageList.shift(); - // } - // //hospital.addComment(me, myPatient, "Follow that nurse."); - - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // } - - + if (me().triageList.length == 0) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let myPatient = me().triageList.shift(); + // Task ID / Severity / Entry Time / Patient / Location + let triageTask = new task("Triage", myPatient.getSeverity(), null, myPatient, myPatient.getAssignedRoom()); + Hospital.triageTaskList.push(triageTask); + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } }) .end() .build(); diff --git a/src/behavior/follow-instructions.js b/src/behavior/follow-instructions.js index b6f545d..e641125 100644 --- a/src/behavior/follow-instructions.js +++ b/src/behavior/follow-instructions.js @@ -1,6 +1,7 @@ import PatientTempState from "../support/patient-temp-state.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree"; import LocationStatus from "../support/location-status.js"; +import task from "../support/task-thesis.js"; class FollowInstructions { @@ -101,6 +102,9 @@ class FollowInstructions { } // SET ROOM AS READY TO CLEAN me().getPermanentRoom().setLocationStatus(LocationStatus.SANITIZE); + let sanitizeTask = new task("Sanitize", null, null, null, me().getPermanentRoom()); + Hospital.janitorTaskList.push(sanitizeTask); + } else if(state == PatientTempState.ARRIVED) { agentConstant.destination = myGoal.location; diff --git a/src/index.js b/src/index.js index da70eca..3ca765d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,8 @@ import CrowdSetup from "@crowdedjs/crowd-setup" -import MedicalAgent from "./people/medical-agent.js" -import PatientAgent from "./people/patient-agent.js" +//import MedicalAgent from "./people/medical-agent.js" +import MedicalAgentThesis from "./people/medical-agent-thesis.js" +//import PatientAgent from "./people/patient-agent.js" +import PatientAgentThesis from "./people/patient-agent-thesis.js" import urlParser from "./url-parser.js" import colorFunction from "./color-function.js" import simulations from "./simulations.js" diff --git a/src/people/thesis/greeter-nurse-thesis.js b/src/people/greeter-nurse-thesis.js similarity index 86% rename from src/people/thesis/greeter-nurse-thesis.js rename to src/people/greeter-nurse-thesis.js index e9eef61..69a0c2c 100644 --- a/src/people/thesis/greeter-nurse-thesis.js +++ b/src/people/greeter-nurse-thesis.js @@ -1,10 +1,10 @@ -import AssignPatientToTriageNurseThesis from "../../behavior/assign-patient-to-triage-nurse-thesis.js"; -import ComputerAssignPatientRoom from "../../behavior/computer-assign-patient-room.js" -import ComputerEnterPatient from "../../behavior/computer-enter-patient.js"; -import ComputerScorePatient from "../../behavior/computer-score-patient.js"; -import GoTo from "../../behavior/go-to.js" -import LookForArrivingPatient from "../../behavior/look-for-arriving-patient.js"; -import TakeTime from "../../behavior/take-time.js"; +import AssignPatientToTriageNurseThesis from "../behavior/assign-patient-to-triage-nurse-thesis.js"; +import ComputerAssignPatientRoom from "../behavior/computer-assign-patient-room.js" +import ComputerEnterPatient from "../behavior/computer-enter-patient.js"; +import ComputerScorePatient from "../behavior/computer-score-patient.js"; +import GoTo from "../behavior/go-to.js" +import LookForArrivingPatient from "../behavior/look-for-arriving-patient.js"; +import TakeTime from "../behavior/take-time.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" diff --git a/src/people/janitorial-thesis.js b/src/people/janitorial-thesis.js new file mode 100644 index 0000000..ab6ab31 --- /dev/null +++ b/src/people/janitorial-thesis.js @@ -0,0 +1,104 @@ +import GoTo from "../behavior/go-to.js" +import GoToLazy from "../behavior/go-to-lazy.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" +import LocationStatus from "../support/location-status.js"; +import TakeTime from "../behavior/take-time.js"; + +class janitorialThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + this.toReturn = null; + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let goToName = "Fast Track 1"; + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + + let myGoal = Hospital.locations.find(l => l.name == goToName); + if (!myGoal) throw new exception("We couldn't find a location called " + goToName); + + this.tree = builder + .sequence("Janitorial") + + .selector("Check for arrival") + .condition("Clock in", async (t) => me().onTheClock) + .do("SHIFT CHANGE", (t) => { + // SHIFT CHANGE + if (me().onTheClock == false) { + me().onTheClock = true; + Hospital.activeJanitor.push(me()); + if (Hospital.activeJanitor[0] != me() && Hospital.activeJanitor.length > 1) { + for (let i = 0; i < Hospital.activeJanitor.length; i++) { + if (!Hospital.activeJanitor[i].replacement) { + Hospital.activeJanitor[i].replacement = true; + //Hospital.activeJanitor.shift(); + Hospital.activeJanitor.splice(i, 1); + break; + } + } + } + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + + // SHIFT CHANGE SEQUENCE OF BEHAVIORS + .selector("Check for Replacement") + .condition("Replacement is Here", async (t) => !me().replacement) + .sequence("Exit Procedure") + .splice(new GoTo(self.index, Hospital.locations.find(l => l.name == "Main Entrance").location).tree) + .do("Leave Simulation", (t) => { + me().inSimulation = false; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + }) + .end() + .end() + + .splice(new GoTo(self.index, myGoal.location).tree) + + //find room to clean + .do("Find Room to Clean", (t) => { + // if (typeof Hospital.locations.find(l => l.locationStatus == LocationStatus.SANITIZE) === 'undefined') { + // return fluentBehaviorTree.BehaviorTreeStatus.Failure; + // } + // else { + // return fluentBehaviorTree.BehaviorTreeStatus.Success; + // } + + if (Hospital.janitorTaskList.length == 0) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + + }) + + // GO TO THE ROOM THAT NEEDS CLEANING + .splice(new GoToLazy(self.index, () => Hospital.locations.find(l => l.locationStatus == LocationStatus.SANITIZE).location).tree) + + // TAKE TIME IN THE ROOM TO CLEAN + .splice(new TakeTime(300, 600).tree) + + // set that room's status as NONE + .do("Done with the Room", (t) => { + Hospital.locations.find(l => l.locationStatus == LocationStatus.SANITIZE).setLocationStatus(LocationStatus.NONE); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + + .end() + .build(); + } + + async update( crowd, msec) { + //this.toReturn = null;//Set the default return value to null (don't change destination) + await this.tree.tick({ crowd, msec }) //Call the behavior tree + //return this.toReturn; //Return what the behavior tree set the return value to + } + +} + +export default janitorialThesis; diff --git a/src/people/medical-agent-thesis.js b/src/people/medical-agent-thesis.js new file mode 100644 index 0000000..3ea11aa --- /dev/null +++ b/src/people/medical-agent-thesis.js @@ -0,0 +1,146 @@ + +import BackAndForth from "../behavior/back-and-forth.js"; +import None from "../behavior/none.js" +import Agent from "./agent.js" +import AMedicalStaff from "./amedical-staff.js"; + +import attending from "./attending.js" +import ct from "./ct.js" +import EscapePerson from "./escape-person.js"; +import greeterNurse from "./greeter-nurse.js" +import janitorial from "./janitorial.js" +import nurse from "./nurse.js" +import pharmacist from "./pharmacist.js" +import phlebotomist from "./phlebotomist.js" +import radiology from "./radiology.js" +import resident from "./resident.js" +import tech from "./tech.js" +import triageNurse from "./triage-nurse.js" +import xray from "./xray.js" + +import greeterNurseThesis from "./greeter-nurse-thesis.js"; +import triageNurseThesis from "./triage-nurse-thesis.js"; +import janitorialThesis from "./janitorial-thesis.js"; + + +class MedicalAgentThesis extends AMedicalStaff { + startX; + startY; + startZ; + destX; + destY; + destZ; + startMSec; + inSimulation = false; + hasEntered = false; + behavior; + // SHIFT CHANGE + replacement = false; + onTheClock = false; + + static index = 0; + idx; //Corresponds to the internal idx number used by recast + + constructor(agent) { + super(agent.location, agent.id, agent.name, agent.type, agent.doctorYear); + + this.name = agent.name; + this.startMSec = agent.arrivalTick * 25; // We simulate 25 fps + this.arrivalLocation = agent.arrivalLocation; + this.age = agent.age; + this.severity = agent.severity; + this.patientName = agent.patientName; + this.gender = agent.gender; + this.id = agent.id; + this.patientTempState = undefined; + + let startLocation = Hospital.locations.find(i => i.name == agent.arrivalLocation); + if (!startLocation) console.error("Bad starting location " + agent.arrivalLocation); + + + this.startX = startLocation.location.x + this.startY = startLocation.location.y; + this.startZ = startLocation.location.z; + + this.destX = 0; + this.destY = 0; + this.destZ = 0; + + + + + if (agent.name == "Tech") { + if (agent.type == "Tech") + this.behavior = new tech(agent.id) + else if (agent.type == "CT") + this.behavior = new ct(agent.id) + else if (agent.type == "Janitorial") + //this.behavior = new janitorial(agent.id) + this.behavior = new janitorialThesis(agent.id) + else if (agent.type == "Phlebotomist") + this.behavior = new phlebotomist(agent.id) + else if (agent.type == "Radiology") + this.behavior = new radiology(agent.id) + else if (agent.type == "XRay") + this.behavior = new xray(agent.id) + else + throw new Exception("That tech type does not exist " + agent.type); + } + else if (agent.name == "Nurse") { + + if (agent.type == "Triage Nurse") + //this.behavior = new triageNurse(agent.id) + this.behavior = new triageNurseThesis(agent.id) + else if (agent.type == "Nurse") + this.behavior = new nurse(agent.id) + else if (agent.type == "Greeter Nurse") + //this.behavior = new greeterNurse(agent.id) + this.behavior = new greeterNurseThesis(agent.id) + else + throw new Exception("That nurse type does not exist " + agent.type); + } + else if (agent.name == "Attending") { + if (agent.type == "Attending") + this.behavior = new attending(agent.id) + else + throw new "That attending type does not exist " + agent.type; + } + else if (agent.name == "Resident") { + if (agent.type == "Resident") + this.behavior = new resident(agent.id) + else + throw new Exception("That resident type does not exist " + agent.type); + } + else if (agent.name == "Pharmacist") { + if (agent.type == "Pharmacist") + this.behavior = new pharmacist(agent.id) + else + throw new Exception("That pharmacist type does not exist " + agent.type); + } + else if (agent.name == "EscapePerson") { + this.behavior = new EscapePerson(agent.id) + } + else { + throw new Exception("The agent name of " + agent.name + " is not a valid agent name."); + } + } + + + getStart() { return [this.startX, this.startY, this.startZ]; } + + getEnd() { return [this.destX, this.destY, this.destZ]; } + + setId(i) { this.id = i; } + + getId() { return this.id; } + + getStartMSec() { return this.startMSec; } + /** + * If current agent is active, update its newDestination to App() class's update method + */ + isActive() { return active; } + setActive(active) { this.active = active; } + getPatientTempState(){return this.patientTempState;} +} + +export default MedicalAgentThesis; \ No newline at end of file diff --git a/src/people/medical-agent.js b/src/people/medical-agent.js index 3d66aaa..a2a3716 100644 --- a/src/people/medical-agent.js +++ b/src/people/medical-agent.js @@ -18,10 +18,6 @@ import tech from "./tech.js" import triageNurse from "./triage-nurse.js" import xray from "./xray.js" -import greeterNurseThesis from "./thesis/greeter-nurse-thesis.js"; -import traigeNurseThesis from "./thesis/triage-nurse-thesis.js"; - - class MedicalAgent extends AMedicalStaff { startX; startY; diff --git a/src/people/patient-agent-thesis.js b/src/people/patient-agent-thesis.js new file mode 100644 index 0000000..073ee32 --- /dev/null +++ b/src/people/patient-agent-thesis.js @@ -0,0 +1,78 @@ +import Agent from "./agent.js" +import patient from "./patient.js" +import APatient from "./apatient.js" + +import patientThesis from "./patient-thesis.js"; + +class PatientAgentThesis extends APatient { + startX; + startY; + startZ; + destX; + destY; + destZ; + startMSec; + inSimulation = false; + hasEntered = false; + behavior; + emergencyQueue = false; + + static index = 0; + idx; //Corresponds to the internal idx number used by recast + + constructor(agent, location, UUID, severity, arrivalCount) { + super(location, UUID, severity, arrivalCount); + + this.name = agent.name; + this.startMSec = agent.arrivalTick * 25; // We simulate 25 fps + this.arrivalLocation = agent.arrivalLocation; + this.age = agent.age; + this.severity = agent.severity; + this.patientName = agent.patientName; + this.gender = agent.gender; + this.id = agent.id; + + let startLocation = Hospital.locations.find(i => i.name == agent.arrivalLocation); + if (!startLocation) console.error("Bad starting location " + agent.arrivalLocation); + + + this.startX = startLocation.location.x + this.startY = startLocation.location.y; + this.startZ = startLocation.location.z; + + this.destX = 0; + this.destY = 0; + this.destZ = 0; + + // ORIGINAL BEHAVIOR + //this.behavior = new patient( agent.id, Hospital.locations.find(l => l.name == "Check In")); + + // NEW BEHAVIOR + this.behavior = new patientThesis( agent.id, Hospital.locations.find(l => l.name == "Check In")); + + if (startLocation == Hospital.locations.find(l => l.name == "Ambulance Entrance")) { + //this.behavior = new patient( agent.id, Hospital.locations.find(l => l.name == "Ambulance Entrance")); + this.behavior = new patientThesis( agent.id, Hospital.locations.find(l => l.name == "Ambulance Entrance")); + } + + } + + + + getStart() { return [this.startX, this.startY, this.startZ]; } + + getEnd() { return [this.destX, this.destY, this.destZ]; } + + setId(i) { this.id = i; } + + getId() { return this.id; } + + getStartMSec() { return this.startMSec; } + /** + * If current agent is active, update its newDestination to App() class's update method + */ + isActive() { return active; } + setActive(active) { this.active = active; } +} + +export default PatientAgentThesis; \ No newline at end of file diff --git a/src/people/patient-agent.js b/src/people/patient-agent.js index 80d6845..6dbd480 100644 --- a/src/people/patient-agent.js +++ b/src/people/patient-agent.js @@ -2,8 +2,6 @@ import Agent from "./agent.js" import patient from "./patient.js" import APatient from "./apatient.js" -import patientThesis from "./thesis/patient-thesis.js"; - class PatientAgent extends APatient { startX; startY; diff --git a/src/people/thesis/patient-thesis.js b/src/people/patient-thesis.js similarity index 94% rename from src/people/thesis/patient-thesis.js rename to src/people/patient-thesis.js index b145a76..fed4c82 100644 --- a/src/people/thesis/patient-thesis.js +++ b/src/people/patient-thesis.js @@ -1,7 +1,7 @@ -import FollowInstructions from "../../behavior/follow-instructions.js"; -import GoToLazy from "../../behavior/go-to-lazy.js"; +import FollowInstructions from "../behavior/follow-instructions.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; // import LOG -import Stop from "../../behavior/stop.js"; +import Stop from "../behavior/stop.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" import PatientTempState from "../support/patient-temp-state.js"; diff --git a/src/people/thesis/task-thesis.js b/src/people/thesis/task-thesis.js deleted file mode 100644 index becdfad..0000000 --- a/src/people/thesis/task-thesis.js +++ /dev/null @@ -1,14 +0,0 @@ -class task { - taskID; - severity; - entryTime; - waitingTime; - patient; - location; - - constructor() { - - } -} - -export default task; \ No newline at end of file diff --git a/src/people/thesis/triage-nurse-thesis.js b/src/people/triage-nurse-thesis.js similarity index 83% rename from src/people/thesis/triage-nurse-thesis.js rename to src/people/triage-nurse-thesis.js index af6f044..b5ffcf0 100644 --- a/src/people/thesis/triage-nurse-thesis.js +++ b/src/people/triage-nurse-thesis.js @@ -1,8 +1,8 @@ -import GoTo from "../../behavior/go-to.js"; -import GoToLazy from "../../behavior/go-to-lazy.js"; -import LeavePatient from "../../behavior/leave-patient.js"; +import GoTo from "../behavior/go-to.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; +import LeavePatient from "../behavior/leave-patient.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree"; -import PatientTempState from "../../support/patient-temp-state.js"; +import PatientTempState from "../support/patient-temp-state.js"; class triageNurseThesis { @@ -74,22 +74,24 @@ class triageNurseThesis { // .end() // .end() - //.splice(new GoTo(self.index, myGoal.location).tree) .splice(new GoTo(self.index, Hospital.locations.find(l => l.name == "TriageNursePlace").location).tree) .do("Wait For Patient Assignment", async (t) => { - if (!me().getCurrentPatient()) return fluentBehaviorTree.BehaviorTreeStatus.Failure; - me().setBusy(true); - //console.log("test"); - return fluentBehaviorTree.BehaviorTreeStatus.Success; - + if (Hospital.triageTaskList.length == 0) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + // THIS IS NOT DESIGNED WITH SEVERITY/WAIT TIME OR ROOM ASSIGNMENT IN MIND YET + let myTask = Hospital.triageTaskList.shift(); + me().setCurrentPatient(myTask.patient); + me().getCurrentPatient().setInstructor(closestTriageNurse); + me().getCurrentPatient().setPatientTempState(PatientTempState.FOLLOWING); + + me().setBusy(true); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } }) - // .do("Test", async (t) => { - // console.log("test"); - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // }) - .splice(new GoToLazy(self.index, () => me().getCurrentPatient().getAssignedRoom().location).tree) .do("Leave Patient", (t) => { diff --git a/src/support/hospital.js b/src/support/hospital.js index a9222fd..3ae4d08 100644 --- a/src/support/hospital.js +++ b/src/support/hospital.js @@ -41,6 +41,7 @@ class Hospital{ // USING THIS FOR AGENT BEHAVIORS static triageTaskList = []; + static janitorTaskList = []; static getFPS(){return 60;} diff --git a/src/support/task-thesis.js b/src/support/task-thesis.js new file mode 100644 index 0000000..6d97a9f --- /dev/null +++ b/src/support/task-thesis.js @@ -0,0 +1,20 @@ +class task { + taskID; + severity; + entryTime; + waitingTime; + patient; + location; + + constructor(taskID, severity, entryTime, patient, location) { + this.taskID = taskID; + this.severity = severity; + this.entryTime = entryTime; + this.patient = patient; + this.location = location; + + waitingTime = 0; + } +} + +export default task; \ No newline at end of file From b6832dce6e733a5d67d941ec19bb5a6081496bf7 Mon Sep 17 00:00:00 2001 From: Narducky Date: Tue, 14 Dec 2021 16:30:45 -0600 Subject: [PATCH 03/42] Fixed bugs Fixed and implemented greeter, triage, and janitor trees. Also found and fixed a bug relating to the CT Queue. --- .../assign-patient-to-triage-nurse-thesis.js | 3 +- src/behavior/follow-instructions.js | 2 + src/behavior/look-for-arriving-patient.js | 1 + .../responsibility/resident-ekg-order-cat.js | 13 ++- .../responsibility/resident-ekg-order-xray.js | 16 ++-- src/index.js | 6 +- src/people/greeter-nurse-thesis.js | 5 - src/people/janitorial-thesis.js | 52 +++++----- src/people/triage-nurse-thesis.js | 94 +++++++++---------- src/support/hospital.js | 1 + src/support/task-thesis.js | 25 +++-- notes.md => thesis-notes.md | 0 12 files changed, 114 insertions(+), 104 deletions(-) rename notes.md => thesis-notes.md (100%) diff --git a/src/behavior/assign-patient-to-triage-nurse-thesis.js b/src/behavior/assign-patient-to-triage-nurse-thesis.js index 8dd8929..bb7885b 100644 --- a/src/behavior/assign-patient-to-triage-nurse-thesis.js +++ b/src/behavior/assign-patient-to-triage-nurse-thesis.js @@ -23,7 +23,8 @@ class AssignPatientToTriageNurseThesis { else { let myPatient = me().triageList.shift(); // Task ID / Severity / Entry Time / Patient / Location - let triageTask = new task("Triage", myPatient.getSeverity(), null, myPatient, myPatient.getAssignedRoom()); + let triageTask = new task("Triage", myPatient.getSeverity(), 0, myPatient, myPatient.getAssignedRoom()); + Hospital.triageTaskList.push(triageTask); return fluentBehaviorTree.BehaviorTreeStatus.Success; diff --git a/src/behavior/follow-instructions.js b/src/behavior/follow-instructions.js index e641125..abf5770 100644 --- a/src/behavior/follow-instructions.js +++ b/src/behavior/follow-instructions.js @@ -101,7 +101,9 @@ class FollowInstructions { Hospital.setXRay2Occupied(false); } // SET ROOM AS READY TO CLEAN + // OLD METHOD me().getPermanentRoom().setLocationStatus(LocationStatus.SANITIZE); + // NEW METHOD let sanitizeTask = new task("Sanitize", null, null, null, me().getPermanentRoom()); Hospital.janitorTaskList.push(sanitizeTask); diff --git a/src/behavior/look-for-arriving-patient.js b/src/behavior/look-for-arriving-patient.js index b1b6b8f..e4d229c 100644 --- a/src/behavior/look-for-arriving-patient.js +++ b/src/behavior/look-for-arriving-patient.js @@ -78,6 +78,7 @@ class LookForArrivingPatient { } } } + // IF THERE ARE NO PATIENTS WAITING, KEEP LOOKING if (me().PatientList.length == 0) { return fluentBehaviorTree.BehaviorTreeStatus.Running; diff --git a/src/behavior/responsibility/resident-ekg-order-cat.js b/src/behavior/responsibility/resident-ekg-order-cat.js index 21cfbe8..a03b9d4 100644 --- a/src/behavior/responsibility/resident-ekg-order-cat.js +++ b/src/behavior/responsibility/resident-ekg-order-cat.js @@ -12,16 +12,21 @@ class ResidentEKGOrderCAT extends AResponsibility{ doFinish() { this.entry.acknowledge(ACK.RESIDENT_EKG_ORDER_CAT); let myPatient = this.entry.getPatient(); - if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue[0].getSeverity() != "ESI1") { + if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() != "ESI1") { Hospital.CTQueue.unshift(myPatient); } - else if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue[0].getSeverity() == "ESI1") { + else if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() == "ESI1") { let i = 0; - while (Hospital.CTQueue[i].getSeverity() == "ESI1") { + while (i < Hospital.CTQueue.length && Hospital.CTQueue[i].getSeverity() == "ESI1") { i++; } - Hospital.CTQueue.splice(i, 0, myPatient); + if (i == Hospital.CTQueue.length) { + Hospital.CTQueue.push(myPatient); + } + else { + Hospital.CTQueue.splice(i, 0, myPatient); + } } else { Hospital.CTQueue.push(myPatient); diff --git a/src/behavior/responsibility/resident-ekg-order-xray.js b/src/behavior/responsibility/resident-ekg-order-xray.js index b2fa429..3d61e0f 100644 --- a/src/behavior/responsibility/resident-ekg-order-xray.js +++ b/src/behavior/responsibility/resident-ekg-order-xray.js @@ -12,19 +12,21 @@ class ResidentEKGOrderXRay extends AResponsibility{ doFinish() { this.entry.acknowledge(ACK.RESIDENT_EKG_ORDER_XRAY); let myPatient = this.entry.getPatient(); - // if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue[0].getSeverity() != "ESI1") { + // if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() != "ESI1") { // Hospital.CTQueue.unshift(myPatient); // } - // else if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue[0].getSeverity() == "ESI1") { + // else if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() == "ESI1") { // let i = 0; - // while (Hospital.CTQueue[i].getSeverity() == "ESI1") { + // while (i < Hospital.CTQueue.length && Hospital.CTQueue[i].getSeverity() == "ESI1") { // i++; // } - // Hospital.CTQueue.splice(i, 0, myPatient); - // } - // else { - // Hospital.CTQueue.push(myPatient); + // if (i == Hospital.CTQueue.length) { + // Hospital.CTQueue.push(myPatient); + // } + // else { + // Hospital.CTQueue.splice(i, 0, myPatient); + // } // } Hospital.XRayQueue.push(myPatient); } diff --git a/src/index.js b/src/index.js index 3ca765d..ba11a7f 100644 --- a/src/index.js +++ b/src/index.js @@ -48,9 +48,9 @@ function boot() { //Add an agent with a behavior and an id arrivalValue.forEach((agent, index) => { if (agent.name == "patient") - agentConstants.push(new PatientAgent(agent, locationValue)); + agentConstants.push(new PatientAgentThesis(agent, locationValue)); else - agentConstants.push(new MedicalAgent(agent, locationValue)); + agentConstants.push(new MedicalAgentThesis(agent, locationValue)); //Is this line necessary? agentConstants[agentConstants.length - 1].setId(index); }) @@ -61,7 +61,7 @@ function boot() { let crowdSetup = new CrowdSetup(objValue, agentConstants, params.secondsOfSimulation, params.millisecondsBetweenFrames, locationValue, window, document.body, colorFunction, simulations, "./crowd-setup/"); - // setupTable(crowdSetup); + //setupTable(crowdSetup); // }) //This can be commented out for debugging purposes. In production, this should not be commented. diff --git a/src/people/greeter-nurse-thesis.js b/src/people/greeter-nurse-thesis.js index 69a0c2c..23d9942 100644 --- a/src/people/greeter-nurse-thesis.js +++ b/src/people/greeter-nurse-thesis.js @@ -27,11 +27,6 @@ class greeterNurseThesis { this.tree = builder .sequence("Greeter Nurse Behaviors") - // ----------------------------------------------- - // - // POTENTIALLY CHANGE CLOCK IN AND OUT BEHAVIORS - // - // ----------------------------------------------- .selector("Check for arrival") .condition("Clock in", async (t) => me().onTheClock) .do("SHIFT CHANGE", (t) => { diff --git a/src/people/janitorial-thesis.js b/src/people/janitorial-thesis.js index ab6ab31..ab19541 100644 --- a/src/people/janitorial-thesis.js +++ b/src/people/janitorial-thesis.js @@ -19,9 +19,12 @@ class janitorialThesis { let myGoal = Hospital.locations.find(l => l.name == goToName); if (!myGoal) throw new exception("We couldn't find a location called " + goToName); + let myRoom; + this.tree = builder .sequence("Janitorial") + // CLOCK IN .selector("Check for arrival") .condition("Clock in", async (t) => me().onTheClock) .do("SHIFT CHANGE", (t) => { @@ -56,38 +59,27 @@ class janitorialThesis { }) .end() .end() - - .splice(new GoTo(self.index, myGoal.location).tree) - - //find room to clean - .do("Find Room to Clean", (t) => { - // if (typeof Hospital.locations.find(l => l.locationStatus == LocationStatus.SANITIZE) === 'undefined') { - // return fluentBehaviorTree.BehaviorTreeStatus.Failure; - // } - // else { - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // } - - if (Hospital.janitorTaskList.length == 0) { - return fluentBehaviorTree.BehaviorTreeStatus.Failure; - } - else { - return fluentBehaviorTree.BehaviorTreeStatus.Success; - } - - }) - - // GO TO THE ROOM THAT NEEDS CLEANING - .splice(new GoToLazy(self.index, () => Hospital.locations.find(l => l.locationStatus == LocationStatus.SANITIZE).location).tree) - // TAKE TIME IN THE ROOM TO CLEAN - .splice(new TakeTime(300, 600).tree) + .sequence("Clean Room") + // GO TO JANITOR CLOSET + .splice(new GoTo(self.index, myGoal.location).tree) + .condition("Is there a room to clean?", async (t) => Hospital.janitorTaskList.length > 0) + // PICK/CLAIM THE ROOM TO CLEAN + .do("Pick the room", (t) => { + myRoom = Hospital.janitorTaskList.shift().location; + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // GO TO THE ROOM THAT NEEDS CLEANING + .splice(new GoToLazy(self.index, () => myRoom.location).tree) + // TAKE TIME IN THE ROOM TO CLEAN + .splice(new TakeTime(300, 600).tree) + // SET STATUS AS NONE - PROBABLY DON'T ACTUALLY NEED THIS + .do("Done with the Room", (t) => { + myRoom.setLocationStatus(LocationStatus.NONE); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) - // set that room's status as NONE - .do("Done with the Room", (t) => { - Hospital.locations.find(l => l.locationStatus == LocationStatus.SANITIZE).setLocationStatus(LocationStatus.NONE); - return fluentBehaviorTree.BehaviorTreeStatus.Success; - }) + .end() .end() .build(); diff --git a/src/people/triage-nurse-thesis.js b/src/people/triage-nurse-thesis.js index b5ffcf0..4ceeee2 100644 --- a/src/people/triage-nurse-thesis.js +++ b/src/people/triage-nurse-thesis.js @@ -27,52 +27,52 @@ class triageNurseThesis { this.tree = builder .sequence("Pick Triage Room") - // .selector("Check for arrival") - // .condition("Clock in", async (t) => me().onTheClock) - // .do("SHIFT CHANGE", (t) => { - // // SHIFT CHANGE - // if (me().onTheClock == false) { - // me().onTheClock = true; - // Hospital.activeTriage.push(me()); - // if (Hospital.activeTriage[0] != me() && Hospital.activeTriage.length > 2) { - // for (let i = 0; i < Hospital.activeTriage.length; i++) { - // if (!Hospital.activeTriage[i].replacement) { - // Hospital.activeTriage[i].replacement = true; - // //Hospital.activeTriage.shift(); - // Hospital.activeTriage.splice(i, 1); - // break; - // } - // } - // } - // } - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // }) - // .end() - - // // SHIFT CHANGE SEQUENCE OF BEHAVIORS - // .selector("Check for Replacement") - // .condition("Replacement is Here", async (t) => !me().replacement) - // .sequence("Exit Procedure") - // .splice(new GoTo(self.index, Hospital.locations.find(l => l.name == "Main Entrance").location).tree) - // .do("Leave Simulation", (t) => { - // for(let i = 0; i < Hospital.computer.entries.length; i++) { - // // LEFTOVER ARTIFACT OF ORIGINAL ATTEMPT TO FIX TRIAGE WITH SHIFT CHANGES - // // THIS IF STATEMENT PROBABLY WON'T EVER RUN DUE TO THE ACTUAL SUCCESSFUL IMPLEMENTATION - // if (Hospital.computer.entries[i].getPatient().getInstructor() != null && Hospital.computer.entries[i].getPatient().getInstructor() == me() && Hospital.computer.entries[i].getPatient().getPatientTempState() == PatientTempState.FOLLOWING) { - // Hospital.computer.entries[i].getPatient().setInstructor(null); - // Hospital.computer.entries[i].getPatient().setPatientTempState(PatientTempState.WAITING); - // // THIS IF STATEMENT DOESN'T DO ANYTHING BECAUSE YOU CAN'T ACCESS THE VALUE FOR SOME REASON - // if (Hospital.activeGreeter[0].triageList[0] == Hospital.computer.entries[i].getPatient()) { - // Hospital.activeGreeter[0].triageList.shift(); - // } - // Hospital.activeGreeter[0].triageList.push(Hospital.computer.entries[i].getPatient()); - // } - // } - // me().inSimulation = false; - // return fluentBehaviorTree.BehaviorTreeStatus.Running; - // }) - // .end() - // .end() + .selector("Check for arrival") + .condition("Clock in", async (t) => me().onTheClock) + .do("SHIFT CHANGE", (t) => { + // SHIFT CHANGE + if (me().onTheClock == false) { + me().onTheClock = true; + Hospital.activeTriage.push(me()); + if (Hospital.activeTriage[0] != me() && Hospital.activeTriage.length > 2) { + for (let i = 0; i < Hospital.activeTriage.length; i++) { + if (!Hospital.activeTriage[i].replacement) { + Hospital.activeTriage[i].replacement = true; + //Hospital.activeTriage.shift(); + Hospital.activeTriage.splice(i, 1); + break; + } + } + } + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + + // SHIFT CHANGE SEQUENCE OF BEHAVIORS + .selector("Check for Replacement") + .condition("Replacement is Here", async (t) => !me().replacement) + .sequence("Exit Procedure") + .splice(new GoTo(self.index, Hospital.locations.find(l => l.name == "Main Entrance").location).tree) + .do("Leave Simulation", (t) => { + for(let i = 0; i < Hospital.computer.entries.length; i++) { + // LEFTOVER ARTIFACT OF ORIGINAL ATTEMPT TO FIX TRIAGE WITH SHIFT CHANGES + // THIS IF STATEMENT PROBABLY WON'T EVER RUN DUE TO THE ACTUAL SUCCESSFUL IMPLEMENTATION + if (Hospital.computer.entries[i].getPatient().getInstructor() != null && Hospital.computer.entries[i].getPatient().getInstructor() == me() && Hospital.computer.entries[i].getPatient().getPatientTempState() == PatientTempState.FOLLOWING) { + Hospital.computer.entries[i].getPatient().setInstructor(null); + Hospital.computer.entries[i].getPatient().setPatientTempState(PatientTempState.WAITING); + // THIS IF STATEMENT DOESN'T DO ANYTHING BECAUSE YOU CAN'T ACCESS THE VALUE FOR SOME REASON + if (Hospital.activeGreeter[0].triageList[0] == Hospital.computer.entries[i].getPatient()) { + Hospital.activeGreeter[0].triageList.shift(); + } + Hospital.activeGreeter[0].triageList.push(Hospital.computer.entries[i].getPatient()); + } + } + me().inSimulation = false; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + }) + .end() + .end() .splice(new GoTo(self.index, Hospital.locations.find(l => l.name == "TriageNursePlace").location).tree) @@ -84,7 +84,7 @@ class triageNurseThesis { // THIS IS NOT DESIGNED WITH SEVERITY/WAIT TIME OR ROOM ASSIGNMENT IN MIND YET let myTask = Hospital.triageTaskList.shift(); me().setCurrentPatient(myTask.patient); - me().getCurrentPatient().setInstructor(closestTriageNurse); + me().getCurrentPatient().setInstructor(me()); me().getCurrentPatient().setPatientTempState(PatientTempState.FOLLOWING); me().setBusy(true); diff --git a/src/support/hospital.js b/src/support/hospital.js index 3ae4d08..00ce1a4 100644 --- a/src/support/hospital.js +++ b/src/support/hospital.js @@ -1,4 +1,5 @@ import * as THREE from "three" +import task from "./task-thesis.js"; class Hospital{ diff --git a/src/support/task-thesis.js b/src/support/task-thesis.js index 6d97a9f..f80fb2c 100644 --- a/src/support/task-thesis.js +++ b/src/support/task-thesis.js @@ -1,10 +1,12 @@ + + class task { - taskID; - severity; - entryTime; - waitingTime; - patient; - location; + taskID; // STRING + severity; // PATIENT SEVERITY OR NUMBER + entryTime; // INT + waitingTime = 0; // INT + patient; // PATIENT + location; // LOCATION constructor(taskID, severity, entryTime, patient, location) { this.taskID = taskID; @@ -12,8 +14,17 @@ class task { this.entryTime = entryTime; this.patient = patient; this.location = location; + } - waitingTime = 0; + toString() { + let toReturn = ""; + toReturn += taskID + ","; + toReturn += severity + ", "; + toReturn += entryTime + ", "; + toReturn += waitingTime + ", "; + toReturn += patient + ", "; + toReturn += location + ", "; + return toReturn; } } diff --git a/notes.md b/thesis-notes.md similarity index 100% rename from notes.md rename to thesis-notes.md From e35f1ddf5d2def35d7d8e0af5ef109aa792cabcb Mon Sep 17 00:00:00 2001 From: Narducky Date: Mon, 27 Dec 2021 18:00:31 -0600 Subject: [PATCH 04/42] Nurse Behavior Tree First real demonstration of the new methods. Simplifies the Nurse tree in a massive way. --- src/people/amedical-staff.js | 11 +++- src/people/medical-agent-thesis.js | 4 +- src/people/nurse-thesis.js | 94 ++++++++++++++++++++++++++++++ src/support/hospital.js | 1 + 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 src/people/nurse-thesis.js diff --git a/src/people/amedical-staff.js b/src/people/amedical-staff.js index dc7bf54..ba136ff 100644 --- a/src/people/amedical-staff.js +++ b/src/people/amedical-staff.js @@ -11,6 +11,7 @@ class AMedicalStaff extends APerson { responsibility; //AResponsibility computer; //IRoom -> ARoom busy = false; //boolean (if the nurse needs to finish their behavior before getting another patient) + task; //Task constructor(location, UUID, medicalStaffType, medicalStaffSubclass, doctorYear, arrivalTick) { super(location, UUID, arrivalTick); @@ -27,8 +28,6 @@ class AMedicalStaff extends APerson { this.myRooms = []; this.patientList = []; this.triageList = []; - - } getBusy() { @@ -57,6 +56,14 @@ class AMedicalStaff extends APerson { this.setCurrentPatient(responsibility.entry.patient); } + get Task() { + return this.task; + } + + set Task(task) { + this.task = task; + } + get MyRooms() { return this.myRooms; } diff --git a/src/people/medical-agent-thesis.js b/src/people/medical-agent-thesis.js index 3ea11aa..01f5530 100644 --- a/src/people/medical-agent-thesis.js +++ b/src/people/medical-agent-thesis.js @@ -19,6 +19,7 @@ import triageNurse from "./triage-nurse.js" import xray from "./xray.js" import greeterNurseThesis from "./greeter-nurse-thesis.js"; +import nurseThesis from "./nurse-thesis.js"; import triageNurseThesis from "./triage-nurse-thesis.js"; import janitorialThesis from "./janitorial-thesis.js"; @@ -92,7 +93,8 @@ class MedicalAgentThesis extends AMedicalStaff { //this.behavior = new triageNurse(agent.id) this.behavior = new triageNurseThesis(agent.id) else if (agent.type == "Nurse") - this.behavior = new nurse(agent.id) + //this.behavior = new nurse(agent.id) + this.behavior = new nurseThesis(agent.id) else if (agent.type == "Greeter Nurse") //this.behavior = new greeterNurse(agent.id) this.behavior = new greeterNurseThesis(agent.id) diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js new file mode 100644 index 0000000..bd9af4d --- /dev/null +++ b/src/people/nurse-thesis.js @@ -0,0 +1,94 @@ +import GoTo from "../behavior/go-to.js"; +import AssignComputer from "../behavior/assign-computer.js" +import TakeTime from "../behavior/take-time.js"; +import task from "../support/task-thesis.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + +class nurseThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + this.toReturn = null; + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + + let goToName = "NursePlace"; + let myGoal = Hospital.locations.find(l => l.name == goToName); + let computer = Hospital.locations.find(l => l.name == "NursePlace"); + this.tree = builder + + // Consider limiting the rooms nurses can be assigned to tasks to + .sequence("Nurse Behaviors") + .splice(new GoTo(self.index, myGoal.location).tree) + .splice(new AssignComputer(myIndex, computer.location).tree) // NURSE PLACE + .selector("Task List Tasks") + .do("Get a Task", (t) => { + if (Hospital.nurseTaskList.length == 0) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + me().Task(Hospital.nurseTaskList.shift()); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // .do("Clock In / Clock Out", (t) => { + // Could make this a spliced behavior that takes the agent as a parameter + //return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) + .do("Get Health Information", (t) => { + if (me().Task.taskID != "Get Health Information") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let patientEntry = Hospital.computer.getEntry(me().Task.patient); + patientEntry.setAnsweredQuestions(true); + me().Task(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + .do("Nurse Discharge Patient", (t) => { + if (me().Task.taskID != "Nurse Discharge Patient") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let dischargeTask = new task("Nurse Escort Patient To Exit", null, null, me().Task.patient, null); + Hospital.nurseTaskList.push(dischargeTask); + // Could just change task to escorting to exit immediately + //me().Task(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + .do("Nurse Escort Patient To Exit", (t) => { + if (me().Task.taskID != "Nurse Escort Patient To Exit") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + + me().Task(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + .end() + // If success in finding and accomplishing task, take time to do that task + .splice(new TakeTime(300, 600).tree) + .end() + .build() + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } + + // checkEndOfSimulation() { + // if (self.Hospital.computer.entries.length > 0) { + // return self.Hospital.computer.entries[0].unacknowledged("NurseEscortPatientToExit"); + // } + // return false; + // } + +} + +export default nurseThesis; \ No newline at end of file diff --git a/src/support/hospital.js b/src/support/hospital.js index 00ce1a4..3aa38e7 100644 --- a/src/support/hospital.js +++ b/src/support/hospital.js @@ -43,6 +43,7 @@ class Hospital{ // USING THIS FOR AGENT BEHAVIORS static triageTaskList = []; static janitorTaskList = []; + static nurseTaskList = []; static getFPS(){return 60;} From f42afb55e477d48b92a5abdabf820f46430ae33f Mon Sep 17 00:00:00 2001 From: Narducky Date: Mon, 3 Jan 2022 16:23:29 -0600 Subject: [PATCH 05/42] Getting new tree functionality working Most functionality set up in nurse tree. Need to set up last two responsibilities. Also consider drafting a flowchart of task allocations. --- src/people/amedical-staff.js | 4 +- src/people/nurse-thesis.js | 63 ++++++++++++++++++++++--------- src/people/triage-nurse-thesis.js | 10 ++++- thesis-notes.md | 4 +- 4 files changed, 58 insertions(+), 23 deletions(-) diff --git a/src/people/amedical-staff.js b/src/people/amedical-staff.js index ba136ff..88edd55 100644 --- a/src/people/amedical-staff.js +++ b/src/people/amedical-staff.js @@ -56,11 +56,11 @@ class AMedicalStaff extends APerson { this.setCurrentPatient(responsibility.entry.patient); } - get Task() { + getTask() { return this.task; } - set Task(task) { + setTask(task) { this.task = task; } diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js index bd9af4d..a81df6a 100644 --- a/src/people/nurse-thesis.js +++ b/src/people/nurse-thesis.js @@ -1,4 +1,5 @@ import GoTo from "../behavior/go-to.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; import AssignComputer from "../behavior/assign-computer.js" import TakeTime from "../behavior/take-time.js"; import task from "../support/task-thesis.js"; @@ -21,36 +22,60 @@ class nurseThesis { this.tree = builder // Consider limiting the rooms nurses can be assigned to tasks to + // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART .sequence("Nurse Behaviors") - .splice(new GoTo(self.index, myGoal.location).tree) + .splice(new GoTo(self.index, computer.location).tree) .splice(new AssignComputer(myIndex, computer.location).tree) // NURSE PLACE .selector("Task List Tasks") .do("Get a Task", (t) => { - if (Hospital.nurseTaskList.length == 0) { + // IF ALREADY ALLOCATED A TASK, CONTINUE + if (me().getTask() != null) { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } + // CHECK IF ANY TASKS ARE AVAILABLE, CONTINUE + else if (Hospital.nurseTaskList.length != 0) { + me().setTask(Hospital.nurseTaskList.shift()); + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // OTHERWISE DON'T PROCEED (SUCCESS WILL RESTART SELECTOR) else { - me().Task(Hospital.nurseTaskList.shift()); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) + // I think it has to be done this way because you can't do operations in a splice for the most part + .inverter("Need to return failure") + .sequence("Go to Task") + .do("Determine Location", (t) => { + if (me().getTask().location != null) { + myGoal = me().getTask().location; + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // GoTo gives me problems sometimes that GoToLazy does not + .splice(new GoToLazy(self.index, () => myGoal.location).tree) + .end() + .end() + // .do("Clock In / Clock Out", (t) => { // Could make this a spliced behavior that takes the agent as a parameter //return fluentBehaviorTree.BehaviorTreeStatus.Success; // }) + + // THIS TASK IS GIVEN BY THE TRIAGE NURSE .do("Get Health Information", (t) => { - if (me().Task.taskID != "Get Health Information") { + if (me().getTask().taskID != "Get Health Information") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let patientEntry = Hospital.computer.getEntry(me().Task.patient); + let patientEntry = Hospital.computer.getEntry(me().getTask().patient); patientEntry.setAnsweredQuestions(true); - me().Task(null); + me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) + // THIS TASK IS GIVEN BY ?? (probably tech that escorts patient back from CT) .do("Nurse Discharge Patient", (t) => { - if (me().Task.taskID != "Nurse Discharge Patient") { + if (me().getTask().taskID != "Nurse Discharge Patient") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { @@ -61,20 +86,23 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) + // THIS TASK IS GIVEN BY THE PREVIOUS TASK + // need to code this still .do("Nurse Escort Patient To Exit", (t) => { - if (me().Task.taskID != "Nurse Escort Patient To Exit") { + if (me().getTask().taskID != "Nurse Escort Patient To Exit") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - me().Task(null); + me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) .end() - // If success in finding and accomplishing task, take time to do that task + // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK + // Need to fix TakeTime .splice(new TakeTime(300, 600).tree) - .end() + .end() .build() } @@ -82,12 +110,13 @@ class nurseThesis { await this.tree.tick({ crowd, msec }) //Call the behavior tree } - // checkEndOfSimulation() { - // if (self.Hospital.computer.entries.length > 0) { - // return self.Hospital.computer.entries[0].unacknowledged("NurseEscortPatientToExit"); - // } - // return false; - // } + // NEED TO ALTER THIS + checkEndOfSimulation() { + if (self.Hospital.computer.entries.length > 0) { + return self.Hospital.computer.entries[0].unacknowledged("NurseEscortPatientToExit"); + } + return false; + } } diff --git a/src/people/triage-nurse-thesis.js b/src/people/triage-nurse-thesis.js index 4ceeee2..f35357e 100644 --- a/src/people/triage-nurse-thesis.js +++ b/src/people/triage-nurse-thesis.js @@ -3,7 +3,7 @@ import GoToLazy from "../behavior/go-to-lazy.js"; import LeavePatient from "../behavior/leave-patient.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree"; import PatientTempState from "../support/patient-temp-state.js"; - +import task from "../support/task-thesis.js"; class triageNurseThesis { @@ -75,7 +75,7 @@ class triageNurseThesis { .end() .splice(new GoTo(self.index, Hospital.locations.find(l => l.name == "TriageNursePlace").location).tree) - + // THESE ASSIGNMENTS ARE GIVEN BY THE GREETER NURSE .do("Wait For Patient Assignment", async (t) => { if (Hospital.triageTaskList.length == 0) { return fluentBehaviorTree.BehaviorTreeStatus.Failure; @@ -95,10 +95,16 @@ class triageNurseThesis { .splice(new GoToLazy(self.index, () => me().getCurrentPatient().getAssignedRoom().location).tree) .do("Leave Patient", (t) => { + // ONCE THE PATIENT HAS BEEN DELIVERED, QUEUE TASKS TO THE APPROPRIATE MEDICAL STAFF + // Task ID / Severity / Entry Time / Patient / Location + let nurseTask = new task("Get Health Information", me().getCurrentPatient().getSeverity(), 0, me().getCurrentPatient(), me().getCurrentPatient().getAssignedRoom()); + Hospital.nurseTaskList.push(nurseTask); + let result = leavePatient.tick(t) if (me().replacement == false) { me().setBusy(false); } + return result; }) diff --git a/thesis-notes.md b/thesis-notes.md index bd9bd45..90c0318 100644 --- a/thesis-notes.md +++ b/thesis-notes.md @@ -12,7 +12,7 @@ The basis of these code changes boil down to this: - even getting the number and doing like testArray[tempValue] doesn't work. It must just be a number. # Questions -- Should probably have some sort of format/object for what goes in the ToDo arrays: -{taskname/ID/#, importance/severity, timestep it was entered?, potential patient it concerns, potential location?} - the arrays should probably be sorted every so often (by importance and time)? +- probably should make a flow chart (could include it in thesis as well) that illustrates the flow of tasks + greeter --assigns--> triage --assigns--> nurse / tech? / ? --> From 074525500be57bd05d8d01b32dc7d4041b14226f Mon Sep 17 00:00:00 2001 From: Narducky Date: Tue, 4 Jan 2022 15:58:17 -0600 Subject: [PATCH 06/42] Getting Tech set up General tech set up is good, going to go after the Resident tree next. Complications arising in that I can't completely finish one tree because they have dependencies to others queueing them tasks. Should look good when it is done though. --- src/people/aperson.js | 1 + src/people/medical-agent-thesis.js | 5 +- src/people/nurse-thesis.js | 29 ++++-- src/people/tech-thesis.js | 143 +++++++++++++++++++++++++++++ src/people/triage-nurse-thesis.js | 6 ++ src/support/hospital.js | 1 + 6 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 src/people/tech-thesis.js diff --git a/src/people/aperson.js b/src/people/aperson.js index ab2e104..b788468 100644 --- a/src/people/aperson.js +++ b/src/people/aperson.js @@ -16,6 +16,7 @@ class APerson extends AThing { UUID; // int assignedRoom; // IRoom -> ARoom moving = true; // boolean + taskTime = 0; get Moving() { return this.moving; diff --git a/src/people/medical-agent-thesis.js b/src/people/medical-agent-thesis.js index 01f5530..5b08229 100644 --- a/src/people/medical-agent-thesis.js +++ b/src/people/medical-agent-thesis.js @@ -22,7 +22,7 @@ import greeterNurseThesis from "./greeter-nurse-thesis.js"; import nurseThesis from "./nurse-thesis.js"; import triageNurseThesis from "./triage-nurse-thesis.js"; import janitorialThesis from "./janitorial-thesis.js"; - +import techThesis from "./tech-thesis.js"; class MedicalAgentThesis extends AMedicalStaff { startX; @@ -72,7 +72,8 @@ class MedicalAgentThesis extends AMedicalStaff { if (agent.name == "Tech") { if (agent.type == "Tech") - this.behavior = new tech(agent.id) + //this.behavior = new tech(agent.id) + this.behavior = new techThesis(agent.id) else if (agent.type == "CT") this.behavior = new ct(agent.id) else if (agent.type == "Janitorial") diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js index a81df6a..94bb406 100644 --- a/src/people/nurse-thesis.js +++ b/src/people/nurse-thesis.js @@ -26,6 +26,7 @@ class nurseThesis { .sequence("Nurse Behaviors") .splice(new GoTo(self.index, computer.location).tree) .splice(new AssignComputer(myIndex, computer.location).tree) // NURSE PLACE + // Add a behavior here or in the selector that will order the tasks (by severity)? .selector("Task List Tasks") .do("Get a Task", (t) => { // IF ALREADY ALLOCATED A TASK, CONTINUE @@ -49,6 +50,9 @@ class nurseThesis { if (me().getTask().location != null) { myGoal = me().getTask().location; } + else { + myGoal = computer; + } return fluentBehaviorTree.BehaviorTreeStatus.Success; }) // GoTo gives me problems sometimes that GoToLazy does not @@ -70,6 +74,7 @@ class nurseThesis { let patientEntry = Hospital.computer.getEntry(me().getTask().patient); patientEntry.setAnsweredQuestions(true); me().setTask(null); + me().taskTime = 100; return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) @@ -79,8 +84,8 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let dischargeTask = new task("Nurse Escort Patient To Exit", null, null, me().Task.patient, null); - Hospital.nurseTaskList.push(dischargeTask); + let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().Task.patient, null); + Hospital.nurseTaskList.push(exitTask); // Could just change task to escorting to exit immediately //me().Task(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -93,15 +98,24 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - + me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) .end() // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK - // Need to fix TakeTime - .splice(new TakeTime(300, 600).tree) + // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. + //.splice(new TakeTime(1000, 2000).tree) + .do("Take Time", (t) => { + while (me().taskTime > 0) + { + me().taskTime == me().taskTime--; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) .end() .build() } @@ -113,7 +127,10 @@ class nurseThesis { // NEED TO ALTER THIS checkEndOfSimulation() { if (self.Hospital.computer.entries.length > 0) { - return self.Hospital.computer.entries[0].unacknowledged("NurseEscortPatientToExit"); + return self.Hospital.computer.entries[0].unacknowledged("NurseEscortPatientToExit"); + //let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + //let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().Task.patient, null); + //return Hospital.nurseTaskList.push(exitTask); } return false; } diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js new file mode 100644 index 0000000..3004259 --- /dev/null +++ b/src/people/tech-thesis.js @@ -0,0 +1,143 @@ +import AssignBed from "../behavior/assign-bed.js"; +import AssignComputer from "../behavior/assign-computer.js" +import GoTo from "../behavior/go-to.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; +import TakeTime from "../behavior/take-time.js"; +import task from "../support/task-thesis.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + +class techThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + this.toReturn = null; + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + + let goToName = "TechPlace"; + let myGoal = Hospital.locations.find(l => l.name == goToName); + let computer = Hospital.locations.find(l => l.name == "TechPlace"); + this.tree = builder + + // Consider limiting the rooms nurses can be assigned to tasks to + // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART + .sequence("Tech Behaviors") + .splice(new GoTo(self.index, computer.location).tree) + //.splice(new AssignBed(myIndex, Hospital.locations.find(l => l.name == "C1").location).tree) + .splice(new AssignComputer(myIndex, computer.location).tree) // TECH PLACE + // Add a behavior here or in the selector that will order the tasks (by severity)? + .selector("Task List Tasks") + .do("Get a Task", (t) => { + // IF ALREADY ALLOCATED A TASK, CONTINUE + if (me().getTask() != null) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // CHECK IF ANY TASKS ARE AVAILABLE, CONTINUE + else if (Hospital.techTaskList.length != 0) { + me().setTask(Hospital.techTaskList.shift()); + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // OTHERWISE DON'T PROCEED (SUCCESS WILL RESTART SELECTOR) + else { + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // I think it has to be done this way because you can't do operations in a splice for the most part + .inverter("Need to return failure") + .sequence("Go to Task") + .do("Determine Location", (t) => { + if (me().getTask().location != null) { + myGoal = me().getTask().location; + } + else { + myGoal = computer; + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // GoTo gives me problems sometimes that GoToLazy does not + .splice(new GoToLazy(self.index, () => myGoal.location).tree) + .end() + .end() + + // .do("Clock In / Clock Out", (t) => { + // Could make this a spliced behavior that takes the agent as a parameter + //return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) + + // THIS TASK IS GIVEN BY THE TRIAGE NURSE + .do("Get Vitals", (t) => { + Hospital.computer.getEntry(me().getTask().patient).setVitals("Taken"); + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .do("Get EKG", (t) => { + Hospital.computer.getEntry(me().getTask().patient).setEkg("EKG Results"); + me().setTask(null); + // CREATE TASK FOR THE RESIDENT : RESIDENT_EKG_READ + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .do("CT Pickup", (t) => { + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .do("XRay Pickup", (t) => { + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .do("Escort Patient", (t) => { + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + + // // THIS TASK IS GIVEN BY THE TRIAGE NURSE + // .do("Get Health Information", (t) => { + // if (me().getTask().taskID != "Get Health Information") { + // return fluentBehaviorTree.BehaviorTreeStatus.Failure; + // } + // else { + // let patientEntry = Hospital.computer.getEntry(me().getTask().patient); + // patientEntry.setAnsweredQuestions(true); + // me().setTask(null); + // me().taskTime = 100; + // return fluentBehaviorTree.BehaviorTreeStatus.Success; + // } + // }) + // // THIS TASK IS GIVEN BY ?? (probably tech that escorts patient back from CT) + // .do("Nurse Discharge Patient", (t) => { + // if (me().getTask().taskID != "Nurse Discharge Patient") { + // return fluentBehaviorTree.BehaviorTreeStatus.Failure; + // } + // else { + // let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().Task.patient, null); + // Hospital.nurseTaskList.push(exitTask); + // // Could just change task to escorting to exit immediately + // //me().Task(null); + // return fluentBehaviorTree.BehaviorTreeStatus.Success; + // } + // }) + .end() + // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK + // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. + //.splice(new TakeTime(1000, 2000).tree) + .do("Take Time", (t) => { + while (me().taskTime > 0) + { + me().taskTime == me().taskTime--; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + .build() + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } +} + +export default techThesis; \ No newline at end of file diff --git a/src/people/triage-nurse-thesis.js b/src/people/triage-nurse-thesis.js index f35357e..bb8c505 100644 --- a/src/people/triage-nurse-thesis.js +++ b/src/people/triage-nurse-thesis.js @@ -100,6 +100,12 @@ class triageNurseThesis { let nurseTask = new task("Get Health Information", me().getCurrentPatient().getSeverity(), 0, me().getCurrentPatient(), me().getCurrentPatient().getAssignedRoom()); Hospital.nurseTaskList.push(nurseTask); + let techTaskVitals = new task("Get Vitals", me().getCurrentPatient().getSeverity(), 0, me().getCurrentPatient(), me().getCurrentPatient().getAssignedRoom()); + Hospital.techTaskList.push(techTaskVitals); + + let techTaskEKG = new task("Get EKG", me().getCurrentPatient().getSeverity(), 0, me().getCurrentPatient(), me().getCurrentPatient().getAssignedRoom()); + Hospital.techTaskList.push(techTaskEKG); + let result = leavePatient.tick(t) if (me().replacement == false) { me().setBusy(false); diff --git a/src/support/hospital.js b/src/support/hospital.js index 3aa38e7..835a00e 100644 --- a/src/support/hospital.js +++ b/src/support/hospital.js @@ -44,6 +44,7 @@ class Hospital{ static triageTaskList = []; static janitorTaskList = []; static nurseTaskList = []; + static techTaskList = []; static getFPS(){return 60;} From 8ba3de6dd6f16b085dd89d18e4b9b9a37ab2d013 Mon Sep 17 00:00:00 2001 From: Narducky Date: Wed, 5 Jan 2022 18:38:57 -0600 Subject: [PATCH 07/42] Tech, Nurse, Resident Trees Set up these three trees, but need to finish the escort/pick up behaviors of the tech and nurse. Then will start working on the radiology tree. --- src/people/medical-agent-thesis.js | 4 +- src/people/nurse-thesis.js | 20 ++- src/people/resident-thesis.js | 220 +++++++++++++++++++++++++++++ src/people/tech-thesis.js | 64 ++++----- src/support/hospital.js | 1 + 5 files changed, 264 insertions(+), 45 deletions(-) create mode 100644 src/people/resident-thesis.js diff --git a/src/people/medical-agent-thesis.js b/src/people/medical-agent-thesis.js index 5b08229..cfec127 100644 --- a/src/people/medical-agent-thesis.js +++ b/src/people/medical-agent-thesis.js @@ -23,6 +23,7 @@ import nurseThesis from "./nurse-thesis.js"; import triageNurseThesis from "./triage-nurse-thesis.js"; import janitorialThesis from "./janitorial-thesis.js"; import techThesis from "./tech-thesis.js"; +import residentThesis from "./resident-thesis.js"; class MedicalAgentThesis extends AMedicalStaff { startX; @@ -110,7 +111,8 @@ class MedicalAgentThesis extends AMedicalStaff { } else if (agent.name == "Resident") { if (agent.type == "Resident") - this.behavior = new resident(agent.id) + //this.behavior = new resident(agent.id) + this.behavior = new residentThesis(agent.id) else throw new Exception("That resident type does not exist " + agent.type); } diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js index 94bb406..bde88dc 100644 --- a/src/people/nurse-thesis.js +++ b/src/people/nurse-thesis.js @@ -1,6 +1,7 @@ +import AssignComputer from "../behavior/assign-computer.js" import GoTo from "../behavior/go-to.js"; import GoToLazy from "../behavior/go-to-lazy.js"; -import AssignComputer from "../behavior/assign-computer.js" +import PatientTempState from "../../support/patient-temp-state.js"; import TakeTime from "../behavior/take-time.js"; import task from "../support/task-thesis.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" @@ -78,7 +79,7 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) - // THIS TASK IS GIVEN BY ?? (probably tech that escorts patient back from CT) + // THIS TASK IS GIVEN BY THE RESIDENT .do("Nurse Discharge Patient", (t) => { if (me().getTask().taskID != "Nurse Discharge Patient") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; @@ -86,19 +87,24 @@ class nurseThesis { else { let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().Task.patient, null); Hospital.nurseTaskList.push(exitTask); - // Could just change task to escorting to exit immediately - //me().Task(null); + me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) - // THIS TASK IS GIVEN BY THE PREVIOUS TASK - // need to code this still + // THIS TASK IS GIVEN BY NURSE DISCHARGE PATIENT + // need to add more to this .do("Nurse Escort Patient To Exit", (t) => { if (me().getTask().taskID != "Nurse Escort Patient To Exit") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - + let myPatient = me().getTask().patient; + myPatient.setPatientTempState(PatientTempState.DONE); + for (let i = 0; i < Hospital.emergencyQueue.length; i++) { + if (myPatient == Hospital.emergencyQueue[i]) { + Hospital.emergencyQueue.splice(i, 1); + } + } me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } diff --git a/src/people/resident-thesis.js b/src/people/resident-thesis.js new file mode 100644 index 0000000..c893d43 --- /dev/null +++ b/src/people/resident-thesis.js @@ -0,0 +1,220 @@ +import AssignBed from "../behavior/assign-bed.js"; +import AssignComputer from "../behavior/assign-computer.js" +import GoTo from "../behavior/go-to.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; +import TakeTime from "../behavior/take-time.js"; +import task from "../support/task-thesis.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + +class residentThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + this.toReturn = null; + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + + let goToName = "ResidentStart"; + let myGoal = Hospital.locations.find(l => l.name == goToName); + let computer = Hospital.locations.find(l => l.name == "ResidentStart"); + this.tree = builder + + // Consider limiting the rooms nurses can be assigned to tasks to + // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART + .sequence("Resident Behaviors") + .splice(new GoTo(self.index, computer.location).tree) + //.splice(new AssignBed(myIndex, Hospital.locations.find(l => l.name == "C1").location).tree) + .splice(new AssignComputer(myIndex, computer.location).tree) // RESIDENT PLACE + // Add a behavior here or in the selector that will order the tasks (by severity)? + .selector("Task List Tasks") + .do("Get a Task", (t) => { + // IF ALREADY ALLOCATED A TASK, CONTINUE + if (me().getTask() != null) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // CHECK IF ANY TASKS ARE AVAILABLE, CONTINUE + else if (Hospital.residentTaskList.length != 0) { + me().setTask(Hospital.residentTaskList.shift()); + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // OTHERWISE DON'T PROCEED (SUCCESS WILL RESTART SELECTOR) + else { + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // I think it has to be done this way because you can't do operations in a splice for the most part + .inverter("Need to return failure") + .sequence("Go to Task") + .do("Determine Location", (t) => { + if (me().getTask().location != null) { + myGoal = me().getTask().location; + } + else { + myGoal = computer; + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // GoTo gives me problems sometimes that GoToLazy does not + .splice(new GoToLazy(self.index, () => myGoal.location).tree) + .end() + .end() + + // .do("Clock In / Clock Out", (t) => { + // Could make this a spliced behavior that takes the agent as a parameter + //return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) + + // THIS TASK IS GIVEN BY THE TECH + .do("EKG Read", (t) => { + if (me().getTask().taskID != "EKG Read") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let consultTask = new task("EKG Consult", null, null, me().Task.patient, null); + Hospital.residentTaskList.push(consultTask); + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // THIS TASK IS GIVEN BY EKG READ + .do("EKG Consult", (t) => { + if (me().getTask().taskID != "EKG Consult") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + // queue CAT or XRAY + let catTask = new task("EKG Order CAT", null, null, me().Task.patient, null); + Hospital.residentTaskList.push(catTask); + + //let xrayTask = new task("EKG Order XRay", null, null, me().Task.patient, null); + //Hospital.residentTaskList.push(xrayTask); + + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // THIS TASK IS GIVEN BY EKG CONSULT + .do("EKG Order XRay", (t) => { + if (me().getTask().taskID != "EKG Order XRay") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let myPatient = me().getTask().patient; + // if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() != "ESI1") { + // Hospital.CTQueue.unshift(myPatient); + // } + // else if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() == "ESI1") { + // let i = 0; + // while (i < Hospital.CTQueue.length && Hospital.CTQueue[i].getSeverity() == "ESI1") { + // i++; + // } + + // if (i == Hospital.CTQueue.length) { + // Hospital.CTQueue.push(myPatient); + // } + // else { + // Hospital.CTQueue.splice(i, 0, myPatient); + // } + // } + //else { + Hospital.XRayQueue.push(myPatient); + //} + + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // THIS TASK IS GIVEN BY EKG CONSULT + .do("EKG Order CAT", (t) => { + if (me().getTask().taskID != "EKG Order CAT") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let myPatient = me().getTask().patient; + if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() != "ESI1") { + Hospital.CTQueue.unshift(myPatient); + } + else if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() == "ESI1") { + let i = 0; + while (i < Hospital.CTQueue.length && Hospital.CTQueue[i].getSeverity() == "ESI1") { + i++; + } + + if (i == Hospital.CTQueue.length) { + Hospital.CTQueue.push(myPatient); + } + else { + Hospital.CTQueue.splice(i, 0, myPatient); + } + } + else { + Hospital.CTQueue.push(myPatient); + } + + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // THIS TASK IS GIVEN BY THE RADIOLOGIST + .do("Scan Read", (t) => { + if (me().getTask().taskID != "Scan Read") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let attendingConsultTask = new task("Attending Consult", null, null, me().Task.patient, null); + Hospital.residentTaskList.push(attendingConsultTask); + + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // THIS TASK IS GIVEN BY SCAN READ + .do("Attending Consult", (t) => { + if (me().getTask().taskID != "Attending Consult") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let patientConsultTask = new task("Patient Consult", null, null, me().Task.patient, null); + Hospital.residentTaskList.push(patientConsultTask); + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // THIS TASK IS GIVEN BY ATTENDING CONSULT + .do("Patient Consult", (t) => { + if (me().getTask().taskID != "Patient Consult") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let dischargeTask = new task("Nurse Discharge Patient", null, null, me().Task.patient, null); + Hospital.nurseTaskList.push(dischargeTask); + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + .end() + // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK + // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. + //.splice(new TakeTime(1000, 2000).tree) + .do("Take Time", (t) => { + while (me().taskTime > 0) + { + me().taskTime == me().taskTime--; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + .build() + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } +} + +export default residentThesis; \ No newline at end of file diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js index 3004259..ba30df8 100644 --- a/src/people/tech-thesis.js +++ b/src/people/tech-thesis.js @@ -69,55 +69,45 @@ class techThesis { // THIS TASK IS GIVEN BY THE TRIAGE NURSE .do("Get Vitals", (t) => { - Hospital.computer.getEntry(me().getTask().patient).setVitals("Taken"); - me().setTask(null); - return fluentBehaviorTree.BehaviorTreeStatus.Success; + if (me().getTask().taskID != "Get Vitals") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + Hospital.computer.getEntry(me().getTask().patient).setVitals("Taken"); + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } }) + // THIS TASK IS GIVEN BY THE TRIAGE NURSE .do("Get EKG", (t) => { - Hospital.computer.getEntry(me().getTask().patient).setEkg("EKG Results"); - me().setTask(null); - // CREATE TASK FOR THE RESIDENT : RESIDENT_EKG_READ - return fluentBehaviorTree.BehaviorTreeStatus.Success; + if (me().getTask().taskID != "Get EKG") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + Hospital.computer.getEntry(me().getTask().patient).setEkg("EKG Results"); + me().setTask(null); + // CREATE TASK FOR THE RESIDENT : RESIDENT_EKG_READ + let readTask = new task("EKG Read", null, null, me().Task.patient, null); + Hospital.residentTaskList.push(readTask); + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } }) + // THIS TASK IS GIVEN BY THE CT .do("CT Pickup", (t) => { - + // ??? return fluentBehaviorTree.BehaviorTreeStatus.Success; }) + // THIS TASK IS GIVEN BY THE XRAY .do("XRay Pickup", (t) => { - + // ??? return fluentBehaviorTree.BehaviorTreeStatus.Success; }) + // ESCORTING TO XRAY / CT NEEDS TO BE QUEUED UP SOMEWHERE ... .do("Escort Patient", (t) => { - + // ??? return fluentBehaviorTree.BehaviorTreeStatus.Success; }) - - // // THIS TASK IS GIVEN BY THE TRIAGE NURSE - // .do("Get Health Information", (t) => { - // if (me().getTask().taskID != "Get Health Information") { - // return fluentBehaviorTree.BehaviorTreeStatus.Failure; - // } - // else { - // let patientEntry = Hospital.computer.getEntry(me().getTask().patient); - // patientEntry.setAnsweredQuestions(true); - // me().setTask(null); - // me().taskTime = 100; - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // } - // }) - // // THIS TASK IS GIVEN BY ?? (probably tech that escorts patient back from CT) - // .do("Nurse Discharge Patient", (t) => { - // if (me().getTask().taskID != "Nurse Discharge Patient") { - // return fluentBehaviorTree.BehaviorTreeStatus.Failure; - // } - // else { - // let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().Task.patient, null); - // Hospital.nurseTaskList.push(exitTask); - // // Could just change task to escorting to exit immediately - // //me().Task(null); - // return fluentBehaviorTree.BehaviorTreeStatus.Success; - // } - // }) .end() // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. diff --git a/src/support/hospital.js b/src/support/hospital.js index 835a00e..226177b 100644 --- a/src/support/hospital.js +++ b/src/support/hospital.js @@ -45,6 +45,7 @@ class Hospital{ static janitorTaskList = []; static nurseTaskList = []; static techTaskList = []; + static residentTaskList = []; static getFPS(){return 60;} From 68bd4fe69cf2d1b37810a1ce722c298672f4d6f2 Mon Sep 17 00:00:00 2001 From: Narducky Date: Thu, 13 Jan 2022 12:47:38 -0600 Subject: [PATCH 08/42] Got CT set up, Radiology next CT is set up, xray can be easily copied from there. Radiology is also simple and should be easily done. Some thought/work needs to be put into setting up the escort behaviors, but that shouldn't be too difficult either. --- src/people/ct-thesis.js | 129 +++++++++++++++++++++++++++++++++ src/people/radiology-thesis.js | 0 src/people/tech-thesis.js | 29 ++++++-- src/support/hospital.js | 3 + thesis-notes.md | 7 ++ 5 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 src/people/ct-thesis.js create mode 100644 src/people/radiology-thesis.js diff --git a/src/people/ct-thesis.js b/src/people/ct-thesis.js new file mode 100644 index 0000000..22b7f4c --- /dev/null +++ b/src/people/ct-thesis.js @@ -0,0 +1,129 @@ +import AssignBed from "../behavior/assign-bed.js"; +import AssignComputer from "../behavior/assign-computer.js" +import GoTo from "../behavior/go-to.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; +import TakeTime from "../behavior/take-time.js"; +import task from "../support/task-thesis.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + +class ctThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + this.toReturn = null; + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + + let goToName = "CT 1"; + if (myIndex % 2 == 1) { + goToName = "CT 2"; + } + + let myGoal = Hospital.locations.find(l => l.name == goToName); + if (!myGoal) throw new exception("We couldn't find a location called " + goToName); + + + this.tree = builder + + // Consider limiting the rooms nurses can be assigned to tasks to + // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART + .sequence("CT Behaviors") + .splice(new GoTo(self.index, myGoal.location).tree) + + .splice(new AssignComputer(myIndex, myGoal.location).tree) // RESIDENT PLACE + // Add a behavior here or in the selector that will order the tasks (by severity)? + .selector("Task List Tasks") + .do("Get a Task", (t) => { + // IF ALREADY ALLOCATED A TASK, CONTINUE + if (me().getTask() != null) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // CHECK IF ANY TASKS ARE AVAILABLE, CONTINUE + else if (Hospital.ctTaskList.length != 0) { + me().setTask(Hospital.ctTaskList.shift()); + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // OTHERWISE DON'T PROCEED (SUCCESS WILL RESTART SELECTOR) + else { + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // I think it has to be done this way because you can't do operations in a splice for the most part + .inverter("Need to return failure") + .sequence("Go to Task") + .do("Determine Location", (t) => { + if (me().getTask().location != null) { + myGoal = me().getTask().location; + } + else { + myGoal = computer; + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // GoTo gives me problems sometimes that GoToLazy does not + .splice(new GoToLazy(self.index, () => myGoal.location).tree) + .end() + .end() + + // .do("Clock In / Clock Out", (t) => { + // Could make this a spliced behavior that takes the agent as a parameter + //return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) + + // THIS TASK IS GIVEN BY THE CT TO THE TECH + .do("Queue Escort Patient", (t) => { + if (Hospital.CTQueue.length == 0 || (goToName == "CT 1" && Hospital.isCT1Occupied()) || (goToName == "CT 2" && Hospital.isCT2Occupied())) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + // Escort Patient + let techEscortTask = new task("Escort Patient", null, null, Hospital.CTQueue[0], null); + Hospital.techTaskList.push(techEscortTask); + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + + // THIS TASK IS GIVEN BY THE TECH + .do("CAT Do Scan", (t) => { + if (me().getTask().taskID != "CAT Do Scan") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let ctPickupTask = new task("CT Pickup", null, null, me().Task.patient, null); + Hospital.techTaskList.push(ctPickupTask); + + let radiologyReviewTask = new task("Radiology Review Scan", null, null, me().Task.patient, null); + Hospital.radiologyTaskList.push(radiologyReviewTask); + + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + + .end() + // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK + // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. + //.splice(new TakeTime(1000, 2000).tree) + .do("Take Time", (t) => { + while (me().taskTime > 0) + { + me().taskTime == me().taskTime--; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + .build() + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } +} + +export default ctThesis; \ No newline at end of file diff --git a/src/people/radiology-thesis.js b/src/people/radiology-thesis.js new file mode 100644 index 0000000..e69de29 diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js index ba30df8..1feb5bd 100644 --- a/src/people/tech-thesis.js +++ b/src/people/tech-thesis.js @@ -90,6 +90,28 @@ class techThesis { let readTask = new task("EKG Read", null, null, me().Task.patient, null); Hospital.residentTaskList.push(readTask); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // ESCORTING TO XRAY / CT NEEDS TO BE QUEUED UP SOMEWHERE ... probably queue it from the XRAY / CT when they are ready to receive the patient + .do("Escort Patient", (t) => { + if (me().getTask().taskID != "Escort Patient") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + //me().setDestination(transportResponsibility.getRoom().getLocation()); + //patient.setInstructor(me()); + //patient.setPatientTempState( PatientTempState.FOLLOWING); + + // CT SCAN + let ctScanTask = new task("CAT Do Scan", null, null, me().Task.patient, null); + Hospital.ctTaskList.push(ctScanTask); + + // XRAY + //let xrayScanTask = new task("XRay Do Scan", null, null, me().Task.patient, null); + //Hospital.xrayTaskList.push(xrayScanTask); + + me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) @@ -102,12 +124,7 @@ class techThesis { .do("XRay Pickup", (t) => { // ??? return fluentBehaviorTree.BehaviorTreeStatus.Success; - }) - // ESCORTING TO XRAY / CT NEEDS TO BE QUEUED UP SOMEWHERE ... - .do("Escort Patient", (t) => { - // ??? - return fluentBehaviorTree.BehaviorTreeStatus.Success; - }) + }) .end() // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. diff --git a/src/support/hospital.js b/src/support/hospital.js index 226177b..78e86cd 100644 --- a/src/support/hospital.js +++ b/src/support/hospital.js @@ -46,6 +46,9 @@ class Hospital{ static nurseTaskList = []; static techTaskList = []; static residentTaskList = []; + static ctTaskList = []; + static xrayTaskList = []; + static radiologyTaskList = []; static getFPS(){return 60;} diff --git a/thesis-notes.md b/thesis-notes.md index 90c0318..7f97e77 100644 --- a/thesis-notes.md +++ b/thesis-notes.md @@ -16,3 +16,10 @@ The basis of these code changes boil down to this: - probably should make a flow chart (could include it in thesis as well) that illustrates the flow of tasks greeter --assigns--> triage --assigns--> nurse / tech? / ? --> + - need to figure out what tasks require agents to actually go to location (need to pass in null otherwise) + - need to set up transport behaviors + +# To Do + - three versions of the hospital: actual hospital, like the actual hospital, and the minimal viable end product + - shouldn't be too much of an issue, i believe the json files with the location flags are really the most important things and minimally needed things (aside from the walls) + From ddfb7ba07613e5d0e92a734723174a9ecdd4d19e Mon Sep 17 00:00:00 2001 From: Narducky Date: Thu, 20 Jan 2022 12:45:30 -0600 Subject: [PATCH 09/42] Got Transport Behaviors Set Up Need to set up phlebotomist and pharmacist. Then need to bug fix everything. --- src/people/ct-thesis.js | 8 +- src/people/medical-agent-thesis.js | 18 ++-- src/people/radiology-thesis.js | 106 ++++++++++++++++++++++++ src/people/resident-thesis.js | 4 +- src/people/tech-thesis.js | 73 +++++++++++----- src/people/xray-thesis.js | 129 +++++++++++++++++++++++++++++ 6 files changed, 301 insertions(+), 37 deletions(-) create mode 100644 src/people/xray-thesis.js diff --git a/src/people/ct-thesis.js b/src/people/ct-thesis.js index 22b7f4c..d8d827e 100644 --- a/src/people/ct-thesis.js +++ b/src/people/ct-thesis.js @@ -79,8 +79,8 @@ class ctThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - // Escort Patient - let techEscortTask = new task("Escort Patient", null, null, Hospital.CTQueue[0], null); + // Pick Up Patient + let techEscortTask = new task("Pick Up Patient", Hospital.CTQueue[0].getSeverity(), 0, Hospital.CTQueue[0], myGoal); Hospital.techTaskList.push(techEscortTask); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -93,10 +93,10 @@ class ctThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let ctPickupTask = new task("CT Pickup", null, null, me().Task.patient, null); + let ctPickupTask = new task("CT Pickup", null, 0, me().Task.patient, myGoal); Hospital.techTaskList.push(ctPickupTask); - let radiologyReviewTask = new task("Radiology Review Scan", null, null, me().Task.patient, null); + let radiologyReviewTask = new task("Radiology Review Scan", null, 0, me().Task.patient, null); Hospital.radiologyTaskList.push(radiologyReviewTask); me().setTask(null); diff --git a/src/people/medical-agent-thesis.js b/src/people/medical-agent-thesis.js index cfec127..4f57f17 100644 --- a/src/people/medical-agent-thesis.js +++ b/src/people/medical-agent-thesis.js @@ -24,6 +24,9 @@ import triageNurseThesis from "./triage-nurse-thesis.js"; import janitorialThesis from "./janitorial-thesis.js"; import techThesis from "./tech-thesis.js"; import residentThesis from "./resident-thesis.js"; +import ctThesis from "./ct-thesis.js"; +import xrayThesis from "./xray-thesis.js"; +import radiologyThesis from "./radiology-thesis.js"; class MedicalAgentThesis extends AMedicalStaff { startX; @@ -73,32 +76,28 @@ class MedicalAgentThesis extends AMedicalStaff { if (agent.name == "Tech") { if (agent.type == "Tech") - //this.behavior = new tech(agent.id) this.behavior = new techThesis(agent.id) else if (agent.type == "CT") - this.behavior = new ct(agent.id) + this.behavior = new ctThesis(agent.id) else if (agent.type == "Janitorial") - //this.behavior = new janitorial(agent.id) this.behavior = new janitorialThesis(agent.id) else if (agent.type == "Phlebotomist") this.behavior = new phlebotomist(agent.id) + // NEED TO ADD THIS else if (agent.type == "Radiology") - this.behavior = new radiology(agent.id) + this.behavior = new radiologyThesis(agent.id) else if (agent.type == "XRay") - this.behavior = new xray(agent.id) + this.behavior = new xrayThesis(agent.id) else throw new Exception("That tech type does not exist " + agent.type); } else if (agent.name == "Nurse") { if (agent.type == "Triage Nurse") - //this.behavior = new triageNurse(agent.id) this.behavior = new triageNurseThesis(agent.id) else if (agent.type == "Nurse") - //this.behavior = new nurse(agent.id) this.behavior = new nurseThesis(agent.id) else if (agent.type == "Greeter Nurse") - //this.behavior = new greeterNurse(agent.id) this.behavior = new greeterNurseThesis(agent.id) else throw new Exception("That nurse type does not exist " + agent.type); @@ -106,12 +105,12 @@ class MedicalAgentThesis extends AMedicalStaff { else if (agent.name == "Attending") { if (agent.type == "Attending") this.behavior = new attending(agent.id) + // NOT ENOUGH FUNCTIONALITY TO CHANGE else throw new "That attending type does not exist " + agent.type; } else if (agent.name == "Resident") { if (agent.type == "Resident") - //this.behavior = new resident(agent.id) this.behavior = new residentThesis(agent.id) else throw new Exception("That resident type does not exist " + agent.type); @@ -119,6 +118,7 @@ class MedicalAgentThesis extends AMedicalStaff { else if (agent.name == "Pharmacist") { if (agent.type == "Pharmacist") this.behavior = new pharmacist(agent.id) + // NEED TO ADD THIS else throw new Exception("That pharmacist type does not exist " + agent.type); } diff --git a/src/people/radiology-thesis.js b/src/people/radiology-thesis.js index e69de29..cdb2072 100644 --- a/src/people/radiology-thesis.js +++ b/src/people/radiology-thesis.js @@ -0,0 +1,106 @@ +import AssignBed from "../behavior/assign-bed.js"; +import AssignComputer from "../behavior/assign-computer.js" +import GoTo from "../behavior/go-to.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; +import TakeTime from "../behavior/take-time.js"; +import task from "../support/task-thesis.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + +class radiologyThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + this.toReturn = null; + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + + let goToName = "CT 2"; + let myGoal = Hospital.locations.find(l => l.name == goToName); + + + this.tree = builder + + // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART + .sequence("Radiology Behaviors") + .splice(new GoTo(self.index, myGoal.location).tree) + //.splice(new AssignBed(myIndex, Hospital.locations.find(l => l.name == "C1").location).tree) + .splice(new AssignComputer(myIndex, myGoal.location).tree) // CT 2 + // Add a behavior here or in the selector that will order the tasks (by severity)? + .selector("Task List Tasks") + .do("Get a Task", (t) => { + // IF ALREADY ALLOCATED A TASK, CONTINUE + if (me().getTask() != null) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // CHECK IF ANY TASKS ARE AVAILABLE, CONTINUE + else if (Hospital.radiologyTaskList.length != 0) { + me().setTask(Hospital.radiologyTaskList.shift()); + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // OTHERWISE DON'T PROCEED (SUCCESS WILL RESTART SELECTOR) + else { + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // I think it has to be done this way because you can't do operations in a splice for the most part + .inverter("Need to return failure") + .sequence("Go to Task") + .do("Determine Location", (t) => { + if (me().getTask().location != null) { + myGoal = me().getTask().location; + } + else { + myGoal = computer; + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // GoTo gives me problems sometimes that GoToLazy does not + .splice(new GoToLazy(self.index, () => myGoal.location).tree) + .end() + .end() + + // .do("Clock In / Clock Out", (t) => { + // Could make this a spliced behavior that takes the agent as a parameter + //return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) + + // THIS TASK IS GIVEN BY THE CT (CAT Do Scan Behavior) + .do("Radiology Review Scan", (t) => { + if (me().getTask().taskID != "Radiology Review Scan") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let residentScanTask = new task("Resident Scan Read", null, null, me().Task.patient, null); + Hospital.residentTaskList.push(residentScanTask); + + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + + .end() + // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK + // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. + //.splice(new TakeTime(1000, 2000).tree) + .do("Take Time", (t) => { + while (me().taskTime > 0) + { + me().taskTime == me().taskTime--; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + .build() + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } +} + +export default radiologyThesis; \ No newline at end of file diff --git a/src/people/resident-thesis.js b/src/people/resident-thesis.js index c893d43..9d05bc5 100644 --- a/src/people/resident-thesis.js +++ b/src/people/resident-thesis.js @@ -159,8 +159,8 @@ class residentThesis { } }) // THIS TASK IS GIVEN BY THE RADIOLOGIST - .do("Scan Read", (t) => { - if (me().getTask().taskID != "Scan Read") { + .do("Resident Scan Read", (t) => { + if (me().getTask().taskID != "Resident Scan Read") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js index 1feb5bd..3f79f85 100644 --- a/src/people/tech-thesis.js +++ b/src/people/tech-thesis.js @@ -93,37 +93,66 @@ class techThesis { return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) - // ESCORTING TO XRAY / CT NEEDS TO BE QUEUED UP SOMEWHERE ... probably queue it from the XRAY / CT when they are ready to receive the patient - .do("Escort Patient", (t) => { - if (me().getTask().taskID != "Escort Patient") { + // ESCORTING TO XRAY / CT IS QUEUED BY THE CT AND XRAY + // THIS IS A 2-PART TASK, THEY GO TO THE PATIENT, THEN THEY ESCORT THE PATIENT TO THE CT OR XRAY + .do("Pick Up Patient", (t) => { + if (me().getTask().taskID != "Pick Up Patient") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - //me().setDestination(transportResponsibility.getRoom().getLocation()); - //patient.setInstructor(me()); - //patient.setPatientTempState( PatientTempState.FOLLOWING); + let myPatient = me().Task.patient; + myPatient.setInstructor(me()); + myPatient.setPatientTempState( PatientTempState.FOLLOWING); - // CT SCAN - let ctScanTask = new task("CAT Do Scan", null, null, me().Task.patient, null); - Hospital.ctTaskList.push(ctScanTask); + // NEED TO FIGURE OUT WHEN THEY WOULD GET ONE OVER THE OTHER + if (true) { + // CT SCAN + let ctScanTask = new task("CAT Do Scan", null, 0, me().Task.patient, null); + Hospital.ctTaskList.push(ctScanTask); - // XRAY - //let xrayScanTask = new task("XRay Do Scan", null, null, me().Task.patient, null); - //Hospital.xrayTaskList.push(xrayScanTask); + // NOW ESCORT THE PATIENT + let escortTask = new task("Escort Patient", null, 0, me().Task.patient, me().Task.location); + me().setTask(escortTask); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + else { + // XRAY + let xrayScanTask = new task("XRay Do Scan", null, 0, me().Task.patient, null); + Hospital.xrayTaskList.push(xrayScanTask); + + // NOW ESCORT THE PATIENT + let escortTask = new task("Escort Patient", null, 0, me().Task.patient, me().Task.location); + me().setTask(escortTask); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + } + }) + .do("Escort Patient", (t) => { + if (me().getTask().taskID != "Escort Patient") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + patient.setInstructor(null); + patient.setPatientTempState(PatientTempState.WAITING); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } - }) - // THIS TASK IS GIVEN BY THE CT - .do("CT Pickup", (t) => { - // ??? - return fluentBehaviorTree.BehaviorTreeStatus.Success; - }) - // THIS TASK IS GIVEN BY THE XRAY - .do("XRay Pickup", (t) => { - // ??? - return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + + // THIS TASK IS GIVEN BY THE CT / XRAY + .do("CT/XRAY Pickup", (t) => { + if (me().getTask().taskID != "CT Pickup" && me().getTask().taskID != "XRay Pickup") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + patient.setInstructor(me()); + patient.setPatientTempState(PatientTempState.FOLLOWING); + + let escortTask = new task("Escort Patient", null, 0, me().Task.patient, me().Task.patient.getPermanentRoom()); + me().setTask(escortTask); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } }) .end() // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK diff --git a/src/people/xray-thesis.js b/src/people/xray-thesis.js new file mode 100644 index 0000000..2c7457c --- /dev/null +++ b/src/people/xray-thesis.js @@ -0,0 +1,129 @@ +import AssignBed from "../behavior/assign-bed.js"; +import AssignComputer from "../behavior/assign-computer.js" +import GoTo from "../behavior/go-to.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; +import TakeTime from "../behavior/take-time.js"; +import task from "../support/task-thesis.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + +class xrayThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + this.toReturn = null; + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + + let goToName = "XRay 1"; + if (myIndex == 17) { + goToName = "XRay 2"; + } + + let myGoal = Hospital.locations.find(l => l.name == goToName); + if (!myGoal) throw new exception("We couldn't find a location called " + goToName); + + + this.tree = builder + + // Consider limiting the rooms nurses can be assigned to tasks to + // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART + .sequence("XRay Behaviors") + .splice(new GoTo(self.index, myGoal.location).tree) + + .splice(new AssignComputer(myIndex, myGoal.location).tree) // RESIDENT PLACE + // Add a behavior here or in the selector that will order the tasks (by severity)? + .selector("Task List Tasks") + .do("Get a Task", (t) => { + // IF ALREADY ALLOCATED A TASK, CONTINUE + if (me().getTask() != null) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // CHECK IF ANY TASKS ARE AVAILABLE, CONTINUE + else if (Hospital.ctTaskList.length != 0) { + me().setTask(Hospital.ctTaskList.shift()); + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // OTHERWISE DON'T PROCEED (SUCCESS WILL RESTART SELECTOR) + else { + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // I think it has to be done this way because you can't do operations in a splice for the most part + .inverter("Need to return failure") + .sequence("Go to Task") + .do("Determine Location", (t) => { + if (me().getTask().location != null) { + myGoal = me().getTask().location; + } + else { + myGoal = computer; + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // GoTo gives me problems sometimes that GoToLazy does not + .splice(new GoToLazy(self.index, () => myGoal.location).tree) + .end() + .end() + + // .do("Clock In / Clock Out", (t) => { + // Could make this a spliced behavior that takes the agent as a parameter + //return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) + + // THIS TASK IS GIVEN BY THE XRAY TO THE TECH + .do("Queue Escort Patient", (t) => { + if (Hospital.XRayQueue.length == 0 || (goToName == "XRay 1" && Hospital.isXRay1Occupied()) || (goToName == "XRay 2" && Hospital.isXRay2Occupied())) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + // Escort Patient + let techEscortTask = new task("Escort Patient", null, null, Hospital.XRayQueue[0], null); + Hospital.techTaskList.push(techEscortTask); + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + + // THIS TASK IS GIVEN BY THE TECH + .do("XRay Do Scan", (t) => { + if (me().getTask().taskID != "XRay Do Scan") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let xrayPickupTask = new task("XRay Pickup", null, null, me().Task.patient, null); + Hospital.techTaskList.push(xrayPickupTask); + + let radiologyReviewTask = new task("Radiology Review Scan", null, null, me().Task.patient, null); + Hospital.radiologyTaskList.push(radiologyReviewTask); + + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + + .end() + // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK + // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. + //.splice(new TakeTime(1000, 2000).tree) + .do("Take Time", (t) => { + while (me().taskTime > 0) + { + me().taskTime == me().taskTime--; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + .build() + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } +} + +export default xrayThesis; \ No newline at end of file From 97416d5915a429269ab7a43cb8b4d6f0520e261c Mon Sep 17 00:00:00 2001 From: Narducky Date: Tue, 25 Jan 2022 15:24:11 -0600 Subject: [PATCH 10/42] Bug fixing Need to fix bug with CT and XRay queue being double assigned in CT-thesis and follow-instructions. --- src/people/attending-thesis.js | 42 ++++++++++++ src/people/ct-thesis.js | 36 +++++----- src/people/medical-agent-thesis.js | 29 ++------ src/people/nurse-thesis.js | 4 +- src/people/pharmacist-thesis.js | 38 +++++++++++ src/people/phlebotomist-thesis.js | 104 +++++++++++++++++++++++++++++ src/people/radiology-thesis.js | 4 +- src/people/resident-thesis.js | 12 ++-- src/people/tech-thesis.js | 32 +++++---- src/people/xray-thesis.js | 50 +++++++------- src/support/hospital.js | 4 ++ 11 files changed, 267 insertions(+), 88 deletions(-) create mode 100644 src/people/attending-thesis.js create mode 100644 src/people/pharmacist-thesis.js create mode 100644 src/people/phlebotomist-thesis.js diff --git a/src/people/attending-thesis.js b/src/people/attending-thesis.js new file mode 100644 index 0000000..5f21940 --- /dev/null +++ b/src/people/attending-thesis.js @@ -0,0 +1,42 @@ +import GoTo from "../behavior/go-to.js" +import WaitForever from "../behavior/wait-forever.js" +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + + + +class attendingThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + let myGoal = Hospital.locations.find(l => l.name == "B Desk"); + if (!myGoal) throw new Exception("We couldn't find a location called B Desk"); + + this.goTo = new GoTo(self.index, myGoal.location); + + // attending doctor's behavior is probably to just check in with patients before they are escorted out of the hospital? + + // shadow interns + // consult with patients with the resident + // consult with the other agents in the hospital to make sure everything is going okay + this.tree = builder + .sequence("Attending Tree") + .splice(this.goTo.tree) + .splice(new WaitForever(myIndex).tree) + + .end() + .build(); + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } + +} + +export default attendingThesis; \ No newline at end of file diff --git a/src/people/ct-thesis.js b/src/people/ct-thesis.js index d8d827e..7f2a716 100644 --- a/src/people/ct-thesis.js +++ b/src/people/ct-thesis.js @@ -36,6 +36,22 @@ class ctThesis { .splice(new AssignComputer(myIndex, myGoal.location).tree) // RESIDENT PLACE // Add a behavior here or in the selector that will order the tasks (by severity)? .selector("Task List Tasks") + // THIS TASK IS GIVEN BY THE CT TO THE TECH + .do("Queue Escort Patient", (t) => { + if (Hospital.CTQueue.length == 0 || (goToName == "CT 1" && Hospital.isCT1Occupied()) || (goToName == "CT 2" && Hospital.isCT2Occupied())) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + // Pick Up Patient + let techEscortTask = new task("Pick Up Patient", Hospital.CTQueue[0].getSeverity(), 0, Hospital.CTQueue[0], myGoal); + Hospital.techTaskList.push(techEscortTask); + + //return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + }) + .do("Get a Task", (t) => { // IF ALREADY ALLOCATED A TASK, CONTINUE if (me().getTask() != null) { @@ -59,7 +75,7 @@ class ctThesis { myGoal = me().getTask().location; } else { - myGoal = computer; + myGoal = Hospital.locations.find(l => l.name == goToName); } return fluentBehaviorTree.BehaviorTreeStatus.Success; }) @@ -73,30 +89,16 @@ class ctThesis { //return fluentBehaviorTree.BehaviorTreeStatus.Success; // }) - // THIS TASK IS GIVEN BY THE CT TO THE TECH - .do("Queue Escort Patient", (t) => { - if (Hospital.CTQueue.length == 0 || (goToName == "CT 1" && Hospital.isCT1Occupied()) || (goToName == "CT 2" && Hospital.isCT2Occupied())) { - return fluentBehaviorTree.BehaviorTreeStatus.Failure; - } - else { - // Pick Up Patient - let techEscortTask = new task("Pick Up Patient", Hospital.CTQueue[0].getSeverity(), 0, Hospital.CTQueue[0], myGoal); - Hospital.techTaskList.push(techEscortTask); - - return fluentBehaviorTree.BehaviorTreeStatus.Success; - } - }) - // THIS TASK IS GIVEN BY THE TECH .do("CAT Do Scan", (t) => { if (me().getTask().taskID != "CAT Do Scan") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let ctPickupTask = new task("CT Pickup", null, 0, me().Task.patient, myGoal); + let ctPickupTask = new task("CT Pickup", null, 0, me().getTask().patient, myGoal); Hospital.techTaskList.push(ctPickupTask); - let radiologyReviewTask = new task("Radiology Review Scan", null, 0, me().Task.patient, null); + let radiologyReviewTask = new task("Radiology Review Scan", null, 0, me().getTask().patient, null); Hospital.radiologyTaskList.push(radiologyReviewTask); me().setTask(null); diff --git a/src/people/medical-agent-thesis.js b/src/people/medical-agent-thesis.js index 4f57f17..d7d3d3c 100644 --- a/src/people/medical-agent-thesis.js +++ b/src/people/medical-agent-thesis.js @@ -1,22 +1,5 @@ - -import BackAndForth from "../behavior/back-and-forth.js"; -import None from "../behavior/none.js" -import Agent from "./agent.js" import AMedicalStaff from "./amedical-staff.js"; - -import attending from "./attending.js" -import ct from "./ct.js" import EscapePerson from "./escape-person.js"; -import greeterNurse from "./greeter-nurse.js" -import janitorial from "./janitorial.js" -import nurse from "./nurse.js" -import pharmacist from "./pharmacist.js" -import phlebotomist from "./phlebotomist.js" -import radiology from "./radiology.js" -import resident from "./resident.js" -import tech from "./tech.js" -import triageNurse from "./triage-nurse.js" -import xray from "./xray.js" import greeterNurseThesis from "./greeter-nurse-thesis.js"; import nurseThesis from "./nurse-thesis.js"; @@ -27,6 +10,9 @@ import residentThesis from "./resident-thesis.js"; import ctThesis from "./ct-thesis.js"; import xrayThesis from "./xray-thesis.js"; import radiologyThesis from "./radiology-thesis.js"; +import phlebotomistThesis from "./phlebotomist-thesis.js"; +import pharmacistThesis from "./pharmacist-thesis.js"; +import attendingThesis from "./attending-thesis.js"; class MedicalAgentThesis extends AMedicalStaff { startX; @@ -82,8 +68,7 @@ class MedicalAgentThesis extends AMedicalStaff { else if (agent.type == "Janitorial") this.behavior = new janitorialThesis(agent.id) else if (agent.type == "Phlebotomist") - this.behavior = new phlebotomist(agent.id) - // NEED TO ADD THIS + this.behavior = new phlebotomistThesis(agent.id) else if (agent.type == "Radiology") this.behavior = new radiologyThesis(agent.id) else if (agent.type == "XRay") @@ -104,8 +89,7 @@ class MedicalAgentThesis extends AMedicalStaff { } else if (agent.name == "Attending") { if (agent.type == "Attending") - this.behavior = new attending(agent.id) - // NOT ENOUGH FUNCTIONALITY TO CHANGE + this.behavior = new attendingThesis(agent.id) else throw new "That attending type does not exist " + agent.type; } @@ -117,8 +101,7 @@ class MedicalAgentThesis extends AMedicalStaff { } else if (agent.name == "Pharmacist") { if (agent.type == "Pharmacist") - this.behavior = new pharmacist(agent.id) - // NEED TO ADD THIS + this.behavior = new pharmacistThesis(agent.id) else throw new Exception("That pharmacist type does not exist " + agent.type); } diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js index bde88dc..06958cf 100644 --- a/src/people/nurse-thesis.js +++ b/src/people/nurse-thesis.js @@ -1,7 +1,7 @@ import AssignComputer from "../behavior/assign-computer.js" import GoTo from "../behavior/go-to.js"; import GoToLazy from "../behavior/go-to-lazy.js"; -import PatientTempState from "../../support/patient-temp-state.js"; +import PatientTempState from "../support/patient-temp-state.js"; import TakeTime from "../behavior/take-time.js"; import task from "../support/task-thesis.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" @@ -85,7 +85,7 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().Task.patient, null); + let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().getTask().patient, null); Hospital.nurseTaskList.push(exitTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; diff --git a/src/people/pharmacist-thesis.js b/src/people/pharmacist-thesis.js new file mode 100644 index 0000000..82be7d4 --- /dev/null +++ b/src/people/pharmacist-thesis.js @@ -0,0 +1,38 @@ +import GoTo from "../behavior/go-to.js" +import WaitForever from "../behavior/wait-forever.js" +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + + + +class pharmacistThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + let myGoal = Hospital.locations.find(l => l.name == "Pharmacy"); + if (!myGoal) throw new Exception("We couldn't find a location called Pharmacy"); + + this.goTo = new GoTo(self.index, myGoal.location); + + + this.tree = builder + .sequence("Pharmacist Tree") + .splice(this.goTo.tree) + .splice(new WaitForever(myIndex).tree) + + .end() + .build(); + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } + +} + +export default pharmacistThesis; \ No newline at end of file diff --git a/src/people/phlebotomist-thesis.js b/src/people/phlebotomist-thesis.js new file mode 100644 index 0000000..4cb3746 --- /dev/null +++ b/src/people/phlebotomist-thesis.js @@ -0,0 +1,104 @@ +import AssignBed from "../behavior/assign-bed.js"; +import AssignComputer from "../behavior/assign-computer.js" +import GoTo from "../behavior/go-to.js"; +import GoToLazy from "../behavior/go-to-lazy.js"; +import TakeTime from "../behavior/take-time.js"; +import task from "../support/task-thesis.js"; +import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" + +class phlebotomistThesis { + + constructor(myIndex) { + this.index = myIndex; + + const builder = new fluentBehaviorTree.BehaviorTreeBuilder(); + this.toReturn = null; + + let self = this;//Since we need to reference this in anonymous functions, we need a reference + let me= ()=>Hospital.agents.find(a=>a.id == myIndex); + + let goToName = "Tech Start"; + let myGoal = Hospital.locations.find(l => l.name == goToName); + let computer = Hospital.locations.find(l => l.name == "Tech Start"); + this.tree = builder + + // Consider limiting the rooms nurses can be assigned to tasks to + // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART + .sequence("Phlebotomist Behaviors") + .splice(new GoTo(self.index, computer.location).tree) + //.splice(new AssignBed(myIndex, Hospital.locations.find(l => l.name == "C1").location).tree) + .splice(new AssignComputer(myIndex, computer.location).tree) // TECH PLACE + // Add a behavior here or in the selector that will order the tasks (by severity)? + .selector("Task List Tasks") + .do("Get a Task", (t) => { + // IF ALREADY ALLOCATED A TASK, CONTINUE + if (me().getTask() != null) { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // CHECK IF ANY TASKS ARE AVAILABLE, CONTINUE + else if (Hospital.phlebotomistTaskList.length != 0) { + me().setTask(Hospital.phlebotomistTaskList.shift()); + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + // OTHERWISE DON'T PROCEED (SUCCESS WILL RESTART SELECTOR) + else { + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // I think it has to be done this way because you can't do operations in a splice for the most part + .inverter("Need to return failure") + .sequence("Go to Task") + .do("Determine Location", (t) => { + if (me().getTask().location != null) { + myGoal = me().getTask().location; + } + else { + myGoal = computer; + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // GoTo gives me problems sometimes that GoToLazy does not + .splice(new GoToLazy(self.index, () => myGoal.location).tree) + .end() + .end() + + // .do("Clock In / Clock Out", (t) => { + // Could make this a spliced behavior that takes the agent as a parameter + //return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) + + // THIS TASK IS GIVEN BY ... + .do("Take Blood", (t) => { + if (me().getTask().taskID != "Take Blood") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + Hospital.computer.getEntry(me().getTask().patient).setPhlebotomist(me()); + Hospital.computer.getEntry(me().getTask().patient).setBlood("Drawn"); + me().setTask(null); + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + .end() + // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK + // TakeTime doesn't work in some instances, but the code itself works. For instance if you remove the next .end(), it will work, but then the sequence is broken. + //.splice(new TakeTime(1000, 2000).tree) + .do("Take Time", (t) => { + while (me().taskTime > 0) + { + me().taskTime == me().taskTime--; + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + .end() + .build() + } + + async update( crowd, msec) { + await this.tree.tick({ crowd, msec }) //Call the behavior tree + } +} + +export default phlebotomistThesis; \ No newline at end of file diff --git a/src/people/radiology-thesis.js b/src/people/radiology-thesis.js index cdb2072..c21ea91 100644 --- a/src/people/radiology-thesis.js +++ b/src/people/radiology-thesis.js @@ -53,7 +53,7 @@ class radiologyThesis { myGoal = me().getTask().location; } else { - myGoal = computer; + myGoal = Hospital.locations.find(l => l.name == goToName); } return fluentBehaviorTree.BehaviorTreeStatus.Success; }) @@ -73,7 +73,7 @@ class radiologyThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let residentScanTask = new task("Resident Scan Read", null, null, me().Task.patient, null); + let residentScanTask = new task("Resident Scan Read", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(residentScanTask); me().setTask(null); diff --git a/src/people/resident-thesis.js b/src/people/resident-thesis.js index 9d05bc5..f6ae82c 100644 --- a/src/people/resident-thesis.js +++ b/src/people/resident-thesis.js @@ -73,7 +73,7 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let consultTask = new task("EKG Consult", null, null, me().Task.patient, null); + let consultTask = new task("EKG Consult", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(consultTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -86,10 +86,10 @@ class residentThesis { } else { // queue CAT or XRAY - let catTask = new task("EKG Order CAT", null, null, me().Task.patient, null); + let catTask = new task("EKG Order CAT", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(catTask); - //let xrayTask = new task("EKG Order XRay", null, null, me().Task.patient, null); + //let xrayTask = new task("EKG Order XRay", null, null, me().getTask().patient, null); //Hospital.residentTaskList.push(xrayTask); me().setTask(null); @@ -164,7 +164,7 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let attendingConsultTask = new task("Attending Consult", null, null, me().Task.patient, null); + let attendingConsultTask = new task("Attending Consult", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(attendingConsultTask); me().setTask(null); @@ -177,7 +177,7 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let patientConsultTask = new task("Patient Consult", null, null, me().Task.patient, null); + let patientConsultTask = new task("Patient Consult", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(patientConsultTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -189,7 +189,7 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let dischargeTask = new task("Nurse Discharge Patient", null, null, me().Task.patient, null); + let dischargeTask = new task("Nurse Discharge Patient", null, null, me().getTask().patient, null); Hospital.nurseTaskList.push(dischargeTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js index 3f79f85..7851a75 100644 --- a/src/people/tech-thesis.js +++ b/src/people/tech-thesis.js @@ -4,6 +4,7 @@ import GoTo from "../behavior/go-to.js"; import GoToLazy from "../behavior/go-to-lazy.js"; import TakeTime from "../behavior/take-time.js"; import task from "../support/task-thesis.js"; +import PatientTempState from "../support/patient-temp-state.js"; import fluentBehaviorTree from "@crowdedjs/fluent-behavior-tree" class techThesis { @@ -49,7 +50,10 @@ class techThesis { .inverter("Need to return failure") .sequence("Go to Task") .do("Determine Location", (t) => { - if (me().getTask().location != null) { + if (me().getTask().taskID == "Pick Up Patient") { + myGoal = me().getTask().patient.getPermanentRoom(); + } + else if (me().getTask().location != null) { myGoal = me().getTask().location; } else { @@ -85,10 +89,10 @@ class techThesis { } else { Hospital.computer.getEntry(me().getTask().patient).setEkg("EKG Results"); - me().setTask(null); // CREATE TASK FOR THE RESIDENT : RESIDENT_EKG_READ - let readTask = new task("EKG Read", null, null, me().Task.patient, null); + let readTask = new task("EKG Read", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(readTask); + me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } @@ -100,28 +104,28 @@ class techThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - let myPatient = me().Task.patient; + let myPatient = me().getTask().patient; myPatient.setInstructor(me()); myPatient.setPatientTempState( PatientTempState.FOLLOWING); // NEED TO FIGURE OUT WHEN THEY WOULD GET ONE OVER THE OTHER if (true) { // CT SCAN - let ctScanTask = new task("CAT Do Scan", null, 0, me().Task.patient, null); + let ctScanTask = new task("CAT Do Scan", null, 0, me().getTask().patient, null); Hospital.ctTaskList.push(ctScanTask); // NOW ESCORT THE PATIENT - let escortTask = new task("Escort Patient", null, 0, me().Task.patient, me().Task.location); + let escortTask = new task("Escort Patient", null, 0, me().getTask().patient, me().getTask().location); me().setTask(escortTask); return fluentBehaviorTree.BehaviorTreeStatus.Success; } else { // XRAY - let xrayScanTask = new task("XRay Do Scan", null, 0, me().Task.patient, null); + let xrayScanTask = new task("XRay Do Scan", null, 0, me().getTask().patient, null); Hospital.xrayTaskList.push(xrayScanTask); // NOW ESCORT THE PATIENT - let escortTask = new task("Escort Patient", null, 0, me().Task.patient, me().Task.location); + let escortTask = new task("Escort Patient", null, 0, me().getTask().patient, me().getTask().location); me().setTask(escortTask); return fluentBehaviorTree.BehaviorTreeStatus.Success; } @@ -132,8 +136,9 @@ class techThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - patient.setInstructor(null); - patient.setPatientTempState(PatientTempState.WAITING); + let myPatient = me().getTask().patient; + myPatient.setInstructor(null); + myPatient.setPatientTempState(PatientTempState.WAITING); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -146,10 +151,11 @@ class techThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { - patient.setInstructor(me()); - patient.setPatientTempState(PatientTempState.FOLLOWING); + let myPatient = me().getTask().patient; + myPatient.setInstructor(me()); + myPatient.setPatientTempState(PatientTempState.FOLLOWING); - let escortTask = new task("Escort Patient", null, 0, me().Task.patient, me().Task.patient.getPermanentRoom()); + let escortTask = new task("Escort Patient", null, 0, me().getTask().patient, me().getTask().patient.getPermanentRoom()); me().setTask(escortTask); return fluentBehaviorTree.BehaviorTreeStatus.Success; } diff --git a/src/people/xray-thesis.js b/src/people/xray-thesis.js index 2c7457c..e17c2cd 100644 --- a/src/people/xray-thesis.js +++ b/src/people/xray-thesis.js @@ -59,7 +59,7 @@ class xrayThesis { myGoal = me().getTask().location; } else { - myGoal = computer; + myGoal = Hospital.locations.find(l => l.name == goToName); } return fluentBehaviorTree.BehaviorTreeStatus.Success; }) @@ -74,35 +74,35 @@ class xrayThesis { // }) // THIS TASK IS GIVEN BY THE XRAY TO THE TECH - .do("Queue Escort Patient", (t) => { - if (Hospital.XRayQueue.length == 0 || (goToName == "XRay 1" && Hospital.isXRay1Occupied()) || (goToName == "XRay 2" && Hospital.isXRay2Occupied())) { - return fluentBehaviorTree.BehaviorTreeStatus.Failure; - } - else { - // Escort Patient - let techEscortTask = new task("Escort Patient", null, null, Hospital.XRayQueue[0], null); - Hospital.techTaskList.push(techEscortTask); + // .do("Queue Escort Patient", (t) => { + // if (Hospital.XRayQueue.length == 0 || (goToName == "XRay 1" && Hospital.isXRay1Occupied()) || (goToName == "XRay 2" && Hospital.isXRay2Occupied())) { + // return fluentBehaviorTree.BehaviorTreeStatus.Failure; + // } + // else { + // // Escort Patient + // let techEscortTask = new task("Escort Patient", null, null, Hospital.XRayQueue[0], null); + // Hospital.techTaskList.push(techEscortTask); - return fluentBehaviorTree.BehaviorTreeStatus.Success; - } - }) + // return fluentBehaviorTree.BehaviorTreeStatus.Success; + // } + // }) // THIS TASK IS GIVEN BY THE TECH - .do("XRay Do Scan", (t) => { - if (me().getTask().taskID != "XRay Do Scan") { - return fluentBehaviorTree.BehaviorTreeStatus.Failure; - } - else { - let xrayPickupTask = new task("XRay Pickup", null, null, me().Task.patient, null); - Hospital.techTaskList.push(xrayPickupTask); + // .do("XRay Do Scan", (t) => { + // if (me().getTask().taskID != "XRay Do Scan") { + // return fluentBehaviorTree.BehaviorTreeStatus.Failure; + // } + // else { + // let xrayPickupTask = new task("XRay Pickup", null, null, me().getTask().patient, null); + // Hospital.techTaskList.push(xrayPickupTask); - let radiologyReviewTask = new task("Radiology Review Scan", null, null, me().Task.patient, null); - Hospital.radiologyTaskList.push(radiologyReviewTask); + // let radiologyReviewTask = new task("Radiology Review Scan", null, null, me().getTask().patient, null); + // Hospital.radiologyTaskList.push(radiologyReviewTask); - me().setTask(null); - return fluentBehaviorTree.BehaviorTreeStatus.Success; - } - }) + // me().setTask(null); + // return fluentBehaviorTree.BehaviorTreeStatus.Success; + // } + // }) .end() // IF SUCCEEDING IN TASK, TAKE TIME TO DO THAT TASK diff --git a/src/support/hospital.js b/src/support/hospital.js index 78e86cd..ce12b3f 100644 --- a/src/support/hospital.js +++ b/src/support/hospital.js @@ -41,6 +41,7 @@ class Hospital{ static CT2Agents = 0; // USING THIS FOR AGENT BEHAVIORS + static greeterTaskList = []; static triageTaskList = []; static janitorTaskList = []; static nurseTaskList = []; @@ -49,6 +50,9 @@ class Hospital{ static ctTaskList = []; static xrayTaskList = []; static radiologyTaskList = []; + static phlebotomistTaskList = []; + static pharmacistTaskList = []; + static attendingTaskList = []; static getFPS(){return 60;} From 0b6c63a76c5e67ada68ec8ad64843db73a8fa002 Mon Sep 17 00:00:00 2001 From: Narducky Date: Tue, 1 Feb 2022 16:51:40 -0600 Subject: [PATCH 11/42] Bugfixing Getting all the behaviors to work as they should. Currently fixing implementation of task queueing so they are not done right away. --- src/people/ct-thesis.js | 16 ++++++++++++-- src/people/nurse-thesis.js | 25 ++++++++++++++++++++++ src/people/radiology-thesis.js | 2 ++ src/people/resident-thesis.js | 14 +++++++++++++ src/people/tech-thesis.js | 38 ++++++++++++++++++++++++---------- 5 files changed, 82 insertions(+), 13 deletions(-) diff --git a/src/people/ct-thesis.js b/src/people/ct-thesis.js index 7f2a716..7ba080d 100644 --- a/src/people/ct-thesis.js +++ b/src/people/ct-thesis.js @@ -36,7 +36,7 @@ class ctThesis { .splice(new AssignComputer(myIndex, myGoal.location).tree) // RESIDENT PLACE // Add a behavior here or in the selector that will order the tasks (by severity)? .selector("Task List Tasks") - // THIS TASK IS GIVEN BY THE CT TO THE TECH + // THIS TASK IS GIVEN BY THE CT TO THE TECH AND MUST BE DONE BEFORE GETTING A TASK+ .do("Queue Escort Patient", (t) => { if (Hospital.CTQueue.length == 0 || (goToName == "CT 1" && Hospital.isCT1Occupied()) || (goToName == "CT 2" && Hospital.isCT2Occupied())) { return fluentBehaviorTree.BehaviorTreeStatus.Failure; @@ -44,6 +44,15 @@ class ctThesis { else { // Pick Up Patient let techEscortTask = new task("Pick Up Patient", Hospital.CTQueue[0].getSeverity(), 0, Hospital.CTQueue[0], myGoal); + if (goToName == "CT 1") { + Hospital.setCT1Occupied(true); + Hospital.CTQueue[0].setImagingRoom("CT 1"); + } + else { + Hospital.setCT2Occupied(true); + Hospital.CTQueue[0].setImagingRoom("CT 2"); + } + Hospital.CTQueue.shift(); Hospital.techTaskList.push(techEscortTask); //return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -89,12 +98,15 @@ class ctThesis { //return fluentBehaviorTree.BehaviorTreeStatus.Success; // }) - // THIS TASK IS GIVEN BY THE TECH + //THIS TASK IS GIVEN BY THE TECH .do("CAT Do Scan", (t) => { if (me().getTask().taskID != "CAT Do Scan") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + me().getTask().patient.setScan(true); + // queueing this here could be problematic let ctPickupTask = new task("CT Pickup", null, 0, me().getTask().patient, myGoal); Hospital.techTaskList.push(ctPickupTask); diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js index 06958cf..47eb39e 100644 --- a/src/people/nurse-thesis.js +++ b/src/people/nurse-thesis.js @@ -72,6 +72,8 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let patientEntry = Hospital.computer.getEntry(me().getTask().patient); patientEntry.setAnsweredQuestions(true); me().setTask(null); @@ -85,6 +87,8 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().getTask().patient, null); Hospital.nurseTaskList.push(exitTask); me().setTask(null); @@ -97,6 +101,27 @@ class nurseThesis { if (me().getTask().taskID != "Nurse Escort Patient To Exit") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } + else { + let myPatient = me().getTask().patient; + myPatient.setInstructor(me()); + myPatient.setPatientTempState(PatientTempState.FOLLOWING); + for (let i = 0; i < Hospital.emergencyQueue.length; i++) { + if (myPatient == Hospital.emergencyQueue[i]) { + Hospital.emergencyQueue.splice(i, 1); + } + } + + let entrance = Hospital.locations.find(l => l.name == "Main Entrance"); + let escortTask = new task("Patient Finished", null, 0, myPatient, entrance); + me().setTask(escortTask); + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + .do("Patient Finished", (t) => { + if (me().getTask().taskID != "Patient Finished") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } else { let myPatient = me().getTask().patient; myPatient.setPatientTempState(PatientTempState.DONE); diff --git a/src/people/radiology-thesis.js b/src/people/radiology-thesis.js index c21ea91..bc4b9c3 100644 --- a/src/people/radiology-thesis.js +++ b/src/people/radiology-thesis.js @@ -73,6 +73,8 @@ class radiologyThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let residentScanTask = new task("Resident Scan Read", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(residentScanTask); diff --git a/src/people/resident-thesis.js b/src/people/resident-thesis.js index f6ae82c..36d3aee 100644 --- a/src/people/resident-thesis.js +++ b/src/people/resident-thesis.js @@ -73,6 +73,8 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let consultTask = new task("EKG Consult", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(consultTask); me().setTask(null); @@ -85,6 +87,8 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + // queue CAT or XRAY let catTask = new task("EKG Order CAT", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(catTask); @@ -102,6 +106,8 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let myPatient = me().getTask().patient; // if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() != "ESI1") { // Hospital.CTQueue.unshift(myPatient); @@ -133,6 +139,8 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let myPatient = me().getTask().patient; if (myPatient.getSeverity() == "ESI1" && Hospital.CTQueue.length > 0 && Hospital.CTQueue[0].getSeverity() != "ESI1") { Hospital.CTQueue.unshift(myPatient); @@ -164,6 +172,8 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let attendingConsultTask = new task("Attending Consult", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(attendingConsultTask); @@ -177,6 +187,8 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let patientConsultTask = new task("Patient Consult", null, null, me().getTask().patient, null); Hospital.residentTaskList.push(patientConsultTask); me().setTask(null); @@ -189,6 +201,8 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + let dischargeTask = new task("Nurse Discharge Patient", null, null, me().getTask().patient, null); Hospital.nurseTaskList.push(dischargeTask); me().setTask(null); diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js index 7851a75..03f5f67 100644 --- a/src/people/tech-thesis.js +++ b/src/people/tech-thesis.js @@ -77,6 +77,8 @@ class techThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + Hospital.computer.getEntry(me().getTask().patient).setVitals("Taken"); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -88,6 +90,8 @@ class techThesis { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { + me().taskTime = 100; + Hospital.computer.getEntry(me().getTask().patient).setEkg("EKG Results"); // CREATE TASK FOR THE RESIDENT : RESIDENT_EKG_READ let readTask = new task("EKG Read", null, null, me().getTask().patient, null); @@ -107,24 +111,18 @@ class techThesis { let myPatient = me().getTask().patient; myPatient.setInstructor(me()); myPatient.setPatientTempState( PatientTempState.FOLLOWING); + Hospital.computer.getEntry(myPatient).setTech(me()); // NEED TO FIGURE OUT WHEN THEY WOULD GET ONE OVER THE OTHER if (true) { - // CT SCAN - let ctScanTask = new task("CAT Do Scan", null, 0, me().getTask().patient, null); - Hospital.ctTaskList.push(ctScanTask); - - // NOW ESCORT THE PATIENT + // NOW ESCORT THE PATIENT TO CT let escortTask = new task("Escort Patient", null, 0, me().getTask().patient, me().getTask().location); me().setTask(escortTask); + return fluentBehaviorTree.BehaviorTreeStatus.Success; } else { - // XRAY - let xrayScanTask = new task("XRay Do Scan", null, 0, me().getTask().patient, null); - Hospital.xrayTaskList.push(xrayScanTask); - - // NOW ESCORT THE PATIENT + // NOW ESCORT THE PATIENT TO XRAY let escortTask = new task("Escort Patient", null, 0, me().getTask().patient, me().getTask().location); me().setTask(escortTask); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -135,10 +133,20 @@ class techThesis { if (me().getTask().taskID != "Escort Patient") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } - else { + else { let myPatient = me().getTask().patient; myPatient.setInstructor(null); myPatient.setPatientTempState(PatientTempState.WAITING); + + if (!me().getTask().patient.getScan()) { + // CT SCAN + let ctScanTask = new task("CAT Do Scan", null, 0, me().getTask().patient, null); + Hospital.ctTaskList.push(ctScanTask); + + // XRAY + //let xrayScanTask = new task("XRay Do Scan", null, 0, me().getTask().patient, null); + //Hospital.xrayTaskList.push(xrayScanTask); + } me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -157,6 +165,14 @@ class techThesis { let escortTask = new task("Escort Patient", null, 0, me().getTask().patient, me().getTask().patient.getPermanentRoom()); me().setTask(escortTask); + + if (myPatient.getImagingRoom() == "CT 1") { + Hospital.setCT1Occupied(false); + } + else { + Hospital.setCT2Occupied(false); + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) From 7875cc010728098aea30eb96729b42166097ed0a Mon Sep 17 00:00:00 2001 From: Narducky Date: Tue, 1 Feb 2022 17:40:45 -0600 Subject: [PATCH 12/42] Bugfixing (Again) Almost got the bugs ironed out. Still having some issues with that last behavior of the nurses and noticing odd moments where tech and nurse will go to Main Entrance for some reason. --- src/people/ct-thesis.js | 23 ++++++++++++++++-- src/people/nurse-thesis.js | 30 ++++++++++++++++++++++-- src/people/radiology-thesis.js | 17 +++++++++++++- src/people/resident-thesis.js | 43 ++++++++++++++++++++++++++++++---- src/people/tech-thesis.js | 29 ++++++++++++++++++++--- 5 files changed, 129 insertions(+), 13 deletions(-) diff --git a/src/people/ct-thesis.js b/src/people/ct-thesis.js index 7ba080d..bfb222a 100644 --- a/src/people/ct-thesis.js +++ b/src/people/ct-thesis.js @@ -25,6 +25,7 @@ class ctThesis { let myGoal = Hospital.locations.find(l => l.name == goToName); if (!myGoal) throw new exception("We couldn't find a location called " + goToName); + let taskQueue = []; this.tree = builder @@ -108,10 +109,12 @@ class ctThesis { me().getTask().patient.setScan(true); // queueing this here could be problematic let ctPickupTask = new task("CT Pickup", null, 0, me().getTask().patient, myGoal); - Hospital.techTaskList.push(ctPickupTask); + taskQueue.push(ctPickupTask); + //Hospital.techTaskList.push(ctPickupTask); let radiologyReviewTask = new task("Radiology Review Scan", null, 0, me().getTask().patient, null); - Hospital.radiologyTaskList.push(radiologyReviewTask); + taskQueue.push(radiologyReviewTask); + //Hospital.radiologyTaskList.push(radiologyReviewTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -129,6 +132,22 @@ class ctThesis { return fluentBehaviorTree.BehaviorTreeStatus.Running; } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // QUEUEING FOLLOWING TASKS NEEDS TO COME LAST, OTHERWISE TASKS ARE BLITZED THROUGH TOO QUICKLY + .do("Queue Tasks", (t) => { + while (taskQueue.length > 0) { + switch(taskQueue[0].taskID) { + case "CT Pickup": + Hospital.techTaskList.push(taskQueue.shift()); + break; + case "Radiology Review Scan": + Hospital.radiologyTaskList.push(taskQueue.shift()); + break; + default: break; + } + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; }) .end() diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js index 47eb39e..3d9e2a4 100644 --- a/src/people/nurse-thesis.js +++ b/src/people/nurse-thesis.js @@ -20,6 +20,9 @@ class nurseThesis { let goToName = "NursePlace"; let myGoal = Hospital.locations.find(l => l.name == goToName); let computer = Hospital.locations.find(l => l.name == "NursePlace"); + + let taskQueue = []; + this.tree = builder // Consider limiting the rooms nurses can be assigned to tasks to @@ -90,17 +93,27 @@ class nurseThesis { me().taskTime = 100; let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().getTask().patient, null); - Hospital.nurseTaskList.push(exitTask); + taskQueue.push(exitTask); + //Hospital.nurseTaskList.push(exitTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) // THIS TASK IS GIVEN BY NURSE DISCHARGE PATIENT - // need to add more to this + // this task keeps running before the patient is actually being escorted by the nurse, deleting them wayyyy prematurely!!! .do("Nurse Escort Patient To Exit", (t) => { if (me().getTask().taskID != "Nurse Escort Patient To Exit") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } + + let id = Hospital.agents[self.index].id; + let simulationAgent = t.crowd.find(f=>f.id == id); + let myLocation = new Vector3(simulationAgent.location.x, simulationAgent.location.y, simulationAgent.location.z); + let patientLoc = Vector3.fromObject(t.crowd.find(f=>f.id == me().getTask().patient.id).location); + + if (myLocation.distanceToSquared(patientLoc) > 100) { + return fluentBehaviorTree.BehaviorTreeStatus.Running; + } else { let myPatient = me().getTask().patient; myPatient.setInstructor(me()); @@ -145,6 +158,19 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Running; } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // QUEUEING FOLLOWING TASKS NEEDS TO COME LAST, OTHERWISE TASKS ARE BLITZED THROUGH TOO QUICKLY + .do("Queue Tasks", (t) => { + while (taskQueue.length > 0) { + switch(taskQueue[0].taskID) { + case "Nurse Escort Patient To Exit": + Hospital.nurseTaskList.push(taskQueue.shift()); + break; + default: break; + } + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; }) .end() diff --git a/src/people/radiology-thesis.js b/src/people/radiology-thesis.js index bc4b9c3..87b4a78 100644 --- a/src/people/radiology-thesis.js +++ b/src/people/radiology-thesis.js @@ -20,6 +20,7 @@ class radiologyThesis { let goToName = "CT 2"; let myGoal = Hospital.locations.find(l => l.name == goToName); + let taskQueue = []; this.tree = builder @@ -76,7 +77,8 @@ class radiologyThesis { me().taskTime = 100; let residentScanTask = new task("Resident Scan Read", null, null, me().getTask().patient, null); - Hospital.residentTaskList.push(residentScanTask); + taskQueue.push(residentScanTask); + //Hospital.residentTaskList.push(residentScanTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -94,6 +96,19 @@ class radiologyThesis { return fluentBehaviorTree.BehaviorTreeStatus.Running; } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // QUEUEING FOLLOWING TASKS NEEDS TO COME LAST, OTHERWISE TASKS ARE BLITZED THROUGH TOO QUICKLY + .do("Queue Tasks", (t) => { + while (taskQueue.length > 0) { + switch(taskQueue[0].taskID) { + case "Resident Scan Read": + Hospital.residentTaskList.push(taskQueue.shift()); + break; + default: break; + } + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; }) .end() diff --git a/src/people/resident-thesis.js b/src/people/resident-thesis.js index 36d3aee..01293a3 100644 --- a/src/people/resident-thesis.js +++ b/src/people/resident-thesis.js @@ -20,6 +20,9 @@ class residentThesis { let goToName = "ResidentStart"; let myGoal = Hospital.locations.find(l => l.name == goToName); let computer = Hospital.locations.find(l => l.name == "ResidentStart"); + + let taskQueue = []; + this.tree = builder // Consider limiting the rooms nurses can be assigned to tasks to @@ -76,7 +79,8 @@ class residentThesis { me().taskTime = 100; let consultTask = new task("EKG Consult", null, null, me().getTask().patient, null); - Hospital.residentTaskList.push(consultTask); + taskQueue.push(consultTask); + //Hospital.residentTaskList.push(consultTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } @@ -91,7 +95,8 @@ class residentThesis { // queue CAT or XRAY let catTask = new task("EKG Order CAT", null, null, me().getTask().patient, null); - Hospital.residentTaskList.push(catTask); + taskQueue.push(catTask); + //Hospital.residentTaskList.push(catTask); //let xrayTask = new task("EKG Order XRay", null, null, me().getTask().patient, null); //Hospital.residentTaskList.push(xrayTask); @@ -175,7 +180,8 @@ class residentThesis { me().taskTime = 100; let attendingConsultTask = new task("Attending Consult", null, null, me().getTask().patient, null); - Hospital.residentTaskList.push(attendingConsultTask); + taskQueue.push(attendingConsultTask); + //Hospital.residentTaskList.push(attendingConsultTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -190,7 +196,8 @@ class residentThesis { me().taskTime = 100; let patientConsultTask = new task("Patient Consult", null, null, me().getTask().patient, null); - Hospital.residentTaskList.push(patientConsultTask); + taskQueue.push(patientConsultTask); + //Hospital.residentTaskList.push(patientConsultTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } @@ -204,7 +211,8 @@ class residentThesis { me().taskTime = 100; let dischargeTask = new task("Nurse Discharge Patient", null, null, me().getTask().patient, null); - Hospital.nurseTaskList.push(dischargeTask); + taskQueue.push(dischargeTask); + //Hospital.nurseTaskList.push(dischargeTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; } @@ -220,6 +228,31 @@ class residentThesis { return fluentBehaviorTree.BehaviorTreeStatus.Running; } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // QUEUEING FOLLOWING TASKS NEEDS TO COME LAST, OTHERWISE TASKS ARE BLITZED THROUGH TOO QUICKLY + .do("Queue Tasks", (t) => { + while (taskQueue.length > 0) { + switch(taskQueue[0].taskID) { + case "EKG Consult": + Hospital.residentTaskList.push(taskQueue.shift()); + break; + case "EKG Order CAT": + Hospital.residentTaskList.push(taskQueue.shift()); + break; + case "Attending Consult": + Hospital.residentTaskList.push(taskQueue.shift()); + break; + case "Patient Consult": + Hospital.residentTaskList.push(taskQueue.shift()); + break; + case "Nurse Discharge Patient": + Hospital.nurseTaskList.push(taskQueue.shift()); + break; + default: break; + } + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; }) .end() diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js index 03f5f67..5218e95 100644 --- a/src/people/tech-thesis.js +++ b/src/people/tech-thesis.js @@ -21,15 +21,20 @@ class techThesis { let goToName = "TechPlace"; let myGoal = Hospital.locations.find(l => l.name == goToName); let computer = Hospital.locations.find(l => l.name == "TechPlace"); + + let taskQueue = []; + this.tree = builder // Consider limiting the rooms nurses can be assigned to tasks to - // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART + // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH TASK FROM LIST -> TAKE TIME -> QUEUE TASKS -> RESTART .sequence("Tech Behaviors") .splice(new GoTo(self.index, computer.location).tree) //.splice(new AssignBed(myIndex, Hospital.locations.find(l => l.name == "C1").location).tree) .splice(new AssignComputer(myIndex, computer.location).tree) // TECH PLACE + // Add a behavior here or in the selector that will order the tasks (by severity)? + .selector("Task List Tasks") .do("Get a Task", (t) => { // IF ALREADY ALLOCATED A TASK, CONTINUE @@ -95,7 +100,8 @@ class techThesis { Hospital.computer.getEntry(me().getTask().patient).setEkg("EKG Results"); // CREATE TASK FOR THE RESIDENT : RESIDENT_EKG_READ let readTask = new task("EKG Read", null, null, me().getTask().patient, null); - Hospital.residentTaskList.push(readTask); + taskQueue.push(readTask); + //Hospital.residentTaskList.push(readTask); me().setTask(null); return fluentBehaviorTree.BehaviorTreeStatus.Success; @@ -141,7 +147,8 @@ class techThesis { if (!me().getTask().patient.getScan()) { // CT SCAN let ctScanTask = new task("CAT Do Scan", null, 0, me().getTask().patient, null); - Hospital.ctTaskList.push(ctScanTask); + taskQueue.push(ctScanTask); + //Hospital.ctTaskList.push(ctScanTask); // XRAY //let xrayScanTask = new task("XRay Do Scan", null, 0, me().getTask().patient, null); @@ -187,6 +194,22 @@ class techThesis { return fluentBehaviorTree.BehaviorTreeStatus.Running; } + return fluentBehaviorTree.BehaviorTreeStatus.Success; + }) + // QUEUEING FOLLOWING TASKS NEEDS TO COME LAST, OTHERWISE TASKS ARE BLITZED THROUGH TOO QUICKLY + .do("Queue Tasks", (t) => { + while (taskQueue.length > 0) { + switch(taskQueue[0].taskID) { + case "EKG Read": + Hospital.residentTaskList.push(taskQueue.shift()); + break; + case "CAT Do Scan": + Hospital.ctTaskList.push(taskQueue.shift()); + break; + default: break; + } + } + return fluentBehaviorTree.BehaviorTreeStatus.Success; }) .end() From d112150473c38e6c06ad023b5c0ff3eb3c0a0658 Mon Sep 17 00:00:00 2001 From: Narducky Date: Thu, 3 Feb 2022 16:32:41 -0600 Subject: [PATCH 13/42] Bugfixing Still Going Still ironing out some problems. General flow is right, but there are points where nurse or tech goes to Main Entrance for no reason and trying to figure out why. --- src/index.js | 6 ++-- src/people/nurse-thesis.js | 34 ++++++++------------- src/people/resident-thesis.js | 9 +++--- src/people/tech-thesis.js | 57 +++++++++++++++++++---------------- 4 files changed, 52 insertions(+), 54 deletions(-) diff --git a/src/index.js b/src/index.js index ba11a7f..6869a0c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ import CrowdSetup from "@crowdedjs/crowd-setup" -//import MedicalAgent from "./people/medical-agent.js" +import MedicalAgent from "./people/medical-agent.js" import MedicalAgentThesis from "./people/medical-agent-thesis.js" -//import PatientAgent from "./people/patient-agent.js" +import PatientAgent from "./people/patient-agent.js" import PatientAgentThesis from "./people/patient-agent-thesis.js" import urlParser from "./url-parser.js" import colorFunction from "./color-function.js" @@ -48,8 +48,10 @@ function boot() { //Add an agent with a behavior and an id arrivalValue.forEach((agent, index) => { if (agent.name == "patient") + //agentConstants.push(new PatientAgent(agent, locationValue)); agentConstants.push(new PatientAgentThesis(agent, locationValue)); else + //agentConstants.push(new MedicalAgent(agent, locationValue)); agentConstants.push(new MedicalAgentThesis(agent, locationValue)); //Is this line necessary? agentConstants[agentConstants.length - 1].setId(index); diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js index 3d9e2a4..3a72ff5 100644 --- a/src/people/nurse-thesis.js +++ b/src/people/nurse-thesis.js @@ -28,7 +28,10 @@ class nurseThesis { // Consider limiting the rooms nurses can be assigned to tasks to // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH THE TASK FROM *LIST OF TASKS* AND TAKE TIME -> RESTART .sequence("Nurse Behaviors") - .splice(new GoTo(self.index, computer.location).tree) + .selector("Should I go back to start?") + .condition("Do I have patient", async (t) => me().getBusy()) + .splice(new GoTo(self.index, computer.location).tree) + .end() .splice(new AssignComputer(myIndex, computer.location).tree) // NURSE PLACE // Add a behavior here or in the selector that will order the tasks (by severity)? .selector("Task List Tasks") @@ -89,32 +92,18 @@ class nurseThesis { if (me().getTask().taskID != "Nurse Discharge Patient") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } - else { - me().taskTime = 100; - - let exitTask = new task("Nurse Escort Patient To Exit", null, null, me().getTask().patient, null); - taskQueue.push(exitTask); - //Hospital.nurseTaskList.push(exitTask); - me().setTask(null); - return fluentBehaviorTree.BehaviorTreeStatus.Success; - } - }) - // THIS TASK IS GIVEN BY NURSE DISCHARGE PATIENT - // this task keeps running before the patient is actually being escorted by the nurse, deleting them wayyyy prematurely!!! - .do("Nurse Escort Patient To Exit", (t) => { - if (me().getTask().taskID != "Nurse Escort Patient To Exit") { - return fluentBehaviorTree.BehaviorTreeStatus.Failure; - } - let id = Hospital.agents[self.index].id; let simulationAgent = t.crowd.find(f=>f.id == id); let myLocation = new Vector3(simulationAgent.location.x, simulationAgent.location.y, simulationAgent.location.z); let patientLoc = Vector3.fromObject(t.crowd.find(f=>f.id == me().getTask().patient.id).location); - if (myLocation.distanceToSquared(patientLoc) > 100) { + if (myLocation.distanceToSquared(patientLoc) > 30 || me().getTask().patient.getPatientTempState() != PatientTempState.WAITING) { return fluentBehaviorTree.BehaviorTreeStatus.Running; } else { + me().taskTime = 100; + me().setBusy(true); + let myPatient = me().getTask().patient; myPatient.setInstructor(me()); myPatient.setPatientTempState(PatientTempState.FOLLOWING); @@ -125,14 +114,14 @@ class nurseThesis { } let entrance = Hospital.locations.find(l => l.name == "Main Entrance"); - let escortTask = new task("Patient Finished", null, 0, myPatient, entrance); + let escortTask = new task("Nurse Escort Patient To Exit", null, 0, myPatient, entrance); me().setTask(escortTask); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) - .do("Patient Finished", (t) => { - if (me().getTask().taskID != "Patient Finished") { + .do("Nurse Escort Patient To Exit", (t) => { + if (me().getTask().taskID != "Nurse Escort Patient To Exit") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; } else { @@ -144,6 +133,7 @@ class nurseThesis { } } me().setTask(null); + me().setBusy(false); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) diff --git a/src/people/resident-thesis.js b/src/people/resident-thesis.js index 01293a3..b92e5b3 100644 --- a/src/people/resident-thesis.js +++ b/src/people/resident-thesis.js @@ -78,7 +78,7 @@ class residentThesis { else { me().taskTime = 100; - let consultTask = new task("EKG Consult", null, null, me().getTask().patient, null); + let consultTask = new task("EKG Consult", null, null, me().getTask().patient, me().getTask().patient.getPermanentRoom()); taskQueue.push(consultTask); //Hospital.residentTaskList.push(consultTask); me().setTask(null); @@ -94,7 +94,7 @@ class residentThesis { me().taskTime = 100; // queue CAT or XRAY - let catTask = new task("EKG Order CAT", null, null, me().getTask().patient, null); + let catTask = new task("EKG Order CAT", null, null, me().getTask().patient, me().getTask().location); taskQueue.push(catTask); //Hospital.residentTaskList.push(catTask); @@ -179,6 +179,7 @@ class residentThesis { else { me().taskTime = 100; + // what is ATTENDING as the responsibility subject? let attendingConsultTask = new task("Attending Consult", null, null, me().getTask().patient, null); taskQueue.push(attendingConsultTask); //Hospital.residentTaskList.push(attendingConsultTask); @@ -195,7 +196,7 @@ class residentThesis { else { me().taskTime = 100; - let patientConsultTask = new task("Patient Consult", null, null, me().getTask().patient, null); + let patientConsultTask = new task("Patient Consult", null, null, me().getTask().patient, me().getTask().patient.getPermanentRoom()); taskQueue.push(patientConsultTask); //Hospital.residentTaskList.push(patientConsultTask); me().setTask(null); @@ -210,7 +211,7 @@ class residentThesis { else { me().taskTime = 100; - let dischargeTask = new task("Nurse Discharge Patient", null, null, me().getTask().patient, null); + let dischargeTask = new task("Nurse Discharge Patient", null, null, me().getTask().patient, me().getTask().location); taskQueue.push(dischargeTask); //Hospital.nurseTaskList.push(dischargeTask); me().setTask(null); diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js index 5218e95..e1887e2 100644 --- a/src/people/tech-thesis.js +++ b/src/people/tech-thesis.js @@ -29,7 +29,10 @@ class techThesis { // Consider limiting the rooms nurses can be assigned to tasks to // General Structure of New Trees: GO TO START -> GET A TASK -> GO TO THE TASK -> ACCOMPLISH TASK FROM LIST -> TAKE TIME -> QUEUE TASKS -> RESTART .sequence("Tech Behaviors") - .splice(new GoTo(self.index, computer.location).tree) + .selector("Should I go back to start?") + .condition("Do I have patient", async (t) => me().getBusy()) + .splice(new GoTo(self.index, computer.location).tree) + .end() //.splice(new AssignBed(myIndex, Hospital.locations.find(l => l.name == "C1").location).tree) .splice(new AssignComputer(myIndex, computer.location).tree) // TECH PLACE @@ -108,7 +111,6 @@ class techThesis { } }) // ESCORTING TO XRAY / CT IS QUEUED BY THE CT AND XRAY - // THIS IS A 2-PART TASK, THEY GO TO THE PATIENT, THEN THEY ESCORT THE PATIENT TO THE CT OR XRAY .do("Pick Up Patient", (t) => { if (me().getTask().taskID != "Pick Up Patient") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; @@ -118,6 +120,7 @@ class techThesis { myPatient.setInstructor(me()); myPatient.setPatientTempState( PatientTempState.FOLLOWING); Hospital.computer.getEntry(myPatient).setTech(me()); + me().setBusy(true); // NEED TO FIGURE OUT WHEN THEY WOULD GET ONE OVER THE OTHER if (true) { @@ -135,6 +138,30 @@ class techThesis { } } }) + // THIS TASK IS GIVEN BY THE CT / XRAY + .do("CT/XRAY Pickup", (t) => { + if (me().getTask().taskID != "CT Pickup" && me().getTask().taskID != "XRay Pickup") { + return fluentBehaviorTree.BehaviorTreeStatus.Failure; + } + else { + let myPatient = me().getTask().patient; + myPatient.setInstructor(me()); + myPatient.setPatientTempState(PatientTempState.FOLLOWING); + me().setBusy(true); + if (myPatient.getImagingRoom() == "CT 1") { + Hospital.setCT1Occupied(false); + } + else { + Hospital.setCT2Occupied(false); + } + + let escortTask = new task("Escort Patient", null, 0, me().getTask().patient, me().getTask().patient.getPermanentRoom()); + me().setTask(escortTask); + + return fluentBehaviorTree.BehaviorTreeStatus.Success; + } + }) + // SECOND PART OF ESCORT TASKS: TAKING PATIENT TO WHERE THEY NEED TO BE .do("Escort Patient", (t) => { if (me().getTask().taskID != "Escort Patient") { return fluentBehaviorTree.BehaviorTreeStatus.Failure; @@ -143,6 +170,7 @@ class techThesis { let myPatient = me().getTask().patient; myPatient.setInstructor(null); myPatient.setPatientTempState(PatientTempState.WAITING); + Hospital.computer.getEntry(myPatient).setTech(null); if (!me().getTask().patient.getScan()) { // CT SCAN @@ -156,30 +184,7 @@ class techThesis { } me().setTask(null); - return fluentBehaviorTree.BehaviorTreeStatus.Success; - } - }) - - // THIS TASK IS GIVEN BY THE CT / XRAY - .do("CT/XRAY Pickup", (t) => { - if (me().getTask().taskID != "CT Pickup" && me().getTask().taskID != "XRay Pickup") { - return fluentBehaviorTree.BehaviorTreeStatus.Failure; - } - else { - let myPatient = me().getTask().patient; - myPatient.setInstructor(me()); - myPatient.setPatientTempState(PatientTempState.FOLLOWING); - - let escortTask = new task("Escort Patient", null, 0, me().getTask().patient, me().getTask().patient.getPermanentRoom()); - me().setTask(escortTask); - - if (myPatient.getImagingRoom() == "CT 1") { - Hospital.setCT1Occupied(false); - } - else { - Hospital.setCT2Occupied(false); - } - + me().setBusy(false); return fluentBehaviorTree.BehaviorTreeStatus.Success; } }) From 8766cc3d274adfd489387d3813109b236059e86f Mon Sep 17 00:00:00 2001 From: Narducky Date: Thu, 3 Feb 2022 17:26:59 -0600 Subject: [PATCH 14/42] Fixed Triage Bug Previous bug was that certain patient severities were not being removed from simulation completely, messing up task queueing. Noticed small bugs in triage to fix: always pickup from CT 1 location and put 2 patients in one room. After these bugs are resolved, I'd like to quickly implement the x-ray back in, then implement the shift change. From there I will make sure the code is similar throughout the new work before testing. --- src/people/ct-thesis.js | 30 +++++++++++++++--------------- src/people/nurse-thesis.js | 24 ++++++++++++------------ src/people/tech-thesis.js | 1 + src/people/triage-nurse-thesis.js | 9 +++++++++ 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/people/ct-thesis.js b/src/people/ct-thesis.js index bfb222a..1adfe67 100644 --- a/src/people/ct-thesis.js +++ b/src/people/ct-thesis.js @@ -78,21 +78,21 @@ class ctThesis { } }) // I think it has to be done this way because you can't do operations in a splice for the most part - .inverter("Need to return failure") - .sequence("Go to Task") - .do("Determine Location", (t) => { - if (me().getTask().location != null) { - myGoal = me().getTask().location; - } - else { - myGoal = Hospital.locations.find(l => l.name == goToName); - } - return fluentBehaviorTree.BehaviorTreeStatus.Success; - }) - // GoTo gives me problems sometimes that GoToLazy does not - .splice(new GoToLazy(self.index, () => myGoal.location).tree) - .end() - .end() + // .inverter("Need to return failure") + // .sequence("Go to Task") + // .do("Determine Location", (t) => { + // if (me().getTask().location != null) { + // myGoal = me().getTask().location; + // } + // else { + // myGoal = Hospital.locations.find(l => l.name == goToName); + // } + // return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) + // // GoTo gives me problems sometimes that GoToLazy does not + // .splice(new GoToLazy(self.index, () => myGoal.location).tree) + // .end() + // .end() // .do("Clock In / Clock Out", (t) => { // Could make this a spliced behavior that takes the agent as a parameter diff --git a/src/people/nurse-thesis.js b/src/people/nurse-thesis.js index 3a72ff5..0b1d5a2 100644 --- a/src/people/nurse-thesis.js +++ b/src/people/nurse-thesis.js @@ -151,18 +151,18 @@ class nurseThesis { return fluentBehaviorTree.BehaviorTreeStatus.Success; }) // QUEUEING FOLLOWING TASKS NEEDS TO COME LAST, OTHERWISE TASKS ARE BLITZED THROUGH TOO QUICKLY - .do("Queue Tasks", (t) => { - while (taskQueue.length > 0) { - switch(taskQueue[0].taskID) { - case "Nurse Escort Patient To Exit": - Hospital.nurseTaskList.push(taskQueue.shift()); - break; - default: break; - } - } - - return fluentBehaviorTree.BehaviorTreeStatus.Success; - }) + // .do("Queue Tasks", (t) => { + // while (taskQueue.length > 0) { + // switch(taskQueue[0].taskID) { + // case "Nurse Escort Patient To Exit": + // Hospital.nurseTaskList.push(taskQueue.shift()); + // break; + // default: break; + // } + // } + + // return fluentBehaviorTree.BehaviorTreeStatus.Success; + // }) .end() .build() } diff --git a/src/people/tech-thesis.js b/src/people/tech-thesis.js index e1887e2..36a8755 100644 --- a/src/people/tech-thesis.js +++ b/src/people/tech-thesis.js @@ -58,6 +58,7 @@ class techThesis { .inverter("Need to return failure") .sequence("Go to Task") .do("Determine Location", (t) => { + // THIS IS HERE SO THAT THE CT CAN HAND THEIR SPECIFIC ROOM OVER FOR CT QUEUEING if (me().getTask().taskID == "Pick Up Patient") { myGoal = me().getTask().patient.getPermanentRoom(); } diff --git a/src/people/triage-nurse-thesis.js b/src/people/triage-nurse-thesis.js index bb8c505..0cc5d5b 100644 --- a/src/people/triage-nurse-thesis.js +++ b/src/people/triage-nurse-thesis.js @@ -97,6 +97,15 @@ class triageNurseThesis { .do("Leave Patient", (t) => { // ONCE THE PATIENT HAS BEEN DELIVERED, QUEUE TASKS TO THE APPROPRIATE MEDICAL STAFF // Task ID / Severity / Entry Time / Patient / Location + if (me().getCurrentPatient().getAssignedRoom().name == "Main Entrance") { + me().getCurrentPatient().setPatientTempState(PatientTempState.DONE); + let result = leavePatient.tick(t) + if (me().replacement == false) { + me().setBusy(false); + } + return result; + } + let nurseTask = new task("Get Health Information", me().getCurrentPatient().getSeverity(), 0, me().getCurrentPatient(), me().getCurrentPatient().getAssignedRoom()); Hospital.nurseTaskList.push(nurseTask); From d361140a6cab76438928d899d55ae78d8b580f1d Mon Sep 17 00:00:00 2001 From: Narducky Date: Thu, 3 Feb 2022 19:18:56 -0600 Subject: [PATCH 15/42] CT Fix 1/2 Fixed Techs going to wrong CT room, need to fix the doubling up bug. --- src/people/ct-thesis.js | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/people/ct-thesis.js b/src/people/ct-thesis.js index 1adfe67..b9ebcaa 100644 --- a/src/people/ct-thesis.js +++ b/src/people/ct-thesis.js @@ -23,6 +23,9 @@ class ctThesis { } let myGoal = Hospital.locations.find(l => l.name == goToName); + let computer = Hospital.locations.find(l => l.name == goToName); + let ct1 = Hospital.locations.find(l => l.name == "CT 1"); + let ct2 = Hospital.locations.find(l => l.name == "CT 2"); if (!myGoal) throw new exception("We couldn't find a location called " + goToName); let taskQueue = []; @@ -44,19 +47,19 @@ class ctThesis { } else { // Pick Up Patient - let techEscortTask = new task("Pick Up Patient", Hospital.CTQueue[0].getSeverity(), 0, Hospital.CTQueue[0], myGoal); + let ctPatient = Hospital.CTQueue.shift(); + let techEscortTask = new task("Pick Up Patient", ctPatient.getSeverity(), 0, ctPatient, myGoal); if (goToName == "CT 1") { Hospital.setCT1Occupied(true); - Hospital.CTQueue[0].setImagingRoom("CT 1"); + ctPatient.setImagingRoom("CT 1"); + techEscortTask = new task("Pick Up Patient", ctPatient.getSeverity(), 0, ctPatient, ct1); } - else { + else if (goToName == "CT 2") { Hospital.setCT2Occupied(true); - Hospital.CTQueue[0].setImagingRoom("CT 2"); + ctPatient.setImagingRoom("CT 2"); + techEscortTask = new task("Pick Up Patient", ctPatient.getSeverity(), 0, ctPatient, ct2); } - Hospital.CTQueue.shift(); Hospital.techTaskList.push(techEscortTask); - - //return fluentBehaviorTree.BehaviorTreeStatus.Success; } return fluentBehaviorTree.BehaviorTreeStatus.Failure; @@ -107,8 +110,14 @@ class ctThesis { else { me().taskTime = 100; me().getTask().patient.setScan(true); - // queueing this here could be problematic let ctPickupTask = new task("CT Pickup", null, 0, me().getTask().patient, myGoal); + if (me().getTask().patient.getImagingRoom() == "CT 1") { + ctPickupTask = new task("CT Pickup", null, 0, me().getTask().patient, ct1); + + } + else { + ctPickupTask = new task("CT Pickup", null, 0, me().getTask().patient, ct2); + } taskQueue.push(ctPickupTask); //Hospital.techTaskList.push(ctPickupTask); From b6b87892196a7cc6207d24354313bb9f393dcd2b Mon Sep 17 00:00:00 2001 From: Narducky Date: Fri, 4 Feb 2022 12:38:39 -0600 Subject: [PATCH 16/42] Fixed CT Bugs and Added XRay Added CT and XRay, fully functional. Now to add shift changes. --- index.html | 6 +- src/behavior/follow-instructions-thesis.js | 136 +++++++++++++++++++++ src/people/ct-thesis.js | 35 +++--- src/people/patient-thesis.js | 4 +- src/people/resident-thesis.js | 21 ++-- src/people/tech-thesis.js | 31 +++-- src/people/xray-thesis.js | 105 +++++++++++----- 7 files changed, 269 insertions(+), 69 deletions(-) create mode 100644 src/behavior/follow-instructions-thesis.js diff --git a/index.html b/index.html index 72dfceb..c259614 100644 --- a/index.html +++ b/index.html @@ -12,15 +12,15 @@
- +