001package org.nasdanika.ai; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.Collections; 006import java.util.List; 007import java.util.Map; 008 009import reactor.core.publisher.Mono; 010 011public class CompositeFloatSimilarityComputer<T> implements SimilarityComputer<T,Float> { 012 013 protected Collection<Map.Entry<SimilarityComputer<? super T, Float>,Float>> computers = Collections.synchronizedCollection(new ArrayList<>()); 014 protected float totalWeight; 015 016 public synchronized CompositeFloatSimilarityComputer<T> addComputer(SimilarityComputer<? super T, Float> computer, float weight) { 017 if (weight != 0) { 018 computers.add(Map.entry(computer, weight)); 019 totalWeight += weight; 020 } 021 return this; 022 } 023 024 @Override 025 public Mono<Float> computeAsync(T a, T b) { 026 if (computers.isEmpty() || totalWeight == 0) { 027 return Mono.just(0.0f); 028 } 029 List<Mono<Float>> results = computers 030 .stream() 031 .map(e -> e.getKey().computeAsync(a, b).map(r -> r * e.getValue())) 032 .toList(); 033 034 return Mono.zip(results, ra -> { 035 float total = 0; 036 for (int i = 0; i < ra.length; ++i) { 037 total += (Float) ra[i]; 038 } 039 return total / totalWeight; 040 }); 041 } 042 043}