// Template application. Copyright © 1996-2000 Swarm Development Group.
// This library is distributed without any warranty; without even the
// implied warranty of merchantability or fitness for a particular purpose.
// See file LICENSE for details and terms of copying.

#import "ObserverSwarm.h"
#import <simtoolsgui.h>
#import <analysis.h> //EZGraph
#include <math.h> //M_PI

// implementation of sample graphical interface for models.
@implementation ObserverSwarm

+ createBegin: aZone
{
  ObserverSwarm * obj;
  id <ProbeMap> probeMap;
  
  obj = [super createBegin: aZone];

  // MODIFY: initialize other display options here.
  obj->displayFrequency = 1;

  probeMap = [EmptyProbeMap createBegin: aZone];
  [probeMap setProbedClass: [self class]];
  probeMap = [probeMap createEnd];

  // MODIFY: set any display parameters here.
  [probeMap addProbe: [probeLibrary getProbeForVariable: "displayFrequency"
				    inClass: [self class]]];

  [probeLibrary setProbeMap: probeMap For: [self class]];

  return obj;
}

// MODIFY: possible creation finalization here
- createEnd
{
  time = 0;
  return [super createEnd];
}

- buildObjects
{
  [super buildObjects];
  
  modelSwarm = [ModelSwarm create: self];
  
  CREATE_PROBE_DISPLAY (modelSwarm);
  CREATE_PROBE_DISPLAY (self);

  [actionCache waitForControlEvent];
  if ([controlPanel getState] == ControlStateQuit)
    return self;

  [modelSwarm buildObjects];

  // MODIFY: build display objects here.

  distGraph = [EZGraph create: self
             setTitle: "Opinion Differences (Average across Couples)"
             setAxisLabelsX: "time" Y: "differences of opinion"
             setWindowGeometryRecordName: "distGraph"];
 
  [distGraph enableDestroyNotification: self
                notificationMethod: @selector (_distGraphDeath_:)];

  [distGraph createAverageSequence: "opinion disagreements \n (currently married people)"
                         withFeedFrom: [modelSwarm getMarriedList]
                          andSelector: M(getSpouseDistance)];

  marriedGraph = [EZGraph create: self
			  setTitle: "Summary Information on Couples"
			  setAxisLabelsX: "time" Y: "N"
			  setWindowGeometryRecordName: "marriedGraph"];
 
  [marriedGraph enableDestroyNotification: self
                notificationMethod: @selector (_marriedGraphDeath_:)];

  [marriedGraph createSequence: "still \n married"
                         withFeedFrom: modelSwarm 
                          andSelector: M(getNMarried)];

  //This wasn't interesting:
 //   [marriedGraph createSequence: "couples \n w/reduced \n distance"
//                          withFeedFrom: modelSwarm 
//                           andSelector: M(getSmallerDistMarried)];

  
  return self;
}  


- createMagicGraph
{ 
  id <FunctionGraph> fg;
  id <GraphElement> fe;
  id <Graph> graph;
  
  id fgd = [Frame create: [self getZone]];
  
  graph = [Graph createParent: fgd];
  [graph setWindowTitle: "ContinuouslyMarriedCouples"];

  [graph pack];

  fe = [graph createElement];
  [fe setLabel: "disagreement \n level of \n continuously \n married couples"];
  [fe setColor: "red"];
  [fe setWidth: 1];    
  
  fg = [FunctionGraph createBegin: [self getZone]];
  [fg setElement: fe];
  [fg setDataFeed: modelSwarm];
  [fg setXMin: 0.0 Max: time  StepSize: 1]; 
  [fg setFunctionSelector: M(compute::)];
 
  [fg setResetFrequency: 0];
  fg = [fg createEnd]; 

  [fg graph];
  return self;
}

 
- _distGraphDeath_ : caller
{ 
  [distGraph drop];
  distGraph = nil;
  return self;
}


- _marriedGraphDeath_ : caller
{ 
  [marriedGraph drop];
  marriedGraph = nil;
  return self;
}


- _update_
{
  [distGraph step];
  [marriedGraph step];
  time = getCurrentTime();
  return self;
}

- buildActions
{
  [super buildActions];
  
  [modelSwarm buildActions];

  // MODIFY: schedule display objects here.
  displayActions = [ActionGroup create: self];
  [displayActions createActionTo: probeDisplayManager message: M(update)];
  [displayActions createActionTo: actionCache         message: M(doTkEvents)];

  [displayActions createActionTo: self  message: M(_update_)];

  displaySchedule = [Schedule createBegin: self];
  [displaySchedule setRepeatInterval: displayFrequency];
  displaySchedule = [displaySchedule createEnd];
  [displaySchedule at: 0 createAction: displayActions];

  [displaySchedule at: 0 createActionTo: self message: M(stop)];

  return self;
}  

- activateIn: swarmContext
{
  [super activateIn: swarmContext];

  [modelSwarm activateIn: self];
  [displaySchedule activateIn: self];
  
  return [self getSwarmActivity];
}

- stop
{
  if ((time %20 ==0 ) && (time > 5)) { [self createMagicGraph];}

  if (time > 99) [controlPanel setStateStopped];
  return self;
}

@end
