fix(plagiarism): не матчить против чужих/своих же загруженных работ
All checks were successful
Deploy / deploy (push) Successful in 14m38s
Deploy / test (push) Successful in 2m47s

Критично: L1/L2/L3 сравнивали фрагменты со ВСЕЙ базой documents, включая
source=user_submission — работы, которые auto_approve_submission сам же
затаскивал в корпус после проверки. Итог: студент, перепроверивший тот
же файл дважды, получал 100% "точное совпадение" по всем фрагментам —
против собственной же более ранней загрузки.

Фикс: все три уровня исключают source=user_submission из кандидатов на
совпадение. AUTO_APPROVE_SUBMISSIONS выключен по умолчанию — раньше рос
корпус для будущего сравнения, но без защиты от self/cross-match это
опаснее, чем полезно.
This commit is contained in:
jze9
2026-08-25 17:42:23 +05:00
parent 43034eda33
commit 74cbf1b8f4
3 changed files with 20 additions and 7 deletions

View File

@@ -108,13 +108,20 @@ def extract_and_check(
continue
frag_hashes = list(frag_fp)
# Источник, разделяющий больше всего отпечатков с этим фрагментом
# Источник, разделяющий больше всего отпечатков с этим фрагментом.
# user_submission исключены: это чужие непубличные загрузки (и
# свои же прошлые прогоны того же файла) — сравнение с ними даёт
# ложные 100%-совпадения, а не реальный плагиат из источника.
row = session.execute(
select(
Fingerprint.doc_id,
func.count(Fingerprint.id).label("cnt"),
)
.where(Fingerprint.hash_value.in_(frag_hashes))
.join(Document, Document.id == Fingerprint.doc_id)
.where(
Fingerprint.hash_value.in_(frag_hashes),
Document.source != "user_submission",
)
.group_by(Fingerprint.doc_id)
.order_by(func.count(Fingerprint.id).desc())
.limit(1)
@@ -164,7 +171,7 @@ def extract_and_check(
try:
doc_id = int(key.split(":")[-1])
doc = session.get(Document, doc_id)
if not doc:
if not doc or doc.source == "user_submission":
continue
level2_matches.append({