Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -345,15 +345,8 @@ OSCE Station Result: [Pass/Borderline/Fail based on score]
|
|
| 345 |
else:
|
| 346 |
level = "Needs Improvement"
|
| 347 |
|
| 348 |
-
# Determine color based on score
|
| 349 |
-
|
| 350 |
-
color = "#0F766E" # Deep teal
|
| 351 |
-
elif weighted_score >= 7:
|
| 352 |
-
color = "#1E40AF" # Professional blue
|
| 353 |
-
elif weighted_score >= 5:
|
| 354 |
-
color = "#EA580C" # Professional orange
|
| 355 |
-
else:
|
| 356 |
-
color = "#B91C1C" # Deep red
|
| 357 |
|
| 358 |
return weighted_score, percentage, level, color, overall_assessment_text
|
| 359 |
|
|
@@ -377,13 +370,14 @@ OSCE Station Result: [Pass/Borderline/Fail based on score]
|
|
| 377 |
# Container for the 'Flowable' objects
|
| 378 |
elements = []
|
| 379 |
|
| 380 |
-
# Define styles with professional colors
|
| 381 |
styles = getSampleStyleSheet()
|
| 382 |
title_style = ParagraphStyle(
|
| 383 |
'CustomTitle',
|
| 384 |
parent=styles['Heading1'],
|
|
|
|
| 385 |
fontSize=24,
|
| 386 |
-
textColor=HexColor('#
|
| 387 |
spaceAfter=30,
|
| 388 |
alignment=TA_CENTER
|
| 389 |
)
|
|
@@ -391,8 +385,9 @@ OSCE Station Result: [Pass/Borderline/Fail based on score]
|
|
| 391 |
heading_style = ParagraphStyle(
|
| 392 |
'CustomHeading',
|
| 393 |
parent=styles['Heading2'],
|
|
|
|
| 394 |
fontSize=14,
|
| 395 |
-
textColor=HexColor('#
|
| 396 |
spaceAfter=12,
|
| 397 |
spaceBefore=12,
|
| 398 |
)
|
|
@@ -400,7 +395,9 @@ OSCE Station Result: [Pass/Borderline/Fail based on score]
|
|
| 400 |
body_style = ParagraphStyle(
|
| 401 |
'CustomBody',
|
| 402 |
parent=styles['BodyText'],
|
|
|
|
| 403 |
fontSize=11,
|
|
|
|
| 404 |
alignment=TA_JUSTIFY,
|
| 405 |
spaceAfter=12
|
| 406 |
)
|
|
@@ -530,43 +527,20 @@ def show_saving_status(video):
|
|
| 530 |
|
| 531 |
# Create animated status HTML
|
| 532 |
status_html = """
|
| 533 |
-
<div style="background:
|
| 534 |
<style>
|
| 535 |
@keyframes pulse {
|
| 536 |
0%, 100% { opacity: 1; }
|
| 537 |
-
50% { opacity: 0.
|
| 538 |
-
}
|
| 539 |
-
@keyframes slide {
|
| 540 |
-
0% { transform: translateX(-100%); }
|
| 541 |
-
100% { transform: translateX(100%); }
|
| 542 |
-
}
|
| 543 |
-
.progress-bar {
|
| 544 |
-
position: relative;
|
| 545 |
-
height: 6px;
|
| 546 |
-
background: rgba(255, 255, 255, 0.3);
|
| 547 |
-
border-radius: 3px;
|
| 548 |
-
overflow: hidden;
|
| 549 |
-
margin-top: 15px;
|
| 550 |
-
}
|
| 551 |
-
.progress-bar::after {
|
| 552 |
-
content: '';
|
| 553 |
-
position: absolute;
|
| 554 |
-
top: 0;
|
| 555 |
-
left: 0;
|
| 556 |
-
width: 40%;
|
| 557 |
-
height: 100%;
|
| 558 |
-
background: white;
|
| 559 |
-
animation: slide 1.5s ease-in-out infinite;
|
| 560 |
}
|
| 561 |
</style>
|
| 562 |
-
<div style="text-align: center; color:
|
| 563 |
-
<div style="font-size: 24px; font-weight: bold; margin-bottom: 10px;">
|
| 564 |
Processing Your Recording...
|
| 565 |
</div>
|
| 566 |
-
<div style="font-size: 16px;
|
| 567 |
Saving video file - Preparing for download
|
| 568 |
</div>
|
| 569 |
-
<div class="progress-bar"></div>
|
| 570 |
</div>
|
| 571 |
</div>
|
| 572 |
"""
|
|
@@ -591,12 +565,12 @@ def save_recorded_video_with_status(video):
|
|
| 591 |
|
| 592 |
# Success status
|
| 593 |
success_html = """
|
| 594 |
-
<div style="background:
|
| 595 |
-
<div style="text-align: center; color:
|
| 596 |
-
<div style="font-size: 20px; font-weight: bold;">
|
| 597 |
Video Saved Successfully!
|
| 598 |
</div>
|
| 599 |
-
<div style="font-size: 14px; margin-top: 5px;
|
| 600 |
Ready for download - Click Analyze Video to assess
|
| 601 |
</div>
|
| 602 |
</div>
|
|
@@ -609,12 +583,12 @@ def save_recorded_video_with_status(video):
|
|
| 609 |
except Exception as e:
|
| 610 |
print(f"Failed to save video: {str(e)}")
|
| 611 |
error_html = """
|
| 612 |
-
<div style="background:
|
| 613 |
-
<div style="text-align: center; color:
|
| 614 |
-
<div style="font-size: 20px; font-weight: bold;">
|
| 615 |
Error Saving Video
|
| 616 |
</div>
|
| 617 |
-
<div style="font-size: 14px; margin-top: 5px;">
|
| 618 |
Please try recording again
|
| 619 |
</div>
|
| 620 |
</div>
|
|
@@ -695,73 +669,73 @@ def process_video_core(video, resize_option, assessor, param1, param2, param3, p
|
|
| 695 |
|
| 696 |
# Create enhanced visual summary HTML with parameter information
|
| 697 |
summary_html = f"""
|
| 698 |
-
<div style="max-width:800px; margin:20px auto; padding:30px; border-radius:
|
| 699 |
-
<h2 style="text-align:center; color:#
|
| 700 |
|
| 701 |
-
<div style="background:
|
| 702 |
-
<h3 style="color:#
|
| 703 |
-
<p style="color:#
|
| 704 |
</div>
|
| 705 |
|
| 706 |
<div style="display:flex; justify-content:space-around; margin:30px 0;">
|
| 707 |
<div style="text-align:center;">
|
| 708 |
-
<div style="font-size:48px; font-weight:bold; color:
|
| 709 |
-
<div style="color:#
|
| 710 |
</div>
|
| 711 |
<div style="text-align:center;">
|
| 712 |
-
<div style="font-size:48px; font-weight:bold; color:
|
| 713 |
-
<div style="color:#
|
| 714 |
</div>
|
| 715 |
</div>
|
| 716 |
-
<div style="text-align:center; padding:20px; background:
|
| 717 |
-
<div style="font-size:24px; font-weight:bold; color:
|
| 718 |
</div>
|
| 719 |
<div style="margin-top:30px;">
|
| 720 |
-
<h3 style="color:#
|
| 721 |
-
<div style="background:
|
| 722 |
<div style="display:flex; justify-content:space-between; margin:10px 0;">
|
| 723 |
-
<span style="color:#
|
| 724 |
-
<span style="color:#
|
| 725 |
</div>
|
| 726 |
-
<div style="height:8px; background:#
|
| 727 |
-
<div style="height:100%; background:#
|
| 728 |
</div>
|
| 729 |
|
| 730 |
<div style="display:flex; justify-content:space-between; margin:10px 0; margin-top:20px;">
|
| 731 |
-
<span style="color:#
|
| 732 |
-
<span style="color:#
|
| 733 |
</div>
|
| 734 |
-
<div style="height:8px; background:#
|
| 735 |
-
<div style="height:100%; background:#
|
| 736 |
</div>
|
| 737 |
|
| 738 |
<div style="display:flex; justify-content:space-between; margin:10px 0; margin-top:20px;">
|
| 739 |
-
<span style="color:#
|
| 740 |
-
<span style="color:#
|
| 741 |
</div>
|
| 742 |
-
<div style="height:8px; background:#
|
| 743 |
-
<div style="height:100%; background:#
|
| 744 |
</div>
|
| 745 |
|
| 746 |
<div style="display:flex; justify-content:space-between; margin:10px 0; margin-top:20px;">
|
| 747 |
-
<span style="color:#
|
| 748 |
-
<span style="color:#
|
| 749 |
</div>
|
| 750 |
-
<div style="height:8px; background:#
|
| 751 |
-
<div style="height:100%; background:#
|
| 752 |
</div>
|
| 753 |
|
| 754 |
<div style="display:flex; justify-content:space-between; margin:10px 0; margin-top:20px;">
|
| 755 |
-
<span style="color:#
|
| 756 |
-
<span style="color:#
|
| 757 |
</div>
|
| 758 |
-
<div style="height:8px; background:#
|
| 759 |
-
<div style="height:100%; background:#
|
| 760 |
</div>
|
| 761 |
</div>
|
| 762 |
</div>
|
| 763 |
-
<div style="margin-top:30px; padding:20px; background:
|
| 764 |
-
<p style="text-align:center; color:#
|
| 765 |
Listen to the 1-minute audio summary for key findings<br>
|
| 766 |
Download the PDF report for complete OSCE documentation
|
| 767 |
</p>
|
|
|
|
| 345 |
else:
|
| 346 |
level = "Needs Improvement"
|
| 347 |
|
| 348 |
+
# Determine color based on score - using black for clean look
|
| 349 |
+
color = "#000000"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
|
| 351 |
return weighted_score, percentage, level, color, overall_assessment_text
|
| 352 |
|
|
|
|
| 370 |
# Container for the 'Flowable' objects
|
| 371 |
elements = []
|
| 372 |
|
| 373 |
+
# Define styles with professional colors and Calibri font
|
| 374 |
styles = getSampleStyleSheet()
|
| 375 |
title_style = ParagraphStyle(
|
| 376 |
'CustomTitle',
|
| 377 |
parent=styles['Heading1'],
|
| 378 |
+
fontName='Helvetica-Bold',
|
| 379 |
fontSize=24,
|
| 380 |
+
textColor=HexColor('#000000'),
|
| 381 |
spaceAfter=30,
|
| 382 |
alignment=TA_CENTER
|
| 383 |
)
|
|
|
|
| 385 |
heading_style = ParagraphStyle(
|
| 386 |
'CustomHeading',
|
| 387 |
parent=styles['Heading2'],
|
| 388 |
+
fontName='Helvetica-Bold',
|
| 389 |
fontSize=14,
|
| 390 |
+
textColor=HexColor('#000000'),
|
| 391 |
spaceAfter=12,
|
| 392 |
spaceBefore=12,
|
| 393 |
)
|
|
|
|
| 395 |
body_style = ParagraphStyle(
|
| 396 |
'CustomBody',
|
| 397 |
parent=styles['BodyText'],
|
| 398 |
+
fontName='Helvetica',
|
| 399 |
fontSize=11,
|
| 400 |
+
textColor=HexColor('#000000'),
|
| 401 |
alignment=TA_JUSTIFY,
|
| 402 |
spaceAfter=12
|
| 403 |
)
|
|
|
|
| 527 |
|
| 528 |
# Create animated status HTML
|
| 529 |
status_html = """
|
| 530 |
+
<div style="background: white; padding: 20px; border-radius: 8px; margin: 20px 0; border: 1px solid #000000; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 531 |
<style>
|
| 532 |
@keyframes pulse {
|
| 533 |
0%, 100% { opacity: 1; }
|
| 534 |
+
50% { opacity: 0.6; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 535 |
}
|
| 536 |
</style>
|
| 537 |
+
<div style="text-align: center; color: #000000; animation: pulse 1.5s ease-in-out infinite;">
|
| 538 |
+
<div style="font-size: 24px; font-weight: bold; margin-bottom: 10px; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 539 |
Processing Your Recording...
|
| 540 |
</div>
|
| 541 |
+
<div style="font-size: 16px; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 542 |
Saving video file - Preparing for download
|
| 543 |
</div>
|
|
|
|
| 544 |
</div>
|
| 545 |
</div>
|
| 546 |
"""
|
|
|
|
| 565 |
|
| 566 |
# Success status
|
| 567 |
success_html = """
|
| 568 |
+
<div style="background: white; padding: 15px; border-radius: 8px; margin: 20px 0; border: 1px solid #000000; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 569 |
+
<div style="text-align: center; color: #000000;">
|
| 570 |
+
<div style="font-size: 20px; font-weight: bold; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 571 |
Video Saved Successfully!
|
| 572 |
</div>
|
| 573 |
+
<div style="font-size: 14px; margin-top: 5px; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 574 |
Ready for download - Click Analyze Video to assess
|
| 575 |
</div>
|
| 576 |
</div>
|
|
|
|
| 583 |
except Exception as e:
|
| 584 |
print(f"Failed to save video: {str(e)}")
|
| 585 |
error_html = """
|
| 586 |
+
<div style="background: white; padding: 15px; border-radius: 8px; margin: 20px 0; border: 1px solid #000000; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 587 |
+
<div style="text-align: center; color: #000000;">
|
| 588 |
+
<div style="font-size: 20px; font-weight: bold; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 589 |
Error Saving Video
|
| 590 |
</div>
|
| 591 |
+
<div style="font-size: 14px; margin-top: 5px; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 592 |
Please try recording again
|
| 593 |
</div>
|
| 594 |
</div>
|
|
|
|
| 669 |
|
| 670 |
# Create enhanced visual summary HTML with parameter information
|
| 671 |
summary_html = f"""
|
| 672 |
+
<div style="max-width:800px; margin:20px auto; padding:30px; border-radius:10px; background:white; border:1px solid #e0e0e0; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 673 |
+
<h2 style="text-align:center; color:#000000; margin-bottom:30px; font-weight:600; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Standardized Patient Assessment Summary</h2>
|
| 674 |
|
| 675 |
+
<div style="background:white; padding:20px; border-radius:8px; margin-bottom:30px; border:1px solid #e0e0e0;">
|
| 676 |
+
<h3 style="color:#000000; margin-top:0; margin-bottom:15px; font-weight:600; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Overall Weighted Assessment</h3>
|
| 677 |
+
<p style="color:#000000; line-height:1.8; margin:0; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">{clean_overall_assessment}</p>
|
| 678 |
</div>
|
| 679 |
|
| 680 |
<div style="display:flex; justify-content:space-around; margin:30px 0;">
|
| 681 |
<div style="text-align:center;">
|
| 682 |
+
<div style="font-size:48px; font-weight:bold; color:#000000; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">{weighted_score:.1f}/10</div>
|
| 683 |
+
<div style="color:#000000; margin-top:10px; font-weight:500; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">OSCE Score</div>
|
| 684 |
</div>
|
| 685 |
<div style="text-align:center;">
|
| 686 |
+
<div style="font-size:48px; font-weight:bold; color:#000000; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">{percentage:.0f}%</div>
|
| 687 |
+
<div style="color:#000000; margin-top:10px; font-weight:500; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Overall Performance</div>
|
| 688 |
</div>
|
| 689 |
</div>
|
| 690 |
+
<div style="text-align:center; padding:20px; background:white; border-radius:8px; margin:20px 0; border:1px solid #e0e0e0;">
|
| 691 |
+
<div style="font-size:24px; font-weight:bold; color:#000000; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Performance Level: {level}</div>
|
| 692 |
</div>
|
| 693 |
<div style="margin-top:30px;">
|
| 694 |
+
<h3 style="color:#000000; margin-bottom:20px; font-weight:600; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Your OSCE Evaluation Parameters:</h3>
|
| 695 |
+
<div style="background:white; padding:20px; border-radius:8px; border:1px solid #e0e0e0;">
|
| 696 |
<div style="display:flex; justify-content:space-between; margin:10px 0;">
|
| 697 |
+
<span style="color:#000000; font-weight:500; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">History Taking & Interview:</span>
|
| 698 |
+
<span style="color:#000000; font-weight:bold; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">{param1}/10</span>
|
| 699 |
</div>
|
| 700 |
+
<div style="height:8px; background:#e0e0e0; border-radius:4px; margin:5px 0;">
|
| 701 |
+
<div style="height:100%; background:#000000; border-radius:4px; width:{param1*10}%;"></div>
|
| 702 |
</div>
|
| 703 |
|
| 704 |
<div style="display:flex; justify-content:space-between; margin:10px 0; margin-top:20px;">
|
| 705 |
+
<span style="color:#000000; font-weight:500; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Communication & Rapport:</span>
|
| 706 |
+
<span style="color:#000000; font-weight:bold; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">{param2}/10</span>
|
| 707 |
</div>
|
| 708 |
+
<div style="height:8px; background:#e0e0e0; border-radius:4px; margin:5px 0;">
|
| 709 |
+
<div style="height:100%; background:#000000; border-radius:4px; width:{param2*10}%;"></div>
|
| 710 |
</div>
|
| 711 |
|
| 712 |
<div style="display:flex; justify-content:space-between; margin:10px 0; margin-top:20px;">
|
| 713 |
+
<span style="color:#000000; font-weight:500; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Clinical Reasoning:</span>
|
| 714 |
+
<span style="color:#000000; font-weight:bold; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">{param3}/10</span>
|
| 715 |
</div>
|
| 716 |
+
<div style="height:8px; background:#e0e0e0; border-radius:4px; margin:5px 0;">
|
| 717 |
+
<div style="height:100%; background:#000000; border-radius:4px; width:{param3*10}%;"></div>
|
| 718 |
</div>
|
| 719 |
|
| 720 |
<div style="display:flex; justify-content:space-between; margin:10px 0; margin-top:20px;">
|
| 721 |
+
<span style="color:#000000; font-weight:500; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Physical Examination:</span>
|
| 722 |
+
<span style="color:#000000; font-weight:bold; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">{param4}/10</span>
|
| 723 |
</div>
|
| 724 |
+
<div style="height:8px; background:#e0e0e0; border-radius:4px; margin:5px 0;">
|
| 725 |
+
<div style="height:100%; background:#000000; border-radius:4px; width:{param4*10}%;"></div>
|
| 726 |
</div>
|
| 727 |
|
| 728 |
<div style="display:flex; justify-content:space-between; margin:10px 0; margin-top:20px;">
|
| 729 |
+
<span style="color:#000000; font-weight:500; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">Professionalism & Empathy:</span>
|
| 730 |
+
<span style="color:#000000; font-weight:bold; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">{param5}/10</span>
|
| 731 |
</div>
|
| 732 |
+
<div style="height:8px; background:#e0e0e0; border-radius:4px; margin:5px 0;">
|
| 733 |
+
<div style="height:100%; background:#000000; border-radius:4px; width:{param5*10}%;"></div>
|
| 734 |
</div>
|
| 735 |
</div>
|
| 736 |
</div>
|
| 737 |
+
<div style="margin-top:30px; padding:20px; background:white; border-radius:8px; border:1px solid #000000;">
|
| 738 |
+
<p style="text-align:center; color:#000000; margin:0; font-weight:600; font-family: Calibri, 'Segoe UI', Arial, sans-serif;">
|
| 739 |
Listen to the 1-minute audio summary for key findings<br>
|
| 740 |
Download the PDF report for complete OSCE documentation
|
| 741 |
</p>
|