Building a Command Line Physics Calculations Application with an IIFE Module Pattern
In the previous article, I discussed immediately invoked function expressions or IIFE for short (Link). Now we will use some IIFE programming to construct an interactive command line application which solves basic physics problem. Previously, I created an IIFE based module called iifePhysicsCalculations.js. //iifePhysicsCalculations.js export const physicsCalculations = ( function () { //the below constants are private variables const g = 9.80665; //gravity constant in meters/second squared const c = 299792458; //speed of light in m/s //functions to be returned as methods in this module const velocity = (distance, time) => distance / time; const acceleration = (speed, time) => speed / time; const potentialEnergy = (mass, height) => mass * g * height; const momentum = (mass, speed) => mass * speed; const energy = (mass) => mass * (c ** 2); const force = (mass, acc) => mass * acc; const kineticEnergy = (mass, speed) => 0.5 * mass * (speed ** 2); //object containing named methods including two getter methods return { velocity, acceleration, potentialEnergy, momentum, energy, force, kineticEnergy, getSpeedOfLight: () => c, getGravityConstant: () => g } } )(); The above module will be exported but in order to do this let us create a basic package.jsonfile. This will allow us to import our modules in other files. //package.json { "type": "module" } We also need a way to generate the text associated with the prompts that will appear on the command line. I am creating a file called PhysicsEquations.js. This is another export module. //PhysicsEquations.js export const physicsEquations = [ { id: '1', calculation: "Velocity (V = distance/time)", entries: ["distance in meters", "time in seconds to travel distance"], units: 'meters per second' }, { id: '2', calculation: "Acceleration (A = change in velocity/time)", entries: ["change in velocity in meters per second", "time in seconds to reach velocity"], units: 'meters per second squared' }, { id: '3', calculation: "Potential Energy (PE = mgh)", entries: ["mass in kilograms", "height in meters"], units: 'Joules' }, { id: '4', calculation: "Momentum (M = mv)", entries: ["mass in kilograms", "speed in meters per second"], units: 'kilogram meters per second' }, { id: '5', calculation: "Molecular Energy (E = mc^2)", entries: ["mass in kilograms"], units: 'Joules' }, { id: '6', calculation: "Force (F = ma)", entries: ["mass in kilograms", "acceleration in meters per second squared"], units: 'Newtons' }, { id: '7', calculation: "Kinetic Energy (KE = (1/2)mv^2)", entries: ["mass in kilograms", "speed in meters per second"], units: 'Joules' }, ] Finally we will create the main application file itself, PhysicsCalculationsApp.js. This contains the logic for the command line inputs as well as imports for the other two modules. //PhysicsCalculationsApp.js import { physicsCalculations } from "./iifePhysicsCalculations.js"; import { physicsEquations } from "./PhysicsEquations.js"; import readline from 'node:readline'; const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const choices = physicsEquations.map(question => `\t${(physicsEquations.indexOf(question) + 1)}) ${question.calculation}`); const ids = physicsEquations.map(question => question.id); function calculate(equation, numbers) { switch (equation) { case '1': return physicsCalculations.velocity(...numbers); case '2': return physicsCalculations.acceleration(...numbers); case '3': return physicsCalculations.potentialEnergy(...numbers); case '4': return physicsCalculations.momentum(...numbers); case '5': return physicsCalculations.energy(...numbers); case '6': return physicsCalculations.force(...numbers); case '7': return physicsCalculations.kineticEnergy(...numbers); default: return NaN; } } const askQuestion = (question) => { return new Promise((resolve) => { rl.question(question, (answer) => { resolve(answer) }) }) }; function printChoices() { console.log('Physics Equations'); choices.forEach(choice => console.log(choice)); console.log('\t0) To exit\n'); } let calculating = true; while (calculating) { let numbers = []; printChoices(); const choice = await askQuestion(`Type a number to select an equation: `); if (!ids.includes(choice)) break; const physicsQuestion = physicsEquations.find(question =>

In the previous article, I discussed immediately invoked function expressions or IIFE for short (Link). Now we will use some IIFE programming to construct an interactive command line application which solves basic physics problem. Previously, I created an IIFE based module called iifePhysicsCalculations.js
.
//iifePhysicsCalculations.js
export const physicsCalculations = (
function () {
//the below constants are private variables
const g = 9.80665; //gravity constant in meters/second squared
const c = 299792458; //speed of light in m/s
//functions to be returned as methods in this module
const velocity = (distance, time) => distance / time;
const acceleration = (speed, time) => speed / time;
const potentialEnergy = (mass, height) => mass * g * height;
const momentum = (mass, speed) => mass * speed;
const energy = (mass) => mass * (c ** 2);
const force = (mass, acc) => mass * acc;
const kineticEnergy = (mass, speed) => 0.5 * mass * (speed ** 2);
//object containing named methods including two getter methods
return {
velocity,
acceleration,
potentialEnergy,
momentum,
energy,
force,
kineticEnergy,
getSpeedOfLight: () => c,
getGravityConstant: () => g
}
}
)();
The above module will be exported but in order to do this let us create a basic package.json
file. This will allow us to import our modules in other files.
//package.json
{
"type": "module"
}
We also need a way to generate the text associated with the prompts that will appear on the command line. I am creating a file called PhysicsEquations.js
. This is another export module.
//PhysicsEquations.js
export const physicsEquations = [
{
id: '1',
calculation: "Velocity (V = distance/time)",
entries: ["distance in meters", "time in seconds to travel distance"],
units: 'meters per second'
},
{
id: '2',
calculation: "Acceleration (A = change in velocity/time)",
entries: ["change in velocity in meters per second", "time in seconds to reach velocity"],
units: 'meters per second squared'
},
{
id: '3',
calculation: "Potential Energy (PE = mgh)",
entries: ["mass in kilograms", "height in meters"],
units: 'Joules'
},
{
id: '4',
calculation: "Momentum (M = mv)",
entries: ["mass in kilograms", "speed in meters per second"],
units: 'kilogram meters per second'
},
{
id: '5',
calculation: "Molecular Energy (E = mc^2)",
entries: ["mass in kilograms"],
units: 'Joules'
},
{
id: '6',
calculation: "Force (F = ma)",
entries: ["mass in kilograms", "acceleration in meters per second squared"],
units: 'Newtons'
},
{
id: '7',
calculation: "Kinetic Energy (KE = (1/2)mv^2)",
entries: ["mass in kilograms", "speed in meters per second"],
units: 'Joules'
},
]
Finally we will create the main application file itself, PhysicsCalculationsApp.js. This contains the logic for the command line inputs as well as imports for the other two modules.
//PhysicsCalculationsApp.js
import { physicsCalculations } from "./iifePhysicsCalculations.js";
import { physicsEquations } from "./PhysicsEquations.js";
import readline from 'node:readline';
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const choices = physicsEquations.map(question => `\t${(physicsEquations.indexOf(question) + 1)}) ${question.calculation}`);
const ids = physicsEquations.map(question => question.id);
function calculate(equation, numbers) {
switch (equation) {
case '1': return physicsCalculations.velocity(...numbers);
case '2': return physicsCalculations.acceleration(...numbers);
case '3': return physicsCalculations.potentialEnergy(...numbers);
case '4': return physicsCalculations.momentum(...numbers);
case '5': return physicsCalculations.energy(...numbers);
case '6': return physicsCalculations.force(...numbers);
case '7': return physicsCalculations.kineticEnergy(...numbers);
default: return NaN;
}
}
const askQuestion = (question) => {
return new Promise((resolve) => {
rl.question(question, (answer) => {
resolve(answer)
})
})
};
function printChoices() {
console.log('Physics Equations');
choices.forEach(choice => console.log(choice));
console.log('\t0) To exit\n');
}
let calculating = true;
while (calculating) {
let numbers = [];
printChoices();
const choice = await askQuestion(`Type a number to select an equation: `);
if (!ids.includes(choice)) break;
const physicsQuestion = physicsEquations.find(question => question.id === choice);
console.log(physicsQuestion.calculation);
for (const entry of physicsQuestion.entries) {
const number = await askQuestion(`Enter ${entry}: `);
numbers.push(number)
}
console.log(`${physicsQuestion.calculation.split(' (')[0]} = ${calculate(choice, numbers)} ${physicsQuestion.units}\n`);
}
rl.close();
If you follow these steps, you will quickly have a command line application at your disposal to solve basic physics problems. We took the concept of IIFE and used it to create a small modular application.