1c: извлечение страницы из pdf документа

В настоящий момент в 1С нет встроенного средства для редактирования pdf документов, поэтому единственный выход — использовать внешние программы. Например — pdftk или ExtractPagePDF

Ниже пример реализации для ExtractPagePDF:

функция ИзвлечьСтраницуPDF(имяфайла,страница)
	answer=новый Структура("error,result",false,"");
		// вариант с ExtractPDF
		ПутьКПрограммеИзвлечения = lsОбщегоНазначенияСервер.ПутьКПрограммеРаботыСPDFФайлами();
		ИмяВременногоФайлаИзвлечения 	= ПолучитьИмяВременногоФайла("pdf");
		КаталогИзвлечения 				= ОбщегоНазначенияКлиентСервер.ДобавитьКонечныйРазделительПути(КаталогВременныхФайлов());			
		КодВозвратаКомпоненты = 1;
		ЗапуститьПриложение(ПутьКПрограммеИзвлечения + " 1 """ + имяфайла + """ """ + ИмяВременногоФайлаИзвлечения+""" "+Формат(страница,"ЧГ=0"), , Истина, КодВозвратаКомпоненты);			
		Если КодВозвратаКомпоненты <> 0 Тогда 				
				answer.error=true;      
				answer.result="Не удалось извлечь файлы счетов! для л/с ";
				возврат answer;
		КонецЕсли;
        answer.result=ИмяВременногоФайлаИзвлечения;	
		
		// вариант с pdftk			
		//ПутьКПрограммеИзвлечения = lsОбщегоНазначенияСервер.ПутьКПрограммеРаботыСPDFФайлами();
		//ИмяВременногоФайлаИзвлечения 	= ПолучитьИмяВременногоФайла("pdf");
		//КаталогИзвлечения 				= ОбщегоНазначенияКлиентСервер.ДобавитьКонечныйРазделительПути(КаталогВременныхФайлов());			
		//КодВозвратаКомпоненты = 1;      
		//страница=Формат(страница,"ЧГ=0");
		//ЗапуститьПриложение(ПутьКПрограммеИзвлечения +" """+ имяфайла + """ cat "+страница+" """ + ИмяВременногоФайлаИзвлечения+"""", , Истина, КодВозвратаКомпоненты);			
		//Если КодВозвратаКомпоненты <> 0 Тогда 				
		//		answer.error=true;      
		//		answer.result="Не удалось извлечь файлы счетов! для л/с ";
		//		возврат answer;
		//КонецЕсли;
		//answer.result=ИмяВременногоФайлаИзвлечения;	
		
		
		
	возврат answer;
конецфункции

PHP: нормализация номера телефона

Задача: на входе строка, которая может содержать номер, или номер + какие то комментарии к нему. Необходимо нормализовать номер, что бы были только цифры.

Решение:

Сначала напишем функцию проверки наличия букв в строке:

function LeetterYet($mobile){
    $yet=false;            
        if (preg_match('/[а-яё]/iu',    $mobile)) {$yet=true;};    // символ ё, отдельно проверяем
        if (preg_match('/[a-zA-Z]/',    $mobile)) {$yet=true;};    // английский алфавит
        if (preg_match('/[^a-zA-Z\d]/',    $mobile)) {$yet=true;}; // специальные символы
    return $yet;
}

Далее, если есть буквы, то удалим их, и ограничим длинну поля 11 символами..

function NormalizeMobile($mobile){
  $mobile=preg_replace('/[^0-9]/', '', $mobile);
  $mobile = substr($mobile, 0,11);
  return $mobile;
};

И общий результат:

        $mobile=$res->result->mobile;            
        if (LeetterYet($mobile)==false){                
          $mobile=  NormalizeMobile($mobile);
        };

Пишем Тетрис на Flutter

Дело было вечером, делать было нечего (с)..В качестве разминки решил в кои-то веки написать игру. Пришла на ум идея написать давнюю мечту — тетрис. В т.ч. использовать будем более ранние наработки по работе с Hive и Requets оформленные в виде отдельных классов.

Из интересного:

1) Для отображения стакана и фигур используем три массива:

LandMatrix — массив вида ширина/высота — фактически «стакан» с «приземленными» фигурами. Точка пересечения массива — цвет квадратика. Если пусто — значит в точке стакана ничего нет

MoveFig — массив движущейся по стакану фигуры. В момент совпадения низа фигуры с любой не пустой точкой стакана фигура переносится в «стакан»

ShadowRotareFig — вспомогательный массив, используемый для поворота фигуры. В момент когда фигуру необходимо повернуть, она переносится из MoveFig в этот массив, поворачивается, и переносится обратно в MoveFig. Создание отдельного массива для поворота было обусловлено способом хранения фигур — хранится не матрица, а просто массив текущих координат квадратиков из которых составлена фигура.

2) Отрисовка стакана происходит после того, как фигура перенесена в массив стакана. Причины переноса — касание дна стакана.

List <Widget> MyLandView(){
    int poz=0;
    return List<Widget>.generate(lh, (int index_h){
      return Row(
        children:
        List<Widget>.generate(lw, (int index_w){
          poz++;
          Color BoxColor=FigColors[99]??Colors.black;
          if (MovedFig.contains(poz)==true){
            BoxColor=FigColors[fcurrent]??Colors.black;
          };
          Coords crd=Poz2Coors(poz);
          // если в стакане что-то есть - рисуем
          if (LandMatrix[crd.y][crd.x]>0){  // если  клетка не пустая
            BoxColor=FigColors[100]??Colors.black;
          };
          if (LandMatrix[crd.y][crd.x]==101){  //
            BoxColor=FigColors[101]??Colors.black;
          };
          if (BoxColor==FigColors[100]){
            //определяем это верхний блок или под ним еще что есть?
            bool ground_top=false;
              Coords crd_tmp=Poz2Coors(poz-lw);
              print("Строчка: ${crd.y},${crd.x}");
              print("Строчка вниз: ${crd_tmp.y},${crd_tmp.x}");
              if (crd_tmp.y>0) {
                if (LandMatrix[crd_tmp.y][crd_tmp.x] >0) {
                  print("-- ниже  есть земля!");
                  ground_top = true;
                }
              }
            return
                Container(
                  color: BoxColor,
                  height: MediaQuery.of(context).size.height/lh,
                  width: MediaQuery.of(context).size.width/lw,
                  child:
                    Image.asset(
                        !ground_top?"lib/images/ground.png":"lib/images/ground_full.png",
                      height: 10,
                      width: 10,
                      fit: BoxFit.fill,
                    ),
                );
          } else {
            return
              Padding(
                  padding: EdgeInsets.all(1),
                  child:
                  Container(
                    color: BoxColor,
                    height: MediaQuery.of(context).size.height / lh - 2,
                    width: MediaQuery.of(context).size.width / lw - 2,
                    //child: Text("$poz")
                  )
              );
          };
        }),
      );
    });
  }

3) При старте игры назначаем периодический таймер, при выполнении которого фигура движется на линию ниже. При движении выполняется проверка касания дна в стакане.

  void StartTimer(context){
    timer = Timer.periodic(Duration(seconds: 1), (Timer _) {
      DestroyFullLines();
      print("Сработал таймер..");
      MoveFigDown(context);
    });
  }
  // двигаем фигуру вниз
  void MoveFigDown(context){
      if (GameOver==true) {return;};
      bool move=true;
      // проверим,при следующем шаге, ни одна ли из точек не достигнет дна колодца при движении вниз?
      for (var i = 0; i < MovedFig.length; i++) {
        // проверка дна колодца
        if ((MovedFig[i] + lw)>lw*lh){
          move=false;
        };
        // проверка что наезд на другую фигуру
        Coords crd=Poz2Coors(MovedFig[i] + lw);
        if (MovedFig[i] + lw<=lw*lh) {
          if (LandMatrix[crd.y][crd.x] > 0) {
            move = false;
          };
        };
      };
      if (move==true) {
        for (var i = 0; i < MovedFig.length; i++) {
          MovedFig[i] = MovedFig[i] + lw;
        };
      };
      // если не можем двигаться вниз, то переносим фигуру в "стакан"
      if (move==false){
        print("-переносим фигуру в стакан");
        for (var i = 0; i < MovedFig.length; i++) {
          Coords crd=Poz2Coors(MovedFig[i]);
          LandMatrix[crd.y][crd.x]=1;
        };
        DestroyFullLines();
        // создаём новую фигуру
        FigureSelections();
      };
      setState(() {
        MovedFig=MovedFig;
      });
    print("Фигура двинулась вниз: ${MovedFig}");
      String audioasset = "lib/sounds/click.mp3";
      AssetsAudioPlayer.newPlayer().open(
          Audio(audioasset)
      );
  }

4) Поворот фигуры, как уже писал выше осуществляется переносом фигуры в матрицу, поворот матрицы и обратный перенос фигуры

  // поворачиваем блок
  void RotateFig(context){
    print("До поворота: ${MovedFig}");
    List <int> OldFig=List<int>.from(MovedFig); //запоминаем фигуру и положение до поворота

    // найдем минимальные координаты x и y до поворота
    Coords crd_before_rotare=GetStartXYFigure(MovedFig);
    print("min_x=${crd_before_rotare.x},min_y=${crd_before_rotare.y}");

    // передвинем фигуру в центр
    int center_x=4;
    int center_y=4;

    MovedFig=FigureMove(center_x,center_y,MovedFig);

    for (var i = 0; i < MovedFig.length; i++) {
      Coords crd=Poz2Coors(MovedFig[i]);
      int new_x=(crd.x * cos(3.1415926535897932/2) - crd.y * sin(3.1415926535897932/2)).round();
      int new_y=(crd.x * sin(3.1415926535897932/2) + crd.y * cos(3.1415926535897932/2)).round();
      MovedFig[i]=Coors2Poz(new_x,new_y);
      //print("x=${new_x},y=${new_y}");
    };
    MovedFig=FigureMove(crd_before_rotare.x-2,crd_before_rotare.y,MovedFig);

    print("После поворота: ${MovedFig}");
    // проверяем, а можно ли было поворачивать?
    if (MovedFig[0]==-1){
      MovedFig=OldFig;
    }
    // проверяем, а нет ли наложения элементов на то что уже в стакане?
    for (var i = 0; i < MovedFig.length; i++) {
      Coords crd=Poz2Coors(MovedFig[i] + lw);
      if (MovedFig[i] + lw<=lw*lh) {
        if (LandMatrix[crd.y][crd.x] > 0) {
          MovedFig=OldFig;
        };
      };
    };
  }

Исходный код игры можно скачать тут

1 2