27 const PATTERN_ROMAN_RANGE =
"/^([ivxlcdm]+\.*\s*[*\â “\-&+,;]\s*){1,}[ivxlcdm]+\.?$/i";
const PATTERN_AFFIXES = "/^[a-z]?\d+[a-z]?$/i";
const PATTERN_COMMA_AMPERSAND_RANGE = "/\d*([\s?\-&+,;\s])+\d+/";
const ROMAN_NUMERALS = [
["", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"],
["", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"],
["", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"],
["", "m", "mm", "mmm", "mmmm", "mmmmm"]
];
const ROMAN_DIGITS = [
"M" => 1000,
"D" => 500,
"C" => 100,
"L" => 50,
"X" => 10,
"V" => 5,
"I" => 1
];
/**
* @return Closure
*/
public static function getCompareNumber()
{
return function ($numA, $numB, $order) {
if (is_numeric($numA) && is_numeric($numB)) {
$ret = $numA - $numB;
} else {
$ret = strcasecmp($numA, $numB);
}
if ("descending" === $order) {
return $ret > 0 ? -1 : 1;
}
return $ret > 0 ? 1 : -1;
};
}
/**
* @param $num
* @return string
*/
public static function dec2roman($num)
{
$ret = "";
if ($num < 6000) {
$numStr = strrev($num);
$len = strlen($numStr);
for ($pos = 0; $pos < $len; $pos++) {
$n = $numStr[$pos];
$ret = self::ROMAN_NUMERALS[$pos][$n] . $ret;
}
}
return $ret;
}
/**
* @param $romanNumber
* @return int|mixed
*/
public static function roman2Dec($romanNumber)
{
$romanNumber = trim($romanNumber);
if (is_numeric($romanNumber)) {
return 0;
}
$values = [];
// Convert the string to an array of roman values:
for ($i = 0; $i < strlen($romanNumber); ++$i) {
$char = strtoupper($romanNumber[$i]);
if (self::ROMAN_DIGITS[$char] !== null) {
$values[] = self::ROMAN_DIGITS[$char];
}
}
$sum = 0;
while ($current = current($values)) {
$next = next($values);
$next > $current ? $sum += $next - $current + 0 * next($values) : $sum += $current;
}
return $sum;
}
/**
* @param $str
* @return bool
*/
public static function isRomanNumber($str)
{
$number = trim($str);
for ($i = 0; $i < strlen($number); ++$i) {
$char = strtoupper($number[$i]);
if (!in_array($char, array_keys(self::ROMAN_DIGITS))) {
return false;
}
}
return true;
}
/**
* @param $str
* @return string
*/
public static function evaluateStringPluralism($str)
{
$plural = 'single';
if (!empty($str)) {
$isRange = self::isRange($str);
if ($isRange) {
return 'multiple';
} else {
if (is_numeric($str) || NumberHelper::isRomanNumber($str)) {
return 'single';
}
}
}
return $plural;
}
/**
* @param $string
* @return mixed
*/
public static function extractNumber($string)
{
if (preg_match("/(\d+)[^\d]*$/", $string, $match)) {
return $match[1];
}
return $string;
}
/**
* @param $str
* @return array[]|false|string[]
*/
public static function splitByRangeDelimiter($str)
{
return preg_split("/[-–&,]/", $str);
}
/**
* @param string $str
* @return bool
*/
private static function isRange($str)
{
$rangeParts = self::splitByRangeDelimiter($str);
$isRange = false;
if (count($rangeParts) > 1) {
$isRange = true;
foreach ($rangeParts as $range) {
if (NumberHelper::isRomanNumber(trim($range)) || is_numeric(trim($range))) {
$isRange = $isRange && true;
}
}
}
return $isRange;
}
/**
* @param int|string $number
* @return bool
*/
public static function isRomanRange($number)
{
return preg_match(self::PATTERN_ROMAN_RANGE, $number);
}
}
€“\-&+,;]\s*){1,}[ivxlcdm]+\.?$/i";
34 [
"",
"i",
"ii",
"iii",
"iv",
"v",
"vi",
"vii",
"viii",
"ix"],
35 [
"",
"x",
"xx",
"xxx",
"xl",
"l",
"lx",
"lxx",
"lxxx",
"xc"],
36 [
"",
"c",
"cc",
"ccc",
"cd",
"d",
"dc",
"dcc",
"dccc",
"cm"],
37 [
"",
"m",
"mm",
"mmm",
"mmmm",
"mmmmm"]
55 return function ($numA, $numB, $order) {
56 if (is_numeric($numA) && is_numeric($numB)) {
59 $ret = strcasecmp($numA, $numB);
61 if (
"descending" === $order) {
62 return $ret > 0 ? -1 : 1;
64 return $ret > 0 ? 1 : -1;
76 $numStr = strrev($num);
77 $len = strlen($numStr);
78 for ($pos = 0; $pos < $len; $pos++) {
80 $ret = self::ROMAN_NUMERALS[$pos][$n] . $ret;
92 $romanNumber = trim($romanNumber);
93 if (is_numeric($romanNumber)) {
99 for ($i = 0; $i < strlen($romanNumber); ++$i) {
100 $char = strtoupper($romanNumber[$i]);
101 if (self::ROMAN_DIGITS[$char] !==
null) {
102 $values[] = self::ROMAN_DIGITS[$char];
107 while ($current = current($values)) {
108 $next = next($values);
109 $next > $current ? $sum += $next - $current + 0 * next($values) : $sum += $current;
120 $number = trim($str);
121 for ($i = 0; $i < strlen($number); ++$i) {
122 $char = strtoupper($number[$i]);
123 if (!in_array($char, array_keys(self::ROMAN_DIGITS))) {
138 $isRange = self::isRange($str);
156 if (preg_match(
"/(\d+)[^\d]*$/", $string, $match)) {
168 return preg_split(
"/[-–&,]/", $str);
175 private static function isRange($str)
179 if (count($rangeParts) > 1) {
181 foreach ($rangeParts as $range) {
183 $isRange = $isRange &&
true;
196 return preg_match(self::PATTERN_ROMAN_RANGE, $number);