feat: 完善中文心理测评平台
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import { QuestionType } from "@/types";
|
||||
|
||||
/**
|
||||
* Gender Dysphoria Questionnaire calculator parameters interface
|
||||
*/
|
||||
interface GDCalculatorProps {
|
||||
/** Answer data, key is question ID, value is selected score */
|
||||
answers: { [key: number]: string };
|
||||
/** Questions list */
|
||||
questions: QuestionType[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Gender Dysphoria Questionnaire (GDQ) results
|
||||
*
|
||||
* @param answers - User answer data, containing question ID and selected score
|
||||
* @returns Calculation results, including total score, factor scores, and other information
|
||||
*/
|
||||
export const calculateGDResults = ({ answers }: GDCalculatorProps): any => {
|
||||
// Gender Dysphoria calculation logic
|
||||
let totalRawScore = 0;
|
||||
|
||||
// Reverse-scored items (questions where agreement indicates comfort with assigned gender)
|
||||
const reverseItems = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25];
|
||||
|
||||
// Calculate total score with reverse scoring
|
||||
Object.entries(answers).forEach(([questionId, score]) => {
|
||||
const questionNum = parseInt(questionId);
|
||||
const scoreValue = parseInt(score);
|
||||
|
||||
if (reverseItems.includes(questionNum)) {
|
||||
// Reverse score: 7 becomes 1, 6 becomes 2, etc.
|
||||
totalRawScore += (8 - scoreValue);
|
||||
} else {
|
||||
totalRawScore += scoreValue;
|
||||
}
|
||||
});
|
||||
|
||||
// Calculate factor scores based on conceptual dimensions
|
||||
let genderIdentityScore = 0; // Questions about internal gender identity
|
||||
let socialRoleScore = 0; // Questions about social gender roles
|
||||
let physicalDysphoriaScore = 0; // Questions about physical characteristics
|
||||
let genderExpressionScore = 0; // Questions about gender expression
|
||||
|
||||
Object.entries(answers).forEach(([questionId, score]) => {
|
||||
const questionNum = parseInt(questionId);
|
||||
let scoreValue = parseInt(score);
|
||||
|
||||
// Apply reverse scoring if needed
|
||||
if (reverseItems.includes(questionNum)) {
|
||||
scoreValue = 8 - scoreValue;
|
||||
}
|
||||
|
||||
// Assign to factor scores based on question content
|
||||
if ([2, 4, 6, 17, 18, 20, 22, 24, 27].includes(questionNum)) {
|
||||
genderIdentityScore += scoreValue;
|
||||
} else if ([5, 7, 12, 19, 21, 26].includes(questionNum)) {
|
||||
socialRoleScore += scoreValue;
|
||||
} else if ([3, 9, 10, 13, 15, 16].includes(questionNum)) {
|
||||
physicalDysphoriaScore += scoreValue;
|
||||
} else if ([1, 8, 11, 14, 23, 25].includes(questionNum)) {
|
||||
genderExpressionScore += scoreValue;
|
||||
}
|
||||
});
|
||||
|
||||
// Determine general interpretation level
|
||||
const totalPossibleScore = Object.keys(answers).length * 7;
|
||||
const scorePercentage = (totalRawScore / totalPossibleScore) * 100;
|
||||
|
||||
let interpretation = "low";
|
||||
if (scorePercentage >= 30 && scorePercentage < 50) {
|
||||
interpretation = "mild";
|
||||
} else if (scorePercentage >= 50 && scorePercentage < 70) {
|
||||
interpretation = "moderate";
|
||||
} else if (scorePercentage >= 70) {
|
||||
interpretation = "high";
|
||||
}
|
||||
|
||||
// Calculate factor scores
|
||||
const factorScores: { [key: string]: number } = {
|
||||
"genderIdentity": genderIdentityScore,
|
||||
"socialRole": socialRoleScore,
|
||||
"physicalDysphoria": physicalDysphoriaScore,
|
||||
"genderExpression": genderExpressionScore
|
||||
};
|
||||
|
||||
// Count items with scores above neutral (>4 after reverse scoring)
|
||||
const elevatedItems = Object.entries(answers).filter(([questionId, score]) => {
|
||||
const questionNum = parseInt(questionId);
|
||||
let scoreValue = parseInt(score);
|
||||
|
||||
if (reverseItems.includes(questionNum)) {
|
||||
scoreValue = 8 - scoreValue;
|
||||
}
|
||||
|
||||
return scoreValue > 4;
|
||||
}).length;
|
||||
|
||||
// Return complete calculation results
|
||||
return {
|
||||
totalScore: totalRawScore,
|
||||
factorScores,
|
||||
positiveItemCount: elevatedItems,
|
||||
positiveItemAverage: totalRawScore / Object.keys(answers).length,
|
||||
isSevere: interpretation === "high",
|
||||
interpretation,
|
||||
scorePercentage: Math.round(scorePercentage),
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user