Skip to content
Permalink
Browse files
  • Loading branch information
mateussa committed Sep 24, 2019
2 parents 59d7489 + 1c19206 commit ddfa88872aa3b2a546cfae4fae80371a2c0733db
Show file tree
Hide file tree
Showing 44 changed files with 1,451 additions and 10 deletions.
@@ -13,6 +13,37 @@ Press CTRL-SHIFT-P and a selection box should appear at the top of the editor. T

Now the integrated terminal uses the _Bash Shell_ meaning you can use the standard *nix bash commands!

# If _Bash Shell_ is _not_ listed on your Windows 10 machine

On some versions of Windows 10, some extra configuration is required before Bash Shell is able to be selected within VS Code. If this is the case on your machine, follow the below troubleshooting steps before reattempting to change your shell as above.

To start, we need to make sure Developer Mode is enabled in the Update and Security section of Windows 10. Press **WIN+R** (Windows Key and R simultaneosly) to open a Run dialog. In the dialog enter **ms-settings:developers** followed by the enter key. The window shown below should appear on screen.

![Enabling Windows 10 Developer Mode](exercises/.images/developerMode.PNG)

Select the **Developer mode** radio button and **yes** on any succeeding dialog boxes. Wait for any neccessary installations to complete.

Once that has completed, we need to enable the WSL (Windows Subsystem for Linux). Press **WIN+R**, in the dialog enter **powershell** followed by the enter key. In the powershell window copy and paste the following:

```
Start-Process powershell -Verb runAs
exit
```

Press the enter key and accept the UAC (User Account Control) dialog. A new powershell window will launch with Administrator rights.

Copy and paste the following:

```
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
```

Press the enter key and wait for the process to complete. Once complete, restart your computer before continuing.

Finally, we need to install [Ubuntu from the Microsoft Store](https://www.microsoft.com/en-gb/p/ubuntu/9nblggh4msv6?activetab=pivot:overviewtab). Click the blue **Get** button and accept any dialogs to launch the Microsoft Store and begin the installation. Once Ubuntu for WSL (Windows Subsystem for Linux) has installed, restart Windows.

Once restarted, reattempt to enable Bash Shell in VS Code as per the section above.

## 1 Forking the Foundation Materials

You should start by logging in to the University GitHub server using your university username and password. Make sure you don't log into GitHub.com!
@@ -85,7 +85,7 @@ Start the server and access the `/books/1` route. What is displayed in the web b
2. Note that it is itself a JavaScript object and that it contains a single property called `index` which matches the name of the URL segment.
3. The value of this property is the string we added to the URL.
4. This index value is used to look up the title of the book in the array, the book title is stored in a constant.
5. Finally the book title is send to the web browser.
5. Finally the book title is sent to the web browser.

#### 1.3.1 Core Knowledge

@@ -98,8 +98,9 @@ const sqr = num => num * num
1. Refactor the `remainder2` function expression to take advantage of the implicit return (you will need to reduce it to a single line of code).
2. Compare this to the original version: which is more _readable_?
3. Create a function expression that takes two string parameters and returns the longest string and assign this to a constant called `longest. check this works correctly.
4. Modify the function expression so that it can handle any number of string parameters (use a _rest parameter_).
5. Can you reduce this function expression to a single line (hint: explore using the [reduce function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) combined with the [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator))?
4. Modify the function expression so that it can handle any number of string parameters (use a _rest parameter_). (hint: you will need to use a [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) statement to loop through the strings. How does this differ from a [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) statement?)
5. Use a [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) instead of the `if` statement in the loop.
6. Finally use the [`reduce()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) method to replace the `for...in` loop to reduce the function to a single line.
## 2 Callbacks
@@ -244,7 +244,7 @@ In the example above we store the data returned from the `getData` promise in th

### 6.4 Test Your Knowledge

Run the `promises.js` script, its functionality should be familiar to the `currency.js` script you worked with in chapter 3.
Run the `promises.js` script located in the otherScripts folder. Its functionality should be familiar to the `currency.js` script you worked with in chapter 3.

Open the `promises.js` script and study the code carefully. Notice that it defines 5 promises and chains them together. You are going to extend the functionality by defining some additional promises and adding them to the promise chain.

@@ -376,7 +376,7 @@ both `printObjectPromise` and `printObjectAsync` behave in exactly the same mann

### 7.3 Test Your Knowledge

Run the `asyncFunctions.js` script. Note that it works in the same way as the previous ones. Open the script and study it carefully.
Run the `asyncFunctions.js` script, located in the otherScripts folder. Note that it works in the same way as the previous ones. Open the script and study it carefully.

1. modify the script to ask for the currency to convert to and display only the one conversion rate.
2. instead of printing the exchange rate, ask for the amount to be converted and them return the equivalent in the chosen currency
@@ -114,17 +114,18 @@ In the previous section you learned how to run a test suite and check code cover

### 1.5 Visual Studio Code Extensions

One of the powerful features of VS Code is its support for **Extensions** which allow you to add additional capabilities to the editor.
One of the powerful features of VS Code is its support for **Extensions** which allow you to add additional capabilities to the editor. Make sure you are running the _latest_ version of VS Code (1.38.1 at the time of writing).

![The Extensions Tab](exercises/.images/extensions_tab.png)

You should start by opening the tab and checking for the extensions already installed, these will be listed in the **ENABLED** section. If any of these are not listed you can use the search box to search for them and then install. Once the extensions are installed you will need to shutdown and reload VS Code for them to take effect.

In this lab you will need:

1. coverage-gutters
2. jest
3. test-explorer
1. Coverage Gutters
2. Jest
3. Jest Test Explorer
4. Test Explorer

### 1.6 Running a Test Suite

Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,61 @@

'use strict'

const request = require('request')

getInput('enter base currency', (err, base) => {
if (err) {
console.log(err.message)
process.exit()
}
base = base.trim()
checkValidCurrencyCode(base, err => {
if (err) {
console.log(err.message)
process.exit()
}
getData(`http://api.fixer.io/latest?base=${base}`, (err, data) => {
if (err) {
console.log(err.message)
process.exit()
}
const obj = JSON.parse(data)
printObject(obj)
process.exit()
})
})
})

function getInput(prompt, callback) {
try {
process.stdin.resume()
process.stdin.setEncoding('utf8')
process.stdout.write(`${prompt}: `)
process.stdin.on('data', text => callback(null, text))
} catch(err) {
callback(err)
}
}

function checkValidCurrencyCode(code, callback) {
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,32 @@

'use strict'

const request = require('request')

try {
if (process.argv.length < 3) {
throw 'missing parameter'
}
let address = process.argv[2]
/* we need to remove the single quotes from the string */
address = address.replace(/'/g,'')
console.log(address)
const url = `https://maps.googleapis.com/maps/api/geocode/json?region=gb&units=metric&appid=44c39f3fa462f86b3fc88f5678e5c5ff&address=${address}`
console.log(url)
request.get( url, (err, res, body) => {
if (err) {
throw 'could not complete request'
}
const json = JSON.parse(body)
console.log(JSON.stringify(json, null, 2))
try {
if (json.status === 'ZERO_RESULTS') {
throw 'no results found'
}
} catch(err) {
console.log(err)
}
})
} catch(err) {
console.log(err)
}
@@ -0,0 +1,41 @@

'use strict'

/* eslint no-magic-numbers: 0, arrow-body-style: 0 */

// all four of these functions contain the same functionality.

// traditional JavaScript function that takes an ECMA rest param and returns the total
// no use made of functional programming principles.
function add(...num) {
let total = 0

for (let i=0; i< num.length; i++) {
total += num[i]
}
return total
}

// simple ECMAScript 5 compatible anonymous function assigned to a constant.
// Array.prototype.reduce used to eliminate the loop from the previous example.
const add2 = function(...num) {
return num.reduce( (acc, val) => acc + val)
}

// arrow function syntax used instead of the traditional anonymous function declaration.
// normally a single parameter would not be enclosed in braces but these are needed for rest params.
const add3 = (...num) => {
return num.reduce( (acc, val) => acc + val)
}

// if the body of the function contains a single line of code that returns a value
// the braces and return statement are not required.
const add4 = (...num) => num.reduce( (acc, val) => acc + val)

console.log(add(1, 2, 3))

console.log(add2(1, 2, 3))

console.log(add3(1, 2, 3))

console.log(add4(1, 2, 3))
@@ -0,0 +1,35 @@

'use strict'

const asyncFunc = (name, callback) => {
const names = ['colin', 'bob']
if (names.indexOf(name) > -1) {
// success
const result = 'found'
return callback(null, result)
} else {
// error
const message = 'name not found'
return callback(message)
}
}

// check username exists
const check = name => {
asyncFunc(name, (err, result) => {
if (err) {
// it didn't work i.e. not found
console.error(err)
throw new Error('broke looking for name')
} else {
// success: i.e. result has a value
console.log('It was found.')
console.log(result)
}
})
}

check('colin')
check('nobody')

// (err, data) => {} is common callback signature
@@ -0,0 +1,50 @@

'use strict'

const request = require('request')

async function main() {
try {
const base = await getInput('enter base currency')
await checkValidCurrencyCode(base)
const data = await getData(`http://api.fixer.io/latest?base=${base}`)
await printObject(data)
process.exit()
} catch (err) {
console.log(`error: ${err.message}`)
}
}

const getInput = prompt => new Promise( (resolve) => {
process.stdin.resume()
process.stdin.setEncoding('utf8')
process.stdout.write(`${prompt}: `)
process.stdin.on('data', text => resolve(text))
})

const checkValidCurrencyCode = code => new Promise( (resolve, reject) => {
code = code.trim()
request('http://api.fixer.io/latest', (err, res, body) => {
if (err) reject(new Error('invalid API call'))
const rates = JSON.parse(body).rates
if (!rates.hasOwnProperty(code)) it.throw(new Error(`invalid currency code ${code}`))
resolve()
})
})

const getData = url => new Promise( (resolve, reject) => {
request(url, (err, res, body) => {
if (err) reject(new Error('invalid API call'))
resolve(body)
})
})

const printObject = data => new Promise( (resolve) => {
const indent = 2
data = JSON.parse(data)
const str = JSON.stringify(data, null, indent)
console.log(str)
resolve()
})

main()
@@ -0,0 +1,25 @@
#!/usr/bin/env node

'use strict'

function Book(isbn, title) {
this.isbn = isbn
this.title = title
this.year = null
Object.defineProperty(this, 'published', {
get: () => this.year,
set: year => this.year = year
})
Object.defineProperty(this, 'summary', {
get: () => `${this.title} (${this.isbn}). Published ${this.year}.`
})
}

const b = new Book('1491943122', 'Learning Node')
if (b instanceof Book) console.log('its a Book')
console.log(`the b object is a '${typeof b}'`)
console.log(b.published) // prints null
b.year = 2016
console.log(b.published) // prints 2016
console.log(b)
console.log(b.summary)
@@ -0,0 +1,20 @@
#!/usr/bin/env node
/* eslint no-magic-numbers: 0 */

'use strict'

const Person = require('./person')

module.exports = class Employee extends Person {

constructor(firstname, lastname, grade = 1) {
super(firstname, lastname)
this.joinedDate = new Date()
this.grade = grade
}

calculateSalary(months = 1) {
return this.grade * 1000 * months
}

}
@@ -0,0 +1,22 @@
#!/usr/bin/env node
/* eslint no-magic-numbers: 0 */

'use strict'

const Employee = require('./employee')

try {
const worker = new Employee('John', 'Doe')
console.log(worker.name)

const salary = worker.calculateSalary()
console.log(salary)

const manager = new Employee('Peter', 'Piper', 4)
console.log(manager.name)
console.log(manager.calculateSalary(6))
console.log(manager)

} catch(err) {
console.log(`ERROR: ${err}`)
}

0 comments on commit ddfa888

Please sign in to comment.