Skip to content

Commit

Permalink
Adding scaffolding, tests and solution
Browse files Browse the repository at this point in the history
  • Loading branch information
Cool-Katt committed Feb 9, 2024
1 parent 45ea797 commit 9d431b5
Show file tree
Hide file tree
Showing 4 changed files with 377 additions and 3 deletions.
11 changes: 8 additions & 3 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2582,9 +2582,14 @@
"slug": "ledger",
"name": "Ledger",
"uuid": "8716b347-e18f-48a6-b373-426cc4ca98cb",
"practices": [],
"prerequisites": [],
"difficulty": 1
"practices": [
"strings",
"string-formatting"
],
"prerequisites": [
"string-formatting"
],
"difficulty": 4
}
]
},
Expand Down
67 changes: 67 additions & 0 deletions exercises/practice/ledger/.meta/proof.ci.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
class LedgerEntry {
constructor(date, description, change) {
this.date = new Date(date);
this.description = description;
this.change = change;
}
}

const headerRow = (locale) =>
locale === 'en-US'
? `${`Date`.padEnd(10, ` `)} | ${`Description`.padEnd(
25,
` `,
)} | ${`Change`.padEnd(13, ` `)}`
: `${`Datum`.padEnd(10, ` `)} | ${`Omschrijving`.padEnd(
25,
` `,
)} | ${`Verandering`.padEnd(13, ` `)}`;

export const createEntry = (date, description, change) =>
new LedgerEntry(date, description, change);

export function formatEntries(currency, locale, entries) {
// Generate Header Row
let table = headerRow(locale);
// Set Formatting Options
let formattingOptions = {
style: 'currency',
currency: currency,
currencySign: locale === 'en-US' ? 'accounting' : 'standard',
currencyDisplay: locale === 'en-US' ? 'symbol' : 'narrowSymbol',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
};
// Sort Entries
entries.sort(
(a, b) =>
a.date - b.date ||
a.change - b.change ||
a.description.localeCompare(b.description),
);
// Writing each entry to table
entries.forEach((entry) => {
table += '\n';
// Write entry date to table
table += `${entry.date.toLocaleDateString(locale, {
day: '2-digit',
month: '2-digit',
year: 'numeric',
})} | `;
// Write entry description to table
let truncatedDescription =
entry.description.length > 25
? `${entry.description.substring(0, 22)}...`
: entry.description.padEnd(25, ' ');
table += `${truncatedDescription} | `;
// Write entry change to table
let changeStr = (entry.change / 100).toLocaleString(
locale,
formattingOptions,
);
let trailingSpace = changeStr.includes(')') ? '' : ' ';
table += `${changeStr}${trailingSpace}`.padStart(13, ' ');
});

return table;
}
163 changes: 163 additions & 0 deletions exercises/practice/ledger/ledger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
class LedgerEntry {
constructor() {
this.date = undefined;
this.description = undefined;
this.change = undefined;
}
}

export function createEntry(date, description, change) {
let entry = new LedgerEntry();
entry.date = new Date(date);
entry.description = description;
entry.change = change;
return entry;
}

export function formatEntries(currency, locale, entries) {
let table = '';
if (locale === 'en-US') {
// Generate Header Row
table +=
'Date'.padEnd(10, ' ') +
' | ' +
'Description'.padEnd(25, ' ') +
' | ' +
'Change'.padEnd(13, ' ') +
'\n';

// Sort entries
entries.sort(
(a, b) =>
a.date - b.date ||
a.change - b.change ||
a.description.localeCompare(b.description),
);

entries.forEach((entry) => {
// Write entry date to table
const dateStr = `${(entry.date.getMonth() + 1)
.toString()
.padStart(2, '0')}/${entry.date
.getDate()
.toString()
.padStart(2, '0')}/${entry.date.getFullYear()}`;
table += `${dateStr} | `;

// Write entry description to table
const truncatedDescription =
entry.description.length > 25
? `${entry.description.substring(0, 22)}...`
: entry.description.padEnd(25, ' ');
table += `${truncatedDescription} | `;

// Write entry change to table
let changeStr = '';
if (currency === 'USD') {
let formatingOptions = {
style: 'currency',
currency: 'USD',
//currencySign: 'accounting',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
};
if (entry.change < 0) {
changeStr = `(${Math.abs(entry.change / 100).toLocaleString(
'en-US',
formatingOptions,
)})`;
} else {
changeStr = `${(entry.change / 100).toLocaleString(
'en-US',
formatingOptions,
)} `;
}
} else if (currency === 'EUR') {
let formatingOptions = {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
};
if (entry.change < 0) {
changeStr = `(${Math.abs(entry.change / 100).toLocaleString(
'en-US',
formatingOptions,
)})`;
} else {
changeStr = `${(entry.change / 100).toLocaleString(
'en-US',
formatingOptions,
)} `;
}
}
table += changeStr.padStart(13, ' ');
table += '\n';
});
} else if (locale === 'nl-NL') {
// Generate Header Row
table +=
'Datum'.padEnd(10, ' ') +
' | ' +
'Omschrijving'.padEnd(25, ' ') +
' | ' +
'Verandering'.padEnd(13, ' ') +
'\n';

// Sort entries
entries.sort(
(a, b) =>
a.date - b.date ||
a.change - b.change ||
a.description.localeCompare(b.description),
);

entries.forEach((entry) => {
// Write entry date to table
const dateStr = `${entry.date.getDate().toString().padStart(2, '0')}-${(
entry.date.getMonth() + 1
)
.toString()
.padStart(2, '0')}-${entry.date.getFullYear()}`;
table += `${dateStr} | `;

// Write entry description to table
const truncatedDescription =
entry.description.length > 25
? `${entry.description.substring(0, 22)}...`
: entry.description.padEnd(25, ' ');
table += `${truncatedDescription} | `;

// Write entry change to table
let changeStr = '';
if (currency === 'USD') {
let formatingOptions = {
style: 'currency',
currency: 'USD',
currencyDisplay: 'narrowSymbol',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
};
changeStr = `${(entry.change / 100).toLocaleString(
'nl-NL',
formatingOptions,
)} `;
} else if (currency === 'EUR') {
let formatingOptions = {
style: 'currency',
currency: 'EUR',
currencyDisplay: 'narrowSymbol',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
};
changeStr = `${(entry.change / 100).toLocaleString(
'nl-NL',
formatingOptions,
)} `;
}
table += changeStr.padStart(13, ' ');
table += '\n';
});
}
return table.replace(/\n$/, '');
}
139 changes: 139 additions & 0 deletions exercises/practice/ledger/ledger.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { createEntry, formatEntries } from './ledger';

describe('Ledger', () => {
test('empty ledger', () => {
let currency = 'USD';
let locale = 'en-US';
let entries = [];
let expected = [
'Date | Description | Change ',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('one entry', () => {
let currency = 'USD';
let locale = 'en-US';
let entries = [createEntry('2015-01-01', 'Buy present', -1000)];
let expected = [
'Date | Description | Change ',
'01/01/2015 | Buy present | ($10.00)',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('credit and debit', () => {
let currency = 'USD';
let locale = 'en-US';
let entries = [
createEntry('2015-01-02', 'Get present', 1000),
createEntry('2015-01-01', 'Buy present', -1000),
];
let expected = [
'Date | Description | Change ',
'01/01/2015 | Buy present | ($10.00)',
'01/02/2015 | Get present | $10.00 ',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('final order tie breaker is change', () => {
let currency = 'USD';
let locale = 'en-US';
let entries = [
createEntry('2015-01-01', 'Something', 0),
createEntry('2015-01-01', 'Something', -1),
createEntry('2015-01-01', 'Something', 1),
];
let expected = [
'Date | Description | Change ',
'01/01/2015 | Something | ($0.01)',
'01/01/2015 | Something | $0.00 ',
'01/01/2015 | Something | $0.01 ',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('overlong description is truncated', () => {
let currency = 'USD';
let locale = 'en-US';
let entries = [
createEntry('2015-01-01', 'Freude schoner Gotterfunken', -123456),
];
let expected = [
'Date | Description | Change ',
'01/01/2015 | Freude schoner Gotterf... | ($1,234.56)',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('euros', () => {
let currency = 'EUR';
let locale = 'en-US';
let entries = [createEntry('2015-01-01', 'Buy present', -1000)];
let expected = [
'Date | Description | Change ',
'01/01/2015 | Buy present | (€10.00)',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('Dutch locale', () => {
let currency = 'USD';
let locale = 'nl-NL';
let entries = [createEntry('2015-03-12', 'Buy present', 123456)];
let expected = [
'Datum | Omschrijving | Verandering ',
'12-03-2015 | Buy present | $ 1.234,56 ',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('Dutch locale and euros', () => {
let currency = 'EUR';
let locale = 'nl-NL';
let entries = [createEntry('2015-03-12', 'Buy present', 123456)];
let expected = [
'Datum | Omschrijving | Verandering ',
'12-03-2015 | Buy present | € 1.234,56 ',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('Dutch negative number with 3 digits before decimal point', () => {
let currency = 'USD';
let locale = 'nl-NL';
let entries = [createEntry('2015-03-12', 'Buy present', -12345)];
let expected = [
'Datum | Omschrijving | Verandering ',
'12-03-2015 | Buy present | $ -123,45 ',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('American negative number with 3 digits before decimal point', () => {
let currency = 'USD';
let locale = 'en-US';
let entries = [createEntry('2015-03-12', 'Buy present', -12345)];
let expected = [
'Date | Description | Change ',
'03/12/2015 | Buy present | ($123.45)',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});

xtest('multiple entries on same date ordered by description', () => {
let currency = 'USD';
let locale = 'en-US';
let entries = [
createEntry('2015-01-01', 'Get present', 1000),
createEntry('2015-01-01', 'Buy present', -1000),
];
let expected = [
'Date | Description | Change ',
'01/01/2015 | Buy present | ($10.00)',
'01/01/2015 | Get present | $10.00 ',
].join('\n');
expect(formatEntries(currency, locale, entries)).toEqual(expected);
});
});

0 comments on commit 9d431b5

Please sign in to comment.