private function dec2csv ($inputFileName, $outputFileName) { $inputFile = fopen_utf8($inputFileName, 'rb'); if (!$inputFile) error("Unable to read DEC file: $inputFileName"); $outputFile = fopen_utf8($outputFileName, 'w'); if (!$outputFile) error("Unable to write CSV file: $outputFileName"); $cards = array(); // Read header. fread($inputFile, 8); $cardCount = $this->readInt($inputFile, 2); // Read deck cards. for ($i = 0; $i < $cardCount; $i++) { fread($inputFile, 2); $id = $this->readInt($inputFile, 4); fread($inputFile, 10); if (!@$this->mtgoIdToTitle[$id]) echo "Unable to find card with ID: $id\n"; else $cards[] = $this->mtgoIdToTitle[$id]; } // Read sideboard header. fread($inputFile, 2); $cardCount = $this->readInt($inputFile, 1); fread($inputFile, 1); // Read sideboard cards. for ($i = 0; $i < $cardCount; $i++) { fread($inputFile, 2); $id = $this->readInt($inputFile, 4); fread($inputFile, 10); if (!@$this->mtgoIdToTitle[$id]) echo "Unable to find card with ID: $id\n"; else $cards[] = $this->mtgoIdToTitle[$id]; } fclose($inputFile); // Write csv entries. for ($i = 0, $n = count($cards); $i < $n;) { $title = $cards[$i]; $qty = 0; while ($cards[$i] == $title) { $qty++; $i++; if ($i >= $n) break; } $title = str_replace(' (premium)', '', $title); fputcsv($outputFile, array($qty, $title)); } fclose($outputFile); }
function csvToArray ($fileName) { $array = array(); $file = fopen_utf8($fileName, 'r'); if (!$file) error('Unable to open file: ' . $fileName); while (($data = fgetcsv($file, 6000, ',')) !== FALSE) $array[(string)strtolower($data[0])] = trim($data[1]); fclose($file); return $array; }
public function __construct ($loadFromFile) { if (!$loadFromFile || !file_exists('data/fontSizes.csv')) return; $file = fopen_utf8('data/fontSizes.csv', 'r'); if (!$file) error('Unable to open file: data/fontSizes.csv'); while (($data = fgetcsv($file, 6000, ',')) !== FALSE) { $title = $data[0]; if (@!$this->titleToHashesToSize[(string)$title]) $this->titleToHashesToSize[(string)$title] = array(); if (count($data) < 3) continue; $this->titleToHashesToSize[(string)$title][(string)$data[1]] = $data[2]; } fclose($file); }
public function __construct(SetDB $setDB, CardDB $cardDB) { $this->cardDB = $cardDB; $file = fopen_utf8('data/formats.txt', 'r'); while (!feof($file)) { $format = trim(fgets($file, 6000)); if (!$format) { continue; } $this->formats[] = $format; $this->formatToBanned[$format] = array(); $this->formatToRestricted[$format] = array(); $this->formatToSets[$format] = array(); $state = null; while (!feof($file)) { $line = trim(fgets($file, 6000)); if (!$line) { break; } if ($line == 'BANNED' || $line == 'RESTRICTED' || $line == 'SETS') { $state = $line; continue; } $line = strtolower($line); switch ($state) { case 'BANNED': $this->formatToBanned[$format][] = $line; break; case 'RESTRICTED': $this->formatToRestricted[$format][] = $line; break; case 'SETS': $set = $setDB->normalize($line); if (!$set) { error('Error parsing "data/formats.txt". Unknown set: ' . $set); } $this->formatToSets[$format][] = $set; break; default: error('Error parsing "data/formats.txt". Invalid section: ' . $line); } } } fclose($file); }
public function __construct() { $file = fopen_utf8('data/sets.txt', 'r'); $i = 1000; while (!feof($file)) { $line = trim(fgets($file, 6000)); $spaceIndex = strpos($line, ' '); if ($spaceIndex === false) { continue; } $name = trim(substr($line, $spaceIndex + 1)); if ($i > 1000 && $name == 'Alpha') { $i = 1; } // Everything before alpha starts at 1000. $abbreviations = explode(',', substr($line, 0, $spaceIndex)); $mainSet = ""; foreach ($abbreviations as $set) { if (strlen($mainSet) < strlen($set) && strlen($set) <= 3) { $mainSet = $set; } } $mainSet = strtoupper($mainSet); $this->setToMainSet[(string) strtoupper($name)] = $mainSet; foreach ($abbreviations as $abbreviation) { $this->setToMainSet[(string) strtoupper($abbreviation)] = $mainSet; } $this->mainSetToOrdinal[(string) $mainSet] = $i; $i++; } fclose($file); $file = fopen_utf8('data/sets-pre8th.txt', 'r'); while (!feof($file)) { $line = trim(fgets($file, 6000)); if (!$line) { continue; } $set = $this->normalize($line); if (!$set) { error('Error parsing "data/sets-pre8th.txt". Unknown set: ' . $line); } $this->pre8thSets[(string) $set] = true; } }
public function __construct ($setDB, $cardDB, $convertor, $inputFileName, $quiet = false) { global $config; $this->name = getNameFromPath($inputFileName); if (!$quiet) echo 'Parsing decklist: ' . $this->name . '...'; $fileName = $convertor->toCSV($inputFileName); $file = fopen_utf8($fileName, 'r'); if (!$file) error("Error opening decklist file: $inputFileName"); $hasError = false; $lineNumber = 0; $delimiter = trim($config['decklist.delimiter']); $cards = array(); while (($row = fgetcsv($file, 6000, $delimiter)) !== FALSE) { $lineNumber++; if (count($row) == 0 || (count($row) == 1 && $row[0] == '') || (count($row) == 2 && $row[0] == '')) continue; $qty = trim($row[0]); $name = trim(@$row[1]); $set = $config['decklist.ignore.sets'] ? null : trim(@$row[2]); $promo = trim(@$row[3]); if (strtolower($qty) == 'qty' && strtolower($name) == 'card name') continue; if (!is_numeric($qty)) { echo("\nLine $lineNumber: Invalid quantity: $qty"); $hasError = true; continue; } if (!$name) { echo("\nLine $lineNumber: Missing card name."); $hasError = true; continue; } $pic = null; if (!$config['decklist.ignore.sets'] && !$config['decklist.ignore.picture.numbers'] && preg_match('/ \(([1-9])\)/', $name, $matches)) $pic = $matches[1]; $name = preg_replace('/ \(([1-9])\)/', '', $name); //$name = str_replace('Æ, 'AE', $name); for ($i = 0; $i < $qty; $i++) { $card = $cardDB->getCard($name, $set, $pic); if (!$card) { echo("\nLine $lineNumber: Card not found: $name"); if ($set || $pic) { echo ' ['; if ($set) { echo $set; if ($pic) echo ', '; } if ($pic) echo $pic; echo ']'; } $hasError = true; continue; } // If there are any errors, don't actually process any more cards beyond looking them up by title. if ($hasError) continue; $card->promo = $promo; if ($promo) { $card->rarity = 'R'; $card->set = $promo; } $this->cards[] = $card; } if (!$hasError && count($this->cards) % 300 == 0 && !$quiet) echo '.'; } if (!$quiet) echo "\n"; if ($hasError) error('Unable to parse decklist: ' . $inputFileName); }
public function __construct ($mwsFileName) { $mwsFile = fopen_utf8($mwsFileName, 'rb'); if (!$mwsFile) error('Unable to open masterbase CSV file: ' . $mwsFileName); echo "Processing MWS masterbase..."; // windows-1252 //$csv = new CSV(';', "\r\n", '"'); // Cell separator, row separator, value enclosure. //$csv->setContent(file_get_contents($mwsFileName, false , null)); // Parse the string content. //$rows = $csv->getArray(); $i = 0; while (($row = fgetcsv($mwsFile, 6000, ';', '"')) !== FALSE) { //foreach($rows as $row){ if($i++ == 0) continue; //skip first line if ($i++ % 50 == 0) echo '.'; // Extract. $title = (string)trim($row[0]); $set = (string)trim($row[1]); $color = (string)trim($row[4]); $type = (string)trim($row[6]); $p = (string)trim($row[8]); $t = (string)trim($row[9]); $flavor = (string)trim($row[10]); $rarity = (string)trim($row[11]); $cost = (string)trim($row[5]); $legal = trim($row[7]); $pic = (string)trim($row[2]); $artist = (string)trim($row[12]); $collectorNumber = (string)trim($row[13]); // Title. if ($set == 'VG') $title = 'Avatar: ' . $title; // Casting cost. $cost = $this->replaceDualManaSymbols($cost); $cost = preg_replace('/([0-9]+)/', '{\\1}', $cost); // $cost = preg_replace('/([WUBRGXYZ])/', '{\\1}', $cost); $cost = preg_replace('/{{([0-9XYZWUBRG])}{([WUBRG])}}/', '{\\1\\2}', $cost); // Color. if ($color == 'Z/Z') { // Determine split card colors. $cost1 = substr($cost, 0, strpos($cost, '/')); $colors = Card::getCostColors($cost1); $color = strlen($colors) == 1 ? $colors : 'Gld'; $color .= '/'; $cost2 = substr($cost, strpos($cost, '/') + 1); $colors = Card::getCostColors($cost2); $color .= strlen($colors) == 1 ? $colors : 'Gld'; } //php5 fixups $flavor = str_replace("\xA0", '', $flavor); $flavor = iconv('windows-1250', 'utf-8', $flavor); $legal = iconv('windows-1250', 'utf-8' ,$legal); $artist = iconv('windows-1250', 'utf-8' ,$artist); //convert title and type just in case $title = iconv('windows-1250', 'utf-8', $title); $type = iconv('windows-1250', 'utf-8' ,$type); // Type. $type = str_replace(' - ', ' — ', $type); // Legal. $legal = $this->replaceDualManaSymbols($legal); $legal = preg_replace('/\%([0-9]+)/', '{\\1}', $legal); $legal = preg_replace('/\%([WUBRGTXYZ])/', '{\\1}', $legal); $legal = preg_replace('/\%([C])/', '{Q}', $legal); $legal = preg_replace('/#([^#]+)# – /', '\\1 – ', $legal); // Remove italics from ability keywords. $legal = str_replace("\r\n----\r\n", "\n-----\n", $legal); // Flip card separator. $legal = str_replace('Creature - ', 'Creature — ', $legal); $legal = str_replace(' upkeep - ', ' upkeep—', $legal); $legal = str_replace(' - ', ' — ', $legal); $legal = str_replace('AE', 'Æ', $legal); $legal = str_replace(".]", ".)", $legal); $legal = str_replace("\r\n", "\n", $legal); // Fix vanguard inconsistencies. if (preg_match('/Starting & Max[^\+\-]+([\+\-][0-9]+)[^\+\-]+([\+\-][0-9]+)/', $legal, $matches)) $legal = 'Hand ' . $matches[1] . ', Life ' . $matches[2] . "\n" . substr($legal, 0, strpos($legal, ' Starting & Max')); if (preg_match('/Hand Size[^\+\-]+([\+\-][0-9]+)[^\+\-]+([\+\-][0-9]+)\.?/', $legal, $matches)) $legal = 'Hand ' . $matches[1] . ', Life ' . $matches[2] . "\n" . substr($legal, 0, strpos($legal, 'Hand Size')); $legal = trim($legal); // Flavor. $flavor = str_replace("'", '’', $flavor); // ' to ’ $flavor = preg_replace('/"([^"]*)"/', '“\\1”', $flavor); // "text" to “text” $flavor = preg_replace("/(.*[^.]) '([^']*)'/", "\\1 ‘\\2’", $flavor); // 'text' to ‘text’ $flavor = preg_replace('/(.*[^.]) ’(.*)’/', '\\1 ‘\\2’', $flavor); // ’text’ to ‘text’ $flavor = str_replace('”’', '’”', $flavor); // ”’ to ’” $flavor = str_replace('‘”', '”‘', $flavor); // ‘” to ”‘ $flavor = str_replace('“’', '“‘', $flavor); // “’ to “‘ $flavor = str_replace(',’', '’,', $flavor); // ,’ to ’, $flavor = preg_replace("/\r\n- ?/", "\n—", $flavor); // - to — $flavor = preg_replace("/\r\n#- ?/", "\n#—", $flavor); $flavor = preg_replace("/ - /", "—", $flavor); $flavor = str_replace('AE', 'Æ', $flavor); $flavor = str_replace("\r\n", "\n", $flavor); $flavor = str_replace('"', '”', $flavor); // " to ” // Store. $card = new Card(); $card->title = $title; $card->set = $set; $card->color = $color; $card->type = $type; $card->pt = ($p != "" && $t !="") ? $p . '/' . $t : (preg_match('/%([0-9]+)#/', $p, $matches) ? "/$matches[1]" : ''); $card->flavor = $flavor; $card->rarity = $rarity; $card->cost = $cost; $card->legal = $legal; $card->pic = $pic; $card->artist = $artist; $card->collectorNumber = $collectorNumber; $this->cards[] = $card; } // Compute total cards in each set. $setToCollectorNumbers = array(); foreach ($this->cards as $card) { // Only count cards with collector numbers. if (!$card->collectorNumber) continue; // Don't count the same collector number twice. if (!@$setToCollectorNumbers[$card->set]) $setToCollectorNumbers[$card->set] = array(); if (@$setToCollectorNumbers[$card->set][$card->collectorNumber]) continue; $setToCollectorNumbers[$card->set][$card->collectorNumber] = true; } foreach ($this->cards as $card) { if (!$card->collectorNumber) continue; // Try hardcoded value first. $cardsInSet = MasterBase::getTotalCardsInSet($card->set); // Then try computed vallue. if (!$cardsInSet && @$setToCollectorNumbers[$card->set]) $cardsInSet = count($setToCollectorNumbers[$card->set]); if (!$cardsInSet) continue; $card->collectorNumber .= '/' . $cardsInSet; } }
fwrite($cardsFile, fgets($planesFile)); } fclose($planesFile); // Copy schemes. echo "Copying Schemes...\n"; $schemesFile = fopen_utf8('misc/import/schemes.csv', 'rb'); if (!$schemesFile) { error('Unable to read Scheme CSV file.'); } while (!feof($schemesFile)) { fwrite($cardsFile, fgets($schemesFile)); } fclose($schemesFile); // Copy planes. echo "Copying Sorcerer's Apprentice Cards...\n"; $sorcFile = fopen_utf8('misc/import/sorcerersApprentice.csv', 'rb'); if (!$sorcFile) { error('Unable to read Sorcerer\'s Apprentice Cards CSV file.'); } while (!feof($sorcFile)) { fwrite($cardsFile, fgets($sorcFile)); } fclose($sorcFile); // Write masterbase. $masterBase = new MasterBase($files[0]); $cards = $masterBase->cards; foreach ($cards as $card) { writeCsvRow($cardsFile, CardDB::cardToRow($card)); } fclose($cardsFile); echo "\n" . count($cards) . " cards processed.\n";
public function __construct(SetDB $setDB, ArtDB $artDB) { global $config; $this->setDB = $setDB; $this->artDB = $artDB; // Load english cards. echo 'Loading card data'; $file = fopen_utf8('data/cards.csv', 'r'); if (!$file) { error('Unable to open file: data/cards.csv'); } $i = 0; while (($row = fgetcsv($file, 6000, ',')) !== FALSE) { if ($i++ % 400 == 0) { echo '.'; } $card = CardDB::rowToCard($row); // Ignore cards with an unknown set. $card->set = $setDB->normalize($card->set); if (!$card->set) { continue; } $title = strtolower($card->title); if (!@$this->titleToCards[$title]) { $this->titleToCards[$title] = array(); } $this->titleToCards[(string) $title][] = $card; } fclose($file); echo "\n"; // Load foreign card data. $language = strtolower($config['output.language']); if ($language && $language != 'english') { echo "Loading {$language} card data"; $file = fopen_utf8("data/cards-{$language}.csv", 'r'); if (!$file) { error("Unable to open file: data/cards-{$language}.csv"); } $i = 0; while (($row = fgetcsv($file, 6000, ',')) !== FALSE) { if ($i++ % 400 == 0) { echo '.'; } // Overwrite some of the english card values with the foreign values. $englishTitle = strtolower($row[0]); $cards = @$this->titleToCards[(string) $englishTitle]; if (!$cards) { //print_r($row); echo "\nError matching card data for card: {$row['0']}"; continue; // Skip errors } foreach ($cards as $card) { CardDB::applyLanguageRowToCard($row, $card); } } fclose($file); echo "\n"; if (!$config['output.english.flavor.text']) { echo "Loading {$language} card flavor data"; $file = fopen_utf8("data/cards-{$language}-flavor.csv", 'r'); if (!$file) { echo "\nNo localized flavor for language: {$language}"; } else { $i = 0; while (($row = fgetcsv($file, 6000, ',')) !== FALSE) { if ($i++ % 400 == 0) { echo '.'; } // Overwrite some of the english card values with the foreign values. $englishTitle = strtolower($row[0]); $cards = @$this->titleToCards[(string) $englishTitle]; if (!$cards) { //print_r($row); echo "\nError matching card flavor for card: {$row['0']}"; continue; // Skip errors. } // Find the card from needed edition and apply localized flavor. foreach ($cards as $card) { if ($card->set == $setDB->normalize($row[1])) { $card->flavor = $row[2]; break; } } } fclose($file); echo "\n"; } } } }
//////////////////////////////////////////////////////////////////////// require_once 'scripts/includes/global.php'; echo "Card Generator v{$version} - Build font size cache\n\n"; $existingFontSizeDB = null; if (file_exists('data/fontSizes.csv')) { echo 'Keep existing cache entries? (y/n) '; if (strtolower(trim(fgets(STDIN))) != 'n') { $existingFontSizeDB = new FontSizeDB(true); } if (file_exists("data/fontSizes.csv")) { echo "Backing up file \"data/fontSizes.csv\" to \"data/fontSizes.csv.bak\"...\n"; @unlink("data/fontSizes.csv.bak"); @copy("data/fontSizes.csv", "data/fontSizes.csv.bak"); } } $fontSizesFile = fopen_utf8("data/fontSizes.csv", $existingFontSizeDB ? 'a' : 'w'); if (!$fontSizesFile) { error("Unable to write CSV file: data/fontSizes.csv"); } $config['output.card.set.directories'] = true; $config['card.flavor.random'] = false; $writer = new ImageWriter(); $writer->setOutputType(false, false); echo "Building cache...\n"; foreach ($writer->cardDB->getAllCardTitles() as $title) { if ($existingFontSizeDB && $existingFontSizeDB->hasCard($title)) { continue; } $writer->fontSizeDB->reset(); $writer->addCardByTitle($title); foreach ($writer->renderers as $renderer) {
// along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// require_once 'scripts/includes/global.php'; echo "Card Generator v$version - MWS to cards-<language>.csv\n\n"; $files = getInputFiles( array_slice($argv, 1), 'Drag and drop an MWS masterbase CSV file here and press enter...' ); echo 'Enter the name of the language: '; $language = strtolower(trim(fgets(STDIN))); echo "Creating temporary file: data/cards-$language.csv.temp\n"; $cardsFile = fopen_utf8("data/cards-$language.csv.temp", 'w+'); if (!$cardsFile) error("Unable to write CSV file: data/cards-$language.csv.temp"); // Write masterbase. $masterBase = new MasterBase($files[0]); $cards = $masterBase->cards; foreach ($cards as $card) writeCsvRow($cardsFile, CardDB::cardToLanguageRow($card)); fclose($cardsFile); echo "\n" . count($cards) . " cards processed.\n"; echo "Temporary file complete.\n"; if (file_exists("data/cards-$language.csv")) { echo "Backing up file \"data/cards-$language.csv\" to \"data/cards-$language.csv.bak\"...\n";
private function csvToArray($fileName) { $array = array(); $file = fopen_utf8($fileName, 'r'); if (!$file) { error('Unable to open file: ' . $fileName); } while (($data = fgetcsv($file, 6000, ',')) !== FALSE) { $array[(string) strtolower($data[0])] = array(trim($data[1]), isset($data[2]) ? trim($data[2]) : ""); } fclose($file); return $array; }
public function __construct($mwsFileName) { $mwsFile = fopen_utf8($mwsFileName, 'rb'); if (!$mwsFile) { error('Unable to open masterbase CSV file: ' . $mwsFileName); } echo "Processing MWS masterbase..."; // windows-1252 //$csv = new CSV(';', "\r\n", '"'); // Cell separator, row separator, value enclosure. //$csv->setContent(file_get_contents($mwsFileName, false , null)); // Parse the string content. //$rows = $csv->getArray(); $i = 0; while (($row = fgetcsv($mwsFile, 6000, ';', '"')) !== FALSE) { //foreach($rows as $row){ if ($i++ == 0) { continue; } //skip first line if ($i++ % 50 == 0) { echo '.'; } // Extract. $title = (string) trim($row[0]); $set = (string) trim($row[1]); $color = (string) trim($row[4]); $type = (string) trim($row[6]); $p = (string) trim($row[8]); $t = (string) trim($row[9]); $flavor = (string) trim($row[10]); $rarity = (string) trim($row[11]); $cost = (string) trim($row[5]); $legal = trim($row[7]); $pic = (string) trim($row[2]); $artist = (string) trim($row[12]); $collectorNumber = (string) trim($row[13]); // Title. if ($set == 'VG') { $title = 'Avatar: ' . $title; } // Casting cost. $cost = $this->replaceDualManaSymbols($cost); $cost = $this->replacePhyrexiaSymbols($cost); $cost = preg_replace('/([0-9]+)/', '{\\1}', $cost); // $cost = preg_replace('/([WUBRGXYZ])/', '{\\1}', $cost); $cost = preg_replace('/{{([0-9XYZWUBRG])}{([WUBRG])}}/', '{\\1\\2}', $cost); $cost = preg_replace('/{([P]){([WUBRG])}}/', '{\\1\\2}', $cost); // Color. if ($color == 'Z/Z' || strpos($title, '/') !== FALSE && $p == "" && $t == "") { // Determine split card colors. $cost1 = substr($cost, 0, strpos($cost, '/')); $colors = Card::getCostColors($cost1); $color = strlen($colors) == 1 ? $colors : 'Gld'; $color .= '/'; $cost2 = substr($cost, strpos($cost, '/') + 1); $colors = Card::getCostColors($cost2); $color .= strlen($colors) == 1 ? $colors : 'Gld'; } if (strpos($title, "/") !== FALSE && ($p != "" && $t != "" || $set == 'DKA' || $set == 'ISD')) { // flip cards fixes $title1 = substr($title, 0, strpos($title, '/')); $title2 = substr($title, strpos($title, '/') + 1); $title = $title1; $type1 = substr($type, 0, strpos($type, '/')); $type2 = substr($type, strpos($type, '/') + 1); $type = $type1; $pt = ""; if (strpos($t, '|') !== FALSE) { $t1 = substr($t, 0, strpos($t, '|')); $pt = substr($t, strpos($t, '|') + 1); $t = $t1; } else { if (strpos($p, '|') !== FALSE) { $p1 = substr($p, 0, strpos($p, '|')); $pt = substr($p, strpos($p, '|') + 1) . '/' . $t; $p = $p1; $t = ''; if ($pt == '#/') { //maybe need something more generic for dual planeswalkers later $pt = ''; $p .= '#'; } } } $insertPosition = strpos($legal, "//"); $insertString = "\n" . $title2 . "\n" . $type2 . ($pt != "" ? "\n" . $pt : ""); $legalTmp = substr_replace($legal, $insertString, $insertPosition + 2, 0); $legal = $legalTmp; } //php5 fixups $flavor = str_replace("�", '', $flavor); $flavor = iconv('windows-1250', 'utf-8', $flavor); $legal = iconv('windows-1250', 'utf-8', $legal); $artist = iconv('windows-1250', 'utf-8', $artist); //convert title and type just in case $title = iconv('windows-1250', 'utf-8', $title); $type = iconv('windows-1250', 'utf-8', $type); // Type. $type = str_replace(' - ', ' — ', $type); // Legal. $legal = $this->replaceDualManaSymbols($legal); $legal = $this->replacePhyrexiaSymbols($legal); $legal = preg_replace('/\\%([0-9]+)/', '{\\1}', $legal); $legal = preg_replace('/\\%([WUBRGTXYZ])/', '{\\1}', $legal); $legal = str_replace('%C', '{Q}', $legal); $legal = str_replace("<hr>", "-----", $legal); $flavor = str_replace("<hr>", "-----", $flavor); $legal = str_replace("//", "-----", $legal); $flavor = str_replace("//", "-----", $flavor); //card specific $legal = str_replace('El-Hajjaj', 'El-Hajjâj', $legal); $legal = str_replace('Junun', 'Junún', $legal); $legal = str_replace('Lim-Dul', 'Lim-Dûl', $legal); $legal = str_replace('Jotun', 'Jötun', $legal); $legal = str_replace('Ghazban', 'Ghazbán', $legal); $legal = str_replace('Ifh-Biff', 'Ifh-Bíff', $legal); $legal = str_replace('Juzam', 'Juzám', $legal); $legal = str_replace('Khabal', 'Khabál', $legal); $legal = str_replace('Marton', 'Márton', $legal); $legal = str_replace("Ma'ruf", "Ma'rûf", $legal); $legal = str_replace("Ma’ruf", "Ma’rûf", $legal); $legal = str_replace('Deja Vu', 'Déjà Vu', $legal); $legal = str_replace('Dandan', 'Dandân', $legal); $legal = str_replace('Bosium', 'Bösium', $legal); $legal = str_replace(' en-', ' #en#-', $legal); $legal = str_replace(' il-', ' #il#-', $legal); $legal = str_replace('Seance', 'Séance', $legal); $legal = preg_replace('/#([^#]+)# – /', '\\1 – ', $legal); // Remove italics from ability keywords. $legal = str_replace("\r\n-----\r\n", "\n-----\n", $legal); // Flip card separator. $legal = str_replace('Creature - ', 'Creature — ', $legal); $legal = str_replace(' upkeep - ', ' upkeep—', $legal); $legal = str_replace(' - ', ' — ', $legal); $legal = str_replace('AE', 'Æ', $legal); $legal = str_replace(".]", ".)", $legal); $legal = str_replace("\r\n", "\n", $legal); // Fix vanguard inconsistencies. if (preg_match('/Starting & Max[^\\+\\-]+([\\+\\-][0-9]+)[^\\+\\-]+([\\+\\-][0-9]+)/', $legal, $matches)) { $legal = 'Hand ' . $matches[1] . ', Life ' . $matches[2] . "\n" . substr($legal, 0, strpos($legal, ' Starting & Max')); } if (preg_match('/Hand Size[^\\+\\-]+([\\+\\-][0-9]+)[^\\+\\-]+([\\+\\-][0-9]+)\\.?/', $legal, $matches)) { $legal = 'Hand ' . $matches[1] . ', Life ' . $matches[2] . "\n" . substr($legal, 0, strpos($legal, 'Hand Size')); } $legal = trim($legal); // Flavor. $flavor = str_replace("'", '’', $flavor); // ' to ’ $flavor = preg_replace('/"([^"]*)"/', '“\\1”', $flavor); // "text" to “text” $flavor = preg_replace("/(.*[^.]) '([^']*)'/", "\\1 ‘\\2’", $flavor); // 'text' to ‘text’ $flavor = preg_replace('/(.*[^.]) ’(.*)’/', '\\1 ‘\\2’', $flavor); // ’text’ to ‘text’ $flavor = str_replace('”’', '’”', $flavor); // ”’ to ’” $flavor = str_replace('‘”', '”‘', $flavor); // ‘” to ”‘ $flavor = str_replace('“’', '“‘', $flavor); // “’ to “‘ $flavor = str_replace(',’', '’,', $flavor); // ,’ to ’, $flavor = preg_replace("/\r\n- (.?)/", "\n—\\1", $flavor); // - to — $flavor = preg_replace("/\r\n#- (.?)/", "\n#—\\1", $flavor); $flavor = preg_replace("/ - /", "—", $flavor); $flavor = str_replace('AE', 'Æ', $flavor); $flavor = str_replace("\r\n", "\n", $flavor); $flavor = str_replace('"', '”', $flavor); // " to ” // Store. $card = new Card(); $card->title = $title; $card->set = $set; $card->color = $color; $card->type = $type; $card->pt = $p != "" && $t != "" ? $p . '/' . $t : (preg_match('/%([0-9]+)#/', $p, $matches) ? "/{$matches['1']}" : ''); $card->flavor = $flavor; $card->rarity = $rarity; $card->cost = $cost; $card->legal = $legal; $card->pic = $pic; $card->artist = $artist; $card->collectorNumber = $collectorNumber; $this->cards[] = $card; } // Compute total cards in each set. $setToCollectorNumbers = array(); foreach ($this->cards as $card) { // Only count cards with collector numbers. if (!$card->collectorNumber) { continue; } // Don't count the same collector number twice. if (!@$setToCollectorNumbers[$card->set]) { $setToCollectorNumbers[$card->set] = array(); } if (@$setToCollectorNumbers[$card->set][$card->collectorNumber]) { continue; } $setToCollectorNumbers[$card->set][$card->collectorNumber] = true; } foreach ($this->cards as $card) { if (!$card->collectorNumber) { continue; } // Try hardcoded value first. $cardsInSet = MasterBase::getTotalCardsInSet($card->set); // Then try computed vallue. if (!$cardsInSet && @$setToCollectorNumbers[$card->set]) { $cardsInSet = count($setToCollectorNumbers[$card->set]); } if (!$cardsInSet) { continue; } $card->collectorNumber .= '/' . $cardsInSet; } }
$addCardsFileName = $outputFileDir . $newDecklist->name . ' (add).csv'; $addCardsFile = fopen_utf8($addCardsFileName, 'w'); foreach ($addCardsIndex as $index => $qty) { $card = $newDecklist->cards[$index]; echo $qty . ', ' . $card . "\n"; $name = $card->title; if (!$ignoreSets && $card->pic) { $name .= ' (' . $card->pic . ')'; } fputcsv($addCardsFile, array($qty, $name, $card->set)); } fclose($addCardsFile); echo "\nOutput decklist:\n{$addCardsFileName}\n"; echo "\nCards to remove from " . $oldDecklist->name . ":\n"; $removeCardsFileName = $outputFileDir . $newDecklist->name . ' (remove).csv'; $removeCardsFile = fopen_utf8($removeCardsFileName, 'w'); foreach ($removeCardsIndex as $index => $qty) { $card = $oldDecklist->cards[$index]; echo $qty . ', ' . $card . "\n"; $name = $card->title; if (!$ignoreSets && $card->pic) { $name .= ' (' . $card->pic . ')'; } fputcsv($removeCardsFile, array($qty, $name, $card->set)); } fclose($removeCardsFile); echo "\nOutput decklist:\n{$removeCardsFileName}\n"; function cardsMinusCards($a, $b) { global $ignoreSets; $result = array();
public function writePages() { global $config; // Collect and compute paged output data. $outputDir = $config['output.directory']; $spacing = $config['output.card.spacing'] + 1; $borderSize = $config['output.card.border']; $rows = $config['output.page.rows']; $columns = $config['output.page.columns']; $rotate = $config['output.page.rotate']; $rotateLastRows = $config['output.page.rotate.last.rows']; $cardWidth = $rotate ? 1050 + $borderSize * 2 : 736 + $borderSize * 2; $cardHeight = $rotate ? 736 + $borderSize * 2 : 1050 + $borderSize * 2; $offsetTop = @$config['output.page.offset.top']; $offsetLeft = @$config['output.page.offset.left']; $offsetBottom = @$config['output.page.offset.bottom'] + 1; $offsetRight = @$config['output.page.offset.right'] + 1; $canvasWidth = $cardWidth * $columns + $spacing * ($columns - 1) + $offsetLeft + $offsetRight; $canvasHeight = $cardHeight * ($rows - $rotateLastRows) + $spacing * ($rows - 1) + $cardWidth * $rotateLastRows + $offsetTop + $offsetBottom; $xOffsets = @explode(',', $config['output.card.offsets.x']); $yOffsets = @explode(',', $config['output.card.offsets.y']); $pageNumber = 0; // Open up an existing page image if lastPage.txt exists. $canvas = null; $skipImages = 0; if (file_exists($outputDir . 'lastPage.txt')) { // Read the number of images that were written to the last generated page. $file = fopen_utf8($outputDir . 'lastPage.txt', 'r'); if (!$file) { error('Cannot append. Unable to open file: ' . $outputDir . 'lastPage.txt'); } fgets($file, 1000); $skipImages = trim(fgets($file, 1000)); fclose($file); // Open the last page image. $outputExt = $config['output.extension']; while (true) { $pageNumber++; if (!file_exists($outputDir . 'page' . $pageNumber . '.' . $outputExt)) { break; } } $pageNumber--; $fileName = $outputDir . 'page' . $pageNumber . '.' . $outputExt; $pageNumber--; if ($outputExt == 'png') { $canvas = imagecreatefrompng($fileName); } else { if ($outputExt == 'jpg') { $canvas = imagecreatefromjpeg($fileName); } } } $writtenImageCount = 0; for ($i = 0, $n = count($this->renderers); $i < $n;) { if (!$canvas) { // New page image. $canvas = imagecreatetruecolor($canvasWidth, $canvasHeight); $black = imagecolorallocate($canvas, 0, 0, 0); $white = imagecolorallocate($canvas, 255, 255, 255); imagefill($canvas, 0, 0, $white); } else { // Using existing page image. $black = imagecolorallocate($canvas, 0, 0, 0); } $cardIndex = 0; $y = $borderSize; $writtenImageCount = 0; for ($rowIndex = 0; $rowIndex < $rows; $rowIndex++) { $x = $borderSize; if ($rowIndex >= $rows - $rotateLastRows) { // Rotate the last row the opposite of all previous rows. $tempColumns = floor($cardWidth * $columns / $cardHeight); $tempRotate = !$rotate; $xIncrement = $cardHeight + $spacing; $yIncrement = $cardWidth + $spacing; if ($config['output.page.rotate.align.right']) { $x = $borderSize + $canvasWidth - ($cardHeight * $tempColumns + $spacing * ($tempColumns - 1)); } else { $x = $borderSize; } } else { // Normal row. $tempColumns = $columns; $tempRotate = $rotate; $xIncrement = $cardWidth + $spacing; $yIncrement = $cardHeight + $spacing; } for ($columnIndex = 0; $columnIndex < $tempColumns; $columnIndex++) { if ($i < $n) { if ($skipImages > 0) { $skipImages--; } else { // Render card image. $renderer = $this->renderers[$i]; $cardImage = $renderer->render(); if ($renderer instanceof DecklistRenderer) { $this->artDB->resetUsedArt(); $this->cardDB->resetUsedFlavors(); } // Copy it into the page image. $xCoord = $x + $offsetLeft + @$xOffsets[$cardIndex]; $yCoord = $y + $offsetTop + @$yOffsets[$cardIndex]; if ($tempRotate) { $cardImageTmp = imagerotate($cardImage, 90, 0); imagedestroy($cardImage); $cardImage = $cardImageTmp; imagefilledrectangle($canvas, $xCoord - $borderSize, $yCoord - $borderSize, $xCoord + 1050 + $borderSize, $yCoord + 736 + $borderSize, $black); imagecopy($canvas, $cardImage, $xCoord, $yCoord, 0, 0, 1050, 736); } else { imagefilledrectangle($canvas, $xCoord - $borderSize, $yCoord - $borderSize, $xCoord + 736 + $borderSize, $yCoord + 1050 + $borderSize, $black); imagecopy($canvas, $cardImage, $xCoord, $yCoord, 0, 0, 736, 1050); } imagedestroy($cardImage); $i++; } $writtenImageCount++; } $x += $xIncrement; $cardIndex++; } $y += $yIncrement; } $this->outputImage($canvas, $this->getOutputFileName($outputDir, 'page' . ++$pageNumber)); imagedestroy($canvas); $canvas = null; echo "Page {$pageNumber} complete...\n"; } $file = fopen_utf8($outputDir . 'lastPage.txt', 'w'); if (!$file) { error('Unable to write file: ' . $outputDir . 'lastPage.txt'); } fwrite($file, "Number of cards output on the last page image:\r\n"); fwrite($file, "{$writtenImageCount}\r\n"); fclose($file); $this->reset(); return $pageNumber; }