#!/s/std/bin/perl

#<xmp> This comment helps some browsers correctly render this source code

use lib '/usr3/chaos/perl/lib';
use CGI qw(:standard);
require 'look.pl';

@Names = param;

print "Content-type: text/html\n\n";

if(!defined($Names[0]))
{
	print <<_EOT;
<HTML><HEAD><TITLE>Wisconsin Driver's License Number Analyzer</TITLE></HEAD>
<BODY BGCOLOR=FFFFFF>
<H1>Wisconsin Driver's License Number Analyzer</H1>

It turns out that your Wisconsin Driver's License (or
State ID) Number is a hash of your name, gender, and
date of birth.  This program can take any legal 
Wisconsin Driver's License number, and will figure out
as much as possible about you.
<P>
(If you like, you can
<A HREF="http://www.upl.cs.wisc.edu/cgi-bin/wilic">generate
a Wisconsin Driver's License Number</A> given any name, date of
birth, and gender.)

<FORM ACTION="http://www.upl.cs.wisc.edu/cgi-bin/wilicr" METHOD=GET>
License Number: <INPUT TYPE="TEXT" SIZE=17 NAME="INPUT" MAXLENGTH=17><BR>
<input type=submit value="Submit">
<input type=reset value="Reset">
</FORM>

</BODY></HTML>

_EOT

	exit(0);

}

$Input = param('INPUT');
$Input =~ s/-//g;
($Last, $FirstMiddle, $YearTen, $YearOne, $Day, $Other) =
	($Input =~ /(....)(...)(.)(.)(...)(..)/);

if(!defined $Last)
{
	print <<_EOE;
<HTML><HEAD><TITLE>Error</TITLE></HEAD>
<BODY BGCOLOR=FFFFFF>
<H1>Error</H1>

That didn't look like a Wisconsin Driver's License Number.
It should look something like D253-0017-5096-03.  (That's
<A HREF="http://www.upl.cs.wisc.edu/~chaos/">the author</A>'s
number, if you care.)

</BODY></HTML>

_EOE
	exit(0);
}

$ThisYear = ((gmtime(time))[5]);

$Gender = &Gender($Day);
$LastName = &LastNameDescribe($Last);
$LastNameSound = &LastNameSound($Last);
$FirstName = &FirstName($FirstMiddle, $Gender);
if(length($FirstName) == 1) { $FirstName .= '.'; }
$MiddleInit = &MiddleInit($FirstMiddle).'.';
$DOBMonth = &MonthName($Day);
$DOBDay = &Day($Day);
$DOBYear = $YearTen.$YearOne;
if($DOBYear > $ThisYear){ $DOBCentury = 18; }
else					{ $DOBCentury = 19; }
$Other += 0;
$SimilarLastNames = &SimilarLastNames($Last);

print <<_EOT;
<HTML><HEAD><TITLE>Wisconsin Driver's License Analysis</TITLE></HEAD>
<BODY BGCOLOR=FFFFFF>
<H1>Wisconsin Driver's License Analysis</H1>

<STRONG>License Number:</STRONG> $Last-$FirstMiddle$YearTen-$YearOne$Day-$Other<P>
<STRONG>First Name (or Initial):</STRONG> $FirstName<P>
<STRONG>Middle Initial:</STRONG> $MiddleInit<P>
<STRONG>Last Name Pronunciation:</STRONG> $LastName
                (Perhaps it sounds like $LastNameSound)<P>
<STRONG>Last Name Guesses: </STRONG>$SimilarLastNames<P>
<STRONG>Gender:</STRONG>         $Gender<P>
<STRONG>Date of Birth:</STRONG>  $DOBMonth $DOBDay, $DOBCentury$DOBYear<P>

When you got your license, $Other other people had already
received license numbers the same as yours (excepting the
last two digits).
</BODY></HTML>
_EOT

sub SimilarLastNames
{
	my($Soundex, $Biff) = @_;
	open(INDEX,"/usr3/chaos/public_html/soundex.data") or die "Failed to find soundex index.";
	&look(*INDEX, $Soundex, 0, 0);
	$Biff = <INDEX>;
	($Biff) = ($Biff =~ /.+\t(.+)/);
	close(INDEX);
	return($Biff);
}

sub LastNameDescribe
{
	my($Name) = @_;
	my($Return, @Parts, $This);

	@Parts = split(//,$Name);

	$Return = 'Starts with a '.shift(@Parts);
	while($This = shift(@Parts))
	{
		$Return .= ', followed by a ';
		if   ($This == 1) { $Return .= 'labial'; }
		elsif($This == 2) { $Return .= 'gutteral or sibilant'; }
		elsif($This == 3) { $Return .= 'dental'; }
		elsif($This == 4) { $Return .= 'long liquid'; }
		elsif($This == 5) { $Return .= 'nasal'; }
		elsif($This == 6) { $Return .= 'short liquid'; }
	}
	$Return .= '.';
	return($Return);
}

sub LastNameSound
{
	my($Name) = @_;
	my($Return, @Parts, $This);
	@Parts = split(//,$Name);
	$Return = shift(@Parts).'e';
	while($This = shift(@Parts))
	{
		if   ($This == 1) { $Return .= 'be'; } #bfpv
		elsif($This == 2) { $Return .= 'se'; } #cgjkqsxz
		elsif($This == 3) { $Return .= 'te'; } #td
		elsif($This == 4) { $Return .= 'le'; } #l
		elsif($This == 5) { $Return .= 'me'; } #mn
		elsif($This == 6) { $Return .= 're'; } #r
	}
	return($Return);
}

sub Day
{
	my($Input) = @_;
	$Input %= 500;
	return($Input % 40);
}

sub MonthNum
{
	my($Input) = @_;
	$Input %= 500;
	return(($Input - &Day($Input)) / 40 + 1);
}

sub MonthName
{
	my($Input) = @_;
	my(@Month);
	@Month = ( 'January', 'February', 'March', 'April', 'May', 'June',
		'July', 'August', 'September', 'October', 'November', 'December' );
	return(@Month[&MonthNum - 1]);

}

sub Gender
{
	my($Input) = @_;
	if($Input > 500)	{ return('Female'); }
	else				{ return('Male'); }
}

sub FirstName
{
	my($Input, $Gender) = @_;
	my(%Male, %Female, %FirstInit);
	my($Name);
	%Male = (
		120=>'Carl', 140=>'Charles', 180=>'Donald', 20=>'Albert',
		220=>'Edward', 260=>'Frank', 300=>'George', 340=>'Harold',
		360=>'Harry', 380=>'Henry', 40=>'Arthur', 440=>'James',
		460=>'John', 480=>'Joseph', 560=>'Martin', 580=>'Marvin',
		600=>'Melvin', 680=>'Paul', 740=>'Richard', 760=>'Robert',
		80=>'Bernard', 820=>'Thomas', 900=>'Walter', 920=>'William',
	);
	%Female = (
		120=>'Catherine', 140=>'Clara', 180=>'Dorothy', 20=>'Alice',
		220=>'Elizabeth', 260=>'Florence', 300=>'Grace', 340=>'Harriet',
		360=>'Hazel', 380=>'Helen', 40=>'Ann, Anna, Anne, Annie',
		440=>'Jane, Jayne', 460=>'Jean', 480=>'Joan', 580=>'Mary',
		600=>'Mildred', 680=>'Patricia', 740=>'Ruby', 760=>'Ruth',
		80=>'Bette, Bettie, Betty', 820=>'Thelma', 900=>'Wanda', 920=>'Wilma',
	);
	%FirstInit = (
		0 => 'A', 60 => 'B', 100 => 'C', 160 => 'D', 200 => 'E', 240 => 'F',
		280 => 'G', 320 => 'H', 400 => 'I', 420 => 'J', 500 => 'K', 520 => 'L',
		540 => 'M', 620 => 'N', 640 => 'O', 660 => 'P', 700 => 'Q', 720 => 'R',
		780 => 'S', 800 => 'T', 840 => 'U', 860 => 'V', 880 => 'W', 940 => 'X',
		960 => 'Y', 980 => 'Z',
	);

	$Input -= $Input%20;
 	if(defined($Male{$Input}))
 	{
		if($Gender eq 'Male')	{ $Name = $Male{$Input};   }
		else					{ $Name = $Female{$Input}; }
	}
 	else
 		{ $Name = $FirstInit{$Input}; }
	return($Name);
}

sub MiddleInit
{
	my($Input) = @_;
	my(%MiddleInit);

	$Input %= 20;
	%MiddleInit = (
		1 => 'A', 2 => 'B', 3 => 'C', 4 => 'D', 5 => 'E', 6 => 'F', 7 => 'G',
		8 => 'H', 9 => 'I', 10 => 'J', 11 => 'K', 12 => 'L', 13 => 'M',
		14 => 'N or O', 15 => 'P or Q', 16 => 'R', 17 => 'S',
		18 => 'T, U, or V', 19 => 'W, X, Y, or Z',
	);

	return($MiddleInit{$Input});
}
#</xmp>
