| Global | |
| Event scheduling algorithm | Deterministically |
| Import | import java.util.*; import java.io.*; import java.text.*; |
// Filename: OptionBox.java // Revision: 1 // Author: Joey Morris // Purpose: Create a simple "option box" widget for use in AnyLogic models. // Option boxes may also be known as "drop-down menus" or // "combo boxes". // // Software: AnyLogic 5.5 // // Revision History // Date Author Comment // ----------- ------ ------- // 12-Jun-2007 JM Initial revision. // Modify the following line so that the package name here matches the package // name in the AnyLogic model. package animation; import com.xj.anylogic.animation.*; import java.util.List; import java.util.ArrayList; import java.awt.Color; //------------------------------------------------------------------------------ // Usage :: Installing // // 1) Copy OptionBox.java and OptionItem.java into a folder accessible by your // AnyLogic model. // 2) Add the files into your model by right-clicking a package and selecting // "Add External File..." from the menu. (You should be able to move your // model and the .java files around to different folders as long as their // relative paths stay the same. // 3) Modify the package declaration in both OptionBox.java and OptionItem.java // to match the package name where you added the files in step (2). // // Usage :: Adding an OptionBox to your animation // // 1) In the animation's Additional Class Code, declare the OptionBox: // // OptionBox shapeOption; // // 2) In the animation's Setup Code, create the OptionBox: // // shapeOption = new OptionBox(this); // // 3) In the animation's Setup Code, add options to the OptionBox by passing // OptionItem objects to the addOptionItem() method. To be useful, you will // need to create subclasses of OptionItem and override its onSelect() // method to run whatever code you want to run when the option is selected. // You can do this the quick way using "anonymous inner classes": // // shapeOption.addOptionItem( // new OptionItem("Circle") { // public void onSelect() { // // your code here, for example: // shape = "circle"; // } // } // ); // shapeOption.addOptionItem( // new OptionItem("Square") { // public void onSelect() { // // your code here, for example: // shape = "square"; // } // } // ); // // You can also explicitly create the subclasses if you want: // // class CircleOption extends OptionItem { // CircleOption(String name) { // super(name); // } // public void onSelect() { // // your code here, for example: // shape = "circle"; // } // } // class SquareOption extends OptionItem { // SquareOption(String name) { // super(name); // } // public void onSelect() { // // your code here, for example: // shape = "square"; // } // } // // OptionItem circle = new CircleOption("Circle"); // shapeOption.addOptionItem(circle); // shapeOption.addOptionItem(new SquareOption("Square")); // // You may also override OptionItem's onUnselect() method to execute code // whenever selection is changed from that OptionItem to another. // // Code that you place in the onSelect() methods must be accessible from the // animation. Typically, any variables and methods that you define in the // animation's Additional Class Code or in the Active Object that contains // the animation will be accessible. // // 4) In the animation's Setup Code, add code to configure the OptionBox's // size, colors, etc.: // // shapeOption.setPos(0, 100); // shapeOption.setItemWidth(80); // shapeOption.setTextColor(Color.blue); // // 5) In the animation's Setup Code, choose the initially selected option by // calling one of the setSelectedItem() methods: // // shapeOption.setSelectedItem(0); // // or // shapeOption.setSelectedItem("Circle"); // // or // shapeOption.setSelectedItem(circle); // // 6) In the animation's Additional Class Code, override the animation's // onMouseClicked() method to pass mouse clicks on to the option box: // // protected void onMouseClicked(java.awt.Point p) { // if (shapeOption.handleClick(p.getX(), p.getY())) { // // the click was inside the shapeOption, so there is no need to // // process the click further // return; // } // // ... // } // // The code above that should go in the animation's Setup Code may instead // need to go in the animation's Update Code, enclosed in the condition // if (Engine.getTime() == 0). This may be necessary if the code references // any encapsulated objects, because Setup Code might not be executed after // the encapsulated objects are created, but the Update Code at time 0 will. // //------------------------------------------------------------------------------ public class OptionBox { /** * Class constructor. * * @param g animation group to which this option box is to be added */ public OptionBox(Group g) { animation = g; optionItems = new ArrayList(); selectedItem = null; areOptionsVisible = false; itemWidth = 100; itemHeight = 20; fillColor = Color.white; textColor = Color.black; textOffsetX = 10; textOffsetY = 3; fontSize = 10; unselectedText = "Select One"; headerBox = new ShapeRect(); headerLabel = new ShapeText(); arrowBox = new ShapeRect(); arrow = new ShapePoly(); arrow.setPoints(3); arrow.setClosed(true); optionsBox = new ShapeRect(); optionsBox.setVisible(false); container = new Group(); headerContainer = new Group(); arrowContainer = new Group(); animation.add(container); container.add(headerContainer); container.add(optionsBox); headerContainer.add(arrowContainer); headerContainer.add(headerBox); headerContainer.add(headerLabel); arrowContainer.add(arrowBox); arrowContainer.add(arrow); this.redraw(); this.resetHeaderText(); } //------------------------------------------------------- // Behavioral methods. // /** * Inserts the specified option item at the specified position in this option * box's list of options. Shifts the element currently at that position and * all subsequent elements down in the list. * * @param index position at which the item is to be inserted * @param item item to be inserted */ public void addOptionItem(int index, OptionItem item) { optionItems.add(index, item); item.setVisible(false); // Since OptionItem is not derived from ShapeBase, we cannot add it // directly to our animation. Instead, we must ask the OptionItem to do // it so that it can add its own shapes to the animation. item.addToAnimation(animation); redraw(); } /** * Appends the specified option item to this option box's list of options. * * @param item item to be appended */ public void addOptionItem(OptionItem item) { this.addOptionItem(optionItems.size(), item); } /** * Processes a mouse click at the specified coordinates. If this option box * is not visible, then the mouse click is ignored. * * @param x x-coordinate of the mouse click * @param y y-coordinate of the mouse click * @return <code>true</code> if the mouse click was handled by this option * box; <code>false</code> otherwise */ public boolean handleClick(double x, double y) { boolean isClicked = false; if (headerContainer.isVisible()) { if (areOptionsVisible) { if (headerContainer.contains(x - container.getX(), y - container.getY())) { isClicked = true; this.hideOptions(); } else { for (int i = 0; i < optionItems.size(); i++) { OptionItem item = (OptionItem)optionItems.get(i); if (item.contains(x, y)) { isClicked = true; this.setSelectedItem(i); this.hideOptions(); break; } } } } else { if (headerContainer.contains(x - container.getX(), y - container.getY())) { isClicked = true; this.showOptions(); } } } return isClicked; } /** * Makes the specified option item the currently selected item in this option * box. Execute the previously selected (if any) item's * <code>onUnselect</code> method and then the newly selected item's * <code>onSelect</code> method. If the item is not in this option box's list * of options, do nothing. * * @param item the item to select */ public void setSelectedItem(OptionItem item) { if (selectedItem == null || !selectedItem.equals(item)) { if (optionItems.contains(item)) { if (selectedItem != null) { selectedItem.onUnselect(); } selectedItem = item; selectedItem.onSelect(); this.resetHeaderText(); } } } /** * Makes the option item with the specified index the currently selected item * in this option box. Items are assigned an index starting at 0 based on the * order they were added to this option box using the * <code>addOptionItem</code> method. Execute the previously selected (if * any) item's <code>onUnselect</code> method and then the newly selected * item's <code>onSelect</code> method. If no item in this option box's * list of options has the specified index, do nothing. * * @param index the index of the item to select */ public void setSelectedItem(int index) { if (index >= 0 && index < optionItems.size()) { this.setSelectedItem((OptionItem)optionItems.get(index)); } } /** * Makes the option item with the specified name the currently selected item * in this option box. Execute the previously selected (if any) item's * <code>onUnselect</code> method and then the newly selected item's * <code>onSelect</code> method. If no item in this option box's list of * options has the specified name, do nothing. * * @param name name of the item to select */ public void setSelectedItem(String name) { for (int i = 0; i < optionItems.size(); i++) { OptionItem item = (OptionItem)optionItems.get(i); if (item.getText().equals(name)) { this.setSelectedItem(item); } } } /** * Sets this option box to have no selected item. Execute the currently * selected (if any) item's <code>onUnselect</code> method. */ public void setUnselected() { if (selectedItem != null) { selectedItem.onUnselect(); selectedItem = null; this.resetHeaderText(); } } /** * Sets the visibility of this option box. * * @param visible <code>true</code> if the option box should be visible; * <code>false</code> if not */ public void setVisible(boolean visible) { headerContainer.setVisible(visible); optionsBox.setVisible(visible && areOptionsVisible); for (int i = 0; i < optionItems.size(); i++) { OptionItem item = (OptionItem)optionItems.get(i); item.setVisible(visible && areOptionsVisible); } } //------------------------------------------------------- // Info methods. // /** * Returns the currently selected option item. * * @return the currently selected item, or <code>null</code> if no item is * currently selected */ public OptionItem getSelectedItem() { return selectedItem; } //------------------------------------------------------- // Configuration methods. // /** * Sets the position of the top left corner of this option box. * * @param x the x-coordinate where the option box is to be placed. The * default is 0. * @param y the y-coordinate where the option box is to be placed. The * default is 0. */ public void setPos(double x, double y) { if (container.getX() != x || container.getY() != y) { container.setPos(x, y); redraw(); } } /** * Sets the width of the items in this option box. The entire option box will * be slightly wider since it also includes an arrow beside the items. * * @param width width, in pixels, of the option items. The default is 100. */ public void setItemWidth(double width) { if (itemWidth != width) { itemWidth = width; redraw(); } } /** * Sets the height of the items in this option box. When the list of options * is hidden, this will be the height of the option box. When the list of * options is shown, the height of the option box will be (n+1)*height, where * n is the number of items in the option box. * * @param height height, in pixels, of the option items. The default is 20. */ public void setItemHeight(double height) { if (itemHeight != height) { itemHeight = height; this.redraw(); } } /** * Sets the background color for all the elements of this option box. * * @param color background color for the option box. The default is white. */ public void setFillColor(Color color) { if (!fillColor.equals(color)) { fillColor = color; this.redraw(); } } /** * Sets the text color for all the elements of this option box. The arrow * will also be displayed in this color. * * @param color text color for the option box. The default is black. */ public void setTextColor(Color color) { if (!textColor.equals(color)) { textColor = color; this.redraw(); } } /** * Sets the distance from the top left corner of each option item to the top * left corner of the text label in the item. * * @param x horizontal distance, in pixels, from the left edge of the item to * the left edge of the text label. The default is 10. * @param y vertical distance, in pixels, from the top edge of the item to * the top edge of the text label. The default is 3. */ public void setTextOffset(double x, double y) { if (textOffsetX != x || textOffsetY != y) { textOffsetX = x; textOffsetY = y; this.redraw(); } } /** * Sets the font size for all text labels in this option box. * * @param size the font size. The default is 10. */ public void setFontSize(int size) { if (fontSize != size) { fontSize = size; this.redraw(); } } /** * Sets the text that appears in this option box's selected area when no item * is currently selected. * * @param text text that appears when no item is selected. The default is * "Select One". */ public void setUnselectedText(String text) { if (!unselectedText.equals(text)) { unselectedText = text; this.resetHeaderText(); } } /** * Sets the text label for the item with the specified index. Items are * assigned an index starting at 0 based on the order they were added to * this option box using the <code>addOptionItem</code> method. If no item * in this option box's list of options has the specified index, do nothing. * * @param index the index of the item whose text is to be changed * @param text the new text label for the item */ public void setItemText(int index, String text) { if (index >= 0 && index < optionItems.size()) { OptionItem item = (OptionItem)optionItems.get(index); item.setText(text); if (item.equals(selectedItem)) { this.resetHeaderText(); } } } //------------------------------------------------------- // Protected methods. // /** * Redraws all elements of this option box. This method should be called by * methods that change the size, position, or color of any element. */ protected void redraw() { headerContainer.setPos(0, 0); headerBox.setPos(0, 0); headerBox.setSize(itemWidth, itemHeight); headerBox.setFillColor(fillColor); headerLabel.setPos(textOffsetX, textOffsetY); headerLabel.setFontColor(textColor); headerLabel.setFontSize(fontSize); arrowContainer.setPos(itemWidth, 0); arrowBox.setPos(0, 0); arrowBox.setSize(itemHeight, itemHeight); arrowBox.setFillColor(fillColor); arrow.setPoint(0, 0.25 * itemHeight, 0.50 * itemHeight); arrow.setPoint(1, 0.75 * itemHeight, 0.50 * itemHeight); arrow.setPoint(2, 0.50 * itemHeight, 0.75 * itemHeight); arrow.setLineColor(textColor); arrow.setFillColor(textColor); optionsBox.setPos(0, itemHeight); optionsBox.setSize(itemWidth, optionItems.size() * itemHeight); optionsBox.setFillColor(fillColor); for (int i = 0; i < optionItems.size(); i++) { OptionItem item = (OptionItem)optionItems.get(i); item.setPos(container.getX(), container.getY() + itemHeight * (i + 1)); item.setWidth(itemWidth); item.setHeight(itemHeight); item.setTextColor(textColor); item.setTextOffset(textOffsetX, textOffsetY); item.setFontSize(fontSize); } } /** * Displays the list of options, allowing the user to choose an option by * clicking on it. */ protected void showOptions() { areOptionsVisible = true; optionsBox.setVisible(true); for (int i = 0; i < optionItems.size(); i++) { OptionItem item = (OptionItem)optionItems.get(i); item.setVisible(true); } } /** * Hides the list of options that were shown by <code>showOptions</code>. */ protected void hideOptions() { areOptionsVisible = false; optionsBox.setVisible(false); for (int i = 0; i < optionItems.size(); i++) { OptionItem item = (OptionItem)optionItems.get(i); item.setVisible(false); } } /** * Sets the text in this option box's header area to the text associated with * the currently selected option item, or to the <code>unselectedText</code> * if no item is selected. */ protected void resetHeaderText() { if (selectedItem == null) { headerLabel.setText(unselectedText); } else { headerLabel.setText(selectedItem.getText()); } } //------------------------------------------------------- // Fields. // protected Group animation; protected Group container; protected Group headerContainer; protected Group arrowContainer; protected List optionItems; protected OptionItem selectedItem; protected boolean areOptionsVisible; protected double itemWidth; protected double itemHeight; protected Color fillColor; protected Color textColor; protected double textOffsetX; protected double textOffsetY; protected int fontSize; protected String unselectedText; protected ShapeRect headerBox; protected ShapeText headerLabel; protected ShapeRect arrowBox; protected ShapePoly arrow; protected ShapeRect optionsBox; }
// Filename: OptionItem.java // Revision: 1 // Author: Joey Morris // Purpose: Create an "option item" for use in the option boxes created in // OptionBox.java. // // Software: AnyLogic 5.5 // // Revision History // Date Author Comment // ----------- ------ ------- // 11-Jun-2007 JM Initial revision. // Modify the following line so that the package name here matches the package // name in the AnyLogic model. package animation; import com.xj.anylogic.animation.*; import java.awt.Color; //------------------------------------------------------------------------------ // See the discussion in OptionBox.java for usage instructions. //------------------------------------------------------------------------------ public class OptionItem { public OptionItem(String name) { box = new ShapeRect(); box.setLineColor(null); box.setFillColor(null); label = new ShapeText(); label.setText(name); container = new Group(); container.add(box); container.add(label); } public void addToAnimation(Group g) { g.add(container); } public void setVisible(boolean visible) { container.setVisible(visible); } public void setPos(double x, double y) { container.setPos(x, y); } public void setWidth(double width) { box.setWidth(width); } public void setHeight(double height) { box.setHeight(height); } public void setText(String name) { label.setText(name); } public String getText() { return label.getText(); } public void setTextColor(Color color) { label.setFontColor(color); } public void setTextOffset(double x, double y) { label.setPos(x, y); } public void setFontSize(int size) { label.setFontSize(size); } public boolean contains(double x, double y) { return container.contains(x, y); } public void onSelect() { // the default action upon selecting the item is to do nothing } public void onUnselect() { // the default action upon unselecting the item is to do nothing } protected Group container; protected ShapeText label; protected ShapeRect box; }
// Filename: SeriesPlot.java // Revision: 1 // Author: Joey Morris // Purpose: Plot one or more data series on a single set of axes in an AnyLogic // model. The SeriesPlot is intended as a replacement for the // ChartTime object in AnyLogic's Business Graphics Library. // SeriesPlot offers much of the same functionality while providing // more control and, in some cases, is faster. // // Software: AnyLogic 5.5 // // Revision History // Date Author Comment // ----------- ------ ------- // 11-Jun-2007 JM Initial revision. // 19-Jul-2007 JM Removed the code that automatically set the point (0,0) // to be the first point in each series. // Modify the following line so that the package name here matches the package // name in the AnyLogic model. package animation; import com.xj.anylogic.animation.*; import java.text.NumberFormat; import java.awt.Color; import java.awt.Font; //------------------------------------------------------------------------------ // Usage :: Installing // // 1) Copy SeriesPlot.java into a folder accessible by your AnyLogic model. // 2) Add the file into your model by right-clicking a package and selecting // "Add External File..." from the menu. (You should be able to move your // model and the .java file around to different folders as long as their // relative paths stay the same. // 3) Modify the package declaration in SeriesPlot.java to match the package // name where you added the files in step (2). // // Usage :: Adding a SeriesPlot to your animation // // 1) In the animation's Additional Class Code, declare the SeriesPlot: // // SeriesPlot hivPlot; // // 2) In the animation's Setup Code, create the SeriesPlot: // // hivPlot = new SeriesPlot(this, 3); // // 3) public class SeriesPlot { /** * Creates a <code>SeriesPlot</code> in the specified animation having the * specified number of data series. * * @param g animation group to which this <code>SeriesPlot</code> is to be * added * @param numSeries number of data series in this <code>SeriesPlot</code> */ public SeriesPlot(Group g, int numSeries) { container = new Group(); seriesNames = new String[numSeries]; seriesPlots = new ShapePoly[numSeries]; seriesLastValueX = new double[numSeries]; seriesLastValueY = new double[numSeries]; for (int i = 0; i < numSeries; i++) { seriesNames[i] = new String("series " + i); seriesPlots[i] = new ShapePoly(); seriesPlots[i].setPos(0, 0); seriesPlots[i].setClosed(false); seriesPlots[i].setPoints(0); container.add(seriesPlots[i]); } xaxis = new ShapeLine(); xaxis.setPoint1(0, 0); xaxis.setPoint2Y(0); container.add(xaxis); xaxisTickLabelMin = new ShapeText(); xaxisTickLabelMin.setPosX(0); container.add(xaxisTickLabelMin); xaxisTickLabelMax = new ShapeText(); container.add(xaxisTickLabelMax); xaxisTitle = new ShapeText(); container.add(xaxisTitle); yaxis = new ShapeLine(); yaxis.setPoint1(0, 0); yaxis.setPoint2X(0); container.add(yaxis); yaxisTickLabelMin = new ShapeText(); yaxisTickLabelMin.setPosY(0); container.add(yaxisTickLabelMin); yaxisTickLabelMax = new ShapeText(); container.add(yaxisTickLabelMax); yaxisTitle = new ShapeText(); container.add(yaxisTitle); legendContainer = new Group(); legendLines = new ShapeLine[numSeries]; legendLabels = new ShapeText[numSeries]; for (int i = 0; i < numSeries; i++) { legendLines[i] = new ShapeLine(); legendContainer.add(legendLines[i]); legendLabels[i] = new ShapeText(); legendContainer.add(legendLabels[i]); } container.add(legendContainer); plotTitle = new ShapeText(); container.add(plotTitle); xaxisScale = 1; yaxisScale = 1; xaxisValueMin = 0; yaxisValueMin = 0; this.setPos(0, 0); this.setWidth(200); this.setHeight(100); this.setXaxisRescaleFactor(2); this.setXaxisTickLabelOffset(5); this.setXaxisTickLabelRotation(0); this.setXaxisTickLabelFontSize(8); this.setXaxisTickLabelFormat(null); this.setXaxisTitle("x"); this.setXaxisTitleOffset(20, 15); this.setXaxisTitleFontSize(8); this.setXaxisTitleFontStyle(Font.BOLD); this.setXaxisTitleVisible(false); this.setYaxisRescaleFactor(2); this.setYaxisTickLabelOffset(13); this.setYaxisTickLabelRotation(90); this.setYaxisTickLabelFontSize(8); this.setYaxisTickLabelFormat(null); this.setYaxisTitle("y"); this.setYaxisTitleOffset(25, 20); this.setYaxisTitleRotation(90); this.setYaxisTitleFontSize(8); this.setYaxisTitleFontStyle(Font.BOLD); this.setYaxisTitleVisible(false); this.setLegendOffset(0, 40); this.setLegendItemHeight(10); this.setLegendLineLength(10); this.setLegendLabelOffset(5); this.setLegendLabelFontSize(8); this.setLegendContainsValues(false); this.setLegendValuesFormat(null); this.setLegendVisible(false); this.setPlotTitleOffset(10, 20); this.setPlotTitleFontSize(10); this.setPlotTitleFontStyle(Font.BOLD); this.setPlotTitleVisible(false); g.add(container); } public void addPoint(int seriesNum, double valueX, double valueY) { if (seriesNum >= 0 && seriesNum < seriesPlots.length) { seriesLastValueX[seriesNum] = valueX; seriesLastValueY[seriesNum] = valueY; double pointX = valueX / xaxisScale; double pointY = -valueY / yaxisScale; seriesPlots[seriesNum].addPoint(pointX, pointY); if (pointX > xaxisLength) { rescaleX(xaxisRescaleFactor); } if (-pointY > yaxisLength) { rescaleY(yaxisRescaleFactor); } if (legendContainsValues) { redrawLegendLabel(seriesNum); } } } //------------------------------------------------------ // configuring the data series // public void setSeriesColor(int seriesNum, Color color) { if (seriesNum >= 0 && seriesNum < seriesPlots.length) { seriesPlots[seriesNum].setColor(color); legendLines[seriesNum].setColor(color); } } public void setSeriesName(int seriesNum, String name) { if (seriesNum >= 0 && seriesNum < seriesPlots.length) { seriesNames[seriesNum] = name; redrawLegendLabel(seriesNum); } } //------------------------------------------------------ // configuring the plot as a whole // public void setVisible(boolean visible) { container.setVisible(visible); } public void setPos(double x, double y) { container.setPos(x, y); } public void setWidth(double width) { xaxisLength = width; xaxis.setPoint2X(xaxisLength); xaxisTickLabelMax.setPosX(xaxisLength); double newXaxisScale = (xaxisValueMax - xaxisValueMin) / xaxisLength; rescaleX(newXaxisScale / xaxisScale); } public void setHeight(double height) { double deltaHeight = height - yaxisLength; yaxisLength = height; yaxis.setPoint2Y(-yaxisLength); yaxisTickLabelMax.setPosY(-yaxisLength); double newYaxisScale = (yaxisValueMax - yaxisValueMin) / yaxisLength; rescaleY(newYaxisScale / yaxisScale); plotTitle.setPosY(plotTitle.getY() - deltaHeight); } //------------------------------------------------------ // configuring the x-axis // public void setXaxisValueMax(double max) { if (max > xaxisValueMin) { double newXaxisScale = (max - xaxisValueMin) / xaxisLength; rescaleX(newXaxisScale / xaxisScale); } } public void setXaxisRescaleFactor(double factor) { xaxisRescaleFactor = factor; } public void setXaxisTickLabelOffset(double y) { xaxisTickLabelMin.setPosY(y); xaxisTickLabelMax.setPosY(y); } public void setXaxisTickLabelRotation(double degrees) { xaxisTickLabelMin.setRotation(-(degrees/180) * java.lang.Math.PI); xaxisTickLabelMax.setRotation(-(degrees/180) * java.lang.Math.PI); } public void setXaxisTickLabelFontSize(int size) { xaxisTickLabelMin.setFontSize(size); xaxisTickLabelMax.setFontSize(size); } public void setXaxisTickLabelFormat(NumberFormat fmt) { xaxisTickLabelFormat = fmt; redrawXaxisTickLabels(); } //------------------------------------------------------ // configuring the x-axis title // public void setXaxisTitle(String text) { xaxisTitle.setText(text); } public void setXaxisTitleOffset(double x, double y) { xaxisTitle.setPos(x, y); } public void setXaxisTitleFontSize(int size) { xaxisTitle.setFontSize(size); } public void setXaxisTitleFontStyle(int style) { xaxisTitle.setFontStyle(style); } public void setXaxisTitleVisible(boolean visible) { xaxisTitle.setVisible(visible); } //------------------------------------------------------ // configuring the y-axis // public void setYaxisValueMax(double max) { if (max > yaxisValueMin) { double newYaxisScale = (max - yaxisValueMin) / yaxisLength; rescaleY(newYaxisScale / yaxisScale); } } public void setYaxisRescaleFactor(double factor) { yaxisRescaleFactor = factor; } public void setYaxisTickLabelOffset(double x) { yaxisTickLabelMin.setPosX(-x); yaxisTickLabelMax.setPosX(-x); } public void setYaxisTickLabelRotation(double degrees) { yaxisTickLabelMin.setRotation(-(degrees/180) * java.lang.Math.PI); yaxisTickLabelMax.setRotation(-(degrees/180) * java.lang.Math.PI); } public void setYaxisTickLabelFontSize(int size) { yaxisTickLabelMin.setFontSize(size); yaxisTickLabelMax.setFontSize(size); } public void setYaxisTickLabelFormat(NumberFormat fmt) { yaxisTickLabelFormat = fmt; redrawYaxisTickLabels(); } //------------------------------------------------------ // configuring the y-axis title // public void setYaxisTitle(String text) { yaxisTitle.setText(text); } public void setYaxisTitleOffset(double x, double y) { yaxisTitle.setPos(-x, -y); } public void setYaxisTitleRotation(double degrees) { yaxisTitle.setRotation(-(degrees/180) * java.lang.Math.PI); } public void setYaxisTitleFontSize(int size) { yaxisTitle.setFontSize(size); } public void setYaxisTitleFontStyle(int style) { yaxisTitle.setFontStyle(style); } public void setYaxisTitleVisible(boolean visible) { yaxisTitle.setVisible(visible); } //------------------------------------------------------ // configuring the plot title // public void setPlotTitleVisible(boolean visible) { plotTitle.setVisible(visible); } public void setPlotTitle(String title) { plotTitle.setText(title); } public void setPlotTitleOffset(double x, double y) { plotTitle.setPos(x, -(yaxisLength + y)); } public void setPlotTitleFontSize(int size) { plotTitle.setFontSize(size); } public void setPlotTitleFontStyle(int style) { plotTitle.setFontStyle(style); } //------------------------------------------------------ // configuring the legend // public void setLegendVisible(boolean visible) { legendContainer.setVisible(visible); } public void setLegendOffset(double x, double y) { legendContainer.setPos(x, y); } public void setLegendItemHeight(double height) { for (int i = 0; i < seriesPlots.length; i++) { legendLines[i].setPoint1Y(height*i + height/2); legendLines[i].setPoint2Y(height*i + height/2); legendLabels[i].setPosY(height*i); } } public void setLegendLineLength(double length) { for (int i = 0; i < seriesPlots.length; i++) { double deltaLength = length - legendLines[i].length(); legendLines[i].setPoint2X(length); legendLabels[i].setPosX(legendLabels[i].getX() + deltaLength); } } public void setLegendLabelOffset(double x) { for (int i = 0; i < seriesPlots.length; i++) { legendLabels[i].setPosX(legendLines[i].length() + x); } } public void setLegendLabelFontSize(int size) { for (int i = 0; i < seriesPlots.length; i++) { legendLabels[i].setFontSize(size); } } public void setLegendContainsValues(boolean hasValues) { legendContainsValues = hasValues; for (int i = 0; i < seriesPlots.length; i++) { redrawLegendLabel(i); } } public void setLegendValuesFormat(NumberFormat fmt) { legendValuesFormat = fmt; for (int i = 0; i < seriesPlots.length; i++) { redrawLegendLabel(i); } } //------------------------------------------------------ // protected methods // protected void rescaleX(double factor) { if (factor > 0) { for (int seriesNum = 0; seriesNum < seriesPlots.length; seriesNum++) { for (int i = 0; i < seriesPlots[seriesNum].getPoints(); i++) { seriesPlots[seriesNum].setPointX(i, seriesPlots[seriesNum].getPointX(i) / factor); } } xaxisScale *= factor; xaxisValueMax = xaxisValueMin + xaxisLength * xaxisScale; redrawXaxisTickLabels(); } } protected void rescaleY(double factor) { if (factor > 0) { for (int seriesNum = 0; seriesNum < seriesPlots.length; seriesNum++) { for (int i = 0; i < seriesPlots[seriesNum].getPoints(); i++) { seriesPlots[seriesNum].setPointY(i, seriesPlots[seriesNum].getPointY(i) / factor); } } yaxisScale *= factor; yaxisValueMax = yaxisValueMin + yaxisLength * yaxisScale; redrawYaxisTickLabels(); } } protected void redrawXaxisTickLabels() { if (xaxisTickLabelFormat != null) { xaxisTickLabelMin.setText(xaxisTickLabelFormat.format(xaxisValueMin)); xaxisTickLabelMax.setText(xaxisTickLabelFormat.format(xaxisValueMax)); } else { xaxisTickLabelMin.setText(String.valueOf(xaxisValueMin)); xaxisTickLabelMax.setText(String.valueOf(xaxisValueMax)); } } protected void redrawYaxisTickLabels() { if (yaxisTickLabelFormat != null) { yaxisTickLabelMin.setText(yaxisTickLabelFormat.format(yaxisValueMin)); yaxisTickLabelMax.setText(yaxisTickLabelFormat.format(yaxisValueMax)); } else { yaxisTickLabelMin.setText(String.valueOf(yaxisValueMin)); yaxisTickLabelMax.setText(String.valueOf(yaxisValueMax)); } } protected void redrawLegendLabel(int seriesNum) { if (seriesNum >= 0 && seriesNum < seriesPlots.length) { String seriesName = seriesNames[seriesNum]; if (legendContainsValues) { if (legendValuesFormat != null) { legendLabels[seriesNum].setText(seriesName + " :: " + legendValuesFormat.format(seriesLastValueY[seriesNum])); } else { legendLabels[seriesNum].setText(seriesName + " :: " + seriesLastValueY[seriesNum]); } } else { legendLabels[seriesNum].setText(seriesName); } } } //------------------------------------------------------ // fields // protected Group container; protected String[] seriesNames; protected ShapePoly[] seriesPlots; protected double[] seriesLastValueX; protected double[] seriesLastValueY; protected ShapeText plotTitle; protected ShapeLine xaxis; protected double xaxisScale; protected double xaxisRescaleFactor; protected double xaxisLength; protected double xaxisValueMin; protected double xaxisValueMax; protected ShapeText xaxisTickLabelMin; protected ShapeText xaxisTickLabelMax; protected NumberFormat xaxisTickLabelFormat; protected ShapeText xaxisTitle; protected ShapeLine yaxis; protected double yaxisScale; protected double yaxisRescaleFactor; protected double yaxisLength; protected double yaxisValueMin; protected double yaxisValueMax; protected ShapeText yaxisTickLabelMin; protected ShapeText yaxisTickLabelMax; protected NumberFormat yaxisTickLabelFormat; protected ShapeText yaxisTitle; protected Group legendContainer; protected ShapeText[] legendLabels; protected ShapeLine[] legendLines; protected boolean legendContainsValues; protected NumberFormat legendValuesFormat; }
| General | |
| Import | import message.*; import misc.*; |
| Parameters | |
| Name | homeX |
| Type | real |
| Name | homeY |
| Type | real |
| Name | initialMoney |
| Type | real |
| Name | initialInventory |
| Type | real |
| Name | initialAddiction |
| Type | real |
| Name | initialConcentration |
| Type | real |
| Name | metabolismRate |
| Type | real |
| Name | addictionIncreaseDuration |
| Type | real |
| Name | addictionIncreaseRate |
| Type | real |
| Name | addictionDecreaseOnset |
| Type | real |
| Name | addictionDecreaseRate |
| Type | real |
| Name | incomeAmount |
| Type | real |
| Name | incomeInterval |
| Type | real |
| Name | windfallAmountMin |
| Type | real |
| Name | windfallAmountMax |
| Type | real |
| Name | windfallIntervalMin |
| Type | real |
| Name | windfallIntervalMax |
| Type | real |
| Name | randomUseIntervalMin |
| Type | real |
| Name | randomUseIntervalMax |
| Type | real |
| Name | useDelayMin |
| Type | real |
| Name | useDelayMax |
| Type | real |
| Name | retryDelayMin |
| Type | real |
| Name | retryDelayMax |
| Type | real |
| Name | buyMethod |
| Type | String |
| Name | visionRadius |
| Type | real |
| Name | desperateNeedThreshold |
| Type | real |
| Name | desperateAddictionThreshold |
| Type | real |
| Name | probUseAtSeller |
| Type | real |
| Name | probSeekMoney |
| Type | real |
| Name | probSeekMoneySuccess |
| Type | real |
| Name | seekMoneyDelayMin |
| Type | real |
| Name | seekMoneyDelayMax |
| Type | real |
| Name | probTryPrivateDealer |
| Type | real |
| Name | acceptableSdQueueLength |
| Type | integer |
| Name | acceptablePdQueueLength |
| Type | integer |
| Name | treatmentDelayMin |
| Type | real |
| Name | treatmentDelayMax |
| Type | real |
| Name | treatmentAddictionReduction |
| Type | real |
| Name | initialTimeSinceLastUse |
| Type | real |
| Name | probUseTogether |
| Type | real |
| Name | initialHIV |
| Type | boolean |
| Name | marketQuitTime |
| Type | real |
| Icon | |
| Picture | |
| Structure | |||||||||||||||||||||||||||||||
| Picture | ![]() |
||||||||||||||||||||||||||||||
| ChartTimer | dealQuitTimer | ||||||||||||||||||||||||||||||
| Expire | No (manual mode) | ||||||||||||||||||||||||||||||
| Expiry Action | DealDeniedMsg msg = new DealDeniedMsg(); msg.dealID = dealToSeller.dealID; self.receiveDealDeniedMsg(msg); |
||||||||||||||||||||||||||||||
| ChartTimer | windfallTimer | ||||||||||||||||||||||||||||||
| Timeout | uniform(windfallIntervalMin, windfallIntervalMax) | ||||||||||||||||||||||||||||||
| Expire At Startup | No | ||||||||||||||||||||||||||||||
| Expiry Action | updateMoney(uniform(windfallAmountMin, windfallAmountMax)); |
||||||||||||||||||||||||||||||
| ChartTimer | incomeTimer | ||||||||||||||||||||||||||||||
| Timeout | incomeInterval | ||||||||||||||||||||||||||||||
| Expire At Startup | No | ||||||||||||||||||||||||||||||
| Expiry Action | updateMoney(incomeAmount); | ||||||||||||||||||||||||||||||
| Variable | isUsingAlone | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | targetPrice | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Variable | targetUnits | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Variable | pendingInvitations | ||||||||||||||||||||||||||||||
| Variable type | List | ||||||||||||||||||||||||||||||
| Initial value | new ArrayList() | ||||||||||||||||||||||||||||||
| Variable | isUsingWithSeller | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | lastHarassTime | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | isWaitingOnSeller | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | isBeingHarassed | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | possessionUnits | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | numArrests | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | arrestDuration | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Variable | dealFromSeller | ||||||||||||||||||||||||||||||
| Variable type | DealCompleteMsg | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | visibleStreetSellersIterator | ||||||||||||||||||||||||||||||
| Variable type | Iterator | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | visibleStreetSellers | ||||||||||||||||||||||||||||||
| Variable type | List | ||||||||||||||||||||||||||||||
| Initial value | new ArrayList() | ||||||||||||||||||||||||||||||
| Variable | currentPlace | ||||||||||||||||||||||||||||||
| Variable type | integer | ||||||||||||||||||||||||||||||
| Initial value | Main.PLACE_HOME | ||||||||||||||||||||||||||||||
| Variable | marketStartTime | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | main | ||||||||||||||||||||||||||||||
| Variable type | Main | ||||||||||||||||||||||||||||||
| Initial value | (Main)getOwner() | ||||||||||||||||||||||||||||||
| Variable | targetSellerHistory | ||||||||||||||||||||||||||||||
| Variable type | AgentHistory | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | targetSellerY | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | targetSellerX | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | willUseWithSeller | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | willUseAtSeller | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | targetUsePartner | ||||||||||||||||||||||||||||||
| Variable type | User | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | isActive | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | dealToSeller | ||||||||||||||||||||||||||||||
| Variable type | DealRequestMsg | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | self | ||||||||||||||||||||||||||||||
| Variable type | Customer | ||||||||||||||||||||||||||||||
| Initial value | this | ||||||||||||||||||||||||||||||
| Variable | targetMarket | ||||||||||||||||||||||||||||||
| Variable type | Market | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | targetSeller | ||||||||||||||||||||||||||||||
| Variable type | Seller | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | money | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | initialMoney | ||||||||||||||||||||||||||||||
| Port | randomUseListener | ||||||||||||||||||||||||||||||
| Message type | RandomUseMsg | ||||||||||||||||||||||||||||||
| Port | wantFixListener | ||||||||||||||||||||||||||||||
| Message type | WantFixMsg | ||||||||||||||||||||||||||||||
| Port | travelCompleteListener | ||||||||||||||||||||||||||||||
| Message type | TravelCompleteMsg | ||||||||||||||||||||||||||||||
| Statechart | simulationState | ||||||||||||||||||||||||||||||
| Object | location | ||||||||||||||||||||||||||||||
| Type | misc.Location | ||||||||||||||||||||||||||||||
| Parameters |
|
||||||||||||||||||||||||||||||
| Object | userBehavior | ||||||||||||||||||||||||||||||
| Type | misc.UserBehavior | ||||||||||||||||||||||||||||||
| Parameters |
|
||||||||||||||||||||||||||||||
| Object | marketHistories | ||||||||||||||||||||||||||||||
| Type | misc.AgentHistoryList | ||||||||||||||||||||||||||||||
| Object | streetSellerHistories | ||||||||||||||||||||||||||||||
| Type | misc.AgentHistoryList | ||||||||||||||||||||||||||||||
| Object | privateDealerHistories | ||||||||||||||||||||||||||||||
| Type | misc.AgentHistoryList | ||||||||||||||||||||||||||||||
| Object | marketTrips | ||||||||||||||||||||||||||||||
| Type | misc.TransactionCounter | ||||||||||||||||||||||||||||||
| Object | allTransactions | ||||||||||||||||||||||||||||||
| Type | misc.TransactionCounter | ||||||||||||||||||||||||||||||
| Object | sbTransactions | ||||||||||||||||||||||||||||||
| Type | misc.TransactionCounter | ||||||||||||||||||||||||||||||
| Object | sdTransactions | ||||||||||||||||||||||||||||||
| Type | misc.TransactionCounter | ||||||||||||||||||||||||||||||
| Object | pdTransactions | ||||||||||||||||||||||||||||||
| Type | misc.TransactionCounter | ||||||||||||||||||||||||||||||
| Statechart | |
| Name | simulationState |
| Picture | ![]() |
| ChoicePoint | seekPrivateDealer |
| Action | seekPrivateDealer(); |
| ChoicePoint | seekStreetSeller |
| Action | seekStreetSeller(); |
| ChoicePoint | chooseMarket |
| Action | chooseMarket(); |
| History | preHarassed |
| Type | Shallow |
| Action | // NOTE: // // Due to a bug in AnyLogic 5, a deep history state // will not transition to a simple state that is // inside a composite state when the composite state // is on the same level as the deep history state. // Instead, it will cause a runtime error. Therefore // we avoid deep history states and live with the // limitations of shallow history states. |
| Transition | transition56 |
| Source/target | satisfied=>treatment |
| Fire | Immediately |
| Guard | willGetTreatment() |
| Transition | transition5 |
| Source/target | harassed=>preHarassed |
| Fire | Signal event occurs |
| Signal event | HarassCompleteMsg |
| Action | applyHarassCompleteMsg((HarassCompleteMsg)getEvent()); |
| Transition | transition55 |
| Source/target | state=>harassed |
| Fire | Signal event occurs |
| Signal event | HarassMsg |
| Action | applyHarassMsg((HarassMsg)getEvent()); |
| Transition | transition4 |
| Source/target | waitForPrivateDealer=>seekPrivateDealer |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition7 |
| Source/target | canBuy1=>travelToHome1 |
| Fire | If all other guards are closed |
| Action | madeMarketTrip(false); |
| Transition | transition6 |
| Source/target | canBuy1=>seekStreetSeller |
| Fire | If guard is open |
| Guard | money > targetPrice |
| Transition | transition57 |
| Source/target | arrested=>active |
| Fire | Timeout |
| Timeout | arrestDuration |
| Transition | transition54 |
| Source/target | active=>arrested |
| Fire | Signal event occurs |
| Signal event | ArrestMsg |
| Action | applyArrestMsg((ArrestMsg)getEvent()); |
| Transition | transition53 |
| Source/target | seekStreetSeller=>seekStreetSeller |
| Fire | Signal event occurs |
| Guard | targetSeller != null && dealToSeller == null |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg(new DealDeniedMsg()); |
| Transition | transition52 |
| Source/target | startPrivateDeal=>seekPrivateDealer |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition51 |
| Source/target | seekPrivateDealer=>startPrivateDeal |
| Fire | Signal event occurs |
| Guard | targetSeller != null && dealToSeller != null |
| Action | isWaitingOnSeller = true; sendDealRequestMsg(); |
| Transition | transition50 |
| Source/target | seekStreetSeller=>startStreetDeal |
| Fire | Signal event occurs |
| Guard | targetSeller != null && dealToSeller != null |
| Signal event | TargetFoundMsg |
| Action | isWaitingOnSeller = true; sendDealRequestMsg(); |
| Transition | transition49 |
| Source/target | randomWalk=>seekPrivateDealer |
| Fire | Immediately |
| Guard | Engine.getTime() - marketStartTime > marketQuitTime |
| Action | madeMarketTrip(false); setupKnownPrivateDealers(); |
| Transition | transition48 |
| Source/target | willSeekPrivateDealer=>chooseMarket |
| Fire | If all other guards are closed |
| Transition | transition47 |
| Source/target | willSeekPrivateDealer=>seekPrivateDealer |
| Fire | If guard is open |
| Guard | willSeekPrivateDealer() |
| Action | setupKnownPrivateDealers(); |
| Transition | transition46 |
| Source/target | startStreetDeal=>seekStreetSeller |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition45 |
| Source/target | onPrivateDeal=>seekPrivateDealer |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition44 |
| Source/target | startStreetDeal=>onStreetDeal |
| Fire | Signal event occurs |
| Signal event | DealStartMsg |
| Action | applyDealStartMsg((DealStartMsg)getEvent()); isWaitingOnSeller = true; |
| Transition | transition27 |
| Source/target | onStreetDeal=>canBuy1 |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; setTargetDeal(); |
| Transition | transition15 |
| Source/target | seekPrivateDealer=>seekPrivateDealer |
| Fire | Signal event occurs |
| Guard | targetSeller != null && dealToSeller == null |
| Action | applyDealDeniedMsg(new DealDeniedMsg()); |
| Transition | transition9 |
| Source/target | onStreetDeal=>isTravelRequired |
| Fire | Signal event occurs |
| Signal event | DealCompleteMsg |
| Action | applyDealCompleteMsg((DealCompleteMsg)getEvent()); isWaitingOnSeller = false; madeMarketTrip(true); |
| Transition | transition43 |
| Source/target | willSeekMoney=>tryLater |
| Fire | If all other guards are closed |
| Transition | transition42 |
| Source/target | willSeekMoney=>seekMoney |
| Fire | If guard is open |
| Guard | willSeekMoney() |
| Transition | transition41 |
| Source/target | willGetTreatment=>treatment |
| Fire | If guard is open |
| Guard | willGetTreatment() |
| Transition | transition40 |
| Source/target | seekMoney=>wantFix |
| Fire | Timeout |
| Timeout | uniform(seekMoneyDelayMin, seekMoneyDelayMax) |
| Action | seekMoney(); |
| Transition | transition39 |
| Source/target | willGetTreatment=>willSeekMoney |
| Fire | If all other guards are closed |
| Transition | transition38 |
| Source/target | isDesperate=>willGetTreatment |
| Fire | If guard is open |
| Guard | userBehavior.isDesperate() |
| Transition | transition36 |
| Source/target | isDesperate=>tryLater |
| Fire | If all other guards are closed |
| Transition | transition35 |
| Source/target | useAtSeller=>travelToHome2 |
| Fire | Timeout |
| Timeout | uniform(useDelayMin, useDelayMax) |
| Action | // Waiting until the useDelay timeout fires before calling useAtSeller() // means that we will not call useAtSeller() if we are arrested while // waiting for the timeout to fire. In other words, if we are arrested // in the process of using drugs, the model will assume we did not use // any drugs at all. // // The other option is to call useAtSeller() in the transition entering // the useAtSeller state. In this case, if we are arrested in the process // of using drugs, the model will assume that we used all of our drugs. // Neither situation is realistic. // // The useAtSeller() call was placed here for a practical reason. // useAtSeller() needs to check that the drug partner is also in a // useTogether state, and by waiting until this point to call // useAtSeller(), we can be sure that the drug partner has had an // opportunity to set his status variables properly. useAtSeller(); isUsingAlone = false; if (isUsingWithSeller) { sendUseTogetherCompleteMsg(); isUsingWithSeller = false; } |
| Transition | transition37 |
| Source/target | travelToHome2=>satisfied |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_HOME; possessionUnits = 0; |
| Transition | transition34 |
| Source/target | willUseAtSeller=>travelToHome |
| Fire | If all other guards are closed |
| Transition | transition33 |
| Source/target | willUseAtSeller=>useAtSeller |
| Fire | If guard is open |
| Guard | willUseAtSeller |
| Action | isUsingWithSeller = willUseWithSeller; isUsingAlone = !isUsingWithSeller; |
| Transition | transition32 |
| Source/target | canUse=>canBuy |
| Fire | If all other guards are closed |
| Action | setTargetDeal(); |
| Transition | transition31 |
| Source/target | randomWalk=>seekStreetSeller |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | setupVisibleStreetSellers(); |
| Transition | transition28 |
| Source/target | seekStreetSeller=>randomWalk |
| Fire | Signal event occurs |
| Guard | targetSeller == null |
| Signal event | TargetFoundMsg |
| Transition | transition30 |
| Source/target | chooseMarket=>travelToHome1 |
| Transition | transition29 |
| Source/target | chooseMarket=>travelToMarket |
| Fire | Signal event occurs |
| Guard | targetMarket != null |
| Signal event | TargetFoundMsg |
| Transition | transition26 |
| Source/target | travelToHome1=>isDesperate |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_HOME; |
| Transition | transition25 |
| Source/target | randomWalk=>travelToHome1 |
| Fire | If all other guards are closed |
| Action | madeMarketTrip(false); |
| Transition | transition24 |
| Source/target | travelToPrivateDealer=>onPrivateDeal |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_PRIVATE_DEALER; isWaitingOnSeller = true; sendWaitCompleteMsg(); |
| Transition | transition23 |
| Source/target | waitForPrivateDealer=>onPrivateDeal |
| Fire | Signal event occurs |
| Signal event | WaitCompleteMsg |
| Action | applyWaitCompleteMsg((WaitCompleteMsg)getEvent()); isWaitingOnSeller = true; |
| Transition | transition12 |
| Source/target | travelToMarket=>seekStreetSeller |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_MARKET; marketStartTime = Engine.getTime(); setupVisibleStreetSellers(); |
| Transition | transition22 |
| Source/target | seekPrivateDealer=>chooseMarket |
| Fire | Signal event occurs |
| Guard | targetSeller == null |
| Transition | transition21 |
| Source/target | travelToHome=>useAtHome |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_HOME; possessionUnits = 0; |
| Transition | transition20 |
| Source/target | isTravelRequired=>useAtHome |
| Fire | If guard is open |
| Guard | currentPlace == Main.PLACE_HOME |
| Transition | transition19 |
| Source/target | isTravelRequired=>willUseAtSeller |
| Fire | If all other guards are closed |
| Transition | transition16 |
| Source/target | onPrivateDeal=>isTravelRequired |
| Fire | Signal event occurs |
| Signal event | DealCompleteMsg |
| Action | applyDealCompleteMsg((DealCompleteMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition18 |
| Source/target | startPrivateDeal=>waitForPrivateDealer |
| Fire | Signal event occurs |
| Guard | ((DealerDeliversMsg)getEvent()).delivers |
| Signal event | DealerDeliversMsg |
| Action | applyDealerDeliversMsg((DealerDeliversMsg)getEvent()); isWaitingOnSeller = true; |
| Transition | transition17 |
| Source/target | startPrivateDeal=>travelToPrivateDealer |
| Action | applyDealerDeliversMsg((DealerDeliversMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition14 |
| Source/target | tryLater=>wantFix |
| Fire | Timeout |
| Timeout | uniform(retryDelayMin, retryDelayMax) |
| Transition | transition13 |
| Source/target | canBuy=>isDesperate |
| Fire | If all other guards are closed |
| Transition | transition3 |
| Source/target | useAtHome=>satisfied |
| Fire | Timeout |
| Timeout | uniform(useDelayMin, useDelayMax) |
| Transition | transition11 |
| Source/target | wantFix=>canUse |
| Fire | Immediately |
| Transition | transition10 |
| Source/target | canBuy=>willSeekPrivateDealer |
| Fire | Change event occurs |
| Guard | money >= targetPrice |
| Change event | Util.isDaytime() |
| Transition | transition2 |
| Source/target | canUse=>useAtHome |
| Fire | If guard is open |
| Guard | userBehavior.inventory > 0 |
| Transition | transition1 |
| Source/target | satisfied=>wantFix |
| Fire | Signal event occurs |
| Signal event | WantFixMsg |
| Transition | transition8 |
| Source/target | treatment=>active |
| Fire | Timeout |
| Timeout | uniform(treatmentDelayMin, treatmentDelayMax) |
| Transition | transition |
| Source/target | satisfied=>wantFix |
| Fire | Signal event occurs |
| Signal event | RandomUseMsg |
| State | useAtHome |
| Entry action | isUsingAlone = true; useAtHome(); |
| Exit action | isUsingAlone = false; |
| State | travelToHome |
| Entry action | travelToHome(); |
| State | travelToPrivateDealer |
| Deferred events | new DealDeniedEvent() |
| Entry action | travelToPrivateDealer(); |
| State | waitForPrivateDealer |
| Entry action | dealQuitTimer.restart(Main.csDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | travelToMarket |
| Entry action | travelToMarket(); |
| Exit action | |
| State | travelToHome1 |
| Entry action | travelToHome(); |
| State | randomWalk |
| Entry action | wanderInMarket(); |
| State | travelToHome2 |
| Entry action | travelToHome(); |
| State | onPrivateDeal |
| Entry action | dealQuitTimer.restart(Main.csDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | startStreetDeal |
| Entry action | dealQuitTimer.restart(Main.csDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | onStreetDeal |
| Entry action | dealQuitTimer.restart(Main.csDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | startPrivateDeal |
| Entry action | dealQuitTimer.restart(Main.csDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | harassed |
| Deferred events | new GenericEvent() |
| Entry action | isBeingHarassed = true; |
| Exit action | isBeingHarassed = false; |
| State | arrested |
| Entry action | currentPlace = Main.PLACE_JAIL; |
| State | treatment |
| Entry action | currentPlace = Main.PLACE_TREATMENT; userBehavior.isAddictionFrozen = true; |
| Exit action | userBehavior.addiction *= (1 - treatmentAddictionReduction); userBehavior.isAddictionFrozen = false; |
| State | active |
| Entry action | isActive = true; currentPlace = Main.PLACE_HOME; location.currentX = homeX; location.currentY = homeY; |
| Exit action | isActive = false; isWaitingOnSeller = false; isUsingAlone = false; if (isUsingWithSeller) { sendUseTogetherCompleteMsg(); isUsingWithSeller = false; } |
| Algorithmic Functions | |||||
| Name | applyArrestMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | location.stopTravel(); numArrests++; arrestDuration = msg.duration; updateInventory(-possessionUnits); possessionUnits = 0; |
||||
| Name | applyDealCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | dealFromSeller = msg; // Add the acquired drugs to the customer's inventory. updateInventory(msg.units); // Note that the customer now has drugs in his possession. // This is important because he can now be arrested for // possession. We consider it to be possession only if he // has drugs outside of his home. if (currentPlace != Main.PLACE_HOME) { possessionUnits = msg.units; } // Subtract the cost from the customer's money unless the // customer used a broker (in which case the customer already // gave the broker his money when he started the deal). // // ASSUME: The actual price equals the target price. if (!(targetSeller instanceof StreetBroker)) { updateMoney(-msg.price); } // Update the customer's history with this seller. targetSellerHistory.madeDeal(true, targetSellerX, targetSellerY); // Update transaction counters. allTransactions.addGood(msg.units, msg.price); main.csAllTransactions.addGood(msg.units, msg.price); if (targetSeller instanceof StreetBroker) { sbTransactions.addGood(msg.units, msg.price); main.csSbTransactions.addGood(msg.units, msg.price); } else if (targetSeller instanceof StreetDealer) { sdTransactions.addGood(msg.units, msg.price); main.csSdTransactions.addGood(msg.units, msg.price); } else if (targetSeller instanceof PrivateDealer) { pdTransactions.addGood(msg.units, msg.price); main.csPdTransactions.addGood(msg.units, msg.price); } else { traceln("***ERROR in Customer.receiveDealCompleteMsg(): Unexpected seller type for " + self + " @ " + Engine.getTime()); } // Set up variables indicating the customer's course of action // from this point until he has finished using. if (currentPlace != Main.PLACE_HOME) { // Determine whether the customer will use at the seller's // location before returning home, or if he will return home // first and then use. willUseAtSeller = userBehavior.isDesperate() || randomTrue(probUseAtSeller); // Determine whether the customer will use with the seller. if (willUseAtSeller && targetSeller instanceof User && targetSeller.isWaitingOnBuyer(dealFromSeller.dealID) ) { User usingSeller = (User)targetSeller; willUseWithSeller = willUseTogether() && usingSeller.willUseTogether(); } else { willUseWithSeller = false; } } // If the seller is also a user, let him know whether the customer will // use with him. if (targetSeller instanceof User && targetSeller.isWaitingOnBuyer(dealFromSeller.dealID) ) { User usingSeller = (User)targetSeller; UseTogetherMsg useMsg = new UseTogetherMsg(); useMsg.dealID = dealToSeller.dealID; useMsg.uses = willUseWithSeller; usingSeller.receiveUseTogetherMsg(useMsg); targetUsePartner = willUseWithSeller ? usingSeller : null; } else { targetUsePartner = null; } |
||||
| Name | applyDealDeniedMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // The denial of the deal may come with a refund of the customer's // money. For example, in a brokered deal the customer would have // given the broker his money at the beginning of the deal, so if // the deal ends unsuccessfully the customer should get his money // back. if (msg.refund != 0) { updateMoney(msg.refund); } // Update the customer's history with this seller. targetSellerHistory.madeDeal(false, targetSellerX, targetSellerY); // Update transaction counters. allTransactions.addFailed(); main.csAllTransactions.addFailed(); if (targetSeller instanceof StreetBroker) { sbTransactions.addFailed(); main.csSbTransactions.addFailed(); } else if (targetSeller instanceof StreetDealer) { sdTransactions.addFailed(); main.csSdTransactions.addFailed(); } else if (targetSeller instanceof PrivateDealer) { pdTransactions.addFailed(); main.csPdTransactions.addFailed(); } else { traceln("***ERROR in Customer.receiveDealDeniedMsg(): Unexpected seller type for " + self + " @ " + Engine.getTime()); } |
||||
| Name | applyDealStartMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (targetSeller instanceof StreetBroker) { updateMoney(-targetPrice); } |
||||
| Name | applyDealerDeliversMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // Nothing needs to be done. |
||||
| Name | applyHarassCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // Nothing needs to be done. |
||||
| Name | applyHarassMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | location.stopTravel(); lastHarassTime = Engine.getTime(); |
||||
| Name | applyWaitCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // Nothing needs to be done. |
||||
| Name | chooseMarket | ||||
| Type | void | ||||
| Body | // TODO: Select an algorithm for choosing a market. // For now, choose the market with the highest proportion of // good trips. // May also consider: // distance // random variation targetMarket = null; // Decide whether to try going to a market based on the current // time of day. // // The customer has knowledge of when dealers typically enter // and leave the market. He knows they are never there before // earlyStartHour, and he knows they are always there by // lateStartHour. For the times in between, he decides randomly // whether to go, where the probability of going is higher // the closer it gets to the lateStartHour. At the end of the // day, the customer knows that the dealers sometimes leave by // earlyEndHour. Considering that he has to travel to the market // and find a seller, he will not go if the time is past // earlyEndHour. double earlyStartHour = util.Params.getDouble(Main.sdShiftStartRange, 0); double lateStartHour = util.Params.getDouble(Main.sdShiftStartRange, 1); double earlyEndHour = util.Params.getDouble(Main.sdShiftEndRange, 0); if (randomTrue((util.Clock.getCurrentHour() - earlyStartHour) / (lateStartHour - earlyStartHour)) && util.Clock.getCurrentHour() < earlyEndHour ) { // Sort the markets by proportion of good deals, and // choose the first market in the list. marketHistories.shuffle(); // avoid always breaking ties the same way marketHistories.sort(AgentHistoryList.proportionGoodDealsComparator); targetMarket = (Market)marketHistories.get(0).agent; } |
||||
| Name | createDealRequestMsg | ||||
| Type | void | ||||
| Body | dealToSeller = new DealRequestMsg(); dealToSeller.dealID = main.getNewDealID(); dealToSeller.units = targetUnits; dealToSeller.price = targetPrice; dealToSeller.buyer = self; dealToSeller.buyerPlace = currentPlace; dealToSeller.customer = self; |
||||
| Name | getDrugsOnPerson | ||||
| Type | real | ||||
| Body | return possessionUnits; |
||||
| Name | getLastHarassTime | ||||
| Type | real | ||||
| Body | return lastHarassTime; |
||||
| Name | getLocation | ||||
| Type | Location | ||||
| Body | return location; |
||||
| Name | hasHIV | ||||
| Type | boolean | ||||
| Body | return userBehavior.hasHIV; |
||||
| Name | isBeingHarassed | ||||
| Type | boolean | ||||
| Body | return isBeingHarassed; |
||||
| Name | isInPublic | ||||
| Type | boolean | ||||
| Body | // isInPublic: Can the seller currently be seen in public? // Customers can be seen in public only when they are traveling // or when they are in the market. return currentPlace == Main.PLACE_TRANSIT || currentPlace == Main.PLACE_MARKET; |
||||
| Name | isQueueLengthAcceptable | ||||
| Type | boolean | ||||
| Arguments |
|
||||
| Body | int acceptableQueueLength = 0; if (seller instanceof StreetBroker) { acceptableQueueLength = Main.csAcceptableSbQueueLength; } else if (seller instanceof StreetDealer) { acceptableQueueLength = acceptableSdQueueLength; } else if (seller instanceof PrivateDealer) { acceptableQueueLength = acceptablePdQueueLength; } else { traceln("***ERROR in Customer.isQueueLengthAcceptable(): Unexpected seller type for " + self + " @ " + Engine.getTime()); return false; } return targetSeller.getQueueLength() <= acceptableQueueLength; |
||||
| Name | isUsing | ||||
| Type | boolean | ||||
| Body | // isUsing: Is this user currently using drugs? return isUsingAlone || isUsingWithSeller; |
||||
| Name | isUsingTogether | ||||
| Type | boolean | ||||
| Arguments |
|
||||
| Body | // isUsingTogether: Is this user using drugs with another user as // a result of the specified deal? return isUsingWithSeller && dealToSeller.dealID == dealID; |
||||
| Name | isWaitingOnSeller | ||||
| Type | boolean | ||||
| Arguments |
|
||||
| Body | return isWaitingOnSeller && dealToSeller.dealID == dealID; |
||||
| Name | madeMarketTrip | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // Record the success or failure of the trip. // // Record the market location of the deal if the trip was a success. // Note that a failed trip may not have a specific location associated // with it since the failure could be the result of wandering in the // market for too long and eventually giving up. For this reason, we // will record a dummy location for a failed trip. AgentHistory history = marketHistories.find(targetMarket); if (success) { if (targetMarket.isLocationInMarket(targetSellerX, targetSellerY)) { history.madeDeal(true, targetSellerX, targetSellerY); } else { history.madeDeal(true, -1, -1); traceln("***ERROR in Customer.madeMarketTrip: Seller location is not in market: customer=" + self + " seller=" + targetSeller + " time=" + Engine.getTime()); } } else { // Record the market's reference coordinates as the location of a // failed trip. history.madeDeal(false, targetMarket.x, targetMarket.y); } // Update the market trip counters. if (success) { marketTrips.addGood(dealFromSeller.units, dealFromSeller.price); main.csMarketTrips.addGood(dealFromSeller.units, dealFromSeller.price); } else { marketTrips.addFailed(); main.csMarketTrips.addFailed(); } |
||||
| Name | processPendingInvitations | ||||
| Type | void | ||||
| Body | // Transfer any private dealers from our pendingInvitations list // to our privateDealerHistories list. See receiveInviteBuyerMsg() // for a discussion of the pendingInvitations list. for (int i = 0; i < pendingInvitations.size(); i++) { PrivateDealer pd = (PrivateDealer)pendingInvitations.get(i); privateDealerHistories.add(pd); } pendingInvitations.clear(); |
||||
| Name | receiveArrestMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (currentPlace != Main.PLACE_JAIL) { simulationState.fireEvent(msg); } |
||||
| Name | receiveDealCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (isWaitingOnSeller(msg.dealID)) { simulationState.fireEvent(msg); } else { traceln("***WARNING in Customer.receiveDealCompleteMsg(): " + self + " ignoring message about unexpected deal " + msg.dealID + " @ " + Engine.getTime()); } |
||||
| Name | receiveDealDeniedMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (isWaitingOnSeller(msg.dealID)) { simulationState.fireEvent(msg); } else { traceln("***WARNING in Customer.receiveDealDeniedMsg(): " + self + " ignoring message about unexpected deal " + msg.dealID + " @ " + Engine.getTime()); } |
||||
| Name | receiveDealStartMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (isWaitingOnSeller(msg.dealID)) { simulationState.fireEvent(msg); } else { traceln("***WARNING in Customer.receiveDealStartMsg(): " + self + " ignoring message about unexpected deal " + msg.dealID + " @ " + Engine.getTime()); } |
||||
| Name | receiveDealerDeliversMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (isWaitingOnSeller(msg.dealID)) { simulationState.fireEvent(msg); } else { traceln("***WARNING in Customer.receiveDealerDeliversMsg(): " + self + " ignoring message about unexpected deal " + msg.dealID + " @ " + Engine.getTime()); } |
||||
| Name | receiveHarassCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (isBeingHarassed()) { simulationState.fireEvent(msg); } else { traceln("***WARNING in Customer.receiveHarassCompleteMsg(): " + self + " ignoring unexpected message @ " + Engine.getTime()); } |
||||
| Name | receiveHarassMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (!isBeingHarassed()) { simulationState.fireEvent(msg); } |
||||
| Name | receiveInviteBuyerMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // We have received an invitation from a private dealer to make // direct deals with him instead of going through a broker. // // We can't immediately add him to our list of private dealers, // however, because it's possible that we are currently iterating // over that list looking for another private dealer. If we modify // the list during the iteration process, we will cause a // ConcurrentModificationException and the model will crash. // // Instead, we add the dealer to a separate list of pending // invitations. At a point when we know we are not iterating // over the list, we will add the private dealers from this // pending list to our full list of private dealers. This will // happen in the setupKnownPrivateDealers function. pendingInvitations.add(msg.privateDealer); |
||||
| Name | receiveUseTogetherCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // Customers should not receive a UseTogetherCompleteMsg. // This function exists to implement the User interface. traceln("***WARNING in Customer.receiveUseTogetherCompleteMsg(): " + self + " ignoring message about unexpected deal " + msg.dealID + " @ " + Engine.getTime()); |
||||
| Name | receiveUseTogetherMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // Customers should not receive a UseTogetherMsg. // This function exists to implement the User interface. traceln("***WARNING in Customer.receiveUseTogetherMsg(): " + self + " ignoring message about unexpected deal " + msg.dealID + " @ " + Engine.getTime()); |
||||
| Name | receiveWaitCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (isWaitingOnSeller(msg.dealID)) { simulationState.fireEvent(msg); } else { traceln("***WARNING in Customer.receiveWaitCompleteMsg(): " + self + " ignoring message about unexpected deal " + msg.dealID + " @ " + Engine.getTime()); } |
||||
| Name | seekMoney | ||||
| Type | void | ||||
| Body | if (randomTrue(probSeekMoneySuccess)) { updateMoney(uniform(windfallAmountMin, windfallAmountMax)); } |
||||
| Name | seekPrivateDealer | ||||
| Type | void | ||||
| Body | // We expect this method to be called repeatedly, with each new call // returning the next dealer in the list until an available dealer is // found or the list is exhausted. targetSeller = null; dealToSeller = null; if (privateDealerHistories.hasNext()) { targetSellerHistory = privateDealerHistories.next(); targetSeller = (Seller)targetSellerHistory.agent; targetSellerX = targetSeller.getLocation().currentX; targetSellerY = targetSeller.getLocation().currentY; if (targetSeller.isAcceptingRequests() && targetSeller.willAcceptDeal(self, targetUnits, targetPrice) && isQueueLengthAcceptable(targetSeller) ) { createDealRequestMsg(); } } |
||||
| Name | seekStreetSeller | ||||
| Type | void | ||||
| Body | // We expect this method to be called repeatedly, with each new call // returning the next seller in the list until an available seller is // found or the list is exhausted. targetSeller = null; dealToSeller = null; if (visibleStreetSellersIterator.hasNext()) { targetSeller = (Seller)visibleStreetSellersIterator.next(); targetSellerX = targetSeller.getLocation().currentX; targetSellerY = targetSeller.getLocation().currentY; targetSellerHistory = streetSellerHistories.find(targetSeller); // Bail out without creating a deal request under certain conditions. if (targetSeller instanceof User && ((User)targetSeller).isUsing()) return; if (((PoliceTarget)targetSeller).isBeingHarassed()) return; if (!isQueueLengthAcceptable(targetSeller)) return; createDealRequestMsg(); } |
||||
| Name | sendDealRequestMsg | ||||
| Type | void | ||||
| Body | targetSeller.receiveDealRequestMsg(dealToSeller); |
||||
| Name | sendUseTogetherCompleteMsg | ||||
| Type | void | ||||
| Body | if (targetUsePartner.isUsingTogether(dealToSeller.dealID)) { UseTogetherCompleteMsg msg = new UseTogetherCompleteMsg(); msg.dealID = dealToSeller.dealID; targetUsePartner.receiveUseTogetherCompleteMsg(msg); } |
||||
| Name | sendWaitCompleteMsg | ||||
| Type | void | ||||
| Body | if (targetSeller.isWaitingOnBuyer(dealToSeller.dealID)) { WaitCompleteMsg msg = new WaitCompleteMsg(); msg.dealID = dealToSeller.dealID; targetSeller.receiveWaitCompleteMsg(msg); } |
||||
| Name | setTargetDeal | ||||
| Type | void | ||||
| Body | boolean foundDeal = false; // For convenience below, create true arrays from the stringified // Main array parameters. If Main.dealUnits and Main.dealPrices are // not the same length, we use the length of Main.dealUnits and // replicate the last value of Main.dealPrices as necessary to equal // the length of Main.dealUnits. This replication process is handled // in the util.Params.getDouble function. double[] dealUnits = new double[util.Params.count(Main.dealUnitsList)]; double[] dealPrices = new double[util.Params.count(Main.dealUnitsList)]; for (int i = 0; i < dealUnits.length; i++) { dealUnits[i] = util.Params.getDouble(Main.dealUnitsList, i); dealPrices[i] = util.Params.getDouble(Main.dealPricesList, i); } // If the customer buys based on need, the target deal // is smallest deal amount that is larger than what he // needs. If he can't afford this amount, then he buys // based on what he can afford. // // NOTE: This algorithm requires that the code for // "need" come before the code for "afford". if (buyMethod.equals("need")) { for (int i = 0; i < dealUnits.length; i++) { if (dealUnits[i] >= userBehavior.addiction) { if (dealPrices[i] <= money) { targetUnits = dealUnits[i]; targetPrice = dealPrices[i]; foundDeal = true; } break; } } } // If the customer buys based on what he can afford, // then the target deal is the one with the largest // price that is less than how much money he has. if (!foundDeal || buyMethod.equals("afford")) { for (int i = dealPrices.length - 1; i >= 0; i--) { if (dealPrices[i] <= money) { targetUnits = dealUnits[i]; targetPrice = dealPrices[i]; foundDeal = true; break; } } } // If the customer couldn't find a target deal, this // means he couldn't afford any of the defined deals. // In this case, just set the target deal to the first // defined deal. Here we assume that the customer will // always check whether he can afford the target deal // after this function has been called. // // NOTE: We will have to do something smarter if we add // the ability to make deals on credit. if (!foundDeal) { targetUnits = dealUnits[0]; targetPrice = dealPrices[0]; } |
||||
| Name | setupKnownPrivateDealers | ||||
| Type | void | ||||
| Body | // If any private dealers sent us invitations since the last // time we searched for one, add them to the list of all private // dealers that we know about. processPendingInvitations(); // Sort the dealers so that those with the highest proportion // of good deals appear at the front of the list. privateDealerHistories.shuffle(); // avoid always breaking ties the same way privateDealerHistories.sort(AgentHistoryList.proportionGoodDealsComparator); // Reset the iterator to point to the beginning of the list. // We'll use this to cycle through the list once we're inside // the seekPrivateDealer() function. privateDealerHistories.resetIterator(); |
||||
| Name | setupVisibleStreetSellers | ||||
| Type | void | ||||
| Body | // Find all the street sellers near this customer. Create a list of these // sellers, and add the sellers to the list of known street sellers. visibleStreetSellers.clear(); for (int i = 0; i < targetMarket.streetBrokers.size(); i++) { StreetBroker sb = (StreetBroker)targetMarket.streetBrokers.get(i); if (sb.isInPublic() && location.distance(sb.getLocation().currentX, sb.getLocation().currentY) <= max(visionRadius, sb.visionRadius) ) { visibleStreetSellers.add(sb); streetSellerHistories.add(sb); } } for (int i = 0; i < targetMarket.streetDealers.size(); i++) { StreetDealer sd = (StreetDealer)targetMarket.streetDealers.get(i); if (sd.isInPublic() && location.distance(sd.getLocation().currentX, sd.getLocation().currentY) <= max(visionRadius, sd.visionRadius) ) { visibleStreetSellers.add(sd); streetSellerHistories.add(sd); } } // Sort the sellers so that those with the highest proportion // of good deals appear at the front of the list. We'll first // sort the list of all known street sellers, and then we'll // sort the list of visible street sellers to match the sort // order of the full list of known street sellers. streetSellerHistories.shuffle(); // avoid always breaking ties the same way streetSellerHistories.sort(AgentHistoryList.proportionGoodDealsComparator); Collections.sort(visibleStreetSellers, // Use a comparison function that compares the visibleStreetSellers // elements based on their position in streetSellerHistories. This // comparator needs to be defined somewhere within the Customer // definition because it needs access to streetSellerHistories. new Comparator() { public int compare(Object o1, Object o2) { int i1 = streetSellerHistories.indexOf(o1); int i2 = streetSellerHistories.indexOf(o2); if (i1 == -1 || i2 == -1) { // One of the objects isn't in the full list. This shouldn't // happen since we added each visible seller to the full list, // so report an error. traceln("***ERROR in Customer.setupVisibleStreetSellers(): Visible seller not in list of all sellers for " + self + " @ " + Engine.getTime()); return 0; } else { if (i1 < i2) { return -1; } else if (i2 > i2) { return 1; } else { return 0; } } } } ); // Get an iterator that we will use to cycle through the list // once we're inside the seekStreetSeller() function. visibleStreetSellersIterator = visibleStreetSellers.iterator(); |
||||
| Name | travelToHome | ||||
| Type | void | ||||
| Body | if (currentPlace != Main.PLACE_HOME) { // Begin traveling to home. Assume the travel takes place // at driving speed (by car, bus, etc.). location.travel(homeX, homeY, Main.TRAVEL_DRIVE); // Record that the customer is now traveling. currentPlace = Main.PLACE_TRANSIT; } else { simulationState.fireEvent(new TravelCompleteMsg()); } |
||||
| Name | travelToMarket | ||||
| Type | void | ||||
| Body | // Choose a target location in the market. If the customer has made // a good deal in the market, travel to the location of the most // recent one. If not, travel to a random location in the market. AgentHistory history = marketHistories.find(targetMarket); double destinationX; double destinationY; if (history.numGoodDeals > 0) { destinationX = history.lastGoodDealX; destinationY = history.lastGoodDealY; } else { destinationX = targetMarket.getRandomX(); destinationY = targetMarket.getRandomY(); } // Begin movement to the market. Assume the travel takes place // at driving speed (by car, bus, etc.). location.travel(destinationX, destinationY, Main.TRAVEL_DRIVE); // Record that the customer is now traveling. currentPlace = Main.PLACE_TRANSIT; |
||||
| Name | travelToPrivateDealer | ||||
| Type | void | ||||
| Body | // Begin movement to the private dealer. Assume the travel // takes place at driving speed (by car, bus, etc.). location.travel(targetSellerX, targetSellerY, Main.TRAVEL_DRIVE); // Record that the customer is now traveling. currentPlace = Main.PLACE_TRANSIT; |
||||
| Name | updateInventory | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | userBehavior.inventory += inventoryChange; if (userBehavior.inventory < 0) { traceln("***ERROR in Customer.updateInventory(): Negative inventory for " + self + " @ " + Engine.getTime()); } |
||||
| Name | updateMoney | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | money += moneyChange; if (money < 0) { traceln("***ERROR in Customer.updateMoney(): Negative money for " + self + " @ " + Engine.getTime()); } |
||||
| Name | useAtHome | ||||
| Type | void | ||||
| Body | userBehavior.useNeed(); |
||||
| Name | useAtSeller | ||||
| Type | void | ||||
| Body | double unitsUsed = userBehavior.useNeed(); possessionUnits -= unitsUsed; if (willUseWithSeller) { if (targetUsePartner.isUsingTogether(dealToSeller.dealID) && !hasHIV() && targetUsePartner.hasHIV() && randomTrue(Main.probTransmitHIV) ) { userBehavior.hasHIV = true; } } |
||||
| Name | wanderInMarket | ||||
| Type | void | ||||
| Body | location.wanderInMarket(targetMarket); |
||||
| Name | willGetTreatment | ||||
| Type | boolean | ||||
| Body | if (userBehavior.getNeed() > 0) { return randomTrue(Main.csProbTreatmentNotSatisfied); } else { return randomTrue(Main.csProbTreatmentSatisfied); } |
||||
| Name | willSeekMoney | ||||
| Type | boolean | ||||
| Body | return money < util.Params.getDouble(Main.dealPricesList, 0) && randomTrue(probSeekMoney); |
||||
| Name | willSeekPrivateDealer | ||||
| Type | boolean | ||||
| Body | return randomTrue(probTryPrivateDealer); |
||||
| Name | willUseTogether | ||||
| Type | boolean | ||||
| Body | return randomTrue(probUseTogether); |
||||
| Animation | |
| Name | animation |
| X | 0 |
| Y | 0 |
| Additional class code | public boolean isSelected = false; |
| Picture | ![]() |
| Rectangle | agentShape |
| X | main.animation.getAgentLocationX(main.AGENT_CUSTOMER, isSelected, location.currentX) |
| Y | main.animation.getAgentLocationY(main.AGENT_CUSTOMER, isSelected, location.currentY) |
| Width | main.animation.getAgentSize(main.AGENT_CUSTOMER, isSelected) |
| Height | main.animation.getAgentSize(main.AGENT_CUSTOMER, isSelected) |
| Fill color | main.animation.getAgentFillColor(main.AGENT_CUSTOMER, isSelected) |
| Line color | main.animation.getAgentLineColor(main.AGENT_CUSTOMER, isSelected) |
| Line width | main.animation.getAgentLineWidth(main.AGENT_CUSTOMER, isSelected) |
| Visible | isActive && main.animation.getAgentVisibility(main.AGENT_CUSTOMER, isSelected, location.currentX, location.currentY) |
| General | |
| Import | import message.*; import misc.*; |
| Parameters | |
| Name | initialMarket |
| Type | Market |
| Icon | |
| Picture | |
| Structure | |||||||
| Picture | ![]() |
||||||
| ChartTimer | dailyTimer | ||||||
| Timeout | util.Units.days(1) | ||||||
| Expire At Startup | Yes | ||||||
| Expiry Action | // Each day, the homeless start their "shifts" sometime during // the time period that they know the street dealers tend to // enter the market. They end their shifts sometime during the // time period that they know the street dealers tend to leave // the market. if (isActive) { double earlyStartHour = util.Params.getDouble(Main.sdShiftStartRange, 0); double lateStartHour = util.Params.getDouble(Main.sdShiftStartRange, 1); double shiftStartHour = util.Units.hours(uniform(earlyStartHour, lateStartHour)); shiftStartTimer.restart(shiftStartHour); double earlyEndHour = util.Params.getDouble(Main.sdShiftEndRange, 0); double lateEndHour = util.Params.getDouble(Main.sdShiftEndRange, 1); shiftEndTime = Engine.getTime() + util.Units.hours(uniform(earlyEndHour, lateEndHour)); } |
||||||
| ChartTimer | shiftStartTimer | ||||||
| Expire | No (manual mode) | ||||||
| Expiry Action | simulationState.fireEvent(new ShiftStartMsg()); |
||||||
| Variable | shiftEndTime | ||||||
| Variable type | real | ||||||
| Variable | currentPlace | ||||||
| Variable type | integer | ||||||
| Initial value | Main.PLACE_MARKET | ||||||
| Variable | isActive | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Variable | market | ||||||
| Variable type | Market | ||||||
| Initial value | initialMarket | ||||||
| Variable | main | ||||||
| Variable type | Main | ||||||
| Initial value | (Main)getOwner() | ||||||
| Variable | self | ||||||
| Variable type | Homeless | ||||||
| Initial value | this | ||||||
| Variable | lastHarassTime | ||||||
| Variable type | real | ||||||
| Initial value | 0 | ||||||
| Variable | isBeingHarassed | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Port | travelCompleteListener | ||||||
| Message type | TravelCompleteMsg | ||||||
| Statechart | simulationState | ||||||
| Object | location | ||||||
| Type | misc.Location | ||||||
| Parameters |
|
||||||
| Statechart | |
| Name | simulationState |
| Picture | ![]() |
| History | preHarassed |
| Type | Shallow |
| Action | // NOTE: // // Due to a bug in AnyLogic 5, a deep history state // will not transition to a simple state that is // inside a composite state when the composite state // is on the same level as the deep history state. // Instead, it will cause a runtime error. Therefore // we avoid deep history states and live with the // limitations of shallow history states. |
| Transition | transition5 |
| Source/target | harassed=>preHarassed |
| Fire | Signal event occurs |
| Signal event | HarassCompleteMsg |
| Action | applyHarassCompleteMsg((HarassCompleteMsg)getEvent()); |
| Transition | transition55 |
| Source/target | state=>harassed |
| Fire | Signal event occurs |
| Signal event | HarassMsg |
| Action | applyHarassMsg((HarassMsg)getEvent()); |
| Transition | transition8 |
| Source/target | idle=>randomWalk |
| Fire | Signal event occurs |
| Signal event | ShiftStartMsg |
| Transition | transition7 |
| Source/target | randomWalk=>idle |
| Fire | Immediately |
| Guard | !market.isOpen && Engine.getTime() > shiftEndTime |
| Action | location.travel(location.startX, location.startY, Main.TRAVEL_WALK); |
| Transition | transition9 |
| Source/target | randomWalk=>randomWalk |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| State | randomWalk |
| Entry action | location.wanderInMarket(market); |
| State | harassed |
| Deferred events | new GenericEvent() |
| Entry action | isBeingHarassed = true; |
| Exit action | isBeingHarassed = false; |
| State | active |
| Entry action | isActive = true; currentPlace = Main.PLACE_MARKET; location.currentX = location.startX; location.currentY = location.startY; market.addHomeless(self); |
| Exit action | isActive = false; market.removeHomeless(self); |
| Algorithmic Functions | |||||
| Name | applyHarassCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // Nothing needs to be done. |
||||
| Name | applyHarassMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | location.stopTravel(); lastHarassTime = Engine.getTime(); |
||||
| Name | getDrugsOnPerson | ||||
| Type | real | ||||
| Body | // The homeless do not have drugs. return 0; |
||||
| Name | getLastHarassTime | ||||
| Type | real | ||||
| Body | return lastHarassTime; |
||||
| Name | getLocation | ||||
| Type | Location | ||||
| Body | return location; |
||||
| Name | isBeingHarassed | ||||
| Type | boolean | ||||
| Body | return isBeingHarassed; |
||||
| Name | isInPublic | ||||
| Type | boolean | ||||
| Body | // isInPublic: Can the seller currently be seen in public? // The homeless are always out in public. return true; |
||||
| Name | receiveArrestMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | // Do nothing. The homeless are not arrested. |
||||
| Name | receiveHarassCompleteMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (isBeingHarassed()) { simulationState.fireEvent(msg); } else { traceln("***WARNING in Homeless.receiveHarassCompleteMsg(): " + self + " ignoring unexpected message @ " + Engine.getTime()); } |
||||
| Name | receiveHarassMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (!isBeingHarassed()) { simulationState.fireEvent(msg); } |
||||
| Animation | |
| Name | animation |
| X | 0 |
| Y | 0 |
| Additional class code | public boolean isSelected = false; |
| Picture | ![]() |
| Rectangle | agentShape |
| X | main.animation.getAgentLocationX(main.AGENT_HOMELESS, isSelected, location.currentX) |
| Y | main.animation.getAgentLocationY(main.AGENT_HOMELESS, isSelected, location.currentY) |
| Width | main.animation.getAgentSize(main.AGENT_HOMELESS, isSelected) |
| Height | main.animation.getAgentSize(main.AGENT_HOMELESS, isSelected) |
| Fill color | main.animation.getAgentFillColor(main.AGENT_HOMELESS, isSelected) |
| Line color | main.animation.getAgentLineColor(main.AGENT_HOMELESS, isSelected) |
| Line width | main.animation.getAgentLineWidth(main.AGENT_HOMELESS, isSelected) |
| Visible | isActive && main.animation.getAgentVisibility(main.AGENT_HOMELESS, isSelected, location.currentX, location.currentY) |
| General | |
| Import | import misc.*; import message.*; import animation.*; |
| Startup code | initializeParameters(); initializeAgents(); initializeNetworks(); startTimers(); |
| Additional class code | public static final int AGENT_CUSTOMER = 0; public static final int AGENT_STREET_BROKER = 1; public static final int AGENT_STREET_DEALER = 2; public static final int AGENT_PRIVATE_DEALER = 3; public static final int AGENT_HOMELESS = 4; public static final int AGENT_POLICE = 5; public static final int AGENT_MARKET = 6; public static final int NUM_AGENTS = 7; public static final int PLACE_HOME = 0; public static final int PLACE_TRANSIT = 1; public static final int PLACE_MARKET = 2; public static final int PLACE_PRIVATE_DEALER = 3; public static final int PLACE_TREATMENT = 4; public static final int PLACE_JAIL = 5; public static final int TRAVEL_WALK = 0; public static final int TRAVEL_DRIVE = 1; |
| Parameters | |
| Name | numReplications |
| Type | integer |
| Default value | 1 |
| Name | replicationRunTime |
| Type | real |
| Default value | 180 |
| Name | animationScaleFactor |
| Type | real |
| Default value | 1 |
| Name | minutesPerTimeStep |
| Type | real |
| Default value | 1 |
| Modificator | Global |
| Name | cityWidth |
| Type | real |
| Default value | 5 |
| Name | cityHeight |
| Type | real |
| Default value | 5 |
| Name | marketSizeRange |
| Type | String |
| Default value | "0.5,0.5" |
| Name | walkingSpeed |
| Type | real |
| Default value | 2 |
| Modificator | Global |
| Name | drivingSpeed |
| Type | real |
| Default value | 30 |
| Modificator | Global |
| Name | visionRadiusRange |
| Type | String |
| Default value | "60,60" |
| Name | dealUnitsList |
| Type | String |
| Default value | "10,30,40,60,120,360" |
| Modificator | Global |
| Name | dealPricesList |
| Type | String |
| Default value | "20,40,50,70,130,330" |
| Modificator | Global |
| Name | useIncrement |
| Type | real |
| Default value | 5 |
| Modificator | Global |
| Name | param7 |
| Modificator | Separator |
| Name | outfileSummaryCreate |
| Type | boolean |
| Default value | false |
| Name | outfileSummaryName |
| Type | String |
| Default value | "summary.tsv" |
| Name | outfileSummaryAppend |
| Type | boolean |
| Default value | false |
| Name | outfileSummaryInterval |
| Type | real |
| Default value | 1 |
| Name | outfileCustomerCreate |
| Type | boolean |
| Default value | false |
| Name | outfileCustomerName |
| Type | String |
| Default value | "customer.tsv" |
| Name | outfileCustomerAppend |
| Type | boolean |
| Default value | false |
| Name | outfileCustomerInterval |
| Type | real |
| Default value | 24 |
| Name | outfileStreetBrokerCreate |
| Type | boolean |
| Default value | false |
| Name | outfileStreetBrokerName |
| Type | String |
| Default value | "streetBroker.tsv" |
| Name | outfileStreetBrokerAppend |
| Type | boolean |
| Default value | false |
| Name | outfileStreetBrokerInterval |
| Type | real |
| Default value | 24 |
| Name | param |
| Modificator | Separator |
| Name | numInitialMarkets |
| Type | integer |
| Default value | 1 |
| Name | numInitialCustomers |
| Type | integer |
| Default value | 200 |
| Name | numInitialStreetBrokers |
| Type | integer |
| Default value | 50 |
| Name | numInitialStreetDealers |
| Type | integer |
| Default value | 20 |
| Name | numInitialPrivateDealers |
| Type | integer |
| Default value | 25 |
| Name | numInitialPolice |
| Type | integer |
| Default value | 1 |
| Name | numInitialHomeless |
| Type | integer |
| Default value | 100 |
| Name | param2 |
| Modificator | Separator |
| Name | metabolismRateRange |
| Type | String |
| Default value | "0.004,0.004" |
| Name | addictionIncreaseDurationRange |
| Type | String |
| Default value | "1,1" |
| Name | addictionIncreaseRateRange |
| Type | String |
| Default value | "0.0007,0.0007" |
| Name | addictionDecreaseOnsetRange |
| Type | String |
| Default value | "12,12" |
| Name | addictionDecreaseRateRange |
| Type | String |
| Default value | "0.00014,0.00014" |
| Name | addictionUpperBound |
| Type | real |
| Default value | 360 |
| Modificator | Global |
| Name | desperateNeedThresholdRange |
| Type | String |
| Default value | "0.75,0.75" |
| Name | desperateAddictionThresholdRange |
| Type | String |
| Default value | "5,5" |
| Name | useDelayRange |
| Type | String |
| Default value | "30,30" |
| Name | probTransmitHIV |
| Type | real |
| Default value | 0.005 |
| Modificator | Global |
| Name | treatmentDelayRange |
| Type | String |
| Default value | "1,30" |
| Name | treatmentAddictionReductionRange |
| Type | String |
| Default value | "0.5,0.9" |
| Name | param3 |
| Modificator | Separator |
| Name | csInitialConcentrationDistrParams |
| Type | String |
| Default value | "15,45" |
| Name | csInitialAddictionDistrParams |
| Type | String |
| Default value | "120,55" |
| Name | csInitialInventoryDistrParams |
| Type | String |
| Default value | "0,33" |
| Name | csInitialTimeSinceLastUseDistrParams |
| Type | String |
| Default value | "1,12" |
| Name | csInitialMoneyDistrParams |
| Type | String |
| Default value | "18" |
| Name | csProbInitialHIV |
| Type | real |
| Default value | 0.05 |
| Name | csIncomeAmountDailyRange |
| Type | String |
| Default value | "2,20" |
| Name | csProbIncomeIntervalWeekly |
| Type | real |
| Default value | 0.25 |
| Name | csProbIncomeIntervalMonthly |
| Type | real |
| Default value | 0.25 |
| Name | csWindfallAmountRange |
| Type | String |
| Default value | "20,500" |
| Name | csWindfallIntervalRange |
| Type | String |
| Default value | "1,365" |
| Name | csProbBuyMethodAfford |
| Type | real |
| Default value | 0.25 |
| Description | Probability that a customer's buying method is to buy as much as he can afford. The alternative method is to buy only what he needs. |
| Name | csRandomUseIntervalRange |
| Type | String |
| Default value | "1,7" |
| Name | csProbKnowPrivateDealer |
| Type | real |
| Default value | 0.10 |
| Name | csProbTryPrivateDealerRange |
| Type | String |
| Default value | "0.50,0.50" |
| Name | csAcceptableSbQueueLength |
| Type | integer |
| Default value | 0 |
| Modificator | Global |
| Name | csAcceptableSdQueueLengthRange |
| Type | String |
| Default value | "2,2" |
| Name | csAcceptablePdQueueLengthRange |
| Type | String |
| Default value | "3,3" |
| Name | csDealQuitTime |
| Type | real |
| Default value | 4 |
| Modificator | Global |
| Name | csMarketQuitTimeRange |
| Type | String |
| Default value | "2,2" |
| Name | csProbUseAtSellerRange |
| Type | String |
| Default value | "0.1,0.1" |
| Name | csProbUseTogetherRange |
| Type | String |
| Default value | "0.5,0.5" |
| Name | csProbTreatmentSatisfied |
| Type | real |
| Default value | 0.001 |
| Modificator | Global |
| Name | csProbTreatmentNotSatisfied |
| Type | real |
| Default value | 0 |
| Modificator | Global |
| Name | csProbSeekMoneyRange |
| Type | String |
| Default value | "0.1,0.1" |
| Name | csProbSeekMoneySuccessRange |
| Type | String |
| Default value | "0.5,0.5" |
| Name | csSeekMoneyDelayRange |
| Type | String |
| Default value | "60,360" |
| Name | csRetryDelayRange |
| Type | String |
| Default value | "30,30" |
| Name | param4 |
| Modificator | Separator |
| Name | sbInitialConcentrationDistrParams |
| Type | String |
| Default value | "0,10" |
| Name | sbInitialAddictionDistrParams |
| Type | String |
| Default value | "1,10" |
| Name | sbInitialTimeSinceLastUseDistrParams |
| Type | String |
| Default value | "12,24" |
| Name | sbProbInitialHIV |
| Type | real |
| Default value | 0.10 |
| Name | sbProbKnowPrivateDealer |
| Type | real |
| Default value | 0.9 |
| Name | sbProbTryPrivateDealerRange |
| Type | String |
| Default value | "0.10,0.10" |
| Name | sbCheckAllKnownSd |
| Type | boolean |
| Default value | false |
| Modificator | Global |
| Name | sbNumKnownSdToCheck |
| Type | integer |
| Default value | 1 |
| Modificator | Global |
| Name | sbAcceptableSdQueueLengthRange |
| Type | String |
| Default value | "2,2" |
| Name | sbAcceptablePdQueueLengthRange |
| Type | String |
| Default value | "3,3" |
| Name | sbDealQuitTime |
| Type | real |
| Default value | 2 |
| Modificator | Global |
| Name | sbMarketQuitTimeRange |
| Type | String |
| Default value | "2,2" |
| Name | sbTipPercent |
| Type | real |
| Default value | 10 |
| Modificator | Global |
| Name | sbTipLowerBound |
| Type | real |
| Default value | 3 |
| Modificator | Global |
| Name | sbTipUpperBound |
| Type | real |
| Default value | 30 |
| Modificator | Global |
| Name | sbProbUseTogetherRange |
| Type | String |
| Default value | "0.5,0.5" |
| Name | param5 |
| Modificator | Separator |
| Name | sdInitialMoneyDistrParams |
| Type | String |
| Default value | "500,2000" |
| Name | sdInitialInventoryDistrParams |
| Type | String |
| Default value | "120,3600" |
| Name | sdShiftStartRange |
| Type | String |
| Default value | "6,7" |
| Modificator | Global |
| Name | sdShiftEndRange |
| Type | String |
| Default value | "22,22" |
| Modificator | Global |
| Name | sdProbChangeLocationRange |
| Type | String |
| Default value | "0.1,0.1" |
| Name | sdDealDelayRange |
| Type | String |
| Default value | "15,15" |
| Name | param6 |
| Modificator | Separator |
| Name | pdInitialMoneyDistrParams |
| Type | String |
| Default value | "2000,10000" |
| Name | pdInitialInventoryDistrParams |
| Type | String |
| Default value | "1200,3600" |
| Name | pdShiftStartHourRange |
| Type | String |
| Default value | "6,10" |
| Name | pdShiftLengthRange |
| Type | String |
| Default value | "8,16" |
| Name | pdAcceptableDeliverUnitsRange |
| Type | String |
| Default value | "120,120" |
| Name | pdProbDeliverHomeRange |
| Type | String |
| Default value | "0.5,0.5" |
| Name | pdProbDeliverMarketRange |
| Type | String |
| Default value | "0.1,0.1" |
| Name | pdDealQuitTime |
| Type | real |
| Default value | 4 |
| Modificator | Global |
| Name | pdDealDelayRange |
| Type | String |
| Default value | "30,30" |
| Name | pdInvitationDealsRange |
| Type | String |
| Default value | "6,6" |
| Name | param8 |
| Modificator | Separator |
| Name | poVisionRadius |
| Type | real |
| Default value | 100 |
| Modificator | Global |
| Name | poProbHarassCustomer |
| Type | real |
| Default value | 0.25 |
| Modificator | Global |
| Name | poProbHarassStreetBroker |
| Type | real |
| Default value | 0.5 |
| Modificator | Global |
| Name | poProbHarassStreetDealer |
| Type | real |
| Default value | 0.75 |
| Modificator | Global |
| Name | poProbHarassPrivateDealer |
| Type | real |
| Default value | 0.25 |
| Modificator | Global |
| Name | poProbHarassHomeless |
| Type | real |
| Default value | 0.5 |
| Modificator | Global |
| Name | poHarassDuration |
| Type | real |
| Default value | 60 |
| Modificator | Global |
| Name | poHarassRepeatDelay |
| Type | real |
| Default value | 24 |
| Modificator | Global |
| Name | poProbArrestCustomer |
| Type | real |
| Default value | 0.8 |
| Modificator | Global |
| Name | poProbArrestStreetBroker |
| Type | real |
| Default value | 0.8 |
| Modificator | Global |
| Name | poProbArrestStreetDealer |
| Type | real |
| Default value | 0.9 |
| Modificator | Global |
| Name | poProbArrestPrivateDealer |
| Type | real |
| Default value | 0.1 |
| Modificator | Global |
| Name | poProbArrestHomeless |
| Type | real |
| Default value | 0.8 |
| Modificator | Global |
| Name | poArrestDuration |
| Type | real |
| Default value | 60 |
| Modificator | Global |
| Name | poJailPerDrugUnit |
| Type | real |
| Default value | 0.05 |
| Modificator | Global |
| Name | poUseBusts |
| Type | boolean |
| Default value | false |
| Modificator | Global |
| Name | poBustStartTimes |
| Type | String |
| Default value | "30,60,90,120,150" |
| Modificator | Global |
| Name | poBustDuration |
| Type | real |
| Default value | 24 |
| Modificator | Global |
| Name | poBustOfficers |
| Type | integer |
| Default value | 30 |
| Modificator | Global |
| Name | poBustVisionRadius |
| Type | real |
| Default value | 300 |
| Modificator | Global |
| Name | poBustProbHarassCustomer |
| Type | real |
| Default value | 0.50 |
| Modificator | Global |
| Name | poBustProbHarassStreetBroker |
| Type | real |
| Default value | 0.75 |
| Modificator | Global |
| Name | poBustProbHarassStreetDealer |
| Type | real |
| Default value | 1 |
| Modificator | Global |
| Name | poBustProbHarassPrivateDealer |
| Type | real |
| Default value | 0.50 |
| Modificator | Global |
| Name | poBustProbHarassHomeless |
| Type | real |
| Default value | 0.75 |
| Modificator | Global |
| Name | poBustProbArrestCustomer |
| Type | real |
| Default value | 1 |
| Modificator | Global |
| Name | poBustProbArrestStreetBroker |
| Type | real |
| Default value | 1 |
| Modificator | Global |
| Name | poBustProbArrestStreetDealer |
| Type | real |
| Default value | 1 |
| Modificator | Global |
| Name | poBustProbArrestPrivateDealer |
| Type | real |
| Default value | 0.1 |
| Modificator | Global |
| Name | poBustProbArrestHomeless |
| Type | real |
| Default value | 1 |
| Modificator | Global |
| Icon | |
| Picture | |
| Structure | |
| Picture | ![]() |
| ChartTimer | outfileStreetBrokerTimer |
| Expire | No (manual mode) |
| Expiry Action | // We set this timer's expiry to manual mode so that we can control // precisely when it expires. This is useful mainly at the model // startup. If we set the expiry to cyclic mode expiring at startup, // then AnyLogic will expire the timer for us just before running our // Main startup code. This is a problem since our Main startup code: // 1) modifies variables that are used in defining the expiration time // 2) creates agents that are accessed in the action code below // Write to the outfile only if requested and only if we are not in // applet mode (since applets can't write to files). if (outfileStreetBrokerCreate && !util.Model.getRunMode().equals("applet")) { // Note that we end lines in the outfile with an explicit "\r\n" // instead of using the writeln() method to do it for us. This is // because writeln() chooses the line terminator appropriate to the // platform, meaning it will use "\r\n" on Windows and "\n" on Linux. // However, we want the outfile to have the same line terminators // whether we run the model on our Windows PCs or on the Linux cluster. //----------------------------------------------------------------- // Open the outfile at the beginning of each replication. if (Engine.getTime() == 0) { // Append to the outfile if either of the following conditions // is true: // // 1) The append parameter is true. // 2) This is not the first replication in this simulation. // // If either is false, we will overwrite the outfile. Whenever // we overwrite the outfile, we will add column headers. if (outfileStreetBrokerAppend || Engine.getReplication() > 1) { // appending try { outfileStreetBrokerWriter = new BufferedWriter(new FileWriter(outfileStreetBrokerName, true)); } catch (IOException e) { traceln("***ERROR in outfileStreetBrokerTimer.action: Cannot open outfile in append mode: " + e.getMessage()); } } else { // overwriting try { outfileStreetBrokerWriter = new BufferedWriter(new FileWriter(outfileStreetBrokerName)); } catch (IOException e) { traceln("***ERROR in outfileStreetBrokerTimer.action: Cannot open outfile in overwrite mode: " + e.getMessage()); } try { outfileStreetBrokerWriter.write( "replication" + "\t" + "modelMinutes" + "\t" + "id" + "\t" + "money" + "\t" + "inventory" + "\t" + "addiction" + "\t" + "concentration" + "\t" + "numUses" + "\t" + "allTransactionsGood" + "\t" + "sdTransactionsGood" + "\t" + "pdTransactionsGood" + "\r\n" ); } catch (IOException e) { traceln("***ERROR in outfileStreetBrokerTimer.action: Cannot write headers to outfile: " + e.getMessage()); } } } //----------------------------------------------------------------- // Write a data record to the outfile at every expiration. try { for (int id = 0; id < streetBroker.size(); id++) { StreetBroker sb = streetBroker.item(id); outfileStreetBrokerWriter.write( Engine.getReplication() + "\t" + util.Format.decimalFormat(Engine.getTime() / util.Units.minutes(1), 0) + "\t" + id + "\t" + util.Format.decimalFormat(sb.money, 0) + "\t" + util.Format.decimalFormat(sb.userBehavior.inventory, 0) + "\t" + util.Format.decimalFormat(sb.userBehavior.addiction, 2) + "\t" + util.Format.decimalFormat(sb.userBehavior.concentration, 2) + "\t" + sb.userBehavior.numUses + "\t" + sb.allTransactions.numGood + "\t" + sb.sdTransactions.numGood + "\t" + sb.pdTransactions.numGood + "\r\n" ); } } catch (IOException e) { traceln("***ERROR in outfileStreetBrokerTimer.action: Cannot write data to outfile: " + e.getMessage()); } //----------------------------------------------------------------- // Set the timer to expire at the end of the next interval. restart(outfileStreetBrokerInterval); //----------------------------------------------------------------- // Close the outfile at the end of the replication. // This is performed in the replicationRunTimer code. } |
| ChartTimer | outfileCustomerTimer |
| Expire | No (manual mode) |
| Expiry Action | // We set this timer's expiry to manual mode so that we can control // precisely when it expires. This is useful mainly at the model // startup. If we set the expiry to cyclic mode expiring at startup, // then AnyLogic will expire the timer for us just before running our // Main startup code. This is a problem since our Main startup code: // 1) modifies variables that are used in defining the expiration time // 2) creates agents that are accessed in the action code below // Write to the outfile only if requested and only if we are not in // applet mode (since applets can't write to files). if (outfileCustomerCreate && !util.Model.getRunMode().equals("applet")) { // Note that we end lines in the outfile with an explicit "\r\n" // instead of using the writeln() method to do it for us. This is // because writeln() chooses the line terminator appropriate to the // platform, meaning it will use "\r\n" on Windows and "\n" on Linux. // However, we want the outfile to have the same line terminators // whether we run the model on our Windows PCs or on the Linux cluster. //----------------------------------------------------------------- // Open the outfile at the beginning of each replication. if (Engine.getTime() == 0) { // Append to the outfile if either of the following conditions // is true: // // 1) The append parameter is true. // 2) This is not the first replication in this simulation. // // If either is false, we will overwrite the outfile. Whenever // we overwrite the outfile, we will add column headers. if (outfileCustomerAppend || Engine.getReplication() > 1) { // appending try { outfileCustomerWriter = new BufferedWriter(new FileWriter(outfileCustomerName, true)); } catch (IOException e) { traceln("***ERROR in outfileCustomerTimer.action: Cannot open outfile in append mode: " + e.getMessage()); } } else { // overwriting try { outfileCustomerWriter = new BufferedWriter(new FileWriter(outfileCustomerName)); } catch (IOException e) { traceln("***ERROR in outfileCustomerTimer.action: Cannot open outfile in overwrite mode: " + e.getMessage()); } try { outfileCustomerWriter.write( "replication" + "\t" + "modelMinutes" + "\t" + "id" + "\t" + "money" + "\t" + "inventory" + "\t" + "addiction" + "\t" + "concentration" + "\t" + "numUses" + "\t" + "allTransactionsGood" + "\t" + "sbTransactionsGood" + "\t" + "sdTransactionsGood" + "\t" + "pdTransactionsGood" + "\t" + "marketTripsGood" + "\r\n" ); } catch (IOException e) { traceln("***ERROR in outfileCustomerTimer.action: Cannot write headers to outfile: " + e.getMessage()); } } } //----------------------------------------------------------------- // Write a data record to the outfile at every expiration. try { for (int id = 0; id < customer.size(); id++) { Customer cs = customer.item(id); outfileCustomerWriter.write( Engine.getReplication() + "\t" + util.Format.decimalFormat(Engine.getTime() / util.Units.minutes(1), 0) + "\t" + id + "\t" + util.Format.decimalFormat(cs.money, 0) + "\t" + util.Format.decimalFormat(cs.userBehavior.inventory, 0) + "\t" + util.Format.decimalFormat(cs.userBehavior.addiction, 2) + "\t" + util.Format.decimalFormat(cs.userBehavior.concentration, 2) + "\t" + cs.userBehavior.numUses + "\t" + cs.allTransactions.numGood + "\t" + cs.sbTransactions.numGood + "\t" + cs.sdTransactions.numGood + "\t" + cs.pdTransactions.numGood + "\t" + cs.marketTrips.numGood + "\r\n" ); } } catch (IOException e) { traceln("***ERROR in outfileCustomerTimer.action: Cannot write data to outfile: " + e.getMessage()); } //----------------------------------------------------------------- // Set the timer to expire at the end of the next interval. restart(outfileCustomerInterval); //----------------------------------------------------------------- // Close the outfile at the end of the replication. // This is performed in the replicationRunTimer code. } |
| ChartTimer | replicationRunTimer |
| Expire | No (manual mode) |
| Expiry Action | // We set this timer's expiry to manual mode so that we can control // precisely when it expires. This is useful mainly at the model // startup. If we set the expiry to 'expire once' mode, then AnyLogic // will expire the timer for us just before running our Main startup code. // This is a problem since our Main startup code modifies variables that // are used in defining the expiration time. // Close any open outfiles. if (outfileSummaryWriter != null) { try { outfileSummaryWriter.close(); } catch (IOException e) { traceln("***ERROR in replicationRunTimer.action: Cannot close outfileSummaryWriter: " + e.getMessage()); } } if (outfileCustomerWriter != null) { try { outfileCustomerWriter.close(); } catch (IOException e) { traceln("***ERROR in replicationRunTimer.action: Cannot close outfileCustomerWriter: " + e.getMessage()); } } if (outfileStreetBrokerWriter != null) { try { outfileStreetBrokerWriter.close(); } catch (IOException e) { traceln("***ERROR in replicationRunTimer.action: Cannot close outfileStreetBrokerWriter: " + e.getMessage()); } } // Call the next replication. Engine.nextReplication(); |
| ChartTimer | outfileSummaryTimer |
| Expire | No (manual mode) |
| Expiry Action | // We set this timer's expiry to manual mode so that we can control // precisely when it expires. This is useful mainly at the model // startup. If we set the expiry to cyclic mode expiring at startup, // then AnyLogic will expire the timer for us just before running our // Main startup code. This is a problem since our Main startup code: // 1) modifies variables that are used in defining the expiration time // 2) creates agents that are accessed in the action code below // Write to the outfile only if requested and only if we are not in // applet mode (since applets can't write to files). if (outfileSummaryCreate && !util.Model.getRunMode().equals("applet")) { // Note that we end lines in the outfile with an explicit "\r\n" // instead of using the writeln() method to do it for us. This is // because writeln() chooses the line terminator appropriate to the // platform, meaning it will use "\r\n" on Windows and "\n" on Linux. // However, we want the outfile to have the same line terminators // whether we run the model on our Windows PCs or on the Linux cluster. //----------------------------------------------------------------- // Open the outfile at the beginning of each replication. if (Engine.getTime() == 0) { // Append to the outfile if either of the following conditions // is true: // // 1) The append parameter is true. // 2) This is not the first replication in this simulation. // // If either is false, we will overwrite the outfile. Whenever // we overwrite the outfile, we will add column headers. if (outfileSummaryAppend || Engine.getReplication() > 1) { // appending try { outfileSummaryWriter = new BufferedWriter(new FileWriter(outfileSummaryName, true)); } catch (IOException e) { traceln("***ERROR in outfileSummaryTimer.action: Cannot open outfile in append mode: " + e.getMessage()); } } else { // overwriting try { outfileSummaryWriter = new BufferedWriter(new FileWriter(outfileSummaryName)); } catch (IOException e) { traceln("***ERROR in outfileSummaryTimer.action: Cannot open outfile in overwrite mode: " + e.getMessage()); } try { outfileSummaryWriter.write( "replication" + "\t" + "modelMinutes" + "\t" + "csAvgMoney" + "\t" + "csAvgInventory" + "\t" + "csAvgAddiction" + "\t" + "csAvgConcentration" + "\t" + "csAllTransactionsGood" + "\t" + "csAllTransactionsUnits" + "\t" + "csAllTransactionsPrice" + "\t" + "csAllTransactionsFailed" + "\t" + "csSbTransactionsGood" + "\t" + "csSbTransactionsUnits" + "\t" + "csSbTransactionsPrice" + "\t" + "csSbTransactionsFailed" + "\t" + "csSdTransactionsGood" + "\t" + "csSdTransactionsUnits" + "\t" + "csSdTransactionsPrice" + "\t" + "csSdTransactionsFailed" + "\t" + "csPdTransactionsGood" + "\t" + "csPdTransactionsUnits" + "\t" + "csPdTransactionsPrice" + "\t" + "csPdTransactionsFailed" + "\t" + "csMarketTripsGood" + "\t" + "csMarketTripsUnits" + "\t" + "csMarketTripsPrice" + "\t" + "csMarketTripsFailed" + "\t" + "csNumTreatment" + "\t" + "csNumJail" + "\t" + "csNumHiv" + "\t" + "sbAvgMoney" + "\t" + "sbAvgInventory" + "\t" + "sbAvgAddiction" + "\t" + "sbAvgConcentration" + "\t" + "sbAllTransactionsGood" + "\t" + "sbAllTransactionsUnits" + "\t" + "sbAllTransactionsPrice" + "\t" + "sbAllTransactionsFailed" + "\t" + "sbSdTransactionsGood" + "\t" + "sbSdTransactionsUnits" + "\t" + "sbSdTransactionsPrice" + "\t" + "sbSdTransactionsFailed" + "\t" + "sbPdTransactionsGood" + "\t" + "sbPdTransactionsUnits" + "\t" + "sbPdTransactionsPrice" + "\t" + "sbPdTransactionsFailed" + "\t" + "sbNumJail" + "\t" + "sbNumHiv" + "\t" + "sdNumJail" + "\t" + "pdNumJail" + "\t" + "poNumHarassments" + "\t" + "poNumArrests" + "\r\n" ); } catch (IOException e) { traceln("***ERROR in outfileSummaryTimer.action: Cannot write headers to outfile: " + e.getMessage()); } } } //----------------------------------------------------------------- // Write a data record to the outfile at every expiration. // Aggregate values across all customers. int csNumTreatment = 0; int csNumJail = 0; int csNumHiv = 0; double csTotInventory = 0; double csTotAddiction = 0; double csTotConcentration = 0; for (int i = 0; i < customer.size(); i++) { if (customer.item(i).currentPlace == Main.PLACE_TREATMENT) { csNumTreatment++; } else if (customer.item(i).currentPlace == Main.PLACE_JAIL) { csNumJail++; } if (customer.item(i).hasHIV()) { csNumHiv++; } csTotInventory += customer.item(i).userBehavior.inventory; csTotAddiction += customer.item(i).userBehavior.addiction; csTotConcentration += customer.item(i).userBehavior.concentration; } double csAvgInventory = (customer.size() == 0 ? 0 : csTotInventory / customer.size()); double csAvgAddiction = (customer.size() == 0 ? 0 : csTotAddiction / customer.size()); double csAvgConcentration = (customer.size() == 0 ? 0 : csTotConcentration / customer.size()); // Aggregate values across all street brokers. int sbNumJail = 0; int sbNumHiv = 0; double sbTotInventory = 0; double sbTotAddiction = 0; double sbTotConcentration = 0; for (int i = 0; i < streetBroker.size(); i++) { if (streetBroker.item(i).currentPlace == Main.PLACE_JAIL) { sbNumJail++; } if (streetBroker.item(i).hasHIV()) { sbNumHiv++; } sbTotInventory += streetBroker.item(i).userBehavior.inventory; sbTotAddiction += streetBroker.item(i).userBehavior.addiction; sbTotConcentration += streetBroker.item(i).userBehavior.concentration; } double sbAvgInventory = (streetBroker.size() == 0 ? 0 : sbTotInventory / streetBroker.size()); double sbAvgAddiction = (streetBroker.size() == 0 ? 0 : sbTotAddiction / streetBroker.size()); double sbAvgConcentration = (streetBroker.size() == 0 ? 0 : sbTotConcentration / streetBroker.size()); // Aggregate values across all street dealers. int sdNumJail = 0; for (int i = 0; i < streetDealer.size(); i++) { if (streetDealer.item(i).currentPlace == Main.PLACE_JAIL) { sdNumJail++; } } // Aggregate values across all private dealers. int pdNumJail = 0; for (int i = 0; i < privateDealer.size(); i++) { if (privateDealer.item(i).currentPlace == Main.PLACE_JAIL) { pdNumJail++; } } // Write the data record. try { outfileSummaryWriter.write( Engine.getReplication() + "\t" + util.Format.decimalFormat(Engine.getTime() / util.Units.minutes(1), 0) + "\t" + util.Format.decimalFormat(customer.average("money"), 2) + "\t" + util.Format.decimalFormat(csAvgInventory, 2) + "\t" + util.Format.decimalFormat(csAvgAddiction, 2) + "\t" + util.Format.decimalFormat(csAvgConcentration, 2) + "\t" + csAllTransactions.numGood + "\t" + util.Format.decimalFormat(csAllTransactions.totalUnits, 0) + "\t" + util.Format.decimalFormat(csAllTransactions.totalPrice, 0) + "\t" + csAllTransactions.numFailed + "\t" + csSbTransactions.numGood + "\t" + util.Format.decimalFormat(csSbTransactions.totalUnits, 0) + "\t" + util.Format.decimalFormat(csSbTransactions.totalPrice, 0) + "\t" + csSbTransactions.numFailed + "\t" + csSdTransactions.numGood + "\t" + util.Format.decimalFormat(csSdTransactions.totalUnits, 0) + "\t" + util.Format.decimalFormat(csSdTransactions.totalPrice, 0) + "\t" + csSdTransactions.numFailed + "\t" + csPdTransactions.numGood + "\t" + util.Format.decimalFormat(csPdTransactions.totalUnits, 0) + "\t" + util.Format.decimalFormat(csPdTransactions.totalPrice, 0) + "\t" + csPdTransactions.numFailed + "\t" + csMarketTrips.numGood + "\t" + util.Format.decimalFormat(csMarketTrips.totalUnits, 0) + "\t" + util.Format.decimalFormat(csMarketTrips.totalPrice, 0) + "\t" + csMarketTrips.numFailed + "\t" + csNumTreatment + "\t" + csNumJail + "\t" + csNumHiv + "\t" + util.Format.decimalFormat(streetBroker.average("money"), 2) + "\t" + util.Format.decimalFormat(sbAvgInventory, 2) + "\t" + util.Format.decimalFormat(sbAvgAddiction, 2) + "\t" + util.Format.decimalFormat(sbAvgConcentration, 2) + "\t" + sbAllTransactions.numGood + "\t" + util.Format.decimalFormat(sbAllTransactions.totalUnits, 0) + "\t" + util.Format.decimalFormat(sbAllTransactions.totalPrice, 0) + "\t" + sbAllTransactions.numFailed + "\t" + sbSdTransactions.numGood + "\t" + util.Format.decimalFormat(sbSdTransactions.totalUnits, 0) + "\t" + util.Format.decimalFormat(sbSdTransactions.totalPrice, 0) + "\t" + sbSdTransactions.numFailed + "\t" + sbPdTransactions.numGood + "\t" + util.Format.decimalFormat(sbPdTransactions.totalUnits, 0) + "\t" + util.Format.decimalFormat(sbPdTransactions.totalPrice, 0) + "\t" + sbPdTransactions.numFailed + "\t" + sbNumJail + "\t" + sbNumHiv + "\t" + sdNumJail + "\t" + pdNumJail + "\t" + util.Format.decimalFormat(police.sum("numHarassments"), 0) + "\t" + util.Format.decimalFormat(police.sum("numArrests"), 0) + "\r\n" ); } catch (IOException e) { traceln("***ERROR in outfileSummaryTimer.action: Cannot write data to outfile: " + e.getMessage()); } //----------------------------------------------------------------- // Set the timer to expire at the end of the next interval. restart(outfileSummaryInterval); //----------------------------------------------------------------- // Close the outfile at the end of the replication. // This is performed in the replicationRunTimer code. } |
| Variable | outfileStreetBrokerWriter |
| Variable type | BufferedWriter |
| Initial value | null |
| Variable | dealCounter |
| Variable type | integer |
| Initial value | 0 |
| Variable | outfileCustomerWriter |
| Variable type | BufferedWriter |
| Initial value | null |
| Variable | outfileSummaryWriter |
| Variable type | BufferedWriter |
| Initial value | null |
| Object | sbSdTransactions |
| Type | misc.TransactionCounter |
| Object | sbPdTransactions |
| Type | misc.TransactionCounter |
| Object | sbAllTransactions |
| Type | misc.TransactionCounter |
| Object | csSbTransactions |
| Type | misc.TransactionCounter |
| Object | csSdTransactions |
| Type | misc.TransactionCounter |
| Object | csPdTransactions |
| Type | misc.TransactionCounter |
| Object | csAllTransactions |
| Type | misc.TransactionCounter |
| Object | customer |
| Type | drugmarket.Customer |
| Number of objects | 0 |
| Object | market |
| Type | drugmarket.Market |
| Number of objects | 0 |
| Object | streetBroker |
| Type | drugmarket.StreetBroker |
| Number of objects | 0 |
| Object | privateDealer |
| Type | drugmarket.PrivateDealer |
| Number of objects | 0 |
| Object | csMarketTrips |
| Type | misc.TransactionCounter |
| Object | police |
| Type | drugmarket.Police |
| Number of objects | 0 |
| Object | homeless |
| Type | drugmarket.Homeless |
| Number of objects | 0 |
| Object | marketBustTimers |
| Type | misc.MarketBustTimer |
| Number of objects | 0 |
| Object | streetDealerGroup |
| Type | drugmarket.StreetDealerGroup |
| Number of objects | 0 |
| Object | streetDealer |
| Type | drugmarket.StreetDealer |
| Number of objects | 0 |
| Algorithmic Functions | |
| Name | executionControl |
| Type | void |
| Body | // Override the ActiveObject.executionControl() function to allow // us to run multiple replications in a single simulation. // Engine.getReplication() returns the current replication // number (starting with 1) *during* the replication. However, // we are calling it here *before* the replication. In this // case it returns the previous replication number. If we have // not yet run any replications, it returns 0. while (Engine.getReplication() < numReplications) { // Run one replication of the model. Engine.execute(); } |
| Name | getNewDealID |
| Type | integer |
| Body | if (dealCounter < Integer.MAX_VALUE) { dealCounter++; } else { traceln("***WARNING in Main.getNewDealID(): Reached maximum dealID, resetting counter to 1 @ " + Engine.getTime()); dealCounter = 1; } return dealCounter; |
| Name | initializeAgents |
| Type | void |
| Body | // We manually initialize all the encapsulated objects because we need more // control over the order of this process and more flexibility than we would // have if we let AnyLogic do it for us. //------------------------------------------------------------------------- // Initialize the markets. This must be done prior to initializing // any of the agents that need a reference to a market. for (int i = 0; i < numInitialMarkets; i++) { Market mk = new Market(); mk.width = uniform(util.Params.getDouble(marketSizeRange, 0), util.Params.getDouble(marketSizeRange, 1)); mk.height = uniform(util.Params.getDouble(marketSizeRange, 0), util.Params.getDouble(marketSizeRange, 1)); // Find a position in the city for the market. Make sure it is // fully contained within the city, and make sure it does not // overlap any other markets. boolean foundLocation = false; int numLocationTries = 0; while (!foundLocation && numLocationTries < 20) { mk.x = uniform(cityWidth); mk.y = uniform(cityHeight); numLocationTries++; boolean validMarketLocation = true; if (!mk.isContainedInRectangle(0, 0, cityWidth, cityHeight)) { validMarketLocation = false; } for (int j = 0; j < i; j++) { if (mk.isOverlappingMarket(market.item(j))) { validMarketLocation = false; } } foundLocation = validMarketLocation; } setup_market(mk, market.size()); } //------------------------------------------------------------------------- // Initialize customers. for (int i = 0; i < numInitialCustomers; i++) { Customer cs = new Customer(); cs.homeX = uniform(cityWidth); cs.homeY = uniform(cityHeight); cs.initialMoney = exponential(1/util.Params.getDouble(csInitialMoneyDistrParams, 0)); cs.initialInventory = util.Math.round(uniform(util.Params.getDouble(csInitialInventoryDistrParams, 0), util.Params.getDouble(csInitialInventoryDistrParams, 1)), useIncrement); cs.initialAddiction = max(useIncrement, normal(util.Params.getDouble(csInitialAddictionDistrParams, 1), util.Params.getDouble(csInitialAddictionDistrParams, 0))); cs.initialConcentration = max(0, normal(util.Params.getDouble(csInitialConcentrationDistrParams, 1), util.Params.getDouble(csInitialConcentrationDistrParams, 0))); cs.initialTimeSinceLastUse = uniform(util.Params.getDouble(csInitialTimeSinceLastUseDistrParams, 0), util.Params.getDouble(csInitialTimeSinceLastUseDistrParams, 1)); cs.metabolismRate = uniform(util.Params.getDouble(metabolismRateRange, 0), util.Params.getDouble(metabolismRateRange, 1)); cs.addictionIncreaseDuration = uniform(util.Params.getDouble(addictionIncreaseDurationRange, 0), util.Params.getDouble(addictionIncreaseDurationRange, 1)); cs.addictionIncreaseRate = uniform(util.Params.getDouble(addictionIncreaseRateRange, 0), util.Params.getDouble(addictionIncreaseRateRange, 1)); cs.addictionDecreaseOnset = uniform(util.Params.getDouble(addictionDecreaseOnsetRange, 0), util.Params.getDouble(addictionDecreaseOnsetRange, 1)); cs.addictionDecreaseRate = uniform(util.Params.getDouble(addictionDecreaseRateRange, 0), util.Params.getDouble(addictionDecreaseRateRange, 1)); cs.desperateNeedThreshold = uniform(util.Params.getDouble(desperateNeedThresholdRange, 0), util.Params.getDouble(desperateNeedThresholdRange, 1)); cs.desperateAddictionThreshold = uniform(util.Params.getDouble(desperateAddictionThresholdRange, 0), util.Params.getDouble(desperateAddictionThresholdRange, 1)); cs.useDelayMin = util.Params.getDouble(useDelayRange, 0); cs.useDelayMax = util.Params.getDouble(useDelayRange, 1); if (randomTrue(csProbIncomeIntervalWeekly)) { cs.incomeInterval = util.Units.days(7); cs.incomeAmount = 7 * uniform(util.Params.getDouble(csIncomeAmountDailyRange, 0), util.Params.getDouble(csIncomeAmountDailyRange, 1)); } else if (randomTrue(csProbIncomeIntervalMonthly)) { cs.incomeInterval = util.Units.days(30); cs.incomeAmount = 30 * uniform(util.Params.getDouble(csIncomeAmountDailyRange, 0), util.Params.getDouble(csIncomeAmountDailyRange, 1)); } else { cs.incomeInterval = util.Units.days(15); cs.incomeAmount = 15 * uniform(util.Params.getDouble(csIncomeAmountDailyRange, 0), util.Params.getDouble(csIncomeAmountDailyRange, 1)); } cs.windfallAmountMin = util.Params.getDouble(csWindfallAmountRange, 0); cs.windfallAmountMax = util.Params.getDouble(csWindfallAmountRange, 1); cs.windfallIntervalMin = util.Params.getDouble(csWindfallIntervalRange, 0); cs.windfallIntervalMax = util.Params.getDouble(csWindfallIntervalRange, 1); cs.buyMethod = randomTrue(csProbBuyMethodAfford) ? "afford" : "need"; cs.randomUseIntervalMin = util.Params.getDouble(csRandomUseIntervalRange, 0); cs.randomUseIntervalMax = util.Params.getDouble(csRandomUseIntervalRange, 1); cs.retryDelayMin = util.Params.getDouble(csRetryDelayRange, 0); cs.retryDelayMax = util.Params.getDouble(csRetryDelayRange, 1); cs.probUseAtSeller = uniform(util.Params.getDouble(csProbUseAtSellerRange, 0), util.Params.getDouble(csProbUseAtSellerRange, 1)); cs.probUseTogether = uniform(util.Params.getDouble(csProbUseTogetherRange, 0), util.Params.getDouble(csProbUseTogetherRange, 1)); cs.initialHIV = randomTrue(csProbInitialHIV); cs.probSeekMoney = uniform(util.Params.getDouble(csProbSeekMoneyRange, 0), util.Params.getDouble(csProbSeekMoneyRange, 1)); cs.probSeekMoneySuccess = uniform(util.Params.getDouble(csProbSeekMoneySuccessRange, 0), util.Params.getDouble(csProbSeekMoneySuccessRange, 1)); cs.seekMoneyDelayMin = util.Params.getDouble(csSeekMoneyDelayRange, 0); cs.seekMoneyDelayMax = util.Params.getDouble(csSeekMoneyDelayRange, 1); cs.visionRadius = uniform(util.Params.getDouble(visionRadiusRange, 0), util.Params.getDouble(visionRadiusRange, 1)); cs.marketQuitTime = uniform(util.Params.getDouble(csMarketQuitTimeRange, 0), util.Params.getDouble(csMarketQuitTimeRange, 1)); cs.probTryPrivateDealer = uniform(util.Params.getDouble(csProbTryPrivateDealerRange, 0), util.Params.getDouble(csProbTryPrivateDealerRange, 1)); cs.acceptableSdQueueLength = uniform_discr(util.Params.getInt(csAcceptableSdQueueLengthRange, 0), util.Params.getInt(csAcceptableSdQueueLengthRange, 1)); cs.acceptablePdQueueLength = uniform_discr(util.Params.getInt(csAcceptablePdQueueLengthRange, 0), util.Params.getInt(csAcceptablePdQueueLengthRange, 1)); cs.treatmentDelayMin = util.Params.getDouble(treatmentDelayRange, 0); cs.treatmentDelayMax = util.Params.getDouble(treatmentDelayRange, 1); cs.treatmentAddictionReduction = uniform(util.Params.getDouble(treatmentAddictionReductionRange, 0), util.Params.getDouble(treatmentAddictionReductionRange, 1)); setup_customer(cs, customer.size()); } //------------------------------------------------------------------------- // Initialize the street dealer group. StreetDealerGroup sdg = new StreetDealerGroup(); sdg.initialMarket = market.random(); setup_streetDealerGroup(sdg, streetDealerGroup.size()); //------------------------------------------------------------------------- // Initialize street dealers. for (int i = 0; i < numInitialStreetDealers; i++) { StreetDealer sd = new StreetDealer(); sd.initialGroup = streetDealerGroup.random(); sd.initialMoney = util.Math.round(uniform(util.Params.getDouble(sdInitialMoneyDistrParams, 0), util.Params.getDouble(sdInitialMoneyDistrParams, 1)), useIncrement); sd.initialInventory = util.Math.round(uniform(util.Params.getDouble(sdInitialInventoryDistrParams, 0), util.Params.getDouble(sdInitialInventoryDistrParams, 1)), useIncrement); sd.probChangeLocation = uniform(util.Params.getDouble(sdProbChangeLocationRange, 0), util.Params.getDouble(sdProbChangeLocationRange, 1)); sd.dealDelayMin = util.Params.getDouble(sdDealDelayRange, 0); sd.dealDelayMax = util.Params.getDouble(sdDealDelayRange, 1); sd.visionRadius = uniform(util.Params.getDouble(visionRadiusRange, 0), util.Params.getDouble(visionRadiusRange, 1)); setup_streetDealer(sd, streetDealer.size()); } //------------------------------------------------------------------------- // Initialize street brokers. for (int i = 0; i < numInitialStreetBrokers; i++) { StreetBroker sb = new StreetBroker(); sb.initialMarket = market.random(); sb.initialAddiction = uniform(util.Params.getDouble(sbInitialAddictionDistrParams, 0), util.Params.getDouble(sbInitialAddictionDistrParams, 1)); sb.initialConcentration = uniform(util.Params.getDouble(sbInitialConcentrationDistrParams, 0), util.Params.getDouble(sbInitialConcentrationDistrParams, 1)); sb.initialTimeSinceLastUse = uniform(util.Params.getDouble(sbInitialTimeSinceLastUseDistrParams, 0), util.Params.getDouble(sbInitialTimeSinceLastUseDistrParams, 1)); sb.metabolismRate = uniform(util.Params.getDouble(metabolismRateRange, 0), util.Params.getDouble(metabolismRateRange, 1)); sb.addictionIncreaseDuration = uniform(util.Params.getDouble(addictionIncreaseDurationRange, 0), util.Params.getDouble(addictionIncreaseDurationRange, 1)); sb.addictionIncreaseRate = uniform(util.Params.getDouble(addictionIncreaseRateRange, 0), util.Params.getDouble(addictionIncreaseRateRange, 1)); sb.addictionDecreaseOnset = uniform(util.Params.getDouble(addictionDecreaseOnsetRange, 0), util.Params.getDouble(addictionDecreaseOnsetRange, 1)); sb.addictionDecreaseRate = uniform(util.Params.getDouble(addictionDecreaseRateRange, 0), util.Params.getDouble(addictionDecreaseRateRange, 1)); sb.useDelayMin = util.Params.getDouble(useDelayRange, 0); sb.useDelayMax = util.Params.getDouble(useDelayRange, 1); sb.visionRadius = uniform(util.Params.getDouble(visionRadiusRange, 0), util.Params.getDouble(visionRadiusRange, 1)); sb.marketQuitTime = uniform(util.Params.getDouble(sbMarketQuitTimeRange, 0), util.Params.getDouble(sbMarketQuitTimeRange, 1)); sb.probTryPrivateDealer = uniform(util.Params.getDouble(sbProbTryPrivateDealerRange, 0), util.Params.getDouble(sbProbTryPrivateDealerRange, 1)); sb.acceptableSdQueueLength = uniform_discr(util.Params.getInt(sbAcceptableSdQueueLengthRange, 0), util.Params.getInt(csAcceptableSdQueueLengthRange, 1)); sb.acceptablePdQueueLength = uniform_discr(util.Params.getInt(sbAcceptablePdQueueLengthRange, 0), util.Params.getInt(csAcceptablePdQueueLengthRange, 1)); sb.probUseTogether = uniform(util.Params.getDouble(sbProbUseTogetherRange, 0), util.Params.getDouble(sbProbUseTogetherRange, 1)); sb.initialHIV = randomTrue(sbProbInitialHIV); setup_streetBroker(sb, streetBroker.size()); } //------------------------------------------------------------------------- // Initialize private dealers. for (int i = 0; i < numInitialPrivateDealers; i++) { PrivateDealer pd = new PrivateDealer(); pd.homeX = uniform(cityWidth); pd.homeY = uniform(cityHeight); pd.initialMoney = uniform(util.Params.getDouble(pdInitialMoneyDistrParams, 0), util.Params.getDouble(pdInitialMoneyDistrParams, 1)); pd.initialInventory = util.Math.round(uniform(util.Params.getDouble(pdInitialInventoryDistrParams, 0), util.Params.getDouble(pdInitialInventoryDistrParams, 1)), useIncrement); pd.shiftStartHourMin = util.Params.getDouble(pdShiftStartHourRange, 0); pd.shiftStartHourMax = util.Params.getDouble(pdShiftStartHourRange, 1); pd.shiftLengthMin = util.Params.getDouble(pdShiftLengthRange, 0); pd.shiftLengthMax = util.Params.getDouble(pdShiftLengthRange, 1); pd.dealDelayMin = util.Params.getDouble(pdDealDelayRange, 0); pd.dealDelayMax = util.Params.getDouble(pdDealDelayRange, 1); pd.acceptableDeliverUnits = uniform(util.Params.getDouble(pdAcceptableDeliverUnitsRange, 0), util.Params.getDouble(pdAcceptableDeliverUnitsRange, 1)); pd.probDeliverHome = uniform(util.Params.getDouble(pdProbDeliverHomeRange, 0), util.Params.getDouble(pdProbDeliverHomeRange, 1)); pd.probDeliverMarket = uniform(util.Params.getDouble(pdProbDeliverMarketRange, 0), util.Params.getDouble(pdProbDeliverMarketRange, 1)); pd.invitationDeals = uniform_discr(util.Params.getInt(pdInvitationDealsRange, 0), util.Params.getInt(pdInvitationDealsRange, 1)); setup_privateDealer(pd, privateDealer.size()); } //------------------------------------------------------------------------- // Initialize police. for (int i = 0; i < numInitialPolice; i++) { Police po = new Police(); po.initialMarket = market.random(); po.type = Police.TYPE_REGULAR; setup_police(po, police.size()); } if (poUseBusts) { for (int i = 0; i < market.size(); i++) { // Create the reserve police officers for this market. for (int j = 0; j < poBustOfficers; j++) { Police po = new Police(); po.initialMarket = market.item(i); po.type = Police.TYPE_RESERVE; setup_police(po, police.size()); } // Create the bust timer for this market. MarketBustTimer timer = new MarketBustTimer(); timer.market = market.item(i); setup_marketBustTimers(timer, marketBustTimers.size()); } } //------------------------------------------------------------------------- // Initialize homeless. for (int i = 0; i < numInitialHomeless; i++) { Homeless hm = new Homeless(); hm.initialMarket = market.random(); setup_homeless(hm, homeless.size()); } |
| Name | initializeNetworks |
| Type | void |
| Body | //------------------------------------------------------------------------- // Set up each customer's list of known markets. // TODO: Select an algorithm for assigning known markets. // For now, assign all markets. for (int i = 0; i < customer.size(); i++) { Customer cs = customer.item(i); for (int j = 0; j < market.size(); j++) { cs.marketHistories.add(market.item(j)); } } //------------------------------------------------------------------------- // Set up each customer's list of known private dealers and vice-versa. // TODO: Select an algorithm for assigning known private dealers. // For now, assign one private dealer to any customer who // knows a private dealer. for (int i = 0; i < customer.size(); i++) { Customer cs = customer.item(i); if (randomTrue(csProbKnowPrivateDealer)) { PrivateDealer pd = privateDealer.random(); cs.privateDealerHistories.add(pd); pd.customerHistories.add(cs); } } //------------------------------------------------------------------------- // Set up each street broker's list of known street dealers. // TODO: Select an algorithm for assigning known street dealers. // For now, assign all street dealers in the market. for (int i = 0; i < streetBroker.size(); i++) { StreetBroker sb = streetBroker.item(i); for (int j = 0; j < streetDealer.size(); j++) { StreetDealer sd = streetDealer.item(j); if (sd.group.market == sb.market) { sb.streetDealerHistories.add(sd); } } } //------------------------------------------------------------------------- // Set up each street broker's list of known private dealers. // TODO: Select an algorithm for assigning known private dealers. // For now, assign one private dealer to any street broker // who knows a private dealer. for (int i = 0; i < streetBroker.size(); i++) { StreetBroker sb = streetBroker.item(i); if (randomTrue(sbProbKnowPrivateDealer)) { PrivateDealer pd = privateDealer.random(); sb.privateDealerHistories.add(pd); } } |
| Name | initializeParameters |
| Type | void |
| Body | // Make any necessary adjustments to the user-defined parameters. //--------------------------------------------------------------------- // Allow only one replication if the animation is enabled. if (Engine.getAnimation() != null) { numReplications = 1; } //--------------------------------------------------------------------- // Make sure numInitialMarkets is set to 1. // // To support more than one market, we must either support multiple // streetDealerGroups or we must allow the dealers in a single // streetDealerGroup to split up across multiple markets. if (numInitialMarkets != 1) { traceln("***NOTE: Setting numInitialMarkets=1 because other values are currently unsupported."); numInitialMarkets = 1; } //--------------------------------------------------------------------- // Make sure csAcceptableSbQueueLength is set to 0. // // To support street broker queues, we must either make the street broker // travel to the customer's location before seeking a street dealer, or // we must have the street broker accept the customer's money as soon as // he receives the deal request. if (csAcceptableSbQueueLength != 0) { traceln("***NOTE: Setting csAcceptableSbQueueLength=0 because other values are currently unsupported."); csAcceptableSbQueueLength = 0; } //--------------------------------------------------------------------- // Some parameters are specified in particular time or distance // units. Modify them so that they are all expressed in consistent // units. // // We must be careful with this since we are overwriting the existing // parameter values. If we try to use a parameter before this function // is executed, then the value that gets used will be the original value // instead of the modified value. Therefore, we must make sure that all // references to these parameters come after the call to this function. // This includes some of the things that AnyLogic does automatically, // like the initial values of variable objects, the expiration times // of timers, and parameter values that get passed to encapsulated // objects. replicationRunTime = util.Units.days(replicationRunTime); cityHeight = util.Units.miles(cityHeight); cityWidth = util.Units.miles(cityWidth); marketSizeRange = util.Units.miles(util.Params.getDouble(marketSizeRange, 0)) + "," + util.Units.miles(util.Params.getDouble(marketSizeRange, 1)); walkingSpeed = util.Units.milesPerHour(walkingSpeed); drivingSpeed = util.Units.milesPerHour(drivingSpeed); visionRadiusRange = util.Units.feet(util.Params.getDouble(visionRadiusRange, 0)) + "," + util.Units.feet(util.Params.getDouble(visionRadiusRange, 1)); outfileSummaryInterval = util.Units.hours(outfileSummaryInterval); outfileCustomerInterval = util.Units.hours(outfileCustomerInterval); outfileStreetBrokerInterval = util.Units.hours(outfileStreetBrokerInterval); metabolismRateRange = util.Params.getDouble(metabolismRateRange, 0) / util.Units.minutes(1) + "," + util.Params.getDouble(metabolismRateRange, 1) / util.Units.minutes(1); addictionIncreaseDurationRange = util.Units.hours(util.Params.getDouble(addictionIncreaseDurationRange, 0)) + "," + util.Units.hours(util.Params.getDouble(addictionIncreaseDurationRange, 1)); addictionIncreaseRateRange = util.Params.getDouble(addictionIncreaseRateRange, 0) / util.Units.minutes(1) + "," + util.Params.getDouble(addictionIncreaseRateRange, 1) / util.Units.minutes(1); addictionDecreaseOnsetRange = util.Units.hours(util.Params.getDouble(addictionDecreaseOnsetRange, 0)) + "," + util.Units.hours(util.Params.getDouble(addictionDecreaseOnsetRange, 1)); addictionDecreaseRateRange = util.Params.getDouble(addictionDecreaseRateRange, 0) / util.Units.minutes(1) + "," + util.Params.getDouble(addictionDecreaseRateRange, 1) / util.Units.minutes(1); useDelayRange = util.Units.minutes(util.Params.getDouble(useDelayRange, 0)) + "," + util.Units.minutes(util.Params.getDouble(useDelayRange, 1)); treatmentDelayRange = util.Units.days(util.Params.getDouble(treatmentDelayRange, 0)) + "," + util.Units.days(util.Params.getDouble(treatmentDelayRange, 1)); csInitialTimeSinceLastUseDistrParams = util.Units.hours(util.Params.getDouble(csInitialTimeSinceLastUseDistrParams, 0)) + "," + util.Units.hours(util.Params.getDouble(csInitialTimeSinceLastUseDistrParams, 1)); csWindfallIntervalRange = util.Units.days(util.Params.getDouble(csWindfallIntervalRange, 0)) + "," + util.Units.days(util.Params.getDouble(csWindfallIntervalRange, 1)); csRandomUseIntervalRange = util.Units.days(util.Params.getDouble(csRandomUseIntervalRange, 0)) + "," + util.Units.days(util.Params.getDouble(csRandomUseIntervalRange, 1)); csDealQuitTime = util.Units.hours(csDealQuitTime); csMarketQuitTimeRange = util.Units.hours(util.Params.getDouble(csMarketQuitTimeRange, 0)) + "," + util.Units.hours(util.Params.getDouble(csMarketQuitTimeRange, 1)); csSeekMoneyDelayRange = util.Units.minutes(util.Params.getDouble(csSeekMoneyDelayRange, 0)) + "," + util.Units.minutes(util.Params.getDouble(csSeekMoneyDelayRange, 1)); csRetryDelayRange = util.Units.minutes(util.Params.getDouble(csRetryDelayRange, 0)) + "," + util.Units.minutes(util.Params.getDouble(csRetryDelayRange, 1)); sbInitialTimeSinceLastUseDistrParams = util.Units.hours(util.Params.getDouble(sbInitialTimeSinceLastUseDistrParams, 0)) + "," + util.Units.hours(util.Params.getDouble(sbInitialTimeSinceLastUseDistrParams, 1)); sbDealQuitTime = util.Units.hours(sbDealQuitTime); sbMarketQuitTimeRange = util.Units.hours(util.Params.getDouble(sbMarketQuitTimeRange, 0)) + "," + util.Units.hours(util.Params.getDouble(sbMarketQuitTimeRange, 1)); sdDealDelayRange = util.Units.minutes(util.Params.getDouble(sdDealDelayRange, 0)) + "," + util.Units.minutes(util.Params.getDouble(sdDealDelayRange, 1)); pdShiftLengthRange = util.Units.hours(util.Params.getDouble(pdShiftLengthRange, 0)) + "," + util.Units.hours(util.Params.getDouble(pdShiftLengthRange, 1)); pdDealQuitTime = util.Units.hours(pdDealQuitTime); pdDealDelayRange = util.Units.minutes(util.Params.getDouble(pdDealDelayRange, 0)) + "," + util.Units.minutes(util.Params.getDouble(pdDealDelayRange, 1)); poVisionRadius = util.Units.feet(poVisionRadius); poHarassDuration = util.Units.minutes(poHarassDuration); poHarassRepeatDelay = util.Units.hours(poHarassRepeatDelay); poArrestDuration = util.Units.minutes(poArrestDuration); poJailPerDrugUnit = util.Units.days(poJailPerDrugUnit); StringBuffer new_poBustStartTimes = new StringBuffer(); for (int i = 0; i < util.Params.count(poBustStartTimes); i++) { if (i > 0) { new_poBustStartTimes.append(","); } new_poBustStartTimes.append(util.Units.days(util.Params.getDouble(poBustStartTimes, i))); } poBustStartTimes = new_poBustStartTimes.toString(); poBustDuration = util.Units.hours(poBustDuration); poBustVisionRadius = util.Units.feet(poBustVisionRadius); //--------------------------------------------------------------------- // If outfiles are being created and the replication end time is // a multiple of the write interval, then the replication will end // before the last expected write to the outfile. Therefore we will // lengthen the replication run time slightly to allow the final // write to the outfile. if ( (outfileSummaryCreate && replicationRunTime % outfileSummaryInterval == 0) || (outfileCustomerCreate && replicationRunTime % outfileCustomerInterval == 0) || (outfileStreetBrokerCreate && replicationRunTime % outfileStreetBrokerInterval == 0) ) { replicationRunTime += 1; } |
| Name | startTimers |
| Type | void |
| Body | // The replication end timer will expire once at the end of the // replication. replicationRunTimer.restart(replicationRunTime); // The timers for writing the outfiles should be set to expire at // model startup. Each will handle restarting itself at the // appropriate times. outfileSummaryTimer.restart(0); outfileCustomerTimer.restart(0); outfileStreetBrokerTimer.restart(0); // The timers for starting market busts should be started just // once. After that, they will handle restarting themselves at // the appropriate times. if (poUseBusts) { for (int i = 0; i < marketBustTimers.size(); i++) { marketBustTimers.item(i).scheduleNextBust(); } } |
| Animation | |
| Name | animation |
| Setup code | setScale(animationScaleFactor); // Enable anti-aliasing by default. For some reason this causes a // NullPointerException in interactive mode but not in applet mode, // so execute it only for applet mode. if (util.Model.getRunMode().equals("applet")) { Engine.getAnimation().setAntiAliasingEnabled(true); } |
| Update code | // On every animation update, AnyLogic updates all the animation elements defined // in the animation GUI and then runs the code in this section. Animation updates // may happen many times during a single model time step, and we can also force // an update using the update() method. // // We want to run certain pieces of code on every update, such as code that sets // the visibility of objects. We want to run other pieces of code less frequently, // though. An example of this is code that adds a point to a plot, which we may // want to run on every time step or every N time steps. To deal with these timing // issues, we place code that should be run at a specified time interval inside a // condition that allows the code to be run only when the time interval boundaries // are crossed. // // Further complicating this section, we must perform some initialization // activities here. We do this here instead of in the "Setup code" section because // our initialization requires access to members of the replicated objects in Main. // Those objects are not yet created when the "Setup code" is executed, but they // have been created by the time the "Update code" is first executed. We place other // initialization activities here, even though it's not necessary, to keep all the // initialization code together. // // An important consideration is that the initialization code itself might trigger // another animation update. If we don't account for this, we will cause an infinite // loop at time 0 where the initialization code triggers an update, which runs the // the initialization code again, which triggers another update, etc. To handle this, // we use a flag variable to indicate whether we've already run the initialization // code, and we check this flag variable before running the initialization code again. // // Another important consideration is that the initialization code may perform some // setup activities that are dependencies for "normal" update code. Therefore, we // create another flag variable to indicate when the initialization code is complete, // and then we check this flag variable before runing the normal update code. if (Engine.getTime() == 0 && !hasInitializationStarted) { hasInitializationStarted = true; disableAppletButtons(); initializeAgentColors(); initializeAgentNames(); initializeAgentSelection(); initializeOptionBoxes(); initializePlots(); for (int i = 0; i < NUM_AGENTS; i++) { selectAgent(i, selectedAgents[i]); } setPov(AGENT_CUSTOMER); setZoomLevel(ZOOM_CITY); isInitializationComplete = true; } if (isInitializationComplete) { if ((int)(Engine.getTime() / plotUpdateInterval) > (int)(prevUpdateTime / plotUpdateInterval)) { addPointToPlots(); } setOptionBoxVisibility(); setPlotVisibility(); prevUpdateTime = Engine.getTime(); } |
| Additional class code | private boolean hasInitializationStarted = false; private boolean isInitializationComplete = false; private double prevUpdateTime = -1; //--------------------------------------------------------------------- // Set positions and sizes. // public double distanceToPixels(double distance) { double pixelsPerDistanceUnit; if (zoomLevel == ZOOM_CITY) { pixelsPerDistanceUnit = min(cityRectangle.getWidth(), cityRectangle.getHeight()) / max(cityWidth, cityHeight); } else { Market mk = market.item(selectedAgents[AGENT_MARKET]); pixelsPerDistanceUnit = min(cityRectangle.getWidth() - 2*zoomBuffer, cityRectangle.getHeight() - 2*zoomBuffer) / max(mk.width, mk.height); } return pixelsPerDistanceUnit * distance; } // We make the following assumption throughout this model: // private double cityX = 0; // private double cityY = 0; // However, we do not want to use these variables in all our calculations, // so we will not let them be changed. private double optionBoxY = -30; private double optionBoxHeight = 20; private double filterBoxX = 440; private double filterBoxWidth = 135; private double statBoxX = filterBoxX + filterBoxWidth + optionBoxHeight + 10; private double statBoxWidth = 135; private double statsX = 450; private double statsY = 10; private double plotsX = 490; private double plotsY = 230; private double plotsWidth = 300; private double plotsHeight = 150; //--------------------------------------------------------------------- // Set colors. // private Color titleColor = new Color(140, 161, 175); private Color outlineColor = new Color(85, 104, 117); private Color subtitleColor = new Color(209, 217, 223); private Color inPovButtonColor = new Color(255, 204, 153); private Color outPovButtonColor = Color.lightGray; private Color[] agentFillColors = new Color[NUM_AGENTS]; private Color[] agentLineColors = new Color[NUM_AGENTS]; private Color[] selectedAgentFillColors = new Color[NUM_AGENTS]; private Color[] selectedAgentLineColors = new Color[NUM_AGENTS]; private void initializeAgentColors() { agentFillColors[AGENT_CUSTOMER] = Color.darkGray; agentFillColors[AGENT_STREET_BROKER] = new Color(153, 204, 0); agentFillColors[AGENT_STREET_DEALER] = new Color(255, 153, 0); agentFillColors[AGENT_PRIVATE_DEALER] = new Color(204, 153, 255); agentFillColors[AGENT_HOMELESS] = Color.lightGray; agentFillColors[AGENT_POLICE] = new Color(0, 85, 255); agentFillColors[AGENT_MARKET] = null; agentLineColors[AGENT_CUSTOMER] = Color.darkGray; agentLineColors[AGENT_STREET_BROKER] = new Color(153, 204, 0); agentLineColors[AGENT_STREET_DEALER] = new Color(255, 153, 0); agentLineColors[AGENT_PRIVATE_DEALER] = new Color(204, 153, 255); agentLineColors[AGENT_HOMELESS] = Color.lightGray; agentLineColors[AGENT_POLICE] = new Color(0, 85, 255); agentLineColors[AGENT_MARKET] = Color.black; selectedAgentFillColors[AGENT_CUSTOMER] = Color.red; selectedAgentFillColors[AGENT_STREET_BROKER] = Color.red; selectedAgentFillColors[AGENT_STREET_DEALER] = Color.red; selectedAgentFillColors[AGENT_PRIVATE_DEALER] = Color.red; selectedAgentFillColors[AGENT_HOMELESS] = Color.red; selectedAgentFillColors[AGENT_POLICE] = Color.red; selectedAgentFillColors[AGENT_MARKET] = null; selectedAgentLineColors[AGENT_CUSTOMER] = Color.darkGray; selectedAgentLineColors[AGENT_STREET_BROKER] = new Color(153, 204, 0); selectedAgentLineColors[AGENT_STREET_DEALER] = new Color(255, 153, 0); selectedAgentLineColors[AGENT_PRIVATE_DEALER] = new Color(204, 153, 255); selectedAgentLineColors[AGENT_HOMELESS] = Color.lightGray; selectedAgentLineColors[AGENT_POLICE] = new Color(0, 85, 255); selectedAgentLineColors[AGENT_MARKET] = Color.red; } //--------------------------------------------------------------------- // Functions to determine the current agent attributes. // public double getAgentLocationX(int agent, boolean isSelected, double locCity) { double distance; double originOffset; if (zoomLevel == ZOOM_CITY) { distance = locCity; originOffset = 0; } else { Market mk = market.item(selectedAgents[AGENT_MARKET]); distance = mk.getLocationInMarketX(locCity); originOffset = zoomBuffer; } return originOffset + distanceToPixels(distance) - getAgentSize(agent, isSelected) / 2; } public double getAgentLocationY(int agent, boolean isSelected, double locCity) { double distance; double originOffset; if (zoomLevel == ZOOM_CITY) { distance = locCity; originOffset = 0; } else { Market mk = market.item(selectedAgents[AGENT_MARKET]); distance = mk.getLocationInMarketY(locCity); originOffset = zoomBuffer; } return originOffset + distanceToPixels(distance) - getAgentSize(agent, isSelected) / 2; } public double getAgentSize(int agent, boolean isSelected) { if (agent == AGENT_MARKET) { // this does not apply to markets return 0; } else { // all agents are the same size for now return isSelected && agentPov == agent ? 8 : 4; } } public Color getAgentFillColor(int agent, boolean isSelected) { if (agent >= 0 && agent < NUM_AGENTS) { if (isSelected && agentPov == agent) { return selectedAgentFillColors[agent]; } else { return agentFillColors[agent]; } } else { traceln("***ERROR in Main.animation.getAgentFillColor: Unexpected agent type: " + agent + " @ " + Engine.getTime()); return null; } } public Color getAgentLineColor(int agent, boolean isSelected) { if (agent >= 0 && agent < NUM_AGENTS) { if (isSelected && agentPov == agent) { return selectedAgentLineColors[agent]; } else { return agentLineColors[agent]; } } else { traceln("***ERROR in Main.animation.getAgentLineColor: Unexpected agent type: " + agent + " @ " + Engine.getTime()); return null; } } public double getAgentLineWidth(int agent, boolean isSelected) { // all agents have the same line width for now return isSelected && agentPov == agent ? 2 : 1; } public boolean getAgentVisibility(int agent, boolean isSelected, double x, double y) { if (zoomLevel == ZOOM_CITY) { return true; } else { return cityRectangle.contains( getAgentLocationX(agent, isSelected, x), getAgentLocationY(agent, isSelected, y) ); } } //--------------------------------------------------------------------- // Handle the selection of agent point-of-view. // private int agentPov; private String[] agentNames = new String[NUM_AGENTS]; private String[] agentNamesPlural = new String[NUM_AGENTS]; private void initializeAgentNames() { agentNames[AGENT_CUSTOMER] = "Customer"; agentNames[AGENT_STREET_BROKER] = "Street Broker"; agentNames[AGENT_STREET_DEALER] = "Street Dealer"; agentNames[AGENT_PRIVATE_DEALER] = "Private Dealer"; agentNames[AGENT_HOMELESS] = "Homeless"; agentNames[AGENT_POLICE] = "Police"; agentNames[AGENT_MARKET] = "Market"; agentNamesPlural[AGENT_CUSTOMER] = "Customers"; agentNamesPlural[AGENT_STREET_BROKER] = "Street Brokers"; agentNamesPlural[AGENT_STREET_DEALER] = "Street Dealers"; agentNamesPlural[AGENT_PRIVATE_DEALER] = "Private Dealers"; agentNamesPlural[AGENT_HOMELESS] = "Homeless"; agentNamesPlural[AGENT_POLICE] = "Police"; agentNamesPlural[AGENT_MARKET] = "Markets"; } private void setPov(int agent) { if (agent >= 0 && agent < NUM_AGENTS) { agentPov = agent; selectAgent(agentPov, selectedAgents[agentPov]); filterBox.setItemText(0, "All " + agentNamesPlural[agentPov]); filterBox.setItemText(1, "Selected " + agentNames[agentPov]); } } //--------------------------------------------------------------------- // Handle the selection of specific agents. // private int[] selectedAgents = new int[NUM_AGENTS]; private ReplicatedObject[] agentLists = new ReplicatedObject[NUM_AGENTS]; private void initializeAgentSelection() { selectedAgents[AGENT_CUSTOMER] = 0; selectedAgents[AGENT_STREET_BROKER] = 0; selectedAgents[AGENT_STREET_DEALER] = 0; selectedAgents[AGENT_PRIVATE_DEALER] = 0; selectedAgents[AGENT_HOMELESS] = 0; selectedAgents[AGENT_POLICE] = 0; selectedAgents[AGENT_MARKET] = 0; agentLists[AGENT_CUSTOMER] = customer; agentLists[AGENT_STREET_BROKER] = streetBroker; agentLists[AGENT_STREET_DEALER] = streetDealer; agentLists[AGENT_PRIVATE_DEALER] = privateDealer; agentLists[AGENT_HOMELESS] = homeless; agentLists[AGENT_POLICE] = police; agentLists[AGENT_MARKET] = market; } private void selectAgent(int agent, int id) { // If the agent type is not valid, then do nothing. if (agent < 0 || agent >= NUM_AGENTS) { return; } // If the requested id is out of range, then do nothing. if (id < 0 || id >= agentLists[agent].size()) { return; } // Update the isSelected indicator for the old and new selected agents. // Ideally we would use our agentLists array and loop over the array // instead of using the series of if/else statements. However, agentLists // is too generic for our needs. We need access to the animation.isSelected // field, and we cannot get it from the ReplicatedObjects in agentLists. if (agent == AGENT_CUSTOMER) { customer.item(selectedAgents[agent]).animation.isSelected = false; customer.item(id).animation.isSelected = true; } else if (agent == AGENT_STREET_BROKER) { streetBroker.item(selectedAgents[agent]).animation.isSelected = false; streetBroker.item(id).animation.isSelected = true; } else if (agent == AGENT_STREET_DEALER) { streetDealer.item(selectedAgents[agent]).animation.isSelected = false; streetDealer.item(id).animation.isSelected = true; } else if (agent == AGENT_PRIVATE_DEALER) { privateDealer.item(selectedAgents[agent]).animation.isSelected = false; privateDealer.item(id).animation.isSelected = true; } else if (agent == AGENT_HOMELESS) { homeless.item(selectedAgents[agent]).animation.isSelected = false; homeless.item(id).animation.isSelected = true; } else if (agent == AGENT_POLICE) { police.item(selectedAgents[agent]).animation.isSelected = false; police.item(id).animation.isSelected = true; } else if (agent == AGENT_MARKET) { market.item(selectedAgents[agent]).animation.isSelected = false; market.item(id).animation.isSelected = true; } else { traceln("***ERROR in Main.animation.selectAgent: Unexpected agent type: " + agent + " @ " + Engine.getTime()); } // If the requested agent type has the current POV, update the text box. if (agentPov == agent) { selectedAgentEdit.setValue(id); } // Update our array that tracks the currently selected agents. selectedAgents[agent] = id; // Force an animation update. update(); } //--------------------------------------------------------------------- // Handle zooming in and out of the selected market. // private double zoomBuffer = 10; private int zoomLevel; private final int ZOOM_CITY = 0; private final int ZOOM_MARKET = 1; private void setZoomLevel(int level) { zoomLevel = level; zoomLevelCheckbox.setValue(zoomLevel == ZOOM_MARKET); } //--------------------------------------------------------------------- // Create option boxes. // private OptionBox filterBox; private OptionItem filterBoxAllItem; private OptionItem filterBoxSelectedItem; private int optionFilter; private final int FILTER_ALL = 0; private final int FILTER_SELECTED = 1; // customers private OptionBox csAllStatBox; private int optionCsAllStat; private final int STAT_CS_ALL_TRANSACTIONS_GOOD = 0; private final int STAT_CS_ALL_TRANSACTIONS_COST = 1; private final int STAT_CS_ALL_MODEL_STATUS = 2; private OptionBox csSelectedStatBox; private int optionCsSelectedStat; private final int STAT_CS_SELECTED_ALL = 0; // street brokers private OptionBox sbAllStatBox; private int optionSbAllStat; private final int STAT_SB_ALL_TRANSACTIONS_GOOD = 0; private final int STAT_SB_ALL_MODEL_STATUS = 1; private OptionBox sbSelectedStatBox; private int optionSbSelectedStat; private final int STAT_SB_SELECTED_ALL = 0; // street dealers private OptionBox sdAllStatBox; private int optionSdAllStat; private final int STAT_SD_ALL_MODEL_STATUS = 0; private OptionBox sdSelectedStatBox; private int optionSdSelectedStat; private final int STAT_SD_SELECTED_ALL = 0; // private dealers private OptionBox pdAllStatBox; private int optionPdAllStat; private final int STAT_PD_ALL_MODEL_STATUS = 0; private OptionBox pdSelectedStatBox; private int optionPdSelectedStat; private final int STAT_PD_SELECTED_ALL = 0; // police private OptionBox poAllStatBox; private int optionPoAllStat; private final int STAT_PO_ALL_NUMBER_ACTIVE = 0; private final int STAT_PO_ALL_HARASSMENTS = 1; private OptionBox poSelectedStatBox; private int optionPoSelectedStat; private final int STAT_PO_SELECTED_ALL = 0; // markets private OptionBox mkAllStatBox; private int optionMkAllStat; private final int STAT_MK_ALL_NONE = 0; private OptionBox mkSelectedStatBox; private int optionMkSelectedStat; private final int STAT_MK_SELECTED_NONE = 0; private void initializeOptionBoxes() { filterBox = new OptionBox(this); filterBox.addOptionItem( new OptionItem("All") { public void onSelect() { optionFilter = FILTER_ALL; update(); } } ); filterBox.addOptionItem( new OptionItem("Selected") { public void onSelect() { optionFilter = FILTER_SELECTED; update(); } } ); filterBox.setPos(filterBoxX, optionBoxY); filterBox.setItemWidth(filterBoxWidth); filterBox.setItemHeight(optionBoxHeight); filterBox.setSelectedItem("All"); filterBox.setVisible(true); csAllStatBox = new OptionBox(this); csAllStatBox.addOptionItem( new OptionItem("Completed transactions") { public void onSelect() { optionCsAllStat = STAT_CS_ALL_TRANSACTIONS_GOOD; update(); } } ); csAllStatBox.addOptionItem( new OptionItem("Transaction cost") { public void onSelect() { optionCsAllStat = STAT_CS_ALL_TRANSACTIONS_COST; update(); } } ); csAllStatBox.addOptionItem( new OptionItem("Model Status") { public void onSelect() { optionCsAllStat = STAT_CS_ALL_MODEL_STATUS; update(); } } ); csAllStatBox.setPos(statBoxX, optionBoxY); csAllStatBox.setItemWidth(statBoxWidth); csAllStatBox.setItemHeight(optionBoxHeight); csAllStatBox.setSelectedItem("Completed transactions"); csAllStatBox.setVisible(false); csSelectedStatBox = new OptionBox(this); csSelectedStatBox.addOptionItem( new OptionItem("All stats") { public void onSelect() { optionCsSelectedStat = STAT_CS_SELECTED_ALL; update(); } } ); csSelectedStatBox.setPos(statBoxX, optionBoxY); csSelectedStatBox.setItemWidth(statBoxWidth); csSelectedStatBox.setItemHeight(optionBoxHeight); csSelectedStatBox.setSelectedItem("All stats"); csSelectedStatBox.setVisible(false); sbAllStatBox = new OptionBox(this); sbAllStatBox.addOptionItem( new OptionItem("Completed transactions") { public void onSelect() { optionSbAllStat = STAT_SB_ALL_TRANSACTIONS_GOOD; update(); } } ); sbAllStatBox.addOptionItem( new OptionItem("Model Status") { public void onSelect() { optionSbAllStat = STAT_SB_ALL_MODEL_STATUS; update(); } } ); sbAllStatBox.setPos(statBoxX, optionBoxY); sbAllStatBox.setItemWidth(statBoxWidth); sbAllStatBox.setItemHeight(optionBoxHeight); sbAllStatBox.setSelectedItem("Completed transactions"); sbAllStatBox.setVisible(false); sbSelectedStatBox = new OptionBox(this); sbSelectedStatBox.addOptionItem( new OptionItem("All stats") { public void onSelect() { optionSbSelectedStat = STAT_SB_SELECTED_ALL; update(); } } ); sbSelectedStatBox.setPos(statBoxX, optionBoxY); sbSelectedStatBox.setItemWidth(statBoxWidth); sbSelectedStatBox.setItemHeight(optionBoxHeight); sbSelectedStatBox.setSelectedItem("All stats"); sbSelectedStatBox.setVisible(false); sdAllStatBox = new OptionBox(this); sdAllStatBox.addOptionItem( new OptionItem("Model Status") { public void onSelect() { optionSdAllStat = STAT_SD_ALL_MODEL_STATUS; update(); } } ); sdAllStatBox.setPos(statBoxX, optionBoxY); sdAllStatBox.setItemWidth(statBoxWidth); sdAllStatBox.setItemHeight(optionBoxHeight); sdAllStatBox.setSelectedItem("Model Status"); sdAllStatBox.setVisible(false); sdSelectedStatBox = new OptionBox(this); sdSelectedStatBox.addOptionItem( new OptionItem("All stats") { public void onSelect() { optionSdSelectedStat = STAT_SD_SELECTED_ALL; update(); } } ); sdSelectedStatBox.setPos(statBoxX, optionBoxY); sdSelectedStatBox.setItemWidth(statBoxWidth); sdSelectedStatBox.setItemHeight(optionBoxHeight); sdSelectedStatBox.setSelectedItem("All stats"); sdSelectedStatBox.setVisible(false); pdAllStatBox = new OptionBox(this); pdAllStatBox.addOptionItem( new OptionItem("Model Status") { public void onSelect() { optionPdAllStat = STAT_PD_ALL_MODEL_STATUS; update(); } } ); pdAllStatBox.setPos(statBoxX, optionBoxY); pdAllStatBox.setItemWidth(statBoxWidth); pdAllStatBox.setItemHeight(optionBoxHeight); pdAllStatBox.setSelectedItem("Model Status"); pdAllStatBox.setVisible(false); pdSelectedStatBox = new OptionBox(this); pdSelectedStatBox.addOptionItem( new OptionItem("All stats") { public void onSelect() { optionPdSelectedStat = STAT_PD_SELECTED_ALL; update(); } } ); pdSelectedStatBox.setPos(statBoxX, optionBoxY); pdSelectedStatBox.setItemWidth(statBoxWidth); pdSelectedStatBox.setItemHeight(optionBoxHeight); pdSelectedStatBox.setSelectedItem("All stats"); pdSelectedStatBox.setVisible(false); poAllStatBox = new OptionBox(this); poAllStatBox.addOptionItem( new OptionItem("Harassments and Arrests") { public void onSelect() { optionPoAllStat = STAT_PO_ALL_HARASSMENTS; update(); } } ); poAllStatBox.addOptionItem( new OptionItem("Number Active") { public void onSelect() { optionPoAllStat = STAT_PO_ALL_NUMBER_ACTIVE; update(); } } ); poAllStatBox.setPos(statBoxX, optionBoxY); poAllStatBox.setItemWidth(statBoxWidth); poAllStatBox.setItemHeight(optionBoxHeight); poAllStatBox.setSelectedItem("Harassments and Arrests"); poAllStatBox.setVisible(false); poSelectedStatBox = new OptionBox(this); poSelectedStatBox.addOptionItem(new OptionItem("None available")); poSelectedStatBox.setPos(statBoxX, optionBoxY); poSelectedStatBox.setItemWidth(statBoxWidth); poSelectedStatBox.setItemHeight(optionBoxHeight); poSelectedStatBox.setSelectedItem("None available"); poSelectedStatBox.setVisible(false); mkAllStatBox = new OptionBox(this); mkAllStatBox.addOptionItem(new OptionItem("None available")); mkAllStatBox.setPos(statBoxX, optionBoxY); mkAllStatBox.setItemWidth(statBoxWidth); mkAllStatBox.setItemHeight(optionBoxHeight); mkAllStatBox.setSelectedItem("None available"); mkAllStatBox.setVisible(false); mkSelectedStatBox = new OptionBox(this); mkSelectedStatBox.addOptionItem(new OptionItem("None available")); mkSelectedStatBox.setPos(statBoxX, optionBoxY); mkSelectedStatBox.setItemWidth(statBoxWidth); mkSelectedStatBox.setItemHeight(optionBoxHeight); mkSelectedStatBox.setSelectedItem("None available"); mkSelectedStatBox.setVisible(false); } private void setOptionBoxVisibility() { csAllStatBox.setVisible(agentPov == AGENT_CUSTOMER && optionFilter == FILTER_ALL); csSelectedStatBox.setVisible(agentPov == AGENT_CUSTOMER && optionFilter == FILTER_SELECTED); sbAllStatBox.setVisible(agentPov == AGENT_STREET_BROKER && optionFilter == FILTER_ALL); sbSelectedStatBox.setVisible(agentPov == AGENT_STREET_BROKER && optionFilter == FILTER_SELECTED); sdAllStatBox.setVisible(agentPov == AGENT_STREET_DEALER && optionFilter == FILTER_ALL); sdSelectedStatBox.setVisible(agentPov == AGENT_STREET_DEALER && optionFilter == FILTER_SELECTED); pdAllStatBox.setVisible(agentPov == AGENT_PRIVATE_DEALER && optionFilter == FILTER_ALL); pdSelectedStatBox.setVisible(agentPov == AGENT_PRIVATE_DEALER && optionFilter == FILTER_SELECTED); poAllStatBox.setVisible(agentPov == AGENT_POLICE && optionFilter == FILTER_ALL); poSelectedStatBox.setVisible(agentPov == AGENT_POLICE && optionFilter == FILTER_SELECTED); mkAllStatBox.setVisible(agentPov == AGENT_MARKET && optionFilter == FILTER_ALL); mkSelectedStatBox.setVisible(agentPov == AGENT_MARKET && optionFilter == FILTER_SELECTED); } //--------------------------------------------------------------------- // Create plots. // private double plotUpdateInterval = util.Units.hours(1); private SeriesPlot csTransactionsNumGoodPlot; private SeriesPlot csTransactionsCostPlot; private SeriesPlot csModelStatusPlot; private SeriesPlot sbTransactionsNumGoodPlot; private SeriesPlot sbModelStatusPlot; private SeriesPlot sdModelStatusPlot; private SeriesPlot pdModelStatusPlot; private SeriesPlot poNumberActivePlot; private SeriesPlot poHarassmentsPlot; private void initializePlots() { csTransactionsNumGoodPlot = new SeriesPlot(this, 4); csTransactionsCostPlot = new SeriesPlot(this, 4); csModelStatusPlot = new SeriesPlot(this, 3); sbTransactionsNumGoodPlot = new SeriesPlot(this, 3); sbModelStatusPlot = new SeriesPlot(this, 2); sdModelStatusPlot = new SeriesPlot(this, 2); pdModelStatusPlot = new SeriesPlot(this, 2); poNumberActivePlot = new SeriesPlot(this, 1); poHarassmentsPlot = new SeriesPlot(this, 2); SeriesPlot[] allPlots = { csTransactionsNumGoodPlot , csTransactionsCostPlot , csModelStatusPlot , sbTransactionsNumGoodPlot , sbModelStatusPlot , sdModelStatusPlot , pdModelStatusPlot , poNumberActivePlot , poHarassmentsPlot }; for (int i = 0; i < allPlots.length; i++) { allPlots[i].setPos(plotsX, plotsY); allPlots[i].setWidth(plotsWidth); allPlots[i].setXaxisValueMax(min(10, util.Clock.getDay(replicationRunTime))); allPlots[i].setXaxisTickLabelFormat(new DecimalFormat("0")); allPlots[i].setXaxisTitle("model time (days)"); allPlots[i].setXaxisTitleVisible(true); allPlots[i].setHeight(plotsHeight); allPlots[i].setYaxisTickLabelRotation(90); allPlots[i].setYaxisTitleRotation(90); allPlots[i].setYaxisTitleVisible(true); allPlots[i].setLegendVisible(true); allPlots[i].setLegendContainsValues(true); allPlots[i].setPlotTitleVisible(true); } csTransactionsNumGoodPlot.setYaxisValueMax(200); csTransactionsNumGoodPlot.setYaxisTickLabelFormat(new DecimalFormat("0")); csTransactionsNumGoodPlot.setYaxisTitle("# transactions"); csTransactionsNumGoodPlot.setSeriesName(0, "Total"); csTransactionsNumGoodPlot.setSeriesName(1, "From street brokers"); csTransactionsNumGoodPlot.setSeriesName(2, "From street dealers"); csTransactionsNumGoodPlot.setSeriesName(3, "From private dealers"); csTransactionsNumGoodPlot.setSeriesColor(0, getAgentFillColor(AGENT_CUSTOMER, false)); csTransactionsNumGoodPlot.setSeriesColor(1, getAgentFillColor(AGENT_STREET_BROKER, false)); csTransactionsNumGoodPlot.setSeriesColor(2, getAgentFillColor(AGENT_STREET_DEALER, false)); csTransactionsNumGoodPlot.setSeriesColor(3, getAgentFillColor(AGENT_PRIVATE_DEALER, false)); csTransactionsNumGoodPlot.setLegendValuesFormat(new DecimalFormat("0")); csTransactionsNumGoodPlot.setPlotTitle("Completed Customer Transactions, by Seller"); csTransactionsCostPlot.setYaxisValueMax(5000); csTransactionsCostPlot.setYaxisTickLabelFormat(new DecimalFormat("0")); csTransactionsCostPlot.setYaxisTitle("cost ($)"); csTransactionsCostPlot.setSeriesName(0, "Total"); csTransactionsCostPlot.setSeriesName(1, "From street brokers"); csTransactionsCostPlot.setSeriesName(2, "From street dealers"); csTransactionsCostPlot.setSeriesName(3, "From private dealers"); csTransactionsCostPlot.setSeriesColor(0, getAgentFillColor(AGENT_CUSTOMER, false)); csTransactionsCostPlot.setSeriesColor(1, getAgentFillColor(AGENT_STREET_BROKER, false)); csTransactionsCostPlot.setSeriesColor(2, getAgentFillColor(AGENT_STREET_DEALER, false)); csTransactionsCostPlot.setSeriesColor(3, getAgentFillColor(AGENT_PRIVATE_DEALER, false)); csTransactionsCostPlot.setLegendValuesFormat(new DecimalFormat("$#,##0")); csTransactionsCostPlot.setPlotTitle("Customer Cost for Transactions, by Seller"); csModelStatusPlot.setYaxisValueMax(100); csModelStatusPlot.setYaxisTickLabelFormat(new DecimalFormat("0")); csModelStatusPlot.setYaxisTitle("percent"); csModelStatusPlot.setSeriesName(0, "Active"); csModelStatusPlot.setSeriesName(1, "Treatment"); csModelStatusPlot.setSeriesName(2, "Arrested"); csModelStatusPlot.setSeriesColor(0, getAgentFillColor(AGENT_CUSTOMER, false)); csModelStatusPlot.setSeriesColor(1, Color.orange); csModelStatusPlot.setSeriesColor(2, getAgentFillColor(AGENT_POLICE, false)); csModelStatusPlot.setLegendValuesFormat(new DecimalFormat("0.0'%'")); csModelStatusPlot.setPlotTitle("Customer Distribution by Model Status"); sbTransactionsNumGoodPlot.setYaxisValueMax(200); sbTransactionsNumGoodPlot.setYaxisTickLabelFormat(new DecimalFormat("0")); sbTransactionsNumGoodPlot.setYaxisTitle("# transactions"); sbTransactionsNumGoodPlot.setSeriesName(0, "Total"); sbTransactionsNumGoodPlot.setSeriesName(1, "From street dealers"); sbTransactionsNumGoodPlot.setSeriesName(2, "From private dealers"); sbTransactionsNumGoodPlot.setSeriesColor(0, getAgentFillColor(AGENT_STREET_BROKER, false)); sbTransactionsNumGoodPlot.setSeriesColor(1, getAgentFillColor(AGENT_STREET_DEALER, false)); sbTransactionsNumGoodPlot.setSeriesColor(2, getAgentFillColor(AGENT_PRIVATE_DEALER, false)); sbTransactionsNumGoodPlot.setLegendValuesFormat(new DecimalFormat("0")); sbTransactionsNumGoodPlot.setPlotTitle("Completed Street Broker Transactions, by Seller"); sbModelStatusPlot.setYaxisValueMax(100); sbModelStatusPlot.setYaxisTickLabelFormat(new DecimalFormat("0")); sbModelStatusPlot.setYaxisTitle("percent"); sbModelStatusPlot.setSeriesName(0, "Active"); sbModelStatusPlot.setSeriesName(1, "Arrested"); sbModelStatusPlot.setSeriesColor(0, getAgentFillColor(AGENT_STREET_BROKER, false)); sbModelStatusPlot.setSeriesColor(1, getAgentFillColor(AGENT_POLICE, false)); sbModelStatusPlot.setLegendValuesFormat(new DecimalFormat("0.0'%'")); sbModelStatusPlot.setPlotTitle("Street Broker Distribution by Model Status"); sdModelStatusPlot.setYaxisValueMax(100); sdModelStatusPlot.setYaxisTickLabelFormat(new DecimalFormat("0")); sdModelStatusPlot.setYaxisTitle("percent"); sdModelStatusPlot.setSeriesName(0, "Active"); sdModelStatusPlot.setSeriesName(1, "Arrested"); sdModelStatusPlot.setSeriesColor(0, getAgentFillColor(AGENT_STREET_DEALER, false)); sdModelStatusPlot.setSeriesColor(1, getAgentFillColor(AGENT_POLICE, false)); sdModelStatusPlot.setLegendValuesFormat(new DecimalFormat("0.0'%'")); sdModelStatusPlot.setPlotTitle("Street Dealer Distribution by Model Status"); pdModelStatusPlot.setYaxisValueMax(100); pdModelStatusPlot.setYaxisTickLabelFormat(new DecimalFormat("0")); pdModelStatusPlot.setYaxisTitle("percent"); pdModelStatusPlot.setSeriesName(0, "Active"); pdModelStatusPlot.setSeriesName(1, "Arrested"); pdModelStatusPlot.setSeriesColor(0, getAgentFillColor(AGENT_PRIVATE_DEALER, false)); pdModelStatusPlot.setSeriesColor(1, getAgentFillColor(AGENT_POLICE, false)); pdModelStatusPlot.setLegendValuesFormat(new DecimalFormat("0.0'%'")); pdModelStatusPlot.setPlotTitle("Private Dealer Distribution by Model Status"); poNumberActivePlot.setYaxisValueMax(police.size()); poNumberActivePlot.setYaxisTickLabelFormat(new DecimalFormat("0")); poNumberActivePlot.setYaxisTitle("# active"); poNumberActivePlot.setSeriesName(0, "Active"); poNumberActivePlot.setSeriesColor(0, getAgentFillColor(AGENT_POLICE, false)); poNumberActivePlot.setLegendValuesFormat(new DecimalFormat("0")); poNumberActivePlot.setPlotTitle("Number of Active Police Officers"); poHarassmentsPlot.setYaxisValueMax(200); poHarassmentsPlot.setYaxisTickLabelFormat(new DecimalFormat("0")); poHarassmentsPlot.setYaxisTitle("number"); poHarassmentsPlot.setSeriesName(0, "Harassments"); poHarassmentsPlot.setSeriesName(1, "Arrests"); poHarassmentsPlot.setSeriesColor(0, Color.blue); poHarassmentsPlot.setSeriesColor(1, Color.red); poHarassmentsPlot.setLegendValuesFormat(new DecimalFormat("0")); poHarassmentsPlot.setPlotTitle("Number of Harassments and Arrests"); } private void addPointToPlots() { csTransactionsNumGoodPlot.addPoint(0, util.Clock.getCurrentDay(), csAllTransactions.numGood); csTransactionsNumGoodPlot.addPoint(1, util.Clock.getCurrentDay(), csSbTransactions.numGood); csTransactionsNumGoodPlot.addPoint(2, util.Clock.getCurrentDay(), csSdTransactions.numGood); csTransactionsNumGoodPlot.addPoint(3, util.Clock.getCurrentDay(), csPdTransactions.numGood); csTransactionsCostPlot.addPoint(0, util.Clock.getCurrentDay(), csAllTransactions.totalPrice); csTransactionsCostPlot.addPoint(1, util.Clock.getCurrentDay(), csSbTransactions.totalPrice); csTransactionsCostPlot.addPoint(2, util.Clock.getCurrentDay(), csSdTransactions.totalPrice); csTransactionsCostPlot.addPoint(3, util.Clock.getCurrentDay(), csPdTransactions.totalPrice); int csInTreatment = 0; int csInJail = 0; int csActive = 0; for (int i = 0; i < customer.size(); i++) { if (customer.item(i).currentPlace == PLACE_TREATMENT) { csInTreatment++; } else if (customer.item(i).currentPlace == PLACE_JAIL) { csInJail++; } else if (customer.item(i).isActive) { csActive++; } else { traceln("***ERROR in Main.animation.addPointToPlots(): Unexpected customer status."); } } csModelStatusPlot.addPoint(0, util.Clock.getCurrentDay(), 100.0 * csActive / customer.size()); csModelStatusPlot.addPoint(1, util.Clock.getCurrentDay(), 100.0 * csInTreatment / customer.size()); csModelStatusPlot.addPoint(2, util.Clock.getCurrentDay(), 100.0 * csInJail / customer.size()); sbTransactionsNumGoodPlot.addPoint(0, util.Clock.getCurrentDay(), sbAllTransactions.numGood); sbTransactionsNumGoodPlot.addPoint(1, util.Clock.getCurrentDay(), sbSdTransactions.numGood); sbTransactionsNumGoodPlot.addPoint(2, util.Clock.getCurrentDay(), sbPdTransactions.numGood); int sbInJail = 0; int sbActive = 0; for (int i = 0; i < streetBroker.size(); i++) { if (streetBroker.item(i).currentPlace == PLACE_JAIL) { sbInJail ++; } else if (streetBroker.item(i).isActive) { sbActive++; } else { traceln("***ERROR in Main.animation.addPointToPlots(): Unexpected street broker status."); } } sbModelStatusPlot.addPoint(0, util.Clock.getCurrentDay(), 100.0 * sbActive / streetBroker.size()); sbModelStatusPlot.addPoint(1, util.Clock.getCurrentDay(), 100.0 * sbInJail / streetBroker.size()); int sdInJail = 0; int sdActive = 0; for (int i = 0; i < streetDealer.size(); i++) { if (streetDealer.item(i).currentPlace == PLACE_JAIL) { sdInJail ++; } else if (streetDealer.item(i).isActive) { sdActive++; } else { traceln("***ERROR in Main.animation.addPointToPlots(): Unexpected street dealer status."); } } sdModelStatusPlot.addPoint(0, util.Clock.getCurrentDay(), 100.0 * sdActive / streetDealer.size()); sdModelStatusPlot.addPoint(1, util.Clock.getCurrentDay(), 100.0 * sdInJail / streetDealer.size()); int pdInJail = 0; int pdActive = 0; for (int i = 0; i < privateDealer.size(); i++) { if (privateDealer.item(i).currentPlace == PLACE_JAIL) { pdInJail ++; } else if (privateDealer.item(i).isActive) { pdActive++; } else { traceln("***ERROR in Main.animation.addPointToPlots(): Unexpected street dealer status."); } } pdModelStatusPlot.addPoint(0, util.Clock.getCurrentDay(), 100.0 * pdActive / privateDealer.size()); pdModelStatusPlot.addPoint(1, util.Clock.getCurrentDay(), 100.0 * pdInJail / privateDealer.size()); poNumberActivePlot.addPoint(0, util.Clock.getCurrentDay(), police.sum("isActive")); poHarassmentsPlot.addPoint(0, util.Clock.getCurrentDay(), police.sum("numHarassments")); poHarassmentsPlot.addPoint(1, util.Clock.getCurrentDay(), police.sum("numArrests")); } private void setPlotVisibility() { csTransactionsNumGoodPlot.setVisible(agentPov == AGENT_CUSTOMER && optionFilter == FILTER_ALL && optionCsAllStat == STAT_CS_ALL_TRANSACTIONS_GOOD); csTransactionsCostPlot.setVisible(agentPov == AGENT_CUSTOMER && optionFilter == FILTER_ALL && optionCsAllStat == STAT_CS_ALL_TRANSACTIONS_COST); csModelStatusPlot.setVisible(agentPov == AGENT_CUSTOMER && optionFilter == FILTER_ALL && optionCsAllStat == STAT_CS_ALL_MODEL_STATUS); sbTransactionsNumGoodPlot.setVisible(agentPov == AGENT_STREET_BROKER && optionFilter == FILTER_ALL && optionSbAllStat == STAT_SB_ALL_TRANSACTIONS_GOOD); sbModelStatusPlot.setVisible(agentPov == AGENT_STREET_BROKER && optionFilter == FILTER_ALL && optionSbAllStat == STAT_SB_ALL_MODEL_STATUS); sdModelStatusPlot.setVisible(agentPov == AGENT_STREET_DEALER && optionFilter == FILTER_ALL && optionSdAllStat == STAT_SD_ALL_MODEL_STATUS); pdModelStatusPlot.setVisible(agentPov == AGENT_PRIVATE_DEALER && optionFilter == FILTER_ALL && optionPdAllStat == STAT_PD_ALL_MODEL_STATUS); poNumberActivePlot.setVisible(agentPov == AGENT_POLICE && optionFilter == FILTER_ALL && optionPoAllStat == STAT_PO_ALL_NUMBER_ACTIVE); poHarassmentsPlot.setVisible(agentPov == AGENT_POLICE && optionFilter == FILTER_ALL && optionPoAllStat == STAT_PO_ALL_HARASSMENTS); } //--------------------------------------------------------------------- // Process mouse clicks. // protected void onMouseClicked(java.awt.Point p) { if (filterBox.handleClick(p.getX(), p.getY())) { return; } if (csAllStatBox.handleClick(p.getX(), p.getY())) { return; } if (csSelectedStatBox.handleClick(p.getX(), p.getY())) { return; } if (sbAllStatBox.handleClick(p.getX(), p.getY())) { return; } if (sbSelectedStatBox.handleClick(p.getX(), p.getY())) { return; } if (sdAllStatBox.handleClick(p.getX(), p.getY())) { return; } if (sdSelectedStatBox.handleClick(p.getX(), p.getY())) { return; } if (pdAllStatBox.handleClick(p.getX(), p.getY())) { return; } if (pdSelectedStatBox.handleClick(p.getX(), p.getY())) { return; } if (poAllStatBox.handleClick(p.getX(), p.getY())) { return; } if (poSelectedStatBox.handleClick(p.getX(), p.getY())) { return; } if (mkAllStatBox.handleClick(p.getX(), p.getY())) { return; } if (mkSelectedStatBox.handleClick(p.getX(), p.getY())) { return; } if (cityRectangle.contains(p.getX(), p.getY())) { if (agentPov == AGENT_CUSTOMER) { for (int i = 0; i < customer.size(); i++) { if (customer.item(i).animation.agentShape.contains(p.getX(), p.getY())) { selectAgent(agentPov, i); return; } } } else if (agentPov == AGENT_STREET_BROKER) { for (int i = 0; i < streetBroker.size(); i++) { if (streetBroker.item(i).animation.agentShape.contains(p.getX(), p.getY())) { selectAgent(agentPov, i); return; } } } else if (agentPov == AGENT_STREET_DEALER) { for (int i = 0; i < streetDealer.size(); i++) { if (streetDealer.item(i).animation.agentShape.contains(p.getX(), p.getY())) { selectAgent(agentPov, i); return; } } } else if (agentPov == AGENT_PRIVATE_DEALER) { for (int i = 0; i < privateDealer.size(); i++) { if (privateDealer.item(i).animation.agentShape.contains(p.getX(), p.getY())) { selectAgent(agentPov, i); return; } } } else if (agentPov == AGENT_HOMELESS) { for (int i = 0; i < homeless.size(); i++) { if (homeless.item(i).animation.agentShape.contains(p.getX(), p.getY())) { selectAgent(agentPov, i); return; } } } else if (agentPov == AGENT_POLICE) { for (int i = 0; i < police.size(); i++) { if (police.item(i).animation.agentShape.contains(p.getX(), p.getY())) { selectAgent(agentPov, i); return; } } } else if (agentPov == AGENT_MARKET) { for (int i = 0; i < market.size(); i++) { if (market.item(i).animation.agentShape.contains(p.getX(), p.getY())) { selectAgent(agentPov, i); return; } } } } } private void disableAppletButtons() { // This function will disable or remove buttons from the toolbar that is added // to the top of applets. This is particularly important for the Reset button, // since its behavior does not work as expected. // // To disable a button, use setEnabled(false). This will leave the button in // place but gray it out. // // To remove a button, use setVisible(false). Note however, that the button // to the right of the removed button will slide over into its place. The // next time this function is called, that button will be removed, the one to // its right will slide over, and so on. if (util.Model.getRunMode().equals("applet")) { java.awt.Component toolbar = Engine.getAnimation().getToolbar(); // disable applet Reset button toolbar.getComponentAt(75, 15).setEnabled(false); // Run button -- x = 0, y = 1, width = 30, height = 30 //toolbar.getComponentAt(15, 15); // Pause button -- x = 30, y = 1, width = 30, height = 30 //toolbar.getComponentAt(45, 15); // Reset button -- x = 60, y = 1, width = 30, height = 30 //toolbar.getComponentAt(75, 15); // Model speed slider -- x = 90, y = 0, width = 120, height = 32 //toolbar.getComponentAt(105, 15); // Animation Options button -- x = 210, y = 1, width = 30, height = 30 //toolbar.getComponentAt(225, 15); // blank rectangle - javax.swing.JPanel object //toolbar.getComponentAt(255, 15); // XJ logo -- x = (applet width - 92), y = 0, width = 92, height = 32 //toolbar.getComponentAt(850, 15); } } |
| Picture | ![]() |
| Button | button11 |
| Fill color | agentPov ==AGENT_MARKET ? inPovButtonColor : outPovButtonColor |
| Label | Market |
| Event handling code | setPov(AGENT_MARKET); |
| Button | button10 |
| Label | > |
| Event handling code | int oldId = selectedAgents[agentPov]; int newId; if (oldId == agentLists[agentPov].size() - 1) { newId = 0; } else { newId = oldId + 1; } selectAgent(agentPov, newId); |
| Button | button9 |
| Label | < |
| Event handling code | int oldId = selectedAgents[agentPov]; int newId; if (oldId > 0) { newId = oldId - 1; } else { newId = agentLists[agentPov].size() - 1; } selectAgent(agentPov, newId); |
| Checkbox | zoomLevelCheckbox |
| Label | Zoom selected market |
| Event handling code | if (getValue()) { setZoomLevel(ZOOM_MARKET); } else { setZoomLevel(ZOOM_CITY); } |
| Button | button5 |
| Fill color | agentPov ==AGENT_POLICE ? inPovButtonColor : outPovButtonColor |
| Label | Police |
| Event handling code | setPov(AGENT_POLICE); |
| Button | button4 |
| Fill color | agentPov ==AGENT_PRIVATE_DEALER ? inPovButtonColor : outPovButtonColor |
| Label | Private Dealer |
| Event handling code | setPov(AGENT_PRIVATE_DEALER); |
| Button | button3 |
| Fill color | agentPov == AGENT_STREET_DEALER ? inPovButtonColor : outPovButtonColor |
| Label | Street Dealer |
| Event handling code | setPov(AGENT_STREET_DEALER); |
| Button | button2 |
| Fill color | agentPov == AGENT_STREET_BROKER ? inPovButtonColor : outPovButtonColor |
| Label | Street Broker |
| Event handling code | setPov(AGENT_STREET_BROKER); |
| Button | button |
| Label | Pick Random |
| Event handling code | int size = agentLists[agentPov].size() - 1; selectAgent(agentPov, uniform_discr(size)); |
| Editbox | selectedAgentEdit |
| Label | editBox |
| Event handling code | try { // Integer.parseInt will throw a NumberFormatException if // its argument does not contain an integer. int newID = Integer.parseInt(getValue()); // We throw our own NumberFormatException if the newID is // out of range. if (newID < 0 || newID >= agentLists[agentPov].size()) { throw new NumberFormatException(); } // If we made it this far without an exception, the newID // is valid, so go ahead and select the corresponding agent. selectAgent(agentPov, newID); } catch (NumberFormatException e) { // If an invalid id was entered, reset the text box to its // last valid value. setValue(selectedAgents[agentPov]); } |
| Button | button1 |
| Fill color | agentPov == AGENT_CUSTOMER ? inPovButtonColor : outPovButtonColor |
| Label | Customer |
| Event handling code | setPov(AGENT_CUSTOMER); |
| Encapsulated | encapsulatedAnimation7 |
| Object | homeless |
| Pivot | pivot6 |
| X | statsX |
| Y | statsY |
| Visible | agentPov == AGENT_PRIVATE_DEALER && optionFilter == FILTER_SELECTED && optionPdSelectedStat == STAT_PD_SELECTED_ALL |
| Pivot | pivot3 |
| X | statsX |
| Y | statsY |
| Visible | agentPov == AGENT_STREET_DEALER && optionFilter == FILTER_SELECTED && optionSdSelectedStat == STAT_SD_SELECTED_ALL |
| Encapsulated | encapsulatedAnimation5 |
| Object | police |
| Text | statBoxLabel |
| X | statBoxX |
| Y | optionBoxY - 20 |
| Text | Stats to show: |
| Text | filterBoxLabel |
| X | filterBoxX |
| Y | optionBoxY - 20 |
| Text | Show stats for: |
| Rectangle | rectangle11 |
| Line color | outlineColor |
| Pivot | pivot5 |
| X | statsX |
| Y | statsY |
| Visible | agentPov == AGENT_STREET_BROKER && optionFilter == FILTER_SELECTED && optionSbSelectedStat == STAT_SB_SELECTED_ALL |
| Line | line2 |
| Line color | outlineColor |
| Pivot | pivot4 |
| X | statsX |
| Y | statsY |
| Visible | agentPov == AGENT_CUSTOMER && optionFilter == FILTER_SELECTED && optionCsSelectedStat == STAT_CS_SELECTED_ALL |
| Rectangle | rectangle8 |
| Line color | outlineColor |
| Text | text39 |
| Visible | false |
| Text | Encapsulated animations |
| Pivot | pivot2 |
| X | statsX |
| Y | statsY |
| Visible | false /*agentPov == AGENT_STREET_BROKER && optionFilter == FILTER_ALL && optionSbAllStat == STAT_SB_ALL_ALL*/ |
| Pivot | pivot1 |
| X | statsX |
| Y | statsY |
| Visible | false /*agentPov == AGENT_CUSTOMER && optionFilter == FILTER_ALL*/ |
| Rectangle | rectangle7 |
| Fill color | getAgentFillColor(AGENT_MARKET, false) |
| Line color | getAgentLineColor(AGENT_MARKET, false) |
| Rectangle | rectangle6 |
| Fill color | getAgentFillColor(AGENT_HOMELESS, false) |
| Line color | getAgentLineColor(AGENT_HOMELESS, false) |
| Rectangle | rectangle5 |
| Fill color | getAgentFillColor(AGENT_POLICE, false) |
| Line color | getAgentLineColor(AGENT_POLICE, false) |
| Rectangle | rectangle4 |
| Fill color | getAgentFillColor(AGENT_PRIVATE_DEALER, false) |
| Line color | getAgentLineColor(AGENT_PRIVATE_DEALER, false) |
| Rectangle | rectangle3 |
| Fill color | getAgentFillColor(AGENT_STREET_DEALER, false) |
| Line color | getAgentLineColor(AGENT_STREET_DEALER, false) |
| Rectangle | rectangle2 |
| Fill color | getAgentFillColor(AGENT_STREET_BROKER, false) |
| Line color | getAgentLineColor(AGENT_STREET_BROKER, false) |
| Rectangle | rectangle1 |
| Fill color | getAgentFillColor(AGENT_CUSTOMER, false) |
| Line color | getAgentLineColor(AGENT_CUSTOMER, false) |
| Encapsulated | encapsulatedAnimation4 |
| Object | privateDealer |
| Encapsulated | encapsulatedAnimation3 |
| Object | streetBroker |
| Encapsulated | encapsulatedAnimation2 |
| Object | market |
| Encapsulated | encapsulatedAnimation1 |
| Object | streetDealer |
| Encapsulated | encapsulatedAnimation |
| Object | customer |
| Rectangle | cityRectangle |
| Line color | outlineColor |
| Rectangle | rectangle9 |
| Fill color | titleColor |
| Line color | outlineColor |
| Rectangle | rectangle12 |
| Fill color | subtitleColor |
| General | |
| Import | import message.*; import misc.*; |
| Parameters | |
| Name | x |
| Type | real |
| Name | y |
| Type | real |
| Name | width |
| Type | real |
| Name | height |
| Type | real |
| Icon | |
| Picture | |
| Structure | |
| Picture | ![]() |
| Variable | homeless |
| Variable type | List |
| Initial value | new ArrayList() |
| Variable | main |
| Variable type | Main |
| Initial value | (Main)getOwner() |
| Variable | streetBrokers |
| Variable type | List |
| Initial value | new ArrayList() |
| Variable | isOpen |
| Variable type | boolean |
| Variable | streetDealers |
| Variable type | List |
| Initial value | new ArrayList() |
| Algorithmic Functions | |||||||||||
| Name | addHomeless | ||||||||||
| Type | void | ||||||||||
| Arguments |
|
||||||||||
| Body | if (!homeless.contains(hm)) { homeless.add(hm); } |
||||||||||
| Name | addStreetBroker | ||||||||||
| Type | void | ||||||||||
| Arguments |
|
||||||||||
| Body | if (!streetBrokers.contains(sb)) { streetBrokers.add(sb); } |
||||||||||
| Name | addStreetDealer | ||||||||||
| Type | void | ||||||||||
| Arguments |
|
||||||||||
| Body | if (!streetDealers.contains(sd)) { streetDealers.add(sd); } |
||||||||||
| Name | close | ||||||||||
| Type | void | ||||||||||
| Body | isOpen = false; |
||||||||||
| Name | getLocationInMarketX | ||||||||||
| Type | real | ||||||||||
| Arguments |
|
||||||||||
| Body | return loc - (x - width/2); |
||||||||||
| Name | getLocationInMarketY | ||||||||||
| Type | real | ||||||||||
| Arguments |
|
||||||||||
| Body | return loc - (y - height/2); |
||||||||||
| Name | getRandomX | ||||||||||
| Type | real | ||||||||||
| Body | return uniform(x - width / 2, x + width / 2); |
||||||||||
| Name | getRandomY | ||||||||||
| Type | real | ||||||||||
| Body | return uniform(y - height / 2, y + height / 2); |
||||||||||
| Name | isContainedInRectangle | ||||||||||
| Type | boolean | ||||||||||
| Arguments |
|
||||||||||
| Body | return rectX <= x - width / 2 && rectX + rectWidth >= x + width / 2 && rectY <= y - height / 2 && rectY + rectHeight >= y + height / 2 ; |
||||||||||
| Name | isLocationInMarket | ||||||||||
| Type | boolean | ||||||||||
| Arguments |
|
||||||||||
| Body | return locX >= x - width / 2 && locX <= x + width / 2 && locY >= y - height / 2 && locY <= y + height / 2 ; |
||||||||||
| Name | isOverlappingMarket | ||||||||||
| Type | boolean | ||||||||||
| Arguments |
|
||||||||||
| Body | return // is one of this Market's corners inside Market m? m.isLocationInMarket(x - width / 2, y - height / 2) || m.isLocationInMarket(x + width / 2, y - height / 2) || m.isLocationInMarket(x + width / 2, y + height / 2) || m.isLocationInMarket(x - width / 2, y + height / 2) // is one of Market m's corners inside this market? || isLocationInMarket(m.x - m.width / 2, m.y - m.height / 2) || isLocationInMarket(m.x + m.width / 2, m.y - m.height / 2) || isLocationInMarket(m.x + m.width / 2, m.y + m.height / 2) || isLocationInMarket(m.x - m.width / 2, m.y + m.height / 2) ; |
||||||||||
| Name | open | ||||||||||
| Type | void | ||||||||||
| Body | isOpen = true; |
||||||||||
| Name | removeHomeless | ||||||||||
| Type | void | ||||||||||
| Arguments |
|
||||||||||
| Body | homeless.remove(hm); |
||||||||||
| Name | removeStreetBroker | ||||||||||
| Type | void | ||||||||||
| Arguments |
|
||||||||||
| Body | streetBrokers.remove(sb); |
||||||||||
| Name | removeStreetDealer | ||||||||||
| Type | void | ||||||||||
| Arguments |
|
||||||||||
| Body | streetDealers.remove(sd); |
||||||||||
| Animation | |
| Name | animation |
| X | 0 |
| Y | 0 |
| Additional class code | public boolean isSelected = false; |
| Picture | ![]() |
| Rectangle | agentShape |
| X | main.animation.getAgentLocationX(main.AGENT_MARKET, isSelected, x - width / 2) |
| Y | main.animation.getAgentLocationY(main.AGENT_MARKET, isSelected, y - height / 2) |
| Width | main.animation.distanceToPixels(width) |
| Height | main.animation.distanceToPixels(height) |
| Line color | main.animation.getAgentLineColor(main.AGENT_MARKET, isSelected) |
| Line width | main.animation.getAgentLineWidth(main.AGENT_MARKET, isSelected) |
| Visible | main.animation.getAgentVisibility(main.AGENT_MARKET, isSelected, x, y) |
| General | |
| Import | import message.*; import misc.*; |
| Additional class code | public static final int TYPE_REGULAR = 0; public static final int TYPE_RESERVE = 1; public static final int NUM_TYPES = 2; // Our convention is to avoid defining classes and functions here in the // additional class code because it is somewhat hidden. However, we break // that convention here because: // 1) We want to use it by passing parameters to it when we instantiate it. // This prevents us from defining it as an ActiveObject. // 2) This is such a simple class that we do not bother defining it in an // external file. private class HarassTarget { public HarassTarget(PoliceTarget agent, double harassProb, double arrestProb) { this.agent = agent; this.harassProb = harassProb; this.arrestProb = arrestProb; } public PoliceTarget agent; public double harassProb; public double arrestProb; } |
| Parameters | |
| Name | initialMarket |
| Type | Market |
| Name | type |
| Type | integer |
| Icon | |
| Picture | |
| Structure | |||||||
| Picture | ![]() |
||||||
| Variable | arrestTarget | ||||||
| Variable type | PoliceTarget | ||||||
| Initial value | null | ||||||
| Variable | numArrests | ||||||
| Variable type | integer | ||||||
| Initial value | 0 | ||||||
| Variable | numHarassments | ||||||
| Variable type | integer | ||||||
| Initial value | 0 | ||||||
| Variable | isOnBust | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Variable | isMakingArrest | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Variable | harassTarget | ||||||
| Variable type | HarassTarget | ||||||
| Initial value | null | ||||||
| Variable | isActive | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Variable | main | ||||||
| Variable type | Main | ||||||
| Initial value | (Main)getOwner() | ||||||
| Variable | self | ||||||
| Variable type | Police | ||||||
| Initial value | this | ||||||
| Variable | market | ||||||
| Variable type | Market | ||||||
| Initial value | initialMarket | ||||||
| Port | travelCompleteListener | ||||||
| Message type | TravelCompleteMsg | ||||||
| Statechart | simulationState | ||||||
| Object | location | ||||||
| Type | misc.Location | ||||||
| Parameters |
|
||||||
| Statechart | |
| Name | simulationState |
| Picture | ![]() |
| ChoicePoint | checkArrest |
| Action | checkArrest(); |
| ChoicePoint | seekHarassTarget |
| Action | seekHarassTarget(); |
| Transition | transition8 |
| Source/target | branch=>inactive |
| Fire | If guard is open |
| Guard | type == Police.TYPE_RESERVE |
| Transition | transition7 |
| Source/target | branch=>active |
| Fire | If guard is open |
| Guard | type == Police.TYPE_REGULAR |
| Transition | transition6 |
| Source/target | inactive=>active |
| Fire | Signal event occurs |
| Signal event | BustStartMsg |
| Action | applyBustStartMsg((BustStartMsg)getEvent()); |
| Transition | transition5 |
| Source/target | randomWalk=>inactive |
| Fire | Signal event occurs |
| Guard | type == Police.TYPE_RESERVE |
| Signal event | BustEndMsg |
| Action | applyBustEndMsg((BustEndMsg)getEvent()); |
| Transition | transition4 |
| Source/target | checkArrest=>randomWalk |
| Fire | Signal event occurs |
| Guard | arrestTarget == null |
| Action | PoliceTarget pt = (PoliceTarget)harassTarget.agent; pt.receiveHarassCompleteMsg(new HarassCompleteMsg()); |
| Transition | transition3 |
| Source/target | harass=>checkArrest |
| Fire | Timeout |
| Timeout | Main.poHarassDuration |
| Transition | transition2 |
| Source/target | checkArrest=>arrest |
| Fire | Signal event occurs |
| Guard | arrestTarget != null |
| Transition | transition1 |
| Source/target | arrest=>randomWalk |
| Fire | Timeout |
| Timeout | Main.poArrestDuration |
| Transition | transition |
| Source/target | seekHarassTarget=>harass |
| Fire | Signal event occurs |
| Guard | harassTarget != null |
| Transition | transition31 |
| Source/target | randomWalk=>seekHarassTarget |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Transition | transition28 |
| Source/target | seekHarassTarget=>randomWalk |
| Fire | Signal event occurs |
| Guard | harassTarget == null |
| Signal event | TargetFoundMsg |
| State | randomWalk |
| Entry action | wanderInMarket(); |
| State | arrest |
| Deferred events | new BustEndEvent() |
| Entry action | isMakingArrest = true; arrest(); |
| Exit action | isMakingArrest = false; |
| State | harass |
| Deferred events | new BustEndEvent() |
| Entry action | harass(); |
| State | active |
| Entry action | isActive = true; |
| Exit action | isActive = false; |
| Algorithmic Functions | |||||
| Name | applyBustEndMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | isOnBust = false; |
||||
| Name | applyBustStartMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | isOnBust = true; |
||||
| Name | arrest | ||||
| Type | void | ||||
| Body | ArrestMsg msg = new ArrestMsg(); msg.duration = Main.poJailPerDrugUnit * arrestTarget.getDrugsOnPerson(); arrestTarget.receiveArrestMsg(msg); numArrests++; |
||||
| Name | checkArrest | ||||
| Type | void | ||||
| Body | arrestTarget = null; PoliceTarget pt = (PoliceTarget)harassTarget.agent; if (pt.getDrugsOnPerson() > 0 && randomTrue(harassTarget.arrestProb)) { arrestTarget = pt; } |
||||
| Name | harass | ||||
| Type | void | ||||
| Body | PoliceTarget pt = (PoliceTarget)harassTarget.agent; pt.receiveHarassMsg(new HarassMsg()); numHarassments++; |
||||
| Name | receiveBustEndMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (msg.market == market) { // We handle BustEndMsg messages differently depending on the // officer type. Regular officers do not respond to these messages // in their statecharts. Instead, they immediately change their // parameters to non-bust parameters, which is done in applyBustEndMsg(). // Reserve officers do respond to these messages in their statecharts, // so for them we just pass the message along to the statechart. if (type == Police.TYPE_REGULAR) { applyBustEndMsg(msg); } else if (type == Police.TYPE_RESERVE) { simulationState.fireEvent(msg); } else { traceln("***ERROR in Police.receiveBustEndMsg(): Unexpected officer type [" + type + "] for " + self + " @ " + Engine.getTime()); } } |
||||
| Name | receiveBustStartMsg | ||||
| Type | void | ||||
| Arguments |
|
||||
| Body | if (msg.market == market) { // We handle BustStartMsg messages differently depending on the // officer type. Regular officers do not respond to these messages // in their statecharts. Instead, they immediately change their // parameters to bust parameters, which is done in applyBustStartMsg(). // Reserve officers do respond to these messages in their statecharts, // so for them we just pass the message along to the statechart. if (type == Police.TYPE_REGULAR) { applyBustStartMsg(msg); } else if (type == Police.TYPE_RESERVE) { simulationState.fireEvent(msg); } else { traceln("***ERROR in Police.receiveBustStartMsg(): Unexpected officer type [" + type + "] for " + self + " @ " + Engine.getTime()); } } |
||||
| Name | seekHarassTarget | ||||
| Type | void | ||||
| Body | // Create a list of all the possible people we can harass. List targets = new ArrayList(); for (int i = 0; i < market.streetBrokers.size(); i++) { targets.add(new HarassTarget((PoliceTarget)market.streetBrokers.get(i) , isOnBust ? Main.poBustProbHarassStreetBroker : Main.poProbHarassStreetBroker , isOnBust ? Main.poBustProbArrestStreetBroker : Main.poProbArrestStreetBroker )); } for (int i = 0; i < market.streetDealers.size(); i++) { targets.add(new HarassTarget((PoliceTarget)market.streetDealers.get(i) , isOnBust ? Main.poBustProbHarassStreetDealer : Main.poProbHarassStreetDealer , isOnBust ? Main.poBustProbArrestStreetDealer : Main.poProbArrestStreetDealer )); } for (int i = 0; i < market.homeless.size(); i++) { targets.add(new HarassTarget((PoliceTarget)market.homeless.get(i) , isOnBust ? Main.poBustProbHarassHomeless : Main.poProbHarassHomeless , isOnBust ? Main.poBustProbArrestHomeless : Main.poProbArrestHomeless )); } for (int i = 0; i < main.customer.size(); i++) { targets.add(new HarassTarget((PoliceTarget)main.customer.get(i) , isOnBust ? Main.poBustProbHarassCustomer : Main.poProbHarassCustomer , isOnBust ? Main.poBustProbArrestCustomer : Main.poProbArrestCustomer )); } for (int i = 0; i < main.privateDealer.size(); i++) { targets.add(new HarassTarget((PoliceTarget)main.privateDealer.get(i) , isOnBust ? Main.poBustProbHarassPrivateDealer : Main.poProbHarassPrivateDealer , isOnBust ? Main.poBustProbArrestPrivateDealer : Main.poProbArrestPrivateDealer )); } // Sort the list randomly. util.List.shuffle(targets); // Scan the list of suspects and find the first one within our vision // radius that we have not harassed recently. If we find one, he will // be our harassment target with probability equal to his harassment // probability. harassTarget = null; double visionRadius = isOnBust ? Main.poBustVisionRadius : Main.poVisionRadius; for (int i = 0; i < targets.size(); i++) { HarassTarget ht = (HarassTarget)targets.get(i); PoliceTarget pt = (PoliceTarget)ht.agent; if ( pt.isInPublic() && location.distance(pt.getLocation().currentX, pt.getLocation().currentY) <= visionRadius && !pt.isBeingHarassed() && (pt.getLastHarassTime() == 0 || Engine.getTime() - pt.getLastHarassTime() > Main.poHarassRepeatDelay) && randomTrue(ht.harassProb) ) { harassTarget = ht; break; } } |
||||
| Name | wanderInMarket | ||||
| Type | void | ||||
| Body | location.wanderInMarket(market); |
||||
| Animation | |
| Name | animation |
| X | 0 |
| Y | 0 |
| Additional class code | public boolean isSelected = false; |
| Picture | ![]() |
| Rectangle | agentShape |
| X | main.animation.getAgentLocationX(main.AGENT_POLICE, isSelected, location.currentX) |
| Y | main.animation.getAgentLocationY(main.AGENT_POLICE, isSelected, location.currentY) |
| Width | main.animation.getAgentSize(main.AGENT_POLICE, isSelected) |
| Height | main.animation.getAgentSize(main.AGENT_POLICE, isSelected) |
| Fill color | main.animation.getAgentFillColor(main.AGENT_POLICE, isSelected) |
| Line color | main.animation.getAgentLineColor(main.AGENT_POLICE, isSelected) |
| Line width | main.animation.getAgentLineWidth(main.AGENT_POLICE, isSelected) |
| Visible | isActive && !isMakingArrest && main.animation.getAgentVisibility(main.AGENT_POLICE, isSelected, location.currentX, location.currentY) |
| General | |
| Import | import message.*; import misc.*; |
| Parameters | |
| Name | homeX |
| Type | real |
| Name | homeY |
| Type | real |
| Name | initialMoney |
| Type | real |
| Name | initialInventory |
| Type | real |
| Name | probDeliverHome |
| Type | real |
| Name | probDeliverMarket |
| Type | real |
| Name | dealDelayMin |
| Type | real |
| Name | dealDelayMax |
| Type | real |
| Name | shiftStartHourMin |
| Type | real |
| Name | shiftStartHourMax |
| Type | real |
| Name | shiftLengthMin |
| Type | real |
| Name | shiftLengthMax |
| Type | real |
| Name | invitationDeals |
| Type | integer |
| Name | acceptableDeliverUnits |
| Type | real |
| Icon | |
| Picture | |
| Structure | |||||||
| Picture | ![]() |
||||||
| ChartTimer | shiftEndTimer | ||||||
| Expire | No (manual mode) | ||||||
| Expiry Action | // Alert the dealer's statechart that he is ending his shift. simulationState.fireEvent(new ShiftEndMsg()); |
||||||
| ChartTimer | dailyTimer | ||||||
| Timeout | util.Units.days(1) | ||||||
| Expire At Startup | Yes | ||||||
| Expiry Action | if (isActive) { double shiftStart = uniform(util.Units.hours(shiftStartHourMin), util.Units.hours(shiftStartHourMax)); shiftStartTimer.restart(shiftStart); } |
||||||
| ChartTimer | shiftStartTimer | ||||||
| Expire | No (manual mode) | ||||||
| Expiry Action | if (!isOnShift) { // The dealer is off shift, so we can safely start his shift. // Reset the dealer's inventory. // // For now, we assume that private dealers replenish their // inventories between shifts as needed, and that they never // have problems with shortages. We implement this assumption // by resetting the inventory to its initial value every day. inventory = initialInventory; // Alert the dealer's statechart that he is starting his shift. simulationState.fireEvent(new ShiftStartMsg()); // Start a timer to expire when the dealer's shift ends. shiftEndTimer.restart(uniform(shiftLengthMin, shiftLengthMax)); } else { // The dealer is on shift, so we need to wait until he ends // his current shift before starting the next one. We add // a minute to make sure we restart after the shift ends. restart(shiftEndTimer.getRest() + util.Units.minutes(1)); } |
||||||
| Variable | isWaitingOnBuyer | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Variable | lastHarassTime | ||||||
| Variable type | real | ||||||
| Initial value | 0 | ||||||
| Variable | isBeingHarassed | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Variable | isOnDeal | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Variable | possessionUnits | ||||||
| Variable type | real | ||||||
| Initial value | 0 | ||||||
| Variable | currentPlace | ||||||
| Variable type | integer | ||||||
| Initial value | Main.PLACE_HOME | ||||||
| Variable | numArrests | ||||||
| Variable type | real | ||||||
| Initial value | 0 | ||||||
| Variable | arrestDuration | ||||||
| Variable type | real | ||||||
| Variable | main | ||||||
| Variable type | Main | ||||||
| Initial value | (Main)getOwner() | ||||||
| Variable | money | ||||||
| Variable type | real | ||||||
| Initial value | initialMoney | ||||||
| Variable | inventory | ||||||
| Variable type | real | ||||||
| Initial value | initialInventory | ||||||
| Variable | self | ||||||
| Variable type | PrivateDealer | ||||||
| Initial value | this | ||||||
| Variable | buyerY | ||||||
| Variable type | real | ||||||
| Initial value | 0 | ||||||
| Variable | buyerX | ||||||
| Variable type | real | ||||||
| Initial value | 0 | ||||||
| Variable | dealFromBuyer | ||||||
| Variable type | DealRequestMsg | ||||||
| Initial value | null | ||||||
| Variable | isOnShift | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Variable | isActive | ||||||
| Variable type | boolean | ||||||
| Initial value | false | ||||||
| Port | travelCompleteListener | ||||||
| Message type | TravelCompleteMsg | ||||||
| Statechart | simulationState | ||||||
| Object | location | ||||||
| Type | misc.Location | ||||||
| Parameters |
|
||||||
| Object | customerHistories | ||||||
| Type | misc.AgentHistoryList | ||||||
| Statechart | |
| Name | simulationState |
| Picture | ![]() |
| History | preHarassed |
| Type | Shallow |
| Action | // NOTE: // // Due to a bug in AnyLogic 5, a deep history state // will not transition to a simple state that is // inside a composite state when the composite state // is on the same level as the deep history state. // Instead, it will cause a runtime error. Therefore // we avoid deep history states and live with the // limitations of shallow history states. |
| Transition | transition25 |
| Source/target | harassed=>preHarassed |
| Fire | Signal event occurs |
| Signal event | HarassCompleteMsg |
| Action | applyHarassCompleteMsg((HarassCompleteMsg)getEvent()); |
| Transition | transition24 |
| Source/target | state=>harassed |
| Fire | Signal event occurs |
| Signal event | HarassMsg |
| Action | applyHarassMsg((HarassMsg)getEvent()); |
| Transition | transition23 |
| Source/target | waitForBuyer=>available |
| Fire | Timeout |
| Timeout | Main.pdDealQuitTime |
| Action | isWaitingOnBuyer = false; quitDeal(); |
| Transition | transition22 |
| Source/target | isBuyerWaiting4=>travelToHome |
| Fire | If all other guards are closed |
| Action | endDeal(false); |
| Transition | transition21 |
| Source/target | isBuyerWaiting4=>travelToHome |
| Fire | If guard is open |
| Guard | dealFromBuyer.buyer.isWaitingOnSeller(dealFromBuyer.dealID) |
| Action | possessionUnits = 0; endDeal(true); |
| Transition | transition20 |
| Source/target | isBuyerWaiting3=>travelToHome |
| Fire | If all other guards are closed |
| Action | endDeal(false); |
| Transition | transition19 |
| Source/target | isBuyerWaiting3=>onDeal |
| Fire | If guard is open |
| Guard | dealFromBuyer.buyer.isWaitingOnSeller(dealFromBuyer.dealID) |
| Action | sendWaitCompleteMsg(); |
| Transition | transition18 |
| Source/target | isBuyerWaiting2=>available |
| Fire | If all other guards are closed |
| Action | endDeal(false); |
| Transition | transition17 |
| Source/target | isBuyerWaiting2=>available |
| Fire | If guard is open |
| Guard | dealFromBuyer.buyer.isWaitingOnSeller(dealFromBuyer.dealID) |
| Action | endDeal(true); |
| Transition | transition15 |
| Source/target | arrested=>active |
| Fire | Timeout |
| Timeout | arrestDuration |
| Transition | transition16 |
| Source/target | active=>arrested |
| Fire | Signal event occurs |
| Signal event | ArrestMsg |
| Action | applyArrestMsg((ArrestMsg)getEvent()); |
| Transition | transition14 |
| Source/target | willAcceptDeal=>available |
| Fire | If all other guards are closed |
| Action | sendDealDeniedMsg(dealFromBuyer); |
| Transition | transition13 |
| Source/target | isBuyerWaiting=>available |
| Fire | If all other guards are closed |
| Transition | transition12 |
| Source/target | isBuyerWaiting=>willAcceptDeal |
| Fire | If guard is open |
| Guard | dealFromBuyer.buyer.isWaitingOnSeller(dealFromBuyer.dealID) |
| Transition | transition11 |
| Source/target | willAcceptDeal=>willDeliver |
| Fire | If guard is open |
| Guard | willAcceptDeal(dealFromBuyer.buyer, dealFromBuyer.units, dealFromBuyer.price) |
| Action | startDeal(); |
| Transition | transition10 |
| Source/target | available=>offShift |
| Fire | Immediately |
| Guard | inventory < util.Params.getDouble(Main.dealUnitsList, 0) |
| Transition | transition9 |
| Source/target | waitForBuyer=>onDeal1 |
| Fire | Signal event occurs |
| Signal event | WaitCompleteMsg |
| Action | applyWaitCompleteMsg((WaitCompleteMsg)getEvent()); isWaitingOnBuyer = false; |
| Transition | transition8 |
| Source/target | willDeliver=>travelToBuyer |
| Fire | If guard is open |
| Guard | willDeliver() |
| Action | sendDealerDeliversMsg(true); |
| Transition | transition7 |
| Source/target | onDeal1=>isBuyerWaiting2 |
| Fire | Timeout |
| Timeout | uniform(dealDelayMin, dealDelayMax) |
| Transition | transition6 |
| Source/target | willDeliver=>waitForBuyer |
| Fire | If all other guards are closed |
| Action | sendDealerDeliversMsg(false); isWaitingOnBuyer = true; |
| Transition | transition5 |
| Source/target | travelToHome=>available |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_HOME; |
| Transition | transition4 |
| Source/target | onDeal=>isBuyerWaiting4 |
| Fire | Timeout |
| Timeout | uniform(dealDelayMin, dealDelayMax) |
| Transition | transition3 |
| Source/target | travelToBuyer=>isBuyerWaiting3 |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = dealFromBuyer.buyerPlace; |
| Transition | transition2 |
| Source/target | available=>isBuyerWaiting |
| Fire | Signal event occurs |
| Signal event | DealRequestMsg |
| Action | applyDealRequestMsg((DealRequestMsg)getEvent()); |
| Transition | transition1 |
| Source/target | available=>offShift |
| Fire | Signal event occurs |
| Signal event | ShiftEndMsg |
| Transition | transition |
| Source/target | offShift=>onShift |
| Fire | Signal event occurs |
| Signal event | ShiftStartMsg |
| State | travelToHome |
| Deferred events | new ShiftEndEvent(), new DealRequestEvent() |
| Entry action | currentPlace = Main.PLACE_TRANSIT; travelToHome(); |
| State | onDeal1 |
| Deferred events | new ShiftEndEvent(), new DealRequestEvent() |
| State | waitForBuyer |
| Deferred events | new ShiftEndEvent(), new DealRequestEvent() |
| State | onDeal |
| Deferred events | new ShiftEndEvent(), new DealRequestEvent() |
| Exit action | |
| State | travelToBuyer |
| Deferred events | new ShiftEndEvent(), new DealRequestEvent() |
| Entry action | currentPlace = Main.PLACE_TRANSIT; possessionUnits = dealFromBuyer.units; travelToBuyer(); |
| State | available |
| Exit action | |
| State | harassed |
| Deferred events | new GenericEvent() |
| Entry action | isBeingHarassed = true; |
| Exit action | isBeingHarassed = false; |
| State | onShift |
| Entry action | isOnShift = true; |
| Exit action | isOnShift = false; isWaitingOnBuyer = false; denyPendingRequests(); if (isOnDeal) { sendDealDeniedMsg(dealFromBuyer); isOnDeal = false; } shiftEndTimer.reset(); |
| State | offShift |
| Entry action | currentPlace = Main.PLACE_HOME; |
| Exit action | |
| State | arrested |
| Entry action | currentPlace = Main.PLACE_JAIL; |
| State | active |
| Entry action | isActive = true; location.currentX = homeX; location.currentY = homeY; |
| Exit action | isActive = false; |
| Algorithmic Functions | |||||||||
| Name | applyArrestMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | location.stopTravel(); numArrests++; arrestDuration = msg.duration; updateInventory(-possessionUnits); possessionUnits = 0; |
||||||||
| Name | applyDealRequestMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | dealFromBuyer = msg; |
||||||||
| Name | applyHarassCompleteMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | // Nothing needs to be done. |
||||||||
| Name | applyHarassMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | location.stopTravel(); lastHarassTime = Engine.getTime(); |
||||||||
| Name | applyWaitCompleteMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | // Nothing needs to be done. |
||||||||
| Name | denyPendingRequests | ||||||||
| Type | void | ||||||||
| Body | List pendingEvents = simulationState.getEvents(); for (int i = 0; i < pendingEvents.size(); i++) { Object event = pendingEvents.get(i); if (event instanceof DealRequestMsg) { sendDealDeniedMsg((DealRequestMsg)event); } } |
||||||||
| Name | endDeal | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | // Record that we completed a deal with this customer. We do not // need to maintain the customer's location, so pass the dummy // coordinates (-1, -1). AgentHistory history = customerHistories.find(dealFromBuyer.customer); history.madeDeal(buyerWaiting, -1, -1); if (buyerWaiting) { // Notify the buyer that the deal is complete. DealCompleteMsg dealToBuyer = new DealCompleteMsg(); dealToBuyer.dealID = dealFromBuyer.dealID; dealToBuyer.units = dealFromBuyer.units; dealToBuyer.price = dealFromBuyer.price; dealFromBuyer.buyer.receiveDealCompleteMsg(dealToBuyer); // Apply the deal to the dealer's inventory and money. updateInventory(-dealToBuyer.units); updateMoney(dealToBuyer.price); // If we have made enough successful deals with this customer, // invite him to make direct deals. if (history.numGoodDeals == invitationDeals) { InviteBuyerMsg invitation = new InviteBuyerMsg(); invitation.privateDealer = self; dealFromBuyer.customer.receiveInviteBuyerMsg(invitation); } } // Note that we are no longer on a deal. isOnDeal = false; |
||||||||
| Name | getDrugsOnPerson | ||||||||
| Type | real | ||||||||
| Body | if (currentPlace == Main.PLACE_HOME) { return inventory; } else { return possessionUnits; } |
||||||||
| Name | getLastHarassTime | ||||||||
| Type | real | ||||||||
| Body | return lastHarassTime; |
||||||||
| Name | getLocation | ||||||||
| Type | Location | ||||||||
| Body | return location; |
||||||||
| Name | getQueueLength | ||||||||
| Type | integer | ||||||||
| Body | int length = 0; List pendingEvents = simulationState.getEvents(); for (int i = 0; i < pendingEvents.size(); i++) { Object event = pendingEvents.get(i); if (event instanceof DealRequestMsg) { length++; } } if (isOnDeal) { length++; } return length; |
||||||||
| Name | isAcceptingRequests | ||||||||
| Type | boolean | ||||||||
| Body | // isAcceptingRequests: Is the seller currently willing to accept // a deal request, either for immediate response or to add onto // his queue for a later response? return isOnShift && !isBeingHarassed(); |
||||||||
| Name | isBeingHarassed | ||||||||
| Type | boolean | ||||||||
| Body | return isBeingHarassed; |
||||||||
| Name | isInPublic | ||||||||
| Type | boolean | ||||||||
| Body | // isInPublic: Can the seller currently be seen in public? // Private dealers can be seen in public only when they are traveling // or when they are in the market delivering drugs. return currentPlace == Main.PLACE_TRANSIT || currentPlace == Main.PLACE_MARKET; |
||||||||
| Name | isWaitingOnBuyer | ||||||||
| Type | boolean | ||||||||
| Arguments |
|
||||||||
| Body | // isWaitingOnBuyer: Is this seller waiting for the buyer to take some // action before he can proceed with his own actions? return isWaitingOnBuyer && dealFromBuyer.dealID == dealID; |
||||||||
| Name | quitDeal | ||||||||
| Type | void | ||||||||
| Body | endDeal(false); sendDealDeniedMsg(dealFromBuyer); |
||||||||
| Name | receiveArrestMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | if (currentPlace != Main.PLACE_JAIL) { simulationState.fireEvent(msg); } |
||||||||
| Name | receiveDealRequestMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | if (isAcceptingRequests()) { simulationState.fireEvent(msg); } else { sendDealDeniedMsg(msg); } |
||||||||
| Name | receiveHarassCompleteMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | if (isBeingHarassed()) { simulationState.fireEvent(msg); } else { traceln("***WARNING in PrivateDealer.receiveHarassCompleteMsg(): " + self + " ignoring unexpected message @ " + Engine.getTime()); } |
||||||||
| Name | receiveHarassMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | if (!isBeingHarassed()) { simulationState.fireEvent(msg); } |
||||||||
| Name | receiveWaitCompleteMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | if (isWaitingOnBuyer(msg.dealID)) { simulationState.fireEvent(msg); } else { traceln("***WARNING in PrivateDealer.receiveWaitCompleteMsg(): " + self + " ignoring message about unexpected deal " + msg.dealID + " @ " + Engine.getTime()); } |
||||||||
| Name | sendDealDeniedMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | if (request.buyer.isWaitingOnSeller(request.dealID)) { DealDeniedMsg msg = new DealDeniedMsg(); msg.dealID = request.dealID; request.buyer.receiveDealDeniedMsg(msg); } |
||||||||
| Name | sendDealerDeliversMsg | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | DealerDeliversMsg msg = new DealerDeliversMsg(); msg.dealID = dealFromBuyer.dealID; msg.delivers = delivers; dealFromBuyer.buyer.receiveDealerDeliversMsg(msg); |
||||||||
| Name | sendWaitCompleteMsg | ||||||||
| Type | void | ||||||||
| Body | WaitCompleteMsg msg = new WaitCompleteMsg(); msg.dealID = dealFromBuyer.dealID; dealFromBuyer.buyer.receiveWaitCompleteMsg(msg); |
||||||||
| Name | startDeal | ||||||||
| Type | void | ||||||||
| Body | // Note that we are now on a deal. isOnDeal = true; // Record the buyer's location. buyerX = dealFromBuyer.buyer.getLocation().currentX; buyerY = dealFromBuyer.buyer.getLocation().currentY; // Make sure the customer is on the known customer list. customerHistories.add(dealFromBuyer.customer); // Let the buyer know the deal has started. DealStartMsg msg = new DealStartMsg(); msg.dealID = dealFromBuyer.dealID; dealFromBuyer.buyer.receiveDealStartMsg(msg); |
||||||||
| Name | travelToBuyer | ||||||||
| Type | void | ||||||||
| Body | // Begin traveling to the customer. Assume the travel // takes place at driving speed (car, bus, etc.). location.travel(buyerX, buyerY, Main.TRAVEL_DRIVE); |
||||||||
| Name | travelToHome | ||||||||
| Type | void | ||||||||
| Body | // Begin traveling home. Assume the travel takes // place at driving speed (car, bus, etc.). location.travel(homeX, homeY, Main.TRAVEL_DRIVE); |
||||||||
| Name | updateInventory | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | inventory += inventoryChange; if (inventory < 0) { traceln("***ERROR in PrivateDealer.updateInventory(): Negative inventory for " + self + " @ " + Engine.getTime()); } |
||||||||
| Name | updateMoney | ||||||||
| Type | void | ||||||||
| Arguments |
|
||||||||
| Body | money += moneyChange; if (money < 0) { traceln("***ERROR in PrivateDealer.updateMoney(): Negative money for " + self + " @ " + Engine.getTime()); } |
||||||||
| Name | willAcceptDeal | ||||||||
| Type | boolean | ||||||||
| Arguments |
|
||||||||
| Body | // willAcceptDeal: Will the seller sell the buyer the requested // amount of drugs at the requested price? // Private dealers will accept the deal as long as they have enough // inventory to cover the requested amount of drugs. // // They should probably also verify that the price is appropriate // for the drug amount. For now it's not necessary, though, because // all deals are initiated using the same pricing structure. return inventory >= units; |
||||||||
| Name | willDeliver | ||||||||
| Type | boolean | ||||||||
| Body | if (dealFromBuyer.units >= acceptableDeliverUnits) { if (dealFromBuyer.buyerPlace == Main.PLACE_MARKET) { return randomTrue(probDeliverMarket); } else if (dealFromBuyer.buyerPlace == Main.PLACE_HOME) { return randomTrue(probDeliverHome); } else if (dealFromBuyer.buyerPlace == Main.PLACE_PRIVATE_DEALER) { return false; } else { traceln("***ERROR in PrivateDealer.willDeliver: Unexpected currentPlace (" + dealFromBuyer.buyerPlace + ") for " + dealFromBuyer.buyer + " detected by " + self + " @ " + Engine.getTime()); return false; } } else { return false; } |
||||||||
| Animation | |
| Name | animation |
| X | 0 |
| Y | 0 |
| Additional class code | public boolean isSelected = false; |
| Picture | ![]() |
| Rectangle | agentShape |
| X | main.animation.getAgentLocationX(main.AGENT_PRIVATE_DEALER, isSelected, location.currentX) |
| Y | main.animation.getAgentLocationY(main.AGENT_PRIVATE_DEALER, isSelected, location.currentY) |
| Width | main.animation.getAgentSize(main.AGENT_PRIVATE_DEALER, isSelected) |
| Height | main.animation.getAgentSize(main.AGENT_PRIVATE_DEALER, isSelected) |
| Fill color | main.animation.getAgentFillColor(main.AGENT_PRIVATE_DEALER, isSelected) |
| Line color | main.animation.getAgentLineColor(main.AGENT_PRIVATE_DEALER, isSelected) |
| Line width | main.animation.getAgentLineWidth(main.AGENT_PRIVATE_DEALER, isSelected) |
| Visible | isOnShift && main.animation.getAgentVisibility(main.AGENT_PRIVATE_DEALER, isSelected, location.currentX, location.currentY) |
| General | |
| Import | import message.*; import misc.*; |
| Parameters | |
| Name | initialMarket |
| Type | Market |
| Name | initialConcentration |
| Type | real |
| Name | initialAddiction |
| Type | real |
| Name | metabolismRate |
| Type | real |
| Name | addictionIncreaseDuration |
| Type | real |
| Name | addictionIncreaseRate |
| Type | real |
| Name | addictionDecreaseOnset |
| Type | real |
| Name | addictionDecreaseRate |
| Type | real |
| Name | visionRadius |
| Type | real |
| Name | probTryPrivateDealer |
| Type | real |
| Name | acceptableSdQueueLength |
| Type | integer |
| Name | acceptablePdQueueLength |
| Type | integer |
| Name | initialTimeSinceLastUse |
| Type | real |
| Name | probUseTogether |
| Type | real |
| Name | initialHIV |
| Type | boolean |
| Name | marketQuitTime |
| Type | real |
| Name | useDelayMin |
| Type | real |
| Name | useDelayMax |
| Type | real |
| Icon | |
| Picture | |
| Structure | |||||||||||||||||||||||||||||||
| Picture | ![]() |
||||||||||||||||||||||||||||||
| ChartTimer | dailyTimer | ||||||||||||||||||||||||||||||
| Timeout | util.Units.days(1) | ||||||||||||||||||||||||||||||
| Expire At Startup | Yes | ||||||||||||||||||||||||||||||
| Expiry Action | // Each day, street brokers start their "shifts" sometime during // the time period that they know the street dealers tend to // enter the market. They end their shifts sometime during the // time period that they know the street dealers tend to leave // the market. // // They choose these times not so much because that's when street // dealers will be around, but because that's when customers will // be around. If the street dealers aren't there, they can still // go to a private dealer. if (isActive) { double earlyStartHour = util.Params.getDouble(Main.sdShiftStartRange, 0); double lateStartHour = util.Params.getDouble(Main.sdShiftStartRange, 1); double shiftStartHour = util.Units.hours(uniform(earlyStartHour, lateStartHour)); shiftStartTimer.restart(shiftStartHour); double earlyEndHour = util.Params.getDouble(Main.sdShiftEndRange, 0); double lateEndHour = util.Params.getDouble(Main.sdShiftEndRange, 1); shiftEndTime = Engine.getTime() + util.Units.hours(uniform(earlyEndHour, lateEndHour)); } |
||||||||||||||||||||||||||||||
| ChartTimer | shiftStartTimer | ||||||||||||||||||||||||||||||
| Expire | No (manual mode) | ||||||||||||||||||||||||||||||
| Expiry Action | simulationState.fireEvent(new ShiftStartMsg()); |
||||||||||||||||||||||||||||||
| ChartTimer | dealQuitTimer | ||||||||||||||||||||||||||||||
| Expire | No (manual mode) | ||||||||||||||||||||||||||||||
| Expiry Action | DealDeniedMsg msg = new DealDeniedMsg(); msg.dealID = dealToSeller.dealID; self.receiveDealDeniedMsg(msg); |
||||||||||||||||||||||||||||||
| Variable | shiftEndTime | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Variable | isUsingAlone | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | isOnDeal | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | isUsingWithBuyer | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | isWaitingOnBuyer | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | dealToSeller | ||||||||||||||||||||||||||||||
| Variable type | DealRequestMsg | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | pendingInvitations | ||||||||||||||||||||||||||||||
| Variable type | List | ||||||||||||||||||||||||||||||
| Initial value | new ArrayList() | ||||||||||||||||||||||||||||||
| Variable | lastHarassTime | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | isWaitingOnSeller | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | isBeingHarassed | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | numArrests | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | arrestDuration | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Variable | main | ||||||||||||||||||||||||||||||
| Variable type | Main | ||||||||||||||||||||||||||||||
| Initial value | (Main)getOwner() | ||||||||||||||||||||||||||||||
| Variable | visibleStreetDealersIterator | ||||||||||||||||||||||||||||||
| Variable type | Iterator | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | visibleStreetDealers | ||||||||||||||||||||||||||||||
| Variable type | List | ||||||||||||||||||||||||||||||
| Initial value | new ArrayList() | ||||||||||||||||||||||||||||||
| Variable | currentPlace | ||||||||||||||||||||||||||||||
| Variable type | integer | ||||||||||||||||||||||||||||||
| Initial value | Main.PLACE_MARKET | ||||||||||||||||||||||||||||||
| Variable | marketStartTime | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | targetSellerY | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | targetSellerX | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | money | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Initial value | 0 | ||||||||||||||||||||||||||||||
| Variable | targetSellerHistory | ||||||||||||||||||||||||||||||
| Variable type | AgentHistory | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | dealFromSeller | ||||||||||||||||||||||||||||||
| Variable type | DealCompleteMsg | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | isActive | ||||||||||||||||||||||||||||||
| Variable type | boolean | ||||||||||||||||||||||||||||||
| Initial value | false | ||||||||||||||||||||||||||||||
| Variable | customerY | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Variable | customerX | ||||||||||||||||||||||||||||||
| Variable type | real | ||||||||||||||||||||||||||||||
| Variable | targetSeller | ||||||||||||||||||||||||||||||
| Variable type | Seller | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | dealFromBuyer | ||||||||||||||||||||||||||||||
| Variable type | DealRequestMsg | ||||||||||||||||||||||||||||||
| Initial value | null | ||||||||||||||||||||||||||||||
| Variable | self | ||||||||||||||||||||||||||||||
| Variable type | StreetBroker | ||||||||||||||||||||||||||||||
| Initial value | this | ||||||||||||||||||||||||||||||
| Variable | market | ||||||||||||||||||||||||||||||
| Variable type | Market | ||||||||||||||||||||||||||||||
| Initial value | initialMarket | ||||||||||||||||||||||||||||||
| Port | travelCompleteListener | ||||||||||||||||||||||||||||||
| Message type | TravelCompleteMsg | ||||||||||||||||||||||||||||||
| Port | wantFixListener | ||||||||||||||||||||||||||||||
| Message type | WantFixMsg | ||||||||||||||||||||||||||||||
| Statechart | simulationState | ||||||||||||||||||||||||||||||
| Object | allTransactions | ||||||||||||||||||||||||||||||
| Type | misc.TransactionCounter | ||||||||||||||||||||||||||||||
| Object | sdTransactions | ||||||||||||||||||||||||||||||
| Type | misc.TransactionCounter | ||||||||||||||||||||||||||||||
| Object | pdTransactions | ||||||||||||||||||||||||||||||
| Type | misc.TransactionCounter | ||||||||||||||||||||||||||||||
| Object | location | ||||||||||||||||||||||||||||||
| Type | misc.Location | ||||||||||||||||||||||||||||||
| Parameters |
|
||||||||||||||||||||||||||||||
| Object | userBehavior | ||||||||||||||||||||||||||||||
| Type | misc.UserBehavior | ||||||||||||||||||||||||||||||
| Parameters |
|
||||||||||||||||||||||||||||||
| Object | privateDealerHistories | ||||||||||||||||||||||||||||||
| Type | misc.AgentHistoryList | ||||||||||||||||||||||||||||||
| Object | streetDealerHistories | ||||||||||||||||||||||||||||||
| Type | misc.AgentHistoryList | ||||||||||||||||||||||||||||||
| Statechart | |
| Name | simulationState |
| Picture | ![]() |
| ChoicePoint | checkStreetDealer |
| Action | checkStreetDealer(); |
| ChoicePoint | seekStreetDealer |
| Action | seekStreetDealer(); |
| ChoicePoint | chooseStreetDealer |
| Action | chooseStreetDealer(); |
| ChoicePoint | seekPrivateDealer |
| Action | seekPrivateDealer(); |
| History | preHarassed |
| Type | Shallow |
| Action | // NOTE: // // Due to a bug in AnyLogic 5, a deep history state // will not transition to a simple state that is // inside a composite state when the composite state // is on the same level as the deep history state. // Instead, it will cause a runtime error. Therefore // we avoid deep history states and live with the // limitations of shallow history states. |
| Transition | transition58 |
| Source/target | isMarketOpen=>chooseStreetDealer |
| Fire | If guard is open |
| Guard | market.isOpen |
| Transition | transition56 |
| Source/target | wasDealMade1=>randomWalk1 |
| Fire | If all other guards are closed |
| Action | endCustomerDeal(true, false); |
| Transition | transition50 |
| Source/target | wasDealMade1=>giveToCustomer |
| Fire | If guard is open |
| Guard | dealFromSeller != null |
| Action | isWaitingOnBuyer = true; endCustomerDeal(true, true); |
| Transition | transition53 |
| Source/target | wasDealMade=>useAlone |
| Fire | If guard is open |
| Guard | dealFromSeller != null |
| Action | endCustomerDeal(false, true); isUsingAlone = true; useAlone(); |
| Transition | transition52 |
| Source/target | isBuyerWaiting1=>wasDealMade |
| Fire | If all other guards are closed |
| Transition | transition51 |
| Source/target | isBuyerWaiting1=>wasDealMade1 |
| Fire | If guard is open |
| Guard | dealFromBuyer.buyer.isWaitingOnSeller(dealFromBuyer.dealID) |
| Transition | transition49 |
| Source/target | willAcceptDeal=>randomWalk1 |
| Fire | If all other guards are closed |
| Action | sendDealDeniedMsg(dealFromBuyer, 0); |
| Transition | transition48 |
| Source/target | isBuyerWaiting=>willAcceptDeal |
| Fire | If guard is open |
| Guard | dealFromBuyer.buyer.isWaitingOnSeller(dealFromBuyer.dealID) |
| Transition | transition47 |
| Source/target | isBuyerWaiting=>randomWalk1 |
| Fire | If all other guards are closed |
| Transition | transition46 |
| Source/target | randomWalk1=>isBuyerWaiting |
| Fire | Signal event occurs |
| Signal event | DealRequestMsg |
| Action | applyDealRequestMsg((DealRequestMsg)getEvent()); |
| Transition | transition45 |
| Source/target | travelToMarket=>isMarketOpen |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_MARKET; marketStartTime = Engine.getTime(); setupKnownStreetDealers(); |
| Transition | transition44 |
| Source/target | harassed=>preHarassed |
| Fire | Signal event occurs |
| Signal event | HarassCompleteMsg |
| Action | applyHarassCompleteMsg((HarassCompleteMsg)getEvent()); |
| Transition | transition55 |
| Source/target | state=>harassed |
| Fire | Signal event occurs |
| Signal event | HarassMsg |
| Action | applyHarassMsg((HarassMsg)getEvent()); |
| Transition | transition43 |
| Source/target | waitForPrivateDealer=>seekPrivateDealer |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition57 |
| Source/target | arrested=>active |
| Fire | Timeout |
| Timeout | arrestDuration |
| Transition | transition54 |
| Source/target | active=>arrested |
| Fire | Signal event occurs |
| Signal event | ArrestMsg |
| Action | applyArrestMsg((ArrestMsg)getEvent()); |
| Transition | transition42 |
| Source/target | useAlone=>randomWalk1 |
| Fire | Timeout |
| Timeout | uniform(useDelayMin, useDelayMax) |
| Action | isUsingAlone = false; |
| Transition | transition41 |
| Source/target | seekStreetDealer=>seekStreetDealer |
| Fire | Signal event occurs |
| Guard | targetSeller != null && dealToSeller == null |
| Action | applyDealDeniedMsg(new DealDeniedMsg()); |
| Transition | transition40 |
| Source/target | startPrivateDeal=>seekPrivateDealer |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition37 |
| Source/target | seekPrivateDealer=>startPrivateDeal |
| Fire | Signal event occurs |
| Guard | targetSeller != null && dealToSeller != null |
| Signal event | TargetFoundMsg |
| Action | isWaitingOnSeller = true; sendDealRequestMsg(); |
| Transition | transition39 |
| Source/target | startStreetDeal=>isMarketOpen |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition38 |
| Source/target | checkStreetDealer=>startStreetDeal |
| Fire | Signal event occurs |
| Guard | dealToSeller != null |
| Action | isWaitingOnSeller = true; sendDealRequestMsg(); |
| Transition | transition36 |
| Source/target | seekStreetDealer=>startStreetDeal1 |
| Fire | Signal event occurs |
| Guard | targetSeller != null && dealToSeller != null |
| Action | isWaitingOnSeller = true; sendDealRequestMsg(); |
| Transition | transition35 |
| Source/target | randomWalk=>seekPrivateDealer |
| Fire | Immediately |
| Guard | !market.isOpen || Engine.getTime() - marketStartTime > marketQuitTime |
| Action | setupKnownPrivateDealers(); |
| Transition | transition34 |
| Source/target | willSeekPrivateDealer=>travelToMarket |
| Fire | If all other guards are closed |
| Transition | transition33 |
| Source/target | willSeekPrivateDealer=>seekPrivateDealer |
| Fire | If guard is open |
| Guard | willSeekPrivateDealer() |
| Action | setupKnownPrivateDealers(); |
| Transition | transition32 |
| Source/target | onStreetDeal1=>travelToCustomer |
| Fire | Signal event occurs |
| Signal event | DealCompleteMsg |
| Action | applyDealCompleteMsg((DealCompleteMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition30 |
| Source/target | onStreetDeal1=>seekStreetDealer |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition16 |
| Source/target | onStreetDeal=>isMarketOpen |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition25 |
| Source/target | onStreetDeal=>travelToCustomer |
| Fire | Signal event occurs |
| Signal event | DealCompleteMsg |
| Action | applyDealCompleteMsg((DealCompleteMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition29 |
| Source/target | useWithCustomer=>randomWalk1 |
| Fire | Signal event occurs |
| Signal event | UseTogetherCompleteMsg |
| Action | applyUseTogetherCompleteMsg((UseTogetherCompleteMsg)getEvent()); // Waiting until we receive a UseTogetherCompleteMsg before calling // useWithCustomer() means that we will not call useWithCustomer() // if we are arrested while waiting for the message to come through. // In other words, if we are arrested in the process of using drugs, // the model will assume we did not use any drugs at all. // // The other option is to call useWithCustomer() as soon as we receive // the UseTogetherMsg. In this case, if we are arrested in the process // of using drugs, the model will assume that we used all of our drugs. // Neither situation is realistic. // // The useWithCustomer() call was placed here for a practical reason. // useWithCustomer() needs to check that the drug partner is also in // a useTogether state, and by waiting until this point to call // useWithCustomer(), we can be sure that the drug partner has had // an opportunity to set his status variables properly. useWithCustomer(); isWaitingOnBuyer = false; isUsingWithBuyer = false; |
| Transition | transition27 |
| Source/target | giveToCustomer=>useWithCustomer |
| Fire | Signal event occurs |
| Guard | ((UseTogetherMsg)getEvent()).uses |
| Signal event | UseTogetherMsg |
| Action | applyUseTogetherMsg((UseTogetherMsg)getEvent()); isWaitingOnBuyer = true; isUsingWithBuyer = true; |
| Transition | transition26 |
| Source/target | giveToCustomer=>useAlone |
| Fire | Signal event occurs |
| Guard | !((UseTogetherMsg)getEvent()).uses |
| Signal event | UseTogetherMsg |
| Action | applyUseTogetherMsg((UseTogetherMsg)getEvent()); isWaitingOnBuyer = false; isUsingAlone = true; useAlone(); |
| Transition | transition22 |
| Source/target | onPrivateDeal=>seekPrivateDealer |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition21 |
| Source/target | checkStreetDealer=>isMarketOpen |
| Fire | Signal event occurs |
| Guard | dealToSeller == null |
| Action | applyDealDeniedMsg(new DealDeniedMsg()); |
| Transition | transition14 |
| Source/target | startStreetDeal1=>seekStreetDealer |
| Fire | Signal event occurs |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg((DealDeniedMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition2 |
| Source/target | seekPrivateDealer=>seekPrivateDealer |
| Fire | Signal event occurs |
| Guard | targetSeller != null && dealToSeller == null |
| Signal event | DealDeniedMsg |
| Action | applyDealDeniedMsg(new DealDeniedMsg()); |
| Transition | transition1 |
| Source/target | startStreetDeal1=>onStreetDeal1 |
| Fire | Signal event occurs |
| Signal event | DealStartMsg |
| Action | applyDealStartMsg((DealStartMsg)getEvent()); isWaitingOnSeller = true; |
| Transition | transition24 |
| Source/target | travelToPrivateDealer=>onPrivateDeal |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_PRIVATE_DEALER; isWaitingOnSeller = true; sendWaitCompleteMsgToSeller(); |
| Transition | transition23 |
| Source/target | waitForPrivateDealer=>onPrivateDeal |
| Fire | Signal event occurs |
| Signal event | WaitCompleteMsg |
| Action | applyWaitCompleteMsg((WaitCompleteMsg)getEvent()); isWaitingOnSeller = true; |
| Transition | transition19 |
| Source/target | startPrivateDeal=>waitForPrivateDealer |
| Fire | Signal event occurs |
| Guard | ((DealerDeliversMsg)getEvent()).delivers |
| Signal event | DealerDeliversMsg |
| Action | applyDealerDeliversMsg((DealerDeliversMsg)getEvent()); isWaitingOnSeller = true; |
| Transition | transition20 |
| Source/target | startPrivateDeal=>travelToPrivateDealer |
| Action | applyDealerDeliversMsg((DealerDeliversMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition18 |
| Source/target | isMarketOpen=>travelToCustomer |
| Transition | transition13 |
| Source/target | travelToStreetDealer=>checkStreetDealer |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Transition | transition12 |
| Source/target | chooseStreetDealer=>seekStreetDealer |
| Fire | Signal event occurs |
| Guard | targetSeller == null |
| Signal event | TargetFoundMsg |
| Action | setupVisibleStreetDealers(); |
| Transition | transition11 |
| Source/target | chooseStreetDealer=>travelToStreetDealer |
| Fire | Signal event occurs |
| Guard | targetSeller != null |
| Transition | transition8 |
| Source/target | idle=>randomWalk1 |
| Fire | Signal event occurs |
| Signal event | ShiftStartMsg |
| Transition | transition7 |
| Source/target | randomWalk1=>idle |
| Fire | Immediately |
| Guard | !market.isOpen && Engine.getTime() > shiftEndTime |
| Action | denyPendingRequests(); location.travel(location.startX, location.startY, Main.TRAVEL_WALK); |
| Transition | transition9 |
| Source/target | randomWalk1=>randomWalk1 |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Transition | transition6 |
| Source/target | startStreetDeal=>onStreetDeal |
| Fire | Signal event occurs |
| Signal event | DealStartMsg |
| Action | applyDealStartMsg((DealStartMsg)getEvent()); isWaitingOnSeller = true; |
| Transition | transition31 |
| Source/target | randomWalk=>seekStreetDealer |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | setupVisibleStreetDealers(); |
| Transition | transition28 |
| Source/target | seekStreetDealer=>randomWalk |
| Fire | Signal event occurs |
| Guard | targetSeller == null |
| Transition | transition5 |
| Source/target | wasDealMade=>randomWalk1 |
| Fire | If all other guards are closed |
| Action | endCustomerDeal(false, false); |
| Transition | transition4 |
| Source/target | travelToCustomer=>isBuyerWaiting1 |
| Fire | Signal event occurs |
| Signal event | TravelCompleteMsg |
| Action | currentPlace = Main.PLACE_MARKET; market.addStreetBroker(self); |
| Transition | transition3 |
| Source/target | onPrivateDeal=>travelToCustomer |
| Fire | Signal event occurs |
| Signal event | DealCompleteMsg |
| Action | applyDealCompleteMsg((DealCompleteMsg)getEvent()); isWaitingOnSeller = false; |
| Transition | transition |
| Source/target | willAcceptDeal=>willSeekPrivateDealer |
| Fire | Signal event occurs |
| Guard | willAcceptDeal(dealFromBuyer.buyer, dealFromBuyer.units, dealFromBuyer.price) |
| Signal event | DealRequestMsg |
| Action | startCustomerDeal(); |
| Transition | transition15 |
| Source/target | seekPrivateDealer=>travelToMarket |
| Fire | Signal event occurs |
| Guard | targetSeller == null |
| State | randomWalk1 |
| Entry action | location.wanderInMarket(market); |
| State | travelToStreetDealer |
| Deferred events | new DealRequestEvent() |
| Entry action | travelToStreetDealer(); |
| State | travelToPrivateDealer |
| Deferred events | new DealRequestEvent(), new DealDeniedEvent() |
| Entry action | market.removeStreetBroker(self); travelToPrivateDealer(); |
| State | waitForPrivateDealer |
| Deferred events | new DealRequestEvent(), new DealDeniedEvent() |
| Entry action | dealQuitTimer.restart(Main.sbDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | onPrivateDeal |
| Deferred events | new DealRequestEvent() |
| Entry action | dealQuitTimer.restart(Main.sbDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | randomWalk |
| Deferred events | new DealRequestEvent() |
| Entry action | wanderInMarket(); |
| State | giveToCustomer |
| Deferred events | new DealRequestEvent() |
| State | travelToCustomer |
| Deferred events | new DealRequestEvent() |
| Entry action | travelToCustomer(); |
| State | useWithCustomer |
| Deferred events | new DealRequestEvent() |
| State | onStreetDeal |
| Deferred events | new DealRequestEvent() |
| Entry action | dealQuitTimer.restart(Main.sbDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | onStreetDeal1 |
| Deferred events | new DealRequestEvent() |
| Entry action | dealQuitTimer.restart(Main.sbDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | startStreetDeal |
| Deferred events | new DealRequestEvent() |
| Entry action | dealQuitTimer.restart(Main.sbDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | startStreetDeal1 |
| Deferred events | new DealRequestEvent() |
| Entry action | dealQuitTimer.restart(Main.sbDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | startPrivateDeal |
| Deferred events | new DealRequestEvent() |
| Entry action | dealQuitTimer.restart(Main.sbDealQuitTime); |
| Exit action | dealQuitTimer.reset(); |
| State | useAlone |
| Deferred events | new DealRequestEvent() |
| Exit action | |
| State | travelToMarket |
| Deferred events | new DealRequestEvent() |
| Entry action | travelToMarket(); |
| State | harassed |
| Deferred events | new GenericEvent() |
| Entry action | isBeingHarassed = true; |
| Exit action | isBeingHarassed = false; |
| State | arrested |
| Entry action | currentPlace = Main.PLACE_JAIL; |
| State | active |
| Entry action | isActive = true; currentPlace = Main.PLACE_MARKET; location.currentX = location.startX; location.currentY = location.startY; market.addStreetBroker(self); |
| Exit action | isActive = false; isOnDeal = false; isWaitingOnSeller = false; isWaitingOnBuyer = false; isUsingAlone = false; isUsingWithBuyer = false; market.removeStreetBroker(self); |
| Algorithmic Functions | |||||||
| Name | applyArrestMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | location.stopTravel(); numArrests++; arrestDuration = msg.duration; updateInventory(-userBehavior.inventory); |
||||||
| Name | applyDealCompleteMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | dealFromSeller = msg; updateInventory(dealFromSeller.units); updateMoney(-dealFromSeller.price); // Update the street broker's history with this seller. targetSellerHistory.madeDeal(true, targetSellerX, targetSellerY); // Update transaction counters. allTransactions.addGood(dealFromSeller.units, dealFromSeller.price); main.sbAllTransactions.addGood(dealFromSeller.units, dealFromSeller.price); if (targetSeller instanceof StreetDealer) { sdTransactions.addGood(dealFromSeller.units, dealFromSeller.price); main.sbSdTransactions.addGood(dealFromSeller.units, dealFromSeller.price); } else if (targetSeller instanceof PrivateDealer) { pdTransactions.addGood(dealFromSeller.units, dealFromSeller.price); main.sbPdTransactions.addGood(dealFromSeller.units, dealFromSeller.price); } else { traceln("***ERROR in StreetBroker.receiveDealCompleteMsg(): Unexpected seller type for " + self + " @ " + Engine.getTime()); } |
||||||
| Name | applyDealDeniedMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | // Update the street broker's history with this seller. targetSellerHistory.madeDeal(false, targetSellerX, targetSellerY); // Update transaction counters. allTransactions.addFailed(); main.sbAllTransactions.addFailed(); if (targetSeller instanceof StreetDealer) { sdTransactions.addFailed(); main.sbSdTransactions.addFailed(); } else if (targetSeller instanceof PrivateDealer) { pdTransactions.addFailed(); main.sbPdTransactions.addFailed(); } else { traceln("***ERROR in StreetBroker.receiveDealDeniedMsg(): Unexpected seller type for " + self + " @ " + Engine.getTime()); } |
||||||
| Name | applyDealRequestMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | dealFromBuyer = msg; |
||||||
| Name | applyDealStartMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | // Nothing needs to be done. |
||||||
| Name | applyDealerDeliversMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | // Nothing needs to be done. |
||||||
| Name | applyHarassCompleteMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | // Nothing needs to be done. |
||||||
| Name | applyHarassMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | location.stopTravel(); lastHarassTime = Engine.getTime(); |
||||||
| Name | applyUseTogetherCompleteMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | // Nothing needs to be done. |
||||||
| Name | applyUseTogetherMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | // Nothing needs to be done. |
||||||
| Name | applyWaitCompleteMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | // Nothing needs to be done. |
||||||
| Name | checkStreetDealer | ||||||
| Type | void | ||||||
| Body | dealToSeller = null; StreetDealer sd = (StreetDealer)targetSeller; // Bail out without creating a deal request under certain conditions. if (!sd.isInPublic()) return; if (location.distance(sd.location.currentX, sd.location.currentY) > max(visionRadius, sd.visionRadius)) return; if (sd instanceof User && ((User)sd).isUsing()) return; if (((PoliceTarget)sd).isBeingHarassed()) return; if (!isQueueLengthAcceptable(sd)) return; createDealRequestMsg(); |
||||||
| Name | chooseStreetDealer | ||||||
| Type | void | ||||||
| Body | // We expect this method to be called repeatedly, with each new call // returning the next dealer in the list until an available dealer is // found. targetSeller = null; if (streetDealerHistories.hasNext()) { targetSellerHistory = streetDealerHistories.next(); if (Main.sbCheckAllKnownSd || streetDealerHistories.indexOf(targetSellerHistory.agent) < Main.sbNumKnownSdToCheck ) { targetSeller = (Seller)targetSellerHistory.agent; // In this case we do not yet know where the dealer is because // we are not standing in front of him. Therefore we have to // guess. Compare this to the seekStreetDealer function. if (targetSellerHistory.lastDeal > 0) { // We have made a deal with this dealer since the model started, // so guess that he is at the same place he was when we made // that deal. targetSellerX = targetSellerHistory.lastDealX; targetSellerY = targetSellerHistory.lastDealY; } else { // We have not made a deal with this dealer since the model // started, so assume that we know his most recent market // location and guess that. StreetDealer sd = (StreetDealer)targetSellerHistory.agent; targetSellerX = sd.marketX; targetSellerY = sd.marketY; } } } |
||||||
| Name | createDealRequestMsg | ||||||
| Type | void | ||||||
| Body | dealToSeller = new DealRequestMsg(); dealToSeller.dealID = main.getNewDealID(); dealToSeller.units = dealFromBuyer.units; dealToSeller.price = dealFromBuyer.price; dealToSeller.customer = dealFromBuyer.customer; dealToSeller.buyer = self; dealToSeller.buyerPlace = currentPlace; |
||||||
| Name | denyPendingRequests | ||||||
| Type | void | ||||||
| Body | List pendingEvents = simulationState.getEvents(); for (int i = 0; i < pendingEvents.size(); i++) { Object event = pendingEvents.get(i); if (event instanceof DealRequestMsg) { sendDealDeniedMsg((DealRequestMsg)event, 0); } } |
||||||
| Name | endCustomerDeal | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | if (buyerWaiting) { if (dealMade) { // Calculate the tip for the deal. double tip = util.Math.round(dealFromSeller.units * Main.sbTipPercent / 100, Main.useIncrement); tip = min(tip, Main.sbTipUpperBound); tip = max(tip, Main.sbTipLowerBound); // The broker is about to give the drugs back to the customer, // so subtract the drug amount (minus the tip) from his inventory. updateInventory(-(dealFromSeller.units - tip)); // Send the completed deal info to the buyer. DealCompleteMsg dealToBuyer = new DealCompleteMsg(); dealToBuyer.dealID = dealFromBuyer.dealID; dealToBuyer.units = dealFromSeller.units - tip; dealToBuyer.price = dealFromSeller.price; dealFromBuyer.buyer.receiveDealCompleteMsg(dealToBuyer); } else { // The broker was not able to find a seller, so return the // customer's money. updateMoney(-dealFromBuyer.price); sendDealDeniedMsg(dealFromBuyer, dealFromBuyer.price); } } isOnDeal = false; |
||||||
| Name | getDrugsOnPerson | ||||||
| Type | real | ||||||
| Body | return userBehavior.inventory; |
||||||
| Name | getLastHarassTime | ||||||
| Type | real | ||||||
| Body | return lastHarassTime; |
||||||
| Name | getLocation | ||||||
| Type | Location | ||||||
| Body | return location; |
||||||
| Name | getQueueLength | ||||||
| Type | integer | ||||||
| Body | int length = 0; List pendingEvents = simulationState.getEvents(); for (int i = 0; i < pendingEvents.size(); i++) { Object event = pendingEvents.get(i); if (event instanceof DealRequestMsg) { length++; } } if (isOnDeal) { length++; } return length; |
||||||
| Name | hasHIV | ||||||
| Type | boolean | ||||||
| Body | return userBehavior.hasHIV; |
||||||
| Name | isAcceptingRequests | ||||||
| Type | boolean | ||||||
| Body | // isAcceptingRequests: Is the seller currently willing to accept // a deal request, either for immediate response or to add onto // his queue for a later response? return market.isOpen && !isBeingHarassed() && !(isUsingAlone || isUsingWithBuyer) ; |
||||||
| Name | isBeingHarassed | ||||||
| Type | boolean | ||||||
| Body | return isBeingHarassed; |
||||||
| Name | isInPublic | ||||||
| Type | boolean | ||||||
| Body | // isInPublic: Can the seller currently be seen in public? // Street brokers are in public when they are traveling or when they are // in the market. return currentPlace == Main.PLACE_TRANSIT || currentPlace == Main.PLACE_MARKET; |
||||||
| Name | isQueueLengthAcceptable | ||||||
| Type | boolean | ||||||
| Arguments |
|
||||||
| Body | int acceptableQueueLength = 0; if (seller instanceof StreetDealer) { acceptableQueueLength = acceptableSdQueueLength; } else if (seller instanceof PrivateDealer) { acceptableQueueLength = acceptablePdQueueLength; } else { traceln("***ERROR in StreetBroker.isQueueLengthAcceptable(): Unexpected seller type for " + self + " @ " + Engine.getTime()); return false; } return targetSeller.getQueueLength() <= acceptableQueueLength; |
||||||
| Name | isUsing | ||||||
| Type | boolean | ||||||
| Body | // isUsing: Is this user currently using drugs? return isUsingAlone || isUsingWithBuyer; |
||||||
| Name | isUsingTogether | ||||||
| Type | boolean | ||||||
| Arguments |
|
||||||
| Body | // isUsingTogether: Is this user using drugs with another user as // a result of the specified deal? return isUsingWithBuyer && dealFromBuyer.dealID == dealID; |
||||||
| Name | isWaitingOnBuyer | ||||||
| Type | boolean | ||||||
| Arguments |
|
||||||
| Body | // isWaitingOnBuyer: Is this seller waiting for the buyer to take some // action before he can proceed with his own actions? return isWaitingOnBuyer && dealFromBuyer.dealID == dealID; |
||||||
| Name | isWaitingOnSeller | ||||||
| Type | boolean | ||||||
| Arguments |
|
||||||
| Body | // isWaitingOnSeller: Is this buyer waiting for the seller to take some // action before he can proceed with his own actions? return isWaitingOnSeller && dealToSeller.dealID == dealID; |
||||||
| Name | processPendingInvitations | ||||||
| Type | void | ||||||
| Body | // See the discussion in Customer.receiveInviteBuyerMsg() for an // explanation of this function. for (int i = 0; i < pendingInvitations.size(); i++) { PrivateDealer pd = (PrivateDealer)pendingInvitations.get(i); privateDealerHistories.add(pd); } pendingInvitations.clear(); |
||||||
| Name | receiveArrestMsg | ||||||
| Type | void | ||||||
| Arguments |
|
||||||
| Body | if (currentPlace != Main.PLACE_JAIL) { simulationState.fireEvent(msg); } |
||||||
| Name | receiveDealCom | ||||||