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

disc-flight

v0.1.1

Published

Disc golf flight path visualization engine. Takes flight numbers (speed/glide/turn/fade) and outputs beautiful flight path graphics.

Readme

disc-flight

Disc golf flight path visualization engine. Takes flight numbers (speed/glide/turn/fade) and outputs accurate, smooth flight path graphics.

Zero dependencies. Works in Node.js and the browser. Dual ESM + CJS builds.

Install

npm install disc-flight

Usage

import { calculateFlightPath, renderSvg } from 'disc-flight'

// Get raw coordinate data
const path = calculateFlightPath({
  speed: 12, glide: 5, turn: -1, fade: 3, // Destroyer
})
console.log(path.distance)     // ~457 (feet)
console.log(path.landingPoint) // { x: -28.7, y: 457 }
console.log(path.points)       // Array of { x, y } coordinates

// Render a single disc as SVG
const svg = renderSvg({
  speed: 12, glide: 5, turn: -1, fade: 3,
  color: '#ff4444',
  label: 'Destroyer',
})

// Compare multiple discs on one fairway
const comparison = renderSvg([
  { speed: 12, glide: 5, turn: -1, fade: 3, color: '#ff4444', label: 'Destroyer' },
  { speed: 5, glide: 4, turn: -1, fade: 1, color: '#44ff44', label: 'Buzzz' },
  { speed: 9, glide: 3, turn: 0, fade: 4, color: '#ff8800', label: 'Firebird' },
], { width: 500, height: 700 })

CLI

Generate flight path SVGs from the command line:

# Single disc to file
disc-flight render --discs "Destroyer:12/5/-1/3:red" --output destroyer.svg

# Multiple discs with grid to stdout
disc-flight render --discs "Destroyer:12/5/-1/3:red,Buzzz:5/4/-1/1:green" --grid

# All options
disc-flight render --discs "<spec>" \
  --output file.svg \
  --width 800 --height 600 \
  --grid --hand lhbh --arm-speed fast \
  --no-labels --no-landing --no-fairway

Disc spec format: Label:Speed/Glide/Turn/Fade:Color — label and color are optional, comma-separated for multiple discs.

Run disc-flight --help for full usage.

API

calculateFlightPath(input: FlightInput): FlightPath

Converts flight numbers to an array of coordinates.

FlightInput: | Field | Type | Required | Description | |-------|------|----------|-------------| | speed | number | yes | 1-14, primary distance driver | | glide | number | yes | 1-7, hang time / distance bonus | | turn | number | yes | -5 to +1, high-speed lateral movement (negative = understable) | | fade | number | yes | 0-5, low-speed hook at end of flight | | hand | string | no | 'rhbh' (default), 'lhbh', 'rhfh', 'lhfh' | | armSpeed | string | no | 'slow', 'normal' (default), 'fast' | | color | string | no | SVG stroke color (for rendering) | | label | string | no | Disc name label (for rendering) | | lineWidth | number | no | SVG stroke width (default 2.5) |

FlightPath: | Field | Type | Description | |-------|------|-------------| | points | Point[] | Array of { x, y } coordinates (feet) | | distance | number | Total flight distance in feet | | landingPoint | Point | Final resting position |

parseDiscSpec(spec: string): FlightInput[]

Parses a disc spec string into FlightInput objects. Useful for building your own tooling on top of disc-flight.

import { parseDiscSpec, renderSvg } from 'disc-flight'

const discs = parseDiscSpec('Destroyer:12/5/-1/3:red,Buzzz:5/4/-1/1:green')
const svg = renderSvg(discs, { showGrid: true })

renderSvg(discs, options?): string

Renders one or more flight paths as an SVG string.

RenderOptions: | Field | Type | Default | Description | |-------|------|---------|-------------| | width | number | 400 | SVG width in pixels | | height | number | 600 | SVG height in pixels | | padding | number | 40 | Inner padding | | showFairway | boolean | true | Dark green background | | showLabels | boolean | true | Disc name labels at landing | | showLandingZone | boolean | true | X marks at landing positions | | showGrid | boolean | false | Distance grid with labeled axes |

How the Math Works

The flight model uses velocity integration rather than position-based phase transitions. This guarantees mathematically smooth curves with no kinks or bumps.

At each point in the flight, two lateral velocity components are calculated:

  1. Turn velocity — models the high-speed lateral drift. Cubic rise (t^3) that accelerates from zero (disc looks straight off the tee), peaks around 55-67% of flight, then decays with a quadratic falloff as the disc slows.

  2. Fade velocity — models the low-speed hook. Quadratic ease-in (t^2) compressed into the last ~20% of flight. Always accelerating — the curve gets steeper as the disc dumps speed, which matches how real discs behave.

These velocities are summed and integrated to produce the lateral position at each sample point. The "coast" period (where the disc drifts along its trajectory between turn and fade) emerges naturally from the velocity crossover — no explicit phase boundary needed.

Key scaling decisions:

  • Turn/fade magnitudes use abs(value)^1.5 so the response is non-linear: turn -1 is barely visible, turn -4 is dramatic
  • Distance model outputs feet: putter ~185ft, mid ~295ft, fairway ~350ft, driver ~450ft
  • Lateral displacement scales with distance so proportions stay realistic
  • SVG renderer uses uniform X/Y scaling so a straight disc actually looks straight

The model was tuned by visual comparison against DG Puttheads flight charts for benchmark discs: Destroyer (12/5/-1/3), Buzzz (5/4/-1/1), Firebird (9/3/0/4), Leopard (6/5/-2/1), and Berg (1/1/0/2).

Handedness

All examples assume RHBH (right-hand backhand). The hand option mirrors the flight path:

  • 'rhbh' — right-hand backhand (default). Turn drifts right, fade hooks left.
  • 'lhbh' — left-hand backhand. Mirror of RHBH.
  • 'rhfh' — right-hand forehand. Same mirror as LHBH.
  • 'lhfh' — left-hand forehand. Same as RHBH.

Arm Speed

The armSpeed modifier affects distance, turn, and fade:

  • 'slow' — 82% distance, 50% turn, 130% fade. Disc flies shorter and more overstable.
  • 'normal' — baseline. Manufacturer flight numbers as-is.
  • 'fast' — 110% distance, 140% turn, 80% fade. Disc flies farther and more understable.

License

MIT