Read how a learner learns from a short survey, and turn it into concrete lesson-planning guidance — for one Marine and for the whole class.
Ask a learner "how do I learn?" once, and Waypoint turns the answers into something an instructor can act on: the dominant way they take information in, how they like it paced and structured, and specific recommendations for delivery. Aggregate a class and it tells the faculty what to adjust for the cohort.
Everything is pure and deterministic — no model, no network, no key. It ships with a ready-to-use
survey, and it reports a dimension as null rather than guessing when it wasn't answered.
A preference read to shape delivery — not a fixed "learning style" that boxes a learner in.
npm install waypointRequires Node 18+. ES modules only.
import { profile, recommendations, toMarkdown } from 'waypoint';
// Likert responses (1 = strongly disagree … 5 = strongly agree) keyed by question id.
const responses = { v1:2, v2:2, b1:3, b2:3, r1:2, r2:2, h1:5, h2:5, p1:5, p2:4, s1:2, s2:2 };
const p = profile(responses, { name: 'Cpl Rivera' });
// { name:'Cpl Rivera', dominantModality:'hands_on', pace:'self-paced', structure:'exploratory',
// dims:{ visual:.., verbal:.., reading:.., hands_on:1, self_paced:.875, structured:.. }, answered:12 }
recommendations(p);
// [ 'Front-load practical reps; keep the lecture short and get to the task.',
// 'Offer a self-paced track with checkpoints rather than a lockstep schedule.',
// 'Allow exploratory practice with scaffolding available on request.' ]Six dimensions, each 0..1:
| Group | Dimensions |
|---|---|
| Modality (how they take it in) | visual · verbal · reading · hands_on |
| Style | self_paced · structured |
The dominant modality is the strongest of the four; pace and structure resolve to a
leaning (self-paced / instructor-paced / flexible, and structured / exploratory / balanced).
defaultInstrument is a 12-item survey (two per dimension) ready to hand to a learner. Bring your own
by passing { instrument } — each item is { id, dim, text, reverse? }. Both defaultInstrument (and
each of its items) and DIMENSIONS are frozen, so the shared survey can't be mutated out from under
scoring.
Responses must be integers 1..5 — a non-number (true, [3], "3") or a non-integer (2.5)
throws TypeError rather than being silently coerced. A blank answer — null, undefined, an omitted
key, or an empty string "" (as web forms send) — is treated as unanswered, and its dimension
reports null rather than being guessed.
import { defaultInstrument, scoreProfile } from 'waypoint';
scoreProfile(responses, { instrument: defaultInstrument }).dims;import { classProfile } from 'waypoint';
const cp = classProfile([riveraResponses, doeResponses, nguyenResponses /* … */]);
// {
// n: 24,
// modalityMix: [ { modality:'hands_on', count:14, share:0.58 }, … ], // most-common first
// dims: { visual:.., hands_on:.., self_paced:.., … }, // class averages
// recommendations: [ '58% of the class is hands-on-leaning — shift the balance toward practical reps and range/lab time.', … ]
// }share and the recommendation's percentage are of all n learners in the cohort — a learner whose
modality wasn't answered counts in the denominator, so a class is never reported as "100% visual" on the
strength of a single answered survey. Pass raw response maps or already-computed profile() results —
either works, and a malformed pre-computed profile is rejected with TypeError rather than silently
skewing the class averages. The recommendations are
the shareable, downloadable output Flores's brief asked for: results go to faculty to shape lesson plans.
import { toMarkdown } from 'waypoint';
toMarkdown(profile(responses, { name: 'PFC Nguyen' })); // → a Markdown profile you can save or hand offThe learner name is escaped before it lands in the document, so a name carrying newlines or markdown/link syntax can't inject headings or links into this shareable output.
| export | purpose |
|---|---|
profile(responses, opts?) |
full learner profile: dims, dominant modality, pace, structure |
scoreProfile(responses, opts?) |
just the 0..1 dimension scores (null where unanswered) |
recommendations(profile) |
concrete, instructor-actionable delivery tips |
classProfile(entries, opts?) |
cohort distribution + faculty recommendations |
toMarkdown(profile) |
a shareable Markdown profile |
defaultInstrument · DIMENSIONS |
the built-in survey and dimension list |
Every function validates its input and throws TypeError on a bad shape.
node example/demo.mjsApache-2.0.