Skip to content

IPW_IP 2324 1 A1

André Jesus edited this page Oct 12, 2023 · 5 revisions
Instituto Superior de Engenharia de Lisboa
Bachelor in Computer Science and Computer Engineering
Bachelor in Informatics, Networks and Telecommunications Engineering
Internet Programming/Introduction to Web Programming
Winter Semester of 2023/2024 – **1st practical assignment**

Delivery

This first practical assignment has 2 parts, and it should be implemented and delivered individually by each student. The delivery dates are the following:

  • Part1: 15/10/2023-23h59.
  • Part2: 22/10/2023-23h59.

Delivery method

The delivery method is done in 2 steps:

  • In Github Classroom, use this invitation link. Following this link, login with your github user account and select your student id to make the correspondence between them, so that a private Github repository is created. The assignment should be delivered in this repository, by creating a tag called A1-P1. If you need to make some amend to the delivery, just create another tag named A1-P1.1, A1-P1.2, etc.

Part 1 - JavaScript functions

Implement the following JavaScript functions and create tests that confirm the described behavior:

  1. Implement the function validateProperty(obj, propValidator), that returns true if it confirms the existence and validity of a given property in obj, or false otherwise. The validity specification is provided in propValidator argument.

    Example

    const validator = {name : "p1" , validators: [s => typeof s == 'string' && s.length > 2, s => s[0]=="a"]  }
    const obj1 = { p1 : "abc" }
    const obj2 = { p2 : 123 }
    const obj3 = { p1 : "a" , p2 : 123 }
    
    validateProperty(obj1, validator) //true
    validateProperty(obj2, validator) //false
    validateProperty(obj3, validator) //false

    Arguments

    • obj: an object to validate a property
    • propValidator: an object that validates a property on obj, having the following properties:
      • name - the name of the property to validate
      • validators - an array of predicate functions that must be called with the property value. If any returns false the property is invalid.

    Conditions

    • Do not create any unnecessary functions e.g. helpers.
    • Create more object and validator usage examples, than the provided ones.

  1. Implement the function copyProperties(obj, propValidators), that returns a new object with properties with the same name and value to the ones existing in obj. The properties to copy are defined and validated by propValidators array argument. Each property that does not exists in obj or the validation fails, will not be present in the returned object. If no property exists or is valid and empty object is returned.

    Example

    const validators = [
       {
          name: "p1", validators: [s => typeof s == 'string' && s.length > 2, s => s[0] == "a"]
       },
       {
          name: "p2", validators: [s => Number.isInteger(s)]
       }
    ]
    
    const obj1 = { p1: "a" }
    const obj2 = { p1: 123 }
    const obj3 = { p1: "abc", p2: 123 }
    console.log(copyProperties(obj1, validators)) // {}
    console.log(copyProperties(obj2, validators)) // {}
    console.log(copyProperties(obj3, validators)) // { p1: 'abc', p2: 123 }   

    Arguments

    • obj: an object to validate the properties

    • propValidators: an array of property validators, as defined in the previous exercise to validate the properties in obj

    Conditions

    • Do not use any for/while loops or Array#forEach.
    • Do not create any unnecessary functions e.g. helpers.
    • Create more object and validator usage examples, than the provided ones.

    Hints

    • The function must call validateProperty for each validator

  1. Add a copyProperties method to Object type. This method implementation should call the copyProperties function implemented in the previous exercise.

Example

   const validators = [
      {
         name: "p1", validators: [s => typeof s == 'string' && s.length > 2, s => s[0] == "a"]
      },
      {
         name: "p2", validators: [s => Number.isInteger(s)]
      }
   ]

   const obj1 = { p1: "a" }
   const obj2 = { p1: 123 }
   const obj3 = { p1: "abc", p2: 123 }
   console.log(obj1.copyProperties(validators)) // {}
   console.log(obj2.copyProperties(validators)) // {}
   console.log(obj3.copyProperties(validators)) // { p1: 'abc', p2: 123 }   

  1. Add the associateWith(transformation) method to the Array type. This function returns an Object in which the elements values of the original Array are properties names, and the corresponding values values are produced from them by the given transformation function. If two elements are equal, only the last one remains in the object. Example:

    let numbers = ["one", "two", "three", "four"]
    console.log(numbers.associateWith( str => str.length ))
    
    // { one: 3, two: 3, three: 5, four: 4}

  1. Implement checkUsersValid(goodUsers)function that returns a function. The returned function, takes a list of valid users in goodUsers, and returns true if all of the supplied users exist in the original list of users, or false otherwise.

    You only need to check that the user ids match. Example:

    var goodUsers = [
       { id: 1 },
       { id: 2 },
       { id: 3 }
    ]
    
    // `checkUsersValid` is the function you'll define
    var testAllValid = checkUsersValid(goodUsers)
    
    testAllValid([
       { id: 2 },
       { id: 1 }
    ])
    // => true
    
    testAllValid([
       { id: 2 },
       { id: 4 },
       { id: 1 }
    ])
    // => false

    Arguments

    • goodUsers: a list of valid users

  1. Override a specified method of an object with new functionality while still maintaining all of the old behavior.

    Create a Spy function that returns an object that keeps track of how many times a function is called.

    Example

    var spy = Spy(console, 'error')
    
    console.error('calling console.error')
    console.error('calling console.error')
    console.error('calling console.error')
    
    console.log(spy.count) // 3

    Arguments

    • target: an object containing the method method
    • method: a string with the name of the method on target to spy on.

    Conditions

    • Do not use any for/while loops or Array#forEach.
    • Do not create any unnecessary functions e.g. helpers.

    Hint

    • Functions have context, input and output. Make sure you consider the context, input to and output from the function you are spying on.

Part 2 - Node application

Foreword

This part requires that your code makes HTTP requests to the Ticketmaster API. To access this API, each student must request the API key that identifies the student application's requests. That key must be included in the URL of each HTTP request. The description of the necessary steps to create the token are described here. Note that this is a free API, and therefore it has rate limits for your requests. Be sure you understand and comply to these limits.

Application requirements

This application reads event ids from a json file, with the following format:

{
   "event-ids" : [
       "Z698xZ2qZa6y5",
       "Z698xZ2qZaFHl",
       "G5vYZ9svBCs1O",
   ]
}

and produces another JSON file containing each event name, date and venue location (if one exists), as shown in following example:

{
  "events": [
    {
      "id": "Z698xZ2qZa6y5",
      "name": "HAUSER - Rebel with a Cello - Meet&Greet Package",
      "date": "2023-10-11T19:00:00Z",
      "venue": {
        "name": "WiZink Center",
        "country": "Spain",
        "city": "Madrid"
      }
    },
    {
      "id": "Z698xZ2qZaFHl",
      "name": "Masood Boomgaard",
      "date": "2023-10-10T19:00:00Z",
      "venue": {
        "name": "Teatro Luchana (Sala 2)",
        "country": "Spain",
        "city": "Madrid"
      }
    },
    {
      "id": "G5vYZ9svBCs1O",
      "name": "Golden State Warriors vs. Phoenix Suns",
      "date": "2023-10-25T02:00:00Z",
      "venue": {
        "name": "Chase Center",
        "country": "United States Of America",
        "city": "San Francisco"
      }
    }
  ]
}

Implement two versions of the application:

  1. Using Promises explicitly
  2. Using the async/await style

REMARK: The students should consider and find solutions for the limitations of this free API, namely the Rate Limits in terms of the number of requests per day and per second.

Clone this wiki locally