// Path: fluency-core/src/main/java/org/komamitsu/fluency/validation/Validatable.java
// public interface Validatable
// {
//     class ValidationList {
//         private static class Validation
//         {
//             Class<? extends Annotation> annotationClass;
//             BiFunction<Annotation, Number, Boolean> isValid;
//             String messageTemplate;
// 
//             Validation(
//                     Class<? extends Annotation> annotationClass,
//                     BiFunction<Annotation, Number, Boolean> isValid,
//                     String messageTemplate)
//             {
//                 this.annotationClass = annotationClass;
//                 this.isValid = isValid;
//                 this.messageTemplate = messageTemplate;
//             }
//         }
// 
//         private static final Validation VALIDATION_MAX  = new Validation(
//                 Max.class,
//                 (annotation, actual) -> {
//                     Max maxAnnotation = (Max) annotation;
//                     if (maxAnnotation.inclusive()) {
//                         return maxAnnotation.value() >= actual.longValue();
//                     }
//                     else {
//                         return maxAnnotation.value() > actual.longValue();
//                     }
//                 },
//                 "This field (%s) is more than (%s)");
// 
//         private static final Validation VALIDATION_MIN  = new Validation(
//                 Min.class,
//                 (annotation, actual) -> {
//                     Min minAnnotation = (Min) annotation;
//                     if (minAnnotation.inclusive()) {
//                         return minAnnotation.value() <= actual.longValue();
//                     }
//                     else {
//                         return minAnnotation.value() < actual.longValue();
//                     }
//                 },
//                 "This field (%s) is less than (%s)");
// 
//         private static final Validation VALIDATION_DECIMAL_MAX  = new Validation(
//                 DecimalMax.class,
//                 (annotation, actual) -> {
//                     DecimalMax maxAnnotation = (DecimalMax) annotation;
//                     BigDecimal limitValue = new BigDecimal(maxAnnotation.value());
//                     BigDecimal actualValue = new BigDecimal(actual.toString());
//                     if (maxAnnotation.inclusive()) {
//                         return limitValue.compareTo(actualValue) >= 0;
//                     }
//                     else {
//                         return limitValue.compareTo(actualValue) > 0;
//                     }
//                 },
//                 "This field (%s) is more than (%s)");
// 
//         private static final Validation VALIDATION_DECIMAL_MIN  = new Validation(
//                 DecimalMin.class,
//                 (annotation, actual) -> {
//                     DecimalMin maxAnnotation = (DecimalMin) annotation;
//                     BigDecimal limitValue = new BigDecimal(maxAnnotation.value());
//                     BigDecimal actualValue = new BigDecimal(actual.toString());
//                     if (maxAnnotation.inclusive()) {
//                         return limitValue.compareTo(actualValue) <= 0;
//                     }
//                     else {
//                         return limitValue.compareTo(actualValue) < 0;
//                     }
//                 },
//                 "This field (%s) is less than (%s)");
// 
//         private static final List<Validation> VALIDATIONS = Arrays.asList(
//                 VALIDATION_MAX,
//                 VALIDATION_MIN,
//                 VALIDATION_DECIMAL_MAX,
//                 VALIDATION_DECIMAL_MIN);
//     }
// 
//     default void validate()
//     {
//         Class<? extends Object> klass = getClass();
//         while (klass != Object.class) {
//             for (Field field : klass.getDeclaredFields()) {
//                 for (ValidationList.Validation validation : ValidationList.VALIDATIONS) {
//                     Class<? extends Annotation> annotationClass = validation.annotationClass;
//                     if (field.isAnnotationPresent(annotationClass)) {
//                         Annotation annotation = field.getAnnotation(annotationClass);
//                         Object value;
//                         try {
//                             field.setAccessible(true);
//                             value = field.get(this);
//                         }
//                         catch (IllegalAccessException e) {
//                             throw new RuntimeException(
//                                     String.format("Failed to get a value from field (%s)", field), e);
//                         }
// 
//                         if (value == null) {
//                             break;
//                         }
// 
//                         if (!(value instanceof Number)) {
//                             throw new IllegalArgumentException(
//                                     String.format("This field has (%s), but actual field is (%s)", annotation, value.getClass()));
//                         }
// 
//                         if (!validation.isValid.apply(annotation, (Number) value)) {
//                             throw new IllegalArgumentException(
//                                     String.format(validation.messageTemplate, field, value));
//                         }
//                     }
//                 }
//             }
//             klass = klass.getSuperclass();
//         }
//     }
// }


import org.komamitsu.failuredetector.PhiAccuralFailureDetector;
import org.komamitsu.fluency.validation.Validatable;
import org.komamitsu.fluency.validation.annotation.DecimalMin;
import org.komamitsu.fluency.validation.annotation.Min;
    {
        failureDetector.heartbeat(now);
    }

    @Override
    public boolean isAvailable()
    {
        return failureDetector.isAvailable();
    }

    public double getPhiThreshold()
    {
        return config.getPhiThreshold();
    }

    public int getArrivalWindowSize()
    {
        return config.getArrivalWindowSize();
    }

    @Override
    public String toString()
    {
        return "PhiAccrualFailureDetectStrategy{" +
                "failureDetector=" + failureDetector +
                "} " + super.toString();
    }

    public static class Config
            extends FailureDetectStrategy.Config
// Path: fluency-core/src/main/java/org/komamitsu/fluency/validation/Validatable.java
// public interface Validatable
// {
//     class ValidationList {
//         private static class Validation
//         {
//             Class<? extends Annotation> annotationClass;
//             BiFunction<Annotation, Number, Boolean> isValid;
//             String messageTemplate;
// 
//             Validation(
//                     Class<? extends Annotation> annotationClass,
//                     BiFunction<Annotation, Number, Boolean> isValid,
//                     String messageTemplate)
//             {
//                 this.annotationClass = annotationClass;
//                 this.isValid = isValid;
//                 this.messageTemplate = messageTemplate;
//             }
//         }
// 
//         private static final Validation VALIDATION_MAX  = new Validation(
//                 Max.class,
//                 (annotation, actual) -> {
//                     Max maxAnnotation = (Max) annotation;
//                     if (maxAnnotation.inclusive()) {
//                         return maxAnnotation.value() >= actual.longValue();
//                     }
//                     else {
//                         return maxAnnotation.value() > actual.longValue();
//                     }
//                 },
//                 "This field (%s) is more than (%s)");
// 
//         private static final Validation VALIDATION_MIN  = new Validation(
//                 Min.class,
//                 (annotation, actual) -> {
//                     Min minAnnotation = (Min) annotation;
//                     if (minAnnotation.inclusive()) {
//                         return minAnnotation.value() <= actual.longValue();
//                     }
//                     else {
//                         return minAnnotation.value() < actual.longValue();
//                     }
//                 },
//                 "This field (%s) is less than (%s)");
// 
//         private static final Validation VALIDATION_DECIMAL_MAX  = new Validation(
//                 DecimalMax.class,
//                 (annotation, actual) -> {
//                     DecimalMax maxAnnotation = (DecimalMax) annotation;
//                     BigDecimal limitValue = new BigDecimal(maxAnnotation.value());
//                     BigDecimal actualValue = new BigDecimal(actual.toString());
//                     if (maxAnnotation.inclusive()) {
//                         return limitValue.compareTo(actualValue) >= 0;
//                     }
//                     else {
//                         return limitValue.compareTo(actualValue) > 0;
//                     }
//                 },
//                 "This field (%s) is more than (%s)");
// 
//         private static final Validation VALIDATION_DECIMAL_MIN  = new Validation(
//                 DecimalMin.class,
//                 (annotation, actual) -> {
//                     DecimalMin maxAnnotation = (DecimalMin) annotation;
//                     BigDecimal limitValue = new BigDecimal(maxAnnotation.value());
//                     BigDecimal actualValue = new BigDecimal(actual.toString());
//                     if (maxAnnotation.inclusive()) {
//                         return limitValue.compareTo(actualValue) <= 0;
//                     }
//                     else {
//                         return limitValue.compareTo(actualValue) < 0;
//                     }
//                 },
//                 "This field (%s) is less than (%s)");
// 
//         private static final List<Validation> VALIDATIONS = Arrays.asList(
//                 VALIDATION_MAX,
//                 VALIDATION_MIN,
//                 VALIDATION_DECIMAL_MAX,
//                 VALIDATION_DECIMAL_MIN);
//     }
// 
//     default void validate()
//     {
//         Class<? extends Object> klass = getClass();
//         while (klass != Object.class) {
//             for (Field field : klass.getDeclaredFields()) {
//                 for (ValidationList.Validation validation : ValidationList.VALIDATIONS) {
//                     Class<? extends Annotation> annotationClass = validation.annotationClass;
//                     if (field.isAnnotationPresent(annotationClass)) {
//                         Annotation annotation = field.getAnnotation(annotationClass);
//                         Object value;
//                         try {
//                             field.setAccessible(true);
//                             value = field.get(this);
//                         }
//                         catch (IllegalAccessException e) {
//                             throw new RuntimeException(
//                                     String.format("Failed to get a value from field (%s)", field), e);
//                         }
// 
//                         if (value == null) {
//                             break;
//                         }
// 
//                         if (!(value instanceof Number)) {
//                             throw new IllegalArgumentException(
//                                     String.format("This field has (%s), but actual field is (%s)", annotation, value.getClass()));
//                         }
// 
//                         if (!validation.isValid.apply(annotation, (Number) value)) {
//                             throw new IllegalArgumentException(
//                                     String.format(validation.messageTemplate, field, value));
//                         }
//                     }
//                 }
//             }
//             klass = klass.getSuperclass();
//         }
//     }
// }


// Path: fluency-fluentd/src/main/java/org/komamitsu/fluency/fluentd/ingester/sender/failuredetect/PhiAccrualFailureDetectStrategy.java
import org.komamitsu.failuredetector.PhiAccuralFailureDetector;
import org.komamitsu.fluency.validation.Validatable;
import org.komamitsu.fluency.validation.annotation.DecimalMin;
import org.komamitsu.fluency.validation.annotation.Min;

    {
        failureDetector.heartbeat(now);
    }

    @Override
    public boolean isAvailable()
    {
        return failureDetector.isAvailable();
    }

    public double getPhiThreshold()
    {
        return config.getPhiThreshold();
    }

    public int getArrivalWindowSize()
    {
        return config.getArrivalWindowSize();
    }

    @Override
    public String toString()
    {
        return "PhiAccrualFailureDetectStrategy{" +
                "failureDetector=" + failureDetector +
                "} " + super.toString();
    }

    public static class Config
            extends FailureDetectStrategy.Config
            implements Validatable