Actions

GUIModel.java.wp

From Santa Fe Institute Events Wiki

Revision as of 19:19, 18 June 2006 by Seoc (talk | contribs)

WikiPeerCode

/*
 * GUIModel.java
 *
 * Created on January 30, 2005, 12:21 PM
 * Modified June 18, 2006 13:20 by Jack
 * 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(){
		return calcTopRepSkills(5);
	    }
	}
	
	// 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() {
    }
    
    
    
}