Эти функции преобразуют любое положительное целое число в его эквивалентную строку Roman Numeral; и любую римскую цифру к ее числу.
Номер в римскую цифру:
Number.prototype.toRoman= function () {
var num = Math.floor(this),
val, s= '', i= 0,
v = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
r = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
function toBigRoman(n) {
var ret = '', n1 = '', rem = n;
while (rem > 1000) {
var prefix = '', suffix = '', n = rem, s = '' + rem, magnitude = 1;
while (n > 1000) {
n /= 1000;
magnitude *= 1000;
prefix += '(';
suffix += ')';
}
n1 = Math.floor(n);
rem = s - (n1 * magnitude);
ret += prefix + n1.toRoman() + suffix;
}
return ret + rem.toRoman();
}
if (this - num || num < 1) num = 0;
if (num > 3999) return toBigRoman(num);
while (num) {
val = v[i];
while (num >= val) {
num -= val;
s += r[i];
}
++i;
}
return s;
};
Строка римской цифры в номер:
Number.fromRoman = function (roman, accept) {
var s = roman.toUpperCase().replace(/ +/g, ''),
L = s.length, sum = 0, i = 0, next, val,
R = { M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1 };
function fromBigRoman(rn) {
var n = 0, x, n1, S, rx =/(\(*)([MDCLXVI]+)/g;
while ((S = rx.exec(rn)) != null) {
x = S[1].length;
n1 = Number.fromRoman(S[2])
if (isNaN(n1)) return NaN;
if (x) n1 *= Math.pow(1000, x);
n += n1;
}
return n;
}
if (/^[MDCLXVI)(]+$/.test(s)) {
if (s.indexOf('(') == 0) return fromBigRoman(s);
while (i < L) {
val = R[s.charAt(i++)];
next = R[s.charAt(i)] || 0;
if (next - val > 0) val *= -1;
sum += val;
}
if (accept || sum.toRoman() === s) return sum;
}
return NaN;
};
angular.module('app', []).controller('ctrl', function($scope){
$scope.data = [
{Referrer: 'Henry', Amount: 20, Location: 'NY'},
{Referrer: 'Tom', Amount: 10, Location: 'London'},
{Referrer: 'Sam', Amount: 10, Location: 'Paris'},
{Referrer: 'Henry', Amount: 10, Location: 'NY'},
{Referrer: 'Tom', Amount: 20, Location: 'London'},
{Referrer: 'Henry', Amount: 30, Location: 'NY'}
];
$scope.sum = function(name){
return $scope.data.filter(function(x) { return x.Referrer == name; })
.map(function(x) { return x.Amount; }).reduce(function(a, b) { return a + b; });
}
})
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
.totalRow{
border-style: solid;
}
.total{
text-align: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js">
</script>
<div ng-app='app' ng-controller='ctrl'>
<table>
<thead>
<tr>
<th>Referrer</th>
<th>Location</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr ng-init='next = $index + 1' ng-repeat-start='item in dataSorted = (data | orderBy : "Referrer")'>
<td>{{item.Referrer}}</td>
<td>{{item.Location}}</td>
<td>{{item.Amount}}</td>
</tr>
<tr class='totalRow' ng-repeat-end ng-if='!dataSorted[next] || (dataSorted[next].Referrer != item.Referrer)'>
<td colspan='2' class='total'>Total:</td>
<td>{{sum(item.Referrer)}}</td>
</tr>
</tbody>
</table>
</div>