using ANOVA, Test, DataFrames, GLM

Base.isapprox(a::Anova, b::Anova) =
  a.Source == b.Source && a.DF ≈ b.DF && a.SS ≈ b.SS && a.MSS ≈ b.MSS &&
  a.F ≈ b.F && a.p ≈ b.p

# # write your own tests here
data = DataFrame(ID = categorical(1:25),
                 Tire = categorical(["GT", "GT", "MX", "MX", "LS", "GT", "LS", "LS", "LS", "MX", "MX", "GT", "LS", "GT", "MX", "MX", "GT", "MX", "LS", "LS", "GT", "MX", "GT", "LS", "LS"]),
                 Tread = categorical([10, 1.5, 1.5, 10, 10, 10, 1.5, 1.5, 10, 10, 10, 10, 1.5, 1.5, 10, 1.5, 10, 1.5, 1.5, 10, 1.5, 1.5, 1.5, 10, 10]),
                 ABS = categorical(["enabled", "disabled", "enabled", "enabled", "disabled", "enabled", "enabled", "disabled", "disabled", "disabled", "disabled", "disabled", "enabled", "disabled", "enabled", "enabled", "disabled", "disabled", "disabled", "enabled", "enabled", "disabled", "enabled", "enabled", "enabled"]),
                 Distance = 10 * [1.93557287740925, 2.33806943448595, 2.40077846814577, 2.50714195337437, 2.63983294771174, 1.86088838586581, 2.32992470891205, 2.61332521553405, 3.10241104060570, 2.61751523813390, 2.70498523179508, 2.46421568043517, 2.38080587240067, 2.59001814923499, 2.40457318442931, 2.48136216797396, 2.60228457322805, 2.72711342214876, 2.94439325048592, 2.40498649478329, 2.19492468934002, 2.62485867993076, 2.24742018940027, 2.10579535297714, 2.00579535297714])
# prepare test for ANOVA type III
anova1_expected = Anova(
          ["ABS", "Tread", "Tire","ABS & Tread", "ABS & Tire", "Tread & Tire", "&(ABS, Tread, Tire)", "Residuals"],
          [1, 1, 2, 1, 2, 2, 2, 13],
          [106.5991986929681445, 2.3651163588824207, 38.2807197340170120, 7.8051389666327555, 12.5399359441607761, 1.6429152697879308, 4.7578414794463368, 31.2374270953612125],
          [44.36311539929538128, 0.98428441534601785, 7.96559452580719363, 3.24824468598099525, 2.60935650648222861, 0.34186391923448084, 0.99002934915192564, 0],
          [1.5624161055791751e-05, 3.3925131671067088e-01, 5.5176093522618852e-03, 9.4722296495528976e-02, 1.1149792216959341e-01, 7.1664324192550988e-01, 3.9791832675247707e-01, 0]
          )
anova2_expected = Anova(
          ["ABS", "Tread", "Tire","ABS & Tread", "ABS & Tire", "Tread & Tire", "&(ABS, Tread, Tire)", "Residuals"],
          [1, 1, 2, 1, 2, 2, 2, 13],
          [107.3953075516341755, 2.3441186495561617, 39.0185831196514528, 7.1128272849473611, 12.5726139970648312, 1.6429152697879310, 4.7578414794463377, 31.2374270953612196],
          [44.69442998327386363, 0.97554585245452230, 8.11913188315684131, 2.96012710720490624, 2.61615627725810418, 0.34186391923448167,  0.99002934915192509, 0],
          [1.5039459685901507e-05, 3.4132855401856044e-01, 5.1516520460311733e-03, 1.0903910333788396e-01, 1.1095844647188244e-01, 7.1664324192550932e-01, 3.9791832675247707e-01, 0]
          )
anova3_expected = Anova(
          ["ABS", "Tread", "Tire","ABS & Tread", "ABS & Tire", "Tread & Tire", "&(ABS, Tread, Tire)", "Residuals"],
          [1, 1, 2, 1, 2, 2, 2, 13],
          [102.1138211805702980, 2.0356309732669118, 40.1164208238708397, 6.9792255733881632, 12.3635146287293978, 1.6557631208168218, 4.7578414794463484, 31.237427095361188],
          [42.49644733207060199, 0.84716332659802784, 8.34757403543913412, 2.90452642520995008, 2.57264610306765462, 0.34453734785690932, 0.99002934915192542, 0],
          [1.9453276992336526e-05, 3.7412049964586458e-01, 4.6577488940770014e-03, 1.1209905804371272e-01, 1.1446323312399301e-01, 7.1482574202441140e-01, 3.9791832675247707e-01, 0]
          )
model = fit(LinearModel,
            @formula(Distance ~ ABS * Tread * Tire),
            data,
            contrasts = Dict(:ABS => EffectsCoding(),
                             :Tread => EffectsCoding(),
                             :Tire => EffectsCoding()))
@testset "Three Factors Model" begin
    @test Anova(model, anovatype = 1) ≈ anova1_expected
    @test Anova(model, anovatype = 2) ≈ anova2_expected
    @test Anova(model) ≈ anova3_expected
end
