Data/src/main/java/de/ph87/data/view/tree/ViewBinary.java

85 lines
2.1 KiB
Java

package de.ph87.data.view.tree;
import de.ph87.data.point.Point;
import de.ph87.data.view.ViewScope;
import jakarta.persistence.*;
import lombok.*;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@DiscriminatorValue("binary")
public class ViewBinary extends View {
@NonNull
@Enumerated(EnumType.STRING)
private Operation operation;
@NonNull
@OneToOne(optional = false, orphanRemoval = true, cascade = CascadeType.ALL)
private View view0;
@NonNull
@OneToOne(optional = false, orphanRemoval = true, cascade = CascadeType.ALL)
private View view1;
public ViewBinary(@NonNull final Operation operation, @NonNull final View view0, @NonNull final View view1) {
this.operation = operation;
this.view0 = view0;
this.view1 = view1;
}
public enum Operation {
PLUS(Double::sum),
MINUS((a, b) -> a - b),
MULTIPLY((a, b) -> a * b),
DIVIDE((a, b) -> a / b),
MODULO((a, b) -> a % b),
PERCENT((a, b) -> a / b * 100),
;
public final BiFunction<Double, Double, Double> function;
Operation(final BiFunction<Double, Double, Double> function) {
this.function = function;
}
@NonNull
public Point apply(@NonNull final Point a, @NonNull final Point b) {
return new Point(a.date, function.apply(a.value, b.value));
}
}
@Override
public List<Point> getPoints(final @NonNull ViewScope scope) {
final List<Point> pointsA = view0.getPoints(scope);
final List<Point> pointsB = view1.getPoints(scope);
final List<Point> result = new ArrayList<>(pointsA.size() + pointsB.size());
int indexA = 0;
int indexB = 0;
while (indexA < pointsA.size() && indexB < pointsB.size()) {
final Point pointA = pointsA.get(indexA);
final Point pointB = pointsB.get(indexB);
int cmp = pointA.date.compareTo(pointB.date);
if (cmp < 0) {
indexA++;
} else if (cmp > 0) {
indexB++;
} else {
result.add(operation.apply(pointA, pointB));
indexA++;
indexB++;
}
}
return result;
}
}