Pure scoring logic matching the browser implementation. The host can provide question text separately, while this tool focuses only on deterministic answer scoring.
function main(args) {
const { answers } = args;
if (!Array.isArray(answers) || answers.length === 0) {
return { success: false, result: null, error: "answers is required" };
}
const dimensionMap = {
EI: { first: "E", second: "I" },
SN: { first: "S", second: "N" },
TF: { first: "T", second: "F" },
JP: { first: "J", second: "P" },
};
const likertWeights = {
1: 0,
2: 0.25,
3: 0.5,
4: 0.75,
5: 1,
};
const dimensionScores = {
EI: { first: 0, second: 0 },
SN: { first: 0, second: 0 },
TF: { first: 0, second: 0 },
JP: { first: 0, second: 0 },
};
for (const answer of answers) {
const dimension = answer.dimension;
const value = answer.value;
if (!dimensionMap[dimension] || !Object.prototype.hasOwnProperty.call(likertWeights, value)) {
return {
success: false,
result: null,
error: "Each answer must include a valid dimension and Likert value from 1 to 5",
};
}
const weightToSecond = likertWeights[value];
const weightToFirst = 1 - weightToSecond;
dimensionScores[dimension].first += weightToFirst;
dimensionScores[dimension].second += weightToSecond;
}
let type = "";
const percentages = {};
const scores = {};
for (const dimension of ["EI", "SN", "TF", "JP"]) {
const mapping = dimensionMap[dimension];
const firstScore = dimensionScores[dimension].first;
const secondScore = dimensionScores[dimension].second;
const total = firstScore + secondScore;
const winner = firstScore > secondScore ? mapping.first : mapping.second;
const winnerScore = winner === mapping.first ? firstScore : secondScore;
type += winner;
scores[mapping.first] = firstScore;
scores[mapping.second] = secondScore;
percentages[dimension] = total > 0 ? Math.round((winnerScore / total) * 100) : 50;
}
return {
success: true,
result: {
type,
scores,
percentages,
dimensionScores,
},
};
}