Skip to content
Permalink
Browse files
added extra labs
  • Loading branch information
aa7401 committed Jul 18, 2019
1 parent 905eb3c commit 01885aa96b6b301b5ccdb24dfaea6ca774f28b5f
Show file tree
Hide file tree
Showing 37 changed files with 2,119 additions and 0 deletions.
@@ -0,0 +1,4 @@

# Currency Converter

This package converts from one currency to another using the current exchange rates.
@@ -0,0 +1,53 @@

'use strict'

const request = require('request')
const decimalPlaces = 2

exports.convert = (base, symbol, units, callback) => {
try {
checkValidCurrencyCode(base, err => {
if (err) callback(err)
checkValidCurrencyCode(symbol, err => {
if (err) callback(err)
base = base.trim()
symbol = symbol.trim()
getData(`http://api.fixer.io/latest?base=${base}&symbols=${symbol}`, (err, data) => {
if (err) callback(err)
const obj = JSON.parse(data)
//printObject(obj)
const result = parseFloat((obj.rates[symbol] * units).toFixed(decimalPlaces))
//console.log(result)
callback(null, result)
})
})
})
} catch(err) {
console.log(err.message)
}
}

function checkValidCurrencyCode(code, callback) {
console.log(`currency: ${JSON.stringify(code)}`)
code = code.trim()
request('http://api.fixer.io/latest', (err, res, body) => {
if (err) callback(new Error('invalid API call'))
const rates = JSON.parse(body).rates
if (!rates.hasOwnProperty(code)) callback(new Error(`invalid currency code ${code}`))
callback(null, true)
})
}

function getData(url, callback) {
request(url, (err, res, body) => {
if (err) callback(new Error('invalid API call'))
callback(null, body)
})
}

function printObject(data) {
const indent = 2
const str = JSON.stringify(data, null, indent)
console.log(str)
}

@@ -0,0 +1,12 @@
{
"name": "currency",
"version": "0.0.3",
"private": true,
"dependencies": {
"request": "^2.81.0"
},
"devDependencies": {
"jasmine": "^2.5.3",
"jasmine-console-reporter": "^1.2.7"
}
}
@@ -0,0 +1,36 @@

'use strict'

// need to allow the use of arbitrary numbers when testing
/* eslint no-magic-numbers: 0 */

const currency = require('../index.js')

describe('currency module', () => {
it('should return a number', done => {
currency.convert('GBP', 'USD', 100, (err, data) => {
try {
if(err) throw err // throw errors to the catch block
expect(data).toEqual(jasmine.any(Number))
expect(data).toBeGreaterThan(0)
done()
} catch(err) {
expect(true).toBe(false) // no error should be thrown
}
})
})

it('should return a value with 2 decimal places', done => {
currency.convert('GBP', 'USD', 111, (err, data) => {
try {
if(err) throw err // throw errors to the catch block
expect(data).toEqual(jasmine.any(Number))
expect(data).toBeGreaterThan(0)
expect(data).toEqual(parseFloat(data.toFixed(2)))
done()
} catch(err) {
expect(true).toBe(false) // no error should be thrown
}
})
})
})
@@ -0,0 +1,9 @@

{
"spec_files": [
"spec/currency-spec.js"
],
"helpers": [
"helpers/**/*.js"
]
}
@@ -0,0 +1,20 @@

'use strict'

const Jasmine = require('jasmine')
const jasmine = new Jasmine()

jasmine.loadConfigFile('spec/jasmine.json')

const JasmineConsoleReporter = require('jasmine-console-reporter')
const reporter = new JasmineConsoleReporter({
colors: true,
cleanStack: true,
verbosity: 4,
listStyle: 'indent',
activity: true
})

jasmine.addReporter(reporter)

jasmine.execute()
@@ -0,0 +1,37 @@

'use strict'

const currency = require('currency')

try {
getInput('enter base currency', (err, data) => {
if (err) throw err
const base = data
getInput('enter currency required', (err, data) => {
if (err) throw err
const symbol = data
getInput('enter amount to convert', (err, data) => {
if (err) throw err
const units = data
currency.convert(base, symbol, units, (err, data) => {
if (err) throw err
console.log(`${data} ${symbol}`)
})
})
})
})
} catch(err) {
console.log(err.message)
}


function getInput(prompt, callback) {
try {
process.stdin.resume()
process.stdin.setEncoding('utf8')
process.stdout.write(`${prompt}: `)
process.stdin.on('data', text => callback(null, text.trim()))
} catch(err) {
callback(err)
}
}
@@ -0,0 +1,14 @@
{
"name": "currency-test",
"version": "1.0.0",
"description": "test for the local currency package",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Mark J Tyers",
"license": "ISC",
"dependencies": {
"currency": "file:///Users/marktyers/Documents/304CEM/06 Writing Robust Code/currency"
}
}
@@ -0,0 +1,25 @@

'use strict'

const list = require('./modules/shopping')
debugger
list.add('bread')
list.add('butter')
debugger
list.add('cheese')
list.add('bread')
list.add('bread')
list.add('butter')
debugger
try {
list.decrement('bread', 2)
list.decrement('butter', 4)
list.decrement('jam', 3)
} catch(err) {
console.log('ERROR: '+err.message)
}

const items = list.getAll()
items.forEach( (element, index) => {
console.log(index+'. '+element.title+'\t x'+element.qty)
})
@@ -0,0 +1,27 @@
"use strict"

const readline = require("readline-sync");

const list = require('./modules/shopping');

do
{
var input = String(readline.question("enter command: ")).trim()
if (input.indexOf('add ') == 0) {
let space = input.indexOf(' ');
let item = input.substring(space).trim();
/* Let's echo the item details back to the user before adding it. Notice the use of Template Literals (https://goo.gl/Yjxa5o), a part of ECMA6. This allows you to include placeholders for variables without the need for concatenation. The string must be enclosed by backticks (`) */
console.log(`adding "${item}"`)
list.add(item)
}
if (input.indexOf("list") == 0) {
const items = list.getAll()
let i = 1
for (var value of items) {
/* process.stdout.write prints to the terminal without adding a newline character at the end. the \t character inserts a tab and the \n character inserts a newline */
process.stdout.write(`${i}. ${value.title}`)
process.stdout.write(`\t${value.qty}\n`)
i++
}
}
} while (input !== "exit");
@@ -0,0 +1,93 @@
'use strict'

/**
* Shopping Module.
* @module shopping
*/

/** this global 'map' object will be used to store the items and quantities. It stores each item against a named key. */
var data = new Map();

/** add a new item to the todo list. Notice that we are using the new 'Arrow Function' syntax from the ECMA6 specification. */
exports.add = item => {
/* check if the item is already in the list */
if (data.get(item) == undefined)
{
/* if the item is not found it is added to the list with its quantity set to 1 */
data.set(item, {title: item, qty: 1})
}
else
{
/* the item is already in the list so it is retrieved and the quantity is incremented */
let i = data.get(item)
i.qty++
/* the new data is then stored in the map */
data.set(item, i)
}
return data.get(item)
}


/** calculates and returns the number of items in the list */
exports.count = () => {
/* the _Map_ object has a _size_ property that returns the number of items */
return data.size
}

/** empties the list */
exports.clear = () => {
data = new Map()
}

/** Returns an array containing all todo items */
exports.getAll = () => {
let data_array = []
for (var value of data.values()) {
data_array.push(value)
}
return data_array
}

/**
* Returns details for the named item.
* @param {string} item - The item name to retrieve.
* @returns {string} The name of the item
* @throws {InvalidItem} item not in list.
*/
exports.getItem = item => {
if (data.get(item) === undefined) {
throw new Error('item not in list')
}
return data.get(item)
}

/** Removes item with the corresponding name. */
exports.removeItem = item => {
console.log('removeItem')
if (data.get(item) === undefined) {
throw new Error('item not in list')
}
data.delete(item)
}

/** Decrements the quantity of an item in the list. */
exports.decrement = (item, count) => {
console.log(arguments)
if (item === undefined || count === undefined) {
throw new Error('function requires two parameters')
}
if (data.get(item) === undefined) {
throw new Error('item not in list')
}
if (isNaN(count)) {
throw new Error('second parameter should be a number')
}
count = parseInt(count)
let current = data.get(item)
if (current.qty <= count) {
data.delete(item)
return
}
current.qty = current.qty - count
data.set(item, current)
}
@@ -0,0 +1,30 @@
{
"name": "shopping",
"version": "1.0.0",
"description": "simple shopping list",
"main": "index.js",
"scripts": {
"app": "node index.js",
"lint": "node_modules/.bin/eslint modules/",
"test": "node_modules/.bin/jasmine-node spec --color --verbose --autotest --watch .",
"coverage": "./node_modules/.bin/istanbul cover -x **spec/** -x **index.js** -x **debug.js** ./node_modules/.bin/jasmine-node spec",
"doc": "node_modules/.bin/jsdoc modules/"
},
"keywords": [
"list",
"jasmine",
"module"
],
"author": "Mark J Tyers",
"license": "ISC",
"dependencies": {
"readline-sync": "^1.2.22"
},
"devDependencies": {
"eslint": "^3.1.0",
"istanbul": "^0.4.0",
"jasmine-node": "^1.14.5",
"jsdoc": "^3.4.0",
"node-inspector": "^0.12.8"
}
}

0 comments on commit 01885aa

Please sign in to comment.