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}