#!/usr/bin/perl

require "../cgi-lib.pl";
#require "../pagelib.pl";
ReadParse(*params);
use Data::Dumper;

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

if($ENV{REMOTE_HOST} !~ /ftiduser|intdata/ && !$params{password} && !$params{letmesee}) {
    print "Sorry, this page was taking up too much processing time from spiders! For any genuine humans out there, append &quot;?letmesee=1&quot; onto the URL, and you'll get data.<br>\n";
    exit(0);
}
my($dir) = '/home/dave/lego/top_sellers';
opendir(D,$dir);
my(@files) = readdir(D);
foreach my $f (@files) {
    next unless($f =~ /^top\.(\d+)$/);
    my($time) = $1;
    #next if($time > 1199163800); #only through roughly 23:59 Dec 31 2007
    if(!$min || $time < $min) { $min = $time; }
    if($time > $max) { $max = $time; }
    my($timestamp) = tstamp($time);
    push @{$raw_stamps{$timestamp}},$time;
    $valid_times{$timestamp}++;
    if($valid_times{$timestamp} > 1) {
	print "$timestamp has multiple times! ".join(",",@{$raw_stamps{$timestamp}})."<br>\n";
    }
    open(F,"$dir/$f");
    while(<F>) {
	chomp;
	my($pos,$id,$name) = split /\t/;
	$data{$id}{place}{$timestamp} = $pos;
	$data{$id}{name} = $name;
    }
    close F;
}
$t = $min;
$timestamp = tstamp($t);
$maxt = tstamp($max);
$max_time_on_list = 0; #The standard by which all other things will be judged!
foreach my $id (keys %data) {
    my(@ts) = sort {$a <=> $b} (keys %{$data{$id}{place}});
    $data{$id}{first_time} = $ts[0];
    $data{$id}{last_time} = $ts[$#ts];
    $data{$id}{time_on} = $ts[$#ts] - $ts[0] + 3600; #seconds on top 25 list
    if($data{$id}{time_on} > $max_time_on_list) {
	$max_time_on_list = $data{$id}{time_on};
    }
}
while($timestamp<=$maxt) {
    foreach my $id (keys %data) {
	if(!$data{$id}{place}{$timestamp}) {
	    if($valid_times{$timestamp}) {
		$data{$id}{place}{$timestamp} = -1;
	    } else {
		$data{$id}{place}{$timestamp} = $last_place{$id};
	    }
	}
	$data{$id}{total} += ($data{$id}{place}{$timestamp} > 0) ? $data{$id}{place}{$timestamp} : 26;
	if($timestamp >= $data{$id}{first_time}) {
	    $data{$id}{bal_total} += ($data{$id}{place}{$timestamp} > 0) ? $data{$id}{place}{$timestamp} : 26;
	}
	$last_place{$id} = $data{$id}{place}{$timestamp};
    }
    $t += (60*60);
    $timestamp = tstamp($t);
}
$num_times_on_list_for_max_id = 0;
foreach my $id (keys %data) {
    foreach my $ts (keys %{$data{$id}{place}}) {
	$data{$id}{"at_".$data{$id}{place}{$ts}}++;
	if($data{$id}{place}{$ts} >= 1 && $data{$id}{place}{$ts} <= 25) {
	    $data{$id}{tot_tally} += (26-$data{$id}{place}{$ts});
	    $data{$id}{num_times_on_list}++;
	}
	if($ts >= $data{$id}{first_time}) {
	    if($ts <= $data{$id}{last_time}) {
		$data{$id}{times_on_list}++; #Not number of times on list, duration of time spent on list
	    } else {
		$data{$id}{times_after_on_list}++;
	    }
	} else {
	    $data{$id}{times_before_on_list}++;
	}
    }
    if($data{$id}{time_on} == $max_time_on_list) {
	$num_times_on_list_for_max_id = $data{$id}{times_on_list};
    }
}
for(-1..26) {
    $minplace{$_} = 26;
}

#print "<table border=\"1\">\n";
$themes = def_themes();

print "<table cellspacing=0 cellpadding=1 border=1>\n";
print "<tr><td colspan=3 align=center><b>Average Set Position in Top 25</b></td></tr>";
foreach my $id (sort {
    return $data{$a}{total} <=> $data{$b}{total};
    if($data{$a}{place}{$maxt} < 0) {
	if($data{$b}{place}{$maxt} < 0) {
	    return $data{$a}{total} <=> $data{$b}{total};
	}
	return 1;
    }
    if($data{$b}{place}{$maxt} < 0) { return -1; }
    return $data{$a}{place}{$maxt}<=>$data{$b}{place}{$maxt}
} (keys %data)) {
    my($avg_place) = $data{$id}{total}/scalar(keys %{$data{$id}{place}});
    #$is_starwars = ($id =~ /^(765[456789]|620[5689]|621[012]|10030|101(34|4[34]|7[459])|3913|85146[24]|85193[89]|852085|GBA960|GC958|KC091|M229|NDS961|PC918|PS2935|PSP939|TS4[123456]|XB376|XB975|766[0123])$/) ? "sw" : "nsw";
    $is_starwars = ($themes->{sw}{ids} =~ /,\Q$id\E,/) ? "sw" : "nsw";
    print "<tr>\n";

    print "<td align=right nowrap><a href=\"http://shop.lego.com/Product/?p=$id\"><font size=-1>$id - $data{$id}{name}</font></a></td>\n";
    
    print "<td>";
    my($ftheme_flag) = 0;
    foreach my $theme (keys %{$themes}) {
	if($themes->{$theme}{ids} =~ /,$id,/) {
	    print "<font size=-1 color=#".$themes->{$theme}{color}.">$themes->{$theme}{name}<br></font>\n";
	    $ftheme_flag++;
	    $themes->{$theme}{tally}+=$data{$id}{tot_tally};
	    $themes->{$theme}{on_list_tally} += $data{$id}{num_times_on_list};
	}
    }
    if($ftheme_flag < 1) {
	print "<font color=red><b>NOT FOUND</b></font>";
    } elsif($ftheme_flag > 1) {
	print "<font color=red><b>EXTRA THEMES!</b></font>";
    }
    print "</td>\n";
    #if($is_starwars eq "sw") {
    #print " color=#FF0000";


    print "<td><font size=-1>".sprintf("%0.2f",($avg_place))."</font></td>\n";

    #in addition to "average place", there's "balanced average place", which
    #takes into account the fact that not every set was offered from the
    #beginning of time. Throw out all the data from before it was offered,
    #and include all the data after it left the list, up until the 'max'
    
    #print "<td>$data{$id}{times_before_on_list},$data{$id}{times_on_list},$data{$id}{times_after_on_list},$num_times_on_list_for_max_id</td>";
    my($bal_avg_place) = $data{$id}{bal_total}/($data{$id}{times_after_on_list}+$data{$id}{times_on_list});
    if(($data{$id}{times_after_on_list}+$data{$id}{times_on_list}) > $num_times_on_list_for_max_id) {
	$bal_avg_place = $data{$id}{bal_total}/$num_times_on_list_for_max_id;
    }
    print "<td nowrap><font size=-1>".sprintf("%.2f",($bal_avg_place))." for ".($data{$id}{times_after_on_list}+$data{$id}{times_on_list})."</font></td>\n";

    my($last) = undef;
    foreach my $ts (sort {$a<=>$b} (keys %{$data{$id}{place}})) {
	my($diff) = 0;
	if(defined($last) && $data{$id}{place}{$ts} != $last) {
	    if($data{$id}{place}{$ts} < 0) {
		$diff = abs(26-$last);
	    } elsif($last < 0) {
		$diff = abs(26-$data{$id}{place}{$ts});
	    } else {
		$diff = abs($data{$id}{place}{$ts} - $last);
	    }
	}
	$time_diffs{$ts}+=$diff;
	if($data{$id}{place}{$ts} <= 0) {
	} else {
	    $swdata{setdata}{$id}++;
	    $swdata{$is_starwars}++;
	    $swdata{$ts}{$data{$id}{place}{$ts}} = $is_starwars;
	    $hourly_sw{$ts}+=(($is_starwars eq "sw") ? 1 : 0);
	    foreach('r','g','b') {
	    }
	}
	if($maxplace{$data{$id}{place}{$ts}} < $avg_place) { $maxplace{$data{$id}{place}{$ts}} = $avg_place; }
	if($minplace{$data{$id}{place}{$ts}} > $avg_place) { $minplace{$data{$id}{place}{$ts}} = $avg_place; }
	$sumplace{$data{$id}{place}{$ts}} += $avg_place;
	$totplace{$data{$id}{place}{$ts}}++;
	$last = $data{$id}{place}{$ts};
    }
    print "<td bgcolor=".(($data{$id}{place}{$maxt} < 1 || $data{$id}{place}{$maxt} > 25) ? "#FFD0D0>Off" : "#D0FFD0>On")."</td>\n";
    print "<td><font size=-1>$data{$id}{tot_tally}</font></td>\n";
    print "<td><font size=-1>$data{$id}{num_times_on_list}</font></td>\n";
    print "<td><font size=-1>$swdata{setdata}{$id}</font></td>\n";
    print "<td><font size=-1>".++$placement."</font></td>\n";

    my($pmax) = 1;
    foreach my $place (1..25) {
	$pmax = $data{$id}{"at_$place"} if($data{$id}{"at_$place"} > $pmax);
    }
    foreach my $place (1..25) {
	print "<td><font size=-1 color=#";
	foreach('r','g','b') {
	    print sprintf("%02x",get_rgb_value(0,$pmax/2,$pmax,$data{$id}{"at_$place"},$_));
	}
	print ">".$data{$id}{"at_$place"}."</font></td>\n";
    }    
    print "</tr>\n";
}
print "</table>\n";

print "<br><br>\n";
print "<table>\n";
print "<tr><td align=center colspan=25><b>Number of Place Changes</b><br><hr></td></tr>\n";
print "<tr><td align=center>Date</td>\n";
for($i=0;$i<24;$i++) {
    print "<td><font size=-2>$i\:00</font></td>";
}
print "</tr>\n";
$t = $min;
$timestamp = tstamp($t);
$maxt = tstamp($max);
$lasthour = 0;
while($timestamp<=$maxt) {
    my($y,$m,$d,$h) = unpack('A4A2A2A2',$timestamp);
    if($h > 0 && $h != ($lasthour+1)) {
	print "<tr><td>$y$m$d</td>\n";
	$daily_total = 0;
	print "<td></td>" x $h;
    } elsif($h == 0) {
	print "<td>$daily_total</td>\n";
	print "</tr><tr><td>$y$m$d</td>\n";
	$daily_total = 0;
    }
    $daily_total+=$time_diffs{$timestamp};
    print "<td bgcolor=#";
    foreach('r','g','b') {
	print sprintf("%02x",get_rgb_value(0,7.5,15,$time_diffs{$timestamp},$_));
    }
    print ">";
    if($time_diffs{$timestamp} % 2) {
	print "<font color=#0000FF><b>";
    } elsif($time_diffs{$timestamp} > 30) {
	print "<font color=#FFFFFF>";
    }
    print "$time_diffs{$timestamp}";
    if($time_diffs{$timestamp} > 30) {
	print "</font>\n";
    }
    print "</td>";

    $lasthour = $h;
    $t += (60*60);
    my($old_stamp) = $timestamp;
    $timestamp = tstamp($t);
    if($old_stamp eq $timestamp) {
	#Daylight savings wierdness
	$t += (60*60);
	$timestamp = tstamp($t);
    }
}
print "</tr>\n";
print "</table>\n";
print "<br><br>\n";
print "Total Star Wars: $swdata{sw}<br>\nTotal Non Star Wars: $swdata{nsw}<br>\n";
print "Percentage Star Wars: ".sprintf("%.2f",(100*$swdata{sw})/($swdata{sw}+$swdata{nsw}))."\%<br>\n";
print "<br>\n";

print "<table border=1>\n";
$total_tally = 0;
$tot_times = 0;
foreach my $theme (keys %{$themes}) {
    $total_tally+=$themes->{$theme}{tally};
    $tot_times+=$themes->{$theme}{on_list_tally};
}
print "<tr><th>Theme</th><th>Weighted<br>Tally</th><th>Weighted Percentage</th><th>Unweighted<br>Tally</th><th>Unweighted Percentage</th></tr>\n";
foreach my $theme (sort {$themes->{$b}{tally} <=> $themes->{$a}{tally}} (keys %{$themes})) {
    print "<tr><td>$themes->{$theme}{name}</td>\n";
    print "<td>$themes->{$theme}{tally}</td>\n";
    print "<td>".($themes->{$theme}{tally}/$total_tally)."</td>\n";
    print "<td>".($themes->{$theme}{on_list_tally})."</td>\n";
    print "<td>".($themes->{$theme}{on_list_tally}/$tot_times)."</td>\n";
    print "</tr>\n";
}
print "</table>\n";

print "<table border=1>\n";
print "<tr><td colspan=4 align=center><b>Positional Average Position (Yeah, that!)</b></td></tr>\n";
print "<tr><td>Place</td>\n";
print "<td>Max</td>\n";
print "<td>Avg</td>\n";
print "<td>Min</td>\n";
print "</tr>\n";
for(-1..25) {
    next if($_ == 0);
    print "<tr>\n";
    print "<td>$_</td>\n";
    print "<td>$maxplace{$_}</td>\n";
    print "<td>".($sumplace{$_}/$totplace{$_})."</td>\n";
    print "<td>$minplace{$_}</td>\n";
    print "</tr>\n";
}

print "<br><br>\n";
if($params{sw}) {
    print "<table>\n";
    print "<tr><td align=center colspan=25><b>Number of Star Wars Sets In Top 25</b><br><hr></td></tr>\n";
    print "<tr><td align=center>Date</td>\n";
    for($i=0;$i<24;$i++) {
	print "<td><font size=-2>$i\:00</font></td>";
    }
    print "</tr>\n";
    $t = $min;
    $timestamp = tstamp($t);
    $maxt = tstamp($max);
    $lasthour = 0;
    while($timestamp<=$maxt) {
	my($y,$m,$d,$h) = unpack('A4A2A2A2',$timestamp);
	if($h > 0 && $h != ($lasthour+1)) {
	    print "<tr><td>$y$m$d</td>\n";
	    print "<td></td>" x $h;
	} elsif($h == 0) {
	    print "</tr><tr><td>$y$m$d</td>\n";
	}
	
	print "<td bgcolor=#";
	foreach('r','g','b') {
	    #print sprintf("%02x",get_rgb_value(0,12,25,$hourly_sw{$timestamp},$_));
	    print sprintf("%02x",get_rgb_value(4,10.5,17,$hourly_sw{$timestamp},$_));
	}
	print ">$hourly_sw{$timestamp}</td>\n";
	
	$lasthour = $h;
	$t += (60*60);
	my($old_stamp) = $timestamp;
	$timestamp = tstamp($t);
	if($old_stamp eq $timestamp) {
	    #Daylight savings wierdness
	    $t += (60*60);
	    $timestamp = tstamp($t);
	}
    }
    print "</tr>\n";
    print "</table>\n";
}

sub tstamp {
    my($time) = @_;
    my(@lt) = localtime($time);
    $lt[5]+=1900;
    $lt[4]++;
    return sprintf("%04d%02d%02d%02d",$lt[5],$lt[4],$lt[3],$lt[2]); #Don't care about minutes/seconds
}

sub get_rgb_value {
    my($min,$mid,$max,$val,$color) = @_;
    
    my($lowr,$midr,$highr) = (255,127,0); #Grey

    if($color eq "r") {    $lowr =  51; $midr = 230; $highr = 204; } #Red
    elsif($color eq "g") { $lowr = 153; $midr = 197; $highr =  51; } #Green
    elsif($color eq "b") { $lowr =  51; $midr =  42; $highr =  34; } #Blue

    #Calculate value
    my($color) =  ((($val-$mid)*($val-$max))/(($min-$mid)*($min-$max)))*$lowr;
    $color += ((($val-$min)*($val-$max))/(($mid-$min)*($mid-$max)))*$midr;
    $color += ((($val-$min)*($val-$mid))/(($max-$min)*($max-$mid)))*$highr;

    #Normalize
    $color = int $color;
    $color = $lowr if($val < $min);
    $color = $highr if($val > $max);
    $color = 255 if($color > 255);
    $color = 0 if ($color < 0);
    return $color;
}

sub def_themes {
    my(%themes) = (
		   'sw' => { name => "Star Wars", color => "FF0000", 
			     ids => ",3913,6205,6206,6209,6210,6211,6212,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676,7678,7679,7680,7681,7751,8014,8015,8016,8017,8018,8019,10030,10144,10174,10175,10178,10179,10186,10188,850353,851939,851659,852113,852085,852086,852355,852356,KC091,M229,", },
		   'tn' => { name => "Town/Modern", color => "0000FF",
			     ids => ",4210,4936,5610,5611,5612,5620,5621,7235,7236,7237,7241,7242,7244,7245,7246,7724,7731,7732,7733,7734,7736,7737,7738,7739,7741,7743,7744,7844,7876,7893,7902,7905,7907,7942,7945,7990,7991,7992,7993,9247,10156,10182,10184,10185,10190,", },
		   'sp' => { name => "Sports", color => "B0B0D0",
			     ids => ",3569,", },
		   'xf' => { name => "Exo Force", color => "FFC000",
			     ids => ",7700,7701,7702,7703,7709,7711,7714,", },
		   'bi' => { name => "Bionicle", color => "40C000",
			     ids => ",8624,8625,8685,8686,8687,8688,8689,8691,8692,8693,8694,8695,8696,8697,8699,8721,8722,8723,8725,8727,8728,8729,8730,8731,8755,8761,8904,8910,8912,8913,8914,8915,8920,8935,8911,8924,8939,8944,8952,8953,8979,8980,8982,851975,K8688,K8915,H107,", },
		   'vk' => { name => "Vikings", color => "4040C0",
			     ids => ",7016,7019,7020,7021,G577,", },
		   'cs' => { name => "Other Castle", color => "C0C040",
			     ids => ",8705,8706,8791,10176,10193,", },
		   'nc' => { name => "Castle - Fantasy", color => "C0C040",
			     ids => ",5615,5618,7009,7029,7036,7037,7038,7040,7041,7090,7091,7092,7093,7094,852001,852003,852009,852132,852231,852271,852272,", },
		   'cr' => { name => "Creator", color => "C000C0",
			     ids => ",4415,4416,4417,4418,4837,4838,4884,4892,4896,4916,4954,4956,4996,", },
		   'aq' => { name => "Aquazone", color => "8080FF",
			     ids => ",7770,7776,", },
		   'hp' => { name => "Harry Potter", color => "808080",
			     ids => ",5378,", },
		   'ft' => { name => "Factory", color => "00C0FF",
			     ids => ",5524,5525,10191,10200,", },
		   'bt' => { name => "Batman", color => "000040",
			     ids => ",7779,7784,7785,7884,7888,", },
		   'rc' => { name => "Racers", color => "FF8080",
			     ids => ",8148,8149,8150,8151,8654,8668,8669,8672,8682,", },
		   'tr' => { name => "Trains", color => "C000FF",
			     ids => ",2159,4515,4519,4520,4531,4548,10133,10153,10173,K10183,", },
		   'sb' => { name => "Sponge Bob", color => "FFFF80",
			     ids => ",3832,4981,", },
		   'mm' => { name => "Mars Mission", color => "FFC080",
			     ids => ",5616,5619,7647,7690,7693,7694,7695,7699,", },
		   'dq' => { name => "Duplo/Quatro", color => "6060C0",
			     ids => ",3300,3301,4422,5476,5556,BAG14,", },
		   'tc' => { name => "Technic", color => "C04040",
			     ids => ",8275,8146,8527,8883,", },
		   'nl' => { name => "Non-Lego", color => "808000",
			     ids => ",851903,851917,851918,851951,851955,852019,EL709,G574,KBM26,KBM27,NDS061,PS3038,WII063,", },
		   'bv' => { name => "Belville", color => "FFC0C0",
			     ids => ",7600,", },
		   'ij' => { name => "Indiana Jones", color => "FFB000",
			     ids => ",7620,7621,7622,7623,7624,7625,7626,7627,7628,7682,K7623,852145,", },
		   'sr' => { name => "Speed Racer", color => "FFB000",
			     ids => ",8158,8159,8160,8161,", },
		   'ag' => { name => "Agents", color => "000080",
			     ids => ",8631,8635,", },
		   'pm' => { name => "Power Miners", color => "40FF40",
			     ids => ",8956,8957,8958,", },
		   'mt' => { name => "Model Team/Advanced", color => "000000",
			     ids => ",10187,10189,", },
		   'pi' => { name => "Pirates", color => "000000",
			     ids => ",6239,6240,6241,6242,6243,6253,8396,8397,", },
		   'ac' => { name => "Other", color => "800080",
			     ids => ",626,628,3461,3471,3472,5585,6112,6166,6167,6177,10071,10168,10169,BAG2,BAG3,BAG4,K3731,LFH101,LFH002,850150,", },
		   );
    return \%themes;
}
