Spaces:
Running
Running
automated progress bar
Browse files- utils/user_progress.py +113 -0
utils/user_progress.py
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# utils/user_progress.py
|
2 |
+
|
3 |
+
import datetime
|
4 |
+
from sqlalchemy import and_
|
5 |
+
from utils.database import get_db
|
6 |
+
from data.models import UserProgress, Annotation, Validation, Annotator, TTSData
|
7 |
+
from utils.logger import Logger
|
8 |
+
|
9 |
+
log = Logger()
|
10 |
+
|
11 |
+
|
12 |
+
def get_user_progress(user_id: int, target_annotator_id: int) -> UserProgress:
|
13 |
+
"""Get or create user progress record for a specific target annotator"""
|
14 |
+
with get_db() as db:
|
15 |
+
progress = db.query(UserProgress).filter(
|
16 |
+
and_(
|
17 |
+
UserProgress.user_id == user_id,
|
18 |
+
UserProgress.target_annotator_id == target_annotator_id
|
19 |
+
)
|
20 |
+
).first()
|
21 |
+
|
22 |
+
if not progress:
|
23 |
+
# Create new progress record
|
24 |
+
progress = UserProgress(
|
25 |
+
user_id=user_id,
|
26 |
+
target_annotator_id=target_annotator_id,
|
27 |
+
last_reviewed_annotation_id=None,
|
28 |
+
last_position=0,
|
29 |
+
updated_at=datetime.datetime.now()
|
30 |
+
)
|
31 |
+
db.add(progress)
|
32 |
+
db.commit()
|
33 |
+
log.info(f"Created new progress record for user {user_id} on target annotator {target_annotator_id}")
|
34 |
+
|
35 |
+
return progress
|
36 |
+
|
37 |
+
|
38 |
+
def update_user_progress(user_id: int, target_annotator_id: int, annotation_id: int, position: int):
|
39 |
+
"""Update user progress with the latest reviewed annotation"""
|
40 |
+
with get_db() as db:
|
41 |
+
progress = get_user_progress(user_id, target_annotator_id)
|
42 |
+
progress.last_reviewed_annotation_id = annotation_id
|
43 |
+
progress.last_position = position
|
44 |
+
progress.updated_at = datetime.datetime.now()
|
45 |
+
db.commit()
|
46 |
+
log.info(f"Updated progress for user {user_id}: annotation {annotation_id}, position {position}")
|
47 |
+
|
48 |
+
|
49 |
+
def get_next_unreviewed_annotation(user_id: int, target_annotator_id: int) -> tuple[int, int]:
|
50 |
+
"""
|
51 |
+
Get the next unreviewed annotation ID and its position in the review list.
|
52 |
+
Returns (annotation_id, position) or (None, 0) if no unreviewed items found.
|
53 |
+
"""
|
54 |
+
with get_db() as db:
|
55 |
+
# Get all annotations for the target annotator, ordered by ID
|
56 |
+
annotations = db.query(Annotation).filter(
|
57 |
+
Annotation.annotator_id == target_annotator_id
|
58 |
+
).order_by(Annotation.id).all()
|
59 |
+
|
60 |
+
if not annotations:
|
61 |
+
return None, 0
|
62 |
+
|
63 |
+
# Find the first annotation that hasn't been reviewed by this user
|
64 |
+
for position, annotation in enumerate(annotations):
|
65 |
+
# Check if this annotation has been validated by the current user
|
66 |
+
validation = db.query(Validation).filter(
|
67 |
+
and_(
|
68 |
+
Validation.annotation_id == annotation.id,
|
69 |
+
Validation.validator_id == user_id
|
70 |
+
)
|
71 |
+
).first()
|
72 |
+
|
73 |
+
if not validation:
|
74 |
+
# This annotation hasn't been reviewed yet
|
75 |
+
return annotation.id, position
|
76 |
+
|
77 |
+
# All annotations have been reviewed
|
78 |
+
return None, len(annotations)
|
79 |
+
|
80 |
+
|
81 |
+
def get_last_reviewed_position(user_id: int, target_annotator_id: int) -> int:
|
82 |
+
"""Get the position of the last reviewed annotation by the user"""
|
83 |
+
with get_db() as db:
|
84 |
+
progress = db.query(UserProgress).filter(
|
85 |
+
and_(
|
86 |
+
UserProgress.user_id == user_id,
|
87 |
+
UserProgress.target_annotator_id == target_annotator_id
|
88 |
+
)
|
89 |
+
).first()
|
90 |
+
|
91 |
+
if progress and progress.last_position is not None:
|
92 |
+
return progress.last_position
|
93 |
+
return 0
|
94 |
+
|
95 |
+
|
96 |
+
def get_annotations_from_position(target_annotator_id: int, start_position: int, batch_size: int = 10) -> list:
|
97 |
+
"""
|
98 |
+
Get annotations starting from a specific position with pagination.
|
99 |
+
Returns list of (annotation, filename, sentence) tuples.
|
100 |
+
"""
|
101 |
+
with get_db() as db:
|
102 |
+
# Get annotations ordered by ID, starting from the specified position
|
103 |
+
annotations = db.query(
|
104 |
+
Annotation,
|
105 |
+
TTSData.filename,
|
106 |
+
TTSData.sentence
|
107 |
+
).join(
|
108 |
+
TTSData, Annotation.tts_data_id == TTSData.id
|
109 |
+
).filter(
|
110 |
+
Annotation.annotator_id == target_annotator_id
|
111 |
+
).order_by(Annotation.id).offset(start_position).limit(batch_size).all()
|
112 |
+
|
113 |
+
return annotations
|