File size: 1,683 Bytes
db3715a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""
feedback/diff_engine.py — difflib-based diff with change_ratio

Computes structured diffs between original and edited draft text.
Filters out trivially small edits (< 5% change) to avoid learning
from minor typo fixes.
"""

import difflib
from models import EditDiff


class DiffEngine:
    """Compute structured diffs between original and edited text."""

    def compute(self, original: str, edited: str) -> EditDiff:
        """
        Compute the diff between original and edited text.

        Returns an EditDiff with additions, deletions, and change_ratio.
        change_ratio ranges from 0.0 (identical) to 1.0 (completely different).
        """
        orig_lines = original.splitlines()
        edit_lines = edited.splitlines()

        opcodes = difflib.SequenceMatcher(
            None, orig_lines, edit_lines
        ).get_opcodes()

        additions: list[str] = []
        deletions: list[str] = []

        for tag, i1, i2, j1, j2 in opcodes:
            if tag == "insert":
                additions.append("\n".join(edit_lines[j1:j2]))
            elif tag == "delete":
                deletions.append("\n".join(orig_lines[i1:i2]))
            elif tag == "replace":
                deletions.append("\n".join(orig_lines[i1:i2]))
                additions.append("\n".join(edit_lines[j1:j2]))

        # Character-level similarity ratio
        change_ratio = 1.0 - difflib.SequenceMatcher(
            None, original, edited
        ).ratio()

        return EditDiff(
            additions=additions,
            deletions=deletions,
            original=original,
            edited=edited,
            change_ratio=round(change_ratio, 3),
        )