InstallShield MSI script project: pass data to Setup.Rul from command line

May 24th, 2010

You can easily pass data from the command line to Setup.Rul by passing /z parameter to command line:

setup.exe /z"MYDATA"

This sets the CMDLINE variable:

function OnFirstUiBefore()
begin
    MessageBox(CMDLINE, MB_OK);
end;

py2exe: win32con missing module

February 16th, 2010

Hi everybody,

Yesterday I tried to turn my python code into win32 executable with py2exe utility and faced with problem: py2exe was unable to find win32con module with error:

The following modules appear to be missing ['win32con']

In a couple of hours I googled next solution: one should simply install Python for Windows extensions. This fixed everything.

Compiling nagios plugins with cygwin: handling ./configure problem with ICMP

June 24th, 2009

To build nagios plugins in windows, one should start cygwin and execute ./configure and make commands. While doing this, I faced with problem: ./configure script just hangs on the “checking for ICMP ping syntax” line.

Since I needed only one plugin (check_http) and I’m not familiar with icmp, cygwin and bash, I simply removed lines from ./configure:

{ echo "$as_me:$LINENO: checking for ICMP ping syntax" >&5
echo $ECHO_N "checking for ICMP ping syntax... $ECHO_C" >&6; }
ac_cv_ping_packets_first=no
ac_cv_ping_has_timeout=no
[REMOVE_THIS]
if test -n "$with_ping_command"
then
    { echo "$as_me:$LINENO: result: (command-line) $with_ping_command" >&5
.....
.....
echo "${ECHO_T}$with_ping_command" >&6; }

else
    { echo "$as_me:$LINENO: WARNING: unable to find usable ping syntax" >&5
echo "$as_me: WARNING: unable to find usable ping syntax" >&2;}
fi
[/REMOVE_THIS]

cat >>confdefs.h <<_ACEOF
#define PING_COMMAND "$with_ping_command"
_ACEOF

After this ./configure finished it’s work. Then I called make, it built 23 plugins before thew the error and died. Luckily create_http.exe was created.

QtWebKit – turn javascript and images off

June 18th, 2009

How to turn javascript and images off in QWebView?

QWebView *myWebView = new QWebView(this);
....
myWebView->settings()->setAttribute(QWebSettings::JavascriptEnabled, false);
myWebView->settings()->setAttribute(QWebSettings::AutoLoadImages, false);

That’s all :)

QWhatsThis – fighting with wordwrap

June 13th, 2009

Another problem with QWhatsThis::showText() method: word wrapping. If you want to turn it off, you’d probably face with some problems: it’s not as easy as it supposed to be.

I’ve found the solution that satisfied me: instead of calling

QWhatsThis::showText(myPoint, "blah blah...", ...);

I frame “blah blah …” text into table with <nobr> tags and use this call:

QWhatsThis::showText(myPoint, "<table><tr><td><nobr>blah blah...</nobr></td></tr></table>", ...);

This solved my problems.

ProtectMy.Info – leave spam no chance

June 13th, 2009

Today I’ve met protectmy.info – free service that allows anyone to publish his contacts (like e-mail) without fair to be spammed.

It’s principle is easy: before showing e-mail one asked to enter CAPTCHA (hard-to-read words from image). If one succeed he can read the e-mail. Spambots are too stupid to pass this check, so e-mail becomes protected for sure.

And now I can publish my e-mail. Yes! The sweet Victory!

Qt: QWhatsThis – handling clicks

June 13th, 2009

QWhatsThis::showText() shows beautiful hint where one can place HTML formatted text. The question is: how we can handle link clicks, like <a href=”more”>more…</a>?

The answer is located in this thread: one should re-implement QWidget::event() method for “parent” widget (3rd param in QWhatsThis::showText() method), like:

void MyWidget::event(QEvent *_event)
{
    if (_event->type() == QEvent::WhatsThisClicked){
        if (QWhatsThisClickedEvent* clicked = dynamic_cast(_event)){
            QString href = clicked->url(); // here is the "href" value of the link user clicked
            ...........
        }
    }
    return QWidget::event(_event);
}

So, when user clicks on the <a href> link, MyWidget::event() fires, extracts the “url” and handles it.

If you don’t want to re-implement the QWidget::event() method, you could use installEventFilter().

Сапер: какова вероятность того, что поле откроется?

December 14th, 2008

Кто играл в “сапера”, тот знает, что бывают ситуации, когда логически вычислить положение следующей мины/пустой клетки невозможно. Я задался вопросом: “А какова вообще вероятность того, что поле откроется, если открывать его настолько аккуратно, насколько это возможно (исключить человеческий фактор)?” Очевидно, что такая цифра существует. Собственно эта статья посвящается тому, как мне удалось приблизиться к этим числам. Сначала сразу приведу результаты, чтобы не напрягать лишний раз людей, которые зашли сюда только за ними :)

Результаты:

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

Новичок (поле 8×8, 10 мин), первый клик в углу: вероятность 75%;

Новичок, первый клик в центре: вероятность 67.7%.

Любитель (поле 16×16, 40 мин), первый клик в углу: вероятность 66.1%

Любитель, первый клик в центре: вероятность 62.9%

Профессионал (30×16, 99 мин), первый клик в углу: 23.1%

Профессионал, первый клик в центре: 22.9%

Как результаты были получены:

Как я уже писал, результаты экспериментальные. Поскольку постановка звучала так: “Какова вероятность того, что самый аккуратный/лучший/идеальный игрок в мире откроет поле размером NxM с K минами, если на первом клике подорваться невозможно”, то для начала был сделан алгоритм, который достаточно хорошо (близок к идеальному) открывает данное ему поле. После этого, для каждого вида поля я создавал 10000 досок и давал ему их решать. Число успешно открытых им досок деленное на 100 и бралось в качестве претендента для искомой вероятности.

Описание “близкого к идеальному” алгоритму, который использовался в эксперименте:

Алгоритм итерационный:

- Если на i-м шаге можно со 100% уверенностью определить, что в какой-то ячейке есть мина, то алгоритм помечает ее как мину. Пример ситуации: вокруг единички все ячейки открыты, одна закрытая. Значит там мина:)

- Если на i-м шаге можно со 100% уверенностью определить, что какая-то ячейка пустая, то алгоритм “кликает” на нее. Пример: единичка, возле нее установлена “мина”. Значит алгоритм кликает на все оставшиеся соседние с этой единичкой ячейки.

- Если на i-м шаге нельзя со 100% уверенностью определить, где мина есть, а где ее нет, то алгоритм 50 раз случайным образом расставляет оставшиеся мины так, чтобы ситуация на доске была допустимой. То есть он не будет возле открытой единички ставить 3 мины. После этого он анализирует эти 50 возможных расстановок, находит клетки, где мины встречались часто, где редко (среди этих 50-и расстановок), то есть находит клетки, в которых наибольшая вероятность мины (или ее отсутствия), и ставит туда мину (или кликает).

Как видно, алгоритм имитирует человека, который играет “нечестно”: использует программу, которая на каждом шаге вычисляет для него вероятность того, где мины есть, а где их нет. Если он не идеален, то ИМХО весьма хорош:)

Зависимость вероятности успеха (открыть поле) от плотности мин:

Для поля размером 8×8 я посчитал вероятности для любого количества мин (те успех когда на поле 0 мин, 1 мина, 2 мины, … 62 мины). Вот как для этого поля выглядит график зависимости вероятность успеха от плотности мин:

Выводы:

Кроме полученных чисел можно заметить, что вероятность так же зависит от начального клика, лучше начинать открывать с угла:)

Еще есть такой ресурс sweepmines.com, на котором предлагают открыть поле 8×8, 12 мин, в случае успеха возвращают удваивоенную ставку. Так вот, вероятность открыть такое поле — 57% (если с угла). Так что в принципе можете попытаться “обмануть” ресурс и заработать бабла. Но я бы не рискнул :)

Приложения:

численные результаты экспериментов (для всех плотностей мин на новичке, до 44 мин на любителе, немного на профи);

исходники алгоритма (на питоне), который использовался для эксперимента;

программа, которая помогает “открывать” поле простому игроку, показывая вероятности нахождения/отсутствия мины (питон + pyWidgets). Надеюсь Rogen не обидится (очень пригодится тем, кто участвует в рейтинге “по плотности мин” на minesweeper.ru :) )

ATnotes – свободные стикеры (записки) для рабочего стола Windows XP

December 12th, 2008

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

Для Windows XP существует огромное множество таких программ: Power Notes, Post-It Notes, Digital Desktop Stickers, и даже MoRUN.net Sticker Professional Edition :) итд. Как правило, это платные продукты, цена колеблется от $10 до $20.

Но существуют и бесплатные аналоги, которые ничем не уступают вышеперечисленным. Например ATnotes. К сожалению, разработка и поддержка продукта закончилась, тем не менее это очень стабильный и достойный представитель стикерского софта. Скачивается с официального сайта, ставится в три клика, запускается при загрузке, интуитивно понятный интерфейс, редактирование шрифта/фона, возможность делать их полупрозрачными поверх всех окон, поддержка кириллицы и прочие вкусности. Рекомендую всем.

Ссылающиеся друг на друга объекты в питоне: возможные последствия

December 7th, 2008

В питоне объект уничтожается (и вызывается его деструктор) только тогда, когда на него ничего не ссылается. Что делать, когда объект A ссылается на объект B, а объект B в свою очередь ссылается на объект A? В этом случае деструкторы этих объектов никогда не будут вызваны. В частности, этот код

import sys
print(sys.version)

class C(object):
    def __del__(self):
        print("Die C!")

class D(object):
    def __del__(self):
        print("Die D!")

c = C()
d = D()

выведет

2.5.2 (r252:60911, Apr 21 2008, 11:12:42)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
Die C!
Die D!
,
но если мы вконец допишем

c.d = d
d.c = c

и запустим, то получим


2.5.2 (r252:60911, Apr 21 2008, 11:12:42)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
.
Все вышенаписанное справедливо как для 2.x ветки, так и для python 3000.

Казалось бы, какой пустяк. Тем не менее, это может вызывать непредсказуемое поведение в, казалось бы, простейших ситуациях. Рассмотрим один пример:

Наверое самый известный ОО паттерн: синглтон. Давайте реализуем его на питоне:

import sys

print(sys.version)

class Singleton(object):
	instance = None
	def __new__(type, *args, **kwargs):
		if type.instance == None:
			type.instance = object.__new__(type, *args, **kwargs)
		return type.instance

class A(Singleton):
       def __del__(self):
		print ("A's destructor is called!")

aobj = A()
bobj = A()

print str(aobj)
print str(bobj)

, результат будет:

2.5.2 (r252:60911, Apr 21 2008, 11:12:42)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
<__main__.A object at 0xb7d8a04c>
<__main__.A object at 0xb7d8a04c>

aobj и bobj указывают на один и тот же объект, но в конце работы программы деструктор для него не вызывается. Возникает естественный вопрос: “Почему”?

В питоне тип (класс) – тоже объект, чем мы и воспользовались для реализации синглтона: когда мы первый раз создали объект класса A, мы присвоили свойству instance класса(-объекта) A ссылку на этот объект. Все логично, но мы забыли об одной вещи: у объекта aobj есть свойство __class__, которое указывает на класс объекта. В нашем случае это класс A.

То есть получается следующее: aobj.__class__ указывает на A, а A.instance указывает на aobj, ссылающиеся друг на друга объекты a и A, их деструкторы никогда не будут вызываны.

Добьем наш пример:

import sys

print(sys.version)

class Singleton(object):
	instance = None
	def __new__(type, *args, **kwargs):
		if type.instance == None:
			type.instance = object.__new__(type, *args, **kwargs)
			Singleton_Destructor.types.append(type)
		return type.instance

class Singleton_Destructor:
	types = []
	def __del__(self):
		for i in self.__class__.types:
			del i.instance

sd = Singleton_Destructor()

class A(Singleton):
	def __del__(self):
		print ("A's destructor is called!")

a = A()
b = A()

print(str(a))
print(str(b))

вернет долгожданный

[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]
<__main__.A object at 0xb7bb430c>
<__main__.A object at 0xb7bb430c>
A's destructor is called!