|
|
|
use v5.30;
|
|
|
|
|
|
|
|
use MediaWiki::API;
|
|
|
|
use HexGrid;
|
|
|
|
use HexGrid::Pin;
|
|
|
|
use MWTemplate;
|
|
|
|
use Carp;
|
|
|
|
|
|
|
|
use Data::Dumper;
|
|
|
|
$Data::Dumper::Indent = 1;
|
|
|
|
|
|
|
|
use feature "signatures";
|
|
|
|
no warnings "experimental::signatures";
|
|
|
|
|
|
|
|
my $api_url = "https://wiki.tensor.green/w/api.php";
|
|
|
|
my $region_template_name = "MapRegion";
|
|
|
|
my $site_template_name = "MapSite";
|
|
|
|
|
|
|
|
my $border_width = 1;
|
|
|
|
my $border_colour = 'black';
|
|
|
|
my $show_coords = 1;
|
|
|
|
|
|
|
|
my $grid = HexGrid->new(defaults => {
|
|
|
|
style => { 'stroke-width' => $border_width, stroke => $border_colour },
|
|
|
|
show_coords => $show_coords });
|
|
|
|
my $mw = MediaWiki::API->new();
|
|
|
|
$mw->{config}->{api_url} = $api_url;
|
|
|
|
|
|
|
|
my $region_pages = $mw->list ( {
|
|
|
|
action => 'query',
|
|
|
|
list => 'categorymembers',
|
|
|
|
cmtitle => 'Category:Regions',
|
|
|
|
cmlimit => 'max' } )
|
|
|
|
|| croak $mw->{error}->{code} . ': ' . $mw->{error}->{details};
|
|
|
|
|
|
|
|
say STDERR "Regions found: " . join(", ", map { $_->{title} } @$region_pages);
|
|
|
|
|
|
|
|
foreach my $region_page_ref (@$region_pages)
|
|
|
|
{
|
|
|
|
my $region_name = $region_page_ref->{title};
|
|
|
|
say STDERR "Processing Region: $region_name";
|
|
|
|
my $region_page = $mw->get_page({ title => $region_name });
|
|
|
|
my $tile_page = $mw->get_page({ title => "$region_name/Tiles" });
|
|
|
|
process_region($grid, $region_name, $region_page->{'*'}, $tile_page->{'*'});
|
|
|
|
}
|
|
|
|
|
|
|
|
my $site_query_results = $mw->api
|
|
|
|
( {
|
|
|
|
action => 'query',
|
|
|
|
generator => 'categorymembers',
|
|
|
|
prop => 'info|revisions',
|
|
|
|
gcmtitle => 'Category:Sites',
|
|
|
|
gcmlimit => 'max',
|
|
|
|
rvprop => 'content',
|
|
|
|
inprop => 'url',
|
|
|
|
} ) || croak $mw->{error}->{code} . ': ' . $mw->{error}->{details};
|
|
|
|
|
|
|
|
# say STDERR "Sites found: " . join(" ,", map { $_->{title} } @$site_pages);
|
|
|
|
# say STDERR Dumper($site_query_results);
|
|
|
|
foreach my $site_page_ref (values %{$site_query_results->{query}{pages}})
|
|
|
|
{
|
|
|
|
say STDERR Dumper($site_page_ref);
|
|
|
|
my $site_name = $site_page_ref->{title};
|
|
|
|
say STDERR "Processing Site $site_name";
|
|
|
|
my $site_url = $site_page_ref->{canonicalurl};
|
|
|
|
my $site_content = $site_page_ref->{revisions}[0]{'*'};
|
|
|
|
my $parsed_template = MWTemplate::Parse($site_content, $site_template_name);
|
|
|
|
my ($nw,$sw) = split /,/, $parsed_template->{named_params}{coords};
|
|
|
|
|
|
|
|
my $imageinfo_query_results = $mw->api({ action => 'query',
|
|
|
|
prop => 'imageinfo',
|
|
|
|
titles => "File:$parsed_template->{named_params}{icon}",
|
|
|
|
iiprop => 'url'
|
|
|
|
}) || carp $mw->{error}->{code} . ': ' . $mw->{error}->{details};
|
|
|
|
my %image_pages = %{$imageinfo_query_results->{query}{pages}};
|
|
|
|
my $image_url = (values %image_pages)[0]{imageinfo}[0]{url};
|
|
|
|
|
|
|
|
my $pin = HexGrid::Pin->new
|
|
|
|
(
|
|
|
|
name => $site_name,
|
|
|
|
id => "${site_name}_pin",
|
|
|
|
icon => $image_url,
|
|
|
|
link => $site_url,
|
|
|
|
description => $parsed_template->{named_params}{abstract}
|
|
|
|
);
|
|
|
|
# say STDERR Dumper($pin);
|
|
|
|
$grid->get_tile_at($nw, $sw)->pin($pin);
|
|
|
|
}
|
|
|
|
|
|
|
|
say wrap_in_html($grid);
|
|
|
|
|
|
|
|
sub process_region($grid, $region_name, $region_spec, $tiles)
|
|
|
|
{
|
|
|
|
my $region = $grid->make_region($region_name);
|
|
|
|
my $parsed_template = MWTemplate::Parse($region_spec, $region_template_name);
|
|
|
|
$region->{defaults}{colour} = $parsed_template->{named_params}{colour};
|
|
|
|
my $image_info = $mw->api({ action => 'query',
|
|
|
|
prop => 'imageinfo',
|
|
|
|
titles => "File:$parsed_template->{named_params}{background}",
|
|
|
|
iiprop => 'url'
|
|
|
|
}) || carp $mw->{error}->{code} . ': ' . $mw->{error}->{details};
|
|
|
|
$region->{defaults}{image} = [];
|
|
|
|
foreach my $page (values %{$image_info->{query}{pages}})
|
|
|
|
{
|
|
|
|
push @{$region->{defaults}{image}}, $page->{imageinfo}[0]{url};
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach my $coords (split /;/, $tiles)
|
|
|
|
{
|
|
|
|
# The below regex is a whitespace forgiving version of /^(-?\d+),(-?\d+)/, an int pair
|
|
|
|
do { carp "Skipping bad spec: $coords"; next; }
|
|
|
|
unless $coords =~ /^\s*(-?\s*\d+)\s*,\s*(-?\s*\d+)\s*$/;
|
|
|
|
$region->make_tile_at($1,$2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub wrap_in_html($grid)
|
|
|
|
{
|
|
|
|
my $html_builder = "<!DOCTYPE html>";
|
|
|
|
$html_builder .= "\n<html>\n<body>";
|
|
|
|
$html_builder .= "\n" . <<EOS;
|
|
|
|
<script>
|
|
|
|
function clickPin(pinId, containerId) {
|
|
|
|
let popup = document.getElementById(pinId + '-popup');
|
|
|
|
popup.style.visibility = popup.style.visibility == 'visible' ? 'hidden' : 'visible';
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
EOS
|
|
|
|
$html_builder .= "\n" . $grid->render;
|
|
|
|
$html_builder .= "\n</body>\n</html>";
|
|
|
|
return $html_builder;
|
|
|
|
}
|