Compare commits
11 commits
master
...
remove-32b
Author | SHA1 | Date | |
---|---|---|---|
|
412c34f6d9 | ||
|
e8a79c8dbf | ||
|
496ef039b7 | ||
|
6cbc22312f | ||
|
3a925948e2 | ||
|
6e15b985cb | ||
|
9a442361ad | ||
|
f5417bcc8d | ||
|
fb3e12b8a7 | ||
|
75da379079 | ||
|
423f355766 |
22 changed files with 97 additions and 71 deletions
|
@ -1,5 +1,5 @@
|
||||||
function amountToInteger(n) {
|
function amountToInteger(n) {
|
||||||
return Math.round(n * 100) | 0;
|
return Math.round(n * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function integerToAmount(n) {
|
function integerToAmount(n) {
|
||||||
|
|
|
@ -362,8 +362,8 @@ ipcMain.on('screenshot', () => {
|
||||||
let width = 1100;
|
let width = 1100;
|
||||||
|
|
||||||
// This is for the main screenshot inside the frame
|
// This is for the main screenshot inside the frame
|
||||||
clientWin.setSize(width, (width * (427 / 623)) | 0);
|
clientWin.setSize(width, Math.floor(width * (427 / 623)));
|
||||||
// clientWin.setSize(width, (width * (495 / 700)) | 0);
|
// clientWin.setSize(width, Math.floor(width * (495 / 700)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -35,31 +35,31 @@ async function init() {
|
||||||
for (let i = 0; i < 100; i++) {
|
for (let i = 0; i < 100; i++) {
|
||||||
if (Math.random() < 0.02) {
|
if (Math.random() < 0.02) {
|
||||||
let parent = {
|
let parent = {
|
||||||
date: '2020-01-' + pad((Math.random() * 30) | 0),
|
date: '2020-01-' + pad(Math.floor(Math.random() * 30)),
|
||||||
amount: (Math.random() * 10000) | 0,
|
amount: Math.floor(Math.random() * 10000),
|
||||||
account: accounts[0].id,
|
account: accounts[0].id,
|
||||||
notes: 'foo'
|
notes: 'foo'
|
||||||
};
|
};
|
||||||
db.insertTransaction(parent);
|
db.insertTransaction(parent);
|
||||||
db.insertTransaction(
|
db.insertTransaction(
|
||||||
makeChild(parent, {
|
makeChild(parent, {
|
||||||
amount: (Math.random() * 1000) | 0
|
amount: Math.floor(Math.random() * 1000)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
db.insertTransaction(
|
db.insertTransaction(
|
||||||
makeChild(parent, {
|
makeChild(parent, {
|
||||||
amount: (Math.random() * 1000) | 0
|
amount: Math.floor(Math.random() * 1000)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
db.insertTransaction(
|
db.insertTransaction(
|
||||||
makeChild(parent, {
|
makeChild(parent, {
|
||||||
amount: (Math.random() * 1000) | 0
|
amount: Math.floor(Math.random() * 1000)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
db.insertTransaction({
|
db.insertTransaction({
|
||||||
date: '2020-01-' + pad((Math.random() * 30) | 0),
|
date: '2020-01-' + pad(Math.floor(Math.random() * 30)),
|
||||||
amount: (Math.random() * 10000) | 0,
|
amount: Math.floor(Math.random() * 10000),
|
||||||
account: accounts[0].id
|
account: accounts[0].id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,6 @@ import {
|
||||||
import q from '../shared/query';
|
import q from '../shared/query';
|
||||||
import { currencyToAmount, amountToInteger } from '../shared/util';
|
import { currencyToAmount, amountToInteger } from '../shared/util';
|
||||||
|
|
||||||
function isInteger(num) {
|
|
||||||
return (num | 0) === num;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAccountFilter(accountId, field = 'account') {
|
export function getAccountFilter(accountId, field = 'account') {
|
||||||
if (accountId) {
|
if (accountId) {
|
||||||
if (accountId === 'budgeted') {
|
if (accountId === 'budgeted') {
|
||||||
|
@ -82,7 +78,7 @@ export function makeTransactionSearchQuery(currentQuery, search, dateFormat) {
|
||||||
amount: { $transform: '$abs', $eq: amountToInteger(amount) }
|
amount: { $transform: '$abs', $eq: amountToInteger(amount) }
|
||||||
},
|
},
|
||||||
amount != null &&
|
amount != null &&
|
||||||
isInteger(amount) && {
|
Number.isInteger(amount) && {
|
||||||
amount: {
|
amount: {
|
||||||
$transform: { $abs: { $idiv: ['$', 100] } },
|
$transform: { $abs: { $idiv: ['$', 100] } },
|
||||||
$eq: amount
|
$eq: amount
|
||||||
|
|
|
@ -93,7 +93,7 @@ function initBasicServer(delay) {
|
||||||
function initPagingServer(dataLength, { delay, eventType = 'select' } = {}) {
|
function initPagingServer(dataLength, { delay, eventType = 'select' } = {}) {
|
||||||
let data = [];
|
let data = [];
|
||||||
for (let i = 0; i < dataLength; i++) {
|
for (let i = 0; i < dataLength; i++) {
|
||||||
data.push({ id: i, date: subDays('2020-05-01', (i / 5) | 0) });
|
data.push({ id: i, date: subDays('2020-05-01', Math.floor(i / 5)) });
|
||||||
}
|
}
|
||||||
|
|
||||||
initServer({
|
initServer({
|
||||||
|
|
|
@ -11,7 +11,7 @@ import * as monthUtils from '../shared/months';
|
||||||
import q from '../shared/query';
|
import q from '../shared/query';
|
||||||
|
|
||||||
function pickRandom(list) {
|
function pickRandom(list) {
|
||||||
return list[((Math.random() * list.length) | 0) % list.length];
|
return list[Math.floor(Math.random() * list.length) % list.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
function number(start, end) {
|
function number(start, end) {
|
||||||
|
@ -19,7 +19,7 @@ function number(start, end) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function integer(start, end) {
|
function integer(start, end) {
|
||||||
return number(start, end) | 0;
|
return Math.round(number(start, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
function findMin(items, field) {
|
function findMin(items, field) {
|
||||||
|
@ -104,13 +104,13 @@ async function fillPrimaryChecking(handlers, account, payees, groups) {
|
||||||
amount,
|
amount,
|
||||||
payee: payee.id,
|
payee: payee.id,
|
||||||
account: account.id,
|
account: account.id,
|
||||||
date: monthUtils.subDays(monthUtils.currentDay(), (i / 3) | 0),
|
date: monthUtils.subDays(monthUtils.currentDay(), Math.floor(i / 3)),
|
||||||
category: category.id
|
category: category.id
|
||||||
};
|
};
|
||||||
transactions.push(transaction);
|
transactions.push(transaction);
|
||||||
|
|
||||||
if (Math.random() < 0.2) {
|
if (Math.random() < 0.2) {
|
||||||
let a = (transaction.amount / 3) | 0;
|
let a = Math.round(transaction.amount / 3);
|
||||||
let pick = () =>
|
let pick = () =>
|
||||||
payee === incomePayee
|
payee === incomePayee
|
||||||
? incomeGroup.categories.find(c => c.name === 'Income').id
|
? incomeGroup.categories.find(c => c.name === 'Income').id
|
||||||
|
@ -244,7 +244,7 @@ async function fillChecking(handlers, account, payees, groups) {
|
||||||
amount,
|
amount,
|
||||||
payee: payee.id,
|
payee: payee.id,
|
||||||
account: account.id,
|
account: account.id,
|
||||||
date: monthUtils.subDays(monthUtils.currentDay(), (i * 2) | 0),
|
date: monthUtils.subDays(monthUtils.currentDay(), i * 2),
|
||||||
category: category.id
|
category: category.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -334,7 +334,7 @@ async function fillSavings(handlers, account, payees, groups) {
|
||||||
amount,
|
amount,
|
||||||
payee: payee.id,
|
payee: payee.id,
|
||||||
account: account.id,
|
account: account.id,
|
||||||
date: monthUtils.subDays(monthUtils.currentDay(), (i * 5) | 0),
|
date: monthUtils.subDays(monthUtils.currentDay(), i * 5),
|
||||||
category: category.id
|
category: category.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ export function generateAccount(name, isConnected, type, offbudget) {
|
||||||
return {
|
return {
|
||||||
id: uuid.v4Sync(),
|
id: uuid.v4Sync(),
|
||||||
name,
|
name,
|
||||||
balance_current: isConnected ? (Math.random() * 100000) | 0 : null,
|
balance_current: isConnected ? Math.floor(Math.random() * 100000) : null,
|
||||||
bank: isConnected ? (Math.random() * 10000) | 0 : null,
|
bank: isConnected ? Math.floor(Math.random() * 10000) : null,
|
||||||
bankId: isConnected ? (Math.random() * 10000) | 0 : null,
|
bankId: isConnected ? Math.floor(Math.random() * 10000) : null,
|
||||||
bankName: isConnected ? 'boa' : null,
|
bankName: isConnected ? 'boa' : null,
|
||||||
type: type || 'checking',
|
type: type || 'checking',
|
||||||
offbudget: offbudget ? 1 : 0,
|
offbudget: offbudget ? 1 : 0,
|
||||||
|
@ -54,7 +54,7 @@ function _generateTransaction(data) {
|
||||||
const id = data.id || uuid.v4Sync();
|
const id = data.id || uuid.v4Sync();
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
amount: data.amount || (Math.random() * 10000 - 7000) | 0,
|
amount: data.amount || Math.floor(Math.random() * 10000 - 7000),
|
||||||
payee: data.payee || (Math.random() < 0.9 ? 'payed-to' : 'guy'),
|
payee: data.payee || (Math.random() < 0.9 ? 'payed-to' : 'guy'),
|
||||||
notes:
|
notes:
|
||||||
Math.random() < 0.1 ? 'A really long note that should overflow' : 'Notes',
|
Math.random() < 0.1 ? 'A really long note that should overflow' : 'Notes',
|
||||||
|
|
|
@ -456,7 +456,7 @@ function compileLiteral(value) {
|
||||||
} else if (typeof value === 'boolean') {
|
} else if (typeof value === 'boolean') {
|
||||||
return typed(value ? 1 : 0, 'boolean', { literal: true });
|
return typed(value ? 1 : 0, 'boolean', { literal: true });
|
||||||
} else if (typeof value === 'number') {
|
} else if (typeof value === 'number') {
|
||||||
return typed(value, (value | 0) === value ? 'integer' : 'float', {
|
return typed(value, Number.isInteger(value) ? 'integer' : 'float', {
|
||||||
literal: true
|
literal: true
|
||||||
});
|
});
|
||||||
} else if (Array.isArray(value)) {
|
} else if (Array.isArray(value)) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ export function convertInputType(value, type) {
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
case 'integer':
|
case 'integer':
|
||||||
if (typeof value === 'number' && (value | 0) === value) {
|
if (typeof value === 'number' && Number.isInteger(value)) {
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Can't convert to integer: " + JSON.stringify(value));
|
throw new Error("Can't convert to integer: " + JSON.stringify(value));
|
||||||
|
|
|
@ -91,7 +91,7 @@ function expectTransactionOrder(data, fields) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function expectPagedData(query, numTransactions, allData) {
|
async function expectPagedData(query, numTransactions, allData) {
|
||||||
let pageCount = Math.max((numTransactions / 3) | 0, 3);
|
let pageCount = Math.max(Math.floor(numTransactions / 3), 3);
|
||||||
let pagedData = [];
|
let pagedData = [];
|
||||||
let done = false;
|
let done = false;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as monthUtils from '../../shared/months';
|
import * as monthUtils from '../../shared/months';
|
||||||
|
import { safeNumber } from '../../shared/util';
|
||||||
import * as db from '../db';
|
import * as db from '../db';
|
||||||
import * as prefs from '../prefs';
|
import * as prefs from '../prefs';
|
||||||
import * as sheet from '../sheet';
|
import * as sheet from '../sheet';
|
||||||
|
@ -6,7 +7,7 @@ import { batchMessages } from '../sync';
|
||||||
|
|
||||||
async function getSheetValue(sheetName, cell) {
|
async function getSheetValue(sheetName, cell) {
|
||||||
const node = await sheet.getCell(sheetName, cell);
|
const node = await sheet.getCell(sheetName, cell);
|
||||||
return typeof node.value === 'number' ? node.value : 0;
|
return safeNumber(typeof node.value === 'number' ? node.value : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to only allow the positive movement of money back and
|
// We want to only allow the positive movement of money back and
|
||||||
|
@ -71,9 +72,7 @@ export function getBudget({ category, month }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setBudget({ category, month, amount }) {
|
export function setBudget({ category, month, amount }) {
|
||||||
if (typeof amount !== 'number') {
|
amount = safeNumber(typeof amount === 'number' ? amount : 0);
|
||||||
amount = 0;
|
|
||||||
}
|
|
||||||
const table = getBudgetTable();
|
const table = getBudgetTable();
|
||||||
|
|
||||||
let existing = db.firstSync(
|
let existing = db.firstSync(
|
||||||
|
@ -185,7 +184,7 @@ export async function set3MonthAvg({ month }) {
|
||||||
'sum-amount-' + cat.id
|
'sum-amount-' + cat.id
|
||||||
);
|
);
|
||||||
|
|
||||||
const avg = ((spent1 + spent2 + spent3) / 3) | 0;
|
const avg = Math.round((spent1 + spent2 + spent3) / 3);
|
||||||
setBudget({ category: cat.id, month, amount: -avg });
|
setBudget({ category: cat.id, month, amount: -avg });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { safeNumber } from '../../shared/util';
|
||||||
import * as sheet from '../sheet';
|
import * as sheet from '../sheet';
|
||||||
import { number, sumAmounts } from './util';
|
import { number, sumAmounts } from './util';
|
||||||
|
|
||||||
|
@ -25,14 +26,14 @@ export async function createCategory(cat, sheetName, prevSheetName) {
|
||||||
],
|
],
|
||||||
run: (budgeted, sumAmount, prevCarryover, prevLeftover) => {
|
run: (budgeted, sumAmount, prevCarryover, prevLeftover) => {
|
||||||
if (cat.is_income) {
|
if (cat.is_income) {
|
||||||
return (
|
return safeNumber(
|
||||||
number(budgeted) -
|
number(budgeted) -
|
||||||
number(sumAmount) +
|
number(sumAmount) +
|
||||||
(prevCarryover ? number(prevLeftover) : 0)
|
(prevCarryover ? number(prevLeftover) : 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return safeNumber(
|
||||||
number(budgeted) +
|
number(budgeted) +
|
||||||
number(sumAmount) +
|
number(sumAmount) +
|
||||||
(prevCarryover ? number(prevLeftover) : 0)
|
(prevCarryover ? number(prevLeftover) : 0)
|
||||||
|
@ -50,7 +51,7 @@ export async function createCategory(cat, sheetName, prevSheetName) {
|
||||||
refresh: true,
|
refresh: true,
|
||||||
run: (budgeted, sumAmount, carryover) => {
|
run: (budgeted, sumAmount, carryover) => {
|
||||||
return carryover
|
return carryover
|
||||||
? Math.max(0, number(budgeted) + number(sumAmount))
|
? Math.max(0, safeNumber(number(budgeted) + number(sumAmount)))
|
||||||
: sumAmount;
|
: sumAmount;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -109,7 +110,7 @@ export function createSummary(groups, categories, sheetName) {
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
dependencies: ['total-income', 'total-spent'],
|
dependencies: ['total-income', 'total-spent'],
|
||||||
run: (income, spent) => {
|
run: (income, spent) => {
|
||||||
return income - -spent;
|
return safeNumber(income - -spent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as monthUtils from '../../shared/months';
|
import * as monthUtils from '../../shared/months';
|
||||||
|
import { safeNumber } from '../../shared/util';
|
||||||
import * as sheet from '../sheet';
|
import * as sheet from '../sheet';
|
||||||
import { number, sumAmounts, flatten2, unflatten2 } from './util';
|
import { number, sumAmounts, flatten2, unflatten2 } from './util';
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ export function createCategory(cat, sheetName, prevSheetName) {
|
||||||
`${prevSheetName}!leftover-pos-${cat.id}`
|
`${prevSheetName}!leftover-pos-${cat.id}`
|
||||||
],
|
],
|
||||||
run: (budgeted, spent, prevCarryover, prevLeftover, prevLeftoverPos) => {
|
run: (budgeted, spent, prevCarryover, prevLeftover, prevLeftoverPos) => {
|
||||||
return (
|
return safeNumber(
|
||||||
number(budgeted) +
|
number(budgeted) +
|
||||||
number(spent) +
|
number(spent) +
|
||||||
(prevCarryover ? number(prevLeftover) : number(prevLeftoverPos))
|
(prevCarryover ? number(prevLeftover) : number(prevLeftoverPos))
|
||||||
|
@ -78,7 +79,7 @@ export function createSummary(groups, categories, prevSheetName, sheetName) {
|
||||||
sheet.get().createDynamic(sheetName, 'from-last-month', {
|
sheet.get().createDynamic(sheetName, 'from-last-month', {
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
dependencies: [`${prevSheetName}!to-budget`, `${prevSheetName}!buffered`],
|
dependencies: [`${prevSheetName}!to-budget`, `${prevSheetName}!buffered`],
|
||||||
run: (toBudget, buffered) => number(toBudget) + number(buffered)
|
run: (toBudget, buffered) => safeNumber(number(toBudget) + number(buffered))
|
||||||
});
|
});
|
||||||
|
|
||||||
// Alias the group income total to `total-income`
|
// Alias the group income total to `total-income`
|
||||||
|
@ -91,7 +92,8 @@ export function createSummary(groups, categories, prevSheetName, sheetName) {
|
||||||
sheet.get().createDynamic(sheetName, 'available-funds', {
|
sheet.get().createDynamic(sheetName, 'available-funds', {
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
dependencies: ['total-income', 'from-last-month'],
|
dependencies: ['total-income', 'from-last-month'],
|
||||||
run: (income, fromLastMonth) => number(income) + number(fromLastMonth)
|
run: (income, fromLastMonth) =>
|
||||||
|
safeNumber(number(income) + number(fromLastMonth))
|
||||||
});
|
});
|
||||||
|
|
||||||
sheet.get().createDynamic(sheetName, 'last-month-overspent', {
|
sheet.get().createDynamic(sheetName, 'last-month-overspent', {
|
||||||
|
@ -104,12 +106,14 @@ export function createSummary(groups, categories, prevSheetName, sheetName) {
|
||||||
),
|
),
|
||||||
run: (...data) => {
|
run: (...data) => {
|
||||||
data = unflatten2(data);
|
data = unflatten2(data);
|
||||||
return data.reduce((total, [leftover, carryover]) => {
|
return safeNumber(
|
||||||
|
data.reduce((total, [leftover, carryover]) => {
|
||||||
if (carryover) {
|
if (carryover) {
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
return total + Math.min(0, number(leftover));
|
return total + Math.min(0, number(leftover));
|
||||||
}, 0);
|
}, 0)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -135,7 +139,7 @@ export function createSummary(groups, categories, prevSheetName, sheetName) {
|
||||||
'buffered'
|
'buffered'
|
||||||
],
|
],
|
||||||
run: (available, lastOverspent, totalBudgeted, buffered) => {
|
run: (available, lastOverspent, totalBudgeted, buffered) => {
|
||||||
return (
|
return safeNumber(
|
||||||
number(available) +
|
number(available) +
|
||||||
number(lastOverspent) +
|
number(lastOverspent) +
|
||||||
number(totalBudgeted) -
|
number(totalBudgeted) -
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
|
import { safeNumber } from '../../shared/util';
|
||||||
import { number } from '../spreadsheet/globals';
|
import { number } from '../spreadsheet/globals';
|
||||||
|
|
||||||
export { number } from '../spreadsheet/globals';
|
export { number } from '../spreadsheet/globals';
|
||||||
|
|
||||||
export function sumAmounts(...amounts) {
|
export function sumAmounts(...amounts) {
|
||||||
return amounts.reduce((total, amount) => {
|
return safeNumber(
|
||||||
|
amounts.reduce((total, amount) => {
|
||||||
return total + number(amount);
|
return total + number(amount);
|
||||||
}, 0);
|
}, 0)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function flatten2(arr) {
|
export function flatten2(arr) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ export function keyToTimestamp(key) {
|
||||||
|
|
||||||
export function insert(trie, timestamp) {
|
export function insert(trie, timestamp) {
|
||||||
let hash = timestamp.hash();
|
let hash = timestamp.hash();
|
||||||
let key = Number((timestamp.millis() / 1000 / 60) | 0).toString(3);
|
let key = Number(Math.floor(timestamp.millis() / 1000 / 60)).toString(3);
|
||||||
|
|
||||||
trie = Object.assign({}, trie, { hash: trie.hash ^ hash });
|
trie = Object.assign({}, trie, { hash: trie.hash ^ hash });
|
||||||
return insertKey(trie, key, hash);
|
return insertKey(trie, key, hash);
|
||||||
|
|
|
@ -34,7 +34,7 @@ export function shoveSortOrders(items, targetId) {
|
||||||
} else {
|
} else {
|
||||||
if (target.sort_order - (before ? before.sort_order : 0) <= 2) {
|
if (target.sort_order - (before ? before.sort_order : 0) <= 2) {
|
||||||
let next = to;
|
let next = to;
|
||||||
let order = (items[next].sort_order | 0) + SORT_INCREMENT;
|
let order = Math.floor(items[next].sort_order) + SORT_INCREMENT;
|
||||||
while (next < items.length) {
|
while (next < items.length) {
|
||||||
// No need to update it if it's already greater than the current
|
// No need to update it if it's already greater than the current
|
||||||
// order. This can happen because there may already be large
|
// order. This can happen because there may already be large
|
||||||
|
|
|
@ -171,7 +171,7 @@ function shuffle(arr) {
|
||||||
let shuffled = new Array(src.length);
|
let shuffled = new Array(src.length);
|
||||||
let item;
|
let item;
|
||||||
while ((item = src.pop())) {
|
while ((item = src.pop())) {
|
||||||
let idx = (Math.random() * shuffled.length) | 0;
|
let idx = Math.floor(Math.random() * shuffled.length);
|
||||||
if (shuffled[idx]) {
|
if (shuffled[idx]) {
|
||||||
src.push(item);
|
src.push(item);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -199,5 +199,5 @@ export function makeValue(value, cond) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getApproxNumberThreshold(number) {
|
export function getApproxNumberThreshold(number) {
|
||||||
return (Math.abs(number) * 0.075) | 0;
|
return Math.round(Math.abs(number) * 0.075);
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,7 @@ export function extractScheduleConds(conditions) {
|
||||||
|
|
||||||
export function getScheduledAmount(amount) {
|
export function getScheduledAmount(amount) {
|
||||||
if (amount && typeof amount !== 'number') {
|
if (amount && typeof amount !== 'number') {
|
||||||
return ((amount.num1 + amount.num2) / 2) | 0;
|
return Math.round((amount.num1 + amount.num2) / 2);
|
||||||
}
|
}
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,6 +298,30 @@ export function getNumberFormat() {
|
||||||
|
|
||||||
setNumberFormat('comma-dot');
|
setNumberFormat('comma-dot');
|
||||||
|
|
||||||
|
// Number utilities
|
||||||
|
|
||||||
|
// We dont use `Number.MAX_SAFE_NUMBER` and such here because those
|
||||||
|
// numbers are so large that it's not safe to convert them to floats
|
||||||
|
// (i.e. N / 100). For example, `9007199254740987 / 100 ===
|
||||||
|
// 90071992547409.88`. While the internal arithemetic would be correct
|
||||||
|
// because we always do that on numbers, the app would potentially
|
||||||
|
// display wrong numbers. Instead of `2**53` we use `2**51` which
|
||||||
|
// gives division more room to be correct
|
||||||
|
const MAX_SAFE_NUMBER = 2 ** 51 - 1;
|
||||||
|
const MIN_SAFE_NUMBER = -MAX_SAFE_NUMBER;
|
||||||
|
|
||||||
|
export function safeNumber(value) {
|
||||||
|
if (!Number.isInteger(value)) {
|
||||||
|
throw new Error('safeNumber: number is not an integer: ' + value);
|
||||||
|
}
|
||||||
|
if (value > MAX_SAFE_NUMBER || value < MIN_SAFE_NUMBER) {
|
||||||
|
throw new Error(
|
||||||
|
"safeNumber: can't safely perform arithmetic with number: " + value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
export function toRelaxedNumber(value) {
|
export function toRelaxedNumber(value) {
|
||||||
return integerToAmount(currencyToInteger(value) || 0);
|
return integerToAmount(currencyToInteger(value) || 0);
|
||||||
}
|
}
|
||||||
|
@ -307,8 +331,7 @@ export function toRelaxedInteger(value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integerToCurrency(n) {
|
export function integerToCurrency(n) {
|
||||||
// Awesome
|
return numberFormat.formatter.format(safeNumber(n) / 100);
|
||||||
return numberFormat.formatter.format(n / 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function amountToCurrency(n) {
|
export function amountToCurrency(n) {
|
||||||
|
@ -340,7 +363,7 @@ export function amountToInteger(n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function integerToAmount(n) {
|
export function integerToAmount(n) {
|
||||||
return parseFloat((n / 100).toFixed(2));
|
return parseFloat((safeNumber(n) / 100).toFixed(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used when the input format could be anything (from
|
// This is used when the input format could be anything (from
|
||||||
|
|
|
@ -7,7 +7,7 @@ let groups = ['y', 'r', 'b', 'n', 'g', 'p'];
|
||||||
let colors = {};
|
let colors = {};
|
||||||
|
|
||||||
list.forEach((color, idx) => {
|
list.forEach((color, idx) => {
|
||||||
const group = (idx / 11) | 0;
|
const group = Math.floor(idx / 11);
|
||||||
const n = idx % 11;
|
const n = idx % 11;
|
||||||
|
|
||||||
colors[groups[group] + (n + 1)] = color;
|
colors[groups[group] + (n + 1)] = color;
|
||||||
|
|
|
@ -24,11 +24,11 @@ global.Date.now = () => 123456789;
|
||||||
|
|
||||||
let seqId = 1;
|
let seqId = 1;
|
||||||
uuid.v4 = function() {
|
uuid.v4 = function() {
|
||||||
return Promise.resolve('testing-uuid-' + ((Math.random() * 1000000) | 0));
|
return Promise.resolve('testing-uuid-' + Math.floor(Math.random() * 1000000));
|
||||||
};
|
};
|
||||||
|
|
||||||
uuid.v4Sync = function() {
|
uuid.v4Sync = function() {
|
||||||
return 'testing-uuid-' + ((Math.random() * 1000000) | 0);
|
return 'testing-uuid-' + Math.floor(Math.random() * 1000000);
|
||||||
};
|
};
|
||||||
|
|
||||||
global.__resetWorld = () => {
|
global.__resetWorld = () => {
|
||||||
|
|
Loading…
Reference in a new issue