diff --git a/Repositories/Maps/gd_map.pl b/Repositories/Maps/gd_map.pl new file mode 100755 index 0000000..5fec60d --- /dev/null +++ b/Repositories/Maps/gd_map.pl @@ -0,0 +1,127 @@ +#!/usr/bin/perl +use strict; +use CGI; +use DBI; +use GD; +use Geo::IP; +use Geo::Proj4; + + +my ($start_time) = time(); + +my ($page); + +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 ($mapimage, $mapimagefile); +my ($red, $white, $black, $blue); +my ($width, $height); + +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) = -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' ); + +$gi = Geo::IP->open( $gidb, GEOIP_STANDARD ) + 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"; + +$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 ); + +$connect = DBI->connect( $dsn, $user_name, $password, { RaiseError => 1 } ); + +$types{'download'} = $types{'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" : '' ); + +$stat = $connect->prepare( $query ); +$stat->execute(); +$num_rows = $stat->rows; + +if ( $num_rows > 0 ) +{ + $num_IPs = $num_rows if ( $num_IPs < 1 ); + + while ( $row = $stat->fetchrow_hashref() ) + { + $ip = $row->{'ip'}; + $count = $row->{'count'}; + $vtype = $row->{'view_type'}; + + $location = $gi->record_by_addr( $ip ); + + if ( defined( $location ) ) + { + $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); + + $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}{'count'} += $count; + $types{$vtype} += $count; + + $cities{$city}{'x'} = $x; + $cities{$city}{'y'} = $y; + } + } +} + +$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, $height - 15, 'Generated in ' . ( time() - $start_time ) . ' seconds', $black ); + +binmode(STDOUT); + +print $mapimage->jpeg(); + + +sub round +{ + my ($n) = shift; + return int( $n + .5 * ($n <=> 0) ); +}