class JobRuntimePredictionSelectors {

    public static JobRuntimePredictionSelector aboveThreshold(double runtimeThresholdInSeconds,
                                                              double sigmaThreshold,
                                                              double quantile,
                                                              Map<String, String> selectionMetadata) {
        Map<String, String> allMetadata = appendSelectorInfoIfMissing(
                selectionMetadata,
                () -> String.format("aboveThreshold{runtimeThresholdInSeconds=%s, sigmaThreshold=%s}, createdAt: %s",
                        runtimeThresholdInSeconds, sigmaThreshold,
                        DateTimeExt.toLocalDateTimeString(System.currentTimeMillis())
                )
        );

        return (jobDescriptor, predictions) -> {
            SortedSet<JobRuntimePrediction> predictionsSet = predictions.getPredictions();
            if (CollectionsExt.isNullOrEmpty(predictionsSet) || predictionsSet.size() < 2) {
                return Optional.empty();
            }

            JobRuntimePrediction first = predictionsSet.first();
            if (!JobRuntimePredictionUtil.expectedLowest(first)) {
                return Optional.empty();
            }
            JobRuntimePrediction requested = JobRuntimePredictionUtil.findRequested(predictionsSet, quantile).orElse(null);
            if (requested == null || requested.getRuntimeInSeconds() > runtimeThresholdInSeconds) {
                return Optional.empty();
            }

            double sigma = (requested.getRuntimeInSeconds() - first.getRuntimeInSeconds()) / JobRuntimePredictionUtil.NORM_SIGMA;
            if (sigma > sigmaThreshold) {
                return Optional.empty();
            }
            return Optional.of(JobRuntimePredictionSelection.newBuilder()
                    .withPrediction(requested)
                    .withMetadata(allMetadata)
                    .build()
            );
        };
    }

    private  JobRuntimePredictionSelectors();

}