WikiPeerCode
/*
* GUIModel.java
*
* Created on January 30, 2005, 12:21 PM
* Modified June 18, 2006 13:55 by Jack
* Modified slightly 6-18-06 23:10 by Andrew
* This runs the graphical interface for the RepMod model
*/
package RepMod;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.HashSet;
import uchicago.src.sim.engine.Schedule;
import uchicago.src.sim.engine.SimModelImpl;
import uchicago.src.sim.engine.*;
import uchicago.src.sim.util.*;
import uchicago.src.sim.gui.*;
import uchicago.src.sim.gui.ColorMap;
import uchicago.src.sim.gui.DisplaySurface;
import uchicago.src.sim.gui.Object2DDisplay;
import uchicago.src.sim.gui.Value2DDisplay;
import uchicago.src.sim.space.Object2DTorus;
import uchicago.src.sim.engine.AbstractGUIController;
import uchicago.src.sim.analysis.*;
import java.util.Collections;
import java.util.Comparator;
/**
*
* @author Jack Waddell
*/
public class GUIModel extends RepMod{
//*******************************************************
// Instance Parameters
// The actual display surface, where things are put on the screen
private DisplaySurface surface;
// A layout, which tells the surface where to put nodes and edges
private AbstractGraphLayout layout;
// A graph of the agreement between rep and skill
private OpenSequenceGraph repSkillGraph;
// A graph of the running sum of the skill of the top repped agents
private OpenSequenceGraph topSkillGraph;
// A plot
private Plot histPlot;
// A Histogram
// private OpenHistogram wealthHist;
// A Histogram
// private OpenHistogram degreeHist;
//*******************************************************************
// Methods
/////////////////////////////////////////////////////////////////////
// setup
//
// This runs automatically when the model starts
// and when you click the reload button, to "tear down" any
// existing display objects, and get ready to initialize
// them at the start of the next 'run'.
//
public void setup() {
// the super class does conceptual-model setup (RepMod)
super.setup();
if ( rDebug > 0 )
System.out.printf( "<== GUIModel setup() begin.\n" );
// NOTE: you may want to set these next two to 'true'
// if you are on a windows machine. that would tell repast
// to by default send System.out and .err output to
// a special repast output window.
AbstractGUIController.CONSOLE_ERR = false;
AbstractGUIController.CONSOLE_OUT = false;
// For restart purposes, dispose of any displays
if ( surface != null ) surface.dispose();
if ( repSkillGraph != null ) repSkillGraph.dispose();
if ( topSkillGraph != null ) topSkillGraph.dispose();
//if ( wealthHist != null) wealthHist.dispose();
//if ( degreeHist != null) degreeHist.dispose();
// Create and register the abstract surface
surface = null;
surface = new DisplaySurface( this, "Network Display" );
registerDisplaySurface( "Main Display", surface );
// Add Custom Buttons
modelManipulator.init();
modelManipulator.addButton("Layout - Circular",
new ActionListener(){
public void actionPerformed(ActionEvent evt){
changeLayoutCircular();
}
}
);
modelManipulator.addButton("Layout - Kamada",
new ActionListener(){
public void actionPerformed(ActionEvent evt){
changeLayoutKamada();
}
}
);
modelManipulator.addButton("Print Nodes",
new ActionListener(){
public void actionPerformed(ActionEvent evt){
printNodes();
}
}
);
modelManipulator.addButton("Print Rep Sorted Nodes",
new ActionListener(){
public void actionPerformed(ActionEvent evt){
printRepSortedNodes();
}
}
);
modelManipulator.addButton("Kill All Edges",
new ActionListener(){
public void actionPerformed(ActionEvent evt){
killAllEdges();
}
}
);
modelManipulator.addButton("Plot Reputation vs. Skill",
new ActionListener(){
public void actionPerformed(ActionEvent evt){
plotRepSkill();
}
}
);
if ( rDebug > 0 )
System.out.printf( "<== GUIModel setup() done.\n" );
}
/////////////////////////////////////////////////////////////////////
// begin
//
// This runs when you click the "initialize" button
// (the button with the single arrow that goes around in a circle)
// or at the first step
public void begin() {
DMSG(1, "==> enter GUIModel-begin()" );
// Set up drawables
CustomNode.setUpNodeDrawing(this);
CustomEdge.setUpEdgeDrawing(this);
buildModel(); // Calls in the base model (RepMod)
buildDisplay(); // Constructs the displays
if (rDebug > 0)
System.out.printf("Display Built Successfully. \n");
// Constructs the schedule; If defined in GUIModel, ignores buildSchedule in base model
buildSchedule();
surface.display(); // displays the surface on the display
writeHeaderCommentsToReportFile();
DMSG(1, "<== leave GUIModel-begin() done." );
}
/////////////////////////////////////////////////////////////////////
// buildDisplay
//
// builds the display and display related things
//
public void buildDisplay() {
if ( rDebug > 0 )
System.out.printf( "==> GUIModel buildDisplay...\n" );
// Layout specifies the arrangement of nodes and edges
// This specifically uses the Kamada-Kawai method
layout = new KamadaGraphLayout(agentList, worldXSize, worldYSize);
Network2DDisplay display = new Network2DDisplay(layout);
layout.updateLayout(); // actually execute the laying out
// Register the layout with the display surface for drawing
surface.addDisplayableProbeable(display, "Network Display");
surface.addZoomable (display);
surface.setBackground (java.awt.Color.black);
addSimEventListener (surface);
// Makes a graph
repSkillGraph = new OpenSequenceGraph("RepSkillMatch", this); // constructs graph
repSkillGraph.setXRange(0, 2000); // sets ranges
repSkillGraph.setYRange(-1.1, 1.1);
repSkillGraph.setAxisTitles("time", "frac. match"); // sets axis lables
// This generates a sequence, which is read into the graph
// To generalize, change sequence class name, and what it returns
class repSkillSequence implements Sequence {
public double getSValue(){
return calcRepSkillMatch();
}
}
// Add the above sequence to the graph.
// You can add several sequences to plot simultaneously
repSkillGraph.addSequence("frace. match", new repSkillSequence());
// Display the graph. It will need to be updated in Step
repSkillGraph.display();
topSkillGraph = new OpenSequenceGraph("Top Rep Skills", this); // constructs graph
topSkillGraph.setXRange(0, 2000); // sets ranges
topSkillGraph.setYRange(0, 5);
topSkillGraph.setAxisTitles("time", "Skills"); // sets axis lables
// This generates a sequence, which is read into the graph
// To generalize, change sequence class name, and what it returns
class topSkillSequence implements Sequence {
public double getSValue(){
// AS: changed to use numTopAgents
//return calcTopRepSkills(5);
return calcTopRepSkills(numTopAgents);
}
}
// Add the above sequence to the graph.
// You can add several sequences to plot simultaneously
topSkillGraph.addSequence("Skill of Top Rep Agents", new topSkillSequence());
// Display the graph. It will need to be updated in Step
topSkillGraph.display();
// Generate a histogram of agent wealth
/*
wealthHist = new OpenHistogram("Agent Wealth Distribution", 10, 0);
wealthHist.setYRange(0, 100.0);
BinDataSource histSource = new BinDataSource(){
public double getBinValue(Object o){
CustomNode node = (CustomNode) o;
return node.getReputation();
}
};
wealthHist.createHistogramItem("Wealth", agentList, histSource);
wealthHist.display();
*/
// Generate a histogram of agent degree
/*
degreeHist = new OpenHistogram("Agent Degree Distribution", 10, 0);
degreeHist.setYRange(0, 100.0);
BinDataSource degreeSource = new BinDataSource(){
public double getBinValue(Object o){
CustomNode node = (CustomNode) o;
return node.getDegree();
}
};
degreeHist.createHistogramItem("Degree", agentList, degreeSource);
degreeHist.display();
*/
}
////////////////////////////////////////////////////////////////
// buildSchedule
// Adds to buildSchedule in main model
// Note, model-type changes should also be included in
// batchmodel's buildSchedule if one wants to ever run in batch
public void buildSchedule() {
schedule = new Schedule(1);
super.buildSchedule(); // Get base model schedule
}
//////////////////////////////////////////////////////////////////
// step
//
// Ask the super-class (RepMod) to do its step() method,
// and then this does display related activities.
public void step() {
super.step(); // the base model does whatever it does
// add things after this for all displays (graphs, etc)
drawNodes();
surface.updateDisplay();
repSkillGraph.step();
topSkillGraph.step();
//wealthHist.step();
}
////////////////////////////////////////////////////////////////
// drawNodes
// has nodes re-draw themselves based on Reputation
public void drawNodes(){
CustomNode node;
double maxReputation = 0;
for(int i = 0; i < numAgents; i++){
node = (CustomNode) agentList.get(i);
if (node.getReputation() > maxReputation)
maxReputation = node.getReputation();
}
for(int i = 0; i < numAgents; i++){
node = (CustomNode) agentList.get(i);
node.setNodeColorFromReputation(maxReputation);
}
}
//////////////////////////////////////////////////////////////////
// processEndOfRun
// called once, at end of run.
public void processEndOfRun ( ) {
long finalStep = (long) schedule.getCurrentTime();
if ( rDebug > 0 )
System.out.printf("\n\n===== GUIModel processEndOfRun =====\n\n" );
applyAnyStoredChanges();
endReportFile(finalStep);
this.fireStopSim();
}
/////////////////////////////////////////////////////////////
// addAgent
// Input: CustomNode agent
// Output: none
// Adds a new agent to the agent list
public void addAgent(CustomNode agent){
super.addAgent(agent);
updateLayoutAgentList();
}
/////////////////////////////////////////////////////////////
// delAgent
// Input: CustomNode agent
// Output: none
// Deletes an agent from the agent list
public void delAgent(CustomNode agent){
super.delAgent(agent);
updateLayoutAgentList();
}
////////////////////////////////////////////////////////////
// updateLayoutAgentList
// Input: none
// Output: none
// Update layout's agentList. Model's agentlist
// is updated with gm's (since they both point to
// the same object). Layout is dumb, and evidently
// re-stores pointers to objects in list, rather than
// the list.
public void updateLayoutAgentList(){
layout.setList(agentList);
// update the layout, re-executing layout method (e.g. Kamada)
layout.updateLayout();
}
///////////////////////////////////////////////////////////////////
// changeLayoutCircular
// Uses circular rather than Kamada layout
public void changeLayoutCircular(){
layout = new CircularGraphLayout(agentList, worldXSize, worldYSize);
layout.updateLayout();
}
///////////////////////////////////////////////////////////////////
// changeLayoutKamada
// Uses kamada-kawai layout, rather than circular
public void changeLayoutKamada(){
layout = new KamadaGraphLayout(agentList, worldXSize, worldYSize);
layout.updateLayout();
}
///////////////////////////////////////////////////////////////////
// printNodes
// print node properties to terminal window
// Mainly used for debugging
public void printNodes(){
System.out.printf("\nAt time = %f\n", schedule.getCurrentTimeDouble());
for(int i = 0; i < agentList.size(); i++){
CustomNode aNode = (CustomNode) agentList.get(i);
String s = String.format("#%d has %1.3f rep with skill %1.3f.\n",
aNode.getID(), aNode.getReputation(), aNode.getSkill());
System.out.printf(s);
}
System.out.printf("\n");
}
///////////////////////////////////////////////////////////////////
// printRepSortedNodes
// print node properties to terminal window
// Mainly used for debugging
public void printRepSortedNodes(){
ArrayList<CustomNode> tempList = new ArrayList<CustomNode>();
tempList.addAll(agentList);
Collections.sort(tempList, compNodes);
System.out.printf("\nAt time = %f\n", schedule.getCurrentTimeDouble());
for(CustomNode agent : tempList){
String s = String.format("#%d has %1.3f rep with skill %1.3f.\n",
agent.getID(), agent.getReputation(), agent.getSkill());
System.out.printf(s);
}
System.out.printf("\n");
}
//////////////////////////////////////////////////////////////////////
// killAllEdges
// deletes all edges
// Mainly used for debugging, or being a bastard
public void killAllEdges(){
for(int i = 0; i < agentList.size(); i++){
CustomNode node = (CustomNode) agentList.get(i);
node.clearInEdges();
node.clearOutEdges();
}
}
////////////////////////////////////////////////////////////////////
// plotRepSkill()
public void plotRepSkill(){
Plot repSkillPlot = new Plot("Reputation v. Skill");
repSkillPlot.display();
repSkillPlot.setConnected(false);
for (int i = 0; i < numAgents; i++) {
CustomNode node = (CustomNode) agentList.get(i);
repSkillPlot.plotPoint(node.getSkill(), node.getReputation(), 0);
}
repSkillPlot.updateGraph();
repSkillPlot.setXRange(0, 1);
repSkillPlot.setYRange(0, 1);
//aPlot.fillPlot();
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// **** NO NEEd TO CHANGE THE REST OF THIS *****
////////////////////////////////////////////////////////////////////
// main entry point
public static void main( String[] args ) {
uchicago.src.sim.engine.SimInit init =
new uchicago.src.sim.engine.SimInit();
GUIModel model = new GUIModel();
//System.out.printf("==> GUIMOdel main...\n" );
// set the type of model class, this is necessary
// so the parameters object knows whether or not
// to do GUI related updates of panels,etc when a
// parameter is changed
model.setModelType("GUIModel");
// Do this to set the Update Probes option to true in the
// Repast Actions panel
Controller.UPDATE_PROBES = true;
model.setCommandLineArgs( args );
init.loadModel( model, null, false ); // does setup()
// this new function calls ProbeUtilities.updateProbePanels() and
// ProbeUtilities.updateModelProbePanel()
model.updateAllProbePanels();
}
/** Creates a new instance of GUIModel */
public GUIModel() {
}
}