Jerlshin's picture
refined progress and defect fix
761d149
Raw
History Blame Contribute Delete
2.38 kB
from __future__ import annotations
from typing import final
from pydantic import BaseModel, ConfigDict
from redstack.config.schema import LogisticsPolicy
from redstack.domain.candidate.logistics import LogisticsProfile
from redstack.domain.enums import LocationFit, NoticeFit
from redstack.domain.ids import Multiplier
@final
class LogisticsEngine(BaseModel):
"""Stateless, pure logistics multiplier engine."""
model_config = ConfigDict(frozen=True, extra="forbid", arbitrary_types_allowed=False)
policy: LogisticsPolicy
# ------------------------------------------------------------------ public
def multiplier(self, profile: LogisticsProfile) -> Multiplier:
"""Compose the bounded logistics multiplier in ``[m_min, m_max]``.
Combination order (fixed, deterministic): location-fit factor × notice-fit
factor × work-mode contribution × salary-inversion dampen, then clamped
into the policy bounds.
"""
location_factor = self._location_factor(profile.location_fit)
notice_factor = self._notice_factor(profile.notice_fit)
# Work-mode fit (already a UnitScore upstream) contributes via a bounded
# weight: a perfect work-mode match contributes ``work_mode_weight``,
# a total mismatch contributes nothing.
work_mode = 1.0 + self.policy.work_mode_weight * (
float(profile.work_mode_fit) - 1.0
)
salary_dampen = (
self.policy.salary_inversion_factor if profile.salary.is_inverted else 1.0
)
raw = location_factor * notice_factor * work_mode * salary_dampen
return self._clamp(raw)
# --------------------------------------------------------------- internals
def _location_factor(self, fit: LocationFit) -> float:
return self.policy.location_fit_factor.get(fit, self.policy.location_default_factor)
def _notice_factor(self, fit: NoticeFit) -> float:
return self.policy.notice_fit_factor.get(fit, self.policy.notice_default_factor)
def _clamp(self, value: float) -> Multiplier:
bounded = (
self.policy.m_min
if value < self.policy.m_min
else self.policy.m_max
if value > self.policy.m_max
else value
)
return Multiplier(bounded)
__all__: tuple[str, ...] = ("LogisticsEngine",)