#!/usr/bin/perl -w

my @games=(
	   {
	       name=>'Sonic 1',
	       levels=>[
			'Green Hill',
			'Marble',
			'Spring Yard',
			'Labyrinth',
			'Star Light',
			'Scrap Brain',
			'S1 Final',
			],
	       },
	   {
	       name=>'Sonic 2',
	       levels=>[
			'S2 Title',
			'Emerald Hill',
			'Chemical Plant',
			'Aquatic Ruin',
			'Casino Night',
			'Hill Top',
			'Mystic Cave',
			'Oil Ocean',
			'Metropolis',
			'Sky Chase',
			'Wing Fortress',
			'Death Egg',
			'Mystic Cave (2 Player)',
			'S2 Badguy',
			'S2 Final Badguy',
			'S2 Special Stage',
			'S2 Beh Heh',
			'S2 Credits',
			'S2 Options',
			],
	       },
	   {
	       name=>'Sonic 3',
	       levels=>[
			'S3 Title',
			'Angel Island 1',
			'Angel Island 2',
			'Hydrocity 1',
			'Hydrocity 2',
			'Marble Garden 1',
			'Marble Garden 2',
			'Carnival Night 1',
			'Carnival Night 2',
			'Icecap 1',
			'Icecap 2',
			'Launch Base 1',
			'Launch Base 2',
			'Azure Lake',
			'Balloon Park',
			'Chrome Gadget',
			'Desert Palace',
			'Endless Mine',
			'S3 Special Stage',
			'S3 Continue',
			'S3 Final Badguy',
			'Spheres Bonus Stage',
			'Fruit Machine Bonus Stage',
			'Gumball Machine Bonus Stage',
			'S3 Save Slot Menu',
			'S3 Competition Select',
			'S3 Credits',
			],
	       },
	   {
	       name=>'Sonic & Knuckles',
	       levels=>[
			'S&K Title',
			'Mushroom Hill 1',
			'Mushroom Hill 2',
			'Flying Battery 1',
			'Flying Battery 2',
			'Sandopolis 1',
			'Sandopolis 2',
			'Lava Reef 1',
			'Lava Reef 2 (Hidden Palace)',
			'Sky Sanctuary',
			'Death Egg 1',
			'Death Egg 2',
			'Doomsday',
			'S&K Special Stage',
			'Knuckles',
			],
	       },
	   {
	       name=>'Sonic 3D',
	       levels=>[
			'S3D Title',
			'Green Grove 1',
			'Green Grove 2',
			'Rusty Ruin 1',
			'Rusty Ruin 2',
			'Spring Stadium 1',
			'Spring Stadium 2',
			'Diamond Dust 1',
			'Diamond Dust 2',
			'Volcano Valley 1',
			'Volcano Valley 2',
			'Gene Gadget 1',
			'Gene Gadget 2',
			'Panic Puppet 1',
			'Panic Puppet 2',
			'The Final Fight',
			'S3D Special Stage',
			'S3D Credits',
			],
	       },
	   );

my %tests=(
	   'Sonic 3'=>[
	    '',
	    'Angel Island 1',
	    'Angel Island 2',
	    'Hydrocity 1',
	    'Hydrocity 2',
	    'Marble Garden 1',
	    'Marble Garden 2',
	    'Carnival Night 1',
	    'Carnival Night 2',
	    'Flying Battery 1',
	    'Flying Battery 2',
	    'Icecap 1',
	    'Icecap 2',
	    'Launch Base 1',
	    'Launch Base 2',
	    'Mushroom Hill 1',
	    'Mushroom Hill 2',
	    'Sandopolis 1',
	    'Sandopolis 2',
	    'Lava Reef 1',
	    'Lava Reef 2 (Hidden Palace)',
	    'Sky Sanctuary',
	    'Death Egg 1',
	    'Death Egg 2',
	    'Badguy',
	    'Badguy 2',
	    'Doomsday',
	    'Spheres Bonus Stage',
	    'S3 Special Stage',
	    'Fruit Machine Bonus Stage',
	    'Gumball Machine Bonus Stage',
	    'Knuckles',
	    'Azure Lake',
	    'Balloon Park',
	    'Desert Palace',
	    'Chrome Gadget',
	    'Endless Mine',
	    'S3 Title',
	    'S3 Credits',
	    'S3 Game Over',
	    'S3 Continue',
	    'S3 Level Complete',
	    'S3 Extra Life',
	    '',
	    'S3 Invulnerability',
	    'S3 Competition Select',
	    'S3 Zone 1 Badguy',
            'S3 Save Menu',
	    'S3 Final Badguy',
	    'S3 Drowning',
	    'S3 Complete',
	    ],
	   'Sonic 2'=>
	   [
	    '',
	    '?',
	    'Emerald Hill',
	    'Mystic Cave (2 Player)',
	    'Oil Ocean',
	    'Metropolis',
	    'Hill Top',
	    'Aquatic Ruin',
	    'Casino Night (2 Player)',
	    'Casino Night',
	    'Death Egg',
	    'Mystic Cave',
	    'Emerald Hill (2 Player)',
	    'Sky Chase',
	    'Chemical Plant',
	    'Wing Fortress',
	    'Hidden Palace',
	    'S2 Options',
	    'S2 Special Stage',
	    'S2 Badguy',
	    'S2 Final Badguy',
	    'S2 Beh Heh',
	    'S2 Super Sonic',
	    'S2 Invulnerability',
	    'S2 Extra Life',
	    'S2 Title',
	    'S2 Complete',
	    'S2 Game Over',
	    'S2 Continue',
	    '',
	    'S2 Credits',
	    'S2 Drowning',
	    ],
	   'Sonic 3D'=>
	   [
	    '',
	    'Green Grove 1',
	    'Green Grove 2',
	    'Rusty Ruin 1',
	    'Rusty Ruin 2',
	    'Volcano Valley 2',
	    'Volcano Valley 1',
	    'Spring Stadium 1',
	    'Spring Stadium 2',
	    'Diamond Dust 1',
	    'Diamond Dust 2',
	    'Gene Gadget 1',
	    'Gene Gadget 2',
	    'Panic Puppet 2',
	    'The Final Fight',
	    '?',
	    'S3D Special Stage',
	    'Panic Puppet 1',
	    '?',
	    'S3D Badguy',
	    'S3D Title',
	    '?',
	    'S3D Game Over',
	    'S3D Continue',
	    'S3D Level Complete',
	    'S3D Extra Life',
	    '',
	    'S3D Invulnerability',
	    'S3D Options',
	    ],
	   );

my @mods=(
#	  {
#	      file=>'marblegarden.mod',
#	      author=>'K',
#	      level=>'Marble Garden 1',
#	  },
#	  {
#	      file=>'s3_icecap.mod',
#	      author=>'K',
#	      level=>'Icecap 1',
#	  },
#	  {
#	      file=>'launchbase.mod',
#	      author=>'K',
#	      level=>'Launch Base 1',
#	  },
#	  {
#	      file=>'flyingbattery.mod',
#	      author=>'K',
#	      level=>'Flying Battery 1',
#	  },
	  {
	      file=>'sk_doomsday.xm',
	      author=>'K',
	      level=>'Doomsday',
	  },
	  {
	      file=>'sk_deathegg1.it',
	      author=>'kip',
	      level=>'Death Egg 1',
	  },
	  {
	      file=>'s2_emeraldhill.it',
	      author=>'bruce',
	      level=>'Emerald Hill',
	  },
#	  {
#	      file=>'s2_metropolis.it',
#	      author=>'bruce',
#	      level=>'Metropolis',
#	  },
	  {
	      file=>'s2_final.it',
	      author=>'bruce',
	      level=>'S2 Final Badguy',
	  },
	  {
	      file=>'s3_hydrocity.xm',
	      author=>'H',
	      level=>'Hydrocity 1',
	  },
	  {
	      file=>'sk_skysanctuary.it',
	      author=>'K',
	      level=>'Sky Sanctuary',
	  },
	  {
	      file=>'sk_lavareef.it',
	      author=>'bruce',
	      level=>'Lava Reef 1',
	  },
	  {
	      file=>'s2_chemicalplant.it',
	      author=>'bruce',
	      level=>'Chemical Plant',
	  },
	  {
	      file=>'s3_hydrocity2.it',
	      author=>'bruce',
	      level=>'Hydrocity 2',
	  },
	  {
	      file=>'s1_starlight.it',
	      author=>'bruce',
	      level=>'Star Light',
	  },
	  {
	      file=>'s3d_diamonddust1.xm',
	      author=>'kip',
	      level=>'Diamond Dust 1',
	  },
	  {
	      file=>'s2_mysticcave.xm',
	      author=>'kip',
	      level=>'Mystic Cave',
	  },
	  {
	      file=>'s1_final.it',
	      author=>'kip',
	      level=>'S1 Final',
	  },
	  {
	      file=>'s1_labyrinth.it',
	      author=>'kip',
	      level=>'Labyrinth',
	  },
	  {
	      file=>'s1_scrapbrain.it',
	      author=>'kip',
	      level=>'Scrap Brain',
	  },
	  {
	      file=>'s1_greenhill.it',
	      author=>'bruce',
	      level=>'Green Hill',
	  },
	  {
	      file=>'s3_balloonpark.it',
	      author=>'K',
	      level=>'Balloon Park',
	  },
	  {
	      file=>'s2_aquaticruin.it',
	      author=>'kip',
	      level=>'Aquatic Ruin',
	  },
	  {
	      file=>'s3d_genegadget2.it',
	      author=>'kip',
	      level=>'Gene Gadget 2',
	  },
	  {
	      file=>'s2_casinonight.it',
	      author=>'bruce',
	      level=>'Casino Night',
	  },
	  {
	      file=>'sk_spheres.it',
	      author=>'K',
	      level=>'Spheres Bonus Stage',
	  },
	  {
	      file=>'s2_deathegg.it',
	      author=>'K',
	      level=>'Death Egg',
	  },
	  {
	      file=>'s3_endlessmine.it',
	      author=>'bruce',
	      level=>'Endless Mine',
	  },
	  {
	      file=>'sk_deathegg2.it',
	      author=>'bruce',
	      level=>'Death Egg 2',
	  },
	  {
	      file=>'s3_carnivalnight1.it',
	      author=>'bruce',
	      level=>'Carnival Night 1',
	  },
	  {
	      file=>'s3_carnivalnight2.it',
	      author=>'bruce',
	      level=>'Carnival Night 2',
	  },
	  {
	      file=>'s1_marble.it',
	      author=>'bruce',
	      level=>'Marble',
	  },
	  {
	      file=>'s1_springyard.it',
	      author=>'bruce',
	      level=>'Spring Yard',
	  },
	  {
	      file=>'s2_mysticcave-2player.it',
	      author=>'K',
	      level=>'Mystic Cave (2 Player)',
	  },
	  {
	      file=>'s3_angelisland2.it',
	      author=>'K',
	      level=>'Angel Island 2',
	  },
	  {
	      file=>'s3_credits.it',
	      author=>'K',
	      level=>'S3 Credits',
	  },
	  {
	      file=>'s3_final.it',
	      author=>'kip',
	      level=>'S3 Final Badguy',
	  },
	  {
	      file=>'s3_launchbase1.it',
	      author=>'K',
	      level=>'Launch Base 1',
	  },
	  {
	      file=>'s3_launchbase2.it',
	      author=>'K',
	      level=>'Launch Base 2',
	  },
	  {
	      file=>'s3_marblegarden1.it',
	      author=>'K',
	      level=>'Marble Garden 1',
	  },
	  {
	      file=>'sk_flyingbattery1.it',
	      author=>'K',
	      level=>'Flying Battery 1',
	  },
	  {
	      file=>'s3d_final.it',
	      author=>'K',
	      level=>'The Final Fight',
	  },
	  {
	      file=>'s2_metropolis.it',
	      author=>'bruce',
	      level=>'Metropolis',
	  },
	  {
	      file=>'s3_azurelake.it',
	      author=>'bruce',
	      level=>'Azure Lake',
	  },
	  {
	      file=>'s2_specialstage.it',
	      author=>'bruce',
	      level=>'S2 Special Stage',
	  },
	  {
	      file=>'sk_knuckles.it',
	      author=>'K',
	      level=>'Knuckles',
	  },
	  {
	      file=>'s3_icecap1.it',
	      author=>'K',
	      level=>'Icecap 1',
	  },
	  {
	      file=>'s3_icecap2.it',
	      author=>'K',
	      level=>'Icecap 2',
	  },
	  {
	      file=>'s3d_greengrove2.it',
	      author=>'K',
	      level=>'Green Grove 2',
	  },
	  {
	      file=>'s3_savemenu.it',
	      author=>'K',
	      level=>'S3 Save Slot Menu',
	  },
	  {
	      file=>'s2_options.it',
	      author=>'K',
	      level=>'S2 Options',
	  },
	  {
	      file=>'sk_hiddenpalace.it',
	      author=>'bruce',
	      level=>'Lava Reef 2 (Hidden Palace)',
	  },
	  {
	      file=>'s2_hilltop.it',
	      author=>'bruce',
	      level=>'Hill Top',
	  },
	  {
	      file=>'s2_wingfortress.it',
	      author=>'K',
	      level=>'Wing Fortress',
	  },
	  {
	      file=>'s3_marblegarden2.it',
	      author=>'bruce',
	      level=>'Marble Garden 2',
	  },
	  {
	      file=>'s3_angelisland1.it',
	      author=>'K',
	      level=>'Angel Island 1',
	  },
	  {
	      file=>'s3_chromegadget.xm',
	      author=>'kip',
	      level=>'Chrome Gadget',
	  },
	  {
	      file=>'sk_mushroomhill1.it',
	      author=>'K',
	      level=>'Mushroom Hill 1',
	  },
	  {
	      file=>'sk_mushroomhill2.it',
	      author=>'kip',
	      level=>'Mushroom Hill 2',
	  },
	  {
	      file=>'s3_invincibility.it',
	      author=>'bruce',
	      level=>'S3 Invulnerability',
	  },
	  {
	      file=>'s2_continue.it',
	      author=>'bruce',
	      level=>'S2 Continue',
	  },

	  );

my %claims=(
	    'Sandopolis 2'=>'kip',
	    'S&K Special Stage'=>'kip',
	    'S3D Credits'=>'bruce',
);	    

my %authors=( 
    H=>'HEx',
    K=>'Kinetic',
    kip=>'Kipling',
    bruce=>'Bruce',
);

my %exts=(
    mod=>'Protracker',
    xm=>'XM',
    it=>'IT',
    med=>'OctaMed',
);

my %levs=map {$_->{level},$_} @mods;

# print the list of levels

use CGI qw[:standard start_ul end_ul start_dl end_dl start_li end_li start_table escape escapeHTML];

local $";

sub filename { "$_[0].gz" }

sub lev {
    my $l=$levs{$_[0]};
    $l?a({href=>escape($l->{file}.".gz")},escapeHTML $_[0]):escapeHTML $_[0];
}

sub game {
    (map {(grep {$_ eq $_[0]} @{$_->{levels}})?$_->{name}:()} @games)[0];
}

print start_html{lang=>'en-GB',title=>'Sonic Project'};
print h1 'Sonic Project';

print h2 'The Mission';
print p "All Sonic tunes must be tracked (and tracked ".i('accurately').")! Our group of covert operatives work ceaselessly, dedicated to this all-important task.";

print h2 'The Tunes';

# sound tests
my @testgames=grep {$tests{$_}} map {$_->{name}} @games;
my $maxtests=0;
map{$maxtests=$_ if $_>$maxtests} map{@$_-1} values %tests;

print start_table{style=>'float: right',summary=>'Sound test numbers',border=>1};

print Tr[th{colspan=>1+@testgames},'Tunes by sound test number'];
print Tr[th['No.',@testgames]];
for my $n (1..$maxtests) {
    print Tr td[sprintf('%02X',$n),map {lev $tests{$_}[$n]} @testgames];
}
print end_table;

for my $game (@games) {
    print h3 escapeHTML $game->{name};
    print start_ul;
    for my $lev (@{$game->{levels}}) {
	print li lev($lev);
    }
    print end_ul;
}

print h2 'The Tracks';

my @fields=('Game','Level','File','Author','Format','Size');
print start_table{border=>1,summary=>'Tracks'};
print Tr th[@fields];
for my $mod (@mods) {
    print Tr[
	     td [map {
		 {
		     Game=>escapeHTML(game($mod->{level})),
		     Level=>escapeHTML($mod->{level}),
		     File=>do{my $f=filename $mod->{file};-s $f?a{href=>escape$f},escapeHTML$mod->{file}:escapeHTML$mod->{file}},
		     Author=>$authors{$mod->{author}},
		     Size=>(-s filename $mod->{file}),
		     Format=>($mod->{file}=~/\.(.*?)$/?$exts{$1}:'???'),
}->{$_}
} @fields]
];
}

print end_table;
print p "Or download the lot in a ".a({href=>'sonic.tar.gz'},"fscking huge tarball")." (by popular request!).";

print h2 'Pending';
print start_table{border=>1,summary=>'Pending'};
print Tr th['Game','Level','Claimed by'];
for my $claim (sort keys %claims) {
    print Tr td[escapeHTML(game($claim)),escapeHTML($claim),$authors{$claims{$claim}}],
}
print end_table;

print h2 'Administrivia';
print p "The ".a({href=>'sonic.pl'},"perl script")." that generates this page, and its associated ".a({href=>'Makefile'},"Makefile").".";
use POSIX;
print p strftime"Last modified on %a, %d %b %Y at %T (%z).",localtime;
#print p "Canonical URL for this page is ",(map {a{href=>$_},$_} 'http://sphere.chronosempire.org.uk/~HEx/sonic/'),'.';
print hr, p i(map{a{href=>$_},$_}'mailto:hex@freezone.co.uk'),'.';
print end_html;

