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

#include <vcl.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <conio.h>
#include <vector>
#pragma hdrstop

#include "Prog_odsp.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TODSP *ODSP;

using namespace std;

__int64 Cislo(__int64 hodnota);

//---------------------------------------------------------------------------
__fastcall TODSP::TODSP(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TODSP::Bt_VypocitejClick(TObject *Sender)
{
  char a[100];

//---------------- ošetření zadání nuly a prázdného řetězce -------------------
__int64 N = 0;

        if (Edit_zadavani->Text != "")
        {
                try
                {
                        N = (__int64)Edit_zadavani->Text.ToInt();           // Zadaný počet N (tj. počet vstupů P nebo výstupů N - spojovací pole je bez koncentrace i expanze
                }
                catch(...){}
        }

   if (N == 0)
   {
        ShowMessage("Chyba!!!   "  "Chybný vstup");
        return;
   }

// tříčlánkové spoj. pole
__int64 g0_min = 0x7FFFFFFFFFFFFFFF;
__int64 res_min = 0x7FFFFFFFFFFFFFFF;
vector<__int64> res_g0;

__int64 SB_min = 0x7FFFFFFFFFFFFFFF;
__int64 g0_min_aaa = 0x7FFFFFFFFFFFFFFF;

// TST
__int64 poc_spin_TST_min = 0x7FFFFFFFFFFFFFFF;
__int64 g0_min_a = 0x7FFFFFFFFFFFFFFF;

// dvoučlánkové spoj. pole
__int64 g0_d_min = 0x7FFFFFFFFFFFFFFF;
__int64 res_d_min = 0x7FFFFFFFFFFFFFFF;
vector<__int64> res_d_g0;
// TT
__int64 poc_spin_TT_min = 0x7FFFFFFFFFFFFFFF;
__int64 g0_min_c = 0x7FFFFFFFFFFFFFFF;

for (__int64 i=1; i<=N; i++)    // zjištění dělitelnosti zadaného čísla N bezezbyku
{
        if(N % i == 0)
        {
                __int64 g0 = i;
                __int64 ga = N / g0;

                // ------ tříčlánkového spoj. pole - počet spínacích bodů -----
                __int64 res = 2*N*(2*g0-1)+((ga*ga)*(2*g0-1));

                // ------ dvoučlánkového spoj. pole - počet spínacích bodů ----
                __int64 res_d = g0*ga*g0*ga+ga*g0*ga*g0;

                // ------------ tříčlánkové spoj. pole TST - počet spínačů ----
                __int64 gb = (g0+g0-1);
                __int64 poc_spin_TST_a = ( (((Cislo(g0))/32)*((Cislo(gb))/32))*ga + ga * ga *((Cislo(gb))/32) + (((Cislo(gb))/32)*((Cislo(g0))/32))*ga );
                // ------------------------------------------------------------

                // ------------ dvoučlánkové spoj. pole TT - počet spínačů ----
                __int64 poc_spin_TT_min_c = ( ((Cislo(g0))/32)*((Cislo(g0))/32)* ga * ga + ((Cislo(g0))/32)*ga*((Cislo(g0))/32)*ga );

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

                // ------ dvoučlánkové spoj. pole TT - počet spínacích bodů ---
                __int64 SB_min_aaa = 2*ga*g0*((2*g0)-1)+((ga*ga)*((2*g0)-1));
                //-------------------------------------------------------------

                res_g0.push_back(g0);
                res_d_g0.push_back(g0);

                if(((__int64)res) < ((__int64)res_min))     // určení minimálního počtu spínacích bodů tříčlánk.
                {
                        res_min = res;
                        g0_min = g0;
                }

                  if(((__int64)poc_spin_TST_a) < ((__int64)poc_spin_TST_min))   // určení minimálního počtu spínačů TST
                {
                        poc_spin_TST_min = poc_spin_TST_a;
                        g0_min_a = g0;
                }

                if(((__int64)poc_spin_TT_min_c) < ((__int64)poc_spin_TT_min))      // určení minimálního počtu spínacích bodů dvoučlánk.
                {
                        poc_spin_TT_min = poc_spin_TT_min_c;
                        g0_min_c = g0;
                }

                 if(((__int64)res_d) < ((__int64)res_d_min))      // určení minimálního počtu spínacích bodů dvoučlánk.
                {
                        res_d_min = res_d;
                        g0_d_min = g0;
                }


                if(((__int64)SB_min_aaa) < ((__int64)SB_min))     // určení minimálního počtu spínacích bodů tříčlánk.
                {
                        SB_min = SB_min_aaa;
                        g0_min_aaa = g0;
                }

        }
}

//-------------------------- výpis do tabulek ---------------------------------
StringGrid_TST->RowCount = res_g0.size() + 1;
StringGrid_STS->RowCount = res_g0.size() + 1;
StringGrid_dvou_TT->RowCount = res_d_g0.size() + 1;
//-----------------------------------------------------------------------------

//******************** TST, STS, T ********************************************

for (unsigned long i = 0; i < res_g0.size(); i++)
{
        __int64 g0 = res_g0[i];
        __int64 ga = N / g0;
        __int64 gbb = (g0+g0-1);


        __int64 SB_norm = 2*N*(2*g0-1)+((ga*ga)*(2*g0-1));

        //-------------------- tříčlánkové spoj. pole TST ---------------------
        // počet spínačů
        __int64 poc_spin_TST = ( (((Cislo(g0))/32)*((Cislo(gbb))/32))*ga + ga * ga *((Cislo(gbb))/32) + (((Cislo(gbb))/32)*((Cislo(g0))/32))*ga );

        // nejmenší počet spínačů / počtům spínacích bodů
        __int64 PS_TST_min = ( (((Cislo(g0_min))/32)*((Cislo(g0_min + g0_min - 1))/32))*(N/g0_min) + (N/g0_min)*(N/g0_min)*((Cislo(g0_min + g0_min -1))/32) + (((Cislo(g0_min + g0_min - 1))/32)*((Cislo(g0_min))/32))*(N/g0_min) );

        // nejmenší počet spínacích bodů / počtům spínačů
        __int64 SB_TST_min = 2*N*(2*g0_min_a-1)+(((N/g0_min_a)*(N/g0_min_a))*(2*g0_min_a-1));

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

        //-------------------- tříčlánkové spoj. pole STS ---------------------
        // počet spínačů
        __int64 poc_spin_STS = ( (((Cislo(g0))/32)*((Cislo(gbb))/32))*ga + ga * ga *((Cislo(gbb))/32) + (((Cislo(gbb))/32)*((Cislo(g0))/32))*ga );

        // nejmenší počet spínačů / počtům spínacích bodů
        __int64 PS_STS_min = ( (((Cislo(g0_min))/32)*((Cislo(g0_min + g0_min - 1))/32))*(N/g0_min) + (N/g0_min)*(N/g0_min)*((Cislo(g0_min + g0_min - 1))/32) + (((Cislo(g0_min + g0_min - 1))/32)*((Cislo(g0_min))/32))*(N/g0_min) );

        // nejmenší počet spínacích bodů / počtům spínačů
        __int64 SB_STS_min = 2*N*(2*g0_min_a-1)+(((N/g0_min_a)*(N/g0_min_a))*(2*g0_min_a-1));

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

        //-------------------- jednočlánkové spoj. pole T ---------------------
        // počet spínacích bodů
        __int64 SB_jed = N*N ;

        // počet spínačů
        __int64 jedn_PS = Cislo(N);

        __int64 PS_jedno = (jedn_PS*jedn_PS)/(32*32);

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

        //**************** zobrazení v tabulkách a jednotlivé výpočty ******************************************

        String s;

        //---------------- pro tříčlánkové spojovací pole TST --------------------------------------------------
        String tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10;   // pomocné proměnné pro výpis

        tmp1 = _ui64toa(g0,a,10); tmp2 = _ui64toa(ga,a,10);

        StringGrid_TST->Cells[0][i+1] = tmp1 + " x " + tmp2;     // výpis do prvního sloupce (g0 x ga)

        StringGrid_TST->Cells[1][i+1] = s.sprintf("%s", _ui64toa(SB_norm,a,10) );    // výpis do druhého sloupce (počet spínacích bodů)

        StringGrid_TST->Cells[2][i+1] = s.sprintf("%s", _ui64toa(poc_spin_TST,a,10) );  // výpis do třetího sloupce (počet spínačů)


        tmp3 = _ui64toa(g0_min,a,10); tmp4 = _ui64toa(N/g0_min,a,10);
        tmp5 = _ui64toa(res_min,a,10); tmp6 = _ui64toa(PS_TST_min,a,10);

        Opt_vel_TST_SB->Caption = "g0=" + tmp3 + " x ga=" + tmp4  + ", SB=" + tmp5 + ", PS=" + tmp6 ;  // výpis optimální velikosti spínacích bodů

        tmp7 = _ui64toa(g0_min_a,a,10); tmp8 = _ui64toa(N/g0_min_a,a,10);
        tmp9 = _ui64toa(poc_spin_TST_min,a,10); tmp10 = _ui64toa(SB_TST_min,a,10);

        Opt_vel_TST_PS->Caption = "g0=" + tmp7 + " x ga=" + tmp8 + ", PS=" + tmp9 + ", SB=" + tmp10 ;    // výpis optimální velikosti počtu spínačů

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

        //---------------- pro tříčlánkové spojovací pole STS ----------------------------------------------------

        String tmp1_1, tmp2_2, tmp3_3, tmp4_4, tmp5_5, tmp6_6, tmp7_7, tmp8_8, tmp9_9, tmp10_10;      // pomocné proměnné pro výpis

        tmp1_1 = _ui64toa(g0,a,10); tmp2_2 = _ui64toa(ga,a,10);

        StringGrid_STS->Cells[0][i+1] = tmp1_1 + " x " + tmp2_2 ;         // výpis do prvního sloupce (g0 x ga)

        StringGrid_STS->Cells[1][i+1] = s.sprintf("%s", _ui64toa(SB_norm,a,10) );        // výpis do druhého sloupce (počet spínacích bodů)

        StringGrid_STS->Cells[2][i+1] = s.sprintf("%s", _ui64toa(poc_spin_STS,a,10));    // výpis do třetího sloupce (počet spínačů)

        tmp3_3 = _ui64toa(g0_min,a,10); tmp4_4 = _ui64toa(N/g0_min,a,10);
        tmp5_5 = _ui64toa(res_min,a,10); tmp6_6 = _ui64toa(PS_STS_min,a,10);

        Opt_vel_STS_SB->Caption = "g0=" + tmp3_3 + " x ga=" + tmp4_4 + ", SB=" + tmp5_5 + ", PS=" + tmp6_6 ;     // výpis optimální velikosti spínacích bodů

        tmp7_7 = _ui64toa(g0_min_a,a,10); tmp8_8 = _ui64toa(N/g0_min_a,a,10);
        tmp9_9 = _ui64toa(poc_spin_TST_min,a,10); tmp10_10 = _ui64toa(SB_STS_min,a,10);

        Opt_vel_STS_PS->Caption = "g0=" + tmp7_7 + " x ga=" + tmp8_8 + ", PS=" + tmp9_9 + ", SB=" + tmp10_10 ;  // výpis optimální velikosti počtu spínačů

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

        //---------------- pro jednočlánkové spojovací pole T ----------------------------------------------------

        String tmpj_1, tmpj_2, tmpj_3, tmpj_4 ;

        tmpj_1 = _ui64toa(N,a,10); tmpj_2 = 1;
        
        StringGrid_jed_T->Cells[0][1] = tmpj_1 + " x " + tmpj_2 ;

        StringGrid_jed_T->Cells[1][i+1] = s.sprintf("%s", _ui64toa(SB_jed,a,10)) ;

        StringGrid_jed_T->Cells[2][i+1] = s.sprintf("%s", _ui64toa(PS_jedno,a,10));

        //--------------------------------------------------------------------------------------------------------
}

//*************************** TT *********************************************************************************

for (__int64 i = 0; i < res_d_g0.size(); i++)
{
        __int64 g0_d = res_d_g0[i];
        __int64 ga_d = N / g0_d;
        __int64 gb_d = ((g0_d+g0_d)-1);

        __int64 SB_dvou = (g0_d*ga_d*g0_d*ga_d + ga_d*g0_d*ga_d*g0_d);

        //-------------------- dvoučlánkové spoj. pole TT ---------------------
        // počet spínačů
        __int64 poc_spin_TT = ( ((Cislo(g0_d))/32)*((Cislo(g0_d))/32)* ga_d * ga_d + ((Cislo(g0_d))/32)*ga_d*((Cislo(g0_d))/32)*ga_d );

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

        //**************** zobrazení v tabulce a jednotlivé výpočty *********
        String sd;

        String tmpd_1, tmpd_2, tmpd_3, tmpd_4, tmpd_5, tmpd_6 ;           // pomocné proměnné pro výpis

        tmpd_1 = _ui64toa(g0_d,a,10); tmpd_2 = _ui64toa(ga_d,a,10);

        StringGrid_dvou_TT->Cells[0][i+1] = tmpd_1 + " x " +  tmpd_2 ;       // výpis do prvního sloupce (g0 x ga)

        StringGrid_dvou_TT->Cells[1][i+1] = sd.sprintf("%s", _ui64toa(SB_dvou,a,10));      // výpis do druhého sloupce (počet spínacích bodů)

        StringGrid_dvou_TT->Cells[2][i+1] = sd.sprintf("%s", _ui64toa(poc_spin_TT,a,10));    // výpis do třetího sloupce (počet spínačů)

        tmpd_3 = _ui64toa(g0_min_c,a,10); tmpd_4 = _ui64toa(N/g0_min_c,a,10);
        tmpd_5 = _ui64toa(res_d_min,a,10); tmpd_6 = _ui64toa(poc_spin_TT_min,a,10);

        Opt_vel_TT->Caption = "g0=" + tmpd_3 + " x ga=" + tmpd_4 + ", SB=" + tmpd_5 + ", PS=" + tmpd_6 ;  // výpis optimální velikosti podle počtu spínačů, protože u dvoučlán. jsou počty spínacích bodů stejné

        //---------------------------------------------------------------------
}

//--------------------- Graf SB -----------------------------------------------

__int64 i,j;
__int64 gjed;
__int64 gdva;
__int64 gtri_t;
__int64 gtri_s;

//------ 1. čl. - T
Series1->FillSampleValues(StringGrid_jed_T->RowCount-1);

        Series1->YValue[0] = StrToInt64(StringGrid_jed_T->Cells[1][1]);
        Series1->XValue[0] = (StringGrid_TST->RowCount-2);
        Series1->XLabel[0] = (StringGrid_jed_T->Cells[0][1]);

//------ 2. čl. - TT
Series3->FillSampleValues(StringGrid_dvou_TT->RowCount-1);
for(gdva=0; gdva<(StringGrid_dvou_TT->RowCount-1); gdva++)
{
        Series3->YValue[gdva] = StrToInt64(StringGrid_dvou_TT->Cells[1][gdva+1]);
        Series3->XValue[gdva] = gdva;
        Series3->XLabel[gdva] = (StringGrid_dvou_TT->Cells[0][gdva+1]);
}

//------ 3. čl. - TST
Series4->FillSampleValues(StringGrid_TST->RowCount-1);
for(gtri_t=0; gtri_t<(StringGrid_TST->RowCount-1); gtri_t++)
{
        Series4->YValue[gtri_t] = StrToInt64(StringGrid_TST->Cells[1][gtri_t+1]);
        Series4->XValue[gtri_t] = gtri_t;
        Series4->XLabel[gtri_t] = (StringGrid_TST->Cells[0][gtri_t+1]);
}

//------ 3. čl. - STS
Series5->FillSampleValues(StringGrid_STS->RowCount-1);
for(gtri_s=0; gtri_s<(StringGrid_STS->RowCount-1); gtri_s++)
{
        Series5->YValue[gtri_s] = StrToInt64(StringGrid_STS->Cells[1][gtri_s+1]);
        Series5->XValue[gtri_s] = gtri_s;
        Series5->XLabel[gtri_s] = (StringGrid_STS->Cells[0][gtri_s+1]);
}

//-----------------------------------------------------------------------------
//--------------------- Graf PS -----------------------------------------------

__int64 gpjed;
__int64 gpdva;
__int64 gptri_t;
__int64 gptri_s;

//------ 1. čl. - T
Series2->FillSampleValues(StringGrid_jed_T->RowCount-1);

        Series2->YValue[0] = StrToInt64(StringGrid_jed_T->Cells[2][1]);
        Series2->XValue[0] = (StringGrid_TST->RowCount-2);
        Series2->XLabel[0] = (StringGrid_jed_T->Cells[0][1]);

//------ 2. čl. - TT
Series6->FillSampleValues(StringGrid_dvou_TT->RowCount-1);
for(gpdva=0; gpdva<(StringGrid_dvou_TT->RowCount-1); gpdva++)
{
        Series6->YValue[gpdva] = StrToInt64(StringGrid_dvou_TT->Cells[2][gpdva+1]);
        Series6->XValue[gpdva] = gpdva;
        Series6->XLabel[gpdva] = (StringGrid_dvou_TT->Cells[0][gpdva+1]);
}

//------ 3. čl. - TST
Series7->FillSampleValues(StringGrid_TST->RowCount-1);
for(gptri_t=0; gptri_t<(StringGrid_TST->RowCount-1); gptri_t++)
{
        Series7->YValue[gptri_t] = StrToInt64(StringGrid_TST->Cells[2][gptri_t+1]);
        Series7->XValue[gptri_t] = gptri_t;
        Series7->XLabel[gptri_t] = (StringGrid_TST->Cells[0][gptri_t+1]);
}

//------ 3. čl. - STS
Series8->FillSampleValues(StringGrid_STS->RowCount-1);
for(gptri_s=0; gptri_s<(StringGrid_STS->RowCount-1); gptri_s++)
{
        Series8->YValue[gptri_s] = StrToInt64(StringGrid_STS->Cells[2][gptri_s+1]);
        Series8->XValue[gptri_s] = gptri_s;
        Series8->XLabel[gptri_s] = (StringGrid_STS->Cells[0][gptri_s+1]);
}
}
//----------------------------------------------------------------------------
//============================================================================
//----------------------------------------------------------------------------

__int64 Cislo(__int64 hodnota)     // násobek 32
{
        __int64 x = (hodnota) / 32;
        if (hodnota % 32 > 0)
                x += 1;
        x = x * 32;
        return x;
}
//-----------------------------------------------------------------------------

void __fastcall TODSP::PozadiEnter(TObject *Sender)
{
      Edit_zadavani->SetFocus();

        // --------------- popis buněk u spojovacích polí ---------------------

        StringGrid_jed_T->Cells[0][0] = "Velikost spoj. pole g0 x ga";
        StringGrid_jed_T->Cells[1][0] = "Počet spínacích bodů";
        StringGrid_jed_T->Cells[2][0] = "Počet spínačů";

        StringGrid_dvou_TT->Cells[0][0] = "Velikost spoj. pole g0 x ga";
        StringGrid_dvou_TT->Cells[1][0] = "Počet spínacích bodů";
        StringGrid_dvou_TT->Cells[2][0] = "Počet spínačů";

        StringGrid_TST->Cells[0][0] = "Velikost spoj. pole g0 x ga";
        StringGrid_TST->Cells[1][0] = "Počet spínacích bodů";
        StringGrid_TST->Cells[2][0] = "Počet spínačů";

        StringGrid_STS->Cells[0][0] = "Velikost spoj. pole g0 x ga";
        StringGrid_STS->Cells[1][0] = "Počet spínacích bodů";
        StringGrid_STS->Cells[2][0] = "Počet spínačů";
}

//----------------------------------------------------------------------------
//============================================================================
// -----------------------Obsluha tlačítka SMAZAT ----------------------------

void __fastcall TODSP::Bt_SmazClick(TObject *Sender)
{
        Edit_zadavani->Clear();
        Edit_zadavani->SetFocus();

        StringGrid_TST->RowCount = 2;
        StringGrid_TST->Cells[0][1] =  "  " ;
        StringGrid_TST->Cells[1][1] =  "  " ;
        StringGrid_TST->Cells[2][1] =  "  " ;
        Opt_vel_TST_SB->Caption = " ";
        Opt_vel_TST_PS->Caption = " ";

        StringGrid_STS->RowCount = 2;
        StringGrid_STS->Cells[0][1] =  "  " ;
        StringGrid_STS->Cells[1][1] =  "  " ;
        StringGrid_STS->Cells[2][1] =  "  " ;
        Opt_vel_STS_SB->Caption = " ";
        Opt_vel_STS_PS->Caption = " ";

        StringGrid_dvou_TT->RowCount = 2;
        StringGrid_dvou_TT->Cells[0][1] =  "  " ;
        StringGrid_dvou_TT->Cells[1][1] =  "  " ;
        StringGrid_dvou_TT->Cells[2][1] =  "  " ;
        Opt_vel_TT->Caption = " ";

        StringGrid_jed_T->RowCount = 2;
        StringGrid_jed_T->Cells[0][1] =  "  " ;
        StringGrid_jed_T->Cells[1][1] =  "  " ;
        StringGrid_jed_T->Cells[2][1] =  "  " ;

        //---- vymazání grafu Chart1 -----
        Series1->Clear();
        Series1->FillSampleValues(1);
        Series1->YValue[0] = 0;
        Series1->XValue[0] = 0;

        Series3->Clear();
        Series3->FillSampleValues(1);
        Series3->YValue[0] = 0;
        Series3->XValue[0] = 0;

        Series4->Clear();
        Series4->FillSampleValues(1);
        Series4->YValue[0] = 0;
        Series4->XValue[0] = 0;

        Series5->Clear();
        Series5->FillSampleValues(1);
        Series5->YValue[0] = 0;
        Series5->XValue[0] = 0;

        //---- vymazání grafu Chart2 -----
        Series2->Clear();
        Series2->FillSampleValues(1);
        Series2->YValue[0] = 0;
        Series2->XValue[0] = 0;

        Series6->Clear();
        Series6->FillSampleValues(1);
        Series6->YValue[0] = 0;
        Series6->XValue[0] = 0;

        Series7->Clear();
        Series7->FillSampleValues(1);
        Series7->YValue[0] = 0;
        Series7->XValue[0] = 0;

        Series8->Clear();
        Series8->FillSampleValues(1);
        Series8->YValue[0] = 0;
        Series8->XValue[0] = 0;
}
//-----------------------------------------------------------------------------
//=============================================================================
//----------------- Omezeni vkládání textu do EDIT ----------------------------
void __fastcall TODSP::Edit_zadavaniKeyPress(TObject *Sender, char &Key)
{
switch (Key)
        {
        case '0' :break;
        case '1' :break;
        case '2' :break;
        case '3' :break;
        case '4' :break;
        case '5' :break;
        case '6' :break;
        case '7' :break;
        case '8' :break;
        case '9' :break;
        case 8 :break;      // povolení backspace
        default:Key=NULL;
        }
}
//---------------------------------------------------------------------------

void __fastcall TODSP::Oprogramu1Click(TObject *Sender)
{
        ShowMessage("Program byl vytvořen jako součást\n"
                    "             diplomové práce \n" "\n"
                    "        Autor: Bc. Marek Mikéska");
}
//---------------------------------------------------------------------------

void __fastcall TODSP::Konec1Click(TObject *Sender)
{
        Close();
}
//---------------------------------------------------------------------------





