/*
    TCFbERecommendationOutputFormatter.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.
*/
//---------------------------------------------------------------------------
#pragma hdrstop

#include "TCFbERecommendationOutputFormatter.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
// コンストラクタ（argc と argv によってコマンドラインを与える
__fastcall TCFbERecommendationOutputFormatter::TCFbERecommendationOutputFormatter(TCFbECommandLineParser* Parser, TCFbEOutputCash* OutputCash, bool IsVerbose)
    : TCFbEOutputFormatter(Parser, OutputCash, IsVerbose)
{
}

//---------------------------------------------------------------------------
__fastcall TCFbERecommendationOutputFormatter::~TCFbERecommendationOutputFormatter()
{
}

//---------------------------------------------------------------------------
// ヘッダ部分を this->FOutputStringList に追加する．ヘッダが必要でない場合はすぐに return する．
void __fastcall TCFbERecommendationOutputFormatter::OutputHeader(void)
{
    // ラベルを出力
    this->FOutputStringList->Add("Label");
    this->FOutputStringList->Add("");
    this->FOutputStringList->Add("Recommended Item's Label,Score");
    this->FOutputStringList->Add("");

    // "値の分布" ラベルの出力
    if (this->Parser->DisplayDistribution) {
        this->FOutputStringList->Add("Distributions of Similarities");
        this->FOutputStringList->Add("");
    }

    // "Neighborのラベル" ラベルの出力
    AnsiString    ALine = "Neighbors'";
    if (this->Parser->DisplayNeighbors) {
        ALine += " Label";
    }

    // "Neighborの類似度" ラベルの出力
    if (this->Parser->DisplaySimilarities) {
        ALine += (ALine != "Neighbors'") ? ",Similarity" : " Similarity";
    }

    // "Neighborの値" ラベルの出力
    if (this->Parser->DisplayValues) {
        ALine += (ALine != "Neighbors'") ? ",Value" : " Value";
    }

    if (ALine != "Neighbors'") {
        this->FOutputStringList->Add(ALine);
        this->FOutputStringList->Add("");
    }

    this->FOutputStringList->Add("");
}

//---------------------------------------------------------------------------
// ボディ部分を this->FOutputStringList に追加する．
void __fastcall TCFbERecommendationOutputFormatter::OutputBody(int TargetRowIndex)
{
    // 行ラベルの出力
    this->FOutputStringList->Add(this->OutputCash->GetResultRowLabel(TargetRowIndex));
    this->FOutputStringList->Add("");

    // 予測結果の値の出力
    TList*    SortedResultList = new TList();
    this->GetSortedResultList(TargetRowIndex, SortedResultList);
    for (int i = 0; i < SortedResultList->Count; i++) {
        TCFbERecommendedItem*    Item = (TCFbERecommendedItem*)SortedResultList->Items[i];
        this->FOutputStringList->Add(Item->Label + "," + FloatToStr(Item->PredictedValue));
    }
    delete SortedResultList;
    this->FOutputStringList->Add("");

    // 類似度の分布の出力
    if (this->Parser->DisplayDistribution) {
        AnsiString    ALine = IntToStr(this->OutputCash->GetDistribution(TargetRowIndex, 19));
        for (int k = 18; k >= 0; k--) {
            ALine += "," + IntToStr(this->OutputCash->GetDistribution(TargetRowIndex, k));
        }
        this->FOutputStringList->Add(ALine);
        this->FOutputStringList->Add("");
    }

    if (this->Parser->DisplayNeighbors || this->Parser->DisplaySimilarities || this->Parser->DisplayValues) {
        for (int k = 0; k < this->OutputCash->GetNumberOfNeighbors(TargetRowIndex); k++) {
            TCFbENeighbor*    Neighbor = this->OutputCash->GetNeighbor(TargetRowIndex, k);

            // Neighborのラベルの出力
            AnsiString    ALine;
            if (this->Parser->DisplayNeighbors) {
                ALine += Neighbor->Label;
            }

            // Neighborの類似度の出力
            if (this->Parser->DisplaySimilarities) {
                if (!ALine.IsEmpty()) {
                    ALine += ",";
                }
                ALine += FloatToStr(Neighbor->Similarity);
            }

            // Neighborの値の出力
            if (this->Parser->DisplayValues) {
                if (!ALine.IsEmpty()) {
                    ALine += ",";
                }
                ALine += FloatToStr(Neighbor->SourceValue);
            }

            this->FOutputStringList->Add(ALine);
        }

        this->FOutputStringList->Add("");
    }

    this->FOutputStringList->Add("");
}

//---------------------------------------------------------------------------
// 以下，protected メソッドの定義
//---------------------------------------------------------------------------
// RowIndex 番目の行の結果をソートし，SortedResultList に入れて返す
void __fastcall TCFbERecommendationOutputFormatter::GetSortedResultList(int RowIndex, TList* SortedResultList)
{
    for (int j = 0; j < this->OutputCash->GetNumberOfColumns(); j++) {
        if (this->OutputCash->GetResultEnabled(RowIndex, j)) {
            TCFbERecommendedItem*    Item = new TCFbERecommendedItem(this->OutputCash->GetResultColumnLabel(j), this->OutputCash->GetResultValue(RowIndex, j));
            SortedResultList->Add(Item);
        }
    }
    SortedResultList->Sort(CompareRecommendedItem);
}

//---------------------------------------------------------------------------

