<?php
// Staring deep into abyss... oh please, oh please
//tools
// tool 1, function to pick form
function doFormCheck($input,$i) {
$form=NULL;
(
0=>array('single'=>'рубль','plural'=>'рублей','special'=>'рубля'), 1=>array('single'=>'тысяча','plural'=>'тысяч','special'=>'тысячи'), 2=>array('single'=>'миллион','plural'=>'миллионов','special'=>'миллиона'), );
// ^this is also map for our numbers layout. 0 roubles 1 thousands 2 millions
//main code identifying form
if ( ($input-1) % 10 == 0 && ($input % 100) !== 11) {
//number ends with 1 except 11
$form= "single";
}
elseif (!($input % 10)) {
//number ends with 0
$form="plural";
}
elseif (round($input / 10) == floor ($input / 10) && !in_array($input % 100, [11,12,13,14])) {
//ends with 1-4 but 1 is omitted because of first condiition check (as is omitted 0)
$form="special";
}
else {
//number ends with 5-9
$form= "plural";
}
return $arrayOfForms[$i][$form];
}
// tool 2, function to lookup last 3 digits of any given number
function identifyLastThreeDigits($input) {
return $input % 1000;
}
//tool 3, function to split complex numbers into array of triplets
function doTriplets($input) {
$arrayOfTriplets=[];
while (identifyLastThreeDigits($input)!==$input) {
//number has > 3 digits
array_push($arrayOfTriplets,identifyLastThreeDigits
($input));
/*
intval() is used here because floor from float produces float. Remainder of float / 1000 will be int. Thus the loop condition !==
in the head will be evaluated as int vs float comparison, thus falling to infinitive cycle
this could be bypassed by either covert coercion in the head of loop != instead of strict !==
or by overt coercion with inval(). i chose the second
*/
}
//now number has <= 3 digits
return $arrayOfTriplets;
}
//tool 4, function to convert arrayofnumbers into a string while picking form with tool1 in a process
function doStringify($arrayOfNumbers) {
$arrayOfStrings = [];
0 => 'ноль', 10 => 'десять', 100 => 'сто',
1 => 'один', 11 => 'одиннадцать', 20 => 'двадцать', 200 => 'двести',
2 => 'два', 12 => 'двенадцать', 30 => 'тридцать', 300 => 'триста',
3 => 'три', 13 => 'тринадцать', 40 => 'сорок', 400 => 'четыреста',
4 => 'четыре', 14 => 'четырнадцать', 50 => 'пятьдесят', 500 => 'пятьсот',
5 => 'пять', 15 => 'пятнадцать', 60 => 'шестьдесят', 600 => 'шестьсот',
6 => 'шесть', 16 => 'шестнадцать', 70 => 'семьдесят', 700 => 'семьсот',
7 => 'семь', 17 => 'семнадцать', 80 => 'восемьдесят', 800 => 'восемьсот',
8 => 'восемь', 18 => 'восемнадцать', 90 => 'девяносто', 900 => 'девятьсот',
9 => 'девять', 19 => 'девятнадцать'
);
1 => 'одна',
2 => 'две',
);
for ($i=0;$i<count($arrayOfNumbers);$i++) {
// remember layout: 0 roubles 1 thousands 2 millions
$spelling = ($i == 1) ? ($femSpelling+$maleSpelling) : $maleSpelling;
// general check for blanks begins
// blanks will not be processed unless '0 roubles' (with 0 being omitted if not standalone)
if ($arrayOfNumbers[$i]==0) {
if ($i==0 && count($arrayOfNumbers) == 1) { $word = $spelling[$arrayOfNumbers[$i]];
$word = $word . " " . doFormCheck($arrayOfNumbers[$i], $i);
}
elseif ($i==0 && count($arrayOfNumbers) > 1) { $word = " " . doFormCheck($arrayOfNumbers[$i], $i);
}
continue;
}
//general check for blanks ends
//filling non-blanks begins
if (isset($spelling[$arrayOfNumbers[$i]])) {
//if number is mapped case
$word = $spelling[$arrayOfNumbers[$i]];
$word = $word . " " . doFormCheck($arrayOfNumbers[$i], $i);
}
else {
//if number is not a mapped case
$componentHundreds=NULL;
$componentTens=NULL;
$componentPrimes=NULL;
//cant use single word, need array of them
$arrayOfWords=[];
//preparing arrayOfWords
if ($arrayOfNumbers[$i] < 100) {
// number will have 2 components. componentHundreds remains NULL.
$componentTens = floor($arrayOfNumbers[$i] / 10) * 10; $componentPrimes = $arrayOfNumbers[$i] - $componentTens;
$arrayOfWords = [$spelling[$componentTens], $spelling[$componentPrimes]];
}
else {
//number will have either 2 (remnant is mapped case) or 3 components
$componentHundreds = floor($arrayOfNumbers[$i] / 100) * 100; $componentTens = $arrayOfNumbers[$i] - $componentHundreds;
//if remnant is mapped case
if (isset($spelling[$componentTens])) { $arrayOfWords=[$spelling[$componentHundreds], $spelling[$componentTens]];
}
// now if remnant is a mapped case having 2 components is enough. If not we must go deeper.
elseif (!isset($spelling[$componentTens])) {
//im using elseif for clarity
$componentTens = floor($componentTens / 10) * 10; $componentPrimes = $arrayOfNumbers[$i] - $componentHundreds - $componentTens;
$arrayOfWords=[$spelling[$componentHundreds], $spelling[$componentTens], $spelling[$componentPrimes]];
}
}
// arrayOfWords prepared
$word = implode(" ", $arrayOfWords) . " " . doFormCheck
($arrayOfNumbers[$i],$i);
// ^our doFormCheck() function can parse number as is, components not needed for it
}
}
return "". implode(" ", $arrayOfStrings);
}
//main function and launcher
function numberToText($input) {
$arrayOfNumbers=[];
//preparing array
if (identifyLastThreeDigits($input)==$input) {
// number is already of <=3 digits
}
elseif (identifyLastThreeDigits($input)!==$input) {
// number has >3 digits
$arrayOfNumbers = doTriplets($input);
}
//array prepared
$string=doStringify($arrayOfNumbers);
// insert amount in parenthesis
$string=preg_replace('/\s(?=(рубл+))/u', " ({$input}) ", $string);
echo "На Вашем счете {$string}";
}
numberToText($amount1);
?>
PD9waHAKCiAKIAovLyBTdGFyaW5nIGRlZXAgaW50byBhYnlzcy4uLiBvaCBwbGVhc2UsIG9oIHBsZWFzZQoKZXJyb3JfcmVwb3J0aW5nKC0xKTsKCi8vdG9vbHMKLy8gdG9vbCAxLCBmdW5jdGlvbiB0byBwaWNrIGZvcm0KCmZ1bmN0aW9uIGRvRm9ybUNoZWNrKCRpbnB1dCwkaSkgewogICAgJGZvcm09TlVMTDsKICAgICRhcnJheU9mRm9ybXM9YXJyYXkKICAgICAgICAoCiAgICAgICAgMD0+YXJyYXkoJ3NpbmdsZSc9PifRgNGD0LHQu9GMJywncGx1cmFsJz0+J9GA0YPQsdC70LXQuScsJ3NwZWNpYWwnPT4n0YDRg9Cx0LvRjycpLAogICAgICAgIDE9PmFycmF5KCdzaW5nbGUnPT4n0YLRi9GB0Y/Rh9CwJywncGx1cmFsJz0+J9GC0YvRgdGP0YcnLCdzcGVjaWFsJz0+J9GC0YvRgdGP0YfQuCcpLAogICAgICAgIDI9PmFycmF5KCdzaW5nbGUnPT4n0LzQuNC70LvQuNC+0L0nLCdwbHVyYWwnPT4n0LzQuNC70LvQuNC+0L3QvtCyJywnc3BlY2lhbCc9PifQvNC40LvQu9C40L7QvdCwJyksCiAgICAgICAgKTsKICAgIAogICAgLy8gXnRoaXMgaXMgYWxzbyBtYXAgZm9yIG91ciBudW1iZXJzIGxheW91dC4gMCByb3VibGVzIDEgdGhvdXNhbmRzIDIgbWlsbGlvbnMKICAgIAogICAgLy9tYWluIGNvZGUgaWRlbnRpZnlpbmcgZm9ybQogICAgCiAgICBpZiAoICgkaW5wdXQtMSkgJSAxMCA9PSAwICYmICgkaW5wdXQgJSAxMDApICE9PSAxMSkgewogICAgICAgIAogICAgICAgIC8vbnVtYmVyIGVuZHMgd2l0aCAxIGV4Y2VwdCAxMQogICAgICAgIAogICAgICAgICRmb3JtPSAic2luZ2xlIjsKICAgICAgICB9CiAgICAKICAgIGVsc2VpZiAoISgkaW5wdXQgJSAxMCkpIHsKICAgICAgICAKICAgICAgICAvL251bWJlciBlbmRzIHdpdGggMAogICAgICAgIAogICAgICAgICRmb3JtPSJwbHVyYWwiOwogICAgICAgIAogICAgfQogICAgZWxzZWlmIChyb3VuZCgkaW5wdXQgLyAxMCkgPT0gZmxvb3IgKCRpbnB1dCAvIDEwKSAmJiAhaW5fYXJyYXkoJGlucHV0ICUgMTAwLCBbMTEsMTIsMTMsMTRdKSkgewogICAgICAgIAogICAgICAgIC8vZW5kcyB3aXRoIDEtNCBidXQgMSBpcyBvbWl0dGVkIGJlY2F1c2Ugb2YgZmlyc3QgY29uZGlpdGlvbiBjaGVjayAoYXMgaXMgb21pdHRlZCAwKQogICAgICAgIAogICAgICAgICRmb3JtPSJzcGVjaWFsIjsKICAgICAgICAKICAgICAgICB9CiAgICAKICAgIGVsc2UgewogICAgICAgIAogICAgICAgIC8vbnVtYmVyIGVuZHMgd2l0aCA1LTkKICAgICAgICAKICAgICAgICAkZm9ybT0gInBsdXJhbCI7CiAgICAgICAgCiAgICAgICAgfQogICAgCiAgICByZXR1cm4gJGFycmF5T2ZGb3Jtc1skaV1bJGZvcm1dOwp9CiAgICAKICAgIAovLyB0b29sIDIsIGZ1bmN0aW9uIHRvIGxvb2t1cCBsYXN0IDMgZGlnaXRzIG9mIGFueSBnaXZlbiBudW1iZXIKCmZ1bmN0aW9uIGlkZW50aWZ5TGFzdFRocmVlRGlnaXRzKCRpbnB1dCkgewogICAgCiAgICByZXR1cm4gJGlucHV0ICUgMTAwMDsKfQogICAKLy90b29sIDMsIGZ1bmN0aW9uIHRvIHNwbGl0IGNvbXBsZXggbnVtYmVycyBpbnRvIGFycmF5IG9mIHRyaXBsZXRzCgpmdW5jdGlvbiBkb1RyaXBsZXRzKCRpbnB1dCkgewogICAgJGFycmF5T2ZUcmlwbGV0cz1bXTsKICAgIAogICAgd2hpbGUgKGlkZW50aWZ5TGFzdFRocmVlRGlnaXRzKCRpbnB1dCkhPT0kaW5wdXQpIHsKICAgICAgICAKICAgICAgICAvL251bWJlciBoYXMgPiAzIGRpZ2l0cwogICAgICAgIAogICAgICAgIGFycmF5X3B1c2goJGFycmF5T2ZUcmlwbGV0cyxpZGVudGlmeUxhc3RUaHJlZURpZ2l0cygkaW5wdXQpKTsKICAgICAgICAkaW5wdXQgPSBpbnR2YWwoZmxvb3IoJGlucHV0IC8gMTAwMCkpOwogICAgICAgIAogICAgICAgICAgLyoKICAgICAgICAKICAgICAgICBpbnR2YWwoKSBpcyB1c2VkIGhlcmUgYmVjYXVzZSBmbG9vciBmcm9tIGZsb2F0IHByb2R1Y2VzIGZsb2F0LiBSZW1haW5kZXIgb2YgZmxvYXQgLyAxMDAwIHdpbGwgYmUgaW50LiBUaHVzIHRoZSBsb29wIGNvbmRpdGlvbiAhPT0KICAgICAgICBpbiB0aGUgaGVhZCB3aWxsIGJlIGV2YWx1YXRlZCBhcyBpbnQgdnMgZmxvYXQgY29tcGFyaXNvbiwgdGh1cyBmYWxsaW5nIHRvIGluZmluaXRpdmUgY3ljbGUgCiAgICAgICAgCiAgICAgICAgdGhpcyBjb3VsZCBiZSBieXBhc3NlZCBieSBlaXRoZXIgY292ZXJ0IGNvZXJjaW9uIGluIHRoZSBoZWFkIG9mIGxvb3AgIT0gaW5zdGVhZCBvZiBzdHJpY3QgIT09CiAgICAgICAgb3IgYnkgb3ZlcnQgY29lcmNpb24gd2l0aCBpbnZhbCgpLiBpIGNob3NlIHRoZSBzZWNvbmQKICAgICAgICAKICAgICAgICAqLwogICAgfQogICAgCiAgICAvL25vdyBudW1iZXIgaGFzIDw9IDMgZGlnaXRzCiAgICAKICAgIGFycmF5X3B1c2goJGFycmF5T2ZUcmlwbGV0cywgJGlucHV0KTsKICAgIAogICAgcmV0dXJuICRhcnJheU9mVHJpcGxldHM7Cn0KICAgICAgICAKICAgICAgICAKLy90b29sIDQsIGZ1bmN0aW9uIHRvIGNvbnZlcnQgYXJyYXlvZm51bWJlcnMgaW50byBhIHN0cmluZyB3aGlsZSBwaWNraW5nIGZvcm0gd2l0aCB0b29sMSBpbiBhIHByb2Nlc3MKCmZ1bmN0aW9uIGRvU3RyaW5naWZ5KCRhcnJheU9mTnVtYmVycykgewogICAgCiAgICAkYXJyYXlPZlN0cmluZ3MgPSBbXTsKICAgIAogICAgCiAgICAkbWFsZVNwZWxsaW5nID0gYXJyYXkoCiAgICAgICAgCiAgICAgICAgMCAgID0+ICAn0L3QvtC70YwnLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxMCAgPT4gICfQtNC10YHRj9GC0YwnLCAgICAgICAxMDAgPT4gICfRgdGC0L4nLAogICAgICAgIDEgICA9PiAgJ9C+0LTQuNC9JywgICAgICAgICAxMSAgPT4gICfQvtC00LjQvdC90LDQtNGG0LDRgtGMJywgICAgICAyMCAgPT4gICfQtNCy0LDQtNGG0LDRgtGMJywgICAgIDIwMCA9PiAgJ9C00LLQtdGB0YLQuCcsCiAgICAgICAgMiAgID0+ICAn0LTQstCwJywgICAgICAgICAgMTIgID0+ICAn0LTQstC10L3QsNC00YbQsNGC0YwnLCAgICAgICAzMCAgPT4gICfRgtGA0LjQtNGG0LDRgtGMJywgICAgIDMwMCA9PiAgJ9GC0YDQuNGB0YLQsCcsCiAgICAgICAgMyAgID0+ICAn0YLRgNC4JywgICAgICAgICAgMTMgID0+ICAn0YLRgNC40L3QsNC00YbQsNGC0YwnLCAgICAgICA0MCAgPT4gICfRgdC+0YDQvtC6JywgICAgICAgIDQwMCA9PiAgJ9GH0LXRgtGL0YDQtdGB0YLQsCcsCiAgICAgICAgNCAgID0+ICAn0YfQtdGC0YvRgNC1JywgICAgICAgMTQgID0+ICAn0YfQtdGC0YvRgNC90LDQtNGG0LDRgtGMJywgICAgIDUwICA9PiAgJ9C/0Y/RgtGM0LTQtdGB0Y/RgicsICAgIDUwMCA9PiAgJ9C/0Y/RgtGM0YHQvtGCJywKICAgICAgICA1ICAgPT4gICfQv9GP0YLRjCcsICAgICAgICAgMTUgID0+ICAn0L/Rj9GC0L3QsNC00YbQsNGC0YwnLCAgICAgICA2MCAgPT4gICfRiNC10YHRgtGM0LTQtdGB0Y/RgicsICAgNjAwID0+ICAn0YjQtdGB0YLRjNGB0L7RgicsCiAgICAgICAgNiAgID0+ICAn0YjQtdGB0YLRjCcsICAgICAgICAxNiAgPT4gICfRiNC10YHRgtC90LDQtNGG0LDRgtGMJywgICAgICA3MCAgPT4gICfRgdC10LzRjNC00LXRgdGP0YInLCAgICA3MDAgPT4gICfRgdC10LzRjNGB0L7RgicsICAgIAogICAgICAgIDcgICA9PiAgJ9GB0LXQvNGMJywgICAgICAgICAxNyAgPT4gICfRgdC10LzQvdCw0LTRhtCw0YLRjCcsICAgICAgIDgwICA9PiAgJ9Cy0L7RgdC10LzRjNC00LXRgdGP0YInLCAgIDgwMCA9PiAgJ9Cy0L7RgdC10LzRjNGB0L7RgicsCiAgICAgICAgOCAgID0+ICAn0LLQvtGB0LXQvNGMJywgICAgICAgMTggID0+ICAn0LLQvtGB0LXQvNC90LDQtNGG0LDRgtGMJywgICAgIDkwICA9PiAgJ9C00LXQstGP0L3QvtGB0YLQvicsICAgICA5MDAgPT4gICfQtNC10LLRj9GC0YzRgdC+0YInLAogICAgICAgIDkgICA9PiAgJ9C00LXQstGP0YLRjCcsICAgICAgIDE5ICA9PiAgJ9C00LXQstGP0YLQvdCw0LTRhtCw0YLRjCcKICAgICk7CiAgICAKICAgICRmZW1TcGVsbGluZyA9IGFycmF5KAogICAgICAgIAogICAgICAgIDEgPT4gJ9C+0LTQvdCwJywKICAgICAgICAyID0+ICfQtNCy0LUnLAogICAgICAgIAogICAgICAgICk7CiAgICAKICAgIGZvciAoJGk9MDskaTxjb3VudCgkYXJyYXlPZk51bWJlcnMpOyRpKyspIHsKICAgICAgICAKICAgICAgICAvLyByZW1lbWJlciBsYXlvdXQ6IDAgcm91YmxlcyAxIHRob3VzYW5kcyAyIG1pbGxpb25zCiAgICAgICAgCiAgICAgICAgJHNwZWxsaW5nID0gKCRpID09IDEpID8gKCRmZW1TcGVsbGluZyskbWFsZVNwZWxsaW5nKSA6ICRtYWxlU3BlbGxpbmc7CiAgICAgICAgCiAgICAgICAgLy8gZ2VuZXJhbCBjaGVjayBmb3IgYmxhbmtzIGJlZ2lucwogICAgICAgIAogICAgICAgIC8vIGJsYW5rcyB3aWxsIG5vdCBiZSBwcm9jZXNzZWQgdW5sZXNzICcwIHJvdWJsZXMnICh3aXRoIDAgYmVpbmcgb21pdHRlZCBpZiBub3Qgc3RhbmRhbG9uZSkKICAgICAgICAKICAgICAgICBpZiAoJGFycmF5T2ZOdW1iZXJzWyRpXT09MCkgewogICAgICAgICAgICAKICAgICAgICAgICAgaWYgKCRpPT0wICYmIGNvdW50KCRhcnJheU9mTnVtYmVycykgPT0gMSkgewogICAgICAgICAgICAgICAgJHdvcmQgPSAkc3BlbGxpbmdbJGFycmF5T2ZOdW1iZXJzWyRpXV07CiAgICAgICAgICAgICAgICAkd29yZCA9ICR3b3JkIC4gIiAiIC4gZG9Gb3JtQ2hlY2soJGFycmF5T2ZOdW1iZXJzWyRpXSwgJGkpOwogICAgICAgICAgICAgICAgYXJyYXlfdW5zaGlmdCgkYXJyYXlPZlN0cmluZ3MsICR3b3JkKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlaWYgKCRpPT0wICYmIGNvdW50KCRhcnJheU9mTnVtYmVycykgPiAxKSB7CiAgICAgICAgICAgICAgICAkd29yZCA9ICIgIiAuIGRvRm9ybUNoZWNrKCRhcnJheU9mTnVtYmVyc1skaV0sICRpKTsKICAgICAgICAgICAgICAgIGFycmF5X3Vuc2hpZnQoJGFycmF5T2ZTdHJpbmdzLCAkd29yZCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgLy9nZW5lcmFsIGNoZWNrIGZvciBibGFua3MgZW5kcwogICAgICAgIAogICAgICAgIC8vZmlsbGluZyBub24tYmxhbmtzIGJlZ2lucwogICAgICAgIAogICAgICAgIAogICAgICAgIGlmIChpc3NldCgkc3BlbGxpbmdbJGFycmF5T2ZOdW1iZXJzWyRpXV0pKSB7CiAgICAgICAgICAgIAogICAgICAgICAgICAvL2lmIG51bWJlciBpcyBtYXBwZWQgY2FzZQogICAgICAgICAgICAKICAgICAgICAgICAgJHdvcmQgPSAkc3BlbGxpbmdbJGFycmF5T2ZOdW1iZXJzWyRpXV07CiAgICAgICAgICAgIAogICAgICAgICAgICAkd29yZCA9ICR3b3JkIC4gIiAiIC4gZG9Gb3JtQ2hlY2soJGFycmF5T2ZOdW1iZXJzWyRpXSwgJGkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgYXJyYXlfdW5zaGlmdCgkYXJyYXlPZlN0cmluZ3MsICR3b3JkKTsKICAgICAgICAgICAgCiAgICAgICAgfQogICAgICAgIAogICAgICAgIGVsc2UgewogICAgICAgICAgICAKICAgICAgICAgICAgLy9pZiBudW1iZXIgaXMgbm90IGEgbWFwcGVkIGNhc2UKICAgICAgICAgICAgCiAgICAgICAgICAgICRjb21wb25lbnRIdW5kcmVkcz1OVUxMOwogICAgICAgICAgICAkY29tcG9uZW50VGVucz1OVUxMOwogICAgICAgICAgICAkY29tcG9uZW50UHJpbWVzPU5VTEw7CiAgICAgICAgICAgIAogICAgICAgICAgICAvL2NhbnQgdXNlIHNpbmdsZSB3b3JkLCBuZWVkIGFycmF5IG9mIHRoZW0KICAgICAgICAgICAgCiAgICAgICAgICAgICRhcnJheU9mV29yZHM9W107CiAgICAgICAgICAgIAogICAgICAgICAgICAKICAgICAgICAgICAgLy9wcmVwYXJpbmcgYXJyYXlPZldvcmRzCiAgICAgICAgICAgIAogICAgICAgICAgICBpZiAoJGFycmF5T2ZOdW1iZXJzWyRpXSA8IDEwMCkgewogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAvLyBudW1iZXIgd2lsbCBoYXZlIDIgY29tcG9uZW50cy4gY29tcG9uZW50SHVuZHJlZHMgcmVtYWlucyBOVUxMLgogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAkY29tcG9uZW50VGVucyA9IGZsb29yKCRhcnJheU9mTnVtYmVyc1skaV0gLyAxMCkgKiAxMDsKICAgICAgICAgICAgICAgICRjb21wb25lbnRQcmltZXMgPSAkYXJyYXlPZk51bWJlcnNbJGldIC0gJGNvbXBvbmVudFRlbnM7CiAgICAgICAgICAgICAgICAkYXJyYXlPZldvcmRzID0gWyRzcGVsbGluZ1skY29tcG9uZW50VGVuc10sICRzcGVsbGluZ1skY29tcG9uZW50UHJpbWVzXV07CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgfQogICAgICAgICAgICAKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vbnVtYmVyIHdpbGwgaGF2ZSBlaXRoZXIgMiAocmVtbmFudCBpcyBtYXBwZWQgY2FzZSkgb3IgMyBjb21wb25lbnRzCiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICRjb21wb25lbnRIdW5kcmVkcyA9IGZsb29yKCRhcnJheU9mTnVtYmVyc1skaV0gLyAxMDApICogMTAwOwogICAgICAgICAgICAgICAgJGNvbXBvbmVudFRlbnMgPSAkYXJyYXlPZk51bWJlcnNbJGldIC0gJGNvbXBvbmVudEh1bmRyZWRzOwogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAvL2lmIHJlbW5hbnQgaXMgbWFwcGVkIGNhc2UKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRzcGVsbGluZ1skY29tcG9uZW50VGVuc10pKSB7CiAgICAgICAgICAgICAgICAgICAgJGFycmF5T2ZXb3Jkcz1bJHNwZWxsaW5nWyRjb21wb25lbnRIdW5kcmVkc10sICRzcGVsbGluZ1skY29tcG9uZW50VGVuc11dOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAvLyBub3cgaWYgcmVtbmFudCBpcyBhIG1hcHBlZCBjYXNlIGhhdmluZyAyIGNvbXBvbmVudHMgaXMgZW5vdWdoLiBJZiBub3Qgd2UgbXVzdCBnbyBkZWVwZXIuCiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGVsc2VpZiAoIWlzc2V0KCRzcGVsbGluZ1skY29tcG9uZW50VGVuc10pKSB7CiAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgLy9pbSB1c2luZyBlbHNlaWYgZm9yIGNsYXJpdHkKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAkY29tcG9uZW50VGVucyA9IGZsb29yKCRjb21wb25lbnRUZW5zIC8gMTApICogMTA7CiAgICAgICAgICAgICAgICAgICAgJGNvbXBvbmVudFByaW1lcyA9ICRhcnJheU9mTnVtYmVyc1skaV0gLSAkY29tcG9uZW50SHVuZHJlZHMgLSAkY29tcG9uZW50VGVuczsKICAgICAgICAgICAgICAgICAgICAkYXJyYXlPZldvcmRzPVskc3BlbGxpbmdbJGNvbXBvbmVudEh1bmRyZWRzXSwgJHNwZWxsaW5nWyRjb21wb25lbnRUZW5zXSwgJHNwZWxsaW5nWyRjb21wb25lbnRQcmltZXNdXTsKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIGFycmF5T2ZXb3JkcyBwcmVwYXJlZAogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgCiAgICAgICAgICAgICR3b3JkID0gaW1wbG9kZSgiICIsICRhcnJheU9mV29yZHMpIC4gIiAiIC4gZG9Gb3JtQ2hlY2soJGFycmF5T2ZOdW1iZXJzWyRpXSwkaSk7IAogICAgICAgICAgICAKICAgICAgICAgICAgLy8gXm91ciBkb0Zvcm1DaGVjaygpIGZ1bmN0aW9uIGNhbiBwYXJzZSBudW1iZXIgYXMgaXMsIGNvbXBvbmVudHMgbm90IG5lZWRlZCBmb3IgaXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgIGFycmF5X3Vuc2hpZnQoJGFycmF5T2ZTdHJpbmdzLCAkd29yZCk7CiAgICAgICAgfQogICAgfQoKICAgIAogICAgcmV0dXJuICIiLiBpbXBsb2RlKCIgIiwgJGFycmF5T2ZTdHJpbmdzKTsKICAgIAp9CgoKLy9tYWluIGZ1bmN0aW9uIGFuZCBsYXVuY2hlcgoKZnVuY3Rpb24gbnVtYmVyVG9UZXh0KCRpbnB1dCkgewogICAgCiAgICAkYXJyYXlPZk51bWJlcnM9W107CiAgICAKICAgIC8vcHJlcGFyaW5nIGFycmF5IAogICAgCiAgICBpZiAoaWRlbnRpZnlMYXN0VGhyZWVEaWdpdHMoJGlucHV0KT09JGlucHV0KSB7CiAgICAgICAKICAgICAgIC8vIG51bWJlciBpcyBhbHJlYWR5IG9mIDw9MyBkaWdpdHMKICAgICAgICAKICAgICAgICBhcnJheV9wdXNoKCRhcnJheU9mTnVtYmVycywgJGlucHV0KTsKICAgICAgICAKICAgIH0KICAgIAogICAgZWxzZWlmIChpZGVudGlmeUxhc3RUaHJlZURpZ2l0cygkaW5wdXQpIT09JGlucHV0KSB7CiAgICAgICAgCiAgICAgICAgLy8gbnVtYmVyIGhhcyA+MyBkaWdpdHMKICAgICAgICAKICAgICAgICAkYXJyYXlPZk51bWJlcnMgPSBkb1RyaXBsZXRzKCRpbnB1dCk7CiAgICB9CiAgICAKICAgIC8vYXJyYXkgcHJlcGFyZWQKICAgIAogICAgJHN0cmluZz1kb1N0cmluZ2lmeSgkYXJyYXlPZk51bWJlcnMpOwogICAgCiAgICAvLyBpbnNlcnQgYW1vdW50IGluIHBhcmVudGhlc2lzCiAgICAKICAgICRzdHJpbmc9cHJlZ19yZXBsYWNlKCcvXHMoPz0o0YDRg9Cx0LsrKSkvdScsICIgKHskaW5wdXR9KSAiLCAkc3RyaW5nKTsKICAgIAogICAgZWNobyAi0J3QsCDQktCw0YjQtdC8INGB0YfQtdGC0LUgeyRzdHJpbmd9IjsKfQogCiRhbW91bnQxID0gbXRfcmFuZCgxLDk5OTk5OTk5KTsKbnVtYmVyVG9UZXh0KCRhbW91bnQxKTsKCiAKIAo/Pg==