Обновить

Комплексная модель производительности и зрелости (CMMI — Capability Maturity Model Integration)

Краткое описание из википедии


Capability Maturity Model Integration (CMMI) — набор моделей (методологий) совершенствования процессов в организациях разных размеров и видов деятельности. CMMI содержит набор рекомендаций в виде практик, реализация которых, по мнению разработчиков модели, позволяет реализовать цели, необходимые для полной реализации определенных областей деятельности.

Набор моделей CMMI включает три модели: CMMI for Development (CMMI-DEV), CMMI for Services (CMMI-SVC) и CMMI for Acquisition (CMMI-ACQ). Наиболее известной является модель CMMI for Development, ориентированная на организации, занимающиеся разработкой программного обеспечения, аппаратного обеспечения, а также комплексных систем. Все действующие версии моделей имеют номер 1.2. Модель CMMI-DEV была опубликована в августе 2006 года, CMMI-ACQ — в ноябре 2007-го, CMMI-SVC — в феврале 2009-го.

CMMI является развитием методологии CMM, которая разрабатывалась со второй половины 1980-х годов Software Engineering Institute (SEI) в университете Карнеги-Меллона (Carnegie Mellon University).

А теперь подробнее…
Читать дальше →

TorrentFlux+cyrillic encoding – выходим из положения

Пользователям TorrentFlux (http://www.torrentflux.com/) приходилось сталкиватся с тем, что при скачивании .torrent-файлов, которые содержали в себе названия файлов и папок кириллицей, с неправильным отображением кодировки при старте загрузки, а также при создании torrentflux этих папок и файлов на разделе жесткого диска. Но ситуацию возможно исправить, внеся несколько изменений в исходный код.
Для начала, займемся фронт-эндом (собственно torrentflux), для приемлемого отображения кириллицы.
Для корректного отображения достаточно строки:
define("_CHARSET","windows-1251");

в файле /language/lang-russian.php и нескольких правок в файле metaInfo.php, а именно:
заменим
$this->name на iconv(«UTF-8»,«WINDOWS-1251»,$this->name)

в строке
echo(«d.add(».$this->num.",".$parent.",\"".$this->name."\",".$this->prio.",0);\n")

и
$v->name

на
iconv("UTF-8","WINDOWS-1251",$v->name)

в строке
echo("d.add(".$v->num.",".$this->num.",\"".$v->name."\",".$v->prio.",".$v->size.");\n");

После чего в строке
echo htmlentities($btmeta['info']['name'].$torrent_size." (".formatBytesToKBMGGB($torrent_size).")", ENT_QUOTES);

заменяем
htmlentities($btmeta['info']['name'].$torrent_size

на
htmlspecialchars(iconv("UTF-8","WINDOWS-1251",$btmeta['info']['name']).$torrent_size <br/>

И, наконец, в строке
echo "<tr><td>Directory Name:</td><td>".htmlentities($btmeta['info']['name'], ENT_QUOTES)."</td></tr>"; <br/>

заменяем
htmlentities($btmeta['info']['name'] <br/>

на
htmlspecialchars(iconv("UTF-8","WINDOWS-1251",$btmeta['info']['name']) <br/>

Так, как bittornado создает названия файлов и каталогов в кодировке utf-8, внесем несколько изменений в исходный код для создания файловой структуры в нужной нам кодировке.
Проверяем наличие нужной локали:
#locale –a | grep koi8-r
Для того, чтобы сгенерировать файлы локали, нужно добавить строку:
ru_RU KOI8-R
в файл /etc/locale.gen (в качестве дистрибутива используется Gentoo Linux) и выполнить команду:
#locale-gen
Текущую локаль можно не изменять, достаточно того, чтобы были сгенерированы файлы нужной локали.
Открываем файл TF_BitTornado/BitTornado/download_bt1.py, добавляем в конце строки:
f = path.split(f)[ 0] <br/>

строку
decode('utf-8').encode('koi8-r') <br/>

В результате чего получим строку:
f = path.split(f)[ 0].decode('utf-8').encode('koi8-r') <br/>

Затем, перед строкой:
if f != '' and not path.exists(f): <br/>

вставляем строку:
if forcedir: f = f.decode('utf-8').encode('koi8-r') <br/>

Открываем файл TF_BitTornado/BitTornado/BT1/Storage.py, ищем строку:
file, length = files[i] <br/>

и заменяем ее на строки:
utf_file, length = files[i]<br/>file = utf_file.decode('utf-8').encode('koi8-r') <br/>


После этого Torrentflux будет нормально работать с кириллическими кодировками.
Видоизмененные файлы находятся тут: http://dl.dropbox.com/u/3248658/tf_modified.tar.gz

Оптимизация «ORDER BY RAND() LIMIT 1» — не абсолют, но намного проще

Недавно был впечатлён размышлениями людей на тему оптимизации выборки произвольной записи из таблицы MySQL.

Конечно, выполненная работа впечатляет, но оправданы-ли такие трудозатраты на написание многострочного кода одним человеком, а затем, возможно, попытки понять его другим, причём часто без комментариев автора?

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

Поэтому хочу предложить простейшую альтернативу оптимизации запроса "… ORDER BY RAND() LIMIT 1;" вставкой в код условия «WHERE RAND()>0.9».

Вот результаты теста (взято две таблицы, каждый запрос выполнялся по два раза, результаты не кешировались):

таблица jos_squeezimages, 12804 записей, два поля: id (INT(11)) и fullname (VARCHAR(255))

SELECT fullname FROM `jos_squeezimages` ORDER BY RAND() LIMIT 1;
запрос выполнялся 0,0324 сек первый раз и 0,0317 сек второй раз

SELECT fullname FROM `jos_squeezimages` WHERE RAND()>0.9 ORDER BY RAND() LIMIT 1;
0,0130 секунды, 0,0134 секунды

SELECT fullname FROM `jos_squeezimages` WHERE RAND()>0.999 ORDER BY RAND() LIMIT 1;
0,0112 секунды, 0,0111 секунды

таблица t_tovars, 20212 записей, 25 полей, по большей части varchar
SELECT * FROM `t_tovars` ORDER BY RAND() LIMIT 1;
0,1717 секунды, 0,1816 секунды

SELECT * FROM `t_tovars` WHERE RAND()>0.9 ORDER BY RAND() LIMIT 1;
0,0735 секунды, 0,0642 секунды

SELECT * FROM `t_tovars` WHERE RAND()>0.999 ORDER BY RAND() LIMIT 1;
0,0455 секунды, 0,0447 секунды

Вуаля!
Добавить условие в запрос очень просто, и времени на оптимизацию ушло немного, а скорость увеличилась в три раза.

А главное — не надо много думать :)

Ruby Enterprise Edition, Nginx и заморозка

Затюнинговал я свой web-сервер, чтобы летал побыстрей. Для этого перенес MYSQL в tmpfs с синхронизацией на диск каждые 10 минут, наложил на него патчи от гугла, поставил в роли фронтэнда nginx, приделал к wordpress’у плагины кэширования. Радость то какая! Стал мой сервачок гораздо шустрее. Счастью не было предела. Но продолжалось, как всегда, не долго…

PHP – это отлично, но есть еще проектики, которые на Ruby On Rails крутятся у меня. Стоял Passanger, прикрученный к apache. Но из-за жутко медленной работы и граблей с одновременной работой в связке с PHP я его отключил, чтобы нервы не портил. Отложил до «хорошего настроения». И вот пришла муза.

Нашел отличную статейку на хабре и понеслась… Поставил Enterprise-версию рельсов, пассажира прикрутил. Nginx удалил, который до этого ставился из репозитория debian. Перенес нужные мне строчки из старого конфига в /opt/nginx/conf/nginx.conf. Замечательно! Теперь PHP и RoR дружат и все работает как надо (читайте, «летает»). Но, как всегда, вылез трабл. Не будь надобности запустить Redmine, я бы и не заметил. Проблемы были две. Вторая выявилась благодаря первой.
  • Redmine работает только с Rails 2.2.2 и не выше. А у меня стоит 2.3.5 (зачем нам барахло?)
  • gem install ставил пакеты в места, которые были определены до этого старыми дебиановскими скриптами, так как до этого описываемый софт ставился из репозитариев Debian.

Теперь по порядку. Трабл №1. Я подумал:»Заморожу версию рельсов с помощью команды rake rails:freeze:gems». Откатываю rails до нужной версии, захожу в директорию Redmine’а, замораживаю. Но копируются либы свежей версии рельсов. Выяснилось, что в /opt/ruby-enterprise/ рельсы не откатились. Вот и Трабл №2…

Замечу, что в статье, по которой все настраивал, сделаны симлинки в директорию /usr/bin/ из /opt/ruby-enterprise/bin/

Обе проблемы решил. Сначала вторую, чтобы все нужные бинарники и либы находились системой там, где нужно (/opt/ruby-enterprise/), потом первую, чтобы заморозить Redmine. Что я сделал:

aptitude purge rubygems rails, ruby
Удаляем пакеты, что ставились не из исходников

rm -f /usr/bin/gem /usr/bin/rails /usr/bin/ruby /usr/bin/rake
Удаляем симлинки, которые создавали

export PATH=/opt/ruby-enterprise/bin:$PATH
Говорим, где искать все это удаленное добро

gem uninstall rails -v=2.3.5
Удаляем старые рельсы. Вам может и не понадобится. У меня стояли обе версии (думается, что из-за MultiRails ). Как сказать фризу, чтобы он страую себе копировал, я не нашел.

gem install rails -v=2.2.2
Ставим старичка

cd /var/www/redmine/
rake rails:freeze:gems
gem uninstall rails -v=2.2.2
gem install rails

Перешли в директорию проекта, заморозили, удалили старичка, поставили свежачек

Все работает! Может кому пригодится.

Использованный материал:
Установка nginx и Ruby Enterprise
http://habrahabr.ru/blogs/ror/64295/
Заморозка проектов на RoR
http://www.softiesonrails.com/2008/1/3/freezing-your-rails-application
Решение с export PATH и удалением пакетов с симлинками
/dev/my_mind

Пишем оболочку для управления маршрутизатором ASUS WL-520GU.

Здравствуйте, уже как два года являюсь счастливым обладателем домашнего маршрутизатора фирмы ASUS, куплен он был потому как в семье начали появляться ноутбуки а провода это очень не удобно хотя быстро и безопасно. Перепрошивался аппарат только двумя прошивками это DD-WRT и OLEG firmware ставил я их для того что бы быть в курсе и может быть заменить оригинальную прошивку, но выбор пал на последнюю а проблема банальна настройка принтера легче и быстрее на оригинальной прошивке нежили на DD-WRT или OLEG, принтер у меня оказался очень капризный зовут его HP Deskjet D1300 настройка через RAW метод не удалась а LPR сервера на последних прошивках (DD-WRT) не было. И так девайс был прошит официальной прошивкой версии 3.0.0.8 дизайн в ней на много лучше чем у DD-WRT и OLEG но и она оказалась не без проблем подглючивает определение рабочих станции в прошивке 3.1.0.9 вроде бы убрали этот глюк

image

Так же тут нет теленета для удаленного управления. Скажите почему не обновил до последней беты, ответ прост лень которая управляется не хваткой времени. По умолчанию шифрование локальной сети было выставлено на Open system и тому есть причина, первая и основная причина фанатичные друзья линуксоиды у которых на то время были проблемы с установкой беспроводной сети, вторая причина это то что шифрование забирает часть полосы для пакетов безопасности по внутреннему убеждению я не хотел терять 10% производительности да и кто в маленьком городе будет воровать Wi Fi многие и интернета не видели но это было на тот момент. Спустя год я заметил визитеров в моей сети, часто замечал падение скорости интернета, снифер показал что качали с файловых обменников, акт вторжения быстро и жестоко пресекался :). Случаи вторжения были не частыми и узнавал я о них совсем случайно без обновления все станции что были подключены показывались в настройках так как лазить на маршрутизатор было не удобно я подумал о такой утилите которая управляет всем добром быстро и удобно а именно меня интересовали такие функции:

1. Просмотр клиентов подключенных к сети по Wi-Fi
2. Перезагрузка маршрутизатора
3. Смена IP адреса по возможности без перезагрузки

Хотелось не темного экрана а много кнопочек и что бы не пришлось устанавливать библиотеки размером 100 мегабайт, ноутбук то у меня слабый. И был еще один нюанс на ADSL модеме Callisto 821+ сгорели кондеры и теперь при выключение света он намертво вис помогал только сброс до заводских настроек пока электрики не выключали еще раз свет, раньше для быстрой смены IP я переводил модем в режим Роутера и скриптом быстро менял адрес, но когда появилась проблема с кондерами настраивать маршрутизатор оказалось накладно и нудно и так я стал жить без смены быстрого IP. Время шло и наконец прорвало, твердо решив довести все дело до конца я поспрашивал у Гугла что это и как реализовать нашел очень мало информации из этих крупиц я понял что писать придется на Delphi используя библиотеку Indi в которой я не очень разбирался, и еще проблема была в исходных кодах их нельзя было найти без проблем, на одном форуме добыл исходник регера почтовых ящиков, посмотрев на код понял что там полная жопа, в понимании библиотеки я знал что мне поможет книга а вот как быть с запросами GET и POST я не знал. После долгих поисков установил в Firefox два плагина Live Http Headers и Firebug и понял с индии все туго потому как нашел я конструктор программ под названием Hiasm

image

Для достижение цели тут нужно два компонента плюс запрос, да многие скажу что это не есть хорошо ламеризм и.т.д. но хочу не согласиться главное выбирать правильный инструмент к тому же программы на Hiasm имеют маленький размер что очень радует. После выбора инструмента взор пал на форум и его файлообменник быстро были найдены пару примеров, самый яркий из них это наверное выдирание ссылок из депозит-файлс =). С начала хотелось написать полноценную оболочку ну что бы вообще забыть за маршрутизатор но эта идея быстро отвалилась потому как долго это все будет происходить, решил выделить пару пунктов которые озвучены в верху. Самое интересно это запросы, ну вот например:

GET / HTTP/1.1
Host: 192.168.2.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; uk; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.2 YB/3.5.1 (.NET CLR 2.0.50727)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Authorization: Basic 9/LuIPXu9+X4/CDz5+3g8vwg7O7pIO/g8O7r/Dr18+kg8uXh5Q==

Для посылки запроса хватит первой(GET / HTTP/1.1) второй(Host: 192.168.2.1) и последней строчки, 9/LuIPXu9+X4/CDz5+3g8vwg7O7pIO/g8O7r/Dr18+kg8uXh5Q== непонятные символы это логин и пароль закодированные по алгоритму base64 но тут есть подводный камень этот запрос останется без ответа сервера если в конце запроса не вставить пустую строку, так делаются почти все GET запросы в двух случаях параметры передаются прямо в запросе в случае с перезагрузкой соединения WAN первая строка будет похожа на вот это GET /device-map/wan_action.asp?wanaction=Disconnect HTTP/1.1. Остальные запросы которые будут изменять разные настройки будут посылаться POST запросами эти запросы не намного отличаются в нашем случае их нужно правильно составить а именно не пропустить пустую строку только она теперь находится не в конце запроса а отделяет заголовок от тела запроса например вот так:

POST /start_apply.htm HTTP/1.1
Host: 192.168.2.1
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; uk; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.2 YB/3.5.1 (.NET CLR 2.0.50727)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: 192.168.2.1/device-map/clients.asp
Authorization: Basic 9/LuIPXu9+X4/CDz5+3g8vwg7O7pIO/g8O7r/Dr18+kg8uXh5Q==
Content-Type: application/x-www-form-urlencoded
Content-Length: 174

sid_list=LANHostConfig%3B&group_id=&action_mode=&action_script=networkmap_refresh¤t_page=%2Fdevice-map%2Fclients.asp&next_page=%2Fdevice-map%2Fclients.asp&flag=nodetect

В этом запросе нужно обратить внимание на Content-Length: 174 после этого блока идет разделитель и переменные которые мы передаем разделяются они знаком &, можно передавать не всю стопку а только маленькую часть но при этом нужно изменить Content-Length на число равное количеству букв в теле запроса в нашем случае их 174. Собственно этой простой техникой делаются регеры мыл и разные программы такого рода. Что бы не превращать эту статью в занудную статью предлагаю посмотреть исходный код программы по это му адресу www.wuala.com/Hort/Soft/WWW/520GU в архиве лежат исполняемый файл, ини-файл (в нем пропишите логин пароль и адрес маршрутизатора) и сам исходный код или схема так будет точнее звучать. Для компиляции схемы понадобится сам Hiasm и желательно компилятор Delphi который лежит по ссылке выше но стандартный фрипаскаль идущий в комплекте тоже будет работать =) но весить на 10% больше. Эту схему можно переделать и под другой тип маршрутизатора хотя глядя на нее можно запутаться

image

Программку малость глючит в плане обновления данных но кнопка обновить должна избавить вас от проблем =), ну если не исправит можете с этим мирится. В данном случае программа умеет выводить список подключенных ПК, выключать соединение с модемом (менять IP пез перезагрузки), перезагружать девайс, показывает и копирует в буфер обмена WAN IP, показывает принтер его можно тоже включать и выключать правда в прошивке глюк который не дает произвести эту операцию. Не откажусь от инвайта если кому понравилась эта статья.

PyQt4 — простейшее рисование

Отрисовка текста


#!/usr/bin/python

# drawtext.py

import sys
from PyQt4 import QtGui, QtCore

class DrawText(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)

self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Draw Text')

self.text = u'Hello from Python'

def paintEvent(self, event):
paint = QtGui.QPainter()
paint.begin(self)
paint.setPen(QtGui.QColor(168, 34, 3))
paint.setFont(QtGui.QFont('Decorative', 10))
paint.drawText(event.rect(), QtCore.Qt.AlignCenter, self.text)
paint.end()

app = QtGui.QApplication(sys.argv)
dt = DrawText()
dt.show()
app.exec_()


Текст выровнен по вертикали и горизонтали.

def paintEvent(self, event):
Для прорисовки создали функцию

paint = QtGui.QPainter()
paint.begin(self)
...
paint.end()

Класс QPainter отвечает за всю прорисовку. Все рисование должно быть между методами begin() и end().

paint.setPen(QtGui.QColor(168, 34, 3))
paint.setFont(QtGui.QFont('Decorative', 10))

Здесь мы определяем тип пера и шрифт, который мы используем, чтобы сделать текст.

paint.drawText(event.rect(), QtCore.Qt.AlignCenter, self.text)
Метод drawText() рисует текст в окне
image

Рисование точек


#!/usr/bin/python

# points.py

import sys, random
from PyQt4 import QtGui, QtCore

class Points(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)

self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Points')

def paintEvent(self, event):
paint = QtGui.QPainter()
paint.begin(self)
paint.setPen(QtCore.Qt.red)
size = self.size()
for i in range(1000):
x = random.randint(1, size.width()-1)
y = random.randint(1, size.height()-1)
paint.drawPoint(x, y)
paint.end()

app = QtGui.QApplication(sys.argv)
dt = Points()
dt.show()
app.exec_()

В нашем примере мы рисуем случайно 1000 красных точек.

paint.setPen(QtCore.Qt.red)
Устанавливаем перо в красный цвет

size = self.size()
Генерируется каждый раз, когда мы изменяем размер окна

paint.drawPoint(x, y)
Рисуем точки методом drawPoint()
image

Цвета


Цвета мы можем задать в виде значения RGB (в диапозоне от 0 до 255), в шестнадцатеричной системе, ну или же в RGBA (red, green, blue, alpha). Значение alpha 255 определяет полную не прозрачность, 0 для полной прозрачности.

#!/usr/bin/python

# colors.py

import sys, random
from PyQt4 import QtGui, QtCore

class Colors(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)

self.setGeometry(300, 300, 350, 280)
self.setWindowTitle('Colors')

def paintEvent(self, event):
paint = QtGui.QPainter()
paint.begin(self)

color = QtGui.QColor(0, 0, 0)
color.setNamedColor('#d4d4d4')
paint.setPen(color)

paint.setBrush(QtGui.QColor(255, 0, 0, 80))
paint.drawRect(10, 15, 90, 60)

paint.setBrush(QtGui.QColor(255, 0, 0, 160))
paint.drawRect(130, 15, 90, 60)

paint.setBrush(QtGui.QColor(255, 0, 0, 255))
paint.drawRect(250, 15, 90, 60)

paint.setBrush(QtGui.QColor(10, 163, 2, 55))
paint.drawRect(10, 105, 90, 60)

paint.setBrush(QtGui.QColor(160, 100, 0, 255))
paint.drawRect(130, 105, 90, 60)

paint.setBrush(QtGui.QColor(60, 100, 60, 255))
paint.drawRect(250, 105, 90, 60)

paint.setBrush(QtGui.QColor(50, 50, 50, 255))
paint.drawRect(10, 195, 90, 60)

paint.setBrush(QtGui.QColor(50, 150, 50, 255))
paint.drawRect(130, 195, 90, 60)

paint.setBrush(QtGui.QColor(223, 135, 19, 255))
paint.drawRect(250, 195, 90, 60)

paint.end()

app = QtGui.QApplication(sys.argv)
dt = Colors()
dt.show()
app.exec_()


image

color = QtGui.QColor(0, 0, 0)
color.setNamedColor('#d4d4d4')

Здесь мы определяем цвет, используя шестнадцатеричное представление

paint.setBrush(QtGui.QColor(255, 0, 0, 80));
paint.drawRect(10, 15, 90, 60)

Здесь определяем кисть, и рисуем прямоугольник. Метод drawRect () рисует прямоугольник, первые два параметра координаты X и Y, третий и четвертый — ширина и высота.

Линии


QPen — элементарный графический объект, который используется для рисования линий, кривых и контуров, элипсов, многоугольников и многих других фигур.

#!/usr/bin/python

# penstyles.py

import sys
from PyQt4 import QtGui, QtCore

class PenStyles(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)

self.setGeometry(300, 300, 280, 270)
self.setWindowTitle('penstyles')

def paintEvent(self, event):
paint = QtGui.QPainter()

paint.begin(self)

pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine)

paint.setPen(pen)
paint.drawLine(20, 40, 250, 40)

pen.setStyle(QtCore.Qt.DashLine)
paint.setPen(pen)
paint.drawLine(20, 80, 250, 80)

pen.setStyle(QtCore.Qt.DashDotLine)
paint.setPen(pen)
paint.drawLine(20, 120, 250, 120)

pen.setStyle(QtCore.Qt.DotLine)
paint.setPen(pen)
paint.drawLine(20, 160, 250, 160)

pen.setStyle(QtCore.Qt.DashDotDotLine)
paint.setPen(pen)
paint.drawLine(20, 200, 250, 200)

pen.setStyle(QtCore.Qt.CustomDashLine)
pen.setDashPattern([1, 4, 5, 4])
paint.setPen(pen)
paint.drawLine(20, 240, 250, 240)

paint.end()

app = QtGui.QApplication(sys.argv)
dt = PenStyles()
dt.show()
app.exec_()


В этом примере мы рисуем шесть линий. Линии проведены в шести различных стилях.

pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine)
Создали QPen объект, цвет черный, толщина 2, QtCore.Qt.SolidLine является одним из предопределенных стилей пера.

pen.setStyle(QtCore.Qt.CustomDashLine)
pen.setDashPattern([1, 4, 5, 4])
paint.setPen(pen)

Здесь мы определяем пользовательский стиль пера. Список цифр определяет стиль пера. В нашем примере. Чем больше число тем больше пространство или тире. У нас: 1px заполнено, 4px пустота, 5px заполнено, 4px пустота, и т.д.
image

QBrush


QBrush – элементарный графический объект. Используется для закраски фона графических фигур, таких как прямоугольники, эллипсы, многоугольники. Кисть может быть трех типов.

#!/usr/bin/python

# brushes.py

import sys
from PyQt4 import QtGui, QtCore

class Brushes(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)

self.setGeometry(300, 300, 355, 280)
self.setWindowTitle('Brushes')

def paintEvent(self, event):
paint = QtGui.QPainter()

paint.begin(self)

brush = QtGui.QBrush(QtCore.Qt.SolidPattern)
paint.setBrush(brush)
paint.drawRect(10, 15, 90, 60)

brush.setStyle(QtCore.Qt.Dense1Pattern)
paint.setBrush(brush)
paint.drawRect(130, 15, 90, 60)

brush.setStyle(QtCore.Qt.Dense2Pattern)
paint.setBrush(brush)
paint.drawRect(250, 15, 90, 60)

brush.setStyle(QtCore.Qt.Dense3Pattern)
paint.setBrush(brush)
paint.drawRect(10, 105, 90, 60)

brush.setStyle(QtCore.Qt.DiagCrossPattern)
paint.setBrush(brush)
paint.drawRect(10, 105, 90, 60)

brush.setStyle(QtCore.Qt.Dense5Pattern)
paint.setBrush(brush)
paint.drawRect(130, 105, 90, 60)

brush.setStyle(QtCore.Qt.Dense6Pattern)
paint.setBrush(brush)
paint.drawRect(250, 105, 90, 60)

brush.setStyle(QtCore.Qt.HorPattern)
paint.setBrush(brush)
paint.drawRect(10, 195, 90, 60)

brush.setStyle(QtCore.Qt.VerPattern)
paint.setBrush(brush)
paint.drawRect(130, 195, 90, 60)

brush.setStyle(QtCore.Qt.BDiagPattern)
paint.setBrush(brush)
paint.drawRect(250, 195, 90, 60)

paint.end()

app = QtGui.QApplication(sys.argv)
dt = Brushes()
dt.show()
app.exec_()

В нашем примере мы рисуем 6 различных прямоугольников.

brush = QtGui.QBrush(QtCore.Qt.SolidPattern)
paint.setBrush(brush)
paint.drawRect(10, 15, 90, 60)


Определяем тип кисти, и рисуем прямоугольник, с помощью метода drawRect()
image

Антиспам для Skype

Некоторое время назад случилось так, что пользоваться скайпом стало практически невозможно — спам-боты стучались один за другим. Неприятным фактом стало то, что в клиенте нет (до сих пор, впрочем) никакой предусмотренной функции антиспама, вроде контрольного вопроса или ещё чего-нибудь.

Нет — будет. На сайте обнаружился какой-никакой, а ассортимент wrapper'ов к API. Выбор пал на Python, ибо ничего масштабного не требовалось, а «import antigravity» только радовало. В процессе отладки скрипта было замечено несколько косяков в API. Оные были заботливо подпёрты костылями. Итак:

import Skype4Py
from time import sleep
skype = Skype4Py.Skype()
TRYING = 1
TEXT = {
¬'QUESTION':"Hello. It's antispam bot. Answer, 2+2=? One figure, please. You have %i trying." % (TRYING),
¬'ANSWER':"4",
¬'WIN':"Right. I'll write you soon.",
¬'AGAIN':"Try one more time.",
¬'FAIL':"Autoignoring.",
¬'INSTANT_BAN':"Autoignoring due to banned word in the authorization request or in the name."
}
BANNED = {
¬'WORDS':("http", "www"),
¬'NAMES':("")
}
HIDE_MESSAGES_AFTER_WRONG_ANSWER = True # True may cause loss of the new answers
REFRESH_DELAY = 30 # in seconds
GET_NAME_DELAY = 1.5
queue = {}

def answer_received(msg, status):
¬username = msg._GetSender()._GetHandle()
¬if username in queue.keys():
¬¬if status==Skype4Py.cmsReceived:
¬¬¬if msg._GetBody()!=TEXT['ANSWER']:
¬¬¬¬if HIDE_MESSAGES_AFTER_WRONG_ANSWER:
¬¬¬¬¬skype.UnregisterEventHandler('MessageStatus', answer_received)
¬¬¬¬¬for eachMsg in msg._GetChat()._GetRecentMessages():
¬¬¬¬¬¬try:
¬¬¬¬¬¬¬eachMsg.MarkAsSeen()
¬¬¬¬¬¬except:
¬¬¬¬¬¬¬continue
¬¬¬¬¬skype.RegisterEventHandler('MessageStatus', answer_received)
¬¬¬¬queue[username] = queue[username]-1
¬¬¬¬if queue[username]:
¬¬¬¬¬skype.SendMessage(username, TEXT['AGAIN'])
¬¬¬¬¬return
¬¬¬¬else:
¬¬¬¬¬del queue[username]
¬¬¬¬¬skype.SendMessage(username, TEXT['FAIL'])
¬¬¬¬¬msg._GetSender()._SetIsBlocked(True)
¬¬¬else:
¬¬¬¬del queue[username]
¬¬¬¬skype.SendMessage(username, TEXT['WIN'])
¬¬¬if len(queue)==0:
¬¬¬¬skype.UnregisterEventHandler('MessageStatus', answer_received)

def hasBanned(txtstr, target):
¬for word in BANNED[target]:
¬¬if word in txtstr:
¬¬¬return True
¬return False

def auth_received(from_user):
¬newUsers = skype._GetUsersWaitingAuthorization()
¬if not newUsers:
¬¬for key in queue.keys():
¬¬¬del queue[key]
¬¬return
¬for user in newUsers:
¬¬username = user._GetHandle()
¬¬if not (username in queue.keys()):
¬¬¬if TRYING < 1:
¬¬¬¬skype.SendMessage(username, TEXT['FAIL'])
¬¬¬¬user._SetIsBlocked(True)
¬¬¬¬continue
¬¬¬if hasBanned(user._GetReceivedAuthRequest(), 'WORDS'):
¬¬¬¬skype.SendMessage(username, TEXT['INSTANT_BAN'])
¬¬¬¬user._SetIsBlocked(True)
¬¬¬¬continue
¬¬¬skype.RegisterEventHandler('MessageStatus', answer_received)
¬¬¬skype.SendMessage(username, TEXT['QUESTION'])
¬¬¬queue[username] = TRYING
¬¬¬sleep(GET_NAME_DELAY)
¬¬¬if hasBanned(user._GetFullName(), 'NAMES'): # Skype's bug: full name is available only after message sending
¬¬¬¬del queue[username]
¬¬¬¬skype.SendMessage(username, TEXT['INSTANT_BAN'])
¬¬¬¬user._SetIsBlocked(True)
¬¬¬¬if len(queue)==0:
¬¬¬¬¬skype.UnregisterEventHandler('MessageStatus', answer_received)
¬¬¬¬continue

skype.RegisterEventHandler('UserAuthorizationRequestReceived', auth_received)
# В принципе следующий цикл не обязателен, но тогда при перезапуске скайпа придётся перезапускать и скрипт. И именно в такой последовательности.
while True:
¬skype.Attach()
¬auth_received(None)
¬sleep(REFRESH_DELAY)


¬ следует автозаменить на табуляцию, так вот глупо и неудобно определяется вложенность...
Затем сие сохраняется в файл с расширением .pyw и крутится в фоне.

P.S. К счастью, волна спама давно поутихла, но вдруг кому-то пригодится.

CodeIgniter — роутинг через базу данных

Возникла необходимость сделать так, чтобы можно было выбирать какой URL на какой контроллер ведет. Каждый раз лазить в файлы и править правила роутинга не есть правильное решение. Кроме того, в основном на сайте будут расположены страницы, и хотелось бы чтобы был ЧПУ из названия раздела и страницы. Особо гуглить я на эту тему не стал и придумал своё решение.

Принцип действия следующий:
1. В базе содержатся alias'ы страниц, к примеру '/it' и '/it/articles'. Последнему соответствует определенный контроллер и метод, допустим 'pages' и 'showList' соответственно.
2. Роутинг CodeIgniter'a смотрит куда обращаться по query_string или path_info. Эту строку мы и будем сравнивать с alias'ом в базе.
3. После сравнения, мы находим самое большое вхождение имеющейся строки. Допустим, если мы введем в строке '/it/test', то результатом будет алиас '/it', а если '/it/articles/param1' — '/it/articles' (все это делается одним запросом)
4. Для передачи параметров, мы из исходной строки удаляем alias, тем самым получается остаток от URI и являющийся параметрами, которые передадутся методу.

Скрипт подключается в виде хука, перед загрузкой всей системы, до того момента, когда срабатывает класс роутинга.
Читать дальше →

Манифест к хабросообществу, как самой многочисленной аудитории IT специалистов в России

Мы стоим на пороге новых открытий, технологий и продуктов для широкого использования. Информационные технологии, компьютеры, телефоны, портативные устройства, навигаторы стали частью нашей жизни и мы используем их каждый день в нашей деятельности. Область IT самая быстроразвивающаяся во всем мире. Посмотрите, что было достигнуто за поледние 20 лет, 10 лет и 5 лет. Каждый год появляются новые технологии, устройства, продукты, которые делают будущее уже сейчас. И благодаря кому это происходит? Благодаря нам, конечно! За всем этим стоят специалисты IT, которые претворяют, порой, даже самые невероятные идеи в жизнь. В 80-х годах началась эра информационных компьютеров. Они прошли путь от огромных вычислительных машин, но с маленькой мощностью для научных институтов до высокопроизводительных систем и портативных устройств, которые умещаются в вашем кармане и востребованы обывателями. Скорость обмена информацией возрасла на порядки за эти годы.
Настало время для нового продукта, который пройдет похожий путь. Роботы. Роботы от программируемых сварочных аппаратов на автозаводах, до неуклюжих конструкций, иммитирующих походку животных и действия человека, вперед к полноценным роботам, которые будут нужны каждому человеку в каждом доме. Роботов, которые не выходят из строя от воды, слабых источников питания, роботов, способных принимать решения на основе прошлого опыта, роботов, которые будут помогать человеку в его повседневных делах.
Читать дальше →

VDPAU или смотрим HD фильмы на Ubuntu

image

Тут товарищ hosco говорит, цитирую:
«Блин, перешёл бы на Линукс (именно этот дистрибутив покорил меня своей простотой в красоте и красотой в простоте), если бы не прошлый печальный опыт с 7-кой. Всё вроде заработало «из коробки», но отказывалось нормально проигрываться HD-видео. После волшебных пассов напильником оно проигрывалось, но после оказалось, что не передаётся звук по HDMI. Полазив по форумам, выяснилось, что сотворить звук по HDMI сродни только человеку с возможностями Нео :) Это мы хотели из Acer Revo сделать медиа-центр. Надеюсь 8-ка избавит многих от никчёмных страданий :)»
Тема — habrahabr.ru/blogs/ubuntu/75144

Ведь хочется помочь этому конкретному человеку, да и чёрт возьми многим другим, но инвайта мне никто не даёт, так что… =ъ «помогите люди добрые, сами мы не местные». Авансом я вам расскажу, как прикрутить VDPAU к SMplayer и XBMC Media Center, для комфортного просмотра HD видео.

Заранее предупреждаю, в линуксе я всего 2 года, так что многие советы могут показаться чересчур… ламерскими? Что я в связи с этим предлагаю, дорогие мои профи, если во-время прочтения у вас что-то и где-то сильно засвербит, кожа покраснеет, а глаза начнут выползать из орбит — не мучайте себя, перестаньте читать немедленно.
По-моему для %username% важнее то, что в итоге всё будет работать, а не трушность подхода. Всё проверенно на себе, на Acer Aspire Revo 3600.
С другой стороны, я должным образом приму любую критику и советы, дабы придать данному мануалу должный вид.

Со вступлением разобрались, и так начнём.
Читать дальше →

Избавляемся от лишних #include'ов

Со временем исходные файлы разрастаются, отпочковываются, в них добавляются и убираются отладочные выводы, реализация некоторых вещей переносится в другие файлы. Постепенно появляются ненужные зависимости. Начинает напрягать чересчур долгая компиляция — изменяешь один хедер, который, по идее, должен влиять всего на пару cpp'шников, а пересобирается половина проекта.

Поэтому у меня возникла идея написать скрипт, который автоматически будет проверять зависимости от хедеров и убирать ненужные. Сканируя все входные файлы, он последовательно пытается убрать все строки, содержащие подстроку "#include", и скомпилировать результат. Если make завершается успешно, скрипт считает, что удалённая строка не нужна.

Скрипт написан на bash и требует от исходников двух вещей:
1) Программа собирается с помощью утилиты make.
2) В данный момент программа успешно компилируется.

#!/bin/bash

function del {
FILE=$1
TEMP_FILE=$FILE".tmp"
BAK_FILE=$FILE".bak"
LINE=$2

echo -n "$LINE..." | tr -d \\r
grep -v "$LINE" "$FILE" > $TEMP_FILE 2>/dev/null
cp $FILE $BAK_FILE
cp $TEMP_FILE $FILE

#cat $FILE
sleep 1
touch -m $FILE
make >/dev/null 2>&1 && echo "YES" || ( cp $BAK_FILE $FILE; echo "NO" )
rm -rf $BAK_FILE $TEMP_FILE
}

function check {
FILE=$1
echo "---------- $FILE ----------"

grep '#include' $FILE | \
while read LINE;
do
del $FILE "$LINE"
done
}

until [ -z "$1" ]
do
check $1
shift
done


Скрипт иногда может работать не совсем корректно:
1) Если A.cpp напрямую зависит от B.h и C.h, а B.h в свою очередь зависит от C.h, то скрипт удалит зависимость A.cpp от C.h. Это не всегда правильно, т.к. зависимость B.h от C.h может измениться без участия A.cpp. Причём такие зависимости могут меняться при смене платформы или компилятора.
2) Если в хедерах есть некая хитрая макроподстановка. Например, файл, содержащий только строки типа #define USE_SOME_FEATURE. Без них программа будет компилироваться, но будет компилироваться не так, как нам хочется.

Также скрипт работает довольно долго: (количество директив #inlcude + время компиляции одного модуля + время линковки) секунд. Это вызвано необходимостью добавления в скрипт строки «Sleep 1», т.к. make проверяет время изменения файлов с точностью до секунды, а частота запуска make больше одного раза в секунду.

Тем не менее, для небольших по сложности проектов скрипт работает вполне сносно.

Критика статьи OpenCL. Практика.

Здравствуйте хабрики! Очень смешное у вас название.

Во-первых, автор ошибается, когда пишет: «Далее выберем устройство (у меня в системе оно всего одно, но на будущее пусть в нашей программе используется устройство с максимальным числом FLOPS).» т.к. он забыл то, что OCL может работать как с GPU, так и с CPU.

Ещё вот эта выделенная жирным шрифтом фраза должна быть помещена гораздо выше, не к оператору oclLoadProgSource, а к oclGetMaxFlopsDev: "ВНИМАНИЕ!!! oclLoadProgSource — не является функцией OpenCL API, а находятся в вспомогательной библиотеке, поставляемой вместе с Nvidia Computing SDK.". Почему? Да потому, что в oclGetMaxFlopsDev я сразу встретился с проблемой, что нет такой функции! А вот узнал, что оказывается она всё таки есть, через пару абзацев.

К предыдущему абзацу. Почему собственно не приведено имя библеотеки? Или её надо самому найти, пользуюсь экстросенсурными способностими? Чтоб не искали — это oclUtils.cpp.

Нужна ссылка на драйверы. Как же без этого? Я ввёл первую строчку и бабах, оказалось, что в системе нет OpenCL.dll.

Статья, конечно, является едвали не единственным описанием OpenCL на практике и на русском, но надо её немного подправить.

Скверная проблема — изменение размера шрифтов в Chrome; или как не ослепнуть за большим разрешением.

Наверняка не я один сталкивался с проблемой изменения размера шрифта фиксированной величины в google chrome на windows. А проблема ведь для многих может быть насущной, вот например у меня 20 дюймовый монитор с разрешением 1680х1050, размер пикселя соответственно небольшой, и читать текст 13ого размера очень неудобно, да что там, ослепнуть можно! «мне бы по-больше, а?»

В общем нашел 2 способа, как это можно ее решить:
первый — в папке C:\Users\имя пользователя\AppData\Local\Google\Chrome\User Data\Default или вместо Users может быть Documents and Settings есть файл Preferences, открываете его блокнотом. В самом конце находите

«webkit»: {
«webprefs»: {
«default_fixed_font_size»: 17,
«default_font_size»: 18,
«fixed_font_family»: «Bitstream Vera Sans Mono»,
«inspector_settings»: «lastActivePanel:string:elements\n»,
«minimum_font_size»: 14,
«minimum_logical_font_siz»: 14,
«sansserif_font_family»: «Times New Roman»,
«serif_font_family»: «Arial»,
«standard_font_is_serif»: false,
«text_areas_are_resizable»: true,
«uses_universal_detector»: true

изменяете там цифры, сохраняете — все)

ps: может быть вариант(у меня так и было), что там следующее:

«webkit»: {
«webprefs»: {
«uses_universal_detector»: true

если будет именно это, то приведите к виду указанному выше(возможно придется удалить строчку «uses_universal_detector»: true

так, это был первый способ.

Теперь способ №2:
Ставите последнюю DEV(тестовую) версию, скачать ее можно отсюда
Там появляется поддержка так называемых расширений. Добавляется это расширение
Теперь при запуске хрома, можете изменить размер страниц в нижней левой части экрана(прямо над пуском). Это изменение будет действовать до закрытия браузера. Т.е. до закрытия браузера все страницы будут открываться именно в том масштабе, который выбрали в этом расширении. При новом запуске придется выбрать заново.

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

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

Так же имеется расширение 125% zoom, которое изменяет навсегда(ну почти) размер страниц, думаю понятно насколько. Нашел я его тут, в осуждении какой-то статьи в разделе хрома.

кстати на линуксе всего этого копро нету — не удивительно кстати

Искусственный Интеллект AND or VS. Человек?!

Трудно что-либо предвидеть, а уж особенно будущее. Нильс Бор.

Ну начнем, пожалуй, не с будущего, а с прошлого. Что вам приходит на ум, когда вы видите дату 29 августа 1997 года? Ничего? А если я сообщу вам, что в этот день в Мичигане из-за неэкономичности была закрыта старейшая в США АЭС, а на Украине открылся конвент фантастов «ФАНКОН-97»? Опять на ум ничего не приходит? А если подобрать ассоциации к этим событиям: атомная энергия, научная фантастика? Опять мимо? Ну ладно, не буду больше вас томить – дело в том, что именно 29 августа 1997 года, согласно знаменитой тетралогии о терминаторах, суперкомпьютер Министерства Обороны США SkyNet, спроектированный Cyberdyne Systems Corporation для управления системой противоракетной обороны США, обретает сознание и начинают разворачиваться события, которые нам хорошо известны.

К чему такая преамбула? – резонно спросите вы. А к тому, что, возможно, такое развитие событий не так уж и фантастично, как казалось нам в те золотые школьные годы, когда мы раз за разом просматривали этот фильм на VHS. Хотя, скорее всего, было наоборот – тогда мы действительно могли в это поверить, но потом, повзрослев, вместе с новыми знаниями приобрели и новое чувство – скептицизм к подобного рода вещам.

Так давайте поспорим с Нильсом, вернемся в те золотые годы и с высоты полученных за это время знаний пофантазируем о нашем будущем, об отношении между искусственным интеллектом (далее-ИИ) и человеком, а может быть даже действительно предвидим его…

История человечества в основном – история идей. Герберт Уэллс.

Первые исследования, относящиеся к проблемам искусственного интеллекта, были предприняты почти сразу же после появления вычислительных машин. Само название новой науки возникло в конце 60-х годов XX века, а в 1969 году в Вашингтоне (США) состоялась первая Всемирная конференция по искусственному интеллекту.

Цель исследований в области искусственного интеллекта – создание арсенала метапроцедур, достаточного для того, чтобы ЭВМ (или другие технические системы, например, роботы) могли находить по постановкам задач их решения. Это цель ближайшая. Последующие цели связаны с попыткой проникнуть в области мышления человека, которые лежат вне сферы рационального и выразимого словесно (вербально) мышления. Ибо в поиске решения многих задач, особенно сильно отличающихся от ранее решенных, большую роль играет та сфера мышления, которую называют подсознательной, бессознательной, или интуитивной.

Вроде бы цели благие – создать интеллект на подобие человеческого, отправить его вместо себя на работу, а самому за заработанные роботом с ИИ деньги нежиться на золотистом пляже Черного моря (а кто сказал, что робот будет зарабатывать больше вас?). При этом такого робота можно задействовать в опасных сферах деятельности человека, обезопасив тем самым жизнь этого самого человека. Хочу заметить, что речь не идет о современных роботах, типа сапера и т.п., где не требуется применение интеллекта. Речь идет о роботах с ИИ, которые бы смогли заменить на «боевом» посту человека, а главное – его интеллектуальную деятельность вкупе с функциональными возможностями человека, а, может быть, даже превосходящими его. Самый типичный пример, на мой взгляд, робот-полицейский. Вот только тут сразу появляется много нюансов. Один из них – можно ли считать робота с ИИ особой формой жизни, только не на основе углерода, а, скажем, кремния и, пожалуй, главный вопрос – можно ли считать его личностью. Если утвердительно ответить на этот вопрос (а для этого есть все основания), то мы углубимся еще дальше – какое право мы имеем эксплуатировать роботов с ИИ, рисковать их жизнями и т.д. Ведь даже у животных в современном цивилизованном обществе есть права. На практике выходит создание нового рабовладельческого строя (не зря говорят, что история развивается по спирали), а в таком строе, как мы знаем из уроков истории, нередко случались восстания.

Но это был пессимистичный расклад. А что, если все же человеку удастся интегрировать ИИ в человеческое общество, дав ему соответствующие права и обязанности, возможно даже, практически идентичные человеческим (почему не полностью, подумайте сами). Согласитесь, пока в это трудно поверить, но технологии сейчас развиваются стремительно и, возможно, когда-нибудь достигнут такого уровня, что жизнь робота с ИИ приравняют к жизни человека. Хотя граница между человеком и роботом с ИИ к тому моменту может размыться – скорее всего, в человеческом теле будут неорганические имплантаты, тогда как в теле робота – органические. Если уж фантазировать о совсем далеком будущем, посмею предположить, что люди (может быть даже совместно с ИИ) научатся воспроизводить такие сложные органические системы как головной мозг и, в конце концов, будут создавать существ (а также модифицировать себя), которые будут использовать высокие возможности и скорости органики для созидания, а неорганику для сложных математических вычислений (например, чисел с плавающей точкой, хе-хе) и замены хрупкого органического организма на более прочный.

Ни у одного народа вера в бессмертие не была так силь на, как у кельтов; у них можно было занимать деньги, с тем что возвратишь их в ином мире. Генрих Гейне.

Это был мой, в какой-то степени дилетантский прогноз. А что думают по поводу будущего ИИ профессиональные футуристы, такие как Ян Пирсон из British Telecom. Если верить футурологу, в ближайшие полвека нас ждет небывалый прогресс компьютерной техники, результатом которого станет наше обретение бессмертия. Правда, пока только виртуального. В момент смерти человека специальный аппарат будет сканировать головной мозг умирающего, переписывая сложные электрические потенциалы нейронов его мозга в модели нейронов в компьютере. «Благодаря подобной оцифровке человек, не заметив момента смерти, плавно переместится в виртуальную реальность, где сможет жить вечно, — полагает Ян Пирсон. — Таким образом, наше сознание сможет пережить смерть тела, которая отныне перестанет быть проблемой для человечества».

Но это все кажется нам далеким будущим, а что же ждет нас в ближайшем? Специалисты одной из самых влиятельных в мире аналитических компаний в области технологических исследований и консалтинга — Gartner — сделали ряд предсказаний на предстоящее десятилетие, касающихся информационных технологий. Так, к 2015 году 40% нынешних должностей в сфере IT заменят средства автоматизации. Организаторы бизнес-процессов смогут менять потоки работ в них при помощи графических интерфейсов без участия специалистов IT-отдела. Это, конечно, приведет к отмиранию многих современных должностей.

Какой же из всего этого можно сделать вывод? А вот какой – cам по себе ИИ, как и большинство изобретений человечества, не хорош и не плох. Самое важное – осознание человеком ответственности за использование своих изобретений перед окружающим миром. Мне кажется, что хотя и лаконичный, но достаточно емкий вывод, жаль только, что не мой, но хорошо, что и не искусственного интеллекта :)

З. Ы. Наслаждайтесь общением с людьми и мыслями друг друга. Возможно, скоро за нас будут думать ДРУГИЕ (звучит финальная мелодия из Терминатора 2).

nnCron — в бой идут одни старики

Вчера задумался, почему я, имея самую простую клавиатуру за 200 р., должен чувствовать себя ущербным по отношению к обладателям мультимедиа-клавиатур за тысячи рублей, утыканых со всех сторон дополнительными кнопками. Хочу назначать на любые клавиши любые приложения и всё тут. Для начала хотелось бы запускать музыку, видео, почту и браузер.

В жизни всегда есть место для творчества — на сцене появляется nnCron. Что это такое? Если сказать, что это планировщик или твикер — это будет верно, но не до конца. nnCron — это швейцарский нож для управления ресурсами вашего компьютера. При своём мало-размере возможности его впечатляют. Лучше об этом почитать на сайте производителя.

Минимум, что он умеет — это запускать приложения по времени (sheduler), при этом синтаксис команд совместим с Unix crontab. Максимум — это встроеный скриптовый язык. При этом не обязательно для добавления задачи писать макрос, у nnCron есть и GUI, через который можно управлять заданиями в привычной для многих форме. По мне, так все остальные твикеры и шедуллеры для виндовз — идут строем в ресайкл бин.

А теперь — слайды :)

Назначаю горячую клавишу <Ctrl+F12> на запуск The Bat

#( Bat-start
AsLoggedUser
WatchHotKey: “^{F12}”
Action:
StartIn: “C:\Program Files\The Bat!”
ShowNormal NormalPriority
START-APP: C:\Program Files\The Bat!\thebat.exe
)#


Назначаю горячую клавишу <Ctrl+F11> на запуск Mozilla Firefox
Тут немного интереснее — если Firefox уже запущен, то nnCron не будет запускать копию, а сделает окно Firefox активным.

#( Firefox-start
AsLoggedUser
WatchHotKey: “^{F11}”
Action:
PROC-EXIST: “firefox.exe”
IF
WIN-ACTIVATE: “/.*firefox/i”
ELSE
StartIn: “C:\Program Files\Mozilla Firefox”
ShowNormal NormalPriority
START-APP: C:\Program Files\Mozilla Firefox\firefox.exe
THEN
)#


Поработал — отдохни.

Назначаю хоткеи <Ctrl+F10> на воспроизведение DVD (используется Mplayer) и <Ctrl+F9> — на воспроизведение mp3 (Winamp).
При запуске Winamp, неплохо было бы, чтобы он сразу стартовал проигрывание трека, я надеялся нагуглить какие-нибудь параметры командной строки для оного, но нашёл это — плагин AutoPlay. Всяко неплохо, даже ещё интереснее. И наконец, чтобы уж до конца довести идею “once-click”, — при запуске DVD будем убивать Winamp, зачем — обьяснять не буду.

#( Mplayer-DVD-autoplay
AsLoggedUser
WatchHotKey: “^{F10}”
Action:
StartIn: “C:\mplayer”
ShowNormal HighPriority
KILL: “mplayer.exe”
KILL: “winamp.exe”
START-APP: C:\mplayer\mplayer.exe dvd://0 -dvd-device e: -fs
)#


#( Winamp-start
AsLoggedUser
WatchHotKey: “^{F9}”
Action:
StartIn: “C:\Program Files\Winamp”
ShowNormal NormalPriority
KILL: “winamp.exe”
START-APP: C:\Program Files\Winamp\winamp.exe
)#


Всё, софт для мультимедия-клавиатуры инсталлирован:)
Обязательно рисую маркером пиктограммы на клаве — без маркера концепция handmade кажется незавершённой, а без пиктограмм никто не поверит, что у меня настоящая мультимедия-клавиатура.

image

Домен.РФ, кириллица в URL и кодировки: добро пожаловать в ад.

Здравствуйте. Итак, я человек которому очень не нравится английский язык, принципиально. А потому, я, ещё задолго до придумывания сильными и умными мира сего домена.РФ, загорелся целью сделать себе сайт с кириллическими ЧПУ. Сайт уже существует, хотя и параллельно дорабатывается до вменяемого состояния.

Но вот началось регистрация доменов.РФ, и скоро, надо полагать, там появятся первые сайты. И скорее всего владельцы кириллического домена захотят чтобы url из сайта выглядел не так: http://домен.рф/news/my_otkrylis/, а вот так: http://домен.рф/новости/мы_открылись/
А так, как я начала реализовывать нечто подобное, то думаю что мой опыт будет многим полезен. Особенно программистам и SEO специалистам — именно для них тут будет много весёлых, занимательных открытий, после которых у некоторых наверняка возникнет желание сделать что-то нехорошее с теми массовиками-затейниками, которые всё это придумали. Если бы я сам знал, что меня ждёт, никогда не стал бы так извращаться и сделал бы всё на латинице.

Итак, поехали.

ЧПУ и сам кириллический URL.


Как обстоит дело с обычными GET запросами вроде ?категория=новости&статья=мы_открылись, я не знаю, но думаю с тут проблем быть не должно. А вот если вы захотите сделать ЧПУ, то боюсь, что придётся вам его делать в коде самой страницы, а не через mod_rewrite, ибо последний кириллицу не понимает. В .htaccess крякозяблы приходят, вместо русских букв. И подружить .htaccess с кириллицей у меня так и не получилось (если кому-то это удастся, то пожалуйста, дайте знать как).

Но тут есть ещё один подводный камень. У меня весь сайт в кодировке cp1251. А от браузеров URL всегда приходит в UTF-8 кодировке, независимо от ОС и браузера. Но в случае, если вы будете делать header(), то тут прежде всего нужно будет перекодировать в юникод. Ибо после header() заголовок посылается уже в той кодировке, которая была в переданной строке, а не в юникоде.
И тут главное чтобы ie6 наконец уже окончательно канул в бездну, так как он, после header`а, в адресной строке отображает крякозяблы. Благо это только его баг, во всех остальных браузерах вроде всё работает как нужно.

Однако, боюсь, что дальше этого пойти не удастся. Я имею ввиду то, что внутренние ссылки не поддерживают кириллицу как минимум в ie6-8 (учитывая что ie занимает всё-таки лидирующие позиции среди пользователей интернета, да и пользоваться этими доменами будут в основном люди не всегда знающие о существовании других браузеров, кроме ie, то думаю что именно на этот браузер нужно ориентироваться в первую очередь).
Т.е. если есть ссылка с name="якорь", то при переходе с http://домен.рф/новости, на http://домен.рф/новости#якорь — страница перезагрузится. Так что клиентов, которые хотят чтобы на их свежекупленном домене.РФ не было латинских символов в принципе, придётся убеждать в необходимости латиницы в якорях.
Но это ещё цветочки, а ягодки пойдут дальше…

Кириллические URL`ы, поисковики и системы размещения рекламы.


А вот здесь начинается настоящий ад. Тут очень многое зависит от настроек сервера. Например, при работе сайта в сети обнаружились очень интересные особенности. А именно, при индексации некоторыми поисковиками и система размещения рекламы страниц с кириллическими URL`ами, сервер им выдавал 406 код ошибки, хотя сам скрипт всё обрабатывал как нужно, делал нужные sql запросы и получал всё необходимое содержимое. И оказалось, что в utf-8 кодировке URL приходит только от браузеров, а все остальные шлют запросы в том виде, в каком им хочется. В частности была и такая проблема с Яндексом. Вот часть ответа из службы поддержки по поводу причины такого явления:
Проверка показывает, что сервер формирует данный код ответа на запрос
документов в типе text/html. То есть, по какой-то причине, сервер, отдавая
text/html, считает, что он не может быть обработан роботом и формирует ответ
406 Not Acceptable.
Браузерам (например FireFox) отдается страница с кодом 200, так как они
отправляют запрос, который предполагает, что сервер может вернуть любой тип
контента, если нет возможности вернуть text/html, application/xhtml+xml или
application/xml (Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8).


Собственно после этого, я плюнул и решил перевести всё-таки все страницы сайта utf-8 кодировку. Но, как ни странно, это не помогло. А дело оказалось в том, что для правильного ответа сервера нужно не просто, чтобы сами ссылки были в юникоде, но и чтобы они были закодированы через urlencode(), иначе — всё равно 406 ошибка. В этом отношении меня порадовал только лишь Google. Ему всегда возвращается 200 код, в какой бы кодировке что не находилось.

Таким образом, для того, чтобы некоторые избранные могли проиндексировать вашу страницу, нужно чтобы они переходили по URL находящемуся в utf-8 кодировке и обработанному через urlencode(). Строка в win-1251 и urlencode() тоже не пройдёт, только юникод.

При этом обработать ссылки через urlencode() не всегда легко так легко. К примеру, что будет, если контент сайта внутри заполняется кем-то, кто не знает вообще про кодировки ничего и он создаст просто обычную внутреннюю ссылку вида href="/новости"? Более того, получается что таким системам и людям нужно подсовывать разные ссылки — людям обычные ссылки, а роботам ссылки после urlencode()? Да и с и с точки зрения того же Яндекса, будут ли одинаковыми ссылки http://домен.рф/новости и http://домен.рф/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8? Не уверен. А при публикации ссылок на внешних ресурсах как быть?
Лично я решил эту проблему так: у меня просто определяется, что за клиент передо мной: из «чёрного списка», в котором все те, кому 406-ая ошибка когда надо и не надо возвращается, или нет. В первом случае при выводе в меню ссылки обрабатываются через urlencode() и весь основной контент страницы так же пропускается через функцию, которая ищет внутренние ссылки, и, если находит, то заменяет их на обработанные в urlencode().

Да-да, вот такие вот мрак, ересь и танцы с бубном приходится использовать. И ведь всё равно, ничего хорошего из этого толком не получается. Получается что всё через задницу сделано, и работает так же. Хорошо только тем, кто не знает, где на клавиатуре английские буквы располагаются.

Ну и на последок ещё одна «нехорошесть».


Ну вот всё описанное выше вы решили, и запустили сайт в сеть. Поставили счетчики статистики и вроде бы все рады, пока клиент не просмотрит статистику через cpannel и не увидит примерно следующее: /\xd0\xbd\xd0\xbe\xd0\xb2\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8. Или на топ.мейл увидит всё те же самые URL`ы, закодированные через urlencode(). И вот попробуйте ему в таком случае объяснить, что вы тут не властны, и что это вовсе не то, что вы хотите скрыть от него кто и какие страницы сайта посещал. А ведь согласитесь, в таком представлении даже сведущему человеку не сразу понять что это за такое, а уж простому обывателю и подавно.

Таким образом, домен.РФ может и существует, может скоро и появятся сайты, где в адресной строке на латинице будет только http, но вот только проблем с такими сайтами будет очень много, как у их разработчиков, так и у оптимизаторов. Ну а пока все роботы и системы к этому привыкнут, подправят свои алгоритмы и начнут выводить и обрабатывать кириллические URL`ы как нужно, пройдёт немало времени.
Надеюсь я этим материалом помогу тем несчастным, которые будут всё-таки вынуждены создавать полностью кириллические сайты.

P.S. Этой мой первый пост на хабре. Извиняюсь, если что-то запостил не так и спасибо всем вам за прочтение. Я буду очень получить инвайт за этот пост)))

BlueJ или ООП для начинающих.

Hello Habrapeople!

Поискав информацию о BlueJ в блогах Хабра, на свое удивление, ничего не обнаружил. Как впрочем и удивлен незначительному количеству статей о JAVA. Значит есть возможность о чем рассказать.:)

image

BlueJ.


Программа была разработана университетами Deakin University (Мельбурн, Австралия) и University of Kent (Canterbury, Великобритания) на основе имеющейся среды Blue, как часть исследовательского проекта по обучению ООП начинающих программистов при поддержке Sun Microsystems. Иными словами, BlueJ(голубая сойка) — это среда программирования для студентов, начинающих изучать JAVA и основы ООП. Особый акцент был сделан на визуализацию и методы взаимодействия для создания интерактивной среды, обеспечивающей понимание того, как все устроено. Программа классифицируется как freeware, работает в любой операционной системе и скачать ее можно здесь.

image

Главный экран показывает структуру классов разрабатываемого приложения в графическом виде (на UML-подобной диаграмме), а объекты можно создавать и тестировать интерактивно. Подобная интерактивность совместно с ясным, простым интерфейсом пользователя позволяет легко экспериментировать с разрабатываемыми объектами. Концепции объектно-ориентированной разработки (классы, объекты, сообщение через вызов методов) интерактивны и наглядно представлены в интерфейсе. Подробнее о причинах использования зарубежными университетами BlueJ и тонкостях интерфейса можно прочитать тут.

Редактируемая линия с тултипом в Google Maps

Наконец-то, нашлась свободная минутка, чтобы поделиться одной из своих наработок. И попытать счастье, может инвайт перепадёт :)

Предисловие.
Примерно месяца четыре назад возникла необходимость для своей организации создать карту-схему объектов с возможностью редактирования. Задачу решил успешно, склеив ExtJS и GMap. Получилась мини ГИС для локального использования, к сожалению, не мо-гу поделиться ссылкой, т.к. информация не для общего пользования, да и сама система крутится в локалке.

Суть.
Итак, в процессе создания столкнулся с необходимостью отображать линии между объек-тами. При этом линии должны отвечать нескольким требованиям:
  1. Возможность редактировать с сохранением в базу.
  2. У каждой линии должна быть подпись. Т.к. линий было очень много, пришлось подписи сделать всплывающими.
  3. При редактировании линии должна быть возможность добавлять точки и изломы.

В итоге, я написал небольшой «класс», который хочу представить на ваш суд. Надеюсь кому-нибудь пригодиться. При желании его можно доработать и улучшить.

Исходник: labeledline2.js

Пример: тут

  1. Сохраняется только в памяти, не в базу, убрал эту часть кода.
  2. Подпись появляется при наведении курсора.
  3. Реализована возможность программного добавления точек, а также визуальное ре-дактирование. После клика на линии она переходит в режим редактирования, где можно удалять точки, добавлять изломы и изменять положение существующих то-чек. По второму клику выдается запрос на сохранение и линия переходит в режим просмотра.


Спасибо за внимание!
12 ...
602