%let name=oldest_domains;
filename odsout '.';

/*
http://en.wikipedia.org/wiki/.com
*/

data domain_data;
length month $20 day $8 year $4 domain_name $30;
input rank month day year domain_name;
datalines;
1 March 15, 1985 symbolics.com
2 April 24, 1985 BBN.com
3 May 24, 1985 think.com
4 July 11, 1985 MCC.com
5 September 30, 1985 DEC.com
6 November 7, 1985 northrop.com 
7 January 9, 1986 xerox.com 
8 January 17, 1986 SRI.com 
9 March 3, 1986 HP.com 
10 March 5, 1986 bellcore.com 
11 March 19, 1986 IBM.com 
11 March 19, 1986 sun.com 
13 March 25, 1986 intel.com 
13 March 25, 1986 TI.com 
15 April 25, 1986 ATT.com 
16 May 8, 1986 GMR.com 
16 May 8, 1986 tek.com 
18 July 10, 1986 FMC.com 
18 July 10, 1986 UB.com 
20 August 5, 1986 bell-atl.com 
20 August 5, 1986 GE.com 
20 August 5, 1986 grebyn.com 
20 August 5, 1986 ISC.com 
20 August 5, 1986 NSC.com 
20 August 5, 1986 stargate.com 
26 September 2, 1986 boeing.com 
27 September 18, 1986 ITCorp.com 
28 September 29, 1986 siemens.com 
29 October 18, 1986 pyramid.com 
30 October 27, 1986 alphaDC.com 
30 October 27, 1986 BDM.com 
30 October 27, 1986 fluke.com 
30 October 27, 1986 inmet.com 
30 October 27, 1986 kesmai.com 
30 October 27, 1986 mentor.com 
30 October 27, 1986 NEC.com 
30 October 27, 1986 ray.com 
30 October 27, 1986 rosemount.com 
30 October 27, 1986 vortex.com 
40 November 5, 1986 alcoa.com 
40 November 5, 1986 GTE.com 
42 November 17, 1986 adobe.com 
42 November 17, 1986 AMD.com 
42 November 17, 1986 DAS.com 
42 November 17, 1986 data-IO.com 
42 November 17, 1986 octopus.com 
42 November 17, 1986 portal.com 
42 November 17, 1986 teltone.com 
50 December 11, 1986 3Com.com 
50 December 11, 1986 amdahl.com 
50 December 11, 1986 CCUR.com 
50 December 11, 1986 CI.com 
50 December 11, 1986 convergent.com 
50 December 11, 1986 DG.com 
50 December 11, 1986 peregrine.com 
50 December 11, 1986 quad.com 
50 December 11, 1986 SQ.com 
50 December 11, 1986 tandy.com 
50 December 11, 1986 TTI.com 
50 December 11, 1986 unisys.com 
61 January 19, 1987 CGI.com 
61 January 19, 1987 CTS.com 
61 January 19, 1987 SPDCC.com 
64 February 19, 1987 apple.com 
65 March 4, 1987 NMA.com 
65 March 4, 1987 prime.com 
67 April 4, 1987 philips.com 
68 April 23, 1987 datacube.com 
68 April 23, 1987 KAI.com 
68 April 23, 1987 TIC.com 
68 April 23, 1987 vine.com 
72 April 30, 1987 NCR.com 
73 May 14, 1987 cisco.com 
73 May 14, 1987 RDL.com 
75 May 20, 1987 SLB.com 
76 May 27, 1987 parcplace.com 
76 May 27, 1987 UTC.com 
78 June 26, 1987 IDE.com 
79 July 9, 1987 TRW.com 
80 July 13, 1987 unipress.com 
81 July 27, 1987 dupont.com 
81 July 27, 1987 lockheed.com 
83 July 28, 1987 rosetta.com 
84 August 18, 1987 toad.com 
85 August 31, 1987 quick.com 
86 September 3, 1987 allied.com 
86 September 3, 1987 DSC.com 
86 September 3, 1987 SCO.com 
89 September 22, 1987 gene.com 
89 September 22, 1987 KCCS.com 
89 September 22, 1987 spectra.com 
89 September 22, 1987 WLK.com 
93 September 30, 1987 mentat.com 
94 October 14, 1987 WYSE.com 
95 November 2, 1987 CFG.com 
96 November 9, 1987 marble.com 
97 November 16, 1987 cayman.com 
97 November 16, 1987 entity.com 
99 November 24, 1987 KSR.com 
100 November 30, 1987 NYNEXST.com 
;
run;

data domain_data; set domain_data;
day=compress(translate(day,' ',','));
chardate=trim(day)||trim(substr(month,1,3))||trim(year); 
format date date9.;
date=input(chardate,date9.); 
run;

proc sort data=domain_data out=domain_data;
by date domain_name;
run;


proc sql noprint;
create table summarized as
select unique date, domain_name, count(*) as count
from domain_data
group by date
order by date, domain_name;
quit; run;

data summarized; set summarized;
by date;
length htmlvar $300;
retain htmlvar;
if first.date then htmlvar='title="'||trim(left(count))||' domains registered on: '||trim(left(put(date,date9.)))||'0d'x||'--------------------------';
htmlvar=trim(left(htmlvar))||'0d'x||trim(left(domain_name));
if last.date then do;
 htmlvar=trim(left(htmlvar))||'"'||' href='||quote('#'||trim(left(date)));
 output;
 end;
run;

data my_data; set summarized;
day=date;
year=0; year=put(date,year4.);
run;

proc sql noprint;
/* Macro variable containing minimum year */
select min(year) into :min_year from my_data;
select max(year) into :max_year from my_data;
/* Start your annotate label data for each year */
create table my_anno as select unique year from my_data;
quit; run;

/* My algorithm assumes you have an obs for each day, so create such a grid */
/* (not essential if you have no days with missing data, but go ahead and
   do it to be on the safe side) */
data grid_days;
 format day date7.;
 do day="01jan.&min_year"d to "31dec.&max_year"d by 1;
  weekday=put(day,weekday.);
  downame=trim(left(put(day,downame.)));
  monname=trim(left(put(day,monname.)));
  year=put(day,year.);
  output;
 end;
run;
/* Join your data with the grid-of-days */
proc sql noprint;
create table my_data as select *
from grid_days left join my_data
on grid_days.day eq my_data.day;
quit; run;

/* Create a 'map' of the days, suitable for use in gmap */
/* If you had 'real' data, it might not be sorted, so sort it here */
/* (must be sorted to use the 'by' below) */
proc sort data=my_data out=datemap;
by year day;
run;
/* You must use 'by year', in order to use first.year */
/* You're starting with minimum date at top/left, max at bottom/right */
data datemap; set datemap;
 keep day x y;
 by year;
 if first.year then x_corner=1;
 else if trim(left(downame)) eq 'Sunday' then x_corner+1;
 /* If this factor is 7, there will be no space between years */
 y_corner=((&min_year-year)*8)-weekday;
 x=x_corner; y=y_corner; output;
 x=x+1; output;
 y=y-1; output;
 x=x-1; output;
run;

/* Create darker outline to annotate around each month, since gmap
   can't automatically do a 2-level outline. */
data outline; set datemap;
length yr_mon $15;
yr_mon=trim(left(put(day,year.)))||'_'||trim(left(put(day,month.)));
order+1;
run;
/* Sort it, so you can use 'by' in next step */
proc sort data=outline out=outline;
by yr_mon order;
run;
proc gremove data=outline out=outline;
 by yr_mon; id day;
run;
data outline;
 length COLOR FUNCTION $ 8;
 xsys='2'; ysys='2'; size=1.75; when='A'; color='gray33';
 set outline; by yr_mon;
 if first.yr_mon then function='poly';
 else function='polycont';
run;

data my_anno; set my_anno;
length text $10;
function='LABEL';
position='4';
xsys='2'; ysys='2'; hsys='d'; when='A';
x=-6;
y=((&min_year-year)*8)-1.25;
style='albany amt/bold';
size=9;
text=trim(left(year)); output;
style='';
x=-.1;
size=8;
text='Sunday'; output;
y=y-1; text='Monday'; output;
y=y-1; text='Tuesday'; output;
y=y-1; text='Wednesday'; output;
y=y-1; text='Thursday'; output;
y=y-1; text='Friday'; output;
y=y-1; text='Saturday'; output;
run;

data month_anno;
length text $10;
function='LABEL';
position='5';
xsys='2'; ysys='2'; hsys='d'; when='A';
size=8;
y=1;
spacing=4.4;
x=3.5; text='JAN'; output;
x=x+spacing; text='FEB'; output;
x=x+spacing; text='MAR'; output;
x=x+spacing; text='APR'; output;
x=x+spacing; text='MAY'; output;
x=x+spacing; text='JUN'; output;
x=x+spacing; text='JUL'; output;
x=x+spacing; text='AUG'; output;
x=x+spacing; text='SEP'; output;
x=x+spacing; text='OCT'; output;
x=x+spacing; text='NOV'; output;
x=x+spacing; text='DEC'; output;
run;

data my_annofake;
run;


goptions device=png;
goptions xpixels=800 ypixels=800;
goptions cback=white;

ODS LISTING CLOSE;
ODS HTML path=odsout body="&name..htm" 
 (title="100 Oldest .com Domains still recently in use") 
 style=minimal options(pagebreak='no');

goptions ftitle="albany amt/bold" ftext="albany amt" htitle=14pt htext=10pt;
goptions ctext=gray33;

/* RGB hex values for color shades gotten from www.colorbrewer.com */
pattern1 v=s c=cxfed976; /* lightest */
pattern2 v=s c=cxfd8d3c;
pattern3 v=s c=cxf03b20;
pattern4 v=s c=cxbd0026; /* darkest */

legend1 shape=bar(.15in,.15in) noframe 
 label=(position=left 'Number of domains registered on that day:')
 /* only hard-code values like this, when you're sure the data isn't changing */
 value=(t=1 '1' t=2 '2');

title1 ls=1.5 "100 Oldest Still-existing Registered com Domains";
title2 link='https://en.wikipedia.org/wiki/.com'
       ls=0.3 "Data source: https://en.wikipedia.org/wiki/.com";
title3 ls=0.3 "Click dates to see domain names & info.";

footnote1 h=42pct " "; /* big space at bottom of page */

proc gmap data=my_data map=datemap all anno=my_anno;
id day;
choro count / levels=4 legend=legend1
 coutline=graycc cempty=graycc
 anno=outline html=htmlvar
 des='' name="&name";
run;

quit;
ODS HTML CLOSE;
ODS LISTING;



filename odsout '.' mod;
ods listing close;
ODS HTML path=odsout body="&name..htm" style=minimal options(pagebreak='no');

data domain_data; set domain_data;

length link $300 href $300;
 link='http://'||trim(left(domain_name));
 label link='Current URL';
 href = 'href="' || trim(left(link)) || '"';
 link = '<a ' || trim(href) || ' target="body">' || htmlencode(trim(domain_name)) || '</a>';

length link2 $300 href2 $300;
 link2='http://web.archive.org/web/*/http://'||trim(left(lowcase(domain_name)));
 label link2='Wayback Machine';
 href2 = 'href="' || trim(left(link2)) || '"';
 link2 = '<a ' || trim(href2) || ' target="body">' || htmlencode('Wayback versions of: '||trim(domain_name)) || '</a>';

run;

footnote h=1in " ";

%macro do_table(date);
ods html anchor="&date";
title;
proc print data=domain_data (where=(date=&date)) noobs label;
var date rank link link2;
run;
%mend;

proc sql noprint; create table foo as select unique date from domain_data; quit; run;
data _null_; set foo;
 call execute('%do_table('|| date ||');');
 call execute('run;');
run;

quit;
ods html close;
