npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pinewood-derby-scheduler

v1.1.0

Published

Lane assignment scheduler for pinewood derby races

Readme

pinewood-derby-scheduler

Node.js CI

A lane assignment scheduler for pinewood derby races. Generates fair race schedules that optimize for lane diversity, opponent variety, and fast race setup.

Live demo: https://pinewood.tomlee.space

Installation

npm install pinewood-derby-scheduler

Usage

import { schedule } from 'pinewood-derby-scheduler';

// Define your racers (can be any shape)
const racers = [
  { id: 1, name: 'Lightning' },
  { id: 2, name: 'Thunder' },
  { id: 3, name: 'Rocket' },
  { id: 4, name: 'Blaze' },
  { id: 5, name: 'Storm' },
];

// Generate a schedule
const raceSchedule = schedule(racers, {
  numLanes: 4,      // 4-lane track
  heatsPerRacer: 3, // each car races 3 times
});

// raceSchedule is a 2D array: [heat][lane]
raceSchedule.forEach((heat, i) => {
  console.log(`Heat ${i + 1}:`, heat.map(r => r?.name ?? '(empty)'));
});

Scheduling Criteria

The scheduler optimizes for three criteria, which you can prioritize in any order:

| Criterion | Description | |-----------|-------------| | 'lanes' | Lane diversity — Each racer uses different lanes across their heats | | 'opponents' | Opponent diversity — Each racer faces different opponents | | 'turnover' | Turnover — Minimize cars appearing in consecutive heats (faster race setup) |

Setting Priorities

Pass an array to prioritize to control the relative importance of each criterion. The first item has highest priority:

// Prioritize fast race setup, then opponent variety, then lane diversity
const raceSchedule = schedule(racers, {
  numLanes: 4,
  heatsPerRacer: 4,
  prioritize: ['turnover', 'opponents', 'lanes'],
});
// Prioritize lane diversity (default behavior)
const raceSchedule = schedule(racers, {
  numLanes: 4,
  heatsPerRacer: 4,
  prioritize: ['lanes', 'turnover', 'opponents'],
});
// Prioritize opponent variety above all else
const raceSchedule = schedule(racers, {
  numLanes: 4,
  heatsPerRacer: 4,
  prioritize: ['opponents', 'lanes', 'turnover'],
});

All three criteria are always considered; the priority order controls their relative weights (first = 1000, second = 100, third = 10).

Backward Compatibility

The old single-string format still works:

// These are equivalent:
prioritize: 'lanes'
prioritize: ['lanes', 'turnover', 'opponents']

// These are equivalent:
prioritize: 'opponents'
prioritize: ['opponents', 'turnover', 'lanes']

API

schedule<T>(racers: T[], options: ScheduleOptions): Schedule<T>

Generates a race schedule.

Parameters:

  • racers — Array of racer objects (any shape)
  • options.numLanes — Number of lanes on the track
  • options.heatsPerRacer — How many heats each racer participates in
  • options.prioritize — Priority order for scheduling criteria
    • Single criterion: 'lanes' | 'opponents' (backward compatible)
    • Array of criteria: ['lanes', 'turnover', 'opponents'] (any order)
    • Default: ['lanes', 'turnover', 'opponents']

Returns: A 2D array where result[heatIndex][laneIndex] is a racer or null (empty lane).

Types

type ScheduleCriterion = 'lanes' | 'opponents' | 'turnover';

interface ScheduleOptions {
  numLanes: number;
  heatsPerRacer: number;
  prioritize?: ScheduleCriterion | ScheduleCriterion[];
}

type Heat<T> = (T | null)[];
type Schedule<T> = Heat<T>[];

License

MIT