- Added PHP to calling web pages.
- Now uses PHP microtime() function to calculate start time.
- Made start time an argument to the final JavaScript load function.
- Parameterised number of entries to retrieve from database.
- Added counts of unmappable IP addresses.
- Changed "num_IPs" to "num_entries".
- Corrected count of distinct IP addresses (was counting duplicates).
1 parent 762207f commit 491db6bf674b16103f0f4b0eabb2493e0822ccc7
nstanger authored on 12 May 2006
Showing 6 changed files
View
9
Repositories/Maps/gd_map.js
// Grab page initialisation time.
var startTime = new Date();
 
function imageLoaded()
function imageLoaded( startTime )
{
var endTime = new Date();
document.getElementById( "timer" ).innerHTML = 'Page generated in ' + ( endTime - startTime ) + ' ms.';
}
View
24
Repositories/Maps/gd_map.php
<?php
list( $start_micro, $start_sec ) = explode( " ", microtime() );
?>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html>
<head>
<body>
 
<h1>Repository hit visualisation using GD</h1>
 
<p>Stats current as of early afternoon 8 May 2006. You can also view the <a href="coordinates.pl?width=3599&amp;height=1826"><strong>REALLY BIG</strong> version</a>.</p>
<p>Stats current as of early afternoon 8 May 2006.</a>.</p>
 
<div id="timer"></div>
 
<p><img id="map" src="gd_map.pl?width=1024&amp;height=520" onLoad="imageLoaded()" width="1024" height="520" alt="Small version loading --- please wait..." /></p>
<p>
<?php
echo '<img id="map" src="gd_map.pl?width=1024&amp;height=520&amp;top='
. ( ( isset( $_REQUEST['top'] ) ) ? $_REQUEST['top'] : 10 )
. '" onLoad="imageLoaded('
. ( ( (float)$start_micro + (float)$start_sec ) * 1000 )
. ')" width="1024" height="520" alt="Small version loading --- please wait..." />';
?>
</p>
 
</body>
</html>
View
177
Repositories/Maps/gd_map.pl
use GD;
use Geo::IP;
use Geo::Proj4;
 
 
my ($start_sec, $start_micro) = gettimeofday;
my ( $start_sec, $start_micro ) = gettimeofday;
my ($start_time) = ( $start_sec * 1000 ) + round( $start_micro / 1000 );
 
my ($page);
 
my ($dsn) = "DBI:mysql:database=eprintstats;host=localhost";
my ($dsn) = "DBI:mysql:database=eprintstats;host=localhost";
my ($user_name) = "eprintstatspriv";
my ($password) = "AuldGrizzel";
my ($connect, $query, %types, $stat, $row, $num_rows, $vtype);
my ($password) = "AuldGrizzel";
my ( $connect, $query, %types, %unmapped, $stat, $row, $num_rows, $vtype );
 
my ($mapimage, $mapimagefile);
my ($red, $white, $black, $blue);
my ($width, $height);
my ( $mapimage, $mapimagefile );
my ( $red, $white, $black, $blue );
my ( $width, $height );
 
my ($gi, $proj);
my ( $gi, $proj );
my ($gidb) = '/usr/local/share/GeoIP/GeoLiteCity.dat';
 
my ($x_offset) = 16986796.16;
my ($y_offset) = 8615499.05;
my ($max_x) = $x_offset * 2;
my ($max_y) = $y_offset * 2;
my (%cities);
my ($num_IPs) = 100;
my ($num_hits) = 0;
my ($ip, $count, $location);
my ($city, $lat, $long, $x, $y);
 
my ($max_x) = $x_offset * 2;
my ($max_y) = $y_offset * 2;
my ( %cities, %IPs );
my ($num_entries) = -1;
my ($num_hits) = 0;
my ( $ip, $count, $location );
my ( $city, $lat, $long, $x, $y );
 
$page = new CGI;
print $page->header( -type=>"image/jpeg", -Pragma=>'no-cache' );
print $page->header( -type => "image/jpeg", -Pragma => 'no-cache' );
$num_entries = $page->param('top');
 
$gi = Geo::IP->open( $gidb, GEOIP_STANDARD )
or die "Unable to open GeoIP database $gidb\n";
or die "Unable to open GeoIP database $gidb\n";
 
$proj = Geo::Proj4->new( proj => "robin", ellps => "sphere", lon_0 => 10 )
or die "parameter error: " . Geo::Proj4->error . "\n";
or die "parameter error: " . Geo::Proj4->error . "\n";
 
$width = $page->param('width');
$height = $page->param('height');
$width = $page->param('width');
$height = $page->param('height');
$mapimagefile = "map_${width}x${height}.png";
$mapimage = GD::Image->newFromPng( $mapimagefile, 1 );
$white = $mapimage->colorAllocate( 255, 255, 255 );
$black = $mapimage->colorAllocate( 0, 0, 0 );
$red = $mapimage->colorAllocate( 255, 0, 0 );
$blue = $mapimage->colorAllocate( 0, 0, 255 );
$mapimage = GD::Image->newFromPng( $mapimagefile, 1 );
$white = $mapimage->colorAllocate( 255, 255, 255 );
$black = $mapimage->colorAllocate( 0, 0, 0 );
$red = $mapimage->colorAllocate( 255, 0, 0 );
$blue = $mapimage->colorAllocate( 0, 0, 255 );
 
$connect = DBI->connect( $dsn, $user_name, $password, { RaiseError => 1 } );
 
$types{'download'} = $types{'abstract'} = 0;
$query =
"SELECT ip, view_type, COUNT(*) AS count
$types{'download'} = $types{'abstract'} = 0;
$unmapped{'download'} = $unmapped{'abstract'} = 0;
$query = "SELECT ip, view_type, COUNT(*) AS count
FROM view
GROUP BY ip, view_type
ORDER BY count DESC" .
( $num_IPs > 0 ? " LIMIT $num_IPs" : '' );
ORDER BY count DESC" . ( ( $num_entries > 0 ) ? " LIMIT $num_entries" : '' );
 
$stat = $connect->prepare( $query );
$stat = $connect->prepare($query);
$stat->execute();
$num_rows = $stat->rows;
 
if ( $num_rows > 0 )
{
$num_IPs = $num_rows if ( $num_IPs < 1 );
$num_entries = $num_rows if ( $num_entries < 1 );
 
while ( $row = $stat->fetchrow_hashref() )
{
$ip = $row->{'ip'};
$ip = $row->{'ip'};
$count = $row->{'count'};
$vtype = $row->{'view_type'};
$location = $gi->record_by_addr( $ip );
if ( defined( $location ) )
 
$IPs{$ip} = 1;
 
$location = $gi->record_by_addr($ip);
 
if ( defined($location) )
{
$lat = $location->latitude;
$lat = $location->latitude;
$long = $location->longitude;
$city = $location->city;
($x, $y) = $proj->forward( $lat, $long );
$x = round(($x + $x_offset) / $max_x * $width);
$y = round(($y_offset - $y) / $max_y * $height);
( $x, $y ) = $proj->forward( $lat, $long );
$x = round( ( $x + $x_offset ) / $max_x * $width );
$y = round( ( $y_offset - $y ) / $max_y * $height );
 
$city = "Unknown ($lat, $long)" if ( $city eq '' );
 
if ( !defined( $cities{$city} ) )
{
$cities{$city}{'count'} = 0;
$cities{$city}{'lat'} = $lat;
$cities{$city}{'long'} = $long;
$mapimage->filledRectangle( $x - 1, $y - 1, $x + 1, $y + 1, ( $vtype eq 'download' ? $red : $blue ) );
$cities{$city}{'lat'} = $lat;
$cities{$city}{'long'} = $long;
 
$mapimage->filledRectangle( $x - 1, $y - 1, $x + 1, $y + 1,
( ( $vtype eq 'download' ) ? $red : $blue ) );
}
$cities{$city}{'count'} += $count;
$types{$vtype} += $count;
$types{$vtype} += $count;
 
$cities{$city}{'x'} = $x;
$cities{$city}{'y'} = $y;
}
else
{
$unmapped{$vtype} += $count;
}
}
}
 
$stat->finish();
$connect->disconnect();
$mapimage->string( gdSmallFont, 3, 3, "$types{'download'} downloads", $red );
$mapimage->string( gdSmallFont, 3, 15, "$types{'abstract'} abstracts", $blue );
$mapimage->string( gdSmallFont, 3, 27, 'from ' . scalar( keys %cities ) . ' cities', $black );
$mapimage->string( gdSmallFont, 3, 39, "($num_rows IP addresses)", $black );
 
$mapimage->string( gdSmallFont,
3, 3,
"$types{'download'} downloads"
. (
( $unmapped{'download'} > 0 )
? " (+$unmapped{'download'} unmappable)"
: ''
),
$red
);
$mapimage->string( gdSmallFont,
3, 15,
"$types{'abstract'} abstracts"
. (
( $unmapped{'abstract'} > 0 )
? " (+$unmapped{'abstract'} unmappable)"
: ''
),
$blue
);
$mapimage->string( gdSmallFont, 3, 27,
'from ' . scalar( keys %cities ) . ' cities', $black );
$mapimage->string( gdSmallFont, 3, 39,
'(' . scalar( keys %IPs ) . ' IP addresses)', $black );
 
my ( $finish_sec, $finish_micro ) = gettimeofday();
my ($finish_time) = ( $finish_sec * 1000 ) + round( $finish_micro / 1000 );
$mapimage->string( gdSmallFont, 3, $height - 15, 'Generated in ' . ( $finish_time - $start_time ) . ' ms', $black );
$mapimage->string( gdSmallFont, 3,
$height - 15,
'Generated in ' . ( $finish_time - $start_time ) . ' ms',
$black );
 
binmode( STDOUT );
binmode(STDOUT);
 
print $mapimage->jpeg();
 
 
sub round
{
my ($n) = shift;
return int( $n + .5 * ($n <=> 0) );
return int( $n + 0.5 * ( $n <=> 0 ) );
}
View
23
Repositories/Maps/google_map.js
// Grab page initialisation time.
var startTime = new Date();
 
function load()
function load( startTime, numEntries )
{
// Page initialisation time.
var startTime = new Date( startTime );
// Somewhere to write the timing information to.
var timer = document.getElementById( "timer" );
timer.innerHTML = "Loading...";
// <markers abs="200" dl="100" ips="27">
// <marker city="Timbuktu" lat="37.441" long="-122.141" abs="10" dl="0" />
// <marker city="West Bromwich" lat="37.322" long="-121.213" abs="22" dl="49" />
// </markers>
GDownloadUrl( "google_map_generate_data.pl",
GDownloadUrl( "google_map_generate_data.pl?top=" + numEntries,
function( data, responseCode )
{
var xml = GXml.parse( data );
var markerlist = xml.documentElement.getElementsByTagName( "marker" );
// Grab finishing time. We have to do this here rather than in
// the main part of the load() function because the map data
// are loaded asynchronously.
var endTime = new Date();
var numUA = xml.documentElement.getAttribute( "ua" );
var numUD = xml.documentElement.getAttribute( "ud" );
timer.innerHTML = '<span style="color:red;">' +
xml.documentElement.getAttribute( "dl" ) +
' downloads</span> & <span style="color:blue;">' +
' downloads' + ( ( numUD > 0 ) ? ( ' (' + numUD + ' unmappable)' ) : '' ) +
'</span> & <span style="color:blue;">' +
xml.documentElement.getAttribute( "abs" ) +
' abstracts</span> from ' +
' abstracts' + ( ( numUD > 0 ) ? ( ' (' + numUA + ' unmappable)' ) : '' ) +
'</span> from ' +
markerlist.length +
' cities (' +
xml.documentElement.getAttribute( "ips" ) +
' IP addresses), page generated in ' +
View
Repositories/Maps/google_map.php
View
Repositories/Maps/google_map_generate_data.pl