feat: Implement dose calculation fix and enhance legend feature
Some checks failed
Build and Push Docker Image / build-and-push (push) Has been cancelled
Some checks failed
Build and Push Docker Image / build-and-push (push) Has been cancelled
- Fixed dose calculation logic in `_calculate_daily_dose` to correctly parse timestamps with multiple colons. - Added comprehensive test cases for various dose formats and edge cases in `test_dose_calculation.py`. - Enhanced graph legend to display individual medicines with average dosages and track medicines without dose data. - Updated legend styling and positioning for better readability and organization. - Created new tests for enhanced legend functionality, including handling of medicines with and without data. - Improved mocking for matplotlib components in tests to prevent TypeErrors.
This commit is contained in:
114
scripts/test_dose_calc.py
Normal file
114
scripts/test_dose_calc.py
Normal file
@@ -0,0 +1,114 @@
|
||||
"""
|
||||
Direct test of dose calculation functionality.
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
import pytest
|
||||
|
||||
|
||||
def calculate_daily_dose(dose_str: str) -> float:
|
||||
"""Calculate total daily dose from dose string format - copied from GraphManager."""
|
||||
if not dose_str or pd.isna(dose_str) or str(dose_str).lower() == "nan":
|
||||
return 0.0
|
||||
|
||||
total_dose = 0.0
|
||||
# Handle different separators and clean the string
|
||||
dose_str = str(dose_str).replace("•", "").strip()
|
||||
|
||||
# Split by | or by spaces if no | present
|
||||
dose_entries = dose_str.split("|") if "|" in dose_str else [dose_str]
|
||||
|
||||
for entry in dose_entries:
|
||||
entry = entry.strip()
|
||||
if not entry:
|
||||
continue
|
||||
|
||||
try:
|
||||
# Extract dose part after the last colon (timestamp:dose format)
|
||||
dose_part = entry.split(":")[-1] if ":" in entry else entry
|
||||
|
||||
# Extract numeric part from dose (e.g., "150mg" -> 150)
|
||||
dose_value = ""
|
||||
for char in dose_part:
|
||||
if char.isdigit() or char == ".":
|
||||
dose_value += char
|
||||
elif dose_value: # Stop at first non-digit after finding digits
|
||||
break
|
||||
|
||||
if dose_value:
|
||||
total_dose += float(dose_value)
|
||||
except (ValueError, IndexError):
|
||||
continue
|
||||
|
||||
return total_dose
|
||||
|
||||
|
||||
class TestDoseCalculation:
|
||||
"""Test dose calculation functionality."""
|
||||
|
||||
def test_standard_format(self):
|
||||
"""Test dose calculation with standard timestamp:dose format."""
|
||||
# Single dose
|
||||
dose_str = "2025-07-28 18:59:45:150mg"
|
||||
assert calculate_daily_dose(dose_str) == 150.0
|
||||
|
||||
# Multiple doses
|
||||
dose_str = "2025-07-28 18:59:45:150mg|2025-07-28 19:34:19:75mg"
|
||||
assert calculate_daily_dose(dose_str) == 225.0
|
||||
|
||||
def test_with_symbols(self):
|
||||
"""Test dose calculation with bullet symbols."""
|
||||
# With bullet symbols
|
||||
dose_str = "• • • • 2025-07-30 07:50:00:300"
|
||||
assert calculate_daily_dose(dose_str) == 300.0
|
||||
|
||||
def test_decimal_values(self):
|
||||
"""Test dose calculation with decimal values."""
|
||||
# Decimal dose
|
||||
dose_str = "2025-07-28 18:59:45:12.5mg"
|
||||
assert calculate_daily_dose(dose_str) == 12.5
|
||||
|
||||
# Multiple decimal doses
|
||||
dose_str = "2025-07-28 18:59:45:12.5mg|2025-07-28 19:34:19:7.5mg"
|
||||
assert calculate_daily_dose(dose_str) == 20.0
|
||||
|
||||
def test_no_timestamp_format(self):
|
||||
"""Test dose calculation without timestamps."""
|
||||
# Simple dose without timestamp
|
||||
dose_str = "100mg|50mg"
|
||||
assert calculate_daily_dose(dose_str) == 150.0
|
||||
|
||||
def test_mixed_format(self):
|
||||
"""Test dose calculation with mixed formats."""
|
||||
# Mixed format
|
||||
dose_str = "• 2025-07-30 22:50:00:10|75mg"
|
||||
assert calculate_daily_dose(dose_str) == 85.0
|
||||
|
||||
def test_edge_cases(self):
|
||||
"""Test dose calculation with edge cases."""
|
||||
# Empty string
|
||||
assert calculate_daily_dose("") == 0.0
|
||||
|
||||
# NaN value
|
||||
assert calculate_daily_dose("nan") == 0.0
|
||||
|
||||
# No units
|
||||
dose_str = "2025-07-28 18:59:45:10|2025-07-28 19:34:19:5"
|
||||
assert calculate_daily_dose(dose_str) == 15.0
|
||||
|
||||
def test_malformed_data(self):
|
||||
"""Test dose calculation with malformed data."""
|
||||
# Malformed data
|
||||
assert calculate_daily_dose("malformed:data") == 0.0
|
||||
assert calculate_daily_dose("::::") == 0.0
|
||||
assert calculate_daily_dose("2025-07-28:") == 0.0
|
||||
assert calculate_daily_dose("2025-07-28::mg") == 0.0
|
||||
|
||||
def test_partial_data(self):
|
||||
"""Test dose calculation with partial data."""
|
||||
# No units but valid dose
|
||||
assert calculate_daily_dose("2025-07-28 18:59:45:150") == 150.0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Reference in New Issue
Block a user