import "layer92.dll"


UserAlgorithmCalc(&info,&r)
{
   // инициализация локальных переменных
   int RetFlag       = code_Break,
       crow          = info.crow,
       b3            = info.b3,
       ikod          = info.ikod,
       kod_alg       = info.kod_alg,
       pos           = info.pos,
       mkat          = info.mkat,
       krabot        = info.krabot,
       tip_s9600     = info.tip_s9600,
       flag_propusk0 = info.flag_propusk0,
       z1            = info.z1,
       z2            = info.z2;

   double h[4];
   double kod        = info.kod,
          n1         = info.n1,
          d1         = info.d1,
          d2         = info.d2,
          bz         = info.bz;
          h[0]       = info.h[0],
          h[1]       = info.h[1],
          h[2]       = info.h[2],
          h[3]       = info.h[3];

   int rowkod[ROWMAX],i,m,m1,b1,b2,mvrem;
   char t[20],str[81],str1[81];
   double n2,n3,n4,n5,n6,n7,n8,n9,n10,r8,r9,k;

   /*-----------------------------------------------------*/
   /* tip_s9600=0 - функция обработки СУММЫ по строке     */
   /*               (s9600) - обнуляет РВ, если СУММА==0. */
   /* tip_s9600=1 - не обнуляет (в спец.случаях)          */
   /*-----------------------------------------------------*/

   /*-----------------------------------------------------*/
   /* Если flag_propusk0=1, то расчет данного вида по его */
   /* алгоритму производится только через режимы "Расчет  */
   /* произвольного вида", "Доп.расчеты" и при расчете от-*/
   /* дельной строки в "Просмотре, корректировке ЛС".     */
   /* flag_propusk0=3, то же, что =1, только в этом случае*/
   /* программа работает со строкой вида даже если у нее  */
   /* вышли даты действия (например, для квартал.дотаций).*/
   /* В остальных режимах - если есть СУММА, то подается  */
   /* на корректировку, иначе - вид пропускается в расчете*/
   /*-----------------------------------------------------*/

   int c=-4096;

   switch(kod_alg)
   {
      // Сюда можно вставлять вызов собственных алгоритмов расчета.
      // Примеры функций с алгоритмами  находятся
      // в файле SCRIPT\ALGSYS.S

      // начало описания алгоритмов пользователя


      // конец описания алгоритмов пользователя

      // Пример вызова алгоритма пользователя.
      //case 4:
      //   return UserAlg4(info,r);

       case 17:
         return UserAlg17(info,r);
      // case 712:
      //   return UserAlg712(info,r);

      default:
         RetFlag=0;
         break;
   }

   if ( RetFlag )
   {
      info.crow            = crow,
      info.b3              = b3,
      info.kod             = kod,
      info.ikod            = ikod,
      info.kod_alg         = kod_alg,
      info.n1              = n1,
      info.d1              = d1,
      info.d2              = d2,
      info.pos             = pos,
      info.mkat            = mkat,
      info.krabot          = krabot,
      info.tip_s9600       = tip_s9600,
      info.flag_propusk0   = flag_propusk0,
      info.z1              = z1,
      info.z2              = z2,
      info.h[0]            = h[0],
      info.h[1]            = h[1],
      info.h[2]            = h[2],
      info.h[3]            = h[3],
      info.bz              = bz;

      if (c<=-4096) c=1;
      info.c               = c;
   }
   return RetFlag;
}

UserAlg4(&info,&r)
{
  return SysAlg4(info,r);
}

UserAlg17(&info,&r)
{
  //В БЗ вида - внешний код вида, из которого нужно брать тариф
   // вычисляем внутренний код
   double int_kod=Extern_To_InternE(info.bz);
   
   double bz=0.;
   poiskbz(0,int_kod,1," ",bz); //Получаем БЗ вида с кодом int_kod

   char t[20];
   if((info.c=korrv(r,t,0,info.h,flagrow,jf)) != 1)
      return code_ReturnCode;
   double proc=40;
   info.n1=bz*r[2]*proc/100.;
   if(FL_V_ALG && uprc != NO_SCREEN)
   {
      infolist.add_record("Ставка",bz);
      infolist.add_record("Рабочее время",r[2]);
      infolist.add_record("Процент выплаты",proc);
      infolist.add_record("Результат",info.n1);
   }
   return code_Break;
}

UserAlg712(&info,&r)
{
   struct Struct_Alg Work;
   var mes1=0;
   var mes2=0;
   var stolbec=ST_MPREM+1;

   // символы для выборки
   // по умолчанию - по всем ненулевым
   char StrSimv[51];
   sprintf(StrSimv,"*");
   Get_AlgWithParam(Work,info.ikod);   // 31.01.1995
   // Work.Count_Par - число паpаметpов для кода алгоpитма
   //-- параметр 1 - столбец таблицы входимости
   if(Work.Count_Par > 0)
   {
      var i=atoi(reinterpret_cast_to_string(Work.List_Par[0]));
      if( i > 0 && i <= 99 ) stolbec=i;
   }

   //-- параметр 2 - месяц начала выборки (относительно расчетного)
   //   (по умолчанию берется за один текущий месяц)
   if(Work.Count_Par > 1)
   {
      var i=atoi(reinterpret_cast_to_string(Work.List_Par[1]));
      if( i >= (- PMES) && i <= BMES )  mes1=mes2=i;
   }

   //-- параметр 3 - месяц конца выборки (относительно расчетного)
   //   (по умолчанию берется за один месяц, указанный параметром 2)
   if(Work.Count_Par > 2)
   {
      var i=atoi(reinterpret_cast_to_string(Work.List_Par[2]));
      if( i >= mes1 && i <= BMES ) mes2=i;
   }

   //-- параметр 4 - символы выборки
   if(Work.Count_Par > 3)
      sprintf(StrSimv,"%.50s",reinterpret_cast_to_string(Work.List_Par[3]));

   var   n5=0.;
   for(var m=mes1; m<=mes2; m++)
   {
      double r9;
      s1001simv(StrSimv,"*",info.d1,info.d2,m,stolbec-1,r9,4,0);
      n5+=r9;
   }


   // Заполним таблицу уже найденными значениями
   if(FL_V_ALG && uprc != NO_SCREEN)
   {
      infolist.add_record("Месяц начала выборки",mes1);
      infolist.add_record("Месяц окончания выборки",mes2);
      infolist.add_record("Столбец выборки",stolbec);
      infolist.add_record("Символы выборки",StrSimv);
      infolist.add_record("Сумма выборки",n5);
   }

   // А теперь пройдемся по полю кадровой части "procPREM"
   // И возьмем оттуда все значения процентов, действовавшие
   // в рассчитываемом месяце
   info.n1=0.;  // обнулили итоговую сумму

   // Дата конца действия очередного значения процента
   // В самом начале она равна последнему дню месяца.
   var DateEnd = CreateObject("KDate");
   DateEnd.SetDateII(countday,mrasch);

   // Найдем дату начала действия очередного значения процента
   char StrD[21];
   GetKchDate("procPREM",StrD,10,DateEnd);
   var Date=CreateObject("KDate");
   Date.SetDate(static_cast_to_string(StrD));
   // Если вдруг дата начала пустая или выходит за рамки расчетного
   // месяца, то установим ее равной первому числу расчетного месяца
   if ( Date.IsEqI(INVALID_DATE_VALUE) || Date.GetAbs()<mrasch )
   {
      Date.SetDateII(1,mrasch);
      sprintf(StrD,"%02d.%02d.%4d",Date.GetDay(),Date.GetMonth(),Date.GetYear());
   }

   // Ну и просматриваем все значения процентов, действовавшие в
   // рассматриваемом месяце
   char StrProc[21];
   while ( 1 )
   {
      // находим очередное значение процента
      double Proc=atof(GetKchValue("procPREM",StrProc,20,DateEnd));

      // определяем коэффициент неполноты для очередного значения процента
      // (неполнота по нормативным дням)
      double KoefNepoln = 1.;
      nepoln(Date.GetDouble(),DateEnd.GetDouble(),info.d1,info.d2,KoefNepoln,2);

      // записываем, если надо, в таблицу найденные значения
      if(FL_V_ALG && uprc != NO_SCREEN)
      {
         infolist.add_record("------------------------","---------------------");
         infolist.add_record("Начало действия процента",StrD);
         sprintf(StrD,"%02d.%02d.%4d",DateEnd.GetDay(),DateEnd.GetMonth(),DateEnd.GetYear());
         infolist.add_record("Конец  действия процента",StrD);
         infolist.add_record("Коэффициент",KoefNepoln);
         infolist.add_record("Процент",Proc);
      }

      // Увеличиваем итоговую сумму на очередную порцию премии
      info.n1 += n5*Proc*KoefNepoln/100.;

      // Устанавливаем дату конца очередного значения процента
      // равной дате начала уже рассмотренного значения минус один день.
      DateEnd.SetDateD(Date.GetDouble());
      DateEnd.Dec();

      // Если дата конца вышла за пределы расчетного месяца - выходим
      if ( DateEnd.IsEqI(INVALID_DATE_VALUE) || DateEnd.GetAbs()<mrasch )
         break;

      // Находим дату начала для очередного значения премии
      GetKchDateP("procPREM",StrD,10,Date);
      Date.SetDate(static_cast_to_string(StrD));
      // Если вдруг дата начала пустая или выходит за рамки расчетного
      // месяца, то установим ее равной первому числу расчетного месяца
      if ( Date.IsEqI(INVALID_DATE_VALUE) || Date.GetAbs()<mrasch )
      {
         Date.SetDateII(1,mrasch);
         sprintf(StrD,"%02d.%02d.%4d",Date.GetDay(),Date.GetMonth(),Date.GetYear());
      }
   }

   // выводим в таблицу окончаительный результат
   if(FL_V_ALG && uprc != NO_SCREEN)
   {
      infolist.add_record("------------------------","---------------------");
      infolist.add_record("Результат",info.n1);
   }
   return code_MDefault;
}
