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 712:
      //   return UserAlg712(info,r);

      case 927:
        return UserAlg927(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);
}

UserAlg927(&info,&r)
{
   // дни повышенной оплаты

   double n6;
   var   m1=s98(0,n6);
   double n2;
   double k;
   //if(m1 == 1)
   //   s97(info.d1,info.d2,n2,k,1); // дневные
   //else
   struct Struct_Alg Work;
   Get_AlgWithParam(Work,info.ikod);   // 31.01.1995
   bool useNormZar=false;
   int stolbec=ST_STAVKA+1;
   // Work.Count_Par - число паpаметpов для кода алгоpитма
   //-- параметр 1 - рассчитывать ставку через ras_normzar
   if (Work.Count_Par>0)
   {
      double i=atoi(reinterpret_cast_to_string(Work.List_Par[0]));
      if ( i!=0 )
         useNormZar=true;
   }
   //-- параметр 2 - столбец для расчета ставки через ras_normzar
   if (Work.Count_Par>1)
   {
      double i=atoi(reinterpret_cast_to_string(Work.List_Par[1]));
      if (i > 0 && i <= 99)
         stolbec=i;
   }
   // допл. за ночн. время; РВ - в часах
   // БЗ - процент доплаты
   double n5;
   if(useNormZar)
   {
      //дата начала вида, либо первое число месяца.
      var db=KDateFromD(info.d1);
      if(!db.IsValid() || db.GetAbs()<mrasch)
         db=KDateFromInt_WithDay(1,mrasch);
      
      var dop;
      n5=GetRasNormzarOnDate(stolbec,db.GetStr(),GetCurPropCountLS(),dop)/norm(2);
   }
   else
      s96(info.d1,info.d2,n2,1);    // часовые
   char t[20];
   if((info.c=korrv(r,t,0,info.h,flagrow,jf)) != 1)
      return code_ReturnCode;
   info.n1=r[2]*n2*info.bz/100.;
   if(FL_V_ALG && uprc != NO_SCREEN)
   {
      infolist.add_record("Џ а ¬Ґва 1  «Ј®аЁв¬ ",useNormZar);
      infolist.add_record("‘в®«ЎҐж ¤«п а бзҐв  бв ўЄЁ",stolbec);
      infolist.add_record("ђ Ў®зҐҐ ўаҐ¬п",r[2]);
      infolist.add_record("‘в ўЄ ",n2);
      infolist.add_record("Џа®жҐ­в",info.bz);
      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;
}
