feat: improve bill math

feat: add escrow storage for aveiro and changes in related UI
feat: add cassettes and stackers count to trader
This commit is contained in:
Sérgio Salgado 2023-04-26 23:44:52 +01:00
parent f3ab63766e
commit 4655d733b2
7 changed files with 136 additions and 17 deletions

View file

@ -1,15 +1,112 @@
const _ = require('lodash/fp')
const sumService = require('@haensl/subset-sum')
const getSolution = (units, amount) => {
const billList = _.reduce(
(acc, value) => {
acc.push(..._.times(_.constant(value.denomination), value.count))
return acc
},
[],
units
)
const BILL_LIST_MODES = {
LAST_UNIT_FIRST: 0,
FIRST_UNIT_FIRST: 1,
LOWEST_VALUE_FIRST: 2,
HIGHEST_VALUE_FIRST: 3,
UNIT_ROUND_ROBIN: 4,
VALUE_ROUND_ROBIN: 5
}
const buildBillList = (units, mode) => {
switch (mode) {
case BILL_LIST_MODES.LAST_UNIT_FIRST:
return _.reduce(
(acc, value) => {
acc.push(..._.times(_.constant(value.denomination), value.count))
return acc
},
[],
_.reverse(units)
)
case BILL_LIST_MODES.FIRST_UNIT_FIRST:
return _.reduce(
(acc, value) => {
acc.push(..._.times(_.constant(value.denomination), value.count))
return acc
},
[],
units
)
case BILL_LIST_MODES.LOWEST_VALUE_FIRST:
return _.reduce(
(acc, value) => {
acc.push(..._.times(_.constant(value.denomination), value.count))
return acc
},
[],
_.orderBy(['denomination'], ['asc'])(units)
)
case BILL_LIST_MODES.HIGHEST_VALUE_FIRST:
return _.reduce(
(acc, value) => {
acc.push(..._.times(_.constant(value.denomination), value.count))
return acc
},
[],
_.orderBy(['denomination'], ['desc'])(units)
)
case BILL_LIST_MODES.UNIT_ROUND_ROBIN:
{
const amountOfBills = _.reduce(
(acc, value) => acc + value.count,
0,
units
)
const _units = _.cloneDeep(units)
const bills = []
for(let i = 0; i < amountOfBills; i++) {
const idx = i % _.size(_units)
if (_units[idx].count > 0) {
bills.push(_units[idx].denomination)
}
_units[idx].count--
if (_units[idx].count === 0) {
_units.splice(idx, 1)
}
}
return bills
}
case BILL_LIST_MODES.VALUE_ROUND_ROBIN:
{
const amountOfBills = _.reduce(
(acc, value) => acc + value.count,
0,
units
)
const _units = _.orderBy(['denomination'], ['asc'])(_.cloneDeep(units))
const bills = []
for(let i = 0; i < amountOfBills; i++) {
const idx = i % _.size(_units)
if (_units[idx].count > 0) {
bills.push(_units[idx].denomination)
}
_units[idx].count--
if (_units[idx].count === 0) {
_units.splice(idx, 1)
}
}
return bills
}
default:
throw new Error(`Invalid mode: ${mode}`)
}
}
const getSolution = (units, amount, mode) => {
const billList = buildBillList(units, mode)
const solver = sumService.subsetSum(billList, amount.toNumber())
const solution = _.countBy(Math.floor, solver.next().value)
@ -39,7 +136,7 @@ const solutionToOriginalUnits = (solution, units) => {
}
function makeChange(outCassettes, amount) {
const solution = getSolution(outCassettes, amount)
const solution = getSolution(outCassettes, amount, BILL_LIST_MODES.VALUE_ROUND_ROBIN)
return solutionToOriginalUnits(solution, outCassettes)
}