|
|
from typing import Dict, Optional |
|
|
import numpy as np |
|
|
|
|
|
|
|
|
class MeasurementProcessor: |
|
|
NORMALIZATION_FACTORS = { |
|
|
"height": 200.0, |
|
|
"weight": 100.0, |
|
|
"chest": 150.0, |
|
|
"waist": 150.0, |
|
|
"hips": 150.0, |
|
|
"shoulder_width": 60.0, |
|
|
"arm_length": 80.0, |
|
|
"leg_length": 120.0, |
|
|
"inseam": 100.0, |
|
|
} |
|
|
|
|
|
REQUIRED_MEASUREMENTS = [ |
|
|
"height", |
|
|
"weight", |
|
|
"chest", |
|
|
"waist", |
|
|
"hips", |
|
|
] |
|
|
|
|
|
OPTIONAL_MEASUREMENTS = { |
|
|
"shoulder_width": 40.0, |
|
|
"arm_length": 60.0, |
|
|
"leg_length": 90.0, |
|
|
"inseam": 75.0, |
|
|
} |
|
|
|
|
|
@classmethod |
|
|
def validate_measurements(cls, measurements: Dict) -> Dict[str, str]: |
|
|
errors = [] |
|
|
|
|
|
for field in cls.REQUIRED_MEASUREMENTS: |
|
|
if field not in measurements: |
|
|
errors.append(f"Missing required measurement: {field}") |
|
|
elif not isinstance(measurements[field], (int, float)): |
|
|
errors.append(f"Invalid type for {field}: must be number") |
|
|
elif measurements[field] <= 0: |
|
|
errors.append(f"Invalid value for {field}: must be positive") |
|
|
|
|
|
for field, default in cls.OPTIONAL_MEASUREMENTS.items(): |
|
|
if field in measurements: |
|
|
if not isinstance(measurements[field], (int, float)): |
|
|
errors.append(f"Invalid type for {field}: must be number") |
|
|
elif measurements[field] <= 0: |
|
|
errors.append(f"Invalid value for {field}: must be positive") |
|
|
|
|
|
return { |
|
|
"valid": len(errors) == 0, |
|
|
"errors": errors |
|
|
} |
|
|
|
|
|
@classmethod |
|
|
def normalize_measurements(cls, measurements: Dict) -> np.ndarray: |
|
|
processed = measurements.copy() |
|
|
for field, default in cls.OPTIONAL_MEASUREMENTS.items(): |
|
|
if field not in processed: |
|
|
processed[field] = default |
|
|
|
|
|
normalized = [] |
|
|
measurement_order = [ |
|
|
"height", "weight", "chest", "waist", "hips", |
|
|
"shoulder_width", "arm_length", "leg_length", "inseam" |
|
|
] |
|
|
|
|
|
for field in measurement_order: |
|
|
value = processed[field] |
|
|
factor = cls.NORMALIZATION_FACTORS[field] |
|
|
normalized.append(value / factor) |
|
|
|
|
|
return np.array(normalized, dtype=np.float32) |
|
|
|
|
|
@classmethod |
|
|
def process(cls, measurements: Dict) -> np.ndarray: |
|
|
validation = cls.validate_measurements(measurements) |
|
|
if not validation["valid"]: |
|
|
raise ValueError(f"Invalid measurements: {', '.join(validation['errors'])}") |
|
|
|
|
|
return cls.normalize_measurements(measurements) |
|
|
|
|
|
|
|
|
def process_measurements(measurements: Dict) -> np.ndarray: |
|
|
return MeasurementProcessor.process(measurements) |
|
|
|
|
|
|