CP_Assessment_engine/services/cognition_simulator.py
2026-02-10 12:59:40 +05:30

194 lines
11 KiB
Python

"""
Cognition Simulator v1.0 - World Class Expertise
Generates realistic aggregated metrics for cognition tests based on student profiles.
"""
import random
import pandas as pd
from typing import Dict, List, Any
class CognitionSimulator:
def __init__(self):
pass
def simulate_student_test(self, student: Dict, test_name: str, age_group: str) -> Dict:
"""
Simulates aggregated metrics for a specific student and test.
"""
# Baseline performance from student profile (Cognitive Overall score if available, or random 6-9)
# Using numeric scores from 3000-students.xlsx if possible, otherwise random high-quality baseline.
# Note: 3000-students.xlsx has: Openness, Conscientiousness, etc.
# We can derive baseline from Conscientiousness (diligence) and Openness (curiosity/speed).
conscientiousness = student.get('Conscientiousness Score', 70) / 10.0
openness = student.get('Openness Score', 70) / 10.0
baseline_accuracy = (conscientiousness * 0.6 + openness * 0.4) / 10.0 # 0.0 to 1.0
# Add random variation
accuracy = min(max(baseline_accuracy + random.uniform(-0.1, 0.15), 0.6), 0.98)
rt_baseline = 1500 - (accuracy * 500) # Faster accuracy usually means faster RT in these tests
participant = f"{student.get('First Name', '')} {student.get('Last Name', '')}".strip()
cpid = student.get('StudentCPID', 'UNKNOWN')
# Test specific logic
if 'Problem_Solving' in test_name or 'Reasoning' in test_name:
total_rounds = 26 if age_group == '14-17' else 31
correct = int(total_rounds * accuracy)
incorrect = total_rounds - correct
if 'SBDM' in test_name: # Special schema
return {
"Participant": participant,
"Student CPID": cpid,
"Total Rounds Answered": total_rounds,
"Total Rounds not Answered": int(0),
"Overall C_score": int(correct * 2),
"Overall N_score": int(incorrect),
"Overall I_Score": int(random.randint(5, 15)),
"Average C_Score": float(round((correct * 2.0) / total_rounds, 2)),
"Average N_Score": float(round(float(incorrect) / total_rounds, 2)),
"Average I_Score": float(round(random.uniform(0.5, 1.5), 2)),
"Average Reaction Time for the task": float(round(float(rt_baseline) + random.uniform(-100, 200), 2))
}
return {
"Participant": participant,
"Student CPID": cpid,
"Total Rounds Answered": total_rounds,
"Total Rounds not Answered": 0,
"No. of Correct Responses": correct,
"No. of Incorrect Responses": incorrect,
"Total Score of the Task": correct,
"Average Reaction Time": float(round(float(rt_baseline + random.uniform(-100, 300)), 2))
}
elif 'Cognitive_Flexibility' in test_name:
total_rounds = 72
correct = int(total_rounds * accuracy)
incorrect = total_rounds - correct
return {
"Participant": participant,
"Student CPID": cpid,
"Total Rounds Answered": total_rounds,
"Total Rounds not Answered": 0,
"No. of Correct Responses": correct,
"No. of Incorrect Responses": incorrect,
"Total Score of the Task": correct,
"Average Reaction Time": float(round(float(rt_baseline * 0.8), 2)),
"No. of Reversal Errors": int(random.randint(2, 8)),
"No. of Perseveratory errors": int(random.randint(1, 5)),
"No.of Final Reversal Errors": int(random.randint(1, 3)),
"Win-Shift rate": float(round(float(random.uniform(0.7, 0.95)), 2)),
"Lose-Shift Rate": float(round(float(random.uniform(0.1, 0.3)), 2)),
"Overall Accuracy": float(round(float(accuracy * 100.0), 2))
}
elif 'Color_Stroop' in test_name:
total_rounds = 80
congruent_acc = accuracy + 0.05
incongruent_acc = accuracy - 0.1
return {
"Participant": participant,
"Student CPID": cpid,
"Total Rounds Answered": total_rounds,
"Total Rounds not Answered": 0,
"No. of Correct Responses": int(total_rounds * accuracy),
"No. of Correct Responses in Congruent Rounds": int(40 * congruent_acc),
"No. of Correct Responses in Incongruent Rounds": int(40 * incongruent_acc),
"No. of Incorrect Responses": int(total_rounds * (1-accuracy)),
"No. of Incorrect Responses in Congruent Rounds": int(40 * (1-congruent_acc)),
"No. of Incorrect Responses in Incongruent Rounds": int(40 * (1-incongruent_acc)),
"Total Score of the Task": int(total_rounds * accuracy),
"Congruent Rounds Average Reaction Time": float(round(float(rt_baseline * 0.7), 2)),
"Incongruent Rounds Average Reaction Time": float(round(float(rt_baseline * 1.2), 2)),
"Average Reaction Time of the task": float(round(float(rt_baseline), 2)),
"Congruent Rounds Accuracy": float(round(float(congruent_acc * 100.0), 2)),
"Incongruent Rounds Accuracy": float(round(float(incongruent_acc * 100.0), 2)),
"Overall Task Accuracy": float(round(float(accuracy * 100.0), 2)),
"Interference Effect": float(round(float(rt_baseline * 0.5), 2))
}
elif 'Sternberg' in test_name:
total_rounds = 120
correct = int(total_rounds * accuracy)
return {
"Participant": participant,
"Student CPID": cpid,
"Total Rounds Answered": total_rounds,
"Total Rounds not Answered": 0,
"No. of Correct Responses": correct,
"No. of Incorrect Responses": total_rounds - correct,
"Total Score of the Task": correct,
"Average Reaction Time for Positive Probes": float(round(float(rt_baseline * 1.1), 2)),
"Average Reaction Time for Negative Probes": float(round(float(rt_baseline * 1.15), 2)),
"Average Reaction Time": float(round(float(rt_baseline * 1.12), 2)),
"Overall Accuracy": float(round(float(accuracy * 100.0), 2)),
"Hit Rate": float(round(float(accuracy + 0.02), 2)),
"False Alarm Rate": float(round(float(random.uniform(0.05, 0.15)), 2)),
"Slope of RT vs Set Size": float(round(float(random.uniform(30.0, 60.0)), 2)),
"Response Bias": float(round(float(random.uniform(-0.5, 0.5)), 2)),
"Sensitivity (d')": float(round(float(random.uniform(1.5, 3.5)), 2))
}
elif 'Visual_Paired' in test_name:
total_rounds = 45
correct = int(total_rounds * accuracy)
return {
"Participant": participant,
"Student CPID": cpid,
"Total Rounds Answered": total_rounds,
"Total Rounds not Answered": 0,
"No. of Correct Responses": correct,
"No. of Incorrect Responses": total_rounds - correct,
"Total Score in Immediate Cued Recall test": int(random.randint(10, 15)),
"Total Score in Delayed Cued Recall test": int(random.randint(8, 14)),
"Total Score in Recognition test": int(random.randint(12, 15)),
"Total Score of the Task": int(correct),
"Immediate Cued Recall Average Reaction Time": float(round(float(rt_baseline * 1.5), 2)),
"Delayed Cued Recall Average Reaction Time": float(round(float(rt_baseline * 1.6), 2)),
"Recognition Phase Average Reaction time": float(round(float(rt_baseline * 1.2), 2)),
"Average Reaction Time": float(round(float(rt_baseline * 1.4), 2)),
"Immediate Cued Recall Accuracy Rate": float(round(float(accuracy * 100.0), 2)),
"Delayed Cued Recall Accuracy Rate": float(round(float((accuracy - 0.05) * 100.0), 2)),
"Recognition Phase Accuracy Rate": float(round(float((accuracy + 0.05) * 100.0), 2)),
"Overall Accuracy Rate": float(round(float(accuracy * 100.0), 2)),
"Consolidation Slope": float(round(float(random.uniform(-0.5, 0.1)), 2)),
"Consolidation Slope (%)": float(round(float(random.uniform(-10.0, 5.0)), 2))
}
elif 'Response_Inhibition' in test_name:
total_rounds = 60
correct = int(total_rounds * accuracy)
return {
"Participant": participant,
"Student CPID": cpid,
"Total Rounds Answered": total_rounds,
"Total Rounds not Answered": 0,
"No. of Correct Responses": correct,
"No. of Correct Responses in Go Rounds": int(40 * accuracy),
"No. of Correct Responses in No-Go Rounds": int(20 * (accuracy - 0.1)),
"No. of Incorrect Responses": total_rounds - correct,
"No. of Incorrect Responses in Go Rounds": int(40 * (1-accuracy)),
"No. of Incorrect Responses in No-Go Rounds": int(20 * (1-(accuracy-0.1))),
"Total Score of the Task": correct,
"Go Rounds Average Reaction Time": float(round(float(rt_baseline * 0.8), 2)),
"No- Rounds Average Reaction Time": float(round(float(rt_baseline * 1.2), 2)),
"Average Reaction Time of the task": float(round(float(rt_baseline), 2)),
"Go Rounds Accuracy": float(round(float(accuracy * 100.0), 2)),
"No-Go Rounds Accuracy": float(round(float((accuracy - 0.1) * 100.0), 2)),
"Overall Task Accuracy": float(round(float(accuracy * 100.0), 2)),
"No. of Commission Errors": int(random.randint(2, 10)),
"No. of Omission Error": int(random.randint(1, 5)),
"Omission Error Rate": float(round(float(random.uniform(0.01, 0.05)), 2)),
"Hit Rate": float(round(float(accuracy), 2)),
"False Alarm Rate": float(round(float(random.uniform(0.1, 0.3)), 2))
}
# Default fallback
return {
"Participant": participant,
"Student CPID": cpid,
"Total Rounds Answered": 0,
"Total Score of the Task": 0
}