#include "win32ui\winplus.h"
#include "cppdecl\plugcommon.hpp"
#pragma hdrstop
#include "res\ExpCurv.rh"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define  DECLARE_PLUGIN(name)\
class name##Plugin : public IPlugIn\
{\
  virtual char* __stdcall MenuName();\
  virtual Boolean __stdcall CanDo();\
  virtual void __stdcall PluginMain();\
} name##;
  

/* 23.11.99 - расчет значений коэффициента кривизны */
DECLARE_PLUGIN(ExponentCurvature)

char* __stdcall ExponentCurvaturePlugin::MenuName() 
{ 
  return "Кривизна реологической кривой";
}

Boolean __stdcall ExponentCurvaturePlugin::CanDo() 
{ 
  IModel *model;
  if(GetMainServer()->CanDo(acExtremum)) {
    model=GetMainServer()->GetCurrentModel();
    if(model && !strcmp(model->Description(),"Сумма линейной функции и экспоненты")) 
      return 1;
  }
  return 0;
}

class CExpCurvatureDialog : public CDialog
{
  CEdit           eStart,eStop,eSteps;
public:
  CExpCurvatureDialog() : CDialog(IDD_EXPCURVATUREDIALOG,GetForegroundWindow(),GetModuleHandle("ExpCurv.dll")) {}
  virtual LRESULT OnInitDialog(HWND hDlg, HWND hFocus);
  virtual LRESULT OnCommand(HWND hDlg, WPARAM idControl);
};

LRESULT CExpCurvatureDialog::OnInitDialog(HWND hDlg, HWND hFocus)
{
  eSteps.Init(hDlg,IDC_ESTEPS);
  eSteps.SetText("5");
  eStart.Init(hDlg,IDC_ESTART);
  eStart.SetText("-1.0");
  eStop.Init(hDlg,IDC_ESTOP);
  eStop.SetText("1.0");
  utCenterWindow(hDlg);
  return 1;
}

static void PerformExpCurvatureTask(int steps,double start,double stop)
{
  // Основная задача.
  FILE *fout;
  CErrorReport err;
  int i;
  double K,c2,c3,t,e,step;
  IModel *model;
  CFileSaveDialog sfd(GetForegroundWindow(),"Сохранить значения в файл",
    "Текстовые базы данных (*.csv)\0*.csv\0\0");
  sfd.DoModal();
  if(sfd.LastError()) return;
  fout=fopen(sfd.GetName(),"wt");
  if(!fout)
  {
    err.Report("Не удается открыть файл '%s' для записи.",sfd.GetName());
    return;
  }
  step=(stop-start)/steps;
  model=GetMainServer()->GetCurrentModel();
  if(!model) 
  {
    err.Report("Внутренняя ошибка: GetMainServer()->GetModel()==NULL");
    return;
  }
  if(model->RequiredDimension()>1)
  {
    err.Report("Внутренняя ошибка: model->RequiredDimension()>1");
    return;
  }
  
  c2=GetMainServer()->GetCurrentBVector()[1];
  c3=GetMainServer()->GetCurrentBVector()[2];

  for(i=0;i<steps;i++)
  {
    e=c3*exp(start);
    t=c2+e;
    K=e/pow((1+t*t),1.5);
    fprintf(fout,"%g;%g\n",start,K);
    start+=step;
  }
  fclose(fout);
}

LRESULT CExpCurvatureDialog::OnCommand(HWND hDlg, WPARAM idControl)
{
  switch(idControl) 
  {
    case IDC_BOK:
      {
        int steps;
        double start,stop;
        steps=atoi(eSteps.GetText());
        if(steps<3 || steps >100)
        {
          CWarnReport rep;
          rep.Report("В поле 'Делений' должно находится число от 3 до 100.");
          break;
        }
        start=atof(eStart.GetText());
        stop=atof(eStop.GetText());
        if(start>=stop)
        {
          CWarnReport rep;
          rep.Report("Неверный интервал изменения аргумента.");
          break;
        }
        PerformExpCurvatureTask(steps,start,stop);
      }
    case IDC_BCANCEL:
      return CDialog::OnCommand(hDlg,idControl);
  }
  return 1;
}

void __stdcall ExponentCurvaturePlugin::PluginMain() 
{
  CExpCurvatureDialog dlg;
  dlg.DoModal();
}

int __declspec(dllexport) __stdcall PlugInsEnumerate(TEnumPlugInsProc EnumProc)
{
  EnumProc(&ExponentCurvature);
  return 1;
}

// Точка входа
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
  return 1;
}

