package org.jbpm.sim; import java.util.Calendar; import org.jbpm.sim.def.JbpmSimulationExperiment; import org.jbpm.sim.def.JbpmSimulationScenario; import org.jbpm.sim.exe.ExperimentReader; import org.jbpm.sim.report.ScenarioReport; import org.jbpm.sim.report.dto.ValueStatisticResult; public class ScenarioTest extends AbstractSimTestCase { private static final String testProcessXml = "<process-definition name='test' start-distribution='start new process instances of test'>" + " <distribution name='start new process instances of test' sample-type='real' type='constant' value='20' /> " + " <distribution name='time required for task one' sample-type='real' type='normal' mean='25' standardDeviation='10' /> " + " <distribution name='time required for task two' sample-type='real' type='normal' mean='6' standardDeviation='1' /> " + " <distribution name='time required for automated state' sample-type='real' type='normal' mean='6' standardDeviation='1' /> " + " <resource-pool name='tester' pool-size='2' />" + " <resource-pool name='big machine' pool-size='3' />" + // TODO: think about shifts for resource pools and implement // " <resource-pool name='big machine'>" + // " <shift from='xx' till='xx' pool-size='3' />" + // " </resource-pool>" + " <swimlane name='tester' pool-size='1' />" + " <start-state name='start'>" + " <transition to='task one' />" + " </start-state>" + " <task-node name='task one'>" + " <task swimlane='tester' time-distribution='time required for task one' />" + " <transition to='task two' />" + " </task-node>" + " <task-node name='task two'>" + " <task swimlane='tester' time-distribution='time required for task two' />" + " <transition to='automated state' />" + " </task-node>" + " <state name='automated state' time-distribution='time required for automated state'>" + " <resource-needed pool='big machine' amount='2' />" + " <transition to='end' />" + " </state>" + " <end-state name='end'/>" + "</process-definition>" ; public void testExperimentReader() { String experimentConfiguration = "<experiment name='MySimulationExperiment'" + " run-time='100'" + " real-start-time='04.10.1982 14:30:10:500'" + " time-unit='minute'>" + " <scenario name='NormalStaffing'>" + // This specification overwrites any distribution specification in the processdefinition.xml " <distribution name='start new process instances of test' sample-type='real' type='constant' value='20' /> " + " <distribution name='time required for task one' sample-type='real' type='normal' mean='25' standardDeviation='10' /> " + " <distribution name='time required for task two' sample-type='real' type='normal' mean='6' standardDeviation='1' /> " + " <distribution name='time required for automated state' sample-type='real' type='normal' mean='6' standardDeviation='1' /> " + // This specification overwrites any resource-pool specification in the processdefinition.xml " <resource-pool name='tester' pool-size='2' />" + " <resource-pool name='big machine' pool-size='3' />" + " <sim-process name='test'>" + // TODO: Think about overwriting special stuff of process simulation and implement // " <task-overwrite task-name='task one' time-distribution='time required for task one' />" + // " <process-overwrite start-distribution='start new process instances of test' />" + " </sim-process>" + " </scenario>" + // maybe more <scenario ... />'s // TODO: Think more about output options " <output path='target' />" + // currently just used as parameter for DESMO-J "</experiment>"; ExperimentReader reader = new ExperimentReader(experimentConfiguration); reader.addProcessDefinition("test", testProcessXml ); JbpmSimulationExperiment experiment = reader.readExperiment(); assertNotNull(experiment); assertEquals("MySimulationExperiment", experiment.getName()); assertEquals(100.0, experiment.getSimulationRunTime(), 0.001); Calendar calendar = Calendar.getInstance(); calendar.set(1982, Calendar.OCTOBER, 4, 14, 30, 10); calendar.set(Calendar.MILLISECOND, 500); assertEquals(calendar.getTime(), experiment.getRealStartDate()); assertEquals(JbpmSimulationExperiment.MINUTES, experiment.getTimeUnit()); assertEquals("target", experiment.getOutputPathName()); assertEquals(1, experiment.getScenarios().size()); JbpmSimulationScenario scenario = experiment.getScenario("NormalStaffing"); assertNotNull(scenario); assertEquals("NormalStaffing", scenario.getName()); } public void testExperimentRun() { String experimentConfiguration = "<experiment name='MySimulationExperiment'" + " run-time='100'" + " real-start-time='30.03.1980 00:00:00:000'" + " time-unit='minute'>" + " <scenario name='NormalStaffing'>" + // This specification overwrites any distribution specification in the processdefinition.xml " <distribution name='start new process instances of test' sample-type='real' type='constant' value='20' /> " + " <distribution name='time required for task one' sample-type='real' type='normal' mean='25' standardDeviation='10' /> " + " <distribution name='time required for task two' sample-type='real' type='normal' mean='6' standardDeviation='1' /> " + " <distribution name='time required for automated state' sample-type='real' type='normal' mean='6' standardDeviation='1' /> " + // This specification overwrites any resource-pool specification in the processdefinition.xml " <resource-pool name='tester' pool-size='2' />" + " <resource-pool name='big machine' pool-size='3' />" + " <sim-process name='test'>" + // TODO: Think about overwriting special stuff of process simulation and implement // " <task-overwrite task-name='task one' time-distribution='time required for task one' />" + // " <process-overwrite start-distribution='start new process instances of test' />" + " </sim-process>" + " </scenario>" + // maybe more <scenario ... />'s // TODO: Think more about output options " <output path='target' />" + // currently just used as parameter for DESMO-J "</experiment>"; ExperimentReader reader = new ExperimentReader(experimentConfiguration); reader.addProcessDefinition("test", testProcessXml ); JbpmSimulationExperiment experiment = reader.readExperiment(); experiment.run(); // TODO: check results and write asserts } public void testTwoScenariosExperimentRun() { String experimentConfiguration = "<experiment name='MySimulationExperiment'>" + " <scenario name='Staffing1'>" + " <resource-pool name='tester' pool-size='1' />" + " <sim-process name='test' />" + " </scenario>" + " <scenario name='Staffing2'>" + " <resource-pool name='tester' pool-size='5' />" + " <sim-process name='test' />" + " </scenario>" + " <output path='target' />" + // currently just used as parameter for DESMO-J "</experiment>"; ExperimentReader reader = new ExperimentReader(experimentConfiguration); reader.addProcessDefinition( "test", testProcessXml ); JbpmSimulationExperiment experiment = reader.readExperiment(); experiment.run(); ScenarioReport report1 = experiment.getSimulationReportForScenario("Staffing1"); assertNotNull(report1); assertEquals("Staffing1", report1.getScenarioName()); assertEquals(1440.0, report1.getSimulationRunTime(), 0.001); assertEquals(3, report1.getStateWaitingTimes().size()); assertEquals(1, report1.getCycleTimesValueStatistics().size()); assertEquals(2, report1.getResourcePoolWaitingTimes().size()); { ValueStatisticResult vsr = report1.getStateWaitingTimes("task one"); assertEquals("task one", vsr.getName()); // assertEquals(71, vsr.getNumberOfObservations()); } ScenarioReport report2 = experiment.getSimulationReportForScenario("Staffing2"); assertNotNull(report2); assertEquals("Staffing2", report2.getScenarioName()); assertEquals(1440.0, report2.getSimulationRunTime(), 0.001); assertEquals(3, report2.getStateWaitingTimes().size()); assertEquals(1, report1.getCycleTimesValueStatistics().size()); assertEquals(2, report2.getResourcePoolWaitingTimes().size()); } /** * This test case shows how to identify the appropriate staffing strategy */ public void testIdentifyResourceCount() { String processXml = "<process-definition name='test' start-distribution='start dist'>" + " <distribution name='start dist' sample-type='real' type='normal' mean='10' standardDeviation='5'/> " + " <distribution name='task dist' sample-type='real' type='normal' mean='20' standardDeviation='5'/> " + " <swimlane name='clerk' pool-size='10' />" + " <start-state name='start'>" + " <transition to='task one' />" + " </start-state>" + " <task-node name='task one'>" + " <task swimlane='clerk' time-distribution='task dist' />" + " <transition to='end' />" + " </task-node>" + " <end-state name='end'/>" + "</process-definition>" ; String experimentConfiguration = "<experiment name='StaffingExperiment'>" + " <scenario name='Only one poor guy'>" + " <resource-pool name='clerk' pool-size='1' />" + " <sim-process name='test' />" + " </scenario>" + " <scenario name='Two people'>" + " <resource-pool name='clerk' pool-size='2' />" + " <sim-process name='test' />" + " </scenario>" + " <scenario name='Three people'>" + " <resource-pool name='clerk' pool-size='3' />" + " <sim-process name='test' />" + " </scenario>" + " <scenario name='Five people'>" + " <resource-pool name='clerk' pool-size='5' />" + " <sim-process name='test' />" + " </scenario>" + " <scenario name='A real crowd'>" + " <resource-pool name='clerk' pool-size='10' />" + " <sim-process name='test' />" + " </scenario>" + " <output path='target' />" + // currently just used as parameter for DESMO-J "</experiment>"; ExperimentReader reader = new ExperimentReader(experimentConfiguration); reader.addProcessDefinition( "test", processXml ); JbpmSimulationExperiment experiment = reader.readExperiment(); experiment.setWriteDesmojHtmlOutput(true); experiment.run(); /* * Here are the results: * * ***Waiting time before Task*** * People Mean StandardDev Min Max * One 373 230 0 764 * Two 70 42 0 137 * Three 1.4 3.4 0 19 * Five 0 0 0 1.7 * Ten 0 0 0 0 * * * ***Cycle Times*** * People Mean StandardDev Min Max * One 388 227 34 776 * Two 90 41 14 168 * Three 22 8 0 44 * Five 20 7 1 39 * Ten 20 7 1 39 * * * ***Queue*** * People Length Avg Waiting Avg. * One 40 378 * Two 7 72 * Three 0.14 6 * Five 0 1.8 * Ten 0 0 * * So: What goals do we have to compare scenarios: * 1.) How much resources would be "good"? * 2.) If we pump in X orders now, when are we finished? */ // now lets check the results ScenarioReport report1 = experiment.getSimulationReportForScenario("Only one poor guy"); assertNotNull(report1); assertEquals("Only one poor guy", report1.getScenarioName()); assertEquals(1440.0, report1.getSimulationRunTime(), 0.0001); assertEquals(373.40751, report1.getStateWaitingTimes("task one").getMean(), 0.0001); assertEquals(388.50746, report1.getCycleTimesValueStatistics("test").getMean(), 0.0001); assertEquals( 40.34285, report1.getResourcePoolWaitingTimes("clerk").getAverageLength(), 0.0001); assertEquals(378.98076, report1.getResourcePoolWaitingTimes("clerk").getAverageWaitTime(), 0.0001); ScenarioReport report2 = experiment.getSimulationReportForScenario("Two people"); assertNotNull(report2); assertEquals("Two people", report2.getScenarioName()); assertEquals(1440.0, report2.getSimulationRunTime(), 0.0001); assertEquals(70.16351, report2.getStateWaitingTimes("task one").getMean(), 0.0001); assertEquals(90.61314, report2.getCycleTimesValueStatistics("test").getMean(), 0.0001); assertEquals( 7.21773, report2.getResourcePoolWaitingTimes("clerk").getAverageLength(), 0.0001); assertEquals(72.78156, report2.getResourcePoolWaitingTimes("clerk").getAverageWaitTime(), 0.0001); ScenarioReport report3 = experiment.getSimulationReportForScenario("Three people"); assertNotNull(report3); assertEquals("Three people", report3.getScenarioName()); assertEquals(1440.0, report3.getSimulationRunTime(), 0.0001); assertEquals( 1.39201, report3.getStateWaitingTimes("task one").getMean(), 0.0001); assertEquals(22.63514, report3.getCycleTimesValueStatistics("test").getMean(), 0.0001); assertEquals( 0.14597, report3.getResourcePoolWaitingTimes("clerk").getAverageLength(), 0.0001); assertEquals( 6.00554, report3.getResourcePoolWaitingTimes("clerk").getAverageWaitTime(), 0.0001); ScenarioReport report4 = experiment.getSimulationReportForScenario("Five people"); assertNotNull(report4); assertEquals("Five people", report4.getScenarioName()); assertEquals(1440.0, report4.getSimulationRunTime(), 0.0001); assertEquals( 0.01188, report4.getStateWaitingTimes("task one").getMean(), 0.0001); assertEquals(20.87838, report4.getCycleTimesValueStatistics("test").getMean(), 0.0001); assertEquals( 0.00125, report4.getResourcePoolWaitingTimes("clerk").getAverageLength(), 0.0001); assertEquals( 1.79324, report4.getResourcePoolWaitingTimes("clerk").getAverageWaitTime(), 0.0001); ScenarioReport report5 = experiment.getSimulationReportForScenario("A real crowd"); assertNotNull(report5); assertEquals("A real crowd", report5.getScenarioName()); assertEquals(1440.0, report5.getSimulationRunTime(), 0.0001); assertEquals( 0.0 , report5.getStateWaitingTimes("task one").getMean(), 0.0001); assertEquals(20.89189, report5.getCycleTimesValueStatistics("test").getMean(), 0.0001); assertEquals( 0.0 , report5.getResourcePoolWaitingTimes("clerk").getAverageLength(), 0.0001); assertEquals( 0.0 , report5.getResourcePoolWaitingTimes("clerk").getAverageWaitTime(), 0.0001); } }