Scala partition в Python

Вперше сьогодні в мене був момент “А якби я писав на Scala…”. Задача – є список з мухами і котлетами вкупі. Треба мухи окремо, котлети окремо.

В Python класично це так:

Frikadellen = [x for x in AllesZusammen if IstFrikadelle(x)]
Fliegen = [x for x in AllesZusammen if not IstFrikadelle(x)]

В Scala:

(Frikadellen, Fliegen) = AllesZusammen partition IstFrikadelle

Scala, окрім того що коротша, виграє тим що проходиться по списку лише раз.

Але StackOverflow як завжди дає жару:

Frikadellen, Fliegen = [], []
for x in AllesZusammen:
    (Fliegen, Frikadellen)[IstFrikadelle(x)].append(x)
    # або
    # (Frikadellen if IstFrikadelle(x) else Fliegen).append(x)

Це вже краще, але все одно було б добре якби до списку додали метод partition. Може б то Ґвідо поскаржитись?


Filed under: Кодерство Tagged: Python, scala

vagrant up!

Vagrant – це як висловився dmytrish – CLI до VirtualBox. (А також для інших систем віртуалізації. Перекладається слово як бродяга, і далі ви зрозумієте чому. Для чого там інтерфейс командного рядка? Ну, щоб швидше створювати і перемикатись між віртуальними машинами, а вони сьогодні ой як потрібні.)

Для чого? Ну, для початку – щоб ізолювати середовище розробки. Бо, коли я пишу на своїй машині команду python, мені пропонують наступний вибір:

python                python3.3
python2               python3.3-config
python2.7             python3.3m
python2.7-config      python3.3m-config
python2.7-dbg         python3.4
python2.7-dbg-config  python3.4-config
python2-config        python3.4m
python2-dbg           python3.4m-config
python2-dbg-config    python3-config
python3               python3mu
python3.2             python-config
python3.2-config      python-dbg
python3.2mu           python-dbg-config
python3.2mu-config

Трохи забагато, чи не так? А от якби я пробував кожен наступний python у своїй віртуалці – все було б набагато акуратніше.

Чи наприклад інший приклад. Я хочу тестувати взаємодію бота з медіавікі. Для цього мені бажано її мати (не тестувати ж на живій, а раптом помилку зроблю?), а їй потрібен LAMP-стек, тобто апач або nginx, php, mysql. І це потрібно мені не завжди, а лише поки я ганяю тести до медіавікі. Було б класно тримати для цього окрему віртуальну машину, щоб можна було її вмикати і вимикати при потребі. Отож, давайте розберемось як Vagrant в такому випадку може допомогти.

Інсталятор можна скачати зі сторінки http://www.vagrantup.com/downloads, або встановити за допомогою пакетного менеджера:

sudo apt-get install vagrant

Далі команда

vagrant init hashicorp/precise32

Створює в поточній директорії файл з назвою “Vagrant” що містить конфігурацію для запуску віртуальної машини на основі образу 32-х розрядної Ubuntu 12.04.

vagrant up

Запускає віртуальну машину описану в даному файлі.

vagrant ssh

Входить в запущену віртуальну машину.

За замовчуванням Vagrant робить директорію вашого проекту, доступною віртуальній машині за адресою /vagrant. Тому обережно з rm -rf / бо це потре і ваш проект. А окрім цього можете робити з віртуальною машиною що завгодно. Також зручно мати проект і всередині віртуальної машини і на хості, бо можна одночасно редагувати в зручному редакторі з хоста, і деплоїти з віртуалки.

О, щодо розгортання. Ми можемо зайти по SSH і поставити апач, але тоді це доведеться робити всім хто використовуватиме Vagrant з вашим проектом. Замість цього можна скористатись автоматичним деплойментом.

Інструкція пише що Apache ставиться отаким скриптом:

#!/usr/bin/env bash

apt-get update
apt-get install -y apache2
if ! [ -L /var/www ]; then
  rm -rf /var/www
  ln -fs /vagrant /var/www
fi

А також директорія яку він хостить перенаправляється на директорію з нашим проектом.

Його можна зберегти в директорії проекту як bootstrap.sh і відредагувати файл Vagrant так, щоб він запускав цей файл при старті машини, якщо цього не було зроблено ним раніше. Тепер наш Vagrant-файл повинен виглядати приблизно так:

Vagrant.configure("2") do |config|
  config.vm.box = "hashicorp/precise32"
  config.vm.provision :shell, path: "bootstrap.sh"
end

Якщо машина вже була запущена, їй можна скомандувати перезапуститись і виконати файл провізіонування:

vagrant reload --provision

Якщо ви отримуєте помилку:

/home/bunyk/post2peer/Vagrantfile:6: syntax error, unexpected ':', expecting kEND
  config.vm.provision :shell, path: "bootstrap.sh"

То значить у вас стара версія Ruby, оновіться.

Як побачити що Apache працює? Браузером звісно, але для цього треба відкрити на віртуалці порт для HTTP. Додаємо до конфігурації такий рядок:

  config.vm.network :forwarded_port, host: 4567, guest: 80

Він каже зробити порт 80 віртуалки доступним на хості як 4567. Щоб зміни мали ефект – перезавантажте машину:

vagrant reload

localhost:4567 повинен показувати вміст файлу index.html, якщо такий наявний в вашому проекті.

Коли ви закінчили роботу з машиною, можна зробити три речі:

  • vagrant suspend – зберегти стан машини і зупинити її. Плюси – все зберігається як ви й залишили і для старту буде потрібно лише 5-10 секунд. Мінуси – машина займатиме диск, бо потрібно буде записати знімок її пам’яті.
  • vagrant halt – зупинити всі програми і вимкнути машину. Вміст диску зберігається, вміст оперативки – звісно ні. Старт буде трохи довшим, бо доведеться знову ініціалізувати всі процеси…
  • vagrant destroy – знищити всі сліди того що ви взагалі працювали з машиною (диск). vagrant up буде працювати ніби вперше. Плюси – нічого не треба зберігати, економиться диск. Мінуси – при старті багато часу піде на провізіонування.

І ще інша перевага Vagrant в тому, що він може керувати не тільки VirtualBox, а й всякими там VMWare, і навіть AWS. Треба просто вказати йому інший провайдер – і ваш сервер в хмарах. Але про це якось іншим разом.

Ах, і я на початку казав про медіавікі. Ну, вона ставиться ось так:

sudo apt-get install nfs-kernel-server # якщо NFS не було встановлено
git clone https://gerrit.wikimedia.org/r/mediawiki/vagrant
cd vagrant
git submodule update --init --recursive
./setup.sh
vagrant up

Filed under: Інструменти, Кодерство Tagged: віртуалізація, розробка

Stm32 Nucleo – вхідні сигнали і комунікація з компю’тером

Сьогодні продовжимо розбиратись з нашою платою, і почнемо з того, як отримати натиснення кнопки. Якщо вас цікавить початок – переходьте сюди.

Якихось чітких інструкцій в інтернеті я не знайшов, зате в IDE було аж два демо проекти про кнопку:

  • “Read the user button state on the Nucleo board.”
  • “Read the user button using external interrupt.”

Код там досить простий, але я його ще спростив ось так:

#include "mbed.h"
 
DigitalIn mybutton(USER_BUTTON);
DigitalOut myled(LED1);
 
int main() {
  while(1) {
    myled = mybutton;
  }
}

Тобто так само як ми оголошуємо що змінна myled міститиме рівень напруги на світлодіоді, так само ми оголошуємо що змінна mybutton міститиме рівень напруги на кнопці.

В документації по mbed написано що оголошення DigitalIn можна використовувати на будь-якому виводі, який позначений на схемі синьою міткою. Якщо на вході будь-яка напруга менше 0.8В – міститиме 0, якщо більше 2В – міститиме 1.

Що цікаво, коли я записав вищеподану програму на плату, світлодіод почав світитись, і почав вимикатись лише коли кнопка натиснута. Це пояснюється чудернацькою схемою підключення кнопок – якщо вона розімкнута – на вхід через резистор йде струм. Якщо замкнута – вхід заземляється, і струм йде в землю, тому там нуль.

Інший приклад – з перериванням:

#include "mbed.h"
 
InterruptIn mybutton(USER_BUTTON);
DigitalOut myled(LED1);
  
void pressed()
{
    myled = !myled;
}
 
int main()
{
    mybutton.fall(&pressed);
    while (1) { // без цього - не працює
        wait(100);
    }
}

Тут з кожним натисканням кнопки світлодіод вмикається або вимикається. Зауважте що тепер ми оголошуємо кнопку не як DigitalIn, а як InterruptIn.

Ок, може пора нарешті попрацювати руками? Хоча страшно, бо кажуть що руками ту плату можна й вбити, якщо створити коротке замикання в неправильному місці. Я от наприклад вирішив спробувати як вона працює окремо від комп’ютера, і замість того аби втикнути USB в комп’ютер, втикнув його в адаптер електричної мережі. Адаптер, як на ньому написано повинен був давати 5.1В 850мА постійного струму. Плата не захотіла моргати до мене світлодіодами, як було запрограмовано, просто LD1 (COM) загорівся загрозливим червоним. Тому напевне спершу піду ще раз інструкцію прочитаю.

Схема виходів. В коді дозволяється використовувати лише ті що написані білим в синіх і зелених прямокутничках.

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

З того що я начитався, виходить що там де написано 5v – є напруга 5В, там де 3V3 – 3.3В. (такий запис – це хитрий спосіб прибрати зайвий символ – десяткову крапку, і зробити підпис компактнішим.) До п’ятивольтового контакту світлодіоди краще приєднувати через резистор. GND – це заземлення (мінус).

В світлодіода довша ніжка – це +, коротша -, або та ніжка що всередині корпусу діода має в собі більше металу – це мінус.

І це можна перевірити, втикаючи світлодіод в 3V3 та GND. Або послідовно з резистором в 5V та GND.

Тепер, давайте зробимо так, щоб наш перемикач з останнього лістингу керував зовнішнім світлодіодом. Для цього втикаємо його мінус в GND, в A5 наприклад втикаємо резистор, і з’єднуємо додатню ніжку діода з резистором.

Замінюємо визначення: DigitalOut myled(LED1); на DigitalOut myled(PC_0);. Перепрошиваємо, і тепер вже зовнішній світлодіод повинен реагувати на нашу кнопку.

Далі я написав програмку яка змушувала б вбудований LED показувати стан піна A5 як входу.

#include "mbed.h"
 
DigitalIn mycontact(PC_0);
DigitalOut myled(LED1);
  
int main() {
    while (1) {
        myled = mycontact;
    }
}

І дуже здивувався, бо коли я опускав туди лише одну ніжку резистора – діод засвічувався. Я подумав що струм тече в мене як заземлення і відпустив резистор – діод все одно світився. Дивно. Або я ще чогось не знаю, або в платі якийсь брак. Думаю варто переключитись на вбудовану кнопку до з’ясування обставин.

Що ще хотілось би зробити – так це взаємодію з комп’ютером. Нехай по натисненні кнопки, комп’ютер виконує якусь команду.

Виявляється, що при приєднанні контролера до комп’ютера, він окрім того що розпізнається як диск, ще й додає пристрій який називається /dev/ttyACM* (замість зірочки має бути якесь число). Принаймі так написано в документації.

Ми можемо подивитись що на цьому пристрої, за допомогою команди:

sudo cat /dev/ttyACM0

Якщо треба вийти, то натискаємо Ctrl+A а тоді вводимо команду :quit. Тепер, можемо змусити контролер посилати нашому комп’ютеру всілякі повідомлення по натисненні кнопочки:

InterruptIn mybutton(USER_BUTTON);
Serial pc(USBTX, USBRX);

void pressed()
{
    pc.printf("I'm clicked!\r\n");
}
 
int main()
{
    mybutton.fall(&pressed);
    while (1) { wait(100); }
}

І ми побачимо щось таке:

$> sudo cat /dev/ttyACM0 
I'm clicked!
I'm clicked!
I'm clicked!

І тепер, ми можемо змусити якийсь процес читати цей пристрій і виконувати з нього команди. Наприклад такий Python скрипт:

import os
with open('/dev/ttyACM0', 'rb', 0) as f:
    while True:
        message = f.read(5) # reading 5 byte messages
        if message == 'ALARM':
            os.system('mplayer -fs /home/bunyk/video/beastie_boys_sabotage.flv')

Замінюємо повідомлення з "I'm clicked!\r\n" на І вийде просто чудова кнопка тривоги наприклад:


Filed under: Інструменти, Кодерство, Конспекти Tagged: C++, hardware

Привіт “ядерному мікроконтролеру” ;)

Вкотре переконуюсь що якщо чогось дуже хочеш – то отримаєш. Так от я хотів якось спробувати скласти гірлянду якою можна буде керувати з комп’ютера, трохи думав про Arduino, і недавно мені в руки для тестування потрапила плата NUCLEO-F411RE від компанії STMicroelectronics. Все завдяки автору сайту embedded.co.ua, Василю Йосипенку, якому за це величезне дякую.

nucleo

Почну з того що на платі надруковане посилання: www.st.com/stm32nucleo. І наклеєна наклейка NUCLEO-F411RE. З діаграми на сайті видно що F411 це найшвидша плата, яка має найбільший розмір флеш-пам’яті – 512K. Аж пів метра!

Далі я звісно перейшов на сторінку плати і почав RTFM. Ось інструкція.

Там в розділі Getting Started знайшов таке:

  1. Перевірте наявність на платі джамперів:JP1 знятий, JP5 (PWR) в позиції U5V, JP6 (IDD) вставлений, CN2 вставлені (NUCLEO). Їх довелось довго шукати, бо всіляких конекторів резисторів та інших деталей на платі трохи є, і вони досить дрібненькі. Але коли я приблизно вивчив їх розташування, виявилось що вже все правильно встановлено.
  2. Для коректної ідентифікації пристрою встановіть драйвери з сайту.Для Linux їх я там не знайшов, тому забив. Але виявилось що й без того мій Linux розпізнав цю плату як диск. На ньому виявився невеликий файл mbed.html, що перенаправляв на https://developer.mbed.org/platforms/ST-Nucleo-F411RE/
  3. Приєднайте плату до комп’ютера за допомогою USB-кабеля type A to mini B. Через USB коннектор CN1. Засвітиться червоні світлодіоди LD3 (PWR) та LD1 (COM). LD1 та зелений світлодіод LD2 повинні мигати. Кабель на щастя знайшовся. Добре мати сусіда-фотографа.
  4. Натисніть кнопку B1 (ту що зліва) і спостерігайте як вона змінює частоту мигання LD2. Вона працює!
  5. Дивіться демо програмки, пишіть свої. Яволь! Заради цього я й відкрив інструкцію.

Далі в інструкції я того як залити програмки не знайшов, погуглив, знайшов хабр. Вони хоч і москалі, але написали непогану невелику інструкцію про те як почати бавитись з Nucleo-F401. Тут приведу її скорочений варіант.

  1. Щоб почати розробляти з mbed.org – треба зареєструватись на сайті mbed за оцим посиланням.
  2. Коли зареєструвались, натискаємо вкладку Platforms, і знаходимо там ST-Nucleo-F411RE.
  3. На сторінці нашої плати справа натискаємо синю кнопку “Add to your mbed compiler”.
  4. Вгорі натискаємо посилання Compiler.
  5. Відкривається симпатичне браузерне IDE. В головному меню натискаємо кнопку “New”.
  6. В вікні нового проекту залишаємо платформу ST-Nucleo-F411RE, вибираємо template “Blinky LED test for the ST Nucleo Boards”, виписуємо собі якесь ім’я програми і натискаємо “OK”.
  7. Створюється проект всередині якого є файл main.cpp, що містить наступний код:
    #include "mbed.h"
    
    DigitalOut myled(LED1);
    
    int main() {
        while(1) {
            myled = 1; // LED is ON
            wait(0.2); // 200 ms
            myled = 0; // LED is OFF
            wait(1.0); // 1 sec
        }
    }
    
  8. Натискаємо кнопку “Compile”. Через деякий час, якщо не сталось ніяких помилок, браузер пропонує нам завантажити файл Nucleo_blink_led_NUCLEO_F411RE.bin, чи з подібною назвою, залежно від того як ви назвали свою програму.
  9. Зберігаємо цей файл прямо в директорію /media/NUCLEO. Так, не треба писати образ ні на які пристрої за допомогою dd, просто скидуємо файл. Червоний світлодіод LD1 (COM) почне мигати зеленим, що означає що дані пишуться.
  10. Коли COM припинить мигати, частота мигання LD2 зміниться, і він перестане реагувати на натискання кнопки B1, а це означає що прошивка змінилась. Ура! Вперше якась мікросхема мигає світлодіодом так як я їй сказав. В директорії /media/NUCLEO ніякого нашого файлу видно не буде, що означає що це таки емуляція диску. Думаю не варто туди якісь інші файли кидати, а то ще не так перепрошиється.

Хоча ні, мигає вона ще не так як я сказав, а так як в прикладі показано. Якщо в нас як пристрій виводу – лише одна лампочка, то крім коду Морзе варіантів мало.

hello world на морзянці виглядає так:
…. . .-.. .-.. — / .– — .-. .-.. -..

Hello world нам моргає

Hello world нам моргає

Прогалик розділяє букви, / – розділяє слова.

Існує такий стандарт:

  1. Довжина крапки – 1
  2. Довжина тире – 3
  3. Відстань між частинами однієї букви – 1
  4. Відстань між окремими буквами – 3
  5. Відстань між словами – 7

Зібравши це все до купи, і так як в прикладі програми було щось схоже на C, і назва файлу main.cpp теж натякає, переклавши все на C, отримаємо таке:

#include "mbed.h"

DigitalOut myled(LED1);

const float DOT_DURATION = 0.5;

void morse(char *code, int len) {
    for(int i = 0; i < len; i++) {
        switch(code[i]) {
            case '-': 
                myled = 1;
                wait(DOT_DURATION * 3);
                break;
            case '.':
                myled = 1;
                wait(DOT_DURATION);
                break;
            case ' ':
                myled = 0;
                wait(DOT_DURATION * 3);
                break;
            case '/': 
                myled = 0;
                wait(DOT_DURATION * 7);
                break;
        }
        myled = 0;
        wait(DOT_DURATION);
    }
};

int main() {
    while(1) {
        morse(".... . .-.. .-.. --- / .-- --- .-. .-.. -..", 43);
        wait(2.0);
    }
}

Ну ось, думаю поки що вистачить. Виявилось набагато простіше ніж я думав. Завтра спробую отримати ввід з вбудованої кнопки, і покерувати зовнішнім світлодіодом, а то вбудовані вже спаяні до мене, і ні про який закон Ома думати не треба. На щастя світлодіоди разом з резисторами і метром проводу для них коштують дешевше ніж поїздка в трамваї, тому дістати їх – нема проблеми. Хоча сама плата в Україні коштує більше ніж 600 грн: http://www.kosmodrom.com.ua/prodlist.php?name=nucleo

Продовження


Filed under: Інструменти, Кодерство, Конспекти Tagged: C++, добре, hardware

Як видалити платні речі з AWS

За січень привалив рахунок на 4 з копійками долари, через те що якісь тестери настворювали в моєму тестовому аккаунті на AWS волюмів і лоад балансерів. А так як це вже не вперше, і мені надоїло перевіряти кожен регіон на наявність вказаних в білінгу пунктів, вирішив написати для цієї справи скрипта. Правда якщо ним захочете користуватись ви – треба ще розширити його інстансами, бакетами і всім іншим за що амазон може здирати бабло.

Дивуюсь чому вони замість повідомлення про перевищення бюджету не зроблять функцію автоматичного вимикання зайвих послуг.

Ах, скрипт:

from boto.ec2.connection import EC2Connection
import boto.ec2.elb

def main():
    ec2 = EC2Connection()
    for region in ec2.get_all_regions():
        print 'Region:', region.name
        process_region(region)

def process_region(r):
    c = r.connect()

    for volume in c.get_all_volumes():
        print '\tVolume:', volume.id
        if volume.attachment_state() == u'attached':
            volume.detach()
        volume.delete()

    c = boto.ec2.elb.connect_to_region(r.name)
    for lb in c.get_all_load_balancers():
        print '\tLoad balancer:', lb

if __name__ == '__main__':
    main()

Filed under: Кодерство Tagged: aws, Python

Додекалендар

Я вирішив стати майстром верстки, CSS3, SVG і всяких інших крутих штук. Для цього вирішив забабахати календар на гранях додекаедра, розгортку якого можна подивитись на моєму гітхабі: http://bunyk.github.io/dodecahedron/

Календар на гранях додекаедра вигідний тим, що це оригінально, бо 3d, а ще ним добре грати футбол чи інші ігри з м’ячем. :)

Так як я на це вбив майже половину вихідних (5 з половиною годин замість трьох запланованих), і вже не маю сил написати рендеринг власне табличок для місяців, бо треба ще вирішити чи залишати текст в тегу <pre>, чи зверстати місяці табличками, то вирішив просто написати про це тут, може хтось хто в веб-дизайні розбирається краще, щось мені порадить і прискорить роботу.

Далі я ще планую зробити кнопочку яка дозволяє змінити рік (аби в 2015 заново не кодити), і кнопочки що дозволяють змінити фонові картинки. Тоді залишатиметься лише роздрукувати на A3 і можна клеїти комусь подарунок до нового року.

Найбільше сил пішло на те, щоб вирішити що React чомусь не хоче рендерити SVG, з D3 доведеться писати море коду, а Angular – саме воно, і треба його трохи підучити. Мені дуже сподобалось, надалі намагатимусь писати на ньому більше.

Розгортка і моделька

Розгортка і моделька з листка A4

А зовсім круті нерди можуть зробити аналогічний календар за допомогою Tikz в \LaTeX.


Filed under: Графіка, Кодерство, Нещоденник, Павутина Tagged: HTML, JavaScript, SVG

Трактат про Zope Component Architecture

Zope – це дуже-дуже старий фреймворк (історія почалася ще з 1995), але деякі його частини, а іноді і сам він використовуються в різних системах і досі. Наприклад Twisted використовує інтерфейси Zope (їх свідчення). Біда з ним в тому, що якась пристойна інструкція в інтернеті не доступна. Може вона й була там колись, але на жаль посилання не завжди працюють, а з такою старовиною як Zope – дуже часто ведуть в тупик 404. Своїм трактатом постараюсь цю біду хоч трохи виправити.

Ах, ще цікавий факт, ZCA з’явилась в Zope 3 (BlueBream), при спробі переписати все “правильно”, ігноруючи зворотню сумісність. Таким чином ситуація трохи нагадує ситуацію з Python 3. Тільки Python 3 з’явився в 2008, і здається таки має деякі шанси вижити, а от Zope 3 (BlueBream) – в 2004, і від нього відросли інші фреймворки, наприклад BFG, який об’єднався з Pylons і став Pyramid. Але цю всі історію дуже цікаво розповідає Пол Еверітт, один з тих хто все це почав. Він пояснить вам що Zope ще не вмерла, вона просто спить:

А тут мова піде лише про таку частинку Zope, як ZCA. І ми будемо писати код. З нуля!

Термінологія

Але почнемо з теорії, аби розуміти що збираємось писати.

  • Zope – Z Object Publishing Environment – фреймворк і веб-сервер які намагались публікувати у вебі об’єкти, ще в ті часи коли Apache віддавав статичний HTML і ганяв CGI скрипти. Шлях в URL в ньому відповідає не шляху до файлу зі скриптом, а шляху в ієрархії об’єктів. Кажуть то був прорив.
  • Компонент (Component) – якийсь код на Python, зазвичай клас, що реалізує інтерфейс. Компоненти поділяються на адаптери та утиліти (див. нижче).
  • Інтерфейс (Interface) – спеціальний клас, єдиною метою якого є опис функціоналу що реалізується іншим класом чи модулем. Вони реєструються в реєстрі компонент, і до цього реєстру можна робити запити “Дайте мені будь-ласка компоненти що реалізують оцей інтерфейс”. Класи можуть декларувати що вони реалізують (implement) певний інтерфейс. Екземпляри цих класів тоді надають (provide) цей же інтерфейс.
  • Сервіс (Service) – це об’єкт що працює з компонентами. Думайте про компоненти як про “речі”, а про сервіс – як про частину коду що бере ці “речі” і робить з ними щось корисне.
  • Реєстр компонентів (Component registry, також Site Manager) – база даних компонентів та інтерфейсів, сервіс за означенням вище. Якщо ви реєструєте компоненти в реєстрі, вони стають доступними для інших користувачів того ж реєстру. Існує глобальний реєстр компонентів що створюється автоматично, і можна використати ZODB як локальний реєстр.
  • ZODB – ZOpe Object Database – база даних об’єктів Zope. Використовувати її з компонентами не обов’язково, тому про неї якось іншим разом.
  • Глобальний реєстр компонентів (global component registry) – сервіс що автоматично створюється коли ваша програма що містить компоненти Zope запускається і наповнюється компонентами що описані в конфігураційних файлах ZCML. До глобального реєстру можна отримати доступ з будь-якого місця програми. Коли програма завершує роботу всі зміни внесені до глобального реєстру зникають і при наступному запуску він заново завантажується з ZCML.
  • Локальні компоненти (Local components) – це компоненти що не створюються в глобальному реєстрі компонентів. Зазвичай їх зберігають в ZODB, що також означає що вони персистентні, тобто можуть пережити перезапуск програми.
  • ZCML (вимовляється “зе-кемел”, Zope Configuration Markup Language) – XML файли, що описують компоненти які потрібно зареєструвати в глобальному реєстрі.
  • Адаптери (Adapter)- це класи що дозволяють використовувати з об’єктом нові інтерфейси. Клас адаптера містить виклик adapts() який вказує інтерфейс що адаптує адаптер, що означає що ви можете передати будь-який об’єкт, що реалізує цей інтерфейс, в метод __init__ класу адаптера, наприклад a = myAdapter(myobject). Тепер MyAdapter бере на себе обов’язок фронт-енда для myobject, таким чином, що будь-який інтерфейс реалізований за допомогою myAdapter, буде правильно працювати з myobject. В певному сенсі адаптер “огортає” адаптований об’єкт.
  • Фабрика (Factory) – це щось (якщо конкретніше, не щось, а утиліта, визначення якої буде нижче), яка створює компоненти та об’єкти. Це як більш високорівнева версія конструктора. Фабрика має бути об’єктом який можна викликати, і повинна реалізувати інтерфейс IFactory. Фабрики надають зручні засоби для доступу до конструкторів компонентів через реєстр компонентів, а не прямим викликом конструктора. Важливо зауважити що ZCM автоматично створює фабрики, коли ви реєструєте компоненти. В багатьох випадках це означає що ви не матимете справи зі створенням фабрики напряму.
  • Утиліта (Utility) – об’єкт який ви хочете додати до реєстру компонентів. Вона може бути будь-яким об’єктом мови Python, який може знадобитись іншій частині програми. Утиліта повинна реалізовувати принаймі один інтерфейс.

Я знаю що ви з цього словника майже нічого не зрозуміли. Не бійтесь, я теж. Далі ми розберемо це на практиці, і ситуація проясниться.
Read more »

Як я отримав швейцарський “диплом”

З відзнакою. Ось як він виглядає. Власне це не зовсім диплом, бо просто показує що я всього лиш завершив курс який тривав сім тижнів, і не підтверджує того факту що завдання робив я. І не зовсім швейцарський, бо Cousera – американська компанія.

Але важливо те, що я пройшов курс функціонального програмування на Scala, який:

  • Базується на SICP.
  • Мову Scala викладає творець мови Scala. І він не тільки багато знає, він ще й вміє це доступно пояснити.
  • Мартін Одерськи – викладач Фередальної політехнічної школи Лузани – одному з двох політехнічних університетів Швейцарії. В іншому, Федеральній вищій технічній школі в Цюріху він в 89-тому отримав PhD, під керівництвом не аби кого, а Ніклауса Вірта. Який створив мову Паскаль – найвідомішу широкому загалу.
  • Задачі настільки добре покриті автоматичними тестами, що можна суто завдяки їм знайти в себе помилку, навіть не звертаючись до форумів. Форуми теж чудові, я двічі застрявав і двічі підказка знаходилась саме на форумі. (Що не означає що вам там викладуть готове рішення).

Ну і найголовніше – що я таки хоч один пройшов. Бо до того записувався на NLP, логіку, криптографію, гейміфікацію, і так і не набрав на жодному з них більше 5%. На цьому ж – 97.5%. Треба було показати собі що це простіше ніж здається, головне кілька місяців зберігати мотивацію, чи просто раз на тиждень застосовувати силу волі і садити себе за комп’ютер.

Крім того, я збираюсь колись написати книжку про те як бути кращим студентом, в тому числі і як використовувати наявні можливості MOOC, а це буде якось дивно, коли поганий студент пише про те як бути гарним. Тому мушу потрохи виправляти ситуацію.

Третя мотивація – я хочу записатись на курс FRP. Що таке FRP – дивіться “Александр Соловьев — Functional Reactive Programming & ClojureScript “. Надихаюча доповідь яку можна розтягувати на цитати.

Як виявилось для успіху потрібно було робити те, що я майже від 8-го класу ніколи не робив – домашні завдання. І здавати їх вчасно, бо за кожну добу спізнення знімають 20% балів. Через це я набрав не 100%. Звідси висновок – не варто здавати лаби в останній момент, бо може ще якась помилка вилізе.

Фото з лекції

Фото з лекції

Коли в університеті я дивився на викладача який звичайною крейдою пише по звичайній дошці і записував це все в цифровий файл, то в цьому випадку я дивився на цифрового викладача, який пише електронним пером по слайдах (набагато зручніше ніж MIT OCW, де вони просто живу лекцію з крейдою знімають на відео, хоча й зробити напевне набагато дорожче), і при цьому записував все звичайною ручкою в звичайний зошит. Хоча, потім оцифрував цей конспект, так як паперові постійно губляться, і зручніше шукати щось в Google ніж в шафі.

Коротше кажучи моя подяка професору Одерськи:

Great introductory course on functional programming, great tasks, and great lectures. Will also inroll into your reactive programming couse. Keep going!


Filed under: Кодерство, Нещоденник Tagged: добре, освіта

Вступ до D3

D3 (розшифровується як DDD, що означає Data Driven Documents) – то бібліотека для написання JavaScript візуалізацій.

Бібліотеку можна скачати з сайту, або під’єднатись до CDN:

<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>

Тепер, щоб змінити наприклад текст якогось елемента, можна за допомогою d3 цей елемент вибрати, і відредагувати його текст:

d3.select('#field').text('hello world!')

Метод select приймає такі самі селектори CSS як і jQuery, тому тут нічого несподіваного для тих хто користувався jQuery (чи CSS) не повинно бути.

Можна також додавати елементи:

d3.select('body').append('p').text('hello world!')

Можна змінювати оформлення елементів:

d3.select('body')
   .append('p')
   .text('hello world!')
   .style('color', 'red')

Цих маніпуляцій з елементами вже досить щоб малювати щось з SVG:

var panel = d3.select('body');
var width = panel[0][0].clientWidth - 2;
var height = panel[0][0].clientHeight - 2;
var svg = panel.append('svg')
    .attr('width', width)
    .attr('height', height)
    .style('border', 'solid black 1px');

var circle = svg.append('circle')
    .attr('cx', width / 2)
    .attr('cy', height / 2)
    .attr('r', height / 2 - 1);

Тепер давайте додамо ще трішки кіл, і подивимось на відмінність між select та selectAll. Перший метод повертає лише перший знайдений елемент, а другий – всі.

for(var i = 0; i <= 10; i++) {
    svg.append('circle')
        .attr('r', 10)
        .attr('cy', height / 2);
};

var circles = svg.selectAll('circle');

Тепер ми можемо задати атрибут всім колам зразу. А можемо сказати що атрибут кожного кола повинен бути результатом обчислення функції. І передати замість значення – лямбду. Наприклад можна змусити наші кола скакати туди-сюди через певний інтервал:

setInterval(function() {
    circles.attr('cx', function() { return Math.random() * width });
}, 100);

Але випадкові функції то не цікаво. Давайте займемось чимось серйозним, і намалюємо графік функції. Для цього функцію треба буде кілька разів обчислити на певному проміжку:

var tabulate_function = function(f, a, b, count) {
    var f_data = [];
    var width = b - a;
    for(var i=0; i < count; i++) {
        f_data.push(f(a + i * width / count));
    };
    return f_data;
};

Передавши в функцію tabulate_function, функцію для табулювання, інтервал a, b, та кількість обчислень, ми отримуємо масив з даними:

var BARS_COUNT = 100;
var data = tabulate_function(Math.sqrt, 0, 10, BARS_COUNT);

Тепер, за допомогою методу data ми можемо прив’язати наші дані до вибірки з прямокутників. А також задати висоту прямокутника як функцію від даних, а його позицію – як функцію від номера елементу (і даних, хоча тут не використовуватимемо):

var bars = svg.selectAll('rectangle').data(data); // Прив’язуємо до вибірки з прямокутників
bars.enter().append('rect'); // А що якщо прямокутників нема (не вистачає)? Тоді додаємо прямокутник.

var bar_width = width / BARS_COUNT;

bars
    .attr('y', function(d) { return height - d * 100 }) // Позиція по осі Y як і висота функції від даних
    .attr('x', function(d, i) { return i * bar_width }) // Позиція по осі X - функція від номера елементу даних.
    .attr('width', bar_width)
    .attr('height', function(d) { return d * 100 });

Має вийти щось схоже на оце: sqrt. Якщо не вийшло – подивіться в чому відмінність вашого і мого коду.

Мені й самому дивно, для чого так незвично описувати залежність між даними й елементами. Але тут основна фішка в тому що ми можемо передати нашому зображенню нові дані, а воно не буде видаляти всі елементи і створювати їх заново, а змінить атрибути тих елементів які треба змінити, додасть нових елементів якщо їх бракує і видалить елементи які стали зайвими.

Щоб вони видалялись, не забудьте написати:

bars.exit().remove();

Тепер про оновлення. Хотілось би просто написати bars.data(new_data), але таке чомусь не працює. Тому треба заново знайти всі елементи, прив’язати до них дані і сказати їм як на ці дані реагувати.

В такому випадку, я виношу це все в функцію update:

var update_graph = function(data) {
    var bar_width = width / data.length;
    var bars = svg.selectAll('rect').data(data);

    bars.enter().append('rect');

    bars
      .attr('x', function(d, i) { return i * bar_width })
      .attr('width', bar_width)
      .transition().duration(2000) // Наступні атрибути змінювати плавно, за 2 секунди
      .attr('y', function(d) { return height - d * 100 })
      .attr('height', function(d) { return d * 100 });
    
    bars.exit().remove();  
};

І тоді, коли ми викличемо цю функцію кілька разів з різними даними – картинка буде плавно змінюватись, не перестворюючи надто багато елементів. А якщо видалити виклик transition().duration() – то буде змінюватись миттєво. Можна подивитись тут.

І на цьому напевне завершу мою розповідь, а то вона щось виходить нуднішою ніж я сподівався. А d3 не нудний, на ньому не тільки графіки можна малювати, а й наприклад прості іграшки.

Посилання

  1. JSFiddle – спонсор даної публікації. :) Всім рекомендую користуватись під час читання різноманітних підручників з веб дизайну.
  2. Scott Murray – Learning d3 (youtube)
  3. Mike Bostock – Three Little Circles
  4. Mike Bostock – Thinking With Joins

Filed under: Графіка, Кодерство, Павутина Tagged: JavaScript

Німецьке QWERTY

Німці використовують деякі букви, яких нема в стандартній латинській розкладці: ÄÖÜẞ, тому існує окрема німецька розкладка. Але біда, біда, вона не QWERTY, а QWERTZ, і Z та Y поміняні місцями. Правильної розкладки чомусь нема, тому я вирішив зробити свою. Має працювати на всіх системах що використовують X keyboard extension з X Window System.

Замість кнопки “-” отримуємо “ß”, замість “[” – “Ü”, “;” – “Ö” ну а замість “‘” – “Ä”. Всі інші залишаються на місці, а не перескакують чорт зна куди як в традиційній німецькій розкладці.

Відкриваємо розкладки для Німеччини:

cd /usr/share/X11/xkb/
sudo vim symbols/de

Додаємо розкладку з наступними клавішами (наслідується від базової американської):

xkb_symbols "germanqwerty" {
    include "us(basic)"
    name[Group1]="German (QWERTY)";

    key <AD11>	{ [udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] };
    key <AC10>	{ [odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] };
    key <AC11>	{ [adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] };
    key <AE11> {type[Group1]="FOUR_LEVEL_PLUS_LOCK",  symbols[Group1]=
                  [ssharp, question, backslash, questiondown, 0x1001E9E ]};
};

Далі додаємо нову розкладку до списку відомих:

cd /usr/share/X11/xkb/
sudo vim rules/evdev.xml

Знаходимо список розкладок для Німеччини і додаємо туди свій варіант:

        <variant>
          <configItem>
            <name>germanqwerty</name>
            <description>German (QWERTY)</description>
          </configItem>
        </variant>

Далі треба розлогінитись і залогінитись заново, і можна додавати розкладки через аплет панелі робочого стола.

Посилання


Filed under: Кодерство, Конспекти Tagged: deutsch, linux