1C: прикрепление файла к документу в разных версиях БСП

БСП < 2.0:

АдресФайлаВХранилище = ПоместитьВоВременноеХранилище(Base64Значение(body.file_base64));
		РаботаСФайламиВызовСервера.СоздатьФайлСВерсией(
			док.Ссылка,
			"результат",
			"pdf",
			ТекущаяДата(),
			ТекущаяДата(),
			,
			АдресФайлаВХранилище,АдресФайлаВХранилище,
			Ложь,
			,
			,
			Истина);		

БСП 2..3:

 // Добавляем его в присоединенные файлы к договору.
    ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ИмяФайла);
    АдресВХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла);
    НаименованиеФайла = НачалоНаименованияФайла + " " + ДоговорСсылка.Номер + " от " + Формат(ДоговорСсылка.Дата, "ДЛФ=D");
    //ПрисоединенныйФайлСсылка = ПрисоединенныеФайлы.ДобавитьФайл(ДоговорСсылка, НаименованиеФайла, РасширениеБезТочки, , , АдресВХранилище,,,, НаименованиеФайла + " (Сф-но автомат-ки)");

    ИмяФайлаПриведенное = ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла(НаименованиеФайла, "_"); // ЕМ 2015_10_20
    ПрисоединенныйФайлСсылка = ПрисоединенныеФайлы.ДобавитьФайл(ДоговорСсылка, ИмяФайлаПриведенное, РасширениеБезТочки, , , АдресВХранилище,,,, НаименованиеФайла + " (Сф-но автомат-ки)");

Современные версии

ИмяФайлаНаДиске = "C:\Users\v.burmistrov\Downloads\ффд12.pdf";	
ДвоичныеДанные = Новый ДвоичныеДанные(ИмяФайлаНаДиске);
ВременноеХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанные);
// Подготоваливаем описание файла заполнив все необходимые параметры
ПараметрыФайла = РаботаСФайлами.ПараметрыДобавленияФайла();
ПараметрыФайла.Автор = Пользователи.ТекущийПользователь();
ПараметрыФайла.ВладелецФайлов = ДокументСсылка;
ПараметрыФайла.ИмяБезРасширения = СтрЗаменить(ИмяФайлаНаДиске,".pdf","");
ПараметрыФайла.РасширениеБезТочки = "pdf";
// Используем функцию БСП и добавляем файл к объекту
РаботаСФайлами.ДобавитьФайл(ПараметрыФайла, ВременноеХранилище);

1C: Выгрузка и загрузка данных

Иногда бывает необходимо выгрузить данные из одной конфигурации и загрузить её в другую. Если конфигурации идентичны, или очень похожи, то можно воспользоваться обработкой «Выгрузка и загрузка данных XML».

В моём случае из-за небольшого фекапа с обновлением, потерялась часть данных в справочнике «файлы», а потому необходимо было выгрузить из конфигурации восстановленной из бекапа выгрузить данные в обновленную конфигурацию. Причём часть реквизитов в ней была изменена. Для реализации задуманного воспользуемся вкладкой «Дополнительные объекты для выгрузки», выбрав там данные «файл» и заполнив таблицу запросом:

ВЫБРАТЬ
	Файлы.Ссылка КАК Ссылка
ИЗ
	Справочник.Файлы КАК Файлы
ГДЕ
	Файлы.ВладелецФайла ССЫЛКА Документ.СК_ГР_ЗапросыГосуслуги

Далее в полученном файле XML необходимо добиться полной идентичности данных. В моём случае это достигается добавленим реквизита

<v8:ПодписанЭЦП>false</v8:ПодписанЭЦП>

После чего открываем обработку в целевой конфигурации и загружаем данные.

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 43 44 45 46 47 308