// Головная часть программы, реализующей метод деформируемого многогранника
// (ввод-вывод и интерфейс пользователя). Содержимое файла simp.c
//
// (c) Boland 1994

#include "menues.h"
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <string.h>

int errorlevel,pr[100],org[100],itflag=0,resflag=0,funflag=0,itern,fcalls,nfun;
float x0[10],xn[10],iters[100][10],fmin,epsilon;
char filename[10],funst[80]="\0";
FILE *flpt;
#include "stack.c"
#include "compl.c"
#include "calc.c"
#include "minim.c"

char ers[9][50]={"",
                 "СТЕК ПОЛОH",
                 "ЧТЕHИЕ ИЗ ПУСТОГО СТЕКА",
                 "ДЕЛЕHИЕ HА HОЛЬ",
                 "ВЫЧИСЛЕHИЕ 0^0",
                 "КВАДРАТHЫЙ КОРЕHЬ ИЗ ОТРИЦАТЕЛЬHОГО ЧИСЛА",
                 "ЛОГАРИФМ HЕПОЛОЖИТЕЛЬHОГО ЧИСЛА",
                 "HЕКОРРЕКТHОЕ ВЫРАЖЕHИЕ",
                 "ПЕРЕПОЛHЕHИЕ ПАМЯТИ ИТЕРАЦИЙ"};

menuoptions  mmenu={"Помощь",
                    "Выдача итераций: выкл",
                    "Вывод: экран",
                    "Ввод функции",
                    "Минимизация",
                    "Результаты",
                    "Выход"};
menuhotkeys mhotkeys={'g','b','d','a','v','h','l'};
menuhindexes hi={0,7,0,5,0,0,4};
menustrings a={"                     Информация о программе",
               "      Управление выдачей/невыдачей данных обо всех итерациях",
               "               Задание файла вывода результатов",
               "                Задание минимизируемой функции",
               "     Выполнение расчетов по методу деформируемого многогранника",
	       "          Просмотр результатов, полученных при расчетах",
               "                     Завершение работы"};

void helpmode()
{
  scrinit(WHITE,BLACK);
  window(2,2,79,23);
  setink(LIGHTMAGENTA); setpaper(BLACK);
  cprintf("                   Помощь по режимам работы\r\n\n"); 
  setink(LIGHTGREEN);
  cprintf("  Запуск пpогpаммы:\n\r");
  cprintf("  simp [/? | [/f]  [/i:имя]  [/o:имя] [/iter] ]\n\n\r");
  cprintf(" /?      Вызов данной стpаницы помощи.\n\n\r");
  cprintf(" /f      Запуск пpогpаммы в pежиме обpаботки файла. Указанные ниже опции\n\r");
  cprintf("         оказывают действие только если указан этот ключ\n\n\r");
  cprintf(" /i:имя  Задание имени обpабатываемого файла.\n\n\r");
  cprintf(" /o:имя  Задание имени файла pезультатов.\n\n\r");
  cprintf(" /iter   Указывает, что в файл pезультатов необходимо включить данные\n\r");
  cprintf("         обо всех итеpациях.\n\n\r");
  cprintf("  Если пpи вызове не указаны ключи /? или /f, то пpогpамма будет pаботать\n\r");
  cprintf("  в диалоговом pежиме.\n\r");
  window(1,1,80,25); gotoxy(80,25);
  pausing();
  scrinit(LIGHTGREEN,CYAN);
  return;
}

void helpperform()
{
  scrinit(WHITE,BLACK);
  window(2,2,79,23);
  setink(LIGHTMAGENTA); setpaper(BLACK);
  cprintf("                   Помощь по режиму обработки файла\r\n\n\n\n\n\n"); setink(LIGHTGREEN);
  cprintf("   Исходный файл должен содержать:\r\n\n");
  cprintf("   1. Минимизируемую функцию ( переменные х0...х9; скобки (); +,-,*,/,^;\r\n");
  cprintf("      функции sqr,abs,exp,ln,sin,cos,tg. Вместо унарного минуса необходимо\r\n");
  cprintf("      явно указывать ноль: 0- ).\r\n\n");
  cprintf("   2. Начальные значения для используемых переменных в порядке возрастания\r\n");
  cprintf("      индексов.\r\n\n");
  cprintf("   3. Точность.\r\n"); window(1,1,80,25); gotoxy(80,25);
  pausing();
  scrinit(LIGHTGREEN,CYAN);
  return;
}

void helpdialog()
{
  scrinit(WHITE,BLACK);
  window(2,2,79,23);
  setink(LIGHTMAGENTA); setpaper(BLACK);
  cprintf("                   Помощь по диалоговому pежиму.\r\n\n"); setink(LIGHTGREEN);
  cprintf("       Пpогpамма pеализует один из методов минимизации функций несколоьких\r\n");
  cprintf("  пеpеменных, а именно метод дефоpмиpуемого многогpанника.\r\n");
  cprintf("       Имеется встpоенный интеpпpетатоp функций, благодаpя чему пеpекомпиляция\r");
  cprintf("  пpогpаммы не нужна.\r\n\n");
  cprintf("       Для выполнения pасчетов Вам необходимо:\r\n");
  cprintf("    1) Задать минимизиpуемую функцию (опция \"ВВОД ФУHКЦИИ\").\r\n");
  cprintf("       Можно использовать пеpеменные х0..х9; действия -,+,*,/,^;\r\n");
  cprintf("       скобки (); функции sqr,abs,exp,ln,sin,cos,tg.\r\n");
  cprintf("       Внимание: унаpный минус отсутствует, вместо -а используйте 0-а.\r\n");
  cprintf("    2) Если Вам нужна выдача всех итеpаций, установите данный pежим\r\n");
  cprintf("       опцией \"ВЫДАЧА ИТЕРАЦИЙ\".\r\n");
  cprintf("    3) Если Вы хотите сохpанить pезультаты в файле, используйте опцию \"ВЫВОД\".\r");
  cprintf("    4) Выбеpите опцию \"МИHИМИЗАЦИЯ\".\r\n");
  cprintf("    5) С pезультаттом (если не пpоизошло ошибок) Вы можете познакомиться,\r\n");
  cprintf("       выбpав опцию \"РЕЗУЛЬТАТЫ\".\r\n\n");
  cprintf("  Для выбоpа опций используйте клавиши со стpелками и ENTER либо клавиши\r\n");
  cprintf("  c подсвеченными символами.");
  window(1,1,80,25); gotoxy(80,25);
  pausing();
  scrinit(LIGHTGREEN,CYAN);
  return;
}

void helper()
{
  menuoptions hmopt={"Режимы работы",
                     "Режим обработки файла",
                     "Диалоговый режим",
                     "Выход             Esc"};
  menuhindexes hmind={0,6,0,0};
  menuhotkeys hmhkys={'h','j','l','d'};
  int o=0;
  cinit(BLUE,WHITE,LIGHTGRAY,BLUE);
  scrinit(LIGHTGREEN,CYAN);
  do
  {
    vertmenu(27,10,4,hmopt,hmhkys,hmind,0,23,&o);
    switch (o)
    {
      case -1:
      case 3:   scrinit(LIGHTGREEN,CYAN); break;
      case -2:  o=0; break;
      case -3:  o=2; break;
      case 1:   helpperform(); break;
      case 0:   helpmode(); break;
      case 2:   helpdialog(); break;
      default:  ;
    }
  } while ((o!=-1)&&(o!=3));
  cinit(BLUE,YELLOW,GREEN,BLACK);
  return;
}

void setiter()
{
	itflag=1-itflag;
	if (itflag)
			strcpy(&mmenu[1][17],"вкл ");
		else	strcpy(&mmenu[1][17],"выкл");
	return;
}

void setfile()
{
  char keeper[2000];
  setpaper(MAGENTA); setink(LIGHTRED);
  gettext(10,10,59,13,keeper);
  hidebox(10,10,50,4);
  printframe(10,10,50,4);
  gotoxy(11,11); setink(WHITE);
  cprintf("Введите имя файла (no - не выводить в файл):");
  gotoxy(11,12); window(11,12,28,12);
  cscanf("%s",filename);
  window(1,1,80,25);
  puttext(10,10,59,13,keeper);
  if (!getch()) getch();
  inverse(0);
  if(!strcmp("no",filename)) strcpy(&mmenu[2][7],"экран");
    else strncpy(&mmenu[2][7],filename,12);
  return;
}

extern void mheader(void);

void outrezult()
{
  int i,j,k;
  if (!resflag)
  {
     bewaring(10,10," Не была произведена минимизация. Результатов нет. ");
     return;
  }
  clrscr();
  printframe(1,1,80,24); setink(WHITE);

  gotoxy(2,2); cprintf("   Функция: %s",funst);
  gotoxy(2,3); cprintf("   Начальное приближение: ( ");
  for(i=0;i<nfun;i++) cprintf("%5.2f ",x0[i]); cprintf(")");
  gotoxy(2,4); cprintf("   Точность: %f",epsilon);
  gotoxy(2,6); cprintf(" Всего итераций: %d",itern);
  gotoxy(2,7); cprintf(" Всего вычислений функции: %d",fcalls);

  pausing();

  if(itflag)
    {
      k=0;
      window(5,10,74,22); gotoxy(1,1);
      for(i=0;i<itern;i++)
      {
	if(k==0)
	{
	  clrscr();
	  gotoxy(1,1); cprintf("∙──");
	  for(j=0;j<nfun;j++) cprintf("∙─────");
	  cprintf("∙\r\n");
	}
	k++;
	 cprintf("│%2u",i);
	for(j=0;j<nfun;j++) cprintf("│%5.2f",iters[i][j]);
	cprintf("│\r\n");
	if(k==10)
	{
	  cprintf("∙──");
	  for(j=0;j<nfun;j++) cprintf("∙─────");
	  cprintf("∙\r\n"); pausing(); k=0;
	}
      }
    }
    if(k&&itflag)
    {
      cprintf("∙──");
      for(j=0;j<nfun;j++) cprintf("∙─────");
      cprintf("∙\r\n"); pausing(); clrscr();
    }
    window(1,1,80,25);
    gotoxy(2,13); cprintf("Результат:");
    gotoxy(3,14);cprintf("Точка ( ");
    for(j=0;j<nfun;j++) cprintf("%5.2f, ",iters[itern-1][j]); cprintf(")\r\n");
    pausing();

  scrinit(LIGHTGREEN,CYAN); mheader();
  cinit(BLUE,YELLOW,GREEN,BLACK);
  return;
}

void setfunction()
{
  char keeper[2000];
  setpaper(BROWN); setink(LIGHTRED);
  gettext(10,10,59,13,keeper);
  hidebox(10,10,50,4);
  printframe(10,10,50,4);
  gotoxy(11,11); setink(WHITE);
  cprintf("Введите функцию:");
  gotoxy(11,12); window(11,12,58,12);
  cscanf("%s",funst);
  window(1,1,80,25);
  puttext(10,10,59,13,keeper);
  compil(funst);
  if(errorlevel)
      bewaring(10,10,ers[errorlevel]);
    else
      {
	int i,qw[10]={0,0,0,0,0,0,0,0,0,0};
	funflag=1;
	for(i=0;pr[i]!=99;i++)
	  if((pr[i]>=0)&&(pr[i]<10)) qw[pr[i]]=1;
	for(i=nfun=0;i<10;i++) nfun+=qw[i];
      }
  if (!getch()) getch();
  inverse(0);
  return;
}

void minimize(int ifl)
{
   int i,j,k;
   char keeper[2000];
   if(ifl)
   {
   if(!funflag)
     { bewaring(10,10,"НЕ БЫЛА ВВЕДЕНА ФУНКЦИЯ !!!"); return; }

   setpaper(BLACK); setink(LIGHTRED);
   gettext(10,10,59,12,keeper);
   hidebox(10,10,50,3);
   printframe(10,10,50,3);
   gotoxy(11,11); setink(WHITE);
   cprintf("Введите точность:");
   window(11,11,58,11); gotoxy(20,1);
   cscanf("%f",&epsilon);
   window(1,1,80,25);
   puttext(10,10,59,12,keeper);
   if (!getch()) getch();
   inverse(0);
   gettext(10,10,59,12+nfun,keeper);
   setpaper(BLACK); setink(LIGHTRED);
   hidebox(10,10,50,3+nfun);
   printframe(10,10,50,3+nfun);
   gotoxy(11,11); setink(WHITE);
   cprintf("Введите точку начального приближения:");
   for(i=0;i<nfun;i++)
     {
	gotoxy(11,12+i);
	cprintf("x0<%1d>=",i);
     }
   for(i=0;i<nfun;i++)
     {
       gotoxy(18,12+i);
       cscanf("%f",&x0[i]);
     }
   window(1,1,80,25);

   }
   nelder(x0,epsilon,xn,&fmin,nfun);
   if(!errorlevel)
       {
	 bewaring(10,10,"Минимизация прошла.");
	 resflag=1;
	 if(strcmp(filename,"no"))
	     {
	       flpt=fopen(filename,"a");
	       fprintf(flpt,"   Функция: %s\n",funst);
	       fprintf(flpt,"   Начальное приближение: ( ");
	       for(i=0;i<nfun;i++) fprintf(flpt,"%5.2f ",x0[i]); fprintf(flpt,")\n");
	       fprintf(flpt,"   Точность: %f\n",epsilon);
	       fprintf(flpt," Всего итераций: %d\n",itern);
	       fprintf(flpt," Всего вычислений функции: %d\n\n",fcalls);

	       if(itflag)
		   {
		     k=0;
		     for(i=0;i<itern;i++)
		     {
		       if(k==0)
			 {
			   fprintf(flpt,"∙──");
			   for(j=0;j<nfun;j++) fprintf(flpt,"∙─────");
			   fprintf(flpt,"∙\n");
			 }
			k++;
			fprintf(flpt,"│%2u",i);
			for(j=0;j<nfun;j++) fprintf(flpt,"│%5.2f",iters[i][j]);
			fprintf(flpt,"│\n");
			if(k==10)
			  {
			    fprintf(flpt,"∙──");
			    for(j=0;j<nfun;j++) fprintf(flpt,"∙─────");
			    fprintf(flpt,"∙\n"); k=0;
			  }
		     }
		   }
	       if(k&&itflag)
		   {
		     fprintf(flpt,"∙──");
		     for(j=0;j<nfun;j++) fprintf(flpt,"∙─────");
		     fprintf(flpt,"∙\n");
		   }
	       fprintf(flpt,"Результат: ");
	       fprintf(flpt,"Точка ( ");
	       for(j=0;j<nfun;j++) fprintf(flpt,"%5.2f, ",iters[itern-1][j]);
	       fprintf(flpt,")\n");
	       fclose(flpt);
	     }
       }
     else
       { bewaring(10,10,ers[errorlevel]); resflag=0; }
   puttext(10,10,59,12+nfun,keeper);

   return;
}

void mheader()
{
	char s1[]="* Метод деформируемого многогранника *";
	char s2[]="1994 Майк Баландин";
	int l1,l2;
	setink(BLACK); setpaper(CYAN);
	l1=strlen(s1);
	l2=strlen(s2);
	gotoxy((80-l1)/2,2); cprintf(s1);
	gotoxy((80-l2)/2,4); cprintf(s2);
	gotoxy(80,25); inverse(0);
	return;
}

void main(int arn,char *arv[])
{
	int i,q=0,help=0,perf=0;
	char ifnm[80]={""};
	for(i=1;i<arn;i++)
	{
	  if (!strncmp(arv[i],"/?",2)) help=1;
	  if (!strncmp(arv[i],"/f",2)) perf=1;
	  if (!strncmp(arv[i],"/i:",3)) strcpy(ifnm,arv[i]+3);
	  if (!strncmp(arv[i],"/o:",3)) strcpy(filename,arv[i]+3);
	  if (!strncmp(arv[i],"/iter",5)) itflag=1;
	}
	if(help)
	    {
	      helpmode();
	      helpperform();
	      setink(LIGHTGRAY); setpaper(BLACK);
	      clrscr(); return;
	    }
	if(perf)
	    {
	      flpt=fopen(ifnm,"r");
	      fscanf(flpt,"%s",funst);
	      compil(funst);
	      if(errorlevel)
		   {
		     bewaring(10,10,ers[errorlevel]);
		     fclose(flpt);
		     return;
		   }
		 else
		   {
		     int i,qw[10]={0,0,0,0,0,0,0,0,0,0};
		     for(i=0;pr[i]!=99;i++)
		     if((pr[i]>=0)&&(pr[i]<10)) qw[pr[i]]=1;
		     for(i=nfun=0;i<10;i++) nfun+=qw[i];
		     for(i=0;i<nfun;i++) fscanf(flpt,"%f",&x0[i]);
		     fscanf(flpt,"%f",&epsilon);
		     fclose(flpt);
		     minimize(0);
		     if(!strcmp(filename,"no")) outrezult();
		     cinit(BLACK,WHITE,BLACK,WHITE);
		     clrscr();
		     return;
		   }
	    }

	scrinit(LIGHTGREEN,CYAN); mheader();
	cinit(BLUE,YELLOW,GREEN,BLACK);
	hotinit(LIGHTRED);
	do
	{
		vertmenu(27,8,7,mmenu,mhotkeys,hi,a,23,&q);
		switch (q)
		{
			case -1: break;
			case -2: q=0; break;
			case -3: q=5; break;
			case 0:  helper(); mheader(); break;
			case 1:  setiter(); break;
			case 2:  setfile(); break;
			case 3:  setfunction(); break;
			case 4:  minimize(1); break;
			case 5:  outrezult(); break;
			default: ;
		}
	} while (q!=6);
	cinit(BLACK,WHITE,BLACK,WHITE);
	clrscr();
	return;
}