FreewarWiki:Bot/Skripts/makemap.php

aus FreewarWiki, der Referenz für Freewar
Version vom 8. Februar 2019, 01:17 Uhr von Count Ypsilon (Diskussion | Beiträge) (Funktionalität für $draw_grid ergänzt)
Zur Navigation springen Zur Suche springen
Dieses Script ist hier lediglich archiviert und nicht direkt lauffähig. Wenn Du es benutzen möchtest, musst Du es lokal abspeichern und mit einem geeigneten Interpreter ausführen lassen. Zum Übernehmen solltest Du nicht den unten angezeigten Text verwenden, sondern den Quelltext des Wiki-Artikels: Dazu wählst Du Bearbeiten und kopierst den (meist zwischen PRE-Tags eingefassten) Scripttext.

Sofern Du die Scripte dauerhaft lokal abgespeichert hältst, solltest Du sie vor der nächsten Ausführung darauf prüfen, ob sie noch aktuell sind.

Letzter Bearbeiter: Count Ypsilon — Zuletzt bearbeitet: 08.02.2019
<?php
header('Content-Type: text/plain; charset=utf-8;');

// Bergfeld url
define("BERGFELD", 'http://welt1.freewar.de/freewar/images/map/std.jpg');

$host   = 'http://www.fwwiki.de';
$prefix = 'Karte';                // Wiki-Namespace

// pfad zu maplist.txt
$maplist = 'maplist.txt';

// Pfad zur Ausgabedatei
$mapfile = './Gesamtkarte (automatisch generiert).jpg';

// pfad zu map_cache
$map_cache = './map_cache';

# Bereich angeben. Alles ausserhalb wird ignoriert. Die Karte wird aber
# immer nur so gross, wie tatsaechlich Felder da sind, nicht so gross,
# wie man hier angibt.
# (nicht mit 1,1 starten, sonst kriegt man den Dummyplace mit)
$min_x = 2;
$min_y = 2;
$max_x = 170; # oestlicher Rand, damit Itolos und Belpharia-Inseln draussen bleiben
$max_y = 400;
 
# Hintergrundfarbe fuer Karte
$bgcolor = "ffffff";

# auf z.b. 5 setzen, wenn felder mit luecken gewuenscht
$cellspacing = 0;
 
# auf 1 setzen, wenn alle 5 zeilen/spalten linie gewuenscht
$draw_grid = 1;

// ab hier nichts ändern ohne Kenntnisse über Funktionsweise des Skripts
function get_templates($template, $wiki_text) {
    $pattern = '/\{\{(Vorlage:)?' . preg_quote($template, '/') . '/';

    $templates = preg_split($pattern, $wiki_text);

    return array_slice($templates, 1);
}

// cacht mapfile
function cache_mapfile($url, $map_cache) {
    $cache_file = "$map_cache/" . md5($url);
    if (!file_exists($cache_file)) {
        file_put_contents($cache_file, file_get_contents($url));
    }
    
    return $cache_file;
}

$parser_function = 'parse_card_article';               // Parser Funktion des Skripts
$api_url         = "$host/api.php?format=json";

// trennzeichen für positionsschlüssel
$pos_delimiter = '|';


// Rahmen
$min_x_found = $max_x;
$min_y_found = $max_y;
$max_x_found = $min_x;
$max_y_found = $min_y;
 
// zusätzliche Felder, die nicht von Feld-Artikeln erfasst werden
$additional_fields = [];

// Bergfeld cachen
cache_mapfile(BERGFELD, $map_cache);

// Karten holen
$api_query_url = "$api_url&action=query&list=categorymembers".
                         "&cmtitle=Kategorie:Karten&cmtype=page".
                         "&cmprop=ids|sortkeyprefix|title&cmlimit=50";
$api_query_url_continue = $api_query_url;

// pageids der karten
$map_pageids = [];

// kategorieeinträge durchlaufen
while (true) {   
    $json = json_decode(file_get_contents($api_query_url_continue), true);
    
    // pageids hinzufügen
    $map_pageids = array_merge($map_pageids, array_filter(array_map(function ($row) {
        // keine ! kategorieeinträge
        return ($row['sortkeyprefix'][0] == '!') ? null : $row['pageid'];
    }, $json['query']['categorymembers'])));
    
    // continue url
    if (isset($json['continue'])) {
        $api_query_url_continue = "$api_query_url&cmcontinue={$json['continue']['cmcontinue']}";
    } else {
        break;
    }
}

// karten durchlaufen
$rvlimit = 10;

foreach (array_chunk($map_pageids, $rvlimit) as $pageids) {
    $api_query_url = "$api_url&action=query&prop=revisions".
                         "&rvprop=content&pageids=". implode("|", $pageids);
    $json = json_decode(file_get_contents($api_query_url), true);
    
    foreach ($json['query']['pages'] as $pageid => $prop) {
        $raw = $prop['revisions'][0]['*'];
        
        // unbetretbare und rahmenfelder erfassen, durchlaufen und an maplist format anpassen
        $additional_fields = array_merge($additional_fields, array_map(function ($template_text) {
            preg_match("/([0-9\-]+)\|([0-9\-]+)(\|([^}\|]+))?/", $template_text, $values);
            
            if (!isset($values[1])) {
                return [];
            }
            
            return [
                // array keys entsprechend format in maplist.txt
                2 => $values[1],
                3 => $values[2],
                5 => isset($values[3]) ? $values[4] : BERGFELD
            ];
        }, array_merge(get_templates("Karte/Unbetretbar", $raw), get_templates("Karte/Rahmenfeld", $raw))));
    }
}

// zusätzliche Felder geholt
// eigentliche maplist holen und mit zusätzlichen zusammenführen
$field_rows = array_merge(array_map(function ($line) {
    return str_getcsv($line, ";");
}, explode("\n", file_get_contents($maplist))), $additional_fields);

// felder in `position` => `url` format überführen
$fields = [];
foreach ($field_rows as $field) {
    # Koordinaten-Check
    if ($field[2] < $min_x || $field[2] > $max_x || $field[3] < $min_y || $field[3] > $max_y) {
        continue;
    }
    if ($field[2] < $min_x_found) {
        $min_x_found = $field[2] ;
    }
    if ($field[3] < $min_y_found) {
        $min_y_found = $field[3];
    }
    if ($field[2] > $max_x_found) {
        $max_x_found = $field[2] ;
    }
    if ($field[3] > $max_y_found) {
        $max_y_found = $field[3];
    }
        
    // und gleich bilddatein holen
    $cache_file = cache_mapfile($field[5], $map_cache);
    
    // kein Feldtitel oder `Feldtitel Pensal (brennend)`
    if (!isset($field[1]) || strpos($field[1], ' (brennend)') === false) {
        $fields["{$field[2]}$pos_delimiter{$field[3]}"] = [
            'x' => $field[2],
            'y' => $field[3],
            'file' => $cache_file
        ];   
    }
    
}

// Randfelder einfügen
foreach ($fields as $field) {
    // Randfelder
    for ($diff_x = -1; $diff_x <= 1; ++$diff_x) {
        for ($diff_y = -1; $diff_y <= 1; ++$diff_y) {
            $edge = ($field['x'] + $diff_x) . $pos_delimiter . ($field['y'] + $diff_y);
            if (!isset($fields[$edge])) {
                $fields[$edge] = [
                    'x' => $field['x'] + $diff_x,
                    'y' => $field['y'] + $diff_y,
                    'file' => "$map_cache/" . md5(BERGFELD)
                ];
            }
        }
    }
}

# Groesse eines Kartenfelds feststellen
list($tilewidth, $tileheight) = getimagesize($cache_file);
echo "tile size: $tilewidth x $tileheight\n";

 # Leeres Kartenbild erstellen
$mapwidth = ($max_x_found - $min_x_found + 3) * $tilewidth + 
            ($max_x_found - $min_x_found + 2) * $cellspacing;
$mapheight = ($max_y_found - $min_y_found + 3) * $tileheight + 
             ($max_y_found - $min_y_found + 2) * $cellspacing;
$mapimage = imagecreatetruecolor($mapwidth, $mapheight);
echo "x_min: $min_x_found; x_max: $max_x_found; y_min: $min_y_found; y_max: $max_y_found;";
echo "map size: $mapwidth x $mapheight\n";

// hintergrundfarbe
imagefill($mapimage, 0, 0, imagecolorallocate($mapimage, hexdec(substr($bgcolor, 0, 2)), 
                                                         hexdec(substr($bgcolor, 2, 2)), 
                                                         hexdec(substr($bgcolor, 4, 2))));

// Gitter malen, wenn angefordert
if ($draw_grid) {
    for ($x = $min_x_found; $x <= $max_x_found; $x++) {
        if ($x%5 == 0) {
            $mpx = ($x - $min_x_found + 1) * ($tilewidth + $cellspacing) + $cellspacing + $tilewidth/2;
            imageline($mapimage, $mpx, 0, $mpx, $mapheight, 0);
        }
    }
    for ($y = $min_y_found; $y <= $max_y_found; $y++) {
        if ($y%5 == 0) {
            $mpy = ($y - $min_y_found + 1) * ($tileheight + $cellspacing) + $cellspacing + $tileheight/2;
            imageline($mapimage, 0, $mpy, $mapwidth, $mpy, 0);
        }
    }
}

// Felder einzeichnen
foreach ($fields as $key => $data) {
    // bild in map einfügen
    imagecopy($mapimage, 
              imagecreatefromjpeg($data['file']), 
              ($data['x'] - $min_x_found + 1) * ($tilewidth + $cellspacing) + $cellspacing, 
              ($data['y'] - $min_y_found + 1) * ($tileheight + $cellspacing) + $cellspacing, 
              0, 0,
              $tilewidth, $tileheight);
}

// ausgabe
imagejpeg($mapimage, $mapfile);
imagedestroy($mapimage);