diff --git a/tools/heatmaps/heatmap.pl b/tools/heatmaps/heatmap.pl new file mode 100755 index 0000000000..ae1a8a9812 --- /dev/null +++ b/tools/heatmaps/heatmap.pl @@ -0,0 +1,156 @@ +#!/usr/bin/perl -w +# +# $FreeBSD$ +# +# Script for parsing the xearth committers markers file and generating a +# heat map with countries of the world colored according to how many committers +# reside there. +# +# Creates an image of the following form : +# http://chart.apis.google.com/chart?chco=ffffff,ffbe38,600000&chd=s:BEICCFKEDBXICMMCBDBFPDBBBBBEDBBBBBQDBBJE9B&chf=bg,s,EAF7FE&chld=ARATAUBEBGBRCACHCNCZDEDKESFRGBGRHUIEINITJPKRKZMNMOMXMYNLNONZPEPLPTRORUSESISKTWUAUSZA&chs=440x220&cht=t&chtm=world +# +# See http://code.google.com/apis/chart/ +# +# Murray Stokely, March 30, 2008 +# + +use strict; + +my %country_iso3166 = ( + 'western australia', 'AU', + 'usa', 'US', + 'poland', 'PL', + 'canada', 'CA', + 'ukraine', 'UA', + 'sweden', 'SE', + 'uk', 'GB', + 'russia', 'RU', + 'bulgaria', 'BG', + 'switzerland', 'CH', + 'czech republic', 'CZ', + 'denmark', 'DK', + 'mexico', 'MX', + 'portugal', 'PT', + 'ca usa', 'US', + 'romania', 'RO', + 'india', 'IN', + 'malaysia', 'MY', + 'the netherlands', 'NL', + 'greece', 'GR', + 'spain', 'ES', + 'japan', 'JP', + 'taiwan', 'TW', + 'austria', 'AT', + 'brazil', 'BR', + 'hungary', 'HU', + 'south africa', 'ZA', + 'italy', 'IT', + 'belgium', 'BE', + 'france', 'FR', + 'mongolia', 'MN', + 'united kingdom', 'GB', + 'slovakia', 'SK', + 'peru', 'PE', + 'ireland', 'IE', + 'south korea', 'KR', + 'norway', 'NO', + 'australia', 'AU', + 'new zealand', 'NZ', + 'slovenia', 'SI', + 'macau sar', 'MO', + 'argentina', 'AR', + 'china', 'CN', + 'germany', 'DE', + 'kazakhstan', 'KZ', + ); + +sub printUsage() { + print STDERR "Usage : heatmap.pl <xearth markers file>\n\n"; +} + +# This is an encoding of data values from 0 to 61 into [A-Za-z0-9]. +# See http://code.google.com/apis/chart/#simple_values +sub simple_encode($) { + my $num = int($_[0]); + if ($num >= 0) { + if ($num <=25) { + return chr(ord('A')+$num); + } elsif ($num<=51) { + return chr(ord('a')+$num); + } elsif ($num<=61) { + return chr(ord('0') + $num - 52); + } else { + die "Can not simple encode $num!"; + } + } +} + +if ($#ARGV < 0) { + printUsage(); + exit; +} + +open(FIN, "$ARGV[0]") || die "Could not open $ARGV[0] : $!"; + +# ISO country code => number of committers from there. +my %country_hash; +foreach my $line (<FIN>) { + chomp $line; +# Match a line like this and extract number of usernames in quotes +# and human-readable country +# 37.40, -122.07, "murray" # (CORE) Mountain View, CA, USA + if ($line =~ m/\s*\d+\.\d+,?\s+-?\d+\.\d+,?\s*"([^"]+)"[^#]*#(.*)$/g) { + my @people = split(/\s*,\s*/, $1); + my $rawcountry = $2; + my $len = 0; + foreach my $person (@people) { + $len++ if ($person =~ m/\S+/); + } + if ($len == 0) { + print STDERR "Couldn't parse: $line\n"; + next; + } + my @components = split(/,/, $rawcountry); + my $country_name = $components[$#components]; + $country_name =~ s/^\s*//; + $country_name =~ s/\s*$//; + if ($country_iso3166{lc($country_name)}) { + $country_hash{$country_iso3166{lc($country_name)}} += $len; + } else { + print STDERR "Unknown ISO code for country: $country_name\n"; + } + } +} +close(FIN); + +my %worldmap; +# Parameters for the Charts API. +$worldmap{'chs'} = '440x220'; +$worldmap{'chco'} = 'ffffff,ffbe38,600000'; +$worldmap{'cht'} = 't'; +$worldmap{'chtm'} = 'world'; +$worldmap{'chld'} = ''; +$worldmap{'chd'} = 's:'; +$worldmap{'chf'} = 'bg,s,EAF7FE'; + +# country_hash - country name -> committers from there +# Find the largest number of committers in one country, so we can normalize +my $max_ppl = (reverse sort {$a <=> $b} values %country_hash)[0]; +my %country_pct; + +# country_pct - iso countr code -> pct committers from there. +foreach my $country (keys %country_hash) { + $country_pct{$country} = simple_encode(sprintf "%d", (((60 * $country_hash{$country}) / $max_ppl) + 1)); +} + +foreach my $key (sort (keys %country_pct)) { + $worldmap{'chld'} .= $key; + $worldmap{'chd'} .= $country_pct{$key}; +} + +my $CHART_URL = 'http://chart.apis.google.com/chart?'; +foreach my $key (sort (keys %worldmap)) { + $CHART_URL .= sprintf '%s=%s&', $key, $worldmap{$key}; +} +chop $CHART_URL; +print $CHART_URL;