Advertisement
Guest User

Untitled

a guest
Jan 8th, 2025
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.67 KB | Source Code | 0 0
  1.     @Override
  2.     public User verifyStudentFingerprint(Long scheduleId, MultipartFile scannedFingerprintImage) throws IOException {
  3.         // Cache the scanned template first to avoid redundant conversions
  4.         byte[] scannedFingerprintImageBytes = scannedFingerprintImage.getBytes();
  5.         FingerprintTemplate probeTemplate = new FingerprintTemplate(
  6.                 new FingerprintImage(scannedFingerprintImageBytes)
  7.         );
  8.  
  9.         // Fetch schedule and students in parallel using CompletableFuture
  10.         CompletableFuture<Schedule> scheduleFuture = CompletableFuture.supplyAsync(() ->
  11.                 scheduleRepository.findById(scheduleId).orElse(null)
  12.         );
  13.  
  14.         CompletableFuture<List<ScheduleStudent>> studentsFuture = scheduleFuture.thenApplyAsync(schedule ->
  15.                 schedule != null ? scheduleStudentRepository.findByScheduleId(schedule.getId()) : Collections.emptyList()
  16.         );
  17.  
  18.         // Wait for both futures to complete
  19.         Schedule schedule = scheduleFuture.join();
  20.         List<ScheduleStudent> students = studentsFuture.join();
  21.  
  22.         if (schedule == null || students.isEmpty()) return null;
  23.  
  24.         // Extract student IDs and fetch fingerprints
  25.         List<Long> studentIds = students.stream()
  26.                 .map(s -> s.getStudent().getId())
  27.                 .collect(Collectors.toList());
  28.  
  29.         // Use batch fetching for fingerprints
  30.         List<Fingerprint> fingerprints = fingerprintRepository.getOneFingerprintPerUser(studentIds);
  31.         if (fingerprints.isEmpty()) return null;
  32.  
  33.         // Create a thread pool with the number of available processors
  34.         int processors = Runtime.getRuntime().availableProcessors();
  35.         ExecutorService executorService = Executors.newFixedThreadPool(processors);
  36.  
  37.         try {
  38.             // Process fingerprints in batches
  39.             int batchSize = Math.max(1, fingerprints.size() / processors);
  40.             List<List<Fingerprint>> batches = partitionList(fingerprints, batchSize);
  41.  
  42.             // Create tasks for parallel processing
  43.             List<CompletableFuture<Optional<Map.Entry<Fingerprint, Double>>>> futures = batches.stream()
  44.                     .map(batch -> CompletableFuture.supplyAsync(() -> processFingerprintBatch(batch, probeTemplate), executorService))
  45.                     .toList();
  46.  
  47.             // Find the best match across all batches
  48.             Optional<Map.Entry<Fingerprint, Double>> bestMatch = futures.stream()
  49.                     .map(CompletableFuture::join)
  50.                     .filter(Optional::isPresent)
  51.                     .map(Optional::get)
  52.                     .max(Map.Entry.comparingByValue());
  53.  
  54.             if (bestMatch.isEmpty() || bestMatch.get().getValue() < threshold) {
  55.                 return null;
  56.             }
  57.  
  58.             // Update attendance status
  59.             Fingerprint matchedFingerprint = bestMatch.get().getKey();
  60.             ScheduleStudent matchedStudent = students.stream()
  61.                     .filter(s -> s.getStudent().getId().equals(matchedFingerprint.getUser().getId()))
  62.                     .findFirst()
  63.                     .orElse(null);
  64.  
  65.             if (matchedStudent != null) {
  66.                 matchedStudent.setHasLogged(true);
  67.                 scheduleStudentRepository.save(matchedStudent);
  68.                 return matchedFingerprint.getUser();
  69.             }
  70.  
  71.             return null;
  72.         } finally {
  73.             executorService.shutdown();
  74.         }
  75.     }
  76.  
  77.     private <T> List<List<T>> partitionList(List<T> list, int batchSize) {
  78.         if (batchSize <= 0) throw new IllegalArgumentException("Batch size must be positive");
  79.  
  80.         int numBatches = (list.size() + batchSize - 1) / batchSize;
  81.         return IntStream.range(0, numBatches)
  82.                 .mapToObj(i -> list.subList(
  83.                         i * batchSize,
  84.                         Math.min((i + 1) * batchSize, list.size())
  85.                 ))
  86.                 .collect(Collectors.toList());
  87.     }
  88.  
  89.     private Optional<Map.Entry<Fingerprint, Double>> processFingerprintBatch(
  90.             List<Fingerprint> batch,
  91.             FingerprintTemplate probeTemplate
  92.     ) {
  93.         FingerprintMatcher matcher = new FingerprintMatcher(probeTemplate);
  94.  
  95.         return batch.parallelStream()
  96.                 .map(fingerprint -> {
  97.                     FingerprintTemplate template = new FingerprintTemplate(
  98.                             new FingerprintImage(fingerprint.getFingerprint())
  99.                     );
  100.                     return Map.entry(fingerprint, matcher.match(template));
  101.                 })
  102.                 .filter(entry -> entry.getValue() >= threshold)
  103.                 .max(Map.Entry.comparingByValue());
  104.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement