Commit e8722a53 authored by Martin Hailant's avatar Martin Hailant

Fist commit

parents
Pipeline #46 failed with stages
in 9 seconds
./node_modules
.idea
module.exports = {
default: `--format-options '{"snippetInterface": "synchronous"}' '--publish-quiet'`
}
module.exports = formatter = (aNumber, aCurrencyType) => {
const dispatch = {
"ars": new ArsFormater(aNumber),
"usd": new UsdFormater(aNumber),
};
if (undefined === dispatch[aCurrencyType])
throw Error(`unknow currency type ${aCurrencyType}`);
return dispatch[aCurrencyType];
}
class CurrencyFormater {
constructor(aNumber) {
this.number = aNumber;
}
get format() {
throw new Error('currency not admitted')
}
}
class ArsFormater extends CurrencyFormater {
get format() {
return new Intl.NumberFormat('es-AR', {
style: 'currency',
currency: 'ARS',
minimumFractionDigits: 2
}).format(this.number / 100);
}
}
class UsdFormater extends CurrencyFormater {
get format() {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2
}).format(this.number / 100);
}
}
# language: es
Característica: Imprimir la factura de una compañía teatral
Necesaria para liquidar el borderau
Escenario: imprimr la factura de BigCo en texto plano y moneda USD
Dado el listado de la facturación de espectáculos
"""
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "as-like",
"audience": 35
},
{
"playID": "othello",
"audience": 40
}
]
}
"""
Y la lista de obras
"""
{
"hamlet": {
"name": "Hamlet",
"type": "tragedy"
},
"as-like": {
"name": "As You Like It",
"type": "comedy"
},
"othello": {
"name": "Othello",
"type": "tragedy"
}
}
"""
Cuando mando a imprimir el borderau en TextoPlano y USD
Entonces debería imprimir el borderau en TextoPlano y USD
"""
Statement for BigCo
Hamlet: $650.00 (55 seats)
As You Like It: $580.00 (35 seats)
Othello: $500.00 (40 seats)
Amount owed is $1,730.00
You earned 47 credits
"""
Escenario: imprimr la factura de BigCo en TextoPlano y ARS
Dado el listado de la facturación de espectáculos
"""
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "as-like",
"audience": 35
},
{
"playID": "othello",
"audience": 40
}
]
}
"""
Y la lista de obras
"""
{
"hamlet": {
"name": "Hamlet",
"type": "tragedy"
},
"as-like": {
"name": "As You Like It",
"type": "comedy"
},
"othello": {
"name": "Othello",
"type": "tragedy"
}
}
"""
Cuando mando a imprimir el borderau en TextoPlano y ARS
Entonces debería imprimir el borderau en TextoPlano y ARS
"""
Statement for BigCo
Hamlet: $ 650,00 (55 seats)
As You Like It: $ 580,00 (35 seats)
Othello: $ 500,00 (40 seats)
Amount owed is $ 1730,00
You earned 47 credits
"""
Escenario: imprimr la factura de BigCo en HTML y USD
Dado el listado de la facturación de espectáculos
"""
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "as-like",
"audience": 35
},
{
"playID": "othello",
"audience": 40
}
]
}
"""
Y la lista de obras
"""
{
"hamlet": {
"name": "Hamlet",
"type": "tragedy"
},
"as-like": {
"name": "As You Like It",
"type": "comedy"
},
"othello": {
"name": "Othello",
"type": "tragedy"
}
}
"""
Cuando mando a imprimir el borderau en HTML en HTML y USD
Entonces debería imprimir el borderau en HTML y USD
"""
<h1>Statement for BigCo</h1>
<table>
<tr><th>play</th><th>seats</th><th>cost</th></tr>
<tr><td>Hamlet</td><td>55</td><td>$650.00</td></tr>
<tr><td>As You Like It</td><td>35</td><td>$580.00</td></tr>
<tr><td>Othello</td><td>40</td><td>$500.00</td></tr>
</table>
<p>Amount owed is <em>$1,730.00</em></p>
<p>You earned <em>47</em> credits</p>
"""
Escenario: imprimr la factura de BigCo en HTML y ARS
Dado el listado de la facturación de espectáculos
"""
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "as-like",
"audience": 35
},
{
"playID": "othello",
"audience": 40
}
]
}
"""
Y la lista de obras
"""
{
"hamlet": {
"name": "Hamlet",
"type": "tragedy"
},
"as-like": {
"name": "As You Like It",
"type": "comedy"
},
"othello": {
"name": "Othello",
"type": "tragedy"
}
}
"""
Cuando mando a imprimir el borderau en HTML en HTML y ARS
Entonces debería imprimir el borderau en HTML y ARS
"""
<h1>Statement for BigCo</h1>
<table>
<tr><th>play</th><th>seats</th><th>cost</th></tr>
<tr><td>Hamlet</td><td>55</td><td>$ 650,00</td></tr>
<tr><td>As You Like It</td><td>35</td><td>$ 580,00</td></tr>
<tr><td>Othello</td><td>40</td><td>$ 500,00</td></tr>
</table>
<p>Amount owed is <em>$ 1730,00</em></p>
<p>You earned <em>47</em> credits</p>
"""
const assert = require("assert");
const { Given, When, Then } = require("@cucumber/cucumber");
const print_the_bill = require('../../statement');
Given("el listado de la facturación de espectáculos", function (espectaculos) {
this.invoice = JSON.parse(espectaculos);
});
Given("la lista de obras", function (obras) {
this.play = JSON.parse(obras);
});
When('mando a imprimir el borderau en TextoPlano y USD', function () {
this.actualAnswer = print_the_bill.statement(this.invoice, this.play, 'usd', 'text').render;
});
Then('debería imprimir el borderau en TextoPlano y USD', function (expectedAnswer) {
assert.strictEqual(this.actualAnswer.trim(), expectedAnswer.trim());
});
When('mando a imprimir el borderau en TextoPlano y ARS', function () {
this.actualAnswer = print_the_bill.statement(this.invoice, this.play, 'ars', 'text').render;
});
Then('debería imprimir el borderau en TextoPlano y ARS', function (expectedAnswer) {
assert.strictEqual(this.actualAnswer.trim(), expectedAnswer.trim());
});
When('mando a imprimir el borderau en HTML en HTML y USD', function () {
this.actualAnswer = print_the_bill.statement(this.invoice, this.play, 'usd', 'html').render;
});
Then('debería imprimir el borderau en HTML y USD', function (expectedAnswer) {
assert.strictEqual(this.actualAnswer.trim(), expectedAnswer.trim());
});
When('mando a imprimir el borderau en HTML en HTML y ARS', function () {
this.actualAnswer = print_the_bill.statement(this.invoice, this.play, 'ars', 'html').render;
});
Then('debería imprimir el borderau en HTML y ARS', function (expectedAnswer) {
assert.strictEqual(this.actualAnswer.trim(), expectedAnswer.trim());
});
[
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "as-like",
"audience": 35
},
{
"playID": "othello",
"audience": 40
}
]
}
]
\ No newline at end of file
const fs = require('fs');
const dataPlays = fs.readFileSync('plays.json', 'utf8');
const plays = JSON.parse(dataPlays);
const dataInvoices = fs.readFileSync('invoices.json', 'utf8');
const invoices = JSON.parse(dataInvoices);
const print_the_bill = require('./statement')
for (let invoice of invoices) {
console.log('Text USD:')
console.log(print_the_bill.statement(invoice, plays, 'usd', 'text').render)
console.log('Html USD:')
console.log(print_the_bill.statement(invoice, plays, 'usd', 'html').render)
console.log('Text ARS:')
console.log(print_the_bill.statement(invoice, plays, 'ars', 'text').render)
console.log('Html ARS:')
console.log(print_the_bill.statement(invoice, plays, 'ars', 'html').render)
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "taller-bdd",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "cucumber-js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@cucumber/cucumber": "^7.0.0"
}
}
{
"hamlet": {
"name": "Hamlet",
"type": "tragedy"
},
"as-like": {
"name": "As You Like It",
"type": "comedy"
},
"othello": {
"name": "Othello",
"type": "tragedy"
}
}
\ No newline at end of file
module.exports = {statement}
function statement(invoice, plays) {
const statementData = {}
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount(statementData.performances);
statementData.totalVolumeCredits = totalVolumeCredits(statementData.performances);
return renderPlainText(statementData);
function enrichPerformance(aPerformance) {
const result = Object.assign({}, aPerformance);
result.name = playFor(result).name;
result.type = playFor(result).type;
result.amount = amountFor(result);
result.volumeCredits = volumeCreditsFor(result);
return result;
}
function amountFor(aPerformance) {
let thisAmount = 0
switch (aPerformance.type) {
case "tragedy":
thisAmount = 40000;
if (aPerformance.audience > 30) {
thisAmount += 1000 * (aPerformance.audience - 30);
}
break;
case "comedy":
thisAmount = 30000;
if (aPerformance.audience > 20) {
thisAmount += 10000 + 500 * (aPerformance.audience - 20);
}
thisAmount += 300 * aPerformance.audience;
break;
default:
throw new Error(`unknown type: ${aPerformance.type}`);
}
return thisAmount
}
function playFor(aPerformance) {
return plays[aPerformance.playID];
}
function volumeCreditsFor(aPerformance){
let volumeCredits = 0;
volumeCredits += Math.max(aPerformance.audience - 30, 0);
if ("comedy" === aPerformance.type) volumeCredits += Math.floor(aPerformance.audience / 5);
return volumeCredits;
}
function totalVolumeCredits(somePerformaces) {
let totalVolumeCredits = 0
for (let perf of somePerformaces) {
totalVolumeCredits += perf.volumeCredits;
}
return totalVolumeCredits
}
function totalAmount(somePerformances) {
let totalAmount = 0
for (let perf of somePerformances) {
totalAmount += perf.amount;
}
return totalAmount
}
}
function usd(aNumber) {
return new Intl.NumberFormat("en-US",
{
style: "currency", currency: "USD",
minimumFractionDigits: 2
}).format(aNumber / 100);
}
function renderPlainText(statementData){
let result = `Statement for ${statementData.customer}\n`;
for (let perf of statementData.performances) {
result += ` ${perf.name}: ${usd(perf.amount)} (${perf.audience} seats)\n`;
}
result += `Amount owed is ${usd(statementData.totalAmount)}\n`;
result += `You earned ${statementData.totalVolumeCredits} credits\n`;
return result;
}
const statementData = require('./statementData')
const formatter = require('./currencyFormater')
function statement(invoice, plays, aCurrency, renderType) {
const dispatch = {
'text': new TextStatement(statementData.createStatementData(invoice, plays), aCurrency),
'html': new HtmlStatement(statementData.createStatementData(invoice, plays), aCurrency)
}
if (undefined === dispatch[renderType])
throw Error(`unknow render type ${renderType}`)
return dispatch[renderType]
}
class Statement {
constructor(aStatementData, aCurrencyType) {
this.data = aStatementData;
this.currency = aCurrencyType
}
get render() {
}
}
class HtmlStatement extends Statement {
get render() {
let result = `<h1>Statement for ${this.data.customer}</h1>\n`;
result += "<table>\n";
result += "<tr><th>play</th><th>seats</th><th>cost</th></tr>\n";
for (let perf of this.data.performances) {
result += `<tr><td>${perf.play.name}</td><td>${perf.audience}</td>`;
result += `<td>${formatter(perf.amount, this.currency).format}</td></tr>\n`;
}
result += "</table>\n";
result += `<p>Amount owed is <em>${formatter(this.data.totalAmount, this.currency).format}</em></p>\n`;
result += `<p>You earned <em>${this.data.totalVolumeCredits}</em> credits</p>\n`;
return result;
}
}
class TextStatement extends Statement {
get render() {
let result = `Statement for ${this.data.customer}\n`;
for (let aPerformance of this.data.performances) {
result += ` ${aPerformance.play.name}: ${formatter(aPerformance.amount, this.currency).format} (${aPerformance.audience} seats)\n`;
}
result += `Amount owed is ${formatter(this.data.totalAmount, this.currency).format}\n`;
result += `You earned ${this.data.totalVolumeCredits} credits\n`;
return result;
}
}
module.exports = {statement}
function createStatementData(invoice, plays) {
const statementData = {}
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount(statementData.performances);
statementData.totalVolumeCredits = totalVolumeCredits(statementData.performances);
return statementData;
function enrichPerformance(aPerformance) {
let calculator = performanceCalculatorFactory(aPerformance, playFor(aPerformance))
const result = Object.assign({}, aPerformance);
result.play = calculator.play
result.amount = calculator.amount
result.volumeCredits = calculator.volumeCredit
return result;
}
function playFor(aPerformance) {
return plays[aPerformance.playID];
}
function totalVolumeCredits(somePerformaces) {
return somePerformaces.reduce((total, aPerformance) => total + aPerformance.volumeCredits, 0)
}
function totalAmount(somePerformances) {
return somePerformances.reduce((total, aPerformance) => total + aPerformance.amount, 0)
}
}
const performanceCalculatorFactory = (aPerformance, aPlay) => {
const dispatch = {
'tragedy': new TragedyCalculator(aPerformance, aPlay),
'comedy': new ComedyCalculator(aPerformance, aPlay)
}
if (undefined === dispatch[aPlay.type])
throw Error(`unknown type: ${aPlay.type} not exist`)
return dispatch[aPlay.type]
}
class PerformanceCalculator {
constructor(aPerformance, aPlay) {
this.performance = aPerformance
this.play = aPlay
}
get amount() {
throw new Error('Subclass responsibility')
}
get volumeCredit() {
throw new Error('Subclass responsibility')
}
}
class TragedyCalculator extends PerformanceCalculator {
get amount() {
let thisAmount = 40000;
if (this.performance.audience > 30) {
thisAmount += 1000 * (this.performance.audience - 30);
}
return thisAmount
}
get volumeCredit() {
return volumeCreditComposer(this.performance.audience)
}
}
class ComedyCalculator extends PerformanceCalculator {
get amount() {
let thisAmount = 30000;
if (this.performance.audience > 20) {
thisAmount += 10000 + 500 * (this.performance.audience - 20);
}
thisAmount += 300 * this.performance.audience;
return thisAmount
}
get volumeCredit() {
return volumeCreditComposer(this.performance.audience) + Math.floor(this.performance.audience / 5);
}
}
function volumeCreditComposer(aAudience) {
return Math.max(aAudience - 30, 0)
}
module.exports = {createStatementData}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment