function vote96(action)

%VOTE96  GUI based analysis of 1996 Presidential election results
%
%  Synopsis:  vote96
%
%  VOTE96 produces an interactive window allowing the analysis
%  of the 1996 presidential election results.  The user is
%  allowed to re-allocate Perot's vote to Clinton and Dole
%  and display the resulting electoral vote outcome.  For any
%  postulated outcome, the states switching for the actual
%  outcome to the hypothesized outcome can be highlighted.  In
%  addition, the user can query the map for detailed election
%  results on a state-by-state basis.  The script is
%  executed by entering VOTE96.

%  Copyright 1996-1998 by Systems Planning and Analysis, Inc. and The MathWorks, Inc.
% $Revision: 1.10 $
%  Written by:  E. Byrns, E. Brown



if nargin == 0;   action = 'initialize';   end


if strcmp(action,'initialize')

     [savehndl,rawdata] = votepanl;

%  Load up the seeded united states map and legend.

     load usamtx

%  Compute the Excess Electoral Vote Function and plot

     [clintonexcss,percents] = votepntl(rawdata);
     [votes,voteclr] = votecalc(rawdata(:,1:3),sum(rawdata(:,4:5)')');
     axes(savehndl(1));
     plot(percents,clintonexcss);

%  Add the line slider to the excess votes function

  	 xlim = get(gca,'Xlim');
  	 ylim = get(gca,'Ylim');
     middle = xlim(1)+diff(xlim)/2;
	 linehndl = plot(middle*[1 1],ylim,':','EraseMode','xor', ...
	                 'ButtonDownFcn', 'vote96(''down'');');


%  Construct the actual results map and display
%  Disable the standard mapping toolbox buttondown callbacks

    axes(savehndl(2));
	[latlim,lonlim]=limitm(map,maplegend);

	range = max(latlim)-min(latlim);
	parallels = [min(latlim)+range/6 max(latlim)-range/6];

	axesm('MapProjection','eqaconic','MapLatLimit',latlim,'MapLonLimit',lonlim,...
			'mapparallels',parallels)
	set(gca,'ButtonDownFcn','')
	meshm(map,maplegend,[2 40],'ButtonDownFcn','')
	colormap([0 0 0; 0 1 1; 1 1 .5; voteclr]);
    title(['Winner by State (Red: Dole, Blue: Clinton)'],'Color','black');
	axis tight
	
%  Save the necessary data for later retrieval

     set(gcf,'UserData', savehndl);
     set(savehndl(3),'UserData',rawdata);
     set(savehndl(4),'UserData',states);
     set(savehndl(5),'UserData',map);
     set(savehndl(6),'UserData',maplegend);
     set(savehndl(7),'UserData',num2str(50) );
 	 set(savehndl(8),'UserData',[votes votes]);
	 set(savehndl(9),'UserData',voteclr);

     set(gcf,'Visible','on')

elseif strcmp(action,'down')  % User clicks on line slider

%  Change the line slider width and set the appropriate
%  window properties.

	hndl = get(gcf,'CurrentObject');
	set(hndl,'UserData',gca);
	set(hndl,'Visible','off','LineWidth', 5);
	set(hndl,'Visible','on')
    set(gcf,'WindowButtonUpFcn', 'vote96(''up'');', ...
            'WindowButtonMotionFcn', 'vote96(''move'');');

elseif strcmp(action,'move')  %  User moves the line slider

%  Retrieve the necessary data

	 hndl = get(gcf,'CurrentObject');
     savehndl = get(gcf,'UserData');
     rawdata  = get(savehndl(3),'UserData');

%  Get the current cursor point and axis limits

     lineaxis = get(hndl,'Parent');
     point = get(lineaxis,'CurrentPoint');
  	 xlim  = get(lineaxis,'Xlim');
	 ylim  = get(lineaxis,'Ylim');

%  Update the slider line display

     newpt    = min(max(point(1,1),xlim(1)),xlim(2));
     set(hndl, 'Xdata', newpt*[1 1]);

%  Compute the new popular vote given the specified split of
%  Perot votes.

     Bvotes = rawdata(:,1) + (1-newpt/100)*rawdata(:,3);
     Cvotes = rawdata(:,2) + (newpt/100)*rawdata(:,3);

%  Compute the electoral votes given the new popular vote

	 [votes,voteclr] = votecalc([Bvotes Cvotes],sum(rawdata(:,4:5)')');
	 rslts = sum(votes);

%  Update the displays

	 set(savehndl(9),'String',int2str(rslts(2)));
	 set(savehndl(10),'String',int2str(rslts(1)));
     if rslts(1) > rslts(2)
	      	 set(savehndl(11),'String','Winner:  Dole');
     else
	      	 set(savehndl(11),'String','Winner:  Clinton');
	 end

%  Display a rounded version of the Perot vote percent

	 set(savehndl(12),'String',num2str(newpt,4));
	 set(savehndl(13),'String',num2str(100-newpt,4));

%  Save the election results data

     set(savehndl(7),'UserData',num2str(newpt,4));
 	 set(savehndl(8),'UserData',[Bvotes Cvotes votes]);
	 set(savehndl(9),'UserData',voteclr);

elseif strcmp(action,'up')  %  Line slider object is released

%  Change the line slider width and set the appropriate
%  window properties.

    hndl = get(gcf,'CurrentObject');
	axishndl = get(hndl,'UserData');
    set(gcf, 'WindowButtonUpFcn','', 'WindowButtonMotionFcn','');
    set(hndl,'Visible','off');
    set(hndl, 'LineWidth', 1, 'ButtonDownFcn', 'vote96(''down'');');
    set(hndl,'Visible','on');
    axes(axishndl);

%  Display the new electoral results map.

%  Retrieve the required data

    savehndl   = get(gcf,'UserData');
    rawdata    = get(savehndl(3),'UserData');
    states     = get(savehndl(4),'UserData');
    map        = get(savehndl(5),'UserData');
	maplegend  = get(savehndl(6),'UserData');
    perotprcnt = get(savehndl(7),'UserData');
    votedata   = get(savehndl(8),'UserData');
    voteclr    = get(savehndl(9),'UserData');

%  Draw the electoral votes map

	colormap([0 0 0; 0 1 1; 1 1 .5; voteclr]);
    title(['Clinton Receives ',perotprcnt,'% of Perot Vote']);

elseif strcmp(action,'show')  % Results button is pressed

%  Retrieve the required data

    savehndl   = get(gcf,'UserData');
    voteclr    = get(savehndl(9),'UserData');

%  Set the results colormap

    clrmap = [0  0  0; 0  1  1; 1  1  .5; voteclr];
    colormap(clrmap);  refresh

elseif strcmp(action,'switch')  %  Switched button is pressed

%  Retrieve the required data

    savehndl   = get(gcf,'UserData');
    rawdata    = get(savehndl(3),'UserData');
    states     = get(savehndl(4),'UserData');
    map        = get(savehndl(5),'UserData');
	maplegend  = get(savehndl(6),'UserData');
    perotprcnt = get(savehndl(7),'UserData');
    votedata   = get(savehndl(8),'UserData');
    voteclr    = get(savehndl(9),'UserData');

%  Compute the highlighed colormap for the map display

    votes     = votedata(:,3:4);
    switched  = (~rawdata(:,4:5)) & votes;
    switched  = sum(switched')';
    indx      = find(switched==1);
    if ~isempty(indx)
	     voteclr(indx,1:3) = 0.5*voteclr(indx,1:3);
    end

%  Set the highlighted colormap

    clrmap = [0  0  0; 0  1  1; 1  1  .5; voteclr];
    colormap(clrmap); refresh

end


%**************************************************************************
%**************************************************************************
%**************************************************************************


function [savehndl,rawdata] = votepanl

%VOTEPANL  Creates the interface objects for the VOTE96 GUI
%
%  The data for the operation of this demo is stored in
%  various user data positions in the interface objects.

%  Copyright 1996-1998 by Systems Planning and Analysis, Inc. and The MathWorks, Inc.
% $Revision: 1.10 $
%  Written by:  E. Byrns, E. Brown


%  1996 Election data results
%  Source:  Wall Street Journal, Thursday Nov. 7, 1996.
%
%     Popular vote (%)         Electoral Vote     % State and Seed
%     Dole, Clinton, Perot     Dole, Clinton

rawdata =[
50	43	6	9	0       % Alabama			1
51	33	11	3	0       % Alaska			2
44	47	8	0	8       % Arizona			3
37	54	8	0	6       % Arkansas			4
38	51	7	0	54      % California		5
46	44	7	6	0       % Colorado			6
36	52	10	0	8       % Connecticut		7
37	52	11	0	3       % Delaware			8
42	48	9	0	25       % Florida 			9
47	46	6	13	0      % Georgia	   		10
32	57	8	0	4       % Hawaii			11
52	34	13	4	0       % Idaho				12
37	54	8	0	22      % Illinois			13
48	41	10	12	0       % Indiana			14
40	50	8	0	7       % Iowa				15
54	36	9	6	0       % Kansas			16
45	46	9	0	8       % Kentucky			17
40	52	7	0	9       % Louisiana			18
31	52	14	0	4       % Maine				19
38	54	7	0	12      % Maryland			20
28	62	9	0	10      % Massachusetts		21
39	52	9	0	18      % Michigan			22
35	51	12	0	10      % Minnesota			23
50	44	6	7	0       % Mississippi		24
41	48	10	0	11      % Missouri			25
44	41	14	3	0       % Montana			26
53	35	11	5	0       % Nebraska			27
42	44	9	0	4       % Nevada			28
40	50	10	0	4       % New Hampshire		29
36	53	9	0	15      % New Jersey		30
41	49	6	0	5       % New Mexico		31
31	59	8	0	33      % New York			32
49	44	7	14	0       % North Carolina	33
47	40	12	3	0       % North Dakota		34
41	47	11	0	21      % Ohio				35
48	40	11	8	0       % Oklahoma			36
37	47	11	0	7       % Oregon			37
40	49	10	0	23      % Pennsylvania		38
27	60	11	0	4       % Rhode Island		39
50	44	6	8	0       % South Carolina	40
46	43	10	3	0       % South Dakota		41
46	48	6	0	11      % Tennessee			42
49	44	7	32	0       % Texas				43
54	33	10	5	0       % Utah				44
31	54	12	0	3       % Vermont			45
47	45	7	13	0       % Virginia			46
36	51	9	0	11      % Washington		47
37	51	11	0	5       % West Virginia		48
39	49	10	0	11      % Wisconsin			49
50	37	12	3	0       % Wyoming			50
9	85	2	0	3       % District of Columbia	51
];


%  Compute the Pixel and Font Scaling Factors so
%  GUI figure windows and fonts look OK across all platforms

PixelFactor = guifactm('pixels');
FontScaling =  guifactm('fonts');

%  Construct the gui figure window

figure('Units','Points',...
    'Resize','on', 'Name','1996 Election Data',...
    'Numbertitle','off',...
	'Renderer','zbuffer', 'Visible','off');

%  Enforce V5 color defaults

colordef(gcf,'white')
figclr = get(gcf,'Color');

%  Excess Electoral Votes axes

savehndl(1) = axes('Position',[0.10   0.10   0.50   0.25], 'Box', 'on', ...
                   'Xlim', [0 100], 'Ylim', [-400 400], ...
	               'NextPlot', 'add'); grid off
xlabel('Percent of Perot Vote For Clinton');
ylabel('Excess Electoral Votes')
title(['DRAG DOTTED LINE TO ALLOCATE PEROT VOTERS']);



%  Map axes

savehndl(2) = axes('Units', 'normalized',...
                   'Position', [0.10   0.45   0.60   0.45], 'Box', 'on');

%  Switched vote button

savehndl(3) = uicontrol(gcf, 'Style','Push',...
			'Units','Normalized', 'Position',[0.80   0.80   0.15   0.09], ...
			'String','Switched', 'CallBack','vote96(''switch'')' );

%  Electoral results button

savehndl(4) = uicontrol(gcf, 'Style','Push',...
			'Units','Normalized', 'Position',[0.80   0.65   0.15   0.09], ...
			'String','Results', 'CallBack','vote96(''show'')' );

%  Exit button

savehndl(5) = uicontrol(gcf, 'Style','Push',...
			'Units','Normalized', 'Position',[0.80   0.50   0.15   0.09], ...
			'String','Exit', 'CallBack','close' );


%  Title text

savehndl(6) = uicontrol(gcf, 'Style','Text', ...
          'Units', 'Normalized', 'Position',[0.71   0.28   0.25   0.03], ...
		  'String','Actual    Potential   % Perot Vote',...
		  'HorizontalAlignment','left',...
		  'BackgroundColor',figclr, 'ForegroundColor','black' );

savehndl(7) = uicontrol(gcf, 'Style', 'Text', ...
          'Units', 'Normalized', 'Position',[0.63   0.23   0.14   0.03], ...
		  'String', 'Clinton        379',...
		  'HorizontalAlignment', 'left',...
		  'BackgroundColor',figclr, 'ForegroundColor','black' );

savehndl(8) = uicontrol(gcf, 'Style', 'Text', ...
          'Units', 'Normalized', 'Position',[0.63   0.18   0.14   0.03], ...
		  'String', 'Dole           159',...
		  'HorizontalAlignment', 'left',...
		  'BackgroundColor',figclr, 'ForegroundColor','black' );


%  Clinton potential electoral votes

savehndl(9) = uicontrol(gcf, 'Style', 'Text', ...
              'Units', 'Normalized', 'Position',[0.80   0.23   0.05   0.03], ...
		      'String', '379',...
		      'HorizontalAlignment', 'right',...
		      'BackgroundColor',figclr, 'ForegroundColor','black' );

%  Dole potential electoral votes

savehndl(10) = uicontrol(gcf, 'Style', 'Text', ...
              'Units', 'Normalized', 'Position',[0.80   0.18   0.05   0.03], ...
		      'String', '159',...
		      'HorizontalAlignment', 'right',...
		      'BackgroundColor',figclr, 'ForegroundColor','black' );

%  Winner banner

savehndl(11) = uicontrol(gcf, 'Style', 'Text', ...
              'Units', 'Normalized', 'Position',[0.63   0.13   0.20   0.03], ...
		      'String', 'Winner:  Clinton',...
		      'HorizontalAlignment', 'left',...
		      'BackgroundColor',figclr, 'ForegroundColor','blue' );

%  Clinton percent of Perot votes

savehndl(12) = uicontrol(gcf, 'Style', 'Text', ...
              'Units', 'Normalized', 'Position',[0.87   0.23   0.06   0.03], ...
		      'String', '50',...
		      'HorizontalAlignment', 'right',...
		      'BackgroundColor',figclr, 'ForegroundColor','black' );

%  Dole percent of Perot votes

savehndl(13) = uicontrol(gcf, 'Style', 'Text', ...
              'Units', 'Normalized', 'Position',[0.87   0.18   0.06   0.03], ...
		      'String', '50',...
		      'HorizontalAlignment', 'right',...
		      'BackgroundColor',figclr, 'ForegroundColor','black' );



%**************************************************************************
%**************************************************************************
%**************************************************************************


function [votes,colormap] = votecalc(votedata,evtotal)

%VOTECALC  Calculates the election results for VOTE96
%
%  VOTECALC  inputs the election data in the form of Dole,
%  Clinton and Perot popular vote percentages and the
%  total electoral votes in a state.  The function outputs
%  a vote result matrix indicating whether Dole or Clinton
%  recieved the corresponding electoral votes.  In addition,
%  a colormap matrix is computed for the states indicating
%  if Dole wins (red) or Clinton wins (Blue).

%  Copyright 1996-1998 by Systems Planning and Analysis, Inc. and The MathWorks, Inc.
% $Revision: 1.10 $
%  Written by:  E. Byrns, E. Brown


result = votedata(:,1) > votedata(:,2);    % Dole state wins
winners = [result ~result];                % State winner matrix
votes   = winners .* evtotal(:,ones(1,2));

colormap = [result 0*result ~result];


%**************************************************************************
%**************************************************************************
%**************************************************************************


function  [clintonexcss,percents] = votepntl(rawdata)

%VOTEPNTL  Computes the spectrum of potential election outcomes for VOTE96
%
%  VOTEPNTL computes the Clinton excess electoral vote function
%  as the percentage of Perot's votes assigned to Clinton varies
%  from 0 to 100%.

%  Copyright 1996-1998 by Systems Planning and Analysis, Inc. and The MathWorks, Inc.
% $Revision: 1.10 $
%  Written by:  E. Byrns, E. Brown


percents = 100:-1:0;
needed  = 269;

for i = 1:length(percents)


%  Compute the new popular vote given the specified split of
%  Perot votes.

      Bvotes = rawdata(:,1) + (1-percents(i)/100)*rawdata(:,3);
      Cvotes = rawdata(:,2) + (percents(i)/100)*rawdata(:,3);

%  Determine the electoral vote outcome for this hypothetical
%  election.

      votes   = votecalc([Bvotes Cvotes],sum(rawdata(:,4:5)')');
      rslts   = sum(votes);

%  Compute the Clinton excess electoral votes

      clintonexcss(i) = rslts(1,2) - needed;
end


%**************************************************************************
%**************************************************************************
%**************************************************************************
