/*
    TCFbEPrimitiveTable.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 "TCFbEPrimitiveTable.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
// コンストラクタ（空のテーブルを作成
__fastcall TCFbEPrimitiveTable::TCFbEPrimitiveTable(void)
{
    this->FRowLabelList = new TStringList();
    this->FColumnLabelList = new TStringList();
    this->RowList = new TObjectList();
}

//---------------------------------------------------------------------------
// 指定された行列を備えた空テーブルを作成
__fastcall TCFbEPrimitiveTable::TCFbEPrimitiveTable(TStringList* RowLabelList, TStringList* ColumnLabelList)
{
    this->FRowLabelList = new TStringList();
    this->FColumnLabelList = new TStringList();
    this->RowList = new TObjectList();

    for (int j = 0; j < ColumnLabelList->Count; j++) {
        TCFbEPrimitiveTable::AddColumn(ColumnLabelList->Strings[j]);
    }

    for (int i = 0; i < RowLabelList->Count; i++) {
        TCFbEPrimitiveTable::AddRow(RowLabelList->Strings[i]);
    }
}

//---------------------------------------------------------------------------
// デストラクタ
__fastcall TCFbEPrimitiveTable::~TCFbEPrimitiveTable()
{
    delete this->RowList;
    delete this->FColumnLabelList;
    delete this->FRowLabelList;
}

//---------------------------------------------------------------------------
// 行を追加する．
// 行が既に存在する場合は例外を送出する．
// 追加した行の添字を返す
int __fastcall TCFbEPrimitiveTable::AddRow(AnsiString RowLabel)
{
    if (this->FRowLabelList->IndexOf(RowLabel) >= 0) {
        throw Exception("The row named \"" + RowLabel + "\" was already existing.");
    }

    TObjectList* AddedRow = new TObjectList();
    for (int j = 0; j < this->GetNumberOfColumns() ; j++) {
        AddedRow->Add(new TCFbECell());
    }
    this->RowList->Add(AddedRow);

    return this->FRowLabelList->Add(RowLabel);
}

//---------------------------------------------------------------------------
// 列を追加する．
// 列が既に存在する場合は例外を送出する．
// 追加した列の添字を返す．
int __fastcall TCFbEPrimitiveTable::AddColumn(AnsiString ColumnLabel)
{
    if (this->FColumnLabelList->IndexOf(ColumnLabel) >= 0) {
        throw Exception("The column named \"" + ColumnLabel + "\" was already existing.");
    }

    for (int i = 0; i < this->GetNumberOfRows() ; i++) {
        ((TObjectList*)this->RowList->Items[i])->Add(new TCFbECell());
    }

    return this->FColumnLabelList->Add(ColumnLabel);
}                                   

//---------------------------------------------------------------------------
// SourceTable の各要素をコピーする
void __fastcall TCFbEPrimitiveTable::Assign(TCFbEPrimitiveTable* SourceTable)
{
    // SourceTable の列要素をコピー
    for (int j = 0; j < SourceTable->GetNumberOfColumns(); j++) {
        if (this->GetNumberOfColumns() <= j) {
            this->AddColumn(SourceTable->FColumnLabelList->Strings[j]);
        } else {
            this->FColumnLabelList->Strings[j] = SourceTable->FColumnLabelList->Strings[j];
        }
    }

    // 余分な列要素を削除
    while (this->GetNumberOfColumns() > SourceTable->GetNumberOfColumns()) {
        this->DeleteColumn(this->FColumnLabelList->Strings[this->GetNumberOfColumns() - 1]);
    }

    // SourceTable の行要素をコピー
    for (int i = 0; i < SourceTable->GetNumberOfRows(); i++) {
        if (this->GetNumberOfRows() <= i) {
            this->AddRow(SourceTable->FRowLabelList->Strings[i]);
        } else {
            this->FRowLabelList->Strings[i] = SourceTable->FRowLabelList->Strings[i];
        }
    }

    // 余分な行要素を削除
    while (this->GetNumberOfRows() > SourceTable->GetNumberOfRows()) {
        this->DeleteRow(this->FRowLabelList->Strings[this->GetNumberOfRows() - 1]);
    }

    // 行列要素の値を全てコピー
    for (int i = 0; i < this->GetNumberOfRows(); i++) {
        for (int j = 0; j < this->GetNumberOfColumns(); j++) {
            this->GetCellByIndex(i, j)->Assign(SourceTable->GetCellByIndex(i, j));
        }
    }
}

//---------------------------------------------------------------------------
// SourceTable の各要素の行と列を入替えてコピーする
void __fastcall TCFbEPrimitiveTable::AssignWithTurn(TCFbEPrimitiveTable* SourceTable) {
    // SourceTable の行要素を列要素としてコピー
    for (int i = 0; i < SourceTable->GetNumberOfRows(); i++) {
        if (this->GetNumberOfColumns() <= i) {
            this->AddColumn(SourceTable->FRowLabelList->Strings[i]);
        } else {
            this->FColumnLabelList->Strings[i] = SourceTable->FRowLabelList->Strings[i];
        }
    }

    // 余分な列要素を削除
    while (this->GetNumberOfColumns() > SourceTable->GetNumberOfRows()) {
        this->DeleteColumn(this->FColumnLabelList->Strings[this->GetNumberOfColumns() - 1]);
    }

    // SourceTable の列要素を行要素としてコピー
    for (int j = 0; j < SourceTable->GetNumberOfColumns(); j++) {
        if (this->GetNumberOfRows() <= j) {
            this->AddRow(SourceTable->FColumnLabelList->Strings[j]);
        } else {
            this->FRowLabelList->Strings[j] = SourceTable->FColumnLabelList->Strings[j];
        }

        for (int i = 0; i < this->GetNumberOfColumns(); i++) {
            this->GetCellByIndex(j, i)->Assign(SourceTable->GetCellByIndex(i, j));
        }
    }

    // 余分な列要素を削除
    while (this->GetNumberOfRows() > SourceTable->GetNumberOfColumns()) {
        this->DeleteRow(this->FRowLabelList->Strings[this->GetNumberOfRows() - 1]);
    }
}

//---------------------------------------------------------------------------
// SourceTable の SourceRowIndex 行目をコピーする
int __fastcall TCFbEPrimitiveTable::CopyRowFrom(TCFbEPrimitiveTable* SourceTable, int SourceRowIndex, bool AddColumn)
{
    int UpdatedIndex = this->FRowLabelList->IndexOf(SourceTable->FRowLabelList->Strings[SourceRowIndex]);
    if (UpdatedIndex < 0) {    // 行が存在しない
        UpdatedIndex = this->AddRow(SourceTable->FRowLabelList->Strings[SourceRowIndex]);
    }
    for (int j = 0; j < SourceTable->GetNumberOfColumns(); j++) {
        int    TargetColumn = this->FColumnLabelList->IndexOf(SourceTable->FColumnLabelList->Strings[j]);
        if (TargetColumn < 0) {
            if (!AddColumn) {   // 列を追加しない
                continue;
            }
            TargetColumn = this->AddColumn(SourceTable->FColumnLabelList->Strings[j]);
        }
        TCFbECell*  SourceCell = SourceTable->GetCellByIndex(SourceRowIndex, j);
        if (SourceCell->GetEnabled()) {
            this->SetValueByIndex(UpdatedIndex, TargetColumn, SourceCell->GetValue());
        } else {
            this->SetEnabledByIndex(UpdatedIndex, TargetColumn, false);
        }
    }

    return UpdatedIndex;
}

//---------------------------------------------------------------------------
// SourceTable の SourceRowIndex 行目を列としてコピーする
int __fastcall TCFbEPrimitiveTable::CopyRowAsColumnFrom(TCFbEPrimitiveTable* SourceTable, int SourceRowIndex, bool AddRow)
{
    int UpdatedIndex = this->FColumnLabelList->IndexOf(SourceTable->FRowLabelList->Strings[SourceRowIndex]);
    if (UpdatedIndex < 0) {    // 行が存在しない
        UpdatedIndex = this->AddColumn(SourceTable->FRowLabelList->Strings[SourceRowIndex]);
    }
    for (int j = 0; j < SourceTable->GetNumberOfColumns(); j++) {
        int    TargetRow = this->FRowLabelList->IndexOf(SourceTable->FColumnLabelList->Strings[j]);
        if (TargetRow < 0) {
            if (!AddRow) {   // 列を追加しない
                continue;
            }
            TargetRow = this->AddRow(SourceTable->FColumnLabelList->Strings[j]);
        }
        TCFbECell*  SourceCell = SourceTable->GetCellByIndex(SourceRowIndex, j);
        if (SourceCell->GetEnabled()) {
            this->SetValueByIndex(TargetRow, UpdatedIndex, SourceCell->GetValue());
        } else {
            this->SetEnabledByIndex(TargetRow, UpdatedIndex, false);
        }
    }

    return UpdatedIndex;
}

//---------------------------------------------------------------------------
// SourceTable の SourceColumnIndex 列目をコピーする
int __fastcall TCFbEPrimitiveTable::CopyColumnFrom(TCFbEPrimitiveTable* SourceTable, int SourceColumnIndex, bool AddRow)
{
    int UpdatedIndex = this->FColumnLabelList->IndexOf(SourceTable->FColumnLabelList->Strings[SourceColumnIndex]);
    if (UpdatedIndex < 0) {    // 列目が存在しない
        UpdatedIndex = this->AddColumn(SourceTable->FColumnLabelList->Strings[SourceColumnIndex]);
    }
    for (int i = 0; i < SourceTable->GetNumberOfRows(); i++) {
        int    TargetRow = this->FRowLabelList->IndexOf(SourceTable->FRowLabelList->Strings[i]);
        if (TargetRow < 0) {
            if (!AddRow) {   // 列を追加しない
                continue;
            }
            TargetRow = this->AddRow(SourceTable->FRowLabelList->Strings[i]);
        }
        TCFbECell*  SourceCell = SourceTable->GetCellByIndex(i, SourceColumnIndex);
        if (SourceCell->GetEnabled()) {
            this->SetValueByIndex(TargetRow, UpdatedIndex, SourceCell->GetValue());
        } else {
            this->SetEnabledByIndex(TargetRow, UpdatedIndex, false);
        }
    }

    return UpdatedIndex;
}

//---------------------------------------------------------------------------
// SourceTable の SourceColumnIndex 列目を列としてコピーする
int __fastcall TCFbEPrimitiveTable::CopyColumnAsRowFrom(TCFbEPrimitiveTable* SourceTable, int SourceColumnIndex, bool AddColumn)
{
    int UpdatedIndex = this->FRowLabelList->IndexOf(SourceTable->FColumnLabelList->Strings[SourceColumnIndex]);
    if (UpdatedIndex < 0) {    // 列目が存在しない
        UpdatedIndex = this->AddRow(SourceTable->FColumnLabelList->Strings[SourceColumnIndex]);
    }
    for (int i = 0; i < SourceTable->GetNumberOfRows(); i++) {
        int    TargetColumn = this->FColumnLabelList->IndexOf(SourceTable->FRowLabelList->Strings[i]);
        if (TargetColumn < 0) {
            if (!AddColumn) {   // 列を追加しない
                continue;
            }
            TargetColumn = this->AddColumn(SourceTable->FRowLabelList->Strings[i]);
        }
        TCFbECell*  SourceCell = SourceTable->GetCellByIndex(i, SourceColumnIndex);
        if (SourceCell->GetEnabled()) {
            this->SetValueByIndex(UpdatedIndex, TargetColumn, SourceCell->GetValue());
        } else {
            this->SetEnabledByIndex(UpdatedIndex, TargetColumn, false);
        }
    }

    return UpdatedIndex;
}

//---------------------------------------------------------------------------
// 列で Enabled なセルの数を返す
int    __fastcall TCFbEPrimitiveTable::GetEnabledCountOfRow(int i)
{
    int    Count = 0;
    for (int j = 0; j < this->GetNumberOfColumns(); j++) {
        if (((TCFbECell*)this->GetCellByIndex(i, j))->GetEnabled()) {
            Count++;
        }
    }
    return    Count;
}

//---------------------------------------------------------------------------
// 列で Enabled なセルの数を返す
int    __fastcall TCFbEPrimitiveTable::GetEnabledCountOfColumn(int j)
{
    int    Count = 0;
    for (int i = 0; i < this->GetNumberOfRows(); i++) {
        if (((TCFbECell*)this->GetCellByIndex(i, j))->GetEnabled()) {
            Count++;
        }
    }
    return    Count;
}

//---------------------------------------------------------------------------
// TargetRowIndex 行目と ComparedRowIndex 行目で共通して Enabled な要素をソートし，TargetSortedCellList と　ComparedSortedCellList にそれぞれ入れて返す（RankCorrelation で使われる
void __fastcall TCFbEPrimitiveTable::GetBothEnableSortedCellList(int TargetRowIndex, int ComparedRowIndex, TList* TargetSortedCellList, TList* ComparedSortedCellList)
{
    TargetSortedCellList->Clear();
    ComparedSortedCellList->Clear();
    for (int j = 0; j < this->GetNumberOfColumns(); j++) {
        TCFbECell* TargetCell = this->GetCellByIndex(TargetRowIndex, j);
        TCFbECell* ComparedCell = this->GetCellByIndex(ComparedRowIndex, j);
        if (TargetCell->GetEnabled() && ComparedCell->GetEnabled()) {
            TargetSortedCellList->Add(TargetCell);
            ComparedSortedCellList->Add(ComparedCell);
        }
    }
    TargetSortedCellList->Sort(CompareCell);
    ComparedSortedCellList->Sort(CompareCell);
}

//---------------------------------------------------------------------------
// 以下，protected method
//---------------------------------------------------------------------------
// RowIndex 番目の行の Enabled な要素を DynArray に入れて返す
void __fastcall TCFbEPrimitiveTable::GetEnabledCellsInRow(int RowIndex, TDoubleDynArray& DynArray)
{
    for (int j = 0; j < this->GetNumberOfColumns(); j++) {
        TCFbECell* CurrentCell = this->GetCellByIndex(RowIndex, j);
        if (CurrentCell->GetEnabled()) {
            DynArray.Length++;
            DynArray[DynArray.High] = CurrentCell->GetValue();
        }
    }
}

//---------------------------------------------------------------------------
// ColumnIndex 番目の列の Enabled な要素を DynArray に入れて返す
void __fastcall TCFbEPrimitiveTable::GetEnabledCellsInColumn(int ColumnIndex, TDoubleDynArray& DynArray)
{
    for (int i = 0; i < this->GetNumberOfRows(); i++) {
        TCFbECell* CurrentCell = this->GetCellByIndex(i, ColumnIndex);
        if (CurrentCell->GetEnabled()) {
            DynArray.Length++;
            DynArray[DynArray.High] = CurrentCell->GetValue();
        }
    }
}

//---------------------------------------------------------------------------
// RowIndex 番目の列の Enabled な要素をソートし，SortedCellList に入れて返す
void __fastcall TCFbEPrimitiveTable::GetSortedCellListOfRow(int RowIndex, TList* SortedCellList)
{
    SortedCellList->Clear();
    for (int j = 0; j < this->GetNumberOfColumns(); j++) {
        TCFbECell* CurrentCell = this->GetCellByIndex(RowIndex, j);
        if (CurrentCell->GetEnabled()) {
            SortedCellList->Add(CurrentCell);
        }
    }
    SortedCellList->Sort(CompareCell);
}

//---------------------------------------------------------------------------
// ColumnIndex 番目の列の Enabled な要素をソートし，SortedCellList に入れて返す
void __fastcall TCFbEPrimitiveTable::GetSortedCellListOfColumn(int ColumnIndex, TList* SortedCellList)
{
    SortedCellList->Clear();
    for (int i = 0; i < this->GetNumberOfRows(); i++) {
        TCFbECell* CurrentCell = this->GetCellByIndex(i, ColumnIndex);
        if (CurrentCell->GetEnabled()) {
            SortedCellList->Add(CurrentCell);
        }
    }
    SortedCellList->Sort(CompareCell);
}

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

