humanvprojectceo commited on
Commit
d69cb90
·
verified ·
1 Parent(s): 66e8694

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +140 -12
app.py CHANGED
@@ -27,6 +27,15 @@ BAI_OPTIONS = [
27
  {"score": 3, "text": "شدید (غیر قابل تحمل بود)", "label": "شدید (۱۰۰٪)", "color": 5}
28
  ]
29
 
 
 
 
 
 
 
 
 
 
30
  # دیتابیس آزمون اول: ۳۰ سوال MBTI
31
  MBTI_QUESTIONS = [
32
  {"id": 1, "text": "در رویدادهای اجتماعی، من معمولاً با افراد جدید زیادی صحبت می‌کنم، نه فقط با کسانی که می‌شناسم.", "dimension": "EI", "direction": 1},
@@ -86,7 +95,7 @@ BAI_QUESTIONS = [
86
  {"id": 21, "text": "عرق کردن شدید که ناشی از دمای محیط یا فعالیت بدنی نباشد.", "dimension": "somatic"}
87
  ]
88
 
89
- # آزمون سوم: ۲۱ سوال افسردگی بک (BDI-II) - همراه با گزینه‌های بالینی اختصاصی هر سوال [2]
90
  BDI_QUESTIONS = [
91
  {
92
  "id": 1,
@@ -311,6 +320,37 @@ BDI_QUESTIONS = [
311
  }
312
  ]
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  class AnswerItem(BaseModel):
315
  question_id: int
316
  score: int
@@ -318,14 +358,15 @@ class AnswerItem(BaseModel):
318
  class AnalysisRequest(BaseModel):
319
  first_name: str
320
  last_name: str
321
- test_type: str = Field(description="Type of test taken: 'mbti', 'bai', or 'bdi'")
322
  answers: List[AnswerItem]
323
 
324
  class UniversalAnalysisSchema(BaseModel):
325
- test_type: str = Field(description="The type of test taken ('mbti', 'bai', or 'bdi')")
326
  mbti_type: str = Field(description="MBTI 4-letter type. Leave blank if not MBTI.")
327
  bai_level: str = Field(description="BAI anxiety severity level. Leave blank if not BAI.")
328
  bdi_level: str = Field(description="BDI depression severity level. Leave blank if not BDI.")
 
329
  personality_title: str = Field(description="A creative Persian title representing their state/personality")
330
  introversion_score: int = Field(description="Percentage of Introversion (0-100)")
331
  extraversion_score: int = Field(description="Percentage of Extraversion (0-100)")
@@ -335,11 +376,11 @@ class UniversalAnalysisSchema(BaseModel):
335
  feeling_score: int = Field(description="Percentage of Feeling (0-100)")
336
  judging_score: int = Field(description="Percentage of Judging (0-100)")
337
  perceiving_score: int = Field(description="Percentage of Perceiving (0-100)")
338
- somatic_score: int = Field(description="Somatic/Physiological symptoms percentage (0-100)")
339
- cognitive_score: int = Field(description="Cognitive/Subjective symptoms percentage (0-100)")
340
- panic_score: int = Field(description="BAI: Panic/Fear symptoms percentage. Leave 0 if BDI.")
341
- affective_score: int = Field(description="BDI: Affective/Emotional symptoms percentage. Leave 0 if BAI.")
342
- total_score_raw: int = Field(description="Total raw score sum of BAI or BDI")
343
  summary: str = Field(description="A short Persian summary of the results (2-3 sentences)")
344
  strengths: List[str] = Field(description="Coping mechanisms, strengths or psychological resources (4-5 items in Persian)")
345
  weaknesses: List[str] = Field(description="Triggers, weaknesses, risk situations or symptoms to monitor (4-5 items in Persian)")
@@ -365,6 +406,13 @@ BDI_SYSTEM_INSTRUCTION = """
365
  لحن متن فوق‌العاده همدلانه، مهربان و امیدبخش باشد. بخش detailed_analysis را با تیترهای مارک‌داون جدا کنید.
366
  """
367
 
 
 
 
 
 
 
 
368
  def calculate_mbti_raw(answers: List[AnswerItem]):
369
  scores = {"EI": 0, "SN": 0, "TF": 0, "JP": 0}
370
  counts = {"EI": 0, "SN": 0, "TF": 0, "JP": 0}
@@ -445,6 +493,54 @@ def calculate_bdi_raw(answers: List[AnswerItem]):
445
 
446
  return {"level": level, "total": total_score, "cognitive": cognitive_pct, "affective": affective_pct, "somatic": somatic_pct}
447
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
  @app.get("/", response_class=HTMLResponse)
449
  async def get_index():
450
  try:
@@ -456,7 +552,6 @@ async def get_index():
456
  @app.get("/api/questions")
457
  async def get_questions(test_type: str = "mbti"):
458
  if test_type == "bai":
459
- # ارسال سوالات اضطراب بک همراه با گزینه‌های پیش‌فرض ۴ گزینه‌ای استاندارد
460
  return [
461
  {
462
  "id": q["id"],
@@ -465,7 +560,6 @@ async def get_questions(test_type: str = "mbti"):
465
  } for q in BAI_QUESTIONS
466
  ]
467
  elif test_type == "bdi":
468
- # ارسال سوالات افسردگی بک همراه با گزینه‌های بالینی و کاملا تخصصی منحصر به فرد خودش
469
  return [
470
  {
471
  "id": q["id"],
@@ -473,8 +567,15 @@ async def get_questions(test_type: str = "mbti"):
473
  "options": q["options"]
474
  } for q in BDI_QUESTIONS
475
  ]
 
 
 
 
 
 
 
 
476
 
477
- # ارسال سوالات تیپ‌شناسی شخصیت MBTI همراه با گزینه‌های استاندارد ۵ گزینه‌ای
478
  return [
479
  {
480
  "id": q["id"],
@@ -529,7 +630,6 @@ async def analyze_personality(payload: AnalysisRequest):
529
  for ans in payload.answers:
530
  q = q_map.get(ans.question_id)
531
  if q:
532
- # استخراج متن پاسخ اختصاصی ثبت شده توسط کاربر بر اساس نمره‌اش
533
  selected_opt = next((o["text"] for o in q["options"] if o["score"] == ans.score), "نامشخص")
534
  answers_text_list.append(f"سوال {ans.question_id}: '{q['text']}' -> پاسخ کاربر: {selected_opt} (نمره: {ans.score})")
535
  answers_summary = "\n".join(answers_text_list)
@@ -544,6 +644,34 @@ async def analyze_personality(payload: AnalysisRequest):
544
  - درصد علائم عاطفی/خلقی: {calc['affective']}%
545
  - درصد علائم بدنی/فیزیولوژیکی: {calc['somatic']}%
546
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  پاسخ‌های تفصیلی کاربر:
548
  {answers_summary}
549
  """
 
27
  {"score": 3, "text": "شدید (غیر قابل تحمل بود)", "label": "شدید (۱۰۰٪)", "color": 5}
28
  ]
29
 
30
+ # گزینه‌های استاندارد برای آزمون اهمال‌کاری تحصیلی سولومون
31
+ SOLOMON_OPTIONS = [
32
+ {"score": 1, "text": "هرگز", "label": "۱", "color": 1},
33
+ {"score": 2, "text": "به ندرت", "label": "۲", "color": 2},
34
+ {"score": 3, "text": "گهگاهی", "label": "۳", "color": 3},
35
+ {"score": 4, "text": "اکثر اوقات", "label": "۴", "color": 4},
36
+ {"score": 5, "text": "همیشه", "label": "۵", "color": 5}
37
+ ]
38
+
39
  # دیتابیس آزمون اول: ۳۰ سوال MBTI
40
  MBTI_QUESTIONS = [
41
  {"id": 1, "text": "در رویدادهای اجتماعی، من معمولاً با افراد جدید زیادی صحبت می‌کنم، نه فقط با کسانی که می‌شناسم.", "dimension": "EI", "direction": 1},
 
95
  {"id": 21, "text": "عرق کردن شدید که ناشی از دمای محیط یا فعالیت بدنی نباشد.", "dimension": "somatic"}
96
  ]
97
 
98
+ # آزمون سوم: ۲۱ سوال افسردگی بک (BDI-II)
99
  BDI_QUESTIONS = [
100
  {
101
  "id": 1,
 
320
  }
321
  ]
322
 
323
+ # آزمون چهارم: ۲۷ سوال اهمال‌کاری تحصیلی سولومون
324
+ SOLOMON_QUESTIONS = [
325
+ {"id": 1, "text": "هنگام مطالعه برای امتحان مرتباً رویاپردازی می‌کنم و تمرکز کردن برایم دشوار است.", "dimension": "exam"},
326
+ {"id": 2, "text": "تا لحظه‌ای که امکان داشته باشد، آماده شدن برای امتحانات را به تأخیر نمی‌اندازم.", "dimension": "exam"},
327
+ {"id": 3, "text": "سازمان دادن مطالب قبل از امتحان برایم دشوار است.", "dimension": "exam"},
328
+ {"id": 4, "text": "هنگامی که از تاریخ یک امتحان اطلاع پیدا می‌کنم، اجازه نمی‌دهم که وقت تلف شود و فوراً شروع به آماده شدن می‌کنم.", "dimension": "exam"},
329
+ {"id": 5, "text": "هنگامی که تاریخ یک امتحان نزدیک شود، آماده شدن برای امتحان برایم دشوار است.", "dimension": "exam"},
330
+ {"id": 6, "text": "هنگامی که می‌بایست برای یک امتحان آماده شوم، بر روی آن متمرکز می‌شوم و دچار حواس‌پرتی نمی‌شوم.", "dimension": "exam"},
331
+ {"id": 7, "text": "هنگامی که آماده شدن برای امتحانات را به تعویق می‌اندازم، احساس بدی به من دست می‌دهد.", "dimension": "exam"},
332
+ {"id": 8, "text": "دوست دارم عادت تعلل‌ورزی و امروز و فردا کردن را در خودم تغییر دهم.", "dimension": "exam"},
333
+ {"id": 9, "text": "تکالیفم را از یک جلسه به جلسه دیگر به تعویق می‌اندازم.", "dimension": "assignment"},
334
+ {"id": 10, "text": "هنگامی که در حال انجام تکالیف هستم، چیزهای دیگری حواسم را پرت می‌کنند و برایم دشوار است که آن را تا پایان انجام دهم.", "dimension": "assignment"},
335
+ {"id": 11, "text": "ترجیح می‌دهم که ابتدا تکالیفم را انجام دهم و سپس به چیزهای دیگر بپردازم.", "dimension": "assignment"},
336
+ {"id": 12, "text": "تمایل دارم که انجام تکالیفم را تا دقیقه آخر به تأخیر بیاندازم.", "dimension": "assignment"},
337
+ {"id": 13, "text": "وقتی که برای مدرسه رفتن بیدار می‌شوم تقریباً فوراً از رختخواب بلند می‌شوم.", "dimension": "assignment"},
338
+ {"id": 14, "text": "دیر به کلاس یا مدرسه می‌رسم.", "dimension": "assignment"},
339
+ {"id": 15, "text": "وقتی که در کلاس چیزی نمی‌فهمم، مطمئنم که به‌زودی آن را خواهم فهمید (مثلاً کتابی می‌خوانم که آن را شرح داده باشد و یا با پرسیدن از دوستم آن را خواهم فهمید).", "dimension": "assignment"},
340
+ {"id": 16, "text": "پیش از اتمام رسیدن مهلت تحویل تکالیف، آن‌ها را تمام می‌کنم.", "dimension": "assignment"},
341
+ {"id": 17, "text": "هنگامی که می‌بایست تکالیفم را مرور کنم، آن را به تعویق می‌اندازم.", "dimension": "assignment"},
342
+ {"id": 18, "text": "وقتی که انجام دادن تکالیف را به تعویق می‌اندازم، احساس بدی به من دست می‌دهد.", "dimension": "assignment"},
343
+ {"id": 19, "text": "دوست دارم که عادت اهمال‌کاری و امروز و فردا کردن در انجام تکالیف را تغییر دهم.", "dimension": "assignment"},
344
+ {"id": 20, "text": "هنگامی که مجبور باشم تکلیفی را آماده کنم، مرتباً آن را به تأخیر می‌اندازم.", "dimension": "paper"},
345
+ {"id": 21, "text": "به محض مشخص شدن زمان انجام تکلیف، شروع به آماده کردن آن می‌کنم و آن را به تأخیر نمی‌اندازم.", "dimension": "paper"},
346
+ {"id": 22, "text": "هنگامی که تصمیم می‌گیرم بر روی تکلیفی کار کنم، احساس می‌کنم انرژی انجام دادن آن را ندارم.", "dimension": "paper"},
347
+ {"id": 23, "text": "هنگامی که برای انجام تکلیفی برنامه‌ریزی می‌کنم، دقیقاً به زمان و تاریخ آن پایبند هستم.", "dimension": "paper"},
348
+ {"id": 24, "text": "هنگامی که بر روی مقاله‌ای کار می‌کنم، نمی‌توانم روی آن تمرکز کنم و مرتباً رویاپردازی می‌کنم.", "dimension": "paper"},
349
+ {"id": 25, "text": "هنگامی که مجبورم تکلیفی را تا تاریخ معینی ارائه دهم، از چندین روز قبل آن را آماده می‌کنم.", "dimension": "paper"},
350
+ {"id": 26, "text": "هنگامی که انجام یک تکلیف را به تأخیر می‌اندازم، احساس بدی به من دست می‌دهد.", "dimension": "paper"},
351
+ {"id": 27, "text": "علاقه‌مند هستم که عادت اهمال‌کاری و امروز و فردا کردن در انجام تکالیف را تغییر دهم.", "dimension": "paper"}
352
+ ]
353
+
354
  class AnswerItem(BaseModel):
355
  question_id: int
356
  score: int
 
358
  class AnalysisRequest(BaseModel):
359
  first_name: str
360
  last_name: str
361
+ test_type: str = Field(description="Type of test taken: 'mbti', 'bai', 'bdi', or 'solomon'")
362
  answers: List[AnswerItem]
363
 
364
  class UniversalAnalysisSchema(BaseModel):
365
+ test_type: str = Field(description="The type of test taken ('mbti', 'bai', 'bdi', or 'solomon')")
366
  mbti_type: str = Field(description="MBTI 4-letter type. Leave blank if not MBTI.")
367
  bai_level: str = Field(description="BAI anxiety severity level. Leave blank if not BAI.")
368
  bdi_level: str = Field(description="BDI depression severity level. Leave blank if not BDI.")
369
+ solomon_level: str = Field(description="Solomon procrastination severity level. Leave blank if not Solomon.")
370
  personality_title: str = Field(description="A creative Persian title representing their state/personality")
371
  introversion_score: int = Field(description="Percentage of Introversion (0-100)")
372
  extraversion_score: int = Field(description="Percentage of Extraversion (0-100)")
 
376
  feeling_score: int = Field(description="Percentage of Feeling (0-100)")
377
  judging_score: int = Field(description="Percentage of Judging (0-100)")
378
  perceiving_score: int = Field(description="Percentage of Perceiving (0-100)")
379
+ somatic_score: int = Field(description="Somatic symptoms / Exam procrastination percentage (0-100)")
380
+ cognitive_score: int = Field(description="Cognitive symptoms / Assignment procrastination percentage (0-100)")
381
+ panic_score: int = Field(description="BAI Panic / Solomon Paper procrastination percentage (0-100)")
382
+ affective_score: int = Field(description="BDI Affective percentage (0-100)")
383
+ total_score_raw: int = Field(description="Total raw score sum of BAI, BDI, or Solomon")
384
  summary: str = Field(description="A short Persian summary of the results (2-3 sentences)")
385
  strengths: List[str] = Field(description="Coping mechanisms, strengths or psychological resources (4-5 items in Persian)")
386
  weaknesses: List[str] = Field(description="Triggers, weaknesses, risk situations or symptoms to monitor (4-5 items in Persian)")
 
406
  لحن متن فوق‌العاده همدلانه، مهربان و امیدبخش باشد. بخش detailed_analysis را با تیترهای مارک‌داون جدا کنید.
407
  """
408
 
409
+ SOLOMON_SYSTEM_INSTRUCTION = """
410
+ شما یک روان‌شناس بالینی ارشد متخصص در حوزه روان‌شناسی تربیتی و تحصیلی و ارزیابی عادات مطالعه و تعلل‌ورزی بر اساس مقیاس اهمال‌کاری تحصیلی سولومون و راث‌بلوم (PASS) هستید.
411
+ وظیفه شما تحلیل دقیق پاسخ‌های کاربر به پرسشنامه ۲۷ سواله اهمال‌کاری تحصیلی سولومون و تولید یک گزارش روان‌شناختی بسیار عمیق، علمی، کاربردی و ارائه‌دهنده راهکارهای عملی مدیریت زمان و غلبه بر تنبلی تحصیلی به زبان فارسی است.
412
+ سه مؤلفه اصلی: آماده شدن برای امتحانات (exam)، آماده شدن برای تکالیف (assignment) و آماده شدن برای مقاله‌های پایان‌ترم (paper) را تحلیل کرده و راهکارهای درمانی معتبر مبتنی بر شناخت‌درمانی (CBT)، تکنیک‌های مدیریت تمرکز و برنامه‌ریزی تحصیلی ارائه دهید.
413
+ بخش detailed_analysis را با تیترهای مارک‌داون تفکیک و تشریح کنید.
414
+ """
415
+
416
  def calculate_mbti_raw(answers: List[AnswerItem]):
417
  scores = {"EI": 0, "SN": 0, "TF": 0, "JP": 0}
418
  counts = {"EI": 0, "SN": 0, "TF": 0, "JP": 0}
 
493
 
494
  return {"level": level, "total": total_score, "cognitive": cognitive_pct, "affective": affective_pct, "somatic": somatic_pct}
495
 
496
+ def calculate_solomon_raw(answers: List[AnswerItem]):
497
+ # گویه‌های نیازمند نمره‌گذاری معکوس طبق پرسشنامه: ۲ - ۴ - ۶ - ۱۱ - ۱۳ - ۱۵ - ۱۶ و ۲۱ - ۲۳ - ۲۵
498
+ reverse_ids = {2, 4, 6, 11, 13, 15, 16, 21, 23, 25}
499
+
500
+ subscales = {
501
+ "exam": {"score": 0, "max": 0},
502
+ "assignment": {"score": 0, "max": 0},
503
+ "paper": {"score": 0, "max": 0}
504
+ }
505
+ total_score = 0
506
+
507
+ q_map = {q["id"]: q for q in SOLOMON_QUESTIONS}
508
+ for ans in answers:
509
+ q_id = ans.question_id
510
+ if q_id in q_map:
511
+ q = q_map[q_id]
512
+ dim = q["dimension"]
513
+
514
+ raw_val = max(1, min(5, ans.score))
515
+ if q_id in reverse_ids:
516
+ actual_score = 6 - raw_val # نمره‌گذاری معکوس: ۵ به ۱، ۴ به ۲، ۳ به ۳، ۲ به ۴، ۱ به ۵
517
+ else:
518
+ actual_score = raw_val
519
+
520
+ subscales[dim]["score"] += actual_score
521
+ subscales[dim]["max"] += 5
522
+ total_score += actual_score
523
+
524
+ # سطح‌بندی بر اساس نمره کل بین ۲۷ تا ۱۳۵
525
+ if total_score <= 67:
526
+ level = "اهمال‌کاری ضعیف (مطلوب)"
527
+ elif total_score <= 101:
528
+ level = "اهمال‌کاری متوسط"
529
+ else:
530
+ level = "اهمال‌کاری شدید"
531
+
532
+ exam_pct = round((subscales["exam"]["score"] / subscales["exam"]["max"]) * 100) if subscales["exam"]["max"] > 0 else 0
533
+ assignment_pct = round((subscales["assignment"]["score"] / subscales["assignment"]["max"]) * 100) if subscales["assignment"]["max"] > 0 else 0
534
+ paper_pct = round((subscales["paper"]["score"] / subscales["paper"]["max"]) * 100) if subscales["paper"]["max"] > 0 else 0
535
+
536
+ return {
537
+ "level": level,
538
+ "total": total_score,
539
+ "exam": exam_pct,
540
+ "assignment": assignment_pct,
541
+ "paper": paper_pct
542
+ }
543
+
544
  @app.get("/", response_class=HTMLResponse)
545
  async def get_index():
546
  try:
 
552
  @app.get("/api/questions")
553
  async def get_questions(test_type: str = "mbti"):
554
  if test_type == "bai":
 
555
  return [
556
  {
557
  "id": q["id"],
 
560
  } for q in BAI_QUESTIONS
561
  ]
562
  elif test_type == "bdi":
 
563
  return [
564
  {
565
  "id": q["id"],
 
567
  "options": q["options"]
568
  } for q in BDI_QUESTIONS
569
  ]
570
+ elif test_type == "solomon":
571
+ return [
572
+ {
573
+ "id": q["id"],
574
+ "text": q["text"],
575
+ "options": SOLOMON_OPTIONS
576
+ } for q in SOLOMON_QUESTIONS
577
+ ]
578
 
 
579
  return [
580
  {
581
  "id": q["id"],
 
630
  for ans in payload.answers:
631
  q = q_map.get(ans.question_id)
632
  if q:
 
633
  selected_opt = next((o["text"] for o in q["options"] if o["score"] == ans.score), "نامشخص")
634
  answers_text_list.append(f"سوال {ans.question_id}: '{q['text']}' -> پاسخ کاربر: {selected_opt} (نمره: {ans.score})")
635
  answers_summary = "\n".join(answers_text_list)
 
644
  - درصد علائم عاطفی/خلقی: {calc['affective']}%
645
  - درصد علائم بدنی/فیزیولوژیکی: {calc['somatic']}%
646
 
647
+ پاسخ‌های تفصیلی کاربر:
648
+ {answers_summary}
649
+ """
650
+ elif payload.test_type == "solomon":
651
+ calc = calculate_solomon_raw(payload.answers)
652
+ system_instruction = SOLOMON_SYSTEM_INSTRUCTION
653
+ q_map = {q["id"]: q for q in SOLOMON_QUESTIONS}
654
+ answers_text_list = []
655
+ for ans in payload.answers:
656
+ q = q_map.get(ans.question_id)
657
+ if q:
658
+ selected_opt = next((o["text"] for o in SOLOMON_OPTIONS if o["score"] == ans.score), "نامشخص")
659
+ answers_text_list.append(f"سوال {ans.question_id}: '{q['text']}' -> پاسخ: {selected_opt} (نمره خام: {ans.score})")
660
+ answers_summary = "\n".join(answers_text_list)
661
+ prompt_data = f"""
662
+ کاربر ارزیابی‌شونده: {payload.first_name} {payload.last_name}
663
+ آزمون انجام شده: سنجش علمی اهمال‌کاری تحصیلی سولومون
664
+
665
+ محاسبات ریاضی پایه (از این محاسبات دقیق در خروجی JSON استفاده کنید):
666
+ - فیلد test_type: مقدار "solomon" قرار گیرد.
667
+ - فیلد solomon_level: مقدار "{calc['level']}" قرار گیرد.
668
+ - فیلد somatic_score (درصد امتحانات): مقدار {calc['exam']} قرار گیرد.
669
+ - فیلد cognitive_score (درصد تکالیف): مقدار {calc['assignment']} قرار گیرد.
670
+ - فیلد panic_score (درصد مقالات): مقدار {calc['paper']} قرار گیرد.
671
+ - فیلد total_score_raw (نمره کل خام): مقدار {calc['total']} قرار گیرد.
672
+ - سایر فیلدهای عددی مربوط به MBTI یا BAI/BDI که در این آزمون کاربرد ندارند را برابر 0 قرار دهید.
673
+ - فیلدهای mbti_type، bai_level و bdi_level را خالی یا تهی بگذارید.
674
+
675
  پاسخ‌های تفصیلی کاربر:
676
  {answers_summary}
677
  """