7.8 KiB

Amusement Park

Welcome to Amusement Park on Exercism's JavaScript Track. If you need help running the tests or submitting your code, check out HELP.md. If you get stuck on the exercise, check out HINTS.md, but try and solve it without using those first :)


In contrast to many other languages, there are two different entities in JavaScript that represent the absence of a (meaningful) value. There is null and undefined.


The primitive value null is used as an intentional "empty value" for variables of any type.

let name = null;
// name is intentionally set to "empty" because it is not
// available

You can check whether a variable is null by using the strict equality operator ===.

let name = null;

name === null;
// => true


A variable that has not been assigned a value is of type undefined.1

That means while null represents an empty value (but still a value), undefined represents the total absence of a value. 🤯

undefined appears in different contexts.

  • If a variable is declared without a value (initialization), it is undefined.
  • If you try to access a value for a non-existing key in an object, you get undefined.
  • If a function does not return a value, the result is undefined.
  • If an argument is not passed to a function, it is undefined, unless that argument has a default value.
let name;
// => undefined

You can check whether a variable is undefined using the strict equality operator ===.

let name;

name === undefined;
// => true

Optional Chaining

If you try to retrieve a nested value in an object but the parent key does not exist, JavaScript will throw an error. To easily avoid this, optional chaining was added to the language specification in 2020. With the optional chaining operator ?. you can ensure that JavaScript only tries to access the nested key if the parent was not null or undefined. Otherwise, undefined is returned.

const obj = {
  address: {
    street: 'Trincomalee Highway',
    city: 'Batticaloa',

// => undefined

// => TypeError: Cannot read property 'street' of undefined

// => undefined

Nullish Coalescing

There are situations where you want to apply a default value in case a variable is null or undefined (but only then). To address this, the nullish coalescing operator ?? was introduced in 2020. It returns the right-hand side operand only when the left-hand side operand is null or undefined. Otherwise, the left-hand side operand is returned.

let amount = null;
amount = amount ?? 1;
// => 1

amount = 0;
amount = amount ?? 1;
// => 0

[1] Undefined, MDN. (2021). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined (accessed June 4, 2021).


It is your job to provide and maintain parts of the IT system of an amusement park. In particular, you are responsible for the program that manages visitors and tickets.

First, you will create a new visitor in the system. Then you will provide a function for revoking a ticket. In tasks 3 and 4, you will work on the ticket tracking system that helps to prevent forgery. Lastly, you will help adapt the system to new legal requirements.

1. Create a new visitor

When visitors come to the amusement park for the first time, they need to register by entering their name and age in a terminal and agreeing to the terms and conditions. Of course, they also need to buy a ticket. Each ticket has an identifier like H32AZ123.

Write a function createVisitor that accepts three arguments.

  • The name of the visitor.
  • The age of the visitor.
  • The identifier of the ticket that the visitor bought.

The function should return an object that holds this information. The keys in the object should be called name, age and ticketId.

createVisitor('Verena Nardi', 45, 'H32AZ123');
// => { name: 'Verena Nardi', age: 45, ticketId: 'H32AZ123' }

2. Revoke the ticket

When people leave the amusement park, their ticket gets revoked. If they come back, they need to buy a new one. To save regular visitors some time, they only need to register once and the visitor information will be kept for subsequent visits.

That means when a visitor leaves the park, only their ticket should be invalidated but the rest of the visitor object should stay the same. Implement the function revokeTicket that accepts a visitor object, sets the ticket identifier to null and returns the object afterwards.

const visitor = {
  name: 'Verena Nardi',
  age: 45,
  ticketId: 'H32AZ123',

// => { name: 'Verena Nardi', age: 45, ticketId: null }

3. Determine the ticket status

To prevent forgery, the ticket identifiers are unique. Once a ticket is printed, its identifier is added as a key in an object in the system so it can be tracked.

Before the ticket is sold to a visitor, it is stored with the value null in the ticket tracking object. When it is sold to a visitor, the visitor's name is assigned as a value. When employees have doubts about the validity of a ticket, they need to check the status of the ticket in the system.

Implement a function ticketStatus that accepts the tracking object and a ticket identifier as arguments. It should return one of the following results.

  • 'unknown ticket id' if the identifier was not found in the tracking object
  • 'not sold' in case the ticket was printed but not sold
  • 'sold to {name}' where {name} is the name of the visitor if the ticket was sold
const tickets = {
  '0H2AZ123': null,
  '23LA9T41': 'Verena Nardi',

ticketStatus(tickets, 'RE90VAW7');
// => 'unknown ticket id'

ticketStatus(tickets, '0H2AZ123');
// => 'not sold'

ticketStatus(tickets, '23LA9T41');
// => 'sold to Verena Nardi'

4. Improve the ticket status response

After a while, you get feedback from the employees that they want the ticket status to be easier to understand at the first glance. They only want to see either the name of the visitor or that the ticket is invalid.

Write a function simpleTicketStatus that accepts the same arguments as ticketStatus in task 3. This function only returns one of two different results.

  • the name of the visitor if the ticket was sold
  • 'invalid ticket !!!' if the ticket was not sold yet or the identifier was not found in the tracking object
const tickets = {
  '0H2AZ123': null,
  '23LA9T41': 'Verena Nardi',

simpleTicketStatus(tickets, '23LA9T41');
// => 'Verena Nardi'

simpleTicketStatus(tickets, '0H2AZ123');
// => 'invalid ticket !!!'

simpleTicketStatus(tickets, 'RE90VAW7');
// => 'invalid ticket !!!'

5. Determine the version of terms and conditions

Due to new legal requirements, newly created visitor objects now also contain detailed information on the "General Terms & Conditions" (GTC) that the user agreed to. You can see an example of the new visitor object below.

The cashiers of the amusement park now need to check whether a visitor needs to sign a new version of the GTC. For this, implement a function gtcVersion that accepts a visitor object as an argument and returns the GTC version if it is available. If the version information is not available, nothing should be returned.

const visitorNew = {
  name: 'Verena Nardi',
  age: 45,
  ticketId: 'H32AZ123',
  gtc: {
    signed: true,
    version: '2.1',

// => '2.1'

const visitorOld = {
  name: 'Verena Nardi',
  age: 45,
  ticketId: 'H32AZ123',

// => undefined


Created by

  • @junedev