PF 101 study hub

PF 101 · Pre-final · ~60–75 min

Ride Start → Garage OOP

Jeepney, trike, habal, tsinelas. Same start() and sakay(n) — different shouts, different max passengers.

Final output

What you can create

Habal max 3. Sakay 10 → illegal recruitment. Sakay 2 → Swakto.

Open full screen

Before you start

Not the Arena

New folder. No fighters. Garage must not use instanceof. Habal-habal max is 3 — ten sakay is illegal recruitment.

Full typed walkthrough: ACTIVITY-ride-start.md

STEP 1

Type the parent Ride

  1. 1

    Create js/ride.js.

  2. 2

    start() and maxPassengers() throw until a subclass writes them.

  3. 3

    sakay(n) lives on the parent — checks max, then Swakto or illegal recruitment.

sakay(n)parent logic
if (n > this.maxPassengers()) {
  return 'Pffft… illegal recruitment. Max ' + this.maxPassengers() + ' lang dito.';
}
return this.boardOk(n);

Habal max is 3. Ten passengers must fail with a funny line.

STEP 2

Jeepney, Tricycle, Habal

  1. 1

    Each subclass implements start() and maxPassengers().

  2. 2

    Habal-habal (Motorcycle) max = 3.

  3. 3

    Optional witty boardOk(count) per ride.

Motorcyclehabal
start() { return 'Vroom'; }
maxPassengers() { return 3; }

Same method names. Different shouts and caps. That is the hook.

STEP 3

Garage — no instanceof

  1. 1

    Garage HAS rides. It does not extend Ride.

  2. 2

    startSelected() and sakaySelected(n) only call the methods.

  3. 3

    Add Tsinelas later — Garage stays untouched.

If you write instanceof, start that file over.

STEP 4

Load scripts in index.html

  1. 1

    The empty starter has no <script> tags — add them before </body>.

  2. 2

    Order matters: parent ride.js first, then subclasses, then garage.js, then main.js.

  3. 3

    Only include a stretch ride after you create that file.

index.htmlbefore </body>
<script src="js/ride.js"></script>
<script src="js/jeepney.js"></script>
<script src="js/tricycle.js"></script>
<script src="js/motorcycle.js"></script>
<script src="js/lantsa.js"></script>
<script src="js/baobao.js"></script>
<script src="js/eroplano.js"></script>
<script src="js/bike.js"></script>
<script src="js/nwow.js"></script>
<script src="js/truck.js"></script>
<script src="js/bulldozer.js"></script>
<script src="js/tsinelas.js"></script>
<script src="js/garage.js"></script>
<script src="js/main.js"></script>

Forgot a script? Console says the class is not defined.

STEP 5

Register rides in main.js

  1. 1

    In main.js: create a Garage, then garage.add(new …()) for each ride you loaded.

  2. 2

    Only add a stretch ride after its class file and script tag exist.

main.jsregister rides
const garage = new Garage();
garage.add(new Jeepney());
garage.add(new Tricycle());
garage.add(new Motorcycle());
garage.add(new Lantsa());
garage.add(new BaoBao());
garage.add(new Eroplano());
garage.add(new Bike());
garage.add(new Nwow());
garage.add(new Truck());
garage.add(new Bulldozer());
garage.add(new Tsinelas());

Forgot an add()? That ride never appears in the list.

STEP 6

Wire Start + Sakay

  1. 1

    Still in main.js: grab the board elements, render the ride list, hook Start and Sakay.

  2. 2

    Click a ride → garage.select. Start / Sakay call Garage only — never the ride type.

  3. 3

    Prove: habal 10 → illegal · habal 2 → Swakto. Then write maxPassengers for habal on paper.

main.jsafter garage.add(…)
const list = document.getElementById('ride-list');
const startBtn = document.getElementById('start-btn');
const sakayBtn = document.getElementById('sakay-btn');
const paxInput = document.getElementById('pax');
const hint = document.getElementById('hint');
const shout = document.getElementById('shout');
const formula = document.getElementById('formula');

function showLine(line, codeLine) {
  shout.textContent = line;
  shout.classList.remove('is-live');
  void shout.offsetWidth;
  shout.classList.add('is-live');
  formula.textContent = codeLine;
}

function setReady(ride) {
  hint.textContent = 'Max ' + ride.maxPassengers() + ' passengers. Start or Sakay.';
  startBtn.disabled = false;
  sakayBtn.disabled = false;
  paxInput.disabled = false;
  paxInput.value = '1';
  shout.textContent = '—';
  shout.classList.remove('is-live');
  formula.textContent = '';
}

function renderList() {
  list.innerHTML = '';
  garage.all().forEach((ride) => {
    const item = document.createElement('li');
    const button = document.createElement('button');
    button.type = 'button';
    button.innerHTML =
      '<span>' + ride.label + '</span>' +
      '<span class="ride-meta">' +
        '<span class="ride-kind ' + ride.kind() + '">' + ride.kind() + '</span>' +
        '<span class="ride-max">max ' + ride.maxPassengers() + '</span>' +
      '</span>';
    button.setAttribute('aria-pressed', garage.selected() === ride ? 'true' : 'false');
    button.addEventListener('click', () => {
      garage.select(ride);
      setReady(ride);
      renderList();
    });
    item.appendChild(button);
    list.appendChild(item);
  });
}

startBtn.addEventListener('click', () => {
  const ride = garage.selected();
  const line = garage.startSelected();
  showLine(line, ride.kind() + '.start() → "' + line + '"');
});

sakayBtn.addEventListener('click', () => {
  const ride = garage.selected();
  const count = paxInput.value;
  const line = garage.sakaySelected(count);
  showLine(line, ride.kind() + '.sakay(' + count + ') · max ' + ride.maxPassengers());
});

renderList();

Compare with the final output demo when you get stuck.

Done checklist

Submit

Ride Start repo only. Recite max passengers for habal with the file closed.

DeliverableWhat to turn in
RepoGitHub URL for ride-start
DemoStart + Sakay 10 on habal (illegal) + Sakay 2 (Swakto)
DefenseWhy Garage does not need instanceof

Start + Sakay already work? Continue Day 2 · Private, Fare, Boarded · Still on Warrior vs Witch? Finish the midterm roster then start a new folder.