using System;
using System.Collections.Generic;
namespace Amphora.RandomComparisons
{
///
/// What one check found: how likely a fair generator is to land this far from the expected result, on either side.
///
public sealed class Outcome
{
public const double FailBelow = 1e-6;
public const double SuspectBelow = 1e-3;
public readonly double P;
public readonly string Detail;
///
/// Whether this is a measurement with no expected value, so it has no probability and no verdict.
///
public readonly bool IsInformation;
public Outcome(double p, string detail, bool isInformation = false)
{
P = p;
Detail = detail;
IsInformation = isInformation;
}
public static Outcome Information(string detail)
{
return new Outcome(1, detail, isInformation: true);
}
///
/// Returns the outcome with the smallest probability, which is the one a reader should look at.
///
public static Outcome Worst(IReadOnlyList outcomes)
{
Outcome returnMe = outcomes[0];
foreach (Outcome outcome in outcomes)
{
if (outcome.P < returnMe.P)
{
returnMe = outcome;
}
}
return returnMe;
}
public string Verdict
{
get
{
if (IsInformation)
{
return "info";
}
if (P < FailBelow)
{
return "FAIL";
}
return P < SuspectBelow ? "SUSPECT" : "ok";
}
}
public string PText
{
get
{
if (IsInformation)
{
return "";
}
return P < 1e-300 ? "p<1e-300" : "p=" + P.ToString("0.###e+0");
}
}
}
///
/// An outcome with the name of the check that produced it.
///
public sealed class NamedOutcome
{
public readonly string Name;
public readonly Outcome Outcome;
///
/// Whether this check runs a method known to be wrong, so failing it is the check working.
///
public readonly bool ExpectsFailure;
public NamedOutcome(string name, Outcome outcome, bool expectsFailure = false)
{
Name = name;
Outcome = outcome;
ExpectsFailure = expectsFailure;
}
}
}