feat: 完善中文心理测评平台
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import { QuestionType } from "@/types";
|
||||
|
||||
/**
|
||||
* Narcissistic Personality Inventory calculator parameters interface
|
||||
*/
|
||||
interface NPDCalculatorProps {
|
||||
/** Answer data, key is question ID, value is selected score */
|
||||
answers: { [key: number]: string };
|
||||
/** Questions list */
|
||||
questions: QuestionType[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Narcissistic Personality Inventory (NPI-16) results
|
||||
*
|
||||
* @param answers - User answer data, containing question ID and selected score
|
||||
* @returns Calculation results, including total score, factor scores, severity level and other information
|
||||
*/
|
||||
export const calculateNPDResults = ({ answers }: NPDCalculatorProps): any => {
|
||||
// NPI-16 calculation logic
|
||||
let totalScore = 0;
|
||||
|
||||
// Subscale score initialization based on NPI factors
|
||||
let leadershipAuthorityScore = 0; // Leadership/Authority subscale
|
||||
let grandioseExhibitionismScore = 0; // Grandiose Exhibitionism subscale
|
||||
let entitlementScore = 0; // Entitlement subscale
|
||||
|
||||
// Calculate total score and subscale scores
|
||||
Object.entries(answers).forEach(([questionId, score]) => {
|
||||
const questionNum = parseInt(questionId);
|
||||
const scoreValue = parseInt(score);
|
||||
|
||||
totalScore += scoreValue;
|
||||
|
||||
// Assign to subscales based on NPI-16 factor structure
|
||||
// Leadership/Authority: questions 1, 8, 10, 11, 12
|
||||
if ([1, 8, 10, 11, 12].includes(questionNum)) {
|
||||
leadershipAuthorityScore += scoreValue;
|
||||
}
|
||||
// Grandiose Exhibitionism: questions 2, 3, 7, 15
|
||||
else if ([2, 3, 7, 15].includes(questionNum)) {
|
||||
grandioseExhibitionismScore += scoreValue;
|
||||
}
|
||||
// Entitlement: questions 4, 5, 6, 9, 13, 14, 16
|
||||
else if ([4, 5, 6, 9, 13, 14, 16].includes(questionNum)) {
|
||||
entitlementScore += scoreValue;
|
||||
}
|
||||
});
|
||||
|
||||
// Determine interpretation level based on total score
|
||||
// Based on research, average scores typically range from 2-8 in general population
|
||||
let interpretation = "low";
|
||||
if (totalScore >= 4 && totalScore <= 7) {
|
||||
interpretation = "average";
|
||||
} else if (totalScore >= 8 && totalScore <= 11) {
|
||||
interpretation = "above_average";
|
||||
} else if (totalScore >= 12) {
|
||||
interpretation = "high";
|
||||
}
|
||||
|
||||
// Calculate percentile approximation
|
||||
let percentile = 0;
|
||||
if (totalScore <= 2) percentile = 25;
|
||||
else if (totalScore <= 5) percentile = 50;
|
||||
else if (totalScore <= 8) percentile = 75;
|
||||
else if (totalScore <= 11) percentile = 90;
|
||||
else percentile = 95;
|
||||
|
||||
// Calculate factor scores
|
||||
const factorScores: { [key: string]: number } = {
|
||||
"leadership": leadershipAuthorityScore,
|
||||
"exhibitionism": grandioseExhibitionismScore,
|
||||
"entitlement": entitlementScore
|
||||
};
|
||||
|
||||
// Identify dominant traits
|
||||
const dominantTrait = Object.entries(factorScores).reduce((a, b) =>
|
||||
factorScores[a[0]] > factorScores[b[0]] ? a : b
|
||||
)[0];
|
||||
|
||||
// Return complete calculation results
|
||||
return {
|
||||
totalScore,
|
||||
factorScores,
|
||||
positiveItemCount: totalScore, // For NPI, each item is either 0 or 1
|
||||
positiveItemAverage: totalScore / Object.keys(answers).length,
|
||||
isSevere: interpretation === "high",
|
||||
interpretation,
|
||||
percentile,
|
||||
dominantTrait,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user