RICE/ICE Calculator
Calculate prioritization scores using RICE or ICE frameworks
Source Code
import { readFileSync, writeFileSync } from "fs";
const [inputFile, outputFile, sensitivity] = process.argv.slice(2);
// Read input data
const input = JSON.parse(readFileSync(inputFile, "utf-8"));
const framework = input.framework?.toLowerCase() || "rice";
const initiatives = input.initiatives || [];
if (initiatives.length === 0) {
console.log(JSON.stringify({ error: "No initiatives provided" }));
process.exit(1);
}
// Calculate scores based on framework
function calculateRICE(initiative) {
const { reach, impact, confidence, effort } = initiative;
if (!reach || !impact || !confidence || !effort) {
return { score: 0, error: "Missing required fields" };
}
const score = (reach * impact * confidence) / effort;
return {
score: Math.round(score * 100) / 100,
breakdown: {
reach,
impact,
confidence,
effort,
formula: `(${reach} × ${impact} × ${confidence}) / ${effort}`,
},
};
}
function calculateICE(initiative) {
const { impact, confidence, ease } = initiative;
if (!impact || !confidence || !ease) {
return { score: 0, error: "Missing required fields" };
}
const score = impact * confidence * ease;
return {
score: Math.round(score * 100) / 100,
breakdown: {
impact,
confidence,
ease,
formula: `${impact} × ${confidence} × ${ease}`,
},
};
}
// Score all initiatives
const scored = initiatives.map((initiative) => {
const calc = framework === "ice" ? calculateICE(initiative) : calculateRICE(initiative);
return {
name: initiative.name,
description: initiative.description || "",
...calc,
};
});
// Sort by score descending
scored.sort((a, b) => b.score - a.score);
// Add rankings
const ranked = scored.map((item, index) => ({
rank: index + 1,
...item,
}));
// Sensitivity analysis (if requested)
let sensitivityAnalysis = null;
if (sensitivity === "true" && framework === "rice") {
sensitivityAnalysis = ranked.slice(0, 3).map((item) => {
const original = initiatives.find((i) => i.name === item.name);
if (!original) return null;
// What if effort is 50% higher?
const effortHigher = calculateRICE({ ...original, effort: original.effort * 1.5 });
// What if reach is 30% lower?
const reachLower = calculateRICE({ ...original, reach: original.reach * 0.7 });
// What if confidence drops to 50%?
const lowConfidence = calculateRICE({ ...original, confidence: 0.5 });
return {
name: item.name,
originalScore: item.score,
scenarios: {
"effort +50%": {
newScore: effortHigher.score,
change: `${Math.round(((effortHigher.score - item.score) / item.score) * 100)}%`,
},
"reach -30%": {
newScore: reachLower.score,
change: `${Math.round(((reachLower.score - item.score) / item.score) * 100)}%`,
},
"confidence → 50%": {
newScore: lowConfidence.score,
change: `${Math.round(((lowConfidence.score - item.score) / item.score) * 100)}%`,
},
},
};
}).filter(Boolean);
}
// Build output
const output = {
framework: framework.toUpperCase(),
initiativeCount: ranked.length,
ranked,
...(sensitivityAnalysis && { sensitivityAnalysis }),
generatedAt: new Date().toISOString(),
};
// Write output
writeFileSync(outputFile, JSON.stringify(output, null, 2));
console.log(`Scored ${ranked.length} initiatives using ${framework.toUpperCase()}`);
console.log(`Top 3:`);
ranked.slice(0, 3).forEach((item) => {
console.log(` ${item.rank}. ${item.name} (score: ${item.score})`);
});
console.log(`Full results written to ${outputFile}`);