This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
package ru.soune.nocopy.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.soune.nocopy.dto.file.SimilarFileResponse;
|
||||
import ru.soune.nocopy.repository.ImageHashRepository;
|
||||
import ru.soune.nocopy.repository.ImageSimilarityRepository;
|
||||
import ru.soune.nocopy.repository.SimilarImageProjection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class FileSimilarityService {
|
||||
|
||||
private final ImageSimilarityRepository repository;
|
||||
private final ImageHashRepository hashRepository;
|
||||
|
||||
public List<SimilarFileResponse> findSimilarFiles(String fileId) {
|
||||
var imageHashEntity = hashRepository.findById(fileId)
|
||||
.orElseThrow(() -> new RuntimeException("Hash not found"));
|
||||
|
||||
Integer hash64Hi = imageHashEntity.getHash64Hi();
|
||||
Integer hash64Lo = imageHashEntity.getHash64Lo();
|
||||
|
||||
List<SimilarImageProjection> candidates =
|
||||
repository.findCandidates(fileId);
|
||||
|
||||
return candidates.stream()
|
||||
.map(c -> {
|
||||
Integer cHi = c.getHash64Hi();
|
||||
Integer cLo = c.getHash64Lo();
|
||||
|
||||
int hamming = hamming64(hash64Hi, hash64Lo, cHi, cLo);
|
||||
|
||||
String level;
|
||||
if (hamming <= 5) {
|
||||
level = "DUPLICATE";
|
||||
} else if (hamming <= 12) {
|
||||
level = "SIMILAR";
|
||||
} else {
|
||||
level = "DIFFERENT";
|
||||
}
|
||||
|
||||
return SimilarFileResponse.builder()
|
||||
.fileId(c.getSimilarFileId())
|
||||
.originalFileName(c.getOriginalFileName())
|
||||
.fileSize(c.getFileSize())
|
||||
.hammingDistance(hamming)
|
||||
.similarityLevel(level)
|
||||
.build();
|
||||
})
|
||||
.sorted((a, b) ->
|
||||
Integer.compare(a.getHammingDistance(), b.getHammingDistance()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private int hamming64(int aHi, int aLo, int bHi, int bLo) {
|
||||
return Integer.bitCount(aHi ^ bHi)
|
||||
+ Integer.bitCount(aLo ^ bLo);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user