fix(plagiarism): не матчить против чужих/своих же загруженных работ
Критично: 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:
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user