class PartialMatchEvaluator:
    def __init__(self, case_sensitive=False):
        self.case_sensitive = case_sensitive

    def __call__(self, *, response: str, expected_answer: str, **kwargs):
        if response is None or response.strip() == "":
            raise ValueError("Response cannot be null or empty.")
        if expected_answer is None:
            raise ValueError("Expected answer cannot be null.")

        resp = response.strip()
        exp = expected_answer.strip()

        # Adjust case sensitivity
        if not self.case_sensitive:
            resp = resp.lower()
            exp = exp.lower()

        # Score: fraction of expected text found inside response
        if exp in resp:
            # Percent of expected text that matched (length-based)
            score = len(exp) / len(resp)
        else:
            score = 0.0

        return {
            "partial_match": score,
            "partial_match_reason": f"Match score: {score:.3f}"
        }
