Freedom to Design

By Robert N. Bilyk
President, LodeStar Learning Corporation

Introduction

Freedom to Design is the ability to first design the learning experience you want and then, without being constrained by a tool, build it faithfully.

When a design calls for eLearning, many designers run into a technical problem: the authoring tool may support only a narrow set of interaction templates. The loss of freedom happens when the original design must be shoe-horned into a present-and-check structure or a prebuilt activity type. In those cases, the tool begins to deform the design.

Freedom to Design means starting with a blank slate and building according to the design blueprint without compromise.

The technical challenge presents itself especially when designing simulations. 

Research repeatedly reminds us of the efficacy of simulations.    The potential for simulation-based eLearning to build advanced skills cannot be overstated.  I’ll outline the potential, and the preparation a learning experience designer must have to break out of the present-and-check mold and create realistic situations that challenge learners.

Background

Analyses from associations like Association for Talent Development (ATD) and the Learning Guild tell us that the predominant uses of eLearning are in new employee onboarding, compliance training, product training, policy training, foundational professional skills, and basic procedural training.  The training typically features content presentation, quizzes for recall, and procedural instruction (how to use the corporate contact management system, for example).

eLearning can play a larger role in advanced skills development but requires more sophisticated treatments such as virtual role plays, decision-making scenarios, interactive case studies, branched instruction, problem-solving in realistic settings – in short, simulations.

The Case for Simulation-Based Learning

A recent meta-analysis titled Simulation-Based Learning in Higher Education: A Meta-Analysis1 and published in 2020 shows us how eLearning can play an important role for advanced skill development and problem-solving. 

The meta-analysis included 145 studies and showed an overall effect size of 0.85.  That is a significant effect.   In these studies, if we compare the students who received simulation-based instruction (the experiment group) with students who received traditional lectures, the mean of the experiment group was 0.85 standard deviations higher than the mean of the control group.  In simpler terms, the average participant in the experimental group performed better than about 80% of the control group.

Experiment Group (orange) compared with Control Group (blue)

But eLearning can’t take much of the credit for this.  The activities were generated by instructors who operated mostly within their wheelhouse.  They used documents, in-person role play, mannequins, live models, and some computer-supported instruction and virtual reality.  The effect sizes ranged from 0.31 with the use of documents to 2.27 with the use of live models.

A meta-analysis summarizes many studies and uses standard techniques (Hedges’ g, Cohen’s d) for grouping the effects of multiple studies.  The Simulation-Based Learning in Higher Education meta-analysis sample included 10,532 higher ed students.  In the analysis the authors suggest that:

  • Application of knowledge in realistic situations is important for the development of complex skills.
  • Learners can acquire complex problem-solving expertise if they have sufficient prior knowledge and practice
  • Approximations of professional practice in which complexity is reduced are beneficial to students

These observations suggest more than a presentation and a quiz.  Learning Experience Designers can expand the role of eLearning in engaging students and employees in realistic situations but that requires some key fundamental skills.  For LXD students and some LXD practitioners this is a big step from presenting content and assessing knowledge with multiple-choice and matching questions.  In fact, the roster of skills that simulations require is impressive and, at first, a bit daunting.

If a Learning Experience Designer (LXD) wants to move beyond form-based, templated e-learning (typical slide + bullet + quiz structures), they need a broader set of design, narrative, technical, and research skills. These skills allow them to design experiential, interactive, and exploratory learning environments rather than filling in activity templates.

I’ll list the 10 key skills here but, in the appendix, I provide more detail.

  • Learning Science & Cognitive Psychology
  • Scenario & Narrative Design
  • Interaction Design (UX/UI)
  • Learner-Centered Thinking
  • Rapid Prototyping
  • Basic Programming or Scripting
  • Data & Analytics Literacy
  • Visual Communication & Information Design
  • Game Design Principles
  • Learning Environment Design

Some of the skills like knowledge of learning science require long-term study whether through reading or formal education.   Other skills like narrative design can be achieved by practice and building projects for real learners.  Basic scripting and data literacy can be achieved through building stepping-stone projects like the one I describe in this linked do-it-yourself article.  The key is understanding some basic principles and applying them to a simple project. 

Stepping Stone Project | LodeStar Web Journal

Conclusion

Simulations represent a huge, missed opportunity for Learning Experience Designers, for education and for workforce learning and development.  We are confident that simulations are effective in a variety of forms, including eLearning.  But we also acknowledge that designing simulations requires a variety of skills.  Some of the skills like scripting code (and its logic) are more difficult to master than others.

For those of you who embrace the value of simulations and want to get your hands dirty, I offer the stepping-stone project.  For L&D managers and educators, consider simulations as an instructional strategy and provide support to the designers who want to take it on.

Appendix: Skills needed by Learning Experience Designers

Learning Experience Designers (LXD) who want to move beyond form-based, templated e-learning (typical slide + bullet + quiz structures) need a broader set of design, narrative, technical, and research skills. These skills allow them to design experiential, interactive, and exploratory learning environments rather than filling in templates.

Below, I provide more detail on 10 key skills that enable that freedom.


1. Learning Science & Cognitive Psychology

Understanding how people learn allows the designer to move beyond rigid templates and design experiences aligned with cognition.

Key concepts include:

  • Cognitive Load Theory
  • Retrieval practice
  • Spaced repetition
  • Interleaving
  • Dual coding
  • Worked examples

These principles guide structure and sequencing.


2. Scenario & Narrative Design

Non-templated learning often uses story structures.

Skills include:

  • Writing branching scenarios
  • Designing decision points
  • Character development
  • Dramatic tension and consequences

This is the foundation of case-based and role-play learning.


3. Interaction Design (UX/UI)

LXDs must understand how users interact with systems.

Key abilities:

  • Meeting Accessibility Standards
  • Following Universal Design Principles to include all learners
  • Creating responsive design to adapt to various devices
  • Creating intuitive navigation
  • Managing attention and focus
  • Designing feedback loops
  • Designing User Testing

Without Accessibility and UX skills, non-templated learning quickly becomes confusing.


4. Learner-Centered Thinking

Complex learning experiences require seeing the learning system as a whole but with the learner at the center of focus.

Skills include:

  • Empathy Mapping
  • Backwards Design
  • Learner Journey Mapping
  • Mapping relationships between concepts
  • Designing knowledge networks
  • Structuring exploratory learning paths

This allows for non-linear learning environments that remain aligned to learning objectives and learner needs.


5. Rapid Prototyping

LXDs should prototype experiences before building them.

Common techniques include:

  • Sketching
  • Storyboarding
  • Paper prototypes
  • Clickable wireframes
  • Functional prototypes

The ability to prototype interactions quickly prevents getting trapped in an ineffective design.


6. Basic Programming or Scripting

Templated tools limit interaction possibilities. Even basic coding unlocks new capabilities.

Useful skills:

  • JavaScript
  • HTML/CSS
  • scripting inside authoring tools
  • event-driven logic

7. Data & Analytics Literacy

LXDs must understand how to measure learning behavior, not just quiz scores.

Skills include:

  • interpreting learning analytics
  • designing meaningful metrics
  • using xAPI statements
  • analyzing interaction patterns
  • conducting A/B tests

This allows designers to refine experiences iteratively.


8. Visual Communication & Information Design

When templates disappear, information design becomes essential.

Skills include:

  • hierarchy and layout
  • visual signaling
  • diagramming
  • iconography
  • cognitive mapping

This prevents experiences from becoming chaotic.


9. Game Design Principles

Many non-templated experiences borrow heavily from games.

Important concepts:

  • extrinsic and intrinsic motivation
  • feedback loops
  • challenge curves
  • meaningful choices
  • progression systems

Frameworks like Octalysis help here.


10. Learning Environment Design

The designer must know how to guide learners without controlling every step.

Skills include:

  • inquiry-based learning design
  • problem-centered learning
  • scaffolding exploration
  • designing constraints rather than instructions

This produces learning environments instead of presentations.


The Underlying Shift

A content-focused e-learning developer is like a PowerPoint designer, while a learner-focused LXD professional working beyond templates is closer to a game designer or interactive storyteller.  Moving beyond templates requires a mindset shift:

Template E-LearningExperience Design
SlidesEnvironments
Content deliveryProblem solving
Linear sequenceExploration
Knowledge checksMeaningful decisions
  

References

  1. Chernikova, O., Heitzmann, N., Stadler, M., Holzberger, D., Seidel, T., & Fischer, F. (2020). Simulation-based learning in Higher Education: A meta-analysis. Review of Educational Research, 90(4), 499–541. https://doi.org/10.3102/0034654320933544

Stepping Stone Project

By Robert N. Bilyk

Background

Freedom to Design is the ability to first design the learning experience you want and then, without being constrained by a tool, build it faithfully.

When a design calls for eLearning, many designers run into a technical problem: the authoring tool may support only a narrow set of interaction templates. The loss of freedom happens when the original design must be shoe-horned into a present-and-check structure or a prebuilt activity type. In those cases, the tool begins to deform the design.

Freedom to Design means starting with a blank slate and building according to the design blueprint without compromise.

This stepping-stone project is intended to help designers move away from templated, form-based authoring and toward free-form authoring built from scratch.


About the Project

At its core, this is a quiz on foundational principles of learner-centered design. It is simple in format, but it includes several important mechanics that push it beyond a basic quiz:

  • Missed items are added back into the queue for spaced repetition
  • Some statements are true for all learners, while others are true only for either a novice or an expert
  • The quizzing engine randomly selects a persona, who may or may not be the appropriate audience for the principle stated in the question stem
  • A dataset stores the initial statements, correctness values, personas, citations, and feedback
  • A queue array holds the initial items plus any missed items that need to repeat
  • The interface is drawn from scratch with vector graphics

This project is intentionally modest in scope. It is meant to be achievable, while still introducing the foundations needed for more advanced simulations and scenario-based designs.


Preparatory Step

If you choose to use LodeStar and are unfamiliar with the authoring tool, it is a good idea to begin with an introductory video:

If you choose another authoring tool, this tutorial assumes that you already know the basics of that tool.

So let’s get started.


Overall Project Structure

In LodeStar, build the overall structure first by adding pages and changing their page types where necessary. Be sure to assign a Page ID to each page so that the Page ID matches the name used in the flow.

Every page needs a Page ID.

The project structure is as follows:

  1. Title page — a Text Page
  2. Instructions page — a Text Page that also holds the initialization code described in Step Five
  3. Challenge Interface page — a Text Page that holds the interface built in Step One and some additional initialization code
  4. Report page — a Report Page
  5. Wall page — a Wall Page that prevents learners from directly accessing Persona and Dataset pages
  6. Persona page — a Text Page that holds the persona images created in Step Three
  7. Dataset page — a Text Page that holds the dataset described in Step Four

The Persona and Dataset pages are not meant to be directly accessible to the learner. They function as support pages and are referenced by script.


Equivalent Structure in Storyline

In Storyline, you would create a structure roughly equivalent to this:

LodeStar Page TypeStoryline Equivalent
Text Page (Title)Title Slide
Text Page (Instructions)Information / Content Slide
Text Page (Challenge Interface)Interaction Slide
Report PageResults Slide
Wall PageNavigation Gate Slide
Image Layout PageAsset / Resource Slide
Dataset PageData / Variable Slide

Equivalent Structure in Captivate

In Captivate, create a structure roughly like this:

LodeStar Page TypeCaptivate Equivalent
Text Page (Title)Title Slide using a title layout from the theme
Text Page (Instructions)Content / Introduction Slide with text, narration, and a Continue button
Text Page (Challenge Interface)Interactive Slide built with buttons, click areas, shapes as buttons, or drag-and-drop elements
Report PageQuiz Results Slide or a custom summary slide displaying variables
Wall PageNavigation Block Slide used to prevent direct access to internal assets or support slides
Image Layout PageResource / Asset Slide holding images used elsewhere in the project
Dataset PageVariable / Data Slide using variables and actions to store or initialize data

Step One: Build the Interface

The interface is intentionally simple.

It is composed entirely of scalable vector graphics (SVG). In many authoring tools, these would simply be shapes drawn directly on the screen.

In LodeStar, the designer would draw these shapes in the SVG editor. In Storyline and Captivate, the designer would draw shapes directly on the slide and adjust their properties such as:

  • fill color
  • border color
  • border thickness
  • corner roundness

Some controls, such as the True and False buttons, are really just grouped elements composed of:

  • a rectangle
  • a circle
  • a text label

Most authoring tools allow designers to group shapes and assign them an ID so that they can later be referenced by script.

Drawing the interface from scratch gives us precise control over the design. That matters because we want to:

  • randomly display a persona image
  • display feedback dynamically
  • use a continue button to move forward
  • update the question stem with script

The mechanics are simple, but they create a foundation for more advanced designs. For example, a similar structure could be extended into a context-challenge-activity-feedback (CCAF) interface by adding space for a coach, a running score, a performance meter, or contextual media.

In this design, the persona image is initially just a placeholder. Script will later replace it with a randomly selected persona and descriptive text. The learner must then judge whether the instructional principle is true or false for that persona.

For example, the interface might display an expert persona and the statement:

prioritize worked examples to improve learning for this learner

Worked examples are generally more important for a novice than for an expert. So if the learner selects True for the expert persona, the system responds that the strategy is mismatched to the learner and adds the missed item back into the queue.

The next time the same statement appears, the randomly selected persona may be different. It may now be shown with a novice, in which case the correct answer could change.

This discourages simple memorization. Instead, the learner must consider the context. That is one reason this project is a stepping stone toward scenario-based or CCAF-like experiences rather than just a conventional quiz.


Step Two: Make the Interface Interactive

The next step is to assign IDs to the elements that will be targeted by script.

Once an element has an ID, script can:

  • change its text
  • change its color
  • change its image
  • read or write values associated with it

For example, we will later replace the placeholder question text with the statement drawn from the queue. We will also update feedback text and swap persona images.

In LodeStar, you assign an ID by selecting a shape, typing an ID, and pressing Enter to commit it. In LodeStar, shapes are often referred to as elements. (Don’t forget to hit Enter or the ID won’t stick!).

Please note: IDs are used in the script and so, they must be exact and they are case sensitive.

In Storyline, the equivalent is usually done through an accessibility name or object name. In Captivate, it is typically done through the Name field in the Properties panel.

Assign the following IDs:

Interface ElementID
Persona imagepersona
Persona description textpeople_characteristics
Feedback textfeedback
Continue button groupcontinue_button
Question stem textquestion_stem
True button grouptrue_area
Circle inside true grouptrue_button
False button groupfalse_area
Circle inside false groupfalse_button
Submit button groupsubmit_button
The selected image element is assigned the id of ‘persona’
The text under People Characteristics is assigned the id of ‘people_characteristics’
The text element under feedback is given the id of ‘feedback’
The Continue button is given the id of ‘continue_button’
The text element under Question Stem is assigned the id of ‘question_stem’
The True grouping is assigned the id of ‘true_area’
The circle within the True grouping is assigned the id of ‘true_button’. The script will be attached to ‘true_area’.
The False grouping is assigned the id of ‘false_area’
The Submit button is assigned the id of ‘submit_button’.

All other interface elements can remain with their default names, because they are not directly targeted by script.

The grouped controls matter. For example, the true_area is the clickable control as a whole, while the inner true_button circle is the element whose color changes when the learner selects that option.


Step Three: Create an Image Layout

Add an Image Layout widget to the Persona page, which comes after the Wall page.

In the widget, click on the image area to add your first image and then click on the plus button to add the second image.

Import two images:

  • one that represents the novice adult learner
  • one that represents the expert adult learner

This is very important:

  • Give the first image the ID persona1
  • Give the second image the ID persona2

Be sure you are filling in the ID field, not the image caption field.

These image IDs matter because the script will later switch the displayed persona by calling changeImage(“persona”, “persona1”) or changeImage(“persona”, “persona2”).

You can leave the other image settings at their defaults for now.

Image Layout widget featuring the ability to add images and assign them IDs.
The second image is assigned the id of ‘persona2’

Step Four: Create a Dataset

In LodeStar, defining a dataset is relatively easy. In Storyline or Captivate, it is more involved, but the same basic idea still applies.

On the Dataset page, add a Dataset widget. Give the dataset the ID of ‘statements‘.

Define the following fields:

  • Persona
  • Statement
  • Correct
  • Citation
  • Feedback

You do this by naming the first property of ‘Persona’ and then clicking on the add button to fill in the second property and then repeat:

If you are familiar with spreadsheets, these fields are like column headings. Each row below those headings is a record.

Here is what it looks like in LodeStar.

After defining the properties, click Generate and enter your data. In the example project, there are 24 items.

Here is how to think about the Persona field:

  • If Persona = all, then the statement applies to both novice and expert learners
  • If Persona = adult_novice, then the statement is only true when the novice persona is displayed
  • If Persona = adult_expert, then the statement is only true when the expert persona is displayed

This means that correctness is sometimes absolute and sometimes conditional on the learner shown.

For example:

  • A statement that is correct for all learners is always correct when the learner answers True
  • A statement that is correct only for experts is true only when the expert persona is displayed
  • The same statement may be false if the novice persona is displayed

That is what makes the activity more interesting than a simple true/false quiz.

Here are three examples of a dataset record:

Statement is false for all learners
Statement is true for adult_novice
Statement is true for adult_expert

How This Relates to Variables in Storyline and Captivate

In Storyline and Captivate, you would usually model this kind of data using groups of variables.

A variable is simply a named place in memory that holds a value.

For example, if a variable named persona_1 holds the value adult_novice, then when you send the variable’s contents to a text field, you will see:

adult_novice

You will not see the variable’s name. You will see the value it holds.

To understand this more deeply and generally, it helps to look at the equivalent idea in plain JavaScript:

[
  {persona: “Novice”, statement: “…”, correct: true, citation: “…”, feedback: “…”},
  {persona: “Expert”, statement: “…”, correct: false, citation: “…”, feedback: “…”}
]

This is called an array of objects.

Here is what that means:

  • [ ] means an array or list. Notice the [ at the beginning of the above script and ] at the end.
  • { } means an object or record. Notice how each line starts and ends with a curly brace {}
  • persona: “Novice” is a property-value pair

So this code represents a list of records, and each record contains the properties:

  • persona
  • statement
  • correct
  • citation
  • feedback

This way of thinking takes some getting used to. Designers often begin with simple variables, then learn arrays, and eventually become comfortable with objects and datasets.

LodeStar makes this easier, but the underlying idea is the same: we are working with a list of records.


Step Five: Write Scripts

Along with datasets, scripting is often the most intimidating part of building a project like this. It is also one reason relatively few designers go on to create simulations.

Artificial intelligence can help generate script, and LodeStar includes AI-supported scripting, but the designer should still understand the fundamentals.

LodeStar has its own scripting language. It resembles JavaScript but reduces some of the complexity and adds high-level helper functions.

Storyline’s primary scripting model is trigger logic and variables, though JavaScript can be added. Captivate supports JavaScript to varying degrees depending on the version, along with advanced actions and conditions.

In this stepping-stone project, the script is used to:

  • build an array from the dataset
  • initialize the user score
  • evaluate whether the learner’s answer is correct
  • randomize the persona shown
  • get the next item in the queue

That means the designer must work with:

  • variables
  • functions
  • if statements
  • loops
  • arrays

For each of these core concepts, it helps to work through a short tutorial first:

  • Variables

Scripting for Designers: Variables

  • Functions

Scripting for Designers: Functions

  • If Statements

Scripting for Designers: IF Statements

  • Switch Statements

Scripting for Designers: Switch Statements

  • Loops

Scripting for Designers: Loops

  • Arrays

Scripting for Designers: Arrays

A good way to begin is to first watch the short “Scripting for Designers” series and then experiment with small snippets of code.


Adding a Queue

We could simply display records directly from the dataset, but we want one additional feature: spaced repetition.

If a learner answers an item incorrectly, we want that item to be added to the end of a queue so that it appears again later.

That means:

  • the original dataset remains untouched
  • the learner works from a queue array
  • incorrect items are added back into that queue

This is why the queue matters.


The Two Key Lines

At the heart of the initialization script are these two lines:

var statement = getDataSet(“statements”, -1);
addToArray(“queue”, statement);

These lines do the following:

  1. Retrieve a record from the dataset named statements
  2. Store that record in a temporary variable called statement
  3. Add that record to the array named queue

Placed inside a loop, these two lines copy all of the dataset items into the queue. In our example, we hard-coded this to 24. Be sure that you have 24 statements in your dataset.


Initialization Script

Add the following script to the Instructions page:

In the following screenshot, we clicked on the green outlined branch icon, selected the option ‘Execute Command’ and then clicked on the Edit button.  When we finished, we saved each step and then saved the entire project.

var initialized = getValue(“initialized”);
var isNum = isNumber(initialized);

if (isNum == true) {
    message(“Already initialized”);
}
else {
    setValue(“userScore”, 0);
    setValue(“totalScore”, 0);

    for (var i = 0; i < 24; i++) {
        var statement = getDataSet(“statements”, -1);
        addToArray(“queue”, statement);
    }

    setValue(“initialized”, 1);
}


What This Script Does

1. It checks whether initialization has already occurred

var initialized = getValue(“initialized”);
var isNum = isNumber(initialized);

The variable initialized is retrieved from global memory.

If it already contains a valid number, then the lesson has already been initialized.


2. It prevents the initialization from running twice

if (isNum == true) {
    message(“Already initialized”);
}

If initialized is already a number, the script simply displays a message and stops.


3. It initializes the learner’s score

setValue(“userScore”, 0);
setValue(“totalScore”, 0);

These two global variables store:

  • the learner’s score
  • the number of items attempted

4. It copies dataset items into the queue

for (var i = 0; i < 24; i++) {
    var statement = getDataSet(“statements”, -1);
    addToArray(“queue”, statement);
}

This loop runs 24 times.

Each time through the loop:

  • a record is retrieved from the dataset
  • that record is added to the queue array

5. It marks the lesson as initialized

setValue(“initialized”, 1);

This ensures that the next time the page runs, the initialization logic does not repeat.


A Simpler Practice Script

Before using the full initialization script, try this smaller example on a blank page and then show the page once, and then return to the page, showing it twice. The second time, you should see a message ‘Already Initialized’.

Add an Execute Command action and enter:

var initialized = getValue(“initialized”);
var isNum = isNumber(initialized);

if (isNum == true) {
    message(“Already initialized”);
}
else {
    setValue(“initialized”, 1);
}

This is a good first test because it demonstrates how an if statement works.

If the condition evaluates to true, the code inside the braces executes. If it evaluates to false, the else block runs instead. A block is defined by { }

The first time the script runs, initialized will likely be undefined. Since undefined is not a number, isNumber(initialized) returns false, so the else block runs and sets initialized to 1.

The next time the page runs, initialized now equals 1, which is a number, so the condition becomes true and the message appears.

This simple example introduces the idea of conditional execution and persistent global variables.


Step Six: Add Branching in Response to Events

Storyline uses branching primarily through triggers that respond to user actions or timeline events. Authors create triggers such as:

  • when the user clicks
  • when the timeline starts
  • when a variable changes

These triggers can perform actions such as:

  • jump to a slide
  • show a layer
  • change an object state
  • adjust a variable

By chaining these together, Storyline creates a rule-based interaction system that supports branching and simulations.

Captivate uses actions and decision blocks, which feel somewhat more script-like. A designer can create standard or advanced actions that execute when an event occurs. These can include variable assignments, navigation, object visibility changes, and If/Else logic.

LodeStar uses a direct event-driven scripting model. Events can be attached to elements and pages, including:

  • select
  • deselect
  • hover
  • drag
  • drag missed
  • page show
  • timer

Each event can execute script. That script can evaluate variables, learner choices, scores, or interface state and then determine what happens next.

In the LodeStar SVG Editor, the designer can right-click an element, select the relevant event, and then respond to that event by choosing Execute Command.

The most commonly used functions in this project are:

getValue(“continue”);
setValue(“continue”, “true”);

getValue() retrieves a value from global memory.

setValue() stores a value in global memory.

A local variable, by contrast, exists only while the current script is running. Once the script ends, the local variable disappears.

Global variables created with setValue() persist across the lesson.


Add Event Scripts to the Key Interface Elements

For each of the following elements, right-click the element in the SVG Editor.:

  • Continue button
  • Submit button
  • true_area
  • false_area

After you right-click the element in the SVG editor, choose Select Branch Options, choose Execute Command, and then click Edit. Paste in the appropriate code, save it, and save your project.


Code Behind the Continue Button

This script runs when the learner clicks Continue.

Its job is to:

  • advance the queue index
  • load the next item
  • reset the interface
  • randomly select a persona
  • finish the challenge if the queue has been exhausted

if (getValue(“continue”) == “true”) {

    setValue(“continue”, “false”);

    var index = appendValue(“index”, 1);
    var items = getArray(“queue”);

    changeColor(“true_button”, “white”);
    changeColor(“false_button”, “white”);
    setValue(“selectedOption”, “”);

    if (index < items.length) {
        var item = items[index];
        changeText(“question_stem”, item[“Statement”]);
        changeSVGCaption(“feedback”, “”, 730, 106);
        setValue(“currentItem”, item);
    }
    else {
        setCustomUserScore(getValue(“userScore”));
        setCustomTotalScore(getValue(“totalScore”));
        message(“Congrats. You have completed the challenge.”);
        changeSVGCaption(“feedback”, “Congrats. You have completed the challenge”, 730, 106);
    }

    randomNumber = Math.round(1 + random() );

    if (randomNumber == 1) {
        setValue(“currentPersona”, “adult_novice”);
        changeText(“people_characteristics”, “Adult. Novice in subject domain.”);
        changeImage(“persona”, “persona1”);
    }
    else {
        setValue(“currentPersona”, “adult_expert”);
        changeText(“people_characteristics”, “Adult. Expert in subject domain.”);
        changeImage(“persona”, “persona2”);
    }
}

One of the more difficult things to understand is the generation of a random number (1 or 2).

Here is that breakdown. Start from the inner function and move outward.:

random()
This is a function that returns a random decimal between 0 and 1.
For example, it might return:

  • 0.2
  • 0.73
  • 0.99




  1. 1 + random()
    This shifts the random value upward by 1. So if random() returns 0.73, then:

1 + 0.73 = 1.73

that means this part produces a number between:

  • 1.0
  • and just under 2.0

Math.round(...)
Math.round() rounds to the nearest whole number. So:

1.2 becomes 1

1.49 becomes 1

1.5 becomes 2

1.9 becomes 2


What the Continue Button Script Is Doing

The first line checks whether the continue action is currently allowed:

if (getValue(“continue”) == “true”) {

This prevents the learner from skipping ahead before submitting an answer.

The script then immediately disables Continue again:

setValue(“continue”, “false”);

This means the learner must answer the new question before continuing again.

Next, the script increments the current queue index and retrieves the queue:

var index = appendValue(“index”, 1);
var items = getArray(“queue”);

Then it resets the true/false indicators and clears the previous selection:

changeColor(“true_button”, “white”);
changeColor(“false_button”, “white”);
setValue(“selectedOption”, “”);

If there are still items left in the queue, the script loads the next one:

var item = items[index];
changeText(“question_stem”, item[“Statement”]);
changeSVGCaption(“feedback”, “”, 730, 106);
setValue(“currentItem”, item);

If there are no items left, it stores the final score and displays a completion message:

setCustomUserScore(getValue(“userScore”));
setCustomTotalScore(getValue(“totalScore”));

Finally, it randomly chooses a persona and updates both the descriptive text and the displayed image.


Code Behind the Submit Button

It helps to approach the Submit button in two versions:

  • a simplified version
  • an advanced version

The simplified version is easier to learn because it ignores the persona and simply checks whether the learner’s answer matches the dataset.

The advanced version adds context sensitivity by considering the persona shown.


Submit Button: Simplified Version

In the simplified version, there are only two possibilities:

  • the learner’s answer matches the dataset
  • the learner’s answer does not match the dataset

If the learner is correct, they gain a point.

If the learner is incorrect, they lose a point and the item is added back into the queue.

Simplified Truth Table

Correct?User AnswerScoreMeaningAdd Item to Queue
truetrue+1User answers correctlyNo
truefalse-1User answers incorrectlyYes
falsetrue-1User answers incorrectlyYes
falsefalse+1User answers correctlyNo

Before looking at the code, remember these operators:

  • = means assignment
  • == means comparison
  • !== means not equal to (this must be an exclamation point followed by two equal signs)

Now the code:

if (getValue(“continue”) == “false”) {

    setValue(“continue”, “true”);

    var currentItem = getValue(“currentItem”);
    var selectedOption = getValue(“selectedOption”);
    var correctness = currentItem[“Correct”];

    appendValue(“totalScore”, 1);

    if (correctness == selectedOption) {
        appendValue(“userScore”, 1);
        changeSVGCaption(“feedback”, “Well done. This strategy is matched to the learner.”, 730, 106);
    }
    else {
        appendValue(“userScore”, -1);
        changeSVGCaption(“feedback”, “Sorry.”, 730, 106);
        addToArray(“queue”, currentItem);
    }
}


What the Simplified Submit Script Does

First, it checks whether the learner is currently allowed to submit:

if (getValue(“continue”) == “false”) {

If Continue is still false, the learner has not yet advanced, so Submit is valid.

The script then flips Continue to true:

setValue(“continue”, “true”);

That allows the learner to move forward after receiving feedback.

Next, it retrieves three values:

var currentItem = getValue(“currentItem”);
var selectedOption = getValue(“selectedOption”);
var correctness = currentItem[“Correct”];

These represent:

  • the current dataset record
  • the learner’s selected true/false response
  • the correct answer from the record

The script increments total attempts:

appendValue(“totalScore”, 1);

Then it compares the learner’s answer with the correct answer:

if (correctness == selectedOption)

If they match, the learner gains a point.

If not, the learner loses a point and the current item is added back into the queue for future repetition.

That repeated reappearance of missed items is the spaced-practice mechanic.

The changeSVGCaption(“feedback”, “Sorry.”, 730, 106); function replaces the SVG text with id of ‘feedback’ with an embedded HTML element that contains the word ‘Sorry’. We need this to accommodate long feedback. SVG text doesn’t wrap lines; HTML text does. So, in effect, this function swaps the native SVG text element with an HTML element to support text wrapping. The 730 is the x position (from the left) and the 106 is the y position (from the top).


Submit Button: Advanced Version

The advanced version introduces a second layer of logic.

Now the correctness of a statement may depend on the persona shown.

A statement may be:

  • true for all learners
  • true only for a novice
  • true only for an expert
  • false regardless of persona

The learner must therefore evaluate both:

  • the statement itself
  • the context represented by the persona

Advanced Truth Table

Correct?User AnswerPersona ConditionScoreMeaningAdd Item to Queue
truetrueall+1Strategy correctly matchedNo
truetruematch+1Strategy correctly matchedNo
truetruemismatch-1Strategy mismatchedYes
truefalsemismatch+1Learner correctly recognized mismatchNo
truefalseall or match-1Strategy actually matchesYes
falsefalseany+1Learner correctly identified false statementNo
falsetrueany-1Learner incorrectly accepted false statementYes

Now the code:

if (getValue(“continue”) == “false”) {

    setValue(“continue”, “true”);

    var currentItem = getValue(“currentItem”);
    var selectedOption = getValue(“selectedOption”);
    var persona = currentItem[“Persona”];
    var correctness = currentItem[“Correct”];
var feedback = currentItem[“feedback”];

    appendValue(“totalScore”, 1);

    var currentPersona = getValue(“currentPersona”);

    // If the statement is true and the learner answered true,
    // we must check whether the persona matches.
    if (correctness == “true” && selectedOption == “true”) {

        if (persona == currentPersona || persona == “all”) {
            appendValue(“userScore”, 1);
            changeSVGCaption(“feedback”, “Well done. This strategy is matched to the learner.”, 730, 106);
        }
        else {
            appendValue(“userScore”, -1);
            changeSVGCaption(“feedback”, “Sorry. This strategy is mismatched to the learner. ” + feedback, 730, 106);
            addToArray(“queue”, currentItem);
        }
    }

    else if (correctness == “true” && selectedOption == “false”) {

        if (persona !== currentPersona && persona !== “all”) {
            appendValue(“userScore”, 1);
            changeSVGCaption(“feedback”, “Well done. This strategy is mismatched to the learner. ” + feedback, 730, 106);
        }
        else {
            appendValue(“userScore”, -1);
            changeSVGCaption(“feedback”, “Sorry. This strategy is mismatched to the learner. ” + feedback, 730, 106);
            addToArray(“queue”, currentItem);
        }
    }

    else if (correctness == “false” && selectedOption == “false”) {
        appendValue(“userScore”, 1);
        changeSVGCaption(“feedback”, “Well done for recognizing a falsehood”, 730, 106);
    }

    else {
        appendValue(“userScore”, -1);
        changeSVGCaption(“feedback”, “Sorry. This statement is not true.”, 730, 106);
        addToArray(“queue”, currentItem);
    }
}


What the Advanced Submit Script Does

The script begins exactly as the simplified version did, but it now retrieves two additional values:

var persona = currentItem[“Persona”];
var currentPersona = getValue(“currentPersona”);

These represent:

  • the persona required by the dataset record
  • the persona currently displayed on screen

Case 1: The statement is true and the learner answers true

if (correctness == “true” && selectedOption == “true”)

Now we must determine whether the current persona actually matches the statement.

If the dataset says the statement applies to the current persona, or to all learners, the learner is correct.

If not, the learner is wrong and the item is added back into the queue.

Case 2: The statement is true and the learner answers false

else if (correctness == “true” && selectedOption == “false”)

This may still be correct if the displayed persona does not match the one required by the statement.

In other words, the learner may be correctly recognizing that the strategy is mismatched to the learner shown.

Case 3: The statement is false and the learner answers false

else if (correctness == “false” && selectedOption == “false”)

That is a straightforward correct response.

Case 4: Everything else

The final else catches the remaining incorrect case, where the learner accepted a false statement.

This version of the script is much closer to the logic used in a simulation, because correctness depends on context rather than on a fixed answer alone.

The following line might be confusing;

changeSVGCaption(“feedback”, “Well done. This strategy is mismatched to the learner. ” + feedback, 730, 90);

What this means is that we are appending the feedback from the dataset to the words ‘This strategy is mismatched to the learner’. The + operator in this context doesn’t add numbers. It adds one string of characters to another.


Code Behind the True Area

When the learner selects True, we want two things to happen:

  • the true indicator changes color
  • the selected option is stored in memory

changeColor(“true_button”, “green”);
changeColor(“false_button”, “white”);
setValue(“selectedOption”, “true”);

This makes it visually clear which option is selected and gives the Submit button something to evaluate.


Code Behind the False Area

The false selection works the same way:

changeColor(“false_button”, “green”);
changeColor(“true_button”, “white”);
setValue(“selectedOption”, “false”);


Composition of the True and False Areas

The true_area grouped element consists of:

  • a circle with the ID true_button
  • a rectangle
  • a text object

The false_area grouped element is similar:

  • a circle with the ID false_button
  • a rectangle
  • a text object

This is a useful design pattern because the learner clicks the grouped area as a whole, while the script changes the color of just the inner circle.


One Last Thing: Pre-Populate the Interface

To avoid confusion, it helps to pre-populate the interface with the first statement and place the buttons in the proper initial state.

We want:

  • the first statement to already be visible
  • a persona to already be visible
  • Continue to be disabled initially
  • Submit to be available

Add the following script through the page-level branch option:

setValue(“continue”, “false”);
changeCSS(“continue_button”, “user-select”, “none”);
changeCSS(“submit_button”, “user-select”, “none”);

var items = getArray(“queue”);
var item = items[0];

changeText(“question_stem”, item[“Statement”]);
changeSVGCaption(“feedback”, “”, 730, 106);
setValue(“index”, 0);
setValue(“currentItem”, item);

randomNumber = Math.round(1 + random() * 1);

if (randomNumber == 1) {
    setValue(“currentPersona”, “adult_novice”);
    changeText(“people_characteristics”, “Adult. Novice in subject domain.”);
    changeImage(“persona”, “persona1”);
}
else {
    setValue(“currentPersona”, “adult_expert”);
    changeText(“people_characteristics”, “Adult. Expert in subject domain.”);
    changeImage(“persona”, “persona2”);
}


What This Initialization Script Does

This script is essentially a first-run version of the Continue button logic.

It does the following:

  1. Sets continue to false so the learner cannot continue immediately
  2. Retrieves the first item from the queue
  3. Displays the statement in the question stem
  4. Clears feedback
  5. Stores the current item in memory
  6. Randomly selects and displays a persona

This makes the interface feel ready as soon as the learner arrives.


Step Seven: Report Learner Performance

LodeStar, Storyline, and Captivate all support common standards for reporting learner performance.

These typically include:

  • SCORM 1.2
  • SCORM 2004
  • xAPI
  • CMI5

SCORM 1.2 is the oldest and most widely supported. xAPI and CMI5 are generally more flexible and powerful.

In LodeStar, simply adding a Report Page allows the project to report performance when it is exported as a SCORM package and imported into a Learning Management System.

In the LodeStar Web Journal, we have also written separately on xAPI and CMI5 for those who want more advanced reporting options.


Conclusion

There is a good chance that you ran into a roadblock somewhere along the way. That is normal.

Building a project like this for the first time is challenging because it introduces several foundational concepts all at once:

  • datasets
  • variables
  • arrays
  • events
  • conditions
  • dynamic interfaces
  • repeated practice

But this is exactly why it is a useful stepping-stone project.

Once you understand these mechanics, you are no longer confined to form-based templates. You can begin building interactions from scratch that reflect the design you actually want to create.

That is the heart of Freedom to Design.

A project like this is still small, but it points toward a much larger possibility: simulations, contextual challenge activities, branching scenarios, and learner experiences that are shaped by design rather than by template.

Keep at it. Once these fundamentals become comfortable, you will be able to create a wide range of projects from scratch.

Friction in eLearning

By Robert N. Bilyk

Introduction

I design happily with a set of assumptions and understandings about how learners learn; and then periodically, I step back and challenge those assumptions.

Recently, I designed an eLearning module for my Strategies for Learner Experience Design course.  It was essentially a simulation, and the intent of the simulation was for student designers to dive into a company, understand its business goals, interview employees, review tech notes and so forth, in order to select the training objectives that would help move the needle toward fulfilling the company’s goals.  In this example, the business goal was to reduce the number of times technicians needed to be dispatched to solve customer problems (i.e. reduce truck rolls). 

The eLearning simulation randomly picks a scenario.  In Michael Allen’s terminology this was the ‘context’ in a Challenge-Context-Activity-Feedback (CCAF) learning interaction.  The challenge was to pick the correct training outcomes that would help employees reduce truck rolls.  The activity included reading notes, interviewing employees, talking to HR, learning about the company’s business, and so forth.  Given the employees’ prior knowledge (prior training), their motivation, their practices, etc., my students needed to select the right training outcomes.   They received feedback based on their choices and could apply that to another randomly chosen scenario.

I had students from another course evaluate the module.  They liked some aspects of the module and disliked other aspects.    One of the complaints was that I didn’t tell them about the company and how it operated up front.  For the students, this presented what Carl Hendrick calls ‘friction’ in his article entitled ‘Why most education apps fail’.  But in my defense, in real life, no one hands you that information on a silver platter to any useful degree.  The company employees enjoy ‘unconscious expertise’.   They don’t fully appreciate how much a visitor to their operation does not know.  So that’s the point.  In this activity, the student must ask questions or probe a little to understand the company’s operations and much more.  Just like in real life.   But in this instance is the friction caused by simply not telling students worth it?  Do students benefit from working a little harder?  Or will they find the activity of interviewing employees, reading notes, etc. tedious and not worth the effort? In fact, why bother with the simulation at all? 

I could have simply constructed a lesson that showed strong alignment between company goals, training objectives, assessments and activities.  That would have taken much much less time than constructing this simulation.  Was a simulation worth the effort?  Would it improve long-term outcomes?

That led me on an investigation.

Duolingo and Friction

I’m reminded of Duolingo.   For the uninitiated, Duolingo started as a language app.  I’m currently on a 400 day streak, learning French.  Duolingo wants you to return day after day.  The company reduces friction to encourage me to return, build my streak and maintain my paid subscription. 

So, let’s look at friction in Duolingo.  In the app, I notice how easy it is to match words.  It is even easy to fill in the blanks or convert French to English.  However, when I’m asked to compose an entire French sentence based on English, I struggle.  My five-minute lesson expands in time.  My frustration level rises.  I’m experiencing friction.  And yet, that is real life.  If I am to learn the language, I must be able to compose a sentence in French.  That action requires me to use the right vocabulary, syntax and verb conjugations.  That is a lot.  I noticed that Duolingo doesn’t ask me to do that very often.  At least not at the novice level.

So again, is that friction worth it?  It seems like it is – at least to a highly motivated life-long learner.  But what does the research tell us?

In Rethinking elearning what works. what doesn’t. what’s missing. 2, Michael Allen tells us that “Learning is a process requiring energy and effort, regardless of the instructional paradigm” 

Related to eLearning design, he writes:

“Challenge First.  To convey relevancy of the training to come, actively engage learners, and to determine how best to assist them in their personal learning journey, avoid jumping immediately into content delivery and provide a context-based challenge.”

“…the initial learning experience should NOT be a content presentation nor even an introduction as is common practice.”

In diving deeper into challenge, I came across Manu Kapur who coined the phrase ‘Productive Failure’. 

In one of his experiments, two groups of students learned a new math concept.  The operative word here is concept.   The first group was given instruction first.  A teacher explained the concept; students then practiced the concept.  The second group was asked to try and solve a math problem related to the concept.  They failed, and a teacher explained the concept.  This was struggle-first. The second group had almost no chance of solving the problem correctly at first. They struggled. They were confused. They got answers wrong.

On immediate tests the instruction-first group looked better. But on deeper understanding and transfer tests, the struggle-first group significantly outperformed the instructed group.

Manu Kapur offers an explanation: when learners attempt solutions first, they activate prior knowledge and build mental frameworks. Failure prepares the brain to learn.

Does this seem to support unguided discovery learning, challenge-first, and other approaches that promote healthy cognitive dissonance?    Should we design failure into eLearning activities and then provide the feedback and resources to rescue the learner?

I now turn to other research. In ‘Cognitive Load During Problem Solving:Effects on Learning’3, John Sweller looked at the cognitive load during problem solving exercises and their effect on learning.  In his research, learners studied algebra/geometry problems under two conditions:  The first group was the problem-solving group.  They solved conventional problems step by step.  The second group was the worked-example group.  They first studied worked solutions.

Both groups spent the same amount of time and saw the same material.  Sweller discovered that the students who practiced solving problems, worked harder, were more engaged, spent more effort, but they learned significantly less than students who studied worked examples. In Sweller’s words ‘Conventional problem-solving activity via means-ends analysis normally leads to problem-solution, not to schema acquisition.’ It is the acquisition of schema that allows problem-solvers to pick the solution path that is much like the other ones they encountered and solve future problems.

For years, we heard about the virtues of discovery learning and problem solving.  But Sweller showed that the opposite was true for novices. The mental effort of searching for a solution consumed working memory, preventing learning.

If we were to design instruction bearing this in mind, we might provide

  • worked examples
  • guidance fading

Why this matters for eLearning

This Sweller experiment demonstrated that effort alone does not cause learning. Beginners should not be thrown into unguided simulations. They need structured guidance first, then challenge later.

Let’s look at another experiment that examines effort in a different way.   In YouTube4 or in journals such as the Journal of Experimental Psychology, you will find references to the generation effect.

Here is an example of a generation-effect experiment.

Subjects studied word pairs under two conditions.   In the ‘read’ conditions, learners read words and then recalled them later.   In the second condition, the ‘generate’ condition learners had to complete a word in a fill-in-the blank style.  In the first group, learners read words like machine and banana.  In the second group, learners generated a word from ma_hine or ba_an_  In other words, they filled in the blanks and ‘generated’ the word.  They expended more effort and that helped them recall the word later.   In short, learners recalled a few more words when they were required to generate the words rather than just read them.  The same positive outcome occurred whether the effort required learners to fill in the blanks, unscramble letters, or find the antonym such as in hot:____.  The effort paid off. Generating an answer produced stronger memory than studying the answer.  Learning improves when the learner must think rather than receive.

From the generation effect, we might consider that:

  • questions beat explanations
  • scenarios beat slides
  • prediction beats instruction
  • decision beats presentation

And importantly, participants often felt learning was harder in the generation condition — yet learned more.  The brain remembers what it had to work to produce.

Aren’t these ideas contradictory?

On one hand we have the notion of desirable difficulty, generation and discovery where learning improves when learners struggle productively.  On the other hand, we have worked-examples, explicit instruction and scaffolding where learning improves when learners are taught directly.  At first glance these look mutually exclusive. They’re not.

In my view, here is where the role of learner analysis is paramount.  Learner analysis is at the heart of learning experience design.  After all, it’s all about the learners.

In my courses, I can categorize the students into personas.  One persona is the working teacher.  Learner Experience Design courses attract teachers who want to understand how learning works or who want to apply their passion to work outside of the classroom to a new vocation.  They want to become designers.  Another persona is the corporate trainer.  This student is already employed and is already serving in a learning and development role.  They have experience; they want to get better.  A third persona is the undergraduate.  At our university, upper division students can elect to take graduate level courses.  In this case, the persona has almost no prior knowledge or experience in instructional design.

This calls for different treatments for different people.  At the very least, this calls for options for students, which match their prior knowledge and motivation.  (After all, isn’t that one of the promises of eLearning: individualization)

The apparent (surface-level) contradiction of these experiments and theories disappears when you add one variable: prior knowledge.  In short, the same instruction can help a novice or harm an expert; or help a student and hinder a gifted student; or discourage one student and motivate another.

When learners don’t yet understand the domain, the brain has no schema (i.e. organization of knowledge) to think with.  When learners are simply exploring the domain and haven’t committed to mastering it, they may not be ready to expend the effort that is required for long term transfer.

So, what happens if you ask novices to discover and figure out things on their own? They search blindly.  Their working memory is overloaded, which leads to confusion and misconceptions.

But what happens when learners have prior knowledge and experience.  The situation can flip. Now if you keep explaining everything, the learner stops thinking. This produces passive processing, illusion of competence, and poor long-term transfer.

Conclusion

Friction can overheat and break things down, or it can spark an understanding that outlives the course.   It is an element that a designer can dial up or turn down based on the prior knowledge and motivation of students.  

This bodes well for the role of the learning experience designer.  Designing instruction isn’t formulaic.  It isn’t a process that guarantees results regardless of the learner.   Nothing messes up a perfect design like the learner.  

When a learning experience designer has done their homework and uses tools like personas, empathy maps, learner journey maps, and the LXD canvas, they can dial up or down the friction, the discovery, the explicitness, the problem-solving, and the effort – all for the benefit of their learners.  That is Learning Experience Design!

Resources

  1. https://carlhendrick.substack.com/p/why-most-education-apps-fail
  2. Allen, M. W. (2026). Rethinking elearning what works. what doesn’t. what’s missing. BenBella Books.
  3. Sweller, J. (1988). Cognitive load during problem solving: Effects on learning. Cognitive Science, 12(2), 257–285. https://doi.org/10.1207/s15516709cog1202_4
  4. Youtubers tested the generation effect. Did it work?

What Ten Years of Geolocation Storytelling Has Taught Us

Introduction

Geolocation storytelling blends narrative, place, and technology into a learning experience that is both memorable and deeply engaging. By tying stories to real-world locations, authors invite learners to move through landscapes, communities, and history while meaningfully interacting with content. Over the past ten years of producing geolocation stories, we have learned that their power lies not in technical complexity, but in creativity, curiosity, and connection to place.

In this article, we share some of our key insights from a decade of practice—what makes geolocation storytelling effective, why the process itself is so engaging for authors and students, and how these stories can be created and published at a range of technical levels. Along the way, we highlight examples from ongoing projects and suggest ideas that educators and students can adapt to their own communities.


Why the Process Is So Engaging

eLearning projects often introduce us to new ideas, new environments, new challenges, and new people. Geolocation storytelling amplifies that sense of discovery. The process is not only intellectually engaging—it is genuinely fun, for authors of any age. Researching locations, visiting sites, and deciding how best to interpret them through story creates a powerful sense of ownership and curiosity.

I am currently re-living that excitement through a project that geolocates the settings of several paintings by the Group of Seven. These Canadian painters, whose work focuses on the Canadian landscape, were introduced to me late in my schooling—only in my senior year (Grade 13 in Ontario). Until then, my education focused largely on British, American, and European history and art. Discovering Canadian art felt like uncovering a hidden treasure. My imagination was transported from Toronto to the Canadian Shield, Georgian Bay, Lake Superior, and beyond.

That sense of rediscovery has returned as we map where key Group of Seven works were painted. The interactive map allows users to “drop in” on these locations and view the landscapes that inspired the paintings, including sites along Georgian Bay, Lake Superior, and in the town of Cobalt. The story emerges from the land itself.1

A work in progress: Group of Seven Canadian Paintings geolocated in Northern Ontario

A similar long-running project is LensFlare Stillwater, now in its tenth year. Bob Molenda has authored numerous free geolocation stories that guide users through the historic town of Stillwater and surrounding communities, demonstrating how local history can be brought to life through place-based storytelling.

LensFlare Stillwater Site Inspired by Bob Molenda

We are also in our seventh year of offering the Van Gogh in Arles tour across multiple platforms, including Google Play and the App Store, further reinforcing the longevity and adaptability of geolocation stories.

Van Gogh In Arles available on the AppStore and in Google Play

Keeping the Technology Simple

One of the most important lessons we have learned is that the challenge of geolocation storytelling is not a technical challenge; it is a creative one. The goal is to let the experience of being in a place take precedence. The story should add meaning and context without distracting from the location itself.

At its core, a geolocation story can be built using a small number of elements: images, narration, and geographic coordinates. For example, in our Group of Seven project, we feature Pic Island by Lawren Harris, painted on the north shore of Lake Superior within view of Neys Provincial Park. The location is defined by its latitude (48.776450) and longitude (-86.585037). When a user approaches this location, the image is displayed and the narration begins.

In our LodeStar eLearning authoring tool, authors work within a specialized template that allows them to enter the coordinates and define how close a visitor must be before the content is triggered. Each location becomes a page in the story, preferably activated by presence rather than clicks.

Entering latitude and longitude on a Geolocation Page with the LodeStar eLearning Authoring Tool

In the Group of Seven application, users will be encouraged to travel to locations across Georgian Bay and Northern Ontario and receive credit for physically visiting the sites. Alternatively, students will be able to explore these locations virtually using maps and street view.  (Not everyone can travel north of Superior.) While virtual visitors gain insight into the landscapes and paintings, only those who travel to the actual locations receive recognition —rewarding real-world exploration without excluding remote learners.


Student Authors and Community Stories

Geolocation storytelling is particularly powerful in educational settings because it adapts easily across grade levels. The technical process remains simple, allowing students to focus on observation, research, and storytelling rather than software complexity.

Students can explore and write about their own communities—examining population, geography, geology, wildlife, history, and cultural landmarks at an age-appropriate level. With support from their schools, they can publish these stories online and instantly share them with classmates, families, and the broader community. This sense of audience transforms student work from an assignment into a contribution.


Creative Approaches to Geolocation Storytelling

Geolocation storytelling uses place as an active part of the narrative rather than a passive backdrop. One approach pairs poetry with artwork, monuments, or sculptures, unlocking poems only when learners arrive at a specific site. Experiencing poetry in front of the artwork encourages close observation, emotional engagement, and interpretation.

Another approach treats locations as story nodes. Sculptures, buildings, or landmarks reveal fragments of a larger narrative—different voices, perspectives, or moments in time. Because the story unfolds non-linearly, learners must synthesize information as they move through space.

Geolocation also lends itself naturally to gamification. Scavenger hunts and exploration challenges encourage learners to solve riddles, examine their surroundings, and unlock content by physically visiting places. Matching poetry to sculptures, identifying architectural details, or uncovering historical clues turns movement and observation into meaningful learning activities.

Together, these approaches transform campuses, museums, neighborhoods, and cities into interactive learning environments that are difficult to replicate in screen-only experiences.


Publishing Geolocation Stories

There are two primary ways to publish geolocation stories: as HTML-based apps or as iOS and Google Play apps.

Converting an HTML-Based App to an IOS and Android App

HTML-Based Apps
HTML-based publishing is the most accessible option. Stories can be uploaded to an institutional learning management system (as SCORM or CMI5) or a school web server with the help of IT. A more flexible alternative is publishing through a GitHub repository, where stories can be made publicly accessible while keeping source files private with a modest subscription to GitHub Plus. We are also exploring one-click publishing of geolocation stories directly to the Inspire Learning Management System.

iOS and Google Play Apps
Publishing to app stores is more complex. It involves converting an HTML-based experience into a mobile application and navigating platform-specific requirements for iOS and Android. LodeStar Learning is currently working with partners on several such projects and can facilitate the process of publishing to the App Store and Google Play.

Conclusion

Geolocation storytelling reminds us that learning does not need to be confined to classrooms, screens, or linear paths. By anchoring stories to real places, authors and learners engage more fully—with landscapes, communities, history, and one another. Whether the experience involves standing before a sculpture, walking a historic street, or virtually exploring a distant shoreline, place becomes an active participant in the story.

Over ten years of creating geolocation stories, we have learned that their success depends far less on technical sophistication than on thoughtful design and curiosity. Simple tools, when paired with meaningful narratives, can produce rich, memorable experiences for authors and learners alike. For student authors in particular, geolocation storytelling offers a powerful way to observe their world, articulate what they discover, and share those insights with a genuine audience.

As technologies and publishing options continue to evolve, the core promise of geolocation storytelling remains the same: it invites us to slow down, look closely, and connect learning to the world around us. Whether published as a web-based experience or a mobile app, geolocation stories open the door to learning that is experiential, interdisciplinary, and deeply human.

Appendix

1LodeStar Learning is currently seeking permissions from Canadian art galleries to use the Group of Seven works.  The McMichael Canadian Art Collection – a beautiful gallery in Kleinberg, Ontario – has helped us identify the rights holders to each of the works in the proposed app.

3Di: Discover, Discuss, and Decide with the help of xAPI

Robert N. Bilyk
President, LodeStar Learning Corporation

Introduction

The 3Di strategy motivates learners.  It engages them in discovering or learning about something; conversing asynchronously with other ‘real’ people (not AI chatbots); and then making a decision based on what they’ve learned from both the material and from others.

I’ve written about the 3Di model in the past, but I’ll elaborate further.  3Di is a learning experience strategy that places the learner in an environment where they discover things by uncovering information, exploring, testing, and playing.   From that discovery, they will arrive at some conclusions and possibly identify and make some assumptions about principles and concepts.  The discussion phase then allows the learner to test their assumptions.  They may converse with others in a chat room, video conferencing, or whatever, and share their insights, learn from others and be better prepared for the next step, which is to decide.  The 3Di environment places them in a situation where they must draw from their knowledge and make decisions.

But wait.  Organizing a discussion may seem a little disconcerting.   For some, organizing a chat room or video conferencing to support this instructional model may be clumsy and, in the example I’m about to show, a little bit complicated.  The example, called the LXD Challenge, randomly selects a scenario.  Learner A may be uncovering the facts of Scenario 1, while Learner B may be working with Scenario 9.  They will have nothing in common to discuss – the facts are different.

Here is where xAPI comes to the rescue.

The LXD Challenge created with the LodeStar authoring tool

A little background

Our example is an adapted version of the LXD Challenge, which I’ve written about before.  In a nutshell, this module challenges the learning experience designer to choose appropriate objectives based on what they learn.  The general situation is that the learner has been hired by a Solar Panel Company to accomplish the business objective of reducing truck rolls.  A truck roll happens when customer service can’t solve the customer problem over the phone and must dispatch a truck and technician to fix the problem.   Truck rolls are expensive. Many problems can be solved over the phone and yet, at this company, customer service isn’t succeeding in solving problems and reducing truck rolls. 

The LXD Challenge randomly picks a scenario and presents that to the learner-designer in the form of short videos, instrument metrics, tech notes, and HR conversation.  All of the scenarios relate to problems that training can address.  In other words, the reality of the situation changes based on what scenario is randomly picked. The designer must decide on the root problem and pick the objectives that will address the problem.   In one scenario it might be lack of generalized problem-solving techniques; and in another scenario it might be lack of knowledge of the support tools.  The underlying problem is only disclosed to the designer through the interviews, tech notes, and instrument readings.

Discover information by Interviewing stakeholders, examining instrument readings, reviewing tech notes

I’ll get into more detail as I show how discovery, discussion and decision play out in the challenge.

Discovery: How it works

Interview the L&D Director

In the background, the module randomly picks a scenario.  The learner’s challenge is to figure out what underlying problems the scenario represents. The learner does this by interviewing the L&D director, the first tier Technicians, and the Dispatcher.  The learner can also look at the instrument levels (for example usage of the Knowledge Management System), field tech notes, and interview HR over the phone.

Discussion: How it Works

The discussion forum is restricted to the chosen scenario.  Learners only read what their colleagues have shared about the current scenario.   Learners enter into the discussion with some ideas about what they heard, read, and viewed.   They might conclude that the techs have been trained on basic problem solving but they don’t how to use the Knowledge Management System or how to collect information from the customer.   

Based on this discovery, they will form a hypothesis or an assumption and then share that in the discussion forum that follows.   They might share that the usage of the KMC is low and that techs may not know how to use the KMC or even how the tool can be helpful. Once they post, they will view other comments.  If the comments agree with their point of view, they can take the next step with confidence.  If the comments don’t agree, the learners might experience some cognitive dissonance and question their own observations – or double down and collect the evidence to support their hypothesis. 

Discuss findings with colleagues with the help of xAPI

Decision: How it Works

For the decision-making step, the learner is confronted with row upon row of possible objectives.  If the learner chooses correctly, they get awarded points.  If they choose incorrectly, they get docked points.   There is no penalty for entirely omitting an objective. 

Once they have decided, the learner is presented with a markup of their choices and total score.

Decide which objectives apply

The Discussion Board Mechanics

The discussion phase of 3Di is one that I’ve thought a lot about over the years.  I’ve experimented with Peer to Peer communications and contemplated other solutions.  

To make this as simple and as integrated with the module as possible, we developed the discussion widget.   The widget communicates to an xAPI Learner Record Store.  Posts are written to and read from the Learner Record Store.

Briefly, a Learner Record Store (LRS) is a database system designed to store and retrieve learning activity data generated by xAPI (Experience API) statements.

xAPi is an easy technology to use.  The designer does not need to create the database system.  The databases are created by companies that offer Learner Record Stores as a service.  One just needs to configure xAPI properly.  All of the magic happens under the hood. 

The author simply needs to supply the tool with an LRS endpoint (location), an LRS key, and LRS secret.  (This information is supplied to the author by the Learner Record Store provider.) For this example, I am using the Veracity LRS, which works very well.

To set up the discussion, the author spells out a forum name (this can be any name), and a topic variable.  In this example, the topic variable refers to a variable called ScenarioID. By passing the variable name to the discussion widget, we’re asking the widget to connect us to the discussion that matches the scenario ID. 

Scenario ID is used to place students in a discussion forum for a specific scenario

To make this work, the forum name is joined to the scenario ID to form an activity name that is specific to this scenario and to this group of students.

So, in short, each discussion post becomes an xAPI statement tied to a specific scenario.

From the author’s view, this is nothing more than filling out a simple form with some values.  The authoring tool then uses this information to find the right LRS in the universe and add a statement to the record store.

For the benefit of the tinkerer, the authoring tool is producing the statement shown in the appendix.  This is gobbledygook communication that is happening under the hood.  The key parts of the communication are:

Actors.goode@gmail.com

Verb:  shared

Activity: urn:org:lodestarlearning:activity:LXD_Challenge_9
(9 being scenario 9)

Object: Use of KMC and Dashboard is moderate.

After the learner posts an observation, the widget then polls the LRS for all statements that match the activity name and displays that to the learner.

Summary of 3Di: Discover, Discuss, and Decide

The 3Di strategy is an instructional model that engages learners in three stages: Discover, Discuss, and Decide. It begins with discovery, where learners actively explore information, uncover facts, and test ideas in realistic scenarios. Next, they move into discussion, where they share insights, test assumptions, and learn from peers in a collaborative space. Finally, they decide—making informed choices that reveal their understanding and earn feedback through scoring.

An example is the LXD Challenge, where learners play the role of a learning experience designer for a solar panel company. The challenge randomly assigns scenarios such as low tool usage or poor problem-solving skills. Learners investigate by interviewing stakeholders, reviewing metrics, and examining tech notes. They then discuss their findings with others working on the same scenario, using an xAPI-enabled discussion widget (built right into the lesson) that connects to a Learner Record Store (LRS). This ensures conversations are scenario-specific, relevant, and persistent.

The final step asks learners to choose objectives that address the root problem. Correct choices are rewarded, while incorrect ones reduce the score. This model not only promotes active exploration and peer learning but also develops decision-making skills tied to real-world problems.

In short, 3Di leverages modern learning technology (xAPI and LRS) to support a structured yet dynamic process where learners discover knowledge, test ideas through discussion, and apply their understanding in decision-making.

Appendix

This what an xAPI statement looks like under the hood. It is JSON (Javascript Object Notation) that spells out actor, verb, object, and a specific activity name that was derived from the forum, and the scenario ID. The statement is generated automatically by the authoring system.

{

  “id”: “e038414c-8768-43d3-af19-5801dcd9c745”,

  “timestamp”: “2025-09-19T22:18:09.593Z”,

  “actor”: {

    “objectType”: “Agent”,

    “mbox”: “mailto:s.goode@gmail.com”

  },

  “verb”: {

    “id”: “http://adlnet.gov/expapi/verbs/shared&#8221;,

    “display”: {

      “und”: “shared”

    }

  },

  “object”: {

    “id”: “urn:org:lodestarlearning:activity:LXD_Challenge_9”,

    “objectType”: “Activity”,

    “definition”: {

      “name”: {

        “en-US”: “Use of KMC and Dashboard is moderate.”

      },

      “description”: {

        “en-US”: “name: shared value: Use of KMC and Dashboard is moderate.”

      }

    }

  },

  “stored”: “2025-09-19T22:18:08.498Z”,

  “authority”: {

    “objectType”: “Agent”,

    “account”: {

      “homePage”: “https://lxd-challenge.lrs.io/keys/LXD_Challenge&#8221;,

      “name”: “LXD_Challenge”

    }

  },

  “meta”: {

    “_id”: “019db60”,

    “id”: ” 1dcd9c745″,

    “request”: {

      “session”: “2a910909-c0fd-4265-9927-b47f60”,

      “sequence”: 1,

      “useragent”: “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36”,

      “ip”: “104.27.208.240”,

      “referer”: “http://127.0.0.1:59224/&#8221;,

      “origin”: “http://127.0.0.1:59224&#8221;,

      “host”: “lxd-challenge.lrs.io”,

      “method”: “PUT”,

      “protocol”: “https”,

      “xhr”: false

    },

    “agent”: [

      “mailto:s.goode@gmail.com”

    ],

    “verb”: [

      “http://adlnet.gov/expapi/verbs/shared&#8221;

    ],

    “activity”: [

      “urn:org:lodestarlearning:activity:LXD_Challenge_9”

    ],

    “registration”: [],

    “relatedAgents”: [

      “mailto:s.goode@gmail.com”,

      “bc296bc1e9018c41df8279b91c91dd5ddd1efc74”

    ],

    “relatedActivities”: [

      “urn:org:lodestarlearning:activity:LXD_Challenge_9”

    ],

    “voided”: false,

    “voids”: null,

    “responseDisplay”: “”,

    “language”: “en-US”,

    “es”: false,

    “parent”: null,

    “provisional”: false

  }

}

Parameter-Driven Simulations

Robert N. Bilyk
President, LodeStar Learning Corporation

Introduction

In eLearning, the word simulation is used in many ways—from simple role-plays to high-end virtual reality. But when you want learners to tweak parameters and see results,  you need a parameter-driven simulation.

A parameter-driven simulation is an interactive learning activity where learners can manipulate input variables (parameters)—with sliders, buttons, or numeric fields—and then observe the resulting system behavior. The purpose is not only to “see what happens,” but also to understand the relationships between inputs and outputs, often reinforcing cause-and-effect reasoning or systems thinking.

Why simulations?

Parameter-driven simulations in a guided discovery environment can promote learning in ways that text, video, and animations cannot.  They allow learners to ask ‘what if?’ questions and see the results immediately.  They allow learners to experiment in a safe environment where time is collapsed into a few minutes or seconds so that learners can get immediate feedback for their choices.

An Example

In one of my earliest experiences as a designer, I was asked to create a fully interactive simulation of the secondary wastewater treatment process.  You may be thinking ‘yuk’, just as I did, but eventually I found it fascinating.   Wastewater goes through stages of treatment.  In the secondary stage, biological processes (microorganisms) break down dissolved organic matter, reducing pollutants like nitrogen and phosphorus.  So, it’s basically bug-farming.  If you think Farmville is fun, you should try bug-farming in a wastewater plant.    The learning goal was to make secondary treatment as efficient as possible.  There are so many parameters.  Tweaking those parameters is what a plant operator does.

In the case of wastewater treatment, a simulation allowed trainees to control variables like the amount of incoming waste, types of microorganisms  in the biomass, oxygen, nutrients, level of ammonia, and other things.  They see the results of their tweaks to the system in seconds rather than in days.   If they make the wrong decisions, the consequences are dramatic.  Wastewater foams up and overflows – often spilling untreated water into a clean waterway.  As importantly, trainees can tweak one thing at a time and see cause and effect rather than make changes in the real world to a dynamic system, struggling to understand the consequence.

A diagram of the wastewater treatment process. The sludge gets directed to an incinerator, another process that I simulated.

Working with Subject Matter Experts

I knew very little about wastewater treatment before I joined a civil engineering company.  But that’s the thing.  I never thought I could get excited about wastewater or many of the subjects that I tackled over the years.  That’s the fun part about being a designer.  You get introduced to worlds you never even contemplated.

So let’s be clear.  I’m not a civil engineer.  As designers, we’re often thrown into muddy waters (or wastewater 😊 ) where we have little knowledge of the content.  That’s where subject matter experts (SMEs) come in.  In the case of secondary wastewater treatment, I was paired with an expert who came into the project as a consultant.   He had deep and precise knowledge of the system.  The challenge was how to translate his knowledge into a working simulation.

Simulations often require equations.  I had the SME create an Excel spreadsheet with all of the inputs, outputs, and formulas.  Once we had the spreadsheet calculating the correct outputs from the inputs, I had a model that I could work with.  If we could get it right in the spreadsheet, I could get it right in the authoring tool. I just needed to convert the Excel formula language into the authoring tool’s scripting language.  At the time, the tool of choice was Authorware with its Pascal-like scripting language.

We’ll return to engineering, formulas, scripts, and all of that later.  Let’s look at simulations from a higher vantage point.

Guided versus unguided discovery

The use of simulations may bring up the question of guided versus unguided discovery.  In guided discovery, learners use the simulation to answer questions or solve problems, but with scaffolding, hints, feedback, worked examples, or prompts provided by the expert or system.  Cognitive load is managed; misconceptions are corrected early; exploration is purposeful.

In unguided discovery, learners are expected to figure things out largely on their own, with little or no scaffolding support.  Researchers tell us that this doesn’t work, especially for novice learners.1  For advanced learners, unguided discovery may promote learner autonomy, curiosity, and self-directed construction of knowledge. For novices, it’s just a muddle.

Simulations can be hosted in a highly guided discovery learning module.    One technique is for the learner to arrive at their own conclusions and check them against the expert or system.  Specific feedback is paramount.

Predator-Prey Model: A working example

For years as Metro State’s director of the Center for Online Learning, I routinely introduced faculty to a tool called InsightMaker and discussed how the tool could be used to create simulations.  One of my favorite simulations was the Isle Royale simulation of wolf and moose populations.

Let me set the context and tell you a little about Isle Royale.

An island on Lake Superior, Isle Royale is home to the Wolf-Moose Project, Briefly, the project is the longest-running predator–prey study in the world.  Over decades, populations have shown dramatic fluctuations rather than stable equilibrium.  Moose have ranged from approximately 500 to 2,400 head.  Wolves have swung from highs near 50 to lows as few as 2.

Educators have modeled the predator-prey cycles inside of InsightMaker with the help of its stocks and flows.  A stock is a running count of the moose or wolf population in a snapshot of time.  A flow is how we add to that stock or deplete it. 

Here is what we see in InsightMaker.

Predator-Prey model in InsightMaker

If you looked at the stock of ‘Moose’ in the light blue box, you can see that for every increment of time (e.g. tenth of a year) the stock is being added to by moose births and depleted by moose deaths.   The number of moose impacts the wolf birth rate because that number is used inside the wolf birth rate formula (a flow) where more prey means more food and, therefore, higher reproduction.  The higher the birthrate, the more the wolf stock gets increased.  The increase of wolves then affects the moose death rate, which depletes the moose stock.  When the moose get killed off, that adversely affects the wolf birth rate so that we eventually see a drop in the wolf population.

This is the output of InsightMaker.  It graphs the rise and fall of both the moose and wolf population.  Setting disease and catastrophic events aside, this graph generally resembles the historical data.

The graph plots the dramatic swings in both the wolf and moose population

Isle Royale is a unique ecological laboratory—one of the rare places where one predator (wolves) and one herbivore (moose) interact in isolation, free from significant human influence.

Neither moose nor wolf were native to the island. Ecologists think a small group of moose swam across Lake Superior from the Ontario mainland, about 20 km (12 miles) away.  A small pack of wolves crossed to the island via a frozen ice bridge that occasionally forms in harsh winters between Isle Royale and the Minnesota/Ontario shoreline.

One would expect the populations to achieve a sort of equilibrium, but that is not what happens.  That is what the learner discovers:  No matter the initial parameter inputs, the system settles into in an oscillating pattern for both populations.

In summary, InsightMaker models the fluctuations with a classic predator–prey system.We’re going to do the same but in our own tool. 

Building a simulation step by step

Let me break down the construction of a simulation step by step. I built the Isle Royale simulation with the LodeStar authoring tool, but I’ll generalize wherever I can so that the same technique can be applied to any tool.

Create Gif Animations (optional)

Ultimately I want to populate the island with grazing moose and hunting wolves.  I generated the gifs and plan to clone animated moose and wolves at the rate of one moose per thousand and one wolf per ten. 

In the LodeStar Script cloning an element is done with:

clone(oldID, newID)


which clones an element so that a copy is made with the newID

In JavaScript, this is done with:

let clone = element.cloneNode(false);

which makes a shallow copy (just the element, no children).

let clone = element.cloneNode(true);

which makes a deep copy (element and all of its child nodes).

My technique was to create a dummy hidden element in an SVG graphic manually.  Then with script, as the population increased, clone the element and change its image to an animated moose or wolf.

I’ll set aside discussion of that for now.  In my article on ‘Can Animations Think?’,I go into detail about animations and state machines.  In this article, for the sake of simplicity, I’ll include one moose representative of the moose population and one wolf, representative of that population. 

Converting a video into a GIF in Adobe Photoshop

Set the scene

I used our own SVG editor but one could use Inkscape or even the Articulate Storyline Slide Stage and skip SVG altogether.

Whatever the tool, the scene can be set with an island and a representative from both the wolf and moose populations; and a slider for each of the following:

  1. Moose growth rate
  2. Predation Strength
  3. Wolf Gain
  4. Wolf Mortality Rate

These are the sliders that will impact the flow or the change in moose and wolf stocks.  I created the sliders with SVG and then constrained them to an underlying track.  You can obviously create sliders in any way that your tool allows.

Lastly, I wanted to display a running count of the stock and so I added two SVG text boxes that will be updated with my script.  I’ll show this later with both LodeStar and JavaScript examples. 

I added the trees as separate objects.  In HTML I could have assigned a z-index to bring the tree forward or back in the scene.  In SVG, this is controlled by element order.  Having the trees as separate objects allows me to move the animals between the trees.  In the screenshot below, the wolf is behind the tree. 

Now comes the fun part.

Add a timer and the script

LodeStar has a timer widget.  I added the timer widget to the page and set it so that it fires every second.  Every time the timer fires, its associated branching options are executed. 

LodeStar authoring tool Timer Widget, which can be set to fire once or repeatedly at a defined interval

I’ll write this in pseudo code.  For completeness, I added the full script in the appendix.

 I’ll repeat the point that this is where you’ll need help from your SME.  Do this in Excel or Google Sheets first.

Pseudocode

  1. Read slider values from the page
    • Get moose growth slider value → call it mg_x
      • Get predation strength slider value → call it ps_x
      • Get wolf gain slider value → call it wg_x
      • Get wolf mortality slider value → call it mr_x
      • If any value is missing, set it to 0.5
  2. Define parameter ranges
    • Moose growth rate minimum = 0.05, maximum = 0.3
    • Predation strength minimum = 0.001, maximum = 0.01
    • Wolf gain per moose minimum = 0.05, maximum = 0.3
    • Wolf mortality minimum = 0.1, maximum = 0.4
  3. Calculate parameter values from sliders
    • Moose growth rate r = rmin + mg_x × (rmax – rmin)
    • Predation strength p = pmin + ps_x × (pmax – pmin)
    • Wolf gain g = gmin + wg_x × (gmax – gmin)
    • Wolf mortality m = mmin + mr_x × (mmax – mmin)
  4. Set constants
    • Time step dt = 1 (years per step)
    • Moose carrying capacity kCap = 2000
  5. Initialize stocks if not already set
    • If Moose population M is not defined, set M = 800
    • If Wolf population W is not defined, set W = 25
  6. Calculate flows (rates of change)
    • Moose killed per year k = p × M × W
    • Change in Moose dM = r × M × (1 – M / kCap) – k
    • Change in Wolves dW = g × k – m × W
  7. Update stocks using Euler method
    • New Moose = M + dt × dM
    • New Wolves = W + dt × dW
    • If Moose < 2, set Moose = 2
    • If Wolves < 2, set Wolves = 2
  8. Save updated values
    • Store new Moose population in M
    • Store new Wolf population in W
  9. Prepare values for display
    • Round Moose down to nearest integer → displayM
    • Round Wolves down to nearest integer → displayW
  10. Update the page display
    • Show displayM in the Moose population element
    • Show displayW in the Wolf population element
    • Set Moose graphic opacity = displayM ÷ 100 (clamped 0–1)
    • Set Wolf graphic opacity = displayW ÷ 20 (clamped 0–1)
  11. Repeat every second
    • Call this whole routine once per second with a timer

The end result:

Take it Step by Step

Even the pseudo code may seem daunting.  Most designers are not mathematicians or coders.   But if you take it step by step, you’ll realize that this is nothing more than simple equations (actually, assignments) in the form of  c = a + b.   There’s just a lot of them.   Some of the values come from sliders or textboxes. Sometimes you’ll need to use more advanced math, but your SME can help you with that.   You then take the output of an equation and change an object or element on the screen.  The basic pattern is:  Inputs -> some calculations -> outputs.   Parameter-driven simulations can be easy once you get the hang of them.   They’ll add another useful instructional strategy to your tool bag.

Conclusion

Parameter-driven simulations shine when they make causal relationships visible, fast, and safe. From “bug-farming” in wastewater treatment to wolves and moose on Isle Royale, the pattern is the same: define a few meaningful inputs, translate expert logic into simple equations, and let learners see the consequences of their choices—immediately. The pedagogy matters as much as the math; novices thrive with guided discovery, purposeful prompts, and targeted feedback.

A practical way to apply parameter-driven simulations.

  • Anchor the learning goal. Decide what you want learners to explain or predict; list likely misconceptions you’ll challenge.
  • Choose 3–4 high-leverage parameters with realistic ranges and clear units; hide the rest.
  • Prove the model on a spreadsheet with your SME; validate against known cases before you script.
  • Implement the loop (inputs → calculations → outputs) in your tool; update displays on a steady timer; clamp to sensible bounds.
  • Wrap with guidance. Ask for predictions, offer hints, show worked examples, and debrief with “why did this happen?” reflection.

Avoid the usual pitfalls: too many dials and models that don’t match reality. Do that and you’ll add a durable strategy to your toolkit: simulations that don’t just let learners “play,” but help them reason, connecting inputs to outcomes in ways text and video can’t. Pick one compact system, build it well, and let learners discover “what if?”—with understanding to match.

Research

1 Guided discovery research

Paul Kirschner, John Sweller, Richard Clark (2006)
Famous paper “Why Minimal Guidance During Instruction Does Not Work”

    David Merrill (First Principles of Instruction):
    Learning should always be task-centered, but with scaffolds and guidance that fade over time.

    Appendix

    LodeStar Script Version

    Here is the script that runs every second:

    var M = getValue(“M”);

    var W = getValue(“W”);

    //moose intrinsic growth

    var rmin = .05;

    var rmax = 0.3;

    var r = rmin + (getProp(“mg_slider”, “xPos”) * (rmax – rmin));

    //predation strength

    var pmin = 0.001;

    var pmax = 0.01;

    var p = pmin + (getProp(“ps_slider”, “xPos”) * (pmax – pmin));

    //wolf gain per moose killed

    var gmin = 0.05;

    var gmax = 0.3;

    var g = gmin + (getProp(“wg_slider”, “xPos”) * (gmax – gmin));

    //wolf mortality

    var mmin = 0.1;

    var mmax = 0.4;

    var m = mmin + (getProp(“mrate_slider”, “xPos”) * (mmax – mmin)) ;

    //message(“r: ” + r + ” p: ” + p + ” g: ” + g + ” m: ” + m);

    var dt = 1; //years per step

    var kCap = 2000;  //moose carrying capacity for isle royale

    var k = p * M * W;  //moose killed per year

    var dM = r * M * (1 – M/kCap) – k;  //logistic moose growth – kills

    var dW = g * k – m * W; //wolf gain minus mortality

    M = Math.max(2, M + dt * dM);  

    W = Math.max(2, W + dt * dW);

    setValue(“M”, M);

    setValue(“W”, W);

    var displayM = Math.floor(M);

    var displayW = Math.floor(W);

    //message(“Moose: ” + displayM + ”     ” + “Wolves:” + displayW);

    changeText(“moose_pop”, displayM);

    changeText(“wolf_pop”, displayW);

    changeOpacity(“moose”, displayM/100);

    changeOpacity(“wolf”, displayW/20);

    If you were doing this entirely in HTML and Javascript, you would define some HTML input elements and assign them IDs.  If you’re using Storyline, you can’t rely on IDs that won’t change, but you can give elements a unique accessibility label and query that.

    HTML and JavaScript Version

    <input id=”mg_slider”     type=”range” min=”0″ max=”1″ step=”0.001″ value=”0.5″>

    <input id=”ps_slider”     type=”range” min=”0″ max=”1″ step=”0.001″ value=”0.5″>

    <input id=”wg_slider”     type=”range” min=”0″ max=”1″ step=”0.001″ value=”0.5″>

    <input id=”mrate_slider”  type=”range” min=”0″ max=”1″ step=”0.001″ value=”0.5″>

    <div id=”moose_pop”></div>

    <div id=”wolf_pop”></div>

    <!– Whatever represents the animals (could be images, SVG groups, etc.) –>

    <div id=”moose” style=”width:60px;height:60px;background:#8a8;border-radius:50%”></div>

    <div id=”wolf”  style=”width:60px;height:60px;background:#555;border-radius:50%”></div>

    JavaScript

    function step() {

      // Read slider positions directly (assume [0,1] range inputs)

      var mg_x = parseFloat(document.getElementById(“mg_slider”).value);

      var ps_x = parseFloat(document.getElementById(“ps_slider”).value);

      var wg_x = parseFloat(document.getElementById(“wg_slider”).value);

      var mr_x = parseFloat(document.getElementById(“mrate_slider”).value);

      if (isNaN(mg_x)) mg_x = 0.5;

      if (isNaN(ps_x)) ps_x = 0.5;

      if (isNaN(wg_x)) wg_x = 0.5;

      if (isNaN(mr_x)) mr_x = 0.5;

      // Parameters

      var rmin = 0.05, rmax = 0.3;

      var pmin = 0.001, pmax = 0.01;

      var gmin = 0.05, gmax = 0.3;

      var mmin = 0.1,  mmax = 0.4;

      var r = rmin + mg_x * (rmax – rmin);

      var p = pmin + ps_x * (pmax – pmin);

      var g = gmin + wg_x * (gmax – gmin);

      var m = mmin + mr_x * (mmax – mmin);

      var dt   = 1;       // years per step

      var kCap = 2000;    // moose carrying capacity

      // Keep stocks in global scope so they persist across calls

      if (typeof window.M === “undefined”) window.M = 800;  // initial Moose

      if (typeof window.W === “undefined”) window.W = 25;   // initial Wolves

      var M = window.M;

      var W = window.W;

      // Flows

      var k  = p * M * W;                         // moose killed per year

      var dM = r * M * (1 – M / kCap) – k;        // logistic moose growth – kills

      var dW = g * k – m * W;                     // wolf gain – mortality

      // Euler update

      M = Math.max(2, M + dt * dM);

      W = Math.max(2, W + dt * dW);

      // Save back to globals

      window.M = M;

      window.W = W;

      // Display as integers

      var displayM = Math.floor(M);

      var displayW = Math.floor(W);

      var moosePop = document.getElementById(“moose_pop”);

      if (moosePop) moosePop.textContent = displayM;

      var wolfPop = document.getElementById(“wolf_pop”);

      if (wolfPop) wolfPop.textContent = displayW;

      var mooseEl = document.getElementById(“moose”);

      if (mooseEl)

    mooseEl.style.opacity = String(Math.max(0, Math.min(1, displayM / 100)));

      var wolfEl = document.getElementById(“wolf”);

      if (wolfEl)

    wolfEl.style.opacity = String(Math.max(0, Math.min(1, displayW / 20)));

    }

    // Run one step per second

    setInterval(step, 1000);

    Adapting to Storyline

    You can’t rely on object (element) IDs because they change. 

    Here’s the short, practical checklist to make your sim work in Storyline without relying on object IDs and while using the player object.

    What to do (step-by-step)

    1. Create Storyline variables (stocks)
      • Add number variables: Moose, Wolves (initial values as you like).
      • (Optional) Add variables for sliders/params if you’re not using Storyline Slider objects.
    2. Name target objects with Accessibility labels (stable selectors)
      • Select each object on the Stage (images, text boxes).
      • Set Alt text / Accessibility Name to unique values (e.g., MooseImage, MoosePop, WolfImage, WolfPop).
      • These export as data-acc-text=”…” (or sometimes aria-label), which you can query—more stable than auto-IDs.
    3. Display the numbers on screen
      • Put text like: Moose: %Moose% and Wolves: %Wolves% in text boxes so they auto-update when variables change.
    4. Add the JavaScript trigger
      • Insert an Execute JavaScript trigger (e.g., “When timeline starts”).
      • Inside, always get the player and read/write variables:
      • var player = GetPlayer();
      • var M = Number(player.GetVar(“Moose”));
      • var W = Number(player.GetVar(“Wolves”));
      • // … do your math …
      • player.SetVar(“Moose”, Math.floor(M));
      • player.SetVar(“Wolves”, Math.floor(W));
      • After setting variables, optionally also target Stage elements by Accessibility label:
      • // Example: adjust opacity using accessibility labels
      • var mooseEl = document.querySelector(‘[data-acc-text=”MooseImage”]’) || document.querySelector(‘[aria-label=”MooseImage”]’);
      • if (mooseEl) mooseEl.style.opacity = String(Math.max(0, Math.min(1, M / 100)));
    5. Create the “tick” (repeat every second)
      • Easiest: add a trigger “When timeline reaches 1.0s → Jump to this slide” so your JS runs again each loop.
    1. Opacity/visual states (if direct CSS is limited)
      • If CSS styling doesn’t work on some objects, create States (e.g., Dim1, Dim2, …) with different transparencies and switch states based on ranges (conditions on Moose, Wolves).
    2. Publish considerations
      • Test selectors in the published output—some themes export data-acc-text, others aria-label. Keep your query flexible (as above).
      • Avoid depending on Storyline’s auto-generated IDs (#object12); they can change on republish.

    Remember that:

    • Stocks live in Storyline variables (read/write via GetPlayer()/SetVar()).
    • Selectors target objects by Accessibility label (not by ID).

    Datasets

    Robert N. Bilyk
    President, LodeStar Learning Corporation

    Introduction

    In eLearning design, we often think of content in terms of slides, quizzes, and interactions. But behind many of these experiences lies something powerful and flexible: the dataset. A dataset is not just a collection of numbers in a spreadsheet—it is a structured container of information that can fuel adaptive quizzes, interactive simulations, and dynamic learning activities.

    Question Banks

    Most of us have experienced the learning management system quizzing engine with its associated question bank.   We recognize the value of a separate question bank because it allows us to reuse the questions, randomize the questions, draw a subset of questions from the question bank, import publisher questions and so on.

    A question bank is essentially a dataset where each record (or row/item) represents a question with its associated data. Instead of numbers in a spreadsheet, your dataset stores structured information that a quiz engine can read and present to learners.

    If we understand datasets – what they are and how they work – we can apply them to many different types of interactions and achieve the same benefits:  reuse, randomization, and relatedness.

    So let’s parse this out very carefully.  I’ll use examples created with the LodeStar eLearning authoring tool, but the concepts and principles can be applied to many of our best authoring platforms.

    What is a dataset really?

    A dataset is simply a structured collection of information. Think of it as a container of data that has been organized in a way that makes it useful for analysis, training, or interaction. Generally, datasets can be a variety of things like a spreadsheet of quiz scores, a table of employee profiles, a set of labeled images, or a JSON file of learner responses.

    Most designers understand the concept of a spreadsheet or a table or a set of things.  It is the last item that is both tremendously useful in eLearning but, at first, a little intimidating. And that is ‘JSON’ or JavaScript Object Notation.

    Here is an example:

    [

      {

        “id”: “Q001”,

        “question”: “What is the capital of France?”,

        “options”: [“Berlin”, “Paris”, “Madrid”, “Rome”],

        “answer”: “Paris”,

        “feedback”: “Paris is the capital and most populous city of France.”,

        “difficulty”: “easy”,

        “category”: “Geography”

      },

      {

        “id”: “Q002”,

        “question”: “Which gas do plants absorb during photosynthesis?”,

        “options”: [“Oxygen”, “Carbon Dioxide”, “Nitrogen”, “Helium”],

        “answer”: “Carbon Dioxide”,

        “feedback”: “Plants use carbon dioxide and sunlight to produce energy.”,

        “difficulty”: “medium”,

        “category”: “Science”

      }

    ]

    This gobbledygook represents all of the key characteristics of a dataset.  I really encourage you to understand it in detail – because you can apply this concept in your eLearning. You can leverage a dataset’s support for reuse, randomization, and relatedness.

    Here it goes: The outermost brackets [ … ] indicate that this is an array or, in simpler terms, a list.

    Inside the array or list are two objects.  Each object is wrapped in curly braces, { … }, each representing a single quiz question.

    Each object has a consistent set of key–value pairs that define the properties of that question.  In the following snippet,

    “category”: “Science”,

    ‘category’ is the key or property, and ‘science’ is the value.  What is the category of this question?  It is science.  Being properties of the same object, science is related to the question.

    Representation of the objects in a dataset with their properties.

    We can find the same idea in HTML through data attributes. Data attributes also use key–value pairs to store information about an element. For instance:

    <div id=”question1″ data-category=”Science” data-difficulty=”medium”>

      Which gas do plants absorb during photosynthesis?

    </div>

    • Here, data-category is the key (property).
    • “Science” is the value.
    • If we ask, What is the category of this question? the answer is Science.

    Because both data-category and data-difficulty belong to the same element, they are related to the same question—just like properties in a JSON object are related to the same record.

    Getting JSON into memory

    JSON is a string format for representing structured data. In other words, it’s just text that follows strict rules. 

    Because JSON is just a string, it must be parsed into a real object in memory before JavaScript in Storyline or Captivate can use it or before LodeStar Script can use it.

    In JavaScript, this is done with the following line of code:

    let obj = JSON.parse(jsonString);

    In LodeStar, we can use the interface to define a dataset.  In this unit on the importance of fire safety, we selected the Dataset Widget, defined the properties, and then populated the dataset with ten examples of costly fires.

    LodeStar’s Dataset Widget

    In the top part we defined what the properties of the dataset are.  There are four properties:

    Name of Fire

    City

    Year

    Extent of Loss

    In the bottom part we entered the data.  We can do this manually or, when appropriate, with the help of Artificial Intelligence (AI) and some careful review,

    With the fire safety dataset, we simply display the information.  In the next example, we do much more than that.

    Let’s review the key characteristics of dataset and then dive into a more involved example.


    Key Characteristics of a Dataset

    • Structured Organization: Data is usually arranged in rows and columns (like a table) or in key–value pairs (like JSON).
    • Consistency: The same types of data are stored together—for example, names in one column, scores in another.
    • Purpose-driven: Datasets are collected to answer a question, train a model, or drive an activity.

    How a Dataset Powers eLearning Interactions

    In eLearning, datasets can be the source material that drives learner experiences. Here are a few examples:

    1. Scenario-based Learning
      • Dataset: A collection of customer complaints with attributes (customer type, issue, severity, resolution).
      • Use: An interaction presents the learner with a complaint and asks them to choose the best response. The dataset provides both the inputs (complaints) and the feedback (model answers).
    2. Adaptive Quizzing
      • Dataset: A bank of questions with difficulty levels, topics, and correct answers.
      • Use: The system draws from the dataset to deliver questions that adapt to the learner’s progress.
    3. Simulations & Role Play
      • Dataset: A set of profiles (age, occupation, goals, challenges) representing virtual characters.
      • Use: In a medical training module, learners interact with patient profiles drawn from the dataset to practice diagnosis.
      • Dataset: JSON records of learner prompts and expert responses.

    In short: a dataset can be the stuff that fuels an eLearning interaction. It supplies the content, context, and variables that the interaction logic can work with to create meaningful learner experiences.

    Dataset in Language Learning

    Recently, I was inspired by a student who is designing a course website to teach students Hindi and the Devanagari script, and to teach Hindi speakers English.

    The student experience related to my own experience with the French language. I decided to create an interaction that challenges a French language learner to construct a sentence in English based on the French sentence that is shown.  Toward that end, I created a dataset that could be quickly populated by AI and then reviewed for accuracy.

    Note: I’ll use LodeStar to build the example, but show you how this can be applied to any tool.

    Here are the key steps:

    Title Screen

    Step One:

    First I set up the dataset.  I used the Dataset widget in LodeStar to set up and populate the properties.

    Dataset used to capture French sentences matched by English translations parsed into separate words

    The first thing I did was give this dataset an ID so that I can reference it.  The ID is found in the top right corner.  I identified this dataset as ‘sentences’. 

    As I’ve discussed, the top part of the Dataset widget prompts you to define your properties.  In this case I created the following properties:

    Foreign_sentence

    Word_0

    Word_1

    Word_2

    Word_9

    You get the idea.  I defined ten properties for ten- (or fewer) word sentences.

    Step Two:

    I then clicked on the AI button and gave AI this prompt:

    Create 10 ten-word sentences in French that would be used in everyday conversation.  Place the French sentence in the field named foreign sentence. Then translate the French words into an English sentence, placing the first word of the English sentence in word_0, the second word in word_1, and so on.

    It took several tries.  AI kept giving me responses that LodeStar’s validator wouldn’t accept.  But then, finally, the fields got filled.  10 French sentences with the English translation parsed into separate words.  The first word filled word_0, the second word filled word_1, and so on, just as the prompt requested.

    Step 3:

    Now comes the fun part: linking the dataset to an existing interaction.

    Student view of a language interaction

    I manually linked the dataset to an Organizer interaction.   I had the option of building an interaction from scratch, but instead I opted for repurposing the Organizer Page interaction.

    Just a quick note about Organizer.   It can be used for matching or ordering.  As you can see from the screenshot, the word tiles can all be assembled into one, two or multiple lines.  Organizer can still figure out the order of the tiles and evaluate whether they are in the correct order.  So rather than trying to recreate that functionality from scratch, I simply fed data to Organizer’s elements.

    Note: I used the Organizer Page in LodeStar, but you’ll soon see how you can link datasets to any HTML elements in any authoring tool that supports Javascript and exposes its elements.

    The connection from the dataset to the Organizer interaction is accomplished with a little bit of script.

    Making the Connection

    Retrieving the Dataset from memory

    var dataset = getDataSet(“sentences”, -1);

    Earlier, I gave the dataset the ID of ‘sentences’.  I now use this in a simple function called getDataSet.  The first part or argument to the function is ID of the dataset.  The second part is -1.  That means, give me a random object from the dataset. 

    Again, a dataset is a collection of objects.  Each object is a related set of properties and values.  I’m asking LodeStar to randomly pick an object from the dataset and assign it to a variable named dataset.

    In pure JavaScript this might look like:

    var datasetArray = [

      {

        foreign_sentence: “Bonjour le monde”,

        word_0: “Hello”,
        word_1: …

      },

      {

        foreign_sentence: ” Comment vous appelez-vous” 

        word_0: “What”,
        word_1: …

      }

    ];

    // Randomly retrieve an object from the array

    var randomIndex = Math.floor(Math.random() * datasetArray.length);

    var dataset = datasetArray[randomIndex];

    In Javascript, we use Math.random() to produce a number from 0 to 1.  We then multiply that random number with the length of the array.  If the random number produced is .5 and the number of the objects in the array is 9, we get 4.5

    But 4.5 can’t be used to access an item in an array.  The index of the array must be expressed with whole numbers. Math.floor rounds down to the nearest whole number or integer, which is 4.  Because arrays are zero-based, 4 means that we are accessing the fifth object in the array.

    A diagram representing an array of objects matched to an Array index. The first object is at 0.

    I’ve written out the entire JavaScript version of this in the appendix.

    Again that is what the -1 accomplishes in LodeStarScript.   It randomly picks an object.

    var dataset = getDataSet(“sentences”, -1);

    Once I have the dataset I can use it.

    for(var i = 0; i  < 10; i++){

        var word = dataset[“word_” + i];

        changeText(pageID + “_” + i, word);

    }

    In this loop, I am accessing the object with the following syntax.  It is the same in LodeStar Script as it is in JavaScript.

    var word = dataset[which property];

    You access an object’s property with square brackets.  The property name must be in quotes.    

    I could write this.

    var word0 = dataset[“word_0”];

    and then this:

    var word1 = dataset[“word_1”];

    and so on.

    But I simply do it in a loop.

    for(var i = 0; i  < 10; i++){

        var word = dataset[“word_” + i ];

    A ‘for’ loop starts with the keyword ‘for’, followed by three parts separated by semi-colon:

    • the initial value of the looping variable i
    • the condition: before each loop cycle, JavaScript checks this condition. If it is true, the code inside the { } runs. If it is false, the loop stops.
    • the increment: after running the code block, i++ increases i by 1.

    The first time through the loop, i will be assigned 0.  I then concatenate or join that to “word_” because that is the name of the property in my dataset.

    The first time through the loop I get “word_0” and the second time I get “word_1”.

    In addition, each time through the loop, I change an element in the Organizer interaction with:

        changeText(pageID + “_” + i, word);

    changeText() is a LodeStar function.  All word tiles in Organizer are assigned a unique ID – like a social security number.  All pages in LodeStar are assigned a unique ID.   I’ve assigned the Organizer page ID to the variable pageID.   Each element on the Organizer page is assigned a number.  So, if PageID were 645, the first word tile would be 645_0, the second word tile would be 645_1, and so on.

    My loop therefore takes each word from the dataset and assigns it to a tile.  Now the tiles represent the English words that translate the French sentence held in foreign_sentence.

    The learner is given a fresh set of jumbled up word tiles every time the Organizer page is displayed.   They order the tiles and get corrective feedback.  Their performance is then logged into the system.

    Conclusion

    The impact of datasets on learning is profound. They give designers the ability to build interactions that adapt, refresh, and surprise learners every time they engage. Instead of creating dozens of static activities, you can create one interaction that draws from a living pool of content. Whether it’s reordering word tiles, branching through a scenario, or working with adaptive question sets, datasets provide the structure that makes these experiences possible. By embracing datasets, you’re not just storing information—you’re giving your eLearning projects the fuel to become more flexible, more personalized, and ultimately more effective.

    Appendix:

    // Example dataset used with plain old JavaScript for use in authoring tools

    var datasetArray = [

      {

        foreign_sentence: “Bonjour le monde”,

        word_0: “Hello”,

        word_1: “the”,

        word_2: “world”

      },

      {

        foreign_sentence: “Comment vous appelez-vous”,

        word_0: “What”,

        word_1: “is”,

        word_2: “your”,

        word_3: “name”

      }

    ];

    var randomIndex = Math.floor(Math.random() * datasetArray.length);

    var dataset = datasetArray[randomIndex];

    // Example page ID

    var pageID = “1756394830561”;

    var attempts = (typeof attempts === “undefined”) ? 0 : attempts;

    attempts += 1;

    // Get the foreign sentence

    var sentence = dataset[“foreign_sentence”];

    var sentenceElement = document.getElementById(“sentence”);

    if (sentenceElement) {

      sentenceElement.textContent = sentence;

    }

    // Loop through words and place them into elements

    for (var i = 0; i < 10; i++) {

      var word = dataset[“word_” + i];

      if (word) { // only if the property exists

        var elem = document.getElementById(pageID + “_” + i);

        if (elem) {

          elem.textContent = word;  // replaces changeText()

        }

      }

    }

    Can Animations Think?

    Robert N. Bilyk
    President, LodeStar Learning Corporation

    Introduction

    Since the start of computer graphics in the early 1970s, animation has transformed how we communicate complex ideas. In education, it offers more than just visual appeal — it provides clarity, interactivity, and immersion. When used intentionally, animation can simulate real-world systems, model abstract concepts, and spark curiosity in ways static visuals never could.

    In this article, I’ll show how we can apply foundational animation concepts — like keyframes and state machines — to create interactive, responsive learning experiences. Our case study is a simulated aquarium where learners select species of fish and observe how their choices affect the ecosystem. This Aquarium Demo is a hands-on example of using motion, state logic, and behavior scripting to illustrate the delicate balance of nature in an engaging and educational way.

    An Aquarium eco-system designed with the LodeStar Authoring Tool

    The Aquarium Demo

    The Aquarium demo is only a mock-up to help demonstrate animation concepts.  But one can easily imagine a similar environment that is more fully developed through which learners can experience the delicate balance of nature.

    I’ll explain the project in some detail so that we have a context and practical application for our animations.

    In the design, learners choose from six species of fish.  Hidden to the learner are the characteristics of the fish that they must deduce by observation and experimentation.  At the end, the learner is challenged to select the laws that were applied to the aquarium. 

    The characteristics of the fish are represented in this table:

    Fish NameRole / NicheNotes
    Neon TetraMid-level schooling fishlow bio load
    Corydoras CatfishBottom scavengerCleans waste; avoids uneaten food buildup
    OtocinclusAlgae-eating cleanerControls algae; low impact
    Bolivian RamCenterpiece, semi-territorialAdds diversity; may defend territory
    Tiger BarbAggressive nipperKnown to harass and eat other fish
    GoldfishColdwater, messy eaterUnsuitable for tropical tank

    In the aquarium, with the help of a little scripting:

    • Tiger barb fish will eat other fish
    • Goldfish produce waste and decrease water quality
    • Catfish and other species control algae and waste
    • Overpopulation reduces water quality
    • Low water quality adversely affects all fish health over time.

    Let’s discuss two important animation concepts and then apply them to the Aquarium project.

    Animation concepts

    GIF Animation

    Let’s start with the fish.  We’ll use one animated GIF for each fish.  An animated GIF is a single file that contains multiple frames (or images) displayed in sequence to create the appearance of animation.  An animated gif is a digital version of the Cel animation (celluloid), a traditional animation technique in which each frame of a scene is drawn by hand on a transparent sheet called a cel. In traditional animation, these cels were then photographed in sequence over a static background to produce the illusion of motion.  Disney’s Snow White and the Seven Dwarfs was the first-ever full-length cel-animated feature film. It used hand-drawn cel animation over painted backgrounds and required thousands of hand-drawn cels.

    gif animation of a Tiger Barb

    Keyframe Animation

    Keyframe animation is a method in which property changes are recorded at specific  positions in time (keyframes) and the animation system interpolates or calculates the frames between them (called tweens) to create smooth motion.

    Keyframes and Tweens

    If the position of a fish were 100% on the x axis at the start of the animation and 0% at the end, the computer can easily calculate that midway through the animation the fish will be positioned at 50%.  A designer need only spell out the start and end positions (the keyframes) and the computer will figure out the rest.


    a. Keyframe

    • A frame that defines a critical point in an animation—such as the start or end of a motion, or a change in properties (position, scale, rotation, etc.).
    • Each keyframe contains property values (e.g., x, y, opacity, transform).

    b. Tweening (Interpolation)

    • The process of calculating the intermediate values between keyframes.
      • The intermediate values might be evenly divided as in a linear transition or they may be smaller values at first and then increase in number as in an ease-in transition (or visa versa).
    • Automates the movement or change between key states.

    c. Timeline

    • A time-based representation where keyframes are placed at specific times.
    • Each property (e.g., position, scale) may have its own timeline track.

    d. Animation Properties

    • Typically, animatable properties include Position (x, y), Scale, Rotation, Opacity and Color

    Application

    In our aquarium we have fish who move their fins and open and shut their mouths.  One way to represent this movement is with a GIF animation.  (Another way is through animated character or puppet rigging.)   Fish also move back and forth through water or around in a circle.  That is best represented by keyframe animation that is captured in a timeline.

    In our aquarium, fish are dropped into the water.  That is represented by one timeline.  Fish start swimming from wherever they are dropped off.  That is represented by a second timeline.   Once fish return to a known spot, they swim normally from one end of the aquarium tank to the other, flip, and return to the original spot.  That is a third timeline.   They may surface or dive deeper to another depth.  Those are separate timelines.  Finally, they might die.  Once again, another timeline.

    Similarly, you may have a character who is walking to the right, walking to the left, running, or jumping.  These are all expressed through timelines.

    That introduces us to another key concept associated with timelines:  The State Machine.

    State Machine

    A state machine in animation is a logic-based system that governs how a character or object transitions between different animations in response to user input, time, or internal conditions.

    It enables interactive, dynamic, and reactive animations without having to manually script frame-by-frame sequences.

    Core Components of a State Machine

    a. States

    • Represent distinct animations or visual conditions.
    • Examples: Idle, Swimming, Surfacing, Diving.

    Each state plays a specific animation timeline or triggers specific motion.

    b. Transitions

    • Define how and when the system moves from one state to another.
    • Transitions can include Conditions (e.g., variable equals true), Duration (fade in/out timing), and Inputs (State Machine Variables)
    • Control logic and flow.
    • Types of inputs such as isRunning, Number – e.g., speed, and Listeners / Events
    • External code or interactions (e.g., click, drag, scroll), which can modify inputs, triggering new states.

    State Machine and States

    To help visualize the state machine, the following diagram shows the four states of our fish: drop, transition, swim and fishkill.

    Diagram of a state machine

    In the Aquarium, each fish (by element ID) is passed into the state machine.

    When we change the state of a fish to ‘Drop’, the onEnter causes the fish to be randomly positioned in the tank, and the onExit executes the state change to ‘Transition”.  The ‘Transition’ state starts the fish swimming from the current position 1 and onExit executes the state change to ‘Swim’.  The ‘Swim’ randomly positions the fish and then causes the fish to swim from one end of the aquarium to the other.  If the fish is still alive, the onExit sets the state to ‘Swim’ causing a repeat.  If the fish’s health has deteriorated or if the fish has been eaten by a Tiger Barb, then state changes to ‘Fishkill’.

    This is what the State Machine looks like in the LodeStar State Widget.

    Screenshot of LodeStar’s State Widget

    The state machine is given an ID of ‘movement’. The state shown in the screenshot is ‘swim’.   The Branch Option contains what happens when the state first starts.  That is the onEnter branch option.  The End Branch contains what happens when the state ends.  That is the onExit branch option.  The timeline is a representation of the keyframes, written in JavaScript Object Notation or JSON.  For those unfamiliar with JSON, AI helps to write the keyframes using this notation.   A little explanation will help uncover the mystery of this notation.

    Keyframes in JSON

    To begin, the animations in LodeStar are executed by the Web Animation API (WAAPI). The Web Animations API (WAAPI) is a browser-native JavaScript API that allows designers to create and control animations directly with script and timelines — without needing CSS or third-party libraries.   To repeat, this animation engine is native to all modern browsers and can be used in a variety of platforms, including LodeStar.

    The Web Animations API provides a programmatic interface for animating HTML or SVG elements. It lets you:

    • Animate styles and transforms
    • Control playback (pause, reverse, seek, cancel)
    • Combine multiple animations
    • Query animation states

    It gives you fine-grained control — similar to CSS animations but with script-level flexibility or, in the case of LodeStar, with LodeStar script-level flexibility.  LodeStar Script offers a number of high-level functions that simplify the use of WAAPI.

    Let’s briefly look at the anatomy of keyframes written in JSON.

    [ { “transform“: “translateX(0vw) scaleX(1)”, “offset“: 0 }, 

    { “transform“: “translateX(100vw) scaleX(1)”, “offset“: 0.49 }, 

    { “transform“: “translateX(100vw) scaleX(-1)”, “offset“: 0.51 }, 

    { “transform“: “translateX(-50vw) scaleX(-1)”, “offset“: 1 } ]

    At first this all seems like gobbledygook, but if you break it down part by part, it will make sense.

    The outer [  ] represent an array or a list – a list of keyframes.  The transform property spells out what changes are, and the offset property spells out when.

    Let’s parse out the first line after the opening [.

    { “transform“: “translateX(0vw) scaleX(1)”, “offset“: 0 }

    The curly braces { } mean that this is an object.  It is a keyframe object.  Objects have properties and values.  In the first line, the first property is named ‘transform’.  The value is translateX(0vw) scaleX(1).  The second property is “offset” and its value is 0.

    This means that the element (in our case, fish) will be visibly placed at 0 on the x axis.  The coordinates are 0vw, which means 0% of the width of the browser window.   scaleX(1) means that an image of a fish facing right will continue to face right with no scaling applied.  scaleX(-1) means that the fish will be flipped horizontally.   To understand why, you would need to understand matrix math, which is beyond the scope of this article.  Just know that scaleX(-1) flips an image.   

    I wrote visibly placed at 0 in the last paragraph.  This is such an important concept to grasp when performing animations.  It means that the element hasn’t changed its place in the HTML document.  It just appears to have moved.  Transforms and translations are so much more efficient and appear less jerky than actually moving an object’s location in the document, which requires a lot of computational overhead.

    Translation versus change of location in the HTML document

    Finally, when does this happen?  When is the element placed at 0 on the x axis?  It happens at the offset in the timeline.  In this case, the offset is 0, which means at the beginning.  An offset at .49 means at the 49% mark.  1 means at the 100% mark.  But 49% and 100% of what amount of time?   That is determined by the duration setting, which is set when you change state.  If the duration is set to 5000, the entire animation happens over 5000 milliseconds or 5 seconds.  0 is at the 0 second mark in the timeline.  .49 is at the  2.45 second mark, and 1 is at the 5 second mark.

    Here is each line in plain language.

    [ { “transform“: “translateX(0vw) scaleX(1)”, “offset“: 0 }, 

    At the beginning of the animation, move the fish to the far left.  Normal scale.

    { “transform“: “translateX(100vw) scaleX(1)”, “offset“: 0.49 }, 

    At the 49% mark, move the left edge of the fish to the very right of the screen.  Normal scale.  The fish disappears off to the right.

    { “transform“: “translateX(100vw) scaleX(-1)”, “offset“: 0.51 }, 

    Past the half-way mark, flip the fish so that it is facing to the left.

    { “transform“: “translateX(-50vw) scaleX(-1)”, “offset“: 1 } ]

    By the end of the animation, move the fish entirely to the left and keep it facing left.

    In LodeStar, designers have the option of describing this in plain language in a prompt and allowing artificial intelligence (AI) to create the keyframes.  It helps, however, to understand what is happening, especially when tweaking the generated timeline.

    Translate and scale are only two examples of what can be animated.   Many CSS properties can be animated.  Some of you may be accustomed to creating keyframes in CSS.  This approach gives you far more control.

    Animation Editor

    As another option for creating keyframes, LodeStar offers an animation editor.  In the screenshot below, I am creating a keyframe at the 2.5 second mark.   The fish therefore moves halfway across the screen.  LodeStar assigns this timeline an ID, which can be used in the state machine in lieu of manual or AI generated keyframes.  LodeStar translates the 2.5 second mark to an offset of .5 because the editor is set to a duration of 5 seconds.

    Screenshot of LodeStar’s Animation Editor

    Applying the laws of nature

    Now let’s apply the laws of nature to our aquatic ecosystem. This is the ‘thinking’ part of the animation. For that I use a Timer widget.  I set the timer to fire and execute a script every 20 seconds.

    Screenshot of LodeStar’s Timer Widget

    Rather than showing the script, I’ll summarize what the script does in plain language.

    The script does the following:

    • Sounds a beep.
    • Gets water quality level and assigns to a local variable
    • Counts the number of fish in a set.  A set is a collection of unique entities.
    • If there are any fish in the aquarium, gets them from the set and assigns them to an array.
    • Builds a temporary set to determine the diversity of the fish.  Loops through the array and adds each type of fish to the set.  The set won’t hold two instances of the same type.  After you’ve looped through the entire array of fish, you’ll know the diversity by counting the items in the temporary set.
    • Uses the water quality variable.  If the water quality is low, adversely affects the health of the fish.  Each fish is represented by an object in memory. 
    An object with properties and values

     The object contains the id of the fish, the type and the health level of the fish.

    If the water quality falls below a certain level, the health level of the fish is decreased.   If below 1, the state of the fish is changed to fishkill.

    The different species of fish have different impacts on the environment and on other fish.  The script checks the fish type and applies the impact according to the table that was introduced at the beginning of the article.  If the fish is a catfish for example (in our case a Corydoras Catfish), the fish cleans up waste and increases the water quality level.

    Lastly, the water meter is updated with a readout of the water quality level.

    A graphic of a water quality meter that will be updated with LodeStar script

    Again, this happens every 20 seconds. 

    Conclusion

    The Aquarium Project is more than a mock-up — it’s a blueprint for how animation can deepen understanding in learning environments. Through the combined use of animated GIFs, keyframe timelines, and state machines, we created a dynamic simulation where learners interact with virtual ecosystems and witness the cause-and-effect relationships that define natural systems.

    Animation here wasn’t just decorative — it was functional. It helped represent states, transitions, behaviors, and consequences in ways that would be difficult to convey otherwise. When paired with logic and scripting, animation becomes a powerful instructional tool, capable of modeling biology, human behavior — or any system we want learners to explore.

    With tools like LodeStar, WAAPI, and a thoughtful design strategy, educators and developers can craft animated environments that not only look compelling but think — responding to input, tracking states, and evolving over time. The Aquarium is just one example of how code, animation, and pedagogy can come together to create rich, meaningful learning experiences.

    Notes

    1. WAAPI and CSS transitions in the aquarium project

    The aquarium project used a combination of WAAPI (Web Animations API) keyframe timelines and CSS transitions to animate elements. This technique works well for HTML elements, where both CSS and WAAPI manipulate the same style properties.

    However, this approach does not work reliably with elements inside an SVG image. That’s because:

    • HTML elements use style properties for positioning and transforming elements (e.g., transform, left, top).
    • SVG elements use XML attributes (e.g., x, y, transform, cx, cy) to define position and shape. These attributes are not always recognized as animatable style properties by WAAPI or CSS transitions.

    For example:

    • If you animate an SVG element’s position using WAAPI by changing its transform attribute, and then try to use a CSS transition to continue the movement, the browser won’t recognize the transformed position as the starting point for the transition. Instead, it will use the original attribute-defined position, leading to unexpected results.

    Best Practice:

    • Only combine WAAPI keyframes and CSS transitions on HTML elements.
    • Do not mix CSS and WAAPI on individual SVG elements.
    • You can animate an entire SVG image (i.e., the <svg> tag treated as an HTML element) using a combination of CSS and WAAPI, because the outer SVG container behaves like a regular HTML element.

    AI-Assisted Question Types

    Robert N. Bilyk
    President, LodeStar Learning Corporation

    Introduction

    Multiple choice questions are familiar to instructors and convenient, but they often fall short when deeper understanding or authentic decision-making is the learning goal. More sophisticated questions challenge instructors because they require time and nuanced thinking to design and assess. This article explores how artificial intelligence can help instructors construct more challenging types of questions.

    Examples of more sophisticated question types include scenario-based decision-making, WebQuests, ranking or prioritization tasks, error analysis or debugging, problem-based learning and the list goes on.

    Many years ago, we developed the State Response Engine1 to promote deeper student understanding and decision-making.  Our implementation of the State Response Engine is named ‘Challenger’.  Essentially the engine randomly selects one state from a set of states.  For example, in CPR training the engine will select a type of victim: an adult, an infant or an elderly person.  The techniques and procedures that follow are judged correct or incorrect based on this random selection.    For the student, it’s not just selecting the plausible answer, but the correct answer given the situation.  In the CPR example, there was one randomly chosen state.  We had the option of injecting multiple random states at various stages of the emergency response. We had the option of making the situation more varied and life-like.

    Challenger Activity created with the LodeStar eLearning Authoring tool

    Unlike the basic multiple-choice or multiple-select question, setting up a state response engine can be challenging for busy instructors who haven’t the time to master the mechanics of a State Response Engine.

    This article re-introduces the State Response Engine (SRE) and how artificial intelligence (AI) can make the task of setting up an SRE easier.   But first, I’ll progress through a series of LodeStar question types and discuss stages of support that are offered by AI.  We’ll move from simple to more complex.

    The Dataset

    So, let’s start easy.  We’ll start with the simple dataset.  Our LodeStar eLearning authoring tool offers instructors and designers a simple Dataset widget.  The author can define the properties that make up a dataset and then ask AI to populate the dataset with dozens of examples.

    To illustrate this and other question types, I’ll use the topic of ‘Putting out a fire’.

    A variety of activities related to extinguishing a fire

    In the screenshot below, we see the author defining a dataset with the following fields:

    • Name of Fire
    • City
    • Year
    • Extent of Loss

    Once the fields are added, the author clicks the ‘Generate’ button and a dataset is created.

    Authors can customize their own datasets

    The author then clicks on the AI tool and asks AI to fill in the details for ten fires, which it does in a manner of seconds. The author can then use the dataset in different ways. The screenshot below shows that the author displayed catastrophic fires in a short slideshow.

    Dataset displayed in a slideshow

    In this simple case, the AI engine is automatically fed with the schema 2 of the dataset and the user (author) prompt.  That means that the AI is given a machine-readable format (the schema) that spells out the name of the field, its data type, its length, and supporting information.  This data is combined with the user’s prompt or instructions.  LodeStar submits this information to the AI service and then converts the response into the dataset – in this case, the ten most costly fires.

    User (Author) Prompt: Fill in the ten costliest fires in terms of life and property loss. 

    The Crossword

    In the next example, the author generates a crossword from terms that relate to extinguishing a fire. 

    In the example, LodeStar provides the AI service with a combination of the schema, the user prompt and a very simple system prompt to help guide AI to generate the data.  The schema was so simple (i.e. Word and Hint) that not much was needed in the form of a System Prompt.  It is important to note that the author need not worry about schema or system prompts.  Those are automatically generated and submitted.  It is, however, helpful if the author provides clear instructions in the user prompt.

    In this screenshot the author prompts AI to generate twenty words and hints.

    Prompting AI to generate crosswords

    After AI returned the results, the author weeded out some words and kept thirteen.  Then the author clicked on the ‘Compile’ button, which generated the crossword.

    Compiling the crossword

    Selecting ‘Preview’ then displays what the learner will see.

    Displaying the crossword puzzle

    User (author) prompt: Create a list of words related to fire safety and classifying fires and their hints.

    Challenger (State Response Engine)

    State Response Engines can be tricky and therefore good candidates for AI assistance.  Unlike multiple choice questions and crosswords, instructors may find it difficult to think in terms of procedures and decisions that are judged or evaluated based on the context (the state).   In CPR, hard chest compressions may be the correct procedure, but only if the victim is not too young or even too old.  The right answer is state dependent. 

    In our Putting out a fire example, the author prompts AI to generate three specific classes of fires as random states as well as correct and incorrect procedures for each state.  AI responds with Class A (Solids) fire; Class B (Liquids) fire; and a pseudo class, Class E (Electrical) fire.  Then AI generates a list of procedures to fight fires.  Some procedures are never correct; others are always correct; and some are correct if a dependency exists – such as the correct state or, in this example, the correct class of fire.   Using a CO2  Extinguisher is only correct, for example, in the case of an electrical fire.

    In Putting out a fire, AI was provided the schema, which is quite extensive.  It consists of

    • Title
    • Category
    • Random State
    • Dependency On
    • Points
    • Correct Response
    • Resource
    • Feedback A (if incorrectly selected)
    • Feedback B (if incorrectly omitted)

    The fields in the schema are not self-explanatory.   States, for example, must have Random State set to true and fall under a specific category.  In a single category only one of the random states is selected.

    Not only will instructors find this a challenge to prepare, but even AI is challenged to fill in the fields based on the schema alone.  The schema is not self-explanatory.  Therefore, LodeStar provides AI with a detailed system prompt that instructs AI on how to generate random states and procedures that are dependent on those states being true.

    With the schema, the user prompt and a detailed system prompt, AI succeeds in providing the data to construct the activity.

    The screenshot below shows two categories: Situation, Procedure.    The situation will be one of the randomly chosen fire types.  In this example, the situation is a Class A Fire. The Procedure category will include a list of decisions.   Only the decisions that help extinguish a Class A Fire will be judged correct.

    Displaying the Situation
    Displaying the procedure or decision-making options

    User prompt: Create three random states.  Label each state in the Title field. Each state is a type of fire including: Class A (Solids), Class B (Liquids), and Class E (Electrical).  Describe the state in the situation category.  Create a category called procedures and include both correct and incorrect procedures for each type of fire.  In total, create 9 procedures. Label each procedure in the Title field.

    Conclusion

    It’s possible that AI assistance can help toolmakers offer more sophisticated activity types to instructors.  In the case of Putting out a fire and the Challenger activity, the information that AI generated may or may not have been of value.  But given the schema and the detailed system prompt, it is likely that AI will adhere to the basic rules of the activity – namely, create random states and procedures dependent on those states.  That will at least guide the instructor on how Challenger (a State Response Engine) works and serve as a model.  The instructor can edit, re-order, delete and add their own data, once they understand how it all works. The same method of AI assistance can be applied to WebQuests, SimpleSims, and other activities that are little more complicated than multiple choice or multiple select questions.

    We may go beyond the multiple-choice question after all.

    References

    1 State Response Engine | LodeStar Web Journal

    2 A schema is like a blueprint or plan that shows how information is organized and stored in a system.

    Think of it like the layout of a filing cabinet:

    • Each drawer (like a table in a database) has a label.
    • Inside each drawer, the folders (like rows) hold specific types of information.
    • The schema tells you what kind of information goes in each folder—like a name, a date, or a number—and in what order.

    So, a schema helps computers know what data to expect, where to find it, and how to keep it organized. It’s used in things like databases, websites, and apps to manage information clearly and consistently.

    Fine-Tuning AI for Education and Training

    By Robert N. Bilyk

    Introduction

    Adaptive learning has long been described as the “holy grail of education.” This metaphor reflects the enduring hope that technology could one day deliver truly personalized instruction at scale. Yet, despite major investments, many adaptive learning platforms have fallen short in the past — often constrained by limited semantic engines.

    A semantic engine (also known as a semantic layer or reasoning engine) plays a critical role in adaptive learning. It connects the dots between educational content, learner behavior, and instructional objectives — enabling systems to respond intelligently to student needs. But until recently, these engines lacked the depth and flexibility to deliver on the promise of adaptivity.

    That’s where artificial intelligence — and especially large language models (LLMs) — change the equation. AI now makes personalized learning achievable. But that benefit is not limited to commercial adaptive learning platforms and well-heeled institutions. Thanks to the open availability of foundational models and the ability to fine-tune them, individual educators and small consortia can now create custom learning systems tailored to their domains and learners.

    While training a foundational LLM like GPT involves vast resources, fine-tuning an existing model requires far less: it’s an affordable and practical pathway for educators to shape AI for instructional use.

    In this article, I invite educators and trainers to explore the potential of fine-tuning. I’ll walk through practical use cases and outline the steps — first at a high level, then with technical detail. In the appendices, I’ll share a case study from LodeStar Learning’s own fine-tuning experience, along with examples of larger-scale educational projects.

    But first, let’s start with the basics.

    What is Fine-Tuning?

    Fine-tuning has tremendous potential for educators and trainers, but it is not generally well understood, especially outside of technical or AI development circles. Among educators, even those actively exploring AI tools, the term is often misunderstood or confused with things like “prompt engineering” or “custom instructions.”

    Fine-tuning isn’t just another AI tool—it’s how you make AI work for you. Here’s why fine-tuning deserves educators’ attention, even in a crowded AI landscape:

    Most AI Apps Are One-Size-Fits-All

    • Many AI tools are built for general audiences—business, marketing, tech—not education.
    • Fine-tuning allows you to shape the AI so it understands your subject matter, your students, and your learning outcomes.
    • Instead of adapting your instruction to fit the tool, you adapt the tool to fit your instruction.

    Think of a general AI model as a very well-read assistant. It knows a lot about a wide range of topics but doesn’t yet “speak your language” as a teacher or trainer. Fine-tuning is like giving that assistant professional development training—focused on your curriculum, your students, and your goals.

    It involves training a publicly available AI model further using examples from your own content—lesson plans, questions, feedback, case studies, or dialogues—so that it behaves more like a trusted co-teacher or tutor in your classroom.  The fine-tuned model becomes your own highly customized model with its own identity.  Instead of using GPT-4o or Claude3  or Gemini 1.5, you would reference your very own model by its unique ID. 

    Your Model: ft:gpt-4o-2024-09-06:personal:Algebra:AuBdgrvA

    Why Does This Matter to Educators?

    • Contextual Accuracy: The AI will understand your subject area better. For example, it won’t confuse “function” in math with “function” in biology.
    •  Instructional Alignment: You can shape the way the AI gives feedback—encouraging a growth mindset, using scaffolding, or promoting critical thinking.
    • Better Engagement: It can respond in a tone or style that matches your learners by being age-appropriate, culturally sensitive, encouraging, or even with a bit of humor.

    Example

    Without fine-tuning:

    “What is photosynthesis?”
    The AI gives a textbook-style answer. 

    Photosynthesis is the process by which…”

    With fine-tuning:

    “What is photosynthesis?”


    The AI responds in a way that matches your curriculum and grade level:
    “Great question! Remember how we talked about leaves being tiny factories? Photosynthesis is how they make food using sunlight, water, and air…”

    Why would educators and trainers wish to fine-tune existing AI Models? 

    Here are some specific use cases:

    1. Personalized Learning

    • Objective: Improve learner engagement and comprehension.
    • How fine-tuning helps: A fine-tuned model can adapt explanations, examples, and pacing to suit different learner profiles, prior knowledge levels, and preferences.
    • Example: Fine-tune a model to provide scaffolded help for struggling students while challenging advanced learners with deeper questions.

    2. Domain-Specific Expertise

    • Objective: Ensure accuracy and relevance in a specialized subject area.
    • How fine-tuning helps: By training on a curated corpus (e.g., medical case studies, engineering problem sets), the model becomes more accurate and confident within that domain.
    • Example: A nursing education model can be fine-tuned on NCLEX prep content to offer clinically accurate and context-sensitive responses.

    3. Instructional Strategy Alignment

    • Objective: Reinforce a pedagogical approach such as Socratic questioning, inquiry-based learning, or mastery learning.
    • How fine-tuning helps: The model can be trained to mimic an instructional persona that prompts, probes, or guides learners based on a chosen method.
    • Example: A fine-tuned tutor could continuously pose open-ended questions to help students reason through problems instead of giving direct answers.

    4. Scenario-Based or Simulation Training

    • Objective: Improve decision-making in complex, real-world situations.
    • How fine-tuning helps: You can train the model to simulate realistic dialogues or branching case studies that respond dynamically to learner input.
    • Example: In law or medicine, a fine-tuned model could role-play clients or patients to let learners practice legal argumentation or diagnosis.

    5. Feedback and Assessment Support

    • Objective: Provide timely, formative feedback to learners.
    • How fine-tuning helps: A model can be trained to evaluate short-answer responses or projects using rubrics, providing feedback that is both automated and pedagogically aligned.
    • Example: Fine-tune a model to assess student writing with an emphasis on clarity, coherence, and grammar—mirroring how a human instructor would grade.

    6. Support for Educators

    • Objective: Reduce teacher workload while enhancing instructional quality.
    • How fine-tuning helps: AI can assist in generating lesson plans, quizzes, or alternative explanations tailored to curriculum goals.
    • Example: A model fine-tuned on a specific curriculum can auto-generate practice problems and answer keys aligned with learning objectives.

    7. Cultural and Contextual Relevance

    • Objective: Make learning content inclusive and locally relevant.
    • How fine-tuning helps: The model can be trained on materials that reflect regional contexts, cultural values, or the linguistic style of the learner audience.
    • Example: A model used in Indigenous education could be fine-tuned on local stories, language use, and values for culturally responsive instruction.

    But Let’s Get Practical:

    Now that I’ve touted the benefits of fine-tuning, it’s time to be practical.  First, I encourage educators to partner with a computer programmer.   As an educator, your role in fine-tuning is invaluable.  You know the content, the audience, the tone, the examples, and so on.  But the mechanics of properly formatting a file, submitting the file to an AI service, and then referencing that file for fine-tuning require a little technical expertise. Different people have different expertise.  I highly encourage educators and trainers to partner with someone who is comfortable writing code.  The educator will know the end goal, and how to prompt the model for accuracy and alignment.  The programmer will understand the mechanics of how to prepare the dataset, send the dataset, and fine-tune an existing model with the dataset.

    Sometimes it takes a village.

    Secondly, as an educator or as an instructional designer, you can’t do this casually.  It will require quite an investment of time and so the model must be something you will use again and again.  To give you a rough idea of the scope of this task, for a highly specialized topic that is narrow in scope, it may require 100 to 500 examples. It will require you to write between 500 and 1000 examples to fine tune a model for a basic algebra course.   If you were instructing the model to support deep, tutor-like mastery with adaptive responses: 50,000+ examples would be ideal—more if you expect varied reasoning steps and multiple solution paths.  Clearly, this would be beyond the reach of a single individual.  It may require a consortium or state system of educators or designers to build a shared model for adaptive learning in a specific topic.

    Given those caveats, consider the basic steps in the process.

    What is involved in fine-tuning?

    From the educator’s perspective, the most important steps in fine-tuning an AI model are:

    • defining the fine-tuning objective
    • partnering with a programmer to prepare and upload the datasets (e.g. training examples)
    • monitoring the progress
    • planning how students will access the model
    • and evaluating the fine-tuned model for accuracy and effectiveness

    In defining the fine-tune objective, you need to consider carefully the purpose and scope of your project.  Are you fine-tuning an AI model to support a specialized topic or entire subject (e.g. College Level Algebra) at a specific grade level? Are you training AI to deliver straightforward answers in a particular tone and style, or are you training AI to be, for example, Socratic in its responses. That is, asking guiding questions rather than giving direct answers.

    Steps in the Fine-tuning Process

    Fine-tuning in a little more detail

    Step 1: Define the Fine-Tuning Objective

    Before you begin, clarify what you want the model to learn. Typical fine-tuning objectives include:

    • Domain (topic) adaptation (e.g., legal, medical, instructional content)
    • Format conditioning (e.g., Q&A, code completion)
    • Behavior change (e.g., being more verbose, precise, or concise)

    Step 2: Prepare Your Dataset

    Fine-tuning requires high-quality data formatted as JSON (Javascript Object Notation) or JSONL (JSON Lines). Each line must contain a conversation structured as follows:

    System: You are a helpful assistant

    User: How do you declare a variable.

    Content: Use the ‘var’ keyword…

    That seems simple enough, but the instruction is formatted like so:

    {“messages”: [{“role”: “system”, “content”: “You are a helpful assistant.”}, {“role”: “user”, “content”: “How do you declare a variable?”}, {“role”: “assistant”, “content”: “Use the ‘var’ keyword like this: var x = 5;”}]}

    This may appear as gobblygook to you, but here is where your computer programmer comes in.   If they know JSON notation, they will know the meaning of a { curly brace versus a [.  This formatting will make sense to them. 


    Step 3: Upload the Dataset

    Your programmer can use a command line interface with such commands as follows:

    openai file upload –purpose=fine-tune –file your_dataset.jsonl

    At LodeStar Learning, we prefer to use PostMan with the following OpenAI end point:

    https://api.openai.com/v1/files

    Essentially, Postman is a tool for API development and testing.

    In simpler terms, it’s a software tool that lets developers (and non-developers) send requests to Application Programmer Interfaces (APIs) and see the responses—without needing to write any code.

    Postman uses the URL endpoint to send an encrypted authorization token and the JSON file that was created in step two.


    Step 4: Start the Fine-Tuning Job

    Initiate training by referencing the uploaded file:

    openai fine_tunes.create -t <file-id> -m gpt-3.5-turbo

    You can specify parameters such as:

    • –suffix to name your model
    • –validation_file if you want to track validation loss

    Again, we use Postman for this step.   The endpoint is https://api.openai.com/v1/fine_tuning/jobs   The message to this end-point includes the name of the model and the name of dataset file that was previously uploaded.


    Step 5: Monitor the Training

    Use the command line interface or dashboard to watch for training loss, and completion status.


    Step 6: Use Your Fine-Tuned Model

    Once complete, your model will be listed under your organization.

    In LodeStar we access the model like we do any other model – through an API.  Our fine-tuned model now has a distinct ID.  Your programmer partner can also use the OpenAI API or set up access through a tool like Google CoLab.

    For the latter, the programmer would follow these steps:

    1. Identify the OpenAI API key, the fine-tuned model ID, and the desired system prompt (e.g. ‘Your are a kind and encouraging college teacher.’)
    2. Create a Google Colab Notebook and install the openai and gradio dependencies
    3. Import the the openai key, model id, and system prompt into the notebook
    4. Define the chatbot function
    5. ‘Create and launch the Gradio app.
    6. Share the public Gradio link with students.

    Step 7: Evaluate and Iterate

    Test your fine-tuned model:

    • Compare outputs to original model.  (OpenAI offers Playground to compare the outputs.)
    • Use test prompts
    • Revise and repeat if needed

    Conclusion

    Today, AI models—particularly large language models—bring the vision of personalized instruction within reach. The ability to fine-tune large language models for specific instructional purposes is now accessible to individual educators or collaborative groups. Thanks to the openness of these models and the growing availability of fine-tuning tools, the dream of personalized instruction is no longer out of reach—it is becoming a practical reality.

    Appendix A

    The Need for Fine-Tuning at LodeStar Learning

    We had our own special use case for fine-tuning.   We were reading post after post of Learning Experience Designers who have stretched the limitations of their tool with a little bit of scripting.  Toward that end, we developed our own scripting language that combines complex operations into simple commands.  In the past couple of years, general AI models have provided marginally correct answers to questions posed about our language.   But how can we improve on that?    How can we move from marginally correct to reliable answers.  The answer is fine-tuning the models. 

    LodeStar Learning’s example

    Prompt:  Get the learner’s score and total score.  Send an xapi statement that the learner experienced the score for an activity named Picasso.  If the learner scores more 80% or greater, send them to an enrichment page; if not, send them to a basic page.

    LodeStar’s Scripting Editor with Test Button

    The correct script would be:

    var score = getUserScore();
    var total = getTotalScore();
    var percentage = (score / total) * 100;
    sendXAPIStatement(“experienced”, “score”, “Picasso”);

    if (percentage >= 80) {
    jumpToPage(“enrichment”)
    } else {
    jumpToPage(“basic”);
    }

    The current fine-tuned model got it wrong in a couple of places.   It used getValue rather than getUserScore().  LodeStar automatically saves the user score in a place retrieved by getUserScore.  The getValue function would require an extra step in saving the user score to the ‘score’ variable.

    The remedy to the current model deficiencies is more fine-tuning.  We will keep sending the model examples of correct code.   We hope to reduce the errors in time.

    In the following example, AI provided a fictitious function ‘goToPage’ .  The correct function is jumpToPage.    When the author clicks on the ‘Test’ button, the error is highlighted.  A Help function lists all of the available functions to help the author correct the mistake.

    LodeStar’s Scripting Editor with Test Button

    Appendix B: Other larger scale examples of Fine-Tuned models

    1. Socratic Tutor Models (e.g., by OpenAI + Khan Academy)

    • Fine-tuned for: Guiding students through step-by-step reasoning, especially in math, physics, and humanities.
    • How it helps: These models are trained with carefully designed Socratic prompts to encourage thinking, not just answer-giving.
    • Example: A student learning about the French Revolution might be asked, “What do you think motivated the Third Estate to revolt?” rather than being given the answer directly.

    2. AI Reading Tutors (e.g., Google’s Read Along / Bolo)

    • Fine-tuned for: Reading fluency and pronunciation.
    • How it helps: These models are tuned on phonetic reading patterns and child speech to provide immediate feedback, encouragement, and progress tracking in early reading skills.

    3. AI for Language Learning (e.g., Duolingo’s Birdbrain)

    • Fine-tuned for: Adaptive language learning paths.
    • How it helps: Duolingo fine-tuned Birdbrain to estimate learner knowledge and select the next best challenge in Spanish, French, English, etc., based on personalized progress.