Как сложить спальник

За инструкцию и фотографии спасибо Илье Глушко.

  1. Расправить и застегнуть.
    photo_2017-05-20_19-41-26
  2. Сложить пополам.
    photo_2017-05-20_19-41-46
  3. Плотно скрутить, начиная с узкой стороны. Сжимать сильнее.
    photo_2017-05-20_19-42-13
  4. Затолкать в чехол.
    photo_2017-05-20_19-43-46

Что означает REF на английских чертежах

На следующем чертеже множество размеров с пометкой REF.

REF

REF (Reference dimension) — размер для справок.

Это понятие пересекается с понятием из ГОСТ 2.307-2011:

3.3 справочные размеры: Размеры, не подлежащие выполнению по данному графическому документу и указываемые для большего удобства пользования этим документом.

4.3 Справочные размеры отмечают знаком «*», а в технических требованиях записывают: «*Размеры для справок». Если все размеры справочные, их знаком «*» не отмечают, а в технических требованиях записывают: «Размеры для справок».

REF_GOST

ARM и специфичный для компиляторов код

Любой разработчик компиляторов расширяет язык программирования и расширяет по своему.

Лучше стараться не отклоняться от спецификации языка. Но если специфичный для компилятора код неизбежен, то его нужно обернуть проверкой компилятора, и, если компилятор не совпадает, выдать ошибку.

Ниже приведен пример кода для некоторых ARM-компиляторов.


#if defined (__CC_ARM)
    /* Код для компилятора Keil */
#elif defined (__ICCARM__)
    /* Код для компилятора IAR */
#elif defined ( __GNUC__ )
    /* Код для компилятора GNU */
#elif defined (__TASKING__)
    /* Код для компилятора TASKING */
#else
    /* Неизвестный компилятор */
    #error Unknown compiler
#endif

Отладка Django-сайта на боевом сервере OpenShift

Ни в коем случае нельзя включать отладку на боевом сервере. Рекомендуется создать копию сервера, недоступную для пользователя.

В файле settings.py задается переменная DEBUG. Если при загрузке страницы произошла ошибка, то в зависимости от значения этой переменной выдается либо страница с HTTP ошибкой, либо страница с отладочной информацией.

На локальном сервере разработчика значение DEBUG равно True большую часть времени, а на боевом сервере значение DEBUG должно быть всегда равно False. Но можно создать тестовый сервер, копию боевого, где значением DEBUG можно управлять.

Следующий код позволяет включать и отключать отладку на локальном сервере и на сервере Openshift. Код располагается в файле settings.py.

import os
ON_PAAS = 'OPENSHIFT_REPO_DIR' in os.environ
LOCAL_DEBUG = True
ENV_DEBUG = os.environ.get('DEBUG') == 'True'

DEBUG = (not ON_PAAS and LOCAL_DEBUG) or (ON_PAAS and ENV_DEBUG)

if ON_PAAS and DEBUG:
    print("Warning: debug mode!")

Переменная ON_PAAS равна True если код выполняется на сервере Openshift, иначе она равна False. Переменная LOCAL_DEBUG включает или отключает локальную отладку.

При отключении отладки на локальном сервере в список ALLOWED_HOSTS должна быть добавлена строка ‘localhost’.

ALLOWED_HOSTS = ['localhost']

Включить отладку на сервере Openshift можно если создать переменную окружения DEBUG со значением True.

Управлять переменными окружения на Openshift можно с помощью инструмента rhc. Следующие команды включают отладку на сервере Openshift.

rhc env set DEBUG=True -a test
rhc app stop -a test
rhc app start -a test

Где test — это имя приложения. Первая команда устанавливает переменную окружения, а две другие перезапускают приложение.

Отключить отладку можно следующими командами.

rhc env unset DEBUG -a test
rhc app stop -a test
rhc app start -a test

Вместо первой команды можно использовать следующую команду.

rhc env set DEBUG=False -a test

 

Библиотека на языке C для конвертации строк из кодировки UTF-8 в CP1251

Написал легкую библиотеку utf8_to_cp1251 для конвертации из UTF-8 в CP1251 для применения в программах для микроконтроллеров. Охватывает языки от С89 до C++.

Библиотека и ее описание опубликованы на Github.

Статические переменные вместо глобальных на Си/Си++

Использование глобальных переменных считается дурным тоном, потому что создает много проблем. Избавиться от них можно с помощью ключевого слова static, которое создает статические переменные.

Есть простой способ избавиться от большинства глобальных переменных.

void fun(void) {
    static int A = 10;
    ...
}

Переменная A располагается в глобальной области памяти, но имеет локальную область видимости (в пределах функции fun). То есть переменная сохраняет свое значение между вызовами функции. Начальное значение переменной равно 10.

Этот способ не годится, если функциям нужно обмениваться данными, например, обработчику прерывания с основной программой. Это решается созданием глобальной переменной в отдельном файле. Ниже приведен код такого файла.

static int A = 10;

void setA(const int value) {
    A = value;
}

int getA(void) {
    return A;
}

Область видимости переменной A — только этот файл. Никаким способом к ней нельзя получить доступ из других файлов. Функции setA и getA позволяют получить и установить значение переменной.

Угол опрокидывания тела

ugol-oprokidivaniya.png

Тело на изображении опрокинется, если его центр тяжести M будет левее точки опоры O. Предельный уклон тела рассчитывается по следующей формуле.

\alpha = arctg \left(\frac{X_M}{Y_M}\right)

Расчет на Питоне:

import math
Xm = 1.5
Ym = 2
math.degrees(math.atan(Xm / Ym))

Результат примерно 37°.

Публикация проекта в PyPI

PyPI — это хранилище пакетов Python.

Регистрируемся на сайте PyPI и на TestPyPI. Поле PGP Key ID заполнять необязательно. На TestPyPI регистрироваться не обязательно, это хранилище нужно только для тренировки, перед тем как опубликовать пакет в PyPI.

В домашней папке пользователя создаем файл .pypirc. Точка в начале имени файла обязательна. Этот файл нужен программе twine, которая выкладывает пакеты. О ней пойдет речь позже.

Добавляем в файл следующее содержимое.

[distutils]
index-servers =
    pypi
    testpypi

[pypi]
repository = https://pypi.python.org/pypi
username = Логин
password = Пароль

[testpypi]
repository = https://testpypi.python.org/pypi
username = Логин
password = Пароль

Вместо Логин и  Пароль указываем логин и пароль, использованные при регистрации на сайтах PyPI и TestPyPI.

Допустим проект называется example, тогда структура файлов и папок проекта должна выглядеть следующим образом.

  • example
    • example
      • __init__.py
      • foo.py
    • LICENSE.txt
    • MANIFEST.in
    • README.rst
    • setup.cfg
    • setup.py

Для большей наглядности приведу изображение.

pypi-dirs-and-files.png

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

Для публикации проекта нужно заполнить файл setup.py, все остальные файлы могут быть пустыми.

Файл setup.py следует заполнить следующим образом.

from setuptools import setup, find_packages

setup(
    name='example',
    version='0.0.1',
    description='Короткое описание',
    packages=find_packages(),
    author='Имя автора',
    author_email='Почта@автора',
    url='http://Сайт проекта',
)

В файле лучше использовать только латиницу.

Чтобы собрать пакет, в папке, где содержится файл setup.py (папке проекта), выполняем следующую команду .

python setup.py sdist

После этого в папке проекта появятся папки dist и example.egg-info.

pypi-dirs-and-files-after-build.png

Устанавливаем программу twine, которая позволит разместить пакет в хранилище, следующей командой.

pip install twine

Зарегистрируем пакет в тестовом хранилище TestPyPI следующей командой.

twine register -r testpypi dist/example-0.0.1.tar.gz

С помощью опции -r задается хранилище, которое было указано в файле .pypirc.

Загрузим пакет в хранилище следующей командой.

twine upload -r testpypi dist/example-0.0.1.tar.gz

Пакет появится в списке пакетов на сайте хранилища.

testpypi-your-packages.png

За более подробной информацией следует обратится к официальному руководству.

Иллюстрация: Ноты для пианино

Скачать иллюстрацию в формате PDF.

Noty_dlya_pianino

Лист А4 разделен на две половины формата А5, чтобы лист А4 можно было сложить пополам. На левой половине нотоносец с басовым ключем, на правой — со скрипичным.

Обозначения

  • ск — субконтроктава,
  • к — контроктава,
  • Б — большая октава,
  • м — малая октава,
  • 1 — первая октава,
  • 2 — вторая октава,
  • 3 — третья октава,
  • 4 — четвертая октава,
  • 5 — пятая октава.

Техническая информация

Проект доступен на Github, чтобы любой желающий мог поправить под свои нужды.

Иллюстрация выполнена в LibreOffice Draw 5.1.4.

Печать HTML-документа в Qt 5.8

23 января 2017 года вышла Qt версии 5.8, в которой появилась поддержка печати полноценных HTML-документов.

До этого возможность напечатать документ тоже была. Можно было:

  • Использовать метод QTextDocument::Print(). Но приходилось ограничиваться небольшими возможностями HTML и CSS.
  • Использовать метод QWebFrame::print(), который существовал пока не вышла Qt 5.6. Потом в Qt был окончательно заменен веб-движок и поддержка печати пропала.
  • Использовать печать в PDF с помощью метода QWebEnginePage::printToPdf(), который появился в Qt 5.7. Но печать в PDF — это не печать через принтер.
  • Вывести видимую часть страницы на печать методом QWebEngineView->render(). Но это плохой обходной путь, так как не вся страница будет выведена на печать и потребуется отобразить страницу.

В Qt 5.8 появился метод QWebEnginePage::print(), который выводит на печать HTML-документы без отрисовки в окне и поддерживает современные возможности HTML, CSS и JavaScript.

Следующий код выводит HTML-документ на принтер.

#include <QDebug>
#include <QPrinter>
#include <QPrintDialog>
#include <QPrinterInfo>
#include <QWebEnginePage>

void MainWindow::on_printButton_clicked()
{
    QPrinter * printer = new QPrinter();

    QPrintDialog printDialog(printer, this);
    if (printDialog.exec() != QDialog::Accepted) {
        return;
    }

    QWebEnginePage * page = new QWebEnginePage;

    page->setHtml("<html><body>Привет<body/></html>");

    connect(page, &QWebEnginePage::loadFinished, [page, printer] (bool ok) {
        if (!ok) {
            qDebug() << "Загрузка документа провалилась."; delete page; delete printer; return; } page->print(printer, [page, printer](bool ok) {
            if (ok) {
                qDebug() << "Документ напечатан.";
            }
            else {
                qDebug() << "Печать документа провалилась.";
            }

            delete page;
            delete printer;
        });
    });
}

В файле проекта (*.pro) нужно подключить два модуля с помощью следующей строчки.

QT += printsupport webenginewidgets

В коде используются лямбда-выражения, которые появились в C++11. Это конструкции вида: «[…] (…) {…}», анонимные функции внутри функций. В Qt 5.8 по умолчанию включен C++11.

Класс QWebEnginePage обрабатывает, отрисовывает и печатает документы асинхронно с основным кодом программы, поэтому код в лямбда-функциях выполняется уже после того, как завершится метод on_printButton_clicked().

Надо внимательно следить за удалением объектов, чтобы не возникло утечки памяти и ошибки сегментации, особенно при печати нескольких документов в цикле. Объект принтера может быть одним, а выводимых на печать документов несколько. Тогда объект принтера надо удалять, после печати последнего документа, и не забывать, что печать происходит асинхронно. То есть функция print() завершается еще до вывода документа на печать.

Но и у этого способа печати есть огромный недостаток. К сожалению модуль Qt WebEngine, в который входит класс QWebEnginePage, недоступен при сборке проекта с помощью MinGW в Виндовс. Собрать проект в Виндовс можно только с помощью Visual Studio.