001 /** 002 * planningtool - A Planning Tool with Critiquing Support. 003 * 004 * Copyright (C) 2006 olale 005 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU General Public License 008 * as published by the Free Software Foundation; either version 2 009 * of the License, or (at your option) any later version. 010 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 016 * You should have received a copy of the GNU General Public License 017 * along with this program; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 020 * Contact information: 021 * E-mail: olale@ida.liu.se 022 * olale@lysator.liu.se 023 */ 024 package se.liu.ida.critiquer.constraints; 025 026 import java.awt.Graphics2D; 027 import java.util.ArrayList; 028 import java.util.Calendar; 029 import java.util.HashMap; 030 import java.util.HashSet; 031 import java.util.Set; 032 import java.util.Map.Entry; 033 034 import javax.swing.JComponent; 035 036 import org.jfree.chart.ChartFactory; 037 import org.jfree.chart.ChartPanel; 038 import org.jfree.chart.JFreeChart; 039 import org.jfree.chart.plot.PlotOrientation; 040 import org.jfree.data.category.DefaultCategoryDataset; 041 042 import se.liu.ida.critiquer.activities.Activity; 043 import se.liu.ida.critiquer.activities.ActivityUtils; 044 import se.liu.ida.critiquer.activities.parameters.Parameter; 045 import se.liu.ida.critiquer.activities.parameters.TimeParameter; 046 import se.liu.ida.critiquer.gui.TimeView; 047 import se.liu.ida.critiquer.gui.View; 048 import se.liu.ida.critiquer.mics.ReferenceHolder; 049 import se.liu.ida.critiquer.resources.Agent; 050 051 /** 052 * 053 * <p> 054 * A critic that is supposed to display information on resource usage depending 055 * on which resources are used at the current time in the time view 056 * </p> 057 * <p> 058 * For each activity that is created, a constraint map is maintained that holds 059 * eq constraints for the activity start and end times so that their values 060 * reflect those of the mission time. The map also contains IfOnlyIf constraints 061 * that forces an integer variable agentUsage to 1 if the current time in the 062 * time view is within the mission time and 0 otherwise. 063 * </p> 064 * <p> 065 * There is finally a total sum of the resource usage which is the sum of all 066 * agentUsage variables for all activities. 067 * </p> 068 * <p> 069 * It's really a shame that constraints cannot force variables to assume values 070 * if they already have other values without raising ContradictionException. As 071 * it stands right now we have to remove and add <code>eq</code> constraints 072 * to achieve the same effect 073 * </p> 074 * 075 * @author olale 076 * 077 */ 078 079 public class ResourceUsageCritic extends StandardConstraint implements GUIComponentCritic { 080 081 082 /** 083 * 084 */ 085 private static final long serialVersionUID = 1L; 086 087 public static final int MAX_USAGE = 1000; 088 089 private String activities = "All activities"; 090 091 092 private DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 093 094 private JFreeChart chart = ChartFactory.createBarChart("Resource usage", 095 "Resource type", 096 "Usage", 097 dataset, 098 PlotOrientation.VERTICAL, 099 true, 100 false, 101 false); 102 103 private ChartPanel panel = new ChartPanel(chart); 104 private HashMap<String,Integer> usageMap = new HashMap<String, Integer>(); 105 106 ResourceUsageCritic() { 107 usageMap.put("All", 0); 108 updateDataSet(); 109 } 110 111 /** 112 * The current time has changed, so modify the barchart dataset 113 * 114 */ 115 private void updateDataSet() { 116 for (Entry<String, Integer> entry : usageMap.entrySet()) { 117 dataset.setValue(entry.getValue(), entry.getKey(), activities); 118 } 119 } 120 121 /** 122 * This view is only applicable to the time view 123 * 124 */ 125 @Override 126 protected void initApplicableViews() { 127 applicableViews.add(TimeView.class); 128 } 129 130 private boolean isActivityActive(Activity activity) { 131 boolean active=false; 132 Calendar currentTime = ReferenceHolder.timeView.getCurrentTime(); 133 TimeParameter startParam = ActivityUtils.getStartTimeParameter(activity); 134 TimeParameter endParam = ActivityUtils.getEndTimeParameter(activity); 135 if (startParam.hasValue() && endParam.hasValue()) { 136 active = (!startParam.getValue().after(currentTime)) && (!endParam.getValue().before(currentTime)); 137 } 138 return active; 139 } 140 141 142 public String getDescription() { 143 return "Displays information on resource usage"; 144 } 145 146 /** 147 * 148 * We only need set the currentTime through changing the currentTime 149 * <code>eq</code> constraint since the updating is already done by the 150 * ChartPanel component 151 * 152 */ 153 public void viewUpdated(View v, Graphics2D g2) { 154 if (v instanceof TimeView) { 155 TimeView timeView = (TimeView) v; 156 ArrayList<Activity> activityList = timeView.getEvaluationActivities(); 157 Set<String> usageKeys = usageMap.keySet(); 158 for (String key : usageKeys) { 159 usageMap.put(key,0); 160 } 161 162 for (Activity activity : activityList) { 163 if (isActivityActive(activity)) { 164 HashSet<Agent> agents = ActivityUtils.getAgentsInActivity(activity); 165 for (Agent agent : agents) { 166 String agentType = agent.getClass().getSimpleName(); 167 if (usageMap.containsKey(agentType)) { 168 usageMap.put(agentType, usageMap.get(agentType)+1); 169 } else { 170 usageMap.put(agentType,1); 171 } 172 } 173 usageMap.put("All",usageMap.get("All")+agents.size()); 174 } 175 } 176 177 updateDataSet(); 178 } 179 } 180 181 @Override 182 public <T> void paramChanged(Activity activity, Parameter<T> p) { 183 // TODO Auto-generated method stub 184 185 } 186 187 /** 188 * Return the chart panel 189 * @see se.liu.ida.critiquer.constraints.GUIComponentCritic#getComponent() 190 */ 191 public JComponent getComponent() { 192 return panel; 193 } 194 }