/*
    TCFbETestCase4.cpp    June 6, 2004.

    Copyright (C) 2003-2004 CFbE Research Group,
    Software Engineering Laboratory,
    Graduate School of Information Science,
    Nara Institute of Science and Technology,
    All rights reserved.

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, (at your option) or
    any later version.

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with GNU Emacs; see the file COPYING.  If not, write to the
    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/
//---------------------------------------------------------------------------
#ifndef TCFbETestCase4H
#define TCFbETestCase4H
//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------
#include <cppunit/TestCase.h>
#include <cppunit/TestSuite.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TestRunner.h>

USING_NAMESPACE_CPPUNIT
//---------------------------------------------------------------------------
#include <System.hpp>

//#include "TCFbEDataAccessor.h"
#include "TCFbETable.h"
#include "TCFbEDataSet.h"
#include "TCFbECommandLineParser.h"
#include "TCFbEOutputCash.h"
#include "TCFbEOutputFormatter.h"
#include "TCFbEDataLoader.h"
//---------------------------------------------------------------------------
// テストケース1
class TCFbETestCase4 : public TestCase
{
    // コンストラクタ
    TEST_CASE_COMMON(TCFbETestCase4)

public:
    // テストを初期化する
    //    FILENAME    BUG    LOC    N_COMM    HALVOL    SCPMN    N_VEXUSE
    //    module_1    1    800    0.3        3600    4        0.6
    //    module_2    0    250    0.2        3200    3.5        0.4
    //    module_3    0    500    0        3200    3        0.3
    //    module_4    1    700    0.25    3500    4        0.8
    //    module_5    0    600    0.2        3200    2.5        0.1
    //    module_6    1    900    0.35    3800    4.1        0.75
    virtual void setUp() {
        TStringList* TestStringList = new TStringList();
        TestStringList->Add("FILENAME,    BUG,    LOC,    N_COMM,    HALVOL,    SCPMN,    N_VEXUSE");
        TestStringList->Add("module_1,    1,        800,    0.3,    3600,    4,        0.6");
        TestStringList->Add("module_2,    0,        250,    0.2,    3200,    3.5,    0.4");
        TestStringList->Add("module_3,    0,        500,    0,        3200,    3,        0.3");
        TestStringList->Add("module_4,    1,        700,    0.25,    3500,    4,        0.8");
        TestStringList->Add("module_5,    0,        600,    0.2,    3200,    2.5,    0.1");
        TestStringList->Add("module_6,    1,        900,    0.35,    3800,    4.1,    0.75");

        this->DataSet = new TCFbEDataSet(TestStringList);
        delete TestStringList;

        this->DataSet->TemporaryUnable(0, 0);
    }

    // テストの後片付けをする
    virtual void tearDown() {
        this->DataSet->RecoverEnabled();
        delete this->DataSet;
    }

    //---------------------------------------------------------------------------
    // 以下，アルゴリズムのテスト
    //---------------------------------------------------------------------------
    // Value-based & Row-based
    //---------------------------------------------------------------------------
    virtual void Test_TCFbECosineSimilarity_vbValue_abRow() {
        this->DataSet->PrepareCF(vbValue, abRow, new TCFbECosineSimilarity(), NULL, 0, false, 0.0, false, 1.0);

        this->DataSet->Similarities["module_2"]["module_1"];
        this->DataSet->Similarities["module_2"]["module_3"];
        this->DataSet->Similarities["module_2"]["module_4"];
        this->DataSet->Similarities["module_2"]["module_5"];
        this->DataSet->Similarities["module_2"]["module_6"];

        TEST_ASSERT_EQUALS_DOUBLE(0.9901177602,    this->DataSet->Similarities["module_1"]["module_2"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.9979735938,    this->DataSet->Similarities["module_1"]["module_3"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.9997737277,    this->DataSet->Similarities["module_1"]["module_4"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.9994448484,    this->DataSet->Similarities["module_1"]["module_5"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.9999035624,    this->DataSet->Similarities["module_1"]["module_6"], 1E-6);
    }

    virtual void Test_TCFbEAdjustedCosineSimilarityWithAverage_vbValue_abRow() {
        this->DataSet->PrepareCF(vbValue, abRow, new TCFbEAdjustedCosineSimilarityWithAverage(), NULL, 0, false, 0.0, false, 1.0);

        this->DataSet->Similarities["module_2"]["module_1"];
        this->DataSet->Similarities["module_2"]["module_3"];
        this->DataSet->Similarities["module_2"]["module_4"];
        this->DataSet->Similarities["module_2"]["module_5"];
        this->DataSet->Similarities["module_2"]["module_6"];

        TEST_ASSERT_EQUALS_DOUBLE(-0.9597356759,    this->DataSet->Similarities["module_1"]["module_2"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(-0.9716063011,    this->DataSet->Similarities["module_1"]["module_3"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.9995642829,    this->DataSet->Similarities["module_1"]["module_4"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(-0.7977311881,    this->DataSet->Similarities["module_1"]["module_5"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.9902375944,    this->DataSet->Similarities["module_1"]["module_6"], 1E-6);
    }

    virtual void Test_TCFbEAdjustedCosineSimilarityWithAverage_vbNormalizedValue_abRow() {
        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbEAdjustedCosineSimilarityWithAverage(), NULL, 0, false, 0.0, false, 1.0);

        this->DataSet->Similarities["module_2"]["module_1"];
        this->DataSet->Similarities["module_2"]["module_3"];
        this->DataSet->Similarities["module_2"]["module_4"];
        this->DataSet->Similarities["module_2"]["module_5"];
        this->DataSet->Similarities["module_2"]["module_6"];

        TEST_ASSERT_EQUALS_DOUBLE(-0.7439788535,    this->DataSet->Similarities["module_1"]["module_2"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(-0.9052136803,    this->DataSet->Similarities["module_1"]["module_3"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.7691866503,    this->DataSet->Similarities["module_1"]["module_4"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(-0.7658445423,    this->DataSet->Similarities["module_1"]["module_5"], 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.9750753757,    this->DataSet->Similarities["module_1"]["module_6"], 1E-6);
    }

    virtual void Test_TCFbEWeightedSum_vbNormalizedValue_abRow() {
        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbECosineSimilarity(), new TCFbEWeightedSum(), 0, false, 0.0, false, 1.0);
        this->DataSet->PredictedValues["module_2"]["BUG"];
        TEST_ASSERT_EQUALS_DOUBLE(0.4655868433,    this->DataSet->PredictedValues["module_1"]["BUG"], 1E-6);

        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbEAdjustedCosineSimilarityWithAverage(), new TCFbEWeightedSum(), 0, false, 0.0, false, 1.0);
        this->DataSet->PredictedValues["module_2"]["BUG"];
        TEST_ASSERT_EQUALS_DOUBLE(0.4193644129,    this->DataSet->PredictedValues["module_1"]["BUG"], 1E-6);

        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbEAdjustedCosineSimilarityWithMedian(), new TCFbEWeightedSum(), 0, false, 0.0, false, 1.0);
        this->DataSet->PredictedValues["module_2"]["BUG"];
        TEST_ASSERT_EQUALS_DOUBLE(0.4441809806,    this->DataSet->PredictedValues["module_1"]["BUG"], 1E-6);

        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbECorrelationCoefficientWithAverage(), new TCFbEWeightedSum(), 0, false, 0.0, false, 1.0);
        this->DataSet->PredictedValues["module_2"]["BUG"];
        TEST_ASSERT_EQUALS_DOUBLE(0.3807384633,    this->DataSet->PredictedValues["module_1"]["BUG"], 1E-6);

        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbECorrelationCoefficientWithMedian(), new TCFbEWeightedSum(), 0, false, 0.0, false, 1.0);
        this->DataSet->PredictedValues["module_2"]["BUG"];
        TEST_ASSERT_EQUALS_DOUBLE(0.6282966972,    this->DataSet->PredictedValues["module_1"]["BUG"], 1E-6);

        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbERankCorrelation(), new TCFbEWeightedSum(), 0, false, 0.0, false, 1.0);
        this->DataSet->PredictedValues["module_2"]["BUG"];
        TEST_ASSERT_EQUALS_DOUBLE(0.3321317612,    this->DataSet->PredictedValues["module_1"]["BUG"], 1E-6);

        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbEDistanceSimilarityWithAverage(), new TCFbEWeightedSum(), 0, false, 0.0, false, 1.0);
        this->DataSet->PredictedValues["module_2"]["BUG"];
        TEST_ASSERT_EQUALS_DOUBLE(0.6910731085,    this->DataSet->PredictedValues["module_1"]["BUG"], 1E-6);

        this->DataSet->PrepareCF(vbNormalizedValue, abRow, new TCFbEDistanceSimilarityWithMedian(), new TCFbEWeightedSum(), 0, false, 0.0, false, 1.0);
        this->DataSet->PredictedValues["module_2"]["BUG"];
        TEST_ASSERT_EQUALS_DOUBLE(0.6735751295,    this->DataSet->PredictedValues["module_1"]["BUG"], 1E-6);
    }

    virtual void Test_TCFbEOutputCash_TCFbEAdjustedCosineSimilarityWithAverage_TCFbEAmplifiedWeightedSumWithMedianOfMultiplier_vbNormalizedValue_abRow() {
        char* argv[] = { "docfbe_test"
            , "-n=normalize"
            , "-ns=0"
            , "-t=BUG"
            , "-l=test\\module1_learn.csv"
            , "-e=test\\module0_1_apply.csv"
            , "-s=AdjustedCosineSimilarityWithAverage"
            , "-p=AmplifiedWeightedSumWithMedianOfMultiplier"
        };

        TCFbECommandLineParser*    Parser = new TCFbECommandLineParser(8, argv);
        TCFbEDataLoader*    DataLoader = new TCFbEDataLoader(Parser);
        TCFbEOutputCash*    Cash = new TCFbEOutputCash(Parser, DataLoader);

        TEST_ASSERT_EQUALS((int)true,    (int)Cash->GetResultEnabled(0, 0));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 1));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 2));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 3));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 4));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 5));

        Cash->GetNeighbor(0, 0);
        Cash->GetNeighbor(0, 1);
        Cash->GetNeighbor(0, 2);
        Cash->GetNeighbor(0, 3);
        Cash->GetNeighbor(0, 4);

        Cash->GetDistribution(0, 0);
        Cash->GetDistribution(0, 1);
        Cash->GetDistribution(0, 2);
        Cash->GetDistribution(0, 3);
        Cash->GetDistribution(0, 4);
        Cash->GetDistribution(0, 5);
        Cash->GetDistribution(0, 6);
        Cash->GetDistribution(0, 7);
        Cash->GetDistribution(0, 8);
        Cash->GetDistribution(0, 9);
        Cash->GetDistribution(0, 10);
        Cash->GetDistribution(0, 11);
        Cash->GetDistribution(0, 12);
        Cash->GetDistribution(0, 13);
        Cash->GetDistribution(0, 14);
        Cash->GetDistribution(0, 15);
        Cash->GetDistribution(0, 16);
        Cash->GetDistribution(0, 17);
        Cash->GetDistribution(0, 18);
        Cash->GetDistribution(0, 19);

        Cash->GetResultValue(0, 0);

        
        TEST_ASSERT_EQUALS((int)true,    (int)Cash->GetResultEnabled(1, 0));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 1));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 2));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 3));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 4));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 5));

        TEST_ASSERT_EQUALS("module_6",    Cash->GetNeighbor(1, 0)->Label.c_str());
        TEST_ASSERT_EQUALS("module_4",    Cash->GetNeighbor(1, 1)->Label.c_str());
        TEST_ASSERT_EQUALS("module_2",    Cash->GetNeighbor(1, 2)->Label.c_str());
        TEST_ASSERT_EQUALS("module_5",    Cash->GetNeighbor(1, 3)->Label.c_str());
        TEST_ASSERT_EQUALS("module_3",    Cash->GetNeighbor(1, 4)->Label.c_str());

        TEST_ASSERT_EQUALS_DOUBLE(0.975075376,    Cash->GetNeighbor(1, 0)->Similarity, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.76918665,    Cash->GetNeighbor(1, 1)->Similarity, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(-0.743978853,    Cash->GetNeighbor(1, 2)->Similarity, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(-0.765844542,    Cash->GetNeighbor(1, 3)->Similarity, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(-0.90521368,    Cash->GetNeighbor(1, 4)->Similarity, 1E-6);

        TEST_ASSERT_EQUALS_DOUBLE(1.0,    Cash->GetNeighbor(1, 0)->SourceValue, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(1.0,    Cash->GetNeighbor(1, 1)->SourceValue, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.0,    Cash->GetNeighbor(1, 2)->SourceValue, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.0,    Cash->GetNeighbor(1, 3)->SourceValue, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(0.0,    Cash->GetNeighbor(1, 4)->SourceValue, 1E-6);

        TEST_ASSERT_EQUALS(1,    Cash->GetDistribution(1, 0));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 1));
        TEST_ASSERT_EQUALS(2,    Cash->GetDistribution(1, 2));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 3));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 4));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 5));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 6));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 7));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 8));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 9));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 10));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 11));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 12));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 13));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 14));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 15));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 16));
        TEST_ASSERT_EQUALS(1,    Cash->GetDistribution(1, 17));
        TEST_ASSERT_EQUALS(0,    Cash->GetDistribution(1, 18));
        TEST_ASSERT_EQUALS(1,    Cash->GetDistribution(1, 19));

        TEST_ASSERT_EQUALS_DOUBLE(0.4202842154,    Cash->GetResultValue(1, 0), 1E-6);

        delete Cash;
        delete DataLoader;
        delete Parser;
    }

    virtual void Test_TCFbEOutputCash_NeighborsValue() {
        char* argv[] = { "docfbe_test"
            , "-n=normalize"
            , "-ns=0"
            , "-t=LOC"
            , "-l=test\\module1_learn.csv"
            , "-e=test\\module0_1_apply.csv"
            , "-s=AdjustedCosineSimilarityWithAverage"
            , "-p=AmplifiedWeightedSumWithMedianOfMultiplier"
        };

        TCFbECommandLineParser*    Parser = new TCFbECommandLineParser(8, argv);
        TCFbEDataLoader*    DataLoader = new TCFbEDataLoader(Parser);
        TCFbEOutputCash*    Cash = new TCFbEOutputCash(Parser, DataLoader);

        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 0));
        TEST_ASSERT_EQUALS((int)true,    (int)Cash->GetResultEnabled(0, 1));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 2));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 3));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 4));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(0, 5));

        Cash->GetNeighbor(0, 0);
        Cash->GetNeighbor(0, 1);
        Cash->GetNeighbor(0, 2);
        Cash->GetNeighbor(0, 3);
        Cash->GetNeighbor(0, 4);

        Cash->GetDistribution(0, 0);
        Cash->GetDistribution(0, 1);
        Cash->GetDistribution(0, 2);
        Cash->GetDistribution(0, 3);
        Cash->GetDistribution(0, 4);
        Cash->GetDistribution(0, 5);
        Cash->GetDistribution(0, 6);
        Cash->GetDistribution(0, 7);
        Cash->GetDistribution(0, 8);
        Cash->GetDistribution(0, 9);
        Cash->GetDistribution(0, 10);
        Cash->GetDistribution(0, 11);
        Cash->GetDistribution(0, 12);
        Cash->GetDistribution(0, 13);
        Cash->GetDistribution(0, 14);
        Cash->GetDistribution(0, 15);
        Cash->GetDistribution(0, 16);
        Cash->GetDistribution(0, 17);
        Cash->GetDistribution(0, 18);
        Cash->GetDistribution(0, 19);

        Cash->GetResultValue(0, 1);

        
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 0));
        TEST_ASSERT_EQUALS((int)true,    (int)Cash->GetResultEnabled(1, 1));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 2));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 3));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 4));
        TEST_ASSERT_EQUALS((int)false,    (int)Cash->GetResultEnabled(1, 5));

        TEST_ASSERT_EQUALS("module_6",    Cash->GetNeighbor(1, 0)->Label.c_str());
        TEST_ASSERT_EQUALS("module_4",    Cash->GetNeighbor(1, 1)->Label.c_str());
        TEST_ASSERT_EQUALS("module_5",    Cash->GetNeighbor(1, 2)->Label.c_str());
        TEST_ASSERT_EQUALS("module_2",    Cash->GetNeighbor(1, 3)->Label.c_str());
        TEST_ASSERT_EQUALS("module_3",    Cash->GetNeighbor(1, 4)->Label.c_str());

        TEST_ASSERT_EQUALS_DOUBLE(900,    Cash->GetNeighbor(1, 0)->SourceValue, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(700,    Cash->GetNeighbor(1, 1)->SourceValue, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(600,    Cash->GetNeighbor(1, 2)->SourceValue, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(250,    Cash->GetNeighbor(1, 3)->SourceValue, 1E-6);
        TEST_ASSERT_EQUALS_DOUBLE(500,    Cash->GetNeighbor(1, 4)->SourceValue, 1E-6);

        delete Cash;
        delete DataLoader;
        delete Parser;
    }

protected:
    TCFbEDataSet* DataSet;
};

//---------------------------------------------------------------------------
#endif