Package jmt.gui.jmodel.JGraphMod

Source Code of jmt.gui.jmodel.JGraphMod.GraphicalQueueState

/**
  * Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano

  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.

  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.

  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */

package jmt.gui.jmodel.JGraphMod;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Arc2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.Vector;

import jmt.gui.common.Defaults;
import jmt.gui.common.definitions.ClassDefinition;
import jmt.gui.common.distributions.Distribution;
import jmt.gui.common.resources.JMTImageLoader;
import jmt.gui.jmodel.controller.Mediator;
import jmt.gui.jmodel.controller.ModelSnapshot;

/**
* <p>Title: GraphicalQueueState</p>
* <p>Description: this class is used to graphically update thestate of queues
* and utilizations</p>
*
* @author Francesco D'Aquino
*         Date: 22-feb-2006
*         Time: 09.09.21

* Modyfied by Bertoli Marco to support JGraph 5.8 - 21/mar/2006
* Modyfied by Bertoli Marco to greatly speed up everything - 18/may/2006

*/
public class GraphicalQueueState {
  private Mediator mediator;
  private HashMap<Object, JmtCell> tm; // Used to map station keys to their cells
  private int oldModel;

  public GraphicalQueueState(Mediator m) {
    mediator = m;
    tm = new HashMap<Object, JmtCell>();
    // Initialize mapping between station keys and their cell components
    // All cells (included blocking regions children)
    Object[] cells = m.getGraph().getDescendants(m.getGraph().getRoots());
    for (Object tempCell : cells) {
      if (tempCell instanceof JmtCell) {
        JmtCell cell = (JmtCell) tempCell;
        Object key = ((CellComponent) cell.getUserObject()).getKey();
        tm.put(key, cell);
      }
    }
  }

  /**
   * Draws the queues and the utilizations over the graph
   * @param queueState a <code> SimulationSnapshot </code> containing information about the queues
   * @param utilizationState a <code> SimulationSnapshot </code> containing information about the utilizations
   * @param detectChanges
   * @throws Exception
   */
  public void draw(ModelSnapshot queueState, ModelSnapshot utilizationState) throws Exception {
    int MAX_NUMBER_OF_CLASSES_QUEUE = Defaults.getAsInteger("representableClasses").intValue();

    double nClasses = mediator.getClassDefinition().getClassKeys().size();
    double maxNJobs = queueState.getMaxValue();

    //used to avoid extreme queue lenght variation when the number of jobs inside the system is very small
    if (maxNJobs < 10) {
      maxNJobs = 10;
    }

    double QUEUE_HEIGHT = (JMTImageLoader.loadImage("queue")).getIconHeight();
    double QUEUE_WIDTH = (JMTImageLoader.loadImage("queue")).getIconWidth() - QUEUE_HEIGHT;

    double SOURCE_SIZE = (JMTImageLoader.loadImage("source")).getIconWidth();
    double SOURCE_MARGIN = 9;
    double source_usable_space = SOURCE_SIZE - SOURCE_MARGIN * 2;

    double H_MARGIN = 2;
    double V_MARGIN = 2;

    double width = QUEUE_WIDTH - 2 * H_MARGIN;
    double height = QUEUE_HEIGHT - 2 * V_MARGIN;

    int H_FREE_SPACE = 2;
    int V_FREE_SPACE = (int) ((QUEUE_HEIGHT - (((int) (height / nClasses)) * nClasses)) / 2);
    //int V_FREE_SPACE = 1;

    Graphics2D g = mediator.getGraphGraphics();

    Vector openClasses = mediator.getClassDefinition().getOpenClassKeys();
    Vector sources = mediator.getStationDefinition().getStationKeysSource();
    for (int i = 0; i < sources.size(); i++) {
      Vector<Object> refClasses = new Vector<Object>(0, 1);
      Object thisSource = sources.get(i);
      JmtCell cell = tm.get(thisSource);
      int classCount = 0;
      for (int k = 0; k < openClasses.size(); k++) {
        Object thisClass = openClasses.get(k);
        if (mediator.getClassDefinition().getClassRefStation(thisClass) == thisSource) {
          refClasses.add(thisClass);
          classCount++;
        }
      }
      Point2D p = mediator.getCellCoordinates(cell);

      //int xStart = (int)(p.x + SOURCE_MARGIN) + 8;
      double xStart = p.getX() + ((mediator.getCellDimension(cell).getWidth() - SOURCE_SIZE + 2 * SOURCE_MARGIN) / 2);
      double yStart = (int) (p.getY() + SOURCE_MARGIN) + 1;
      //if the number of class is less than the maximum representable
      if (classCount < MAX_NUMBER_OF_CLASSES_QUEUE) {
        int classSpace;
        for (int k = 0; k < classCount; k++) {
          classSpace = (int) (source_usable_space / classCount);
          if ((((source_usable_space / classCount) - classSpace) * k) > 1) {
            classSpace++;
          }
          Object thisClass = refClasses.get(k);
          g.setColor(mediator.getClassDefinition().getClassColor(thisClass));
          g.fillRect((int) xStart, (int) yStart, classSpace, (int) source_usable_space);
          xStart += classSpace;
        }
      }
      //else..
      else {
        int classSpace;
        Vector<Object> classesReplication = (Vector<Object>) refClasses.clone();
        Vector<Object> classesToBeDrawn = new Vector<Object>(0, 1);
        double min;
        double mean;
        //... find the first MAX_NUMBER_OF_CLASSES_QUEUE with the smallest mean value
        for (int k = 0; k < MAX_NUMBER_OF_CLASSES_QUEUE; k++) {
          min = Double.MAX_VALUE;
          int index = 0;

          for (int j = 0; j < classesReplication.size(); j++) {
            Object thisClass = classesReplication.get(j);
            Distribution temp = (Distribution) mediator.getClassDefinition().getClassParameter(thisClass,
                ClassDefinition.CLASS_DISTRIBUTION);
            if (temp.hasMean()) {
              mean = temp.getMean();
              if (mean < min) {
                index = j;
                min = mean;
              }
            }
          }
          classesToBeDrawn.add(classesReplication.get(index));
          classesReplication.remove(classesReplication.get(index));
        }
        //if less than MAX_NUMBER_OF_CLASSES_QUEUE classes where found
        //add the ( MAX_NUMBER_OF_CLASSES_QUEUE - classesToBeDrawn.size() )
        //with the highest priority
        if (classesToBeDrawn.size() < MAX_NUMBER_OF_CLASSES_QUEUE) {
          int left = MAX_NUMBER_OF_CLASSES_QUEUE - classesToBeDrawn.size();
          for (int j = 0; j < left; j++) {
            int max = -1;
            int priority;
            int index = 0;
            for (int k = 0; k < classesReplication.size(); k++) {
              Object thisClass = classesReplication.get(k);
              priority = mediator.getClassDefinition().getClassPriority(thisClass);
              if (priority > max) {
                max = priority;
                index = k;
              }
            }
            classesToBeDrawn.add(classesReplication.get(index));
            classesReplication.remove(classesReplication.get(index));
          }
        }
        //draw the classes inside the source
        for (int k = 0; k < MAX_NUMBER_OF_CLASSES_QUEUE; k++) {
          classSpace = (int) (source_usable_space / MAX_NUMBER_OF_CLASSES_QUEUE);
          if ((((source_usable_space / MAX_NUMBER_OF_CLASSES_QUEUE) - classSpace) * k) > 1) {
            classSpace++;
          }
          Object thisClass = classesToBeDrawn.get(k);
          g.setColor(mediator.getClassDefinition().getClassColor(thisClass));
          g.fill(new Rectangle2D.Double(xStart, yStart, classSpace, (int) source_usable_space));
          xStart += classSpace;
        }
      }
    }

    //Now draw station's queue
    Vector servers = queueState.getServers();
    Vector classes = mediator.getClassDefinition().getClassKeys();

    //for each server ...
    for (int i = 0; i < servers.size(); i++) {
      JmtCell cell = tm.get(servers.get(i));
      // Skips blocking region special nodes - Bertoli Marco
      if (cell == null) {
        continue;
      }
      g.setColor(Color.LIGHT_GRAY);
      Point2D p = mediator.getCellCoordinates(cell);
      double offset;
      double xStart;
      double yStart = p.getY() + V_FREE_SPACE;
      offset = (int) ((mediator.getCellDimension(cell).getWidth() - QUEUE_WIDTH - QUEUE_HEIGHT) / 2);
      g.fill(new Rectangle2D.Double(p.getX() + offset, p.getY(), (int) width + 1, (int) height + 2));

      //First draw the queues ....
      //if the number of classes is less then MAX_NUMBER_OF_CLASSES_QUEUE
      if (nClasses <= MAX_NUMBER_OF_CLASSES_QUEUE) {
        for (int j = 0; j < nClasses; j++) {
          double nJobs = queueState.getValue(servers.get(i), classes.get(j));

          int thisWidth = (int) ((nJobs / maxNJobs) * width);
          int thisHeight = (int) (height / nClasses);

          Color color = mediator.getClassDefinition().getClassColor(classes.get(j));
          g.setColor(color);
          xStart = p.getX() + offset + (int) (width - thisWidth) + H_FREE_SPACE;
          g.fill(new Rectangle2D.Double(xStart, yStart, thisWidth, thisHeight));
          yStart += thisHeight;
        }
      }

      // else draw only the first MAX_NUMBER_OF_CLASSES_QUEUE with the greates
      // number of job inside thisStation
      else {
        V_FREE_SPACE = (int) ((QUEUE_HEIGHT - (((int) (height / MAX_NUMBER_OF_CLASSES_QUEUE)) * (double) MAX_NUMBER_OF_CLASSES_QUEUE)) / 2);
        yStart = p.getY() + V_FREE_SPACE;

        Vector classesReplication = (Vector) classes.clone();
        Vector classesToBeDrawn = new Vector(0, 1);
        double max;
        double nJobs;
        for (int k = 0; k < MAX_NUMBER_OF_CLASSES_QUEUE; k++) {
          max = -1;
          int index = 0;

          for (int j = 0; j < classesReplication.size(); j++) {
            Object thisClass = classesReplication.get(j);
            nJobs = queueState.getValue(servers.get(i), thisClass);
            if (nJobs > max) {
              index = j;
              max = nJobs;
            }
          }
          classesToBeDrawn.add(classesReplication.get(index));
          classesReplication.remove(classesReplication.get(index));
        }

        for (int k = 0; k < nClasses; k++) {
          Object thisStation = classes.get(k);
          if (classesToBeDrawn.contains(thisStation)) {
            nJobs = queueState.getValue(servers.get(i), thisStation);

            int thisWidth = (int) ((nJobs / maxNJobs) * width);
            int thisHeight = (int) (height / MAX_NUMBER_OF_CLASSES_QUEUE);

            Color color = mediator.getClassDefinition().getClassColor(thisStation);
            g.setColor(color);
            xStart = p.getX() + offset + (int) (width - thisWidth) + H_FREE_SPACE;
            g.fill(new Rectangle2D.Double(xStart, yStart, thisWidth, thisHeight));
            yStart += thisHeight;
          }
        }
      }

      //then draw the utilization
      //if the number of classes is less then MAX_NUMBER_OF_CLASSES_QUEUE
      //offset =  (int) ( (getCellDimension(cell).getWidth() - QUEUE_WIDTH - QUEUE_HEIGHT)/2 + QUEUE_HEIGHT );
      int startAngle = 0;
      int arcDiameter = (int) (QUEUE_HEIGHT) - 2;
      xStart = p.getX() + offset + (int) QUEUE_WIDTH + 1;
      yStart = p.getY() + 1;
      g.setColor(Color.LIGHT_GRAY);
      g.fill(new Arc2D.Double(xStart, yStart, arcDiameter, arcDiameter, 0, 360, Arc2D.PIE));

      for (int j = 0; j < nClasses; j++) {
        double utilization = utilizationState.getValue(servers.get(i), classes.get(j));
        if (mediator.getStationDefinition().getStationNumberOfServers(servers.get(i)).intValue() > 1) {
          utilization = utilization / (mediator.getStationDefinition().getStationNumberOfServers(servers.get(i))).doubleValue();
        }
        int thisAngle = (int) (utilization * 360);

        Color color = mediator.getClassDefinition().getClassColor(classes.get(j));
        g.setColor(color);

        myFillArc(g, (int) xStart, (int) yStart, arcDiameter, startAngle, thisAngle);
        startAngle += thisAngle;
      }
    }
  }

  /**
   * It acts like Graphics.fillArc(...), I have written this method
   * since the predifined Java function presented strange behavior with
   * very small angles
   *
   * @param g  the Graphics reference
   * @param x  see Graphics.fillArc(...)
   * @param y  see Graphics.fillArc(...)
   * @param diameter  the diameter of the arc
   * @param startAngle  the starting angle in degrees (0° is interpreted as 3 o'clock)
   * @param angle  the angle width
   */
  private void myFillArc(Graphics g, int x, int y, int diameter, int startAngle, int angle) {
    double c = 2 * Math.PI / 360;
    int radius = diameter / 2;
    double MIN_ANGLE = 1 * c;
    double nPoints = Math.round(angle * c / (float) MIN_ANGLE);
    double xStart = x + radius;
    double yStart = y + radius;
    double reachedAngle = startAngle * c;
    for (int i = 0; i < nPoints; i++) {
      double x1;
      double y1;
      double x2;
      double y2;
      x1 = radius * Math.cos(reachedAngle);
      y1 = radius * Math.sin(reachedAngle);
      x2 = radius * Math.cos(reachedAngle + MIN_ANGLE);
      y2 = radius * Math.sin(reachedAngle + MIN_ANGLE);
      x1 = xStart + x1;
      y1 = yStart - y1;
      x2 = xStart + x2;
      y2 = yStart - y2;
      x1 = Math.round(x1);
      y1 = Math.round(y1);
      x2 = Math.round(x2);
      y2 = Math.round(y2);
      int[] xValues = { (int) xStart, (int) x1, (int) x2 };
      int[] yValues = { (int) yStart, (int) y1, (int) y2 };
      g.fillPolygon(xValues, yValues, 3);
      reachedAngle += MIN_ANGLE;
    }
  }
}
TOP

Related Classes of jmt.gui.jmodel.JGraphMod.GraphicalQueueState

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.