xref: /webtrees/app/Services/RomanNumeralsService.php (revision 9cad76450e19b542a70c3dfaef6fe5a028eaee70)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2019 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16declare(strict_types=1);
17
18namespace Fisharebest\Webtrees\Services;
19
20/**
21 * Convert to and from Roman Numerals
22 */
23class RomanNumeralsService
24{
25    // Convert numbers to/from roman numerals
26    private const ROMAN_NUMERALS = [
27        1000 => 'M',
28        900  => 'CM',
29        500  => 'D',
30        400  => 'CD',
31        100  => 'C',
32        90   => 'XC',
33        50   => 'L',
34        40   => 'XL',
35        10   => 'X',
36        9    => 'IX',
37        5    => 'V',
38        4    => 'IV',
39        1    => 'I',
40    ];
41
42    /**
43     * Convert a decimal number to roman numerals
44     *
45     * @param int $number
46     *
47     * @return string
48     */
49    public function numberToRomanNumerals(int $number): string
50    {
51        if ($number < 1) {
52            // Cannot convert zero/negative numbers
53            return (string) $number;
54        }
55        $roman = '';
56        foreach (self::ROMAN_NUMERALS as $key => $value) {
57            while ($number >= $key) {
58                $roman  .= $value;
59                $number -= $key;
60            }
61        }
62
63        return $roman;
64    }
65
66    /**
67     * Convert a roman numeral to decimal
68     *
69     * @param string $roman
70     *
71     * @return int
72     */
73    public function romanNumeralsToNumber(string $roman): int
74    {
75        $num = 0;
76        foreach (self::ROMAN_NUMERALS as $key => $value) {
77            while (strpos($roman, $value) === 0) {
78                $num += $key;
79                $roman = substr($roman, strlen($value));
80            }
81        }
82
83        return $num;
84    }
85}
86