Skip to content

Instantly share code, notes, and snippets.

@pavel-voronin
Created May 12, 2015 21:09
Show Gist options
  • Save pavel-voronin/5dfcc0882e8512188f00 to your computer and use it in GitHub Desktop.
Save pavel-voronin/5dfcc0882e8512188f00 to your computer and use it in GitHub Desktop.
Генератор имён российской военной техники
<?php
// Утилиты
/**
* Multibyte string replace implementation
*
* @param string $search
* @param string $replace
* @param string $subject
* @param int $limit
* @return string
*/
function mb_replace($search, $replace, $subject, $limit = -1)
{
return implode($replace, mb_split(preg_quote($search), $subject, $limit == -1 ? $limit : $limit + 1));
}
/**
* UTF-8 chr() implementation
* @param int $intval
* @return string
*/
function unichr($intval)
{
return mb_convert_encoding(pack('n', $intval), 'UTF-8', 'UTF-16BE');
}
/**
* UTF-8 ord() implementation
* @param string $u
* @return int
*/
function uniord($u)
{
$k = mb_convert_encoding($u, 'UCS-2LE', 'UTF-8');
$k1 = ord(substr($k, 0, 1));
$k2 = ord(substr($k, 1, 1));
return $k2 * 256 + $k1;
}
function printJson($data)
{
$data = (array) $data;
header('Content-Type: application/json');
echo json_encode($data);
die;
}
// Бизнес-логика
/**
* Прочитать шаблоны из файла
*
* @param string $templatesFile Файл с шаблонами
* @return array Группы шаблонов
* @throws Exception
*/
function readTemlates($templatesFile)
{
$file = fopen($templatesFile, 'r');
if(!$file)
throw new Exception("Cannot read $templatesFile");
$templates = [];
$currentGroup = null;
while($line = fgets($file))
{
$line = rtrim($line);
if(mb_strlen(trim($line)) == 0) // пустая строка
continue;
if(preg_match('#^[\w:]+:$#ui', $line)) // именованная группа шаблонов
{
$currentGroup = mb_substr($line, 0, -1);
if(isset($templates[$currentGroup]))
throw new Exception("Group $currentGroup already exists");
$templates[$currentGroup] = [];
continue;
}
if(preg_match('#^\t[^\t]+$#', $line)) // шаблон
{
$templates[$currentGroup][] = trim($line);
continue;
}
throw new Exception("Wrong syntax: $line");
}
fclose($file);
return $templates;
}
/**
* Создать строку по случайному шаблону из указанной группы шаблонов
*
* @param string $templates Группы шаблонов
* @param string $group Группа шаблонов для генерации строки
* @return string Сгенерированная строка
* @throws Exception
*/
function generateFromGroup($templates, $group)
{
if(!isset($templates[$group]))
throw new Exception("There are no $group group in templates array");
if(!count($templates[$group]))
throw new Exception("The $group group is empty");
$string = $templates[$group][array_rand($templates[$group])];
// псевдо regex диапазоны
if(preg_match_all('#\[(\w)\-(\w)\]\{(\d),(\d)\}#ui', $string, $regexRanges, PREG_SET_ORDER))
foreach($regexRanges as $regexRange)
$string = mb_replace($regexRange[0], generateRegexRange($regexRange[1], $regexRange[2], (int) $regexRange[3], (int) $regexRange[4]), $string);
if(preg_match_all('#(' . implode('|', array_keys($templates)) . ')#', $string, $templatesIncludings, PREG_SET_ORDER))
foreach($templatesIncludings as $templatesIncluding)
$string = mb_replace($templatesIncluding[0], generateFromGroup($templates, $templatesIncluding[0]), $string, 1);
return trim($string);
}
/**
* Создать строку по regex-like шаблону
*
* @param string $fromChar левая граница диапазона
* @param string $toChar правая граница диапазона
* @param string $minLength минимальная длина
* @param string $maxLength максимальная длина
* @return string Сгенерированная строка
* @throws Exception
*/
function generateRegexRange($fromChar, $toChar, $minLength, $maxLength)
{
$fromCharCode = uniord($fromChar);
$toCharCode = uniord($toChar);
if($fromCharCode > $toCharCode)
throw new Exception("Wrong regex range: fromChar is greater than toChar");
$string = '';
for($i = 0; $i < rand($minLength, $maxLength); $i++)
$string .= unichr($fromCharCode + rand(0, $toCharCode - $fromCharCode));
return $string;
}
try
{
$templates = readTemlates('templates.txt');
$string = generateFromGroup($templates, 'Название');
}
catch(Exception $e)
{
printJson(['status' => 'error', 'message' => $e->getMessage()]);
}
echo printJson(['status' => 'ok', 'data' => $string]);
Число:
[0-9]{1,3}
Аббр:
[А-И]{1,2}
[К-Щ]{1,2}
[Э-Я]{1,2}
Номер:
Аббр-Число
Аббр-Число АббрАббр
Аббр-ЧислоАббр
АббрАббр-Число
Число
ЧислоАббрЧисло
ЧислоАббрЧислоАббр
Предмет:
Черпак
Дуля
Зомби
Цветы:
Фейхоа
Репей
Дуриан
Персона:
Чижык-Пыжик
Леголас
Обама
Место:
Кудыкина Гора
Мышкина Подмышка
Развесёлая
Название:
Номер Предмет
Номер Цветы
Номер Персона
Номер Место
Предмет
Цветы
Персона
Место
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment