<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>pamiętnik programisty</title>
	<atom:link href="http://piotr.doniec.eu/devlog/feed/" rel="self" type="application/rss+xml" />
	<link>http://piotr.doniec.eu/devlog</link>
	<description></description>
	<lastBuildDate>Sun, 25 Jul 2010 12:54:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Z C++ zagadka nr 4</title>
		<link>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 12:50:24 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[common error]]></category>
		<category><![CDATA[tricky]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=532</guid>
		<description><![CDATA[Mając przedstawioną poniżej strukturę danych i kontener zawierający wskaźniki, wykonać operację/metodę methodA na rzecz obiektu obj_ posługując się iteratorem: class Foo { public: methodA() { printf(&#34;Wykonano...\n&#34;); } } struct data_t { int i_; Foo* obj_; } std::list&#60;data_t*&#62; data_; for(std::list&#60;data_t*&#62;::iterator i = data_.begin(); i != data_.end(); i++ ) { // operacje } W jaki sposób wykonać]]></description>
			<content:encoded><![CDATA[<p>Mając przedstawioną poniżej strukturę danych i kontener zawierający wskaźniki, wykonać operację/metodę methodA na rzecz obiektu obj_ posługując się iteratorem:</p>
<pre class="brush: cpp">
class Foo {
public:
  methodA() {
    printf(&quot;Wykonano...\n&quot;);
  }
}

struct data_t {
  int i_;
  Foo* obj_;
}

std::list&lt;data_t*&gt; data_;

for(std::list&lt;data_t*&gt;::iterator i  = data_.begin(); i != data_.end(); i++ ) {
   // operacje
}
</pre>
<p>W jaki sposób wykonać blok operacji ? Możliwości mamy kilka:</p>
<pre class="brush: cpp">
/* 1 */ i-&gt;obj_-&gt;methodA();
/* 2 */ *i-&gt;obj_-&gt;methodA();
/* 3 */ (*i)-&gt;obj_-&gt;methodA();
</pre>
<p>Rozwiązanie zagadki jest proste, ale wymaga znajomości priorytetów operatorów. Pierwsze wywołania jest całkowicie błędne, ponieważ lista przecowuje wskaźniki do strkutury, a nie samą strukturę. Zatem należy najpier wyłuskać strukturę znajdującą się pod wskazywanym adresem i dopiero wtedy wykonać metodę. Okazuje się że rowiązania 2 również jest nie poprawne, właśnie ze względu na priorytety operatorów. Dopiero numer 3 daje zamierzony efekt. Na szczęście błąd ujawnia się na etapie kompilacji&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/07/z-c-zagadka-nr-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Indywidualne ustawienia php dla każdej witryny na serwerze IIS i Windows 2008</title>
		<link>http://piotr.doniec.eu/devlog/2010/07/indywidualne-ustawienia-php-dla-kazdej-witryny-na-serwerze-iis-i-windows-2008/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/07/indywidualne-ustawienia-php-dla-kazdej-witryny-na-serwerze-iis-i-windows-2008/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 18:25:17 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[IIS]]></category>
		<category><![CDATA[Windows 2008]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=526</guid>
		<description><![CDATA[Problem jak najbardziej z życia wzięty. Na serwerze znajdują się strony kilku użytkowników. Żaden z nich nie chciałby aby ktokolwiek oprócz niego i administratora miał dostęp do plików jego witryny. Gdyby problem powstał w środowisku działającym pod kontrolą Linuxa problem rozwiązałby się w kilka chwil, poprzez odpowiednie ustawienie właścicieli katalogów i praw dostępu. Jednak wspomniana]]></description>
			<content:encoded><![CDATA[<p>Problem jak najbardziej z życia wzięty. Na serwerze znajdują się strony kilku użytkowników. Żaden z nich nie chciałby aby ktokolwiek oprócz niego i administratora miał dostęp do plików jego witryny. Gdyby problem powstał w środowisku działającym pod kontrolą Linuxa problem rozwiązałby się w kilka chwil, poprzez odpowiednie ustawienie właścicieli katalogów i praw dostępu. Jednak wspomniana sytuacja zaistniała pod Windows 2008.<br />
Na pierwszy ogień poszło ustawienie parametru open_basedir w pliku konfiguracyjnym PHP. Ograniczyło to możliwość odczytu includowania i innych tego typu operacji tylko do wymienionych katalogów. Nadal jednak pozostał problem odczytu plików nawzajem przez użytkowników. Ze strony należącej do uzytkownia A np.: c:\Sites\A\1.php bez problemy można odczycztać czy zaincludowac sobie stronę użytkownika B c:\Sites\B\tajne.txt co oczywiście jest nie do przyjęcia. Z pomocą przyszła możliwość ustawienia parametrów PHP dla każdego folderu niezależenie. Aby z tego skorzystać należy utworzyć w rejestrze nowy klucz w gałęzi HKLM/Software/PHP/Per Directory Values/c/Sites/<nazwa_katalogu> czyli np. HKLM/Software/PHP/Per Directory Values/c/Sites/A i umieścić tam nową wartość typu string o nazwie odpowiadającej parametrowi na który chcemy wpłynąć i wartości którą taki parametr ma przyjąć. W przypadku wyżej wspomnianego problemu wyglądałoby to tak:<br />
<a href="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/07/iis_perdirectoryvalues.jpg" rel='lytebox[indywidualne-ustawienia-php-dla-kazdej-witryny-na-serwerze-iis-i-windows-2008]'><img src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/07/iis_perdirectoryvalues.jpg" alt="" title="iis_perdirectoryvalues" width="384" height="162" class="alignleft size-full wp-image-527" /></a><br />
Od tego momentu właściciel strony c:\Sites\A jest ograniczony tylko do własnego katalogu. Wadą tego rozwiązanie jest niestety konieczność utworzenia takich wpisów dla wszystkich stron znajdujących się na serwerze. Jednak (1) w tym wypadku można sobie było na to pozwolić (2) rozwiązanie jest łatwe we wdrożeniu a żadne inne nie przyszło mi do głowy. Chętnie poznam inne metody, może bardziej eleganckie, na osiągnięcie podobnego rezultatu.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/07/indywidualne-ustawienia-php-dla-kazdej-witryny-na-serwerze-iis-i-windows-2008/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>VIM, spacje zamiast wcięć</title>
		<link>http://piotr.doniec.eu/devlog/2010/07/vim-spacje-zamiast-wciec/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/07/vim-spacje-zamiast-wciec/#comments</comments>
		<pubDate>Wed, 07 Jul 2010 21:14:03 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=511</guid>
		<description><![CDATA[Charakterystyczną cechą języka Python jest oddzielanie bloków kodu za pomocą wcięć. Z tego powodu są one niezmiernie istotne, a szukanie błędu powstałego przez źle umieszczone wcięcie, jeśli nie jest sygnalizowane przez interpreter może być bardzo czasochłonne a czasami wręcz frustrujące. Jakiś czas temu spotkałem się z takim problemem, który wynikł z używania 2 edytorów na]]></description>
			<content:encoded><![CDATA[<p>Charakterystyczną cechą języka Python jest oddzielanie bloków kodu za pomocą wcięć. Z tego powodu są one niezmiernie istotne, a szukanie błędu powstałego przez źle umieszczone wcięcie, jeśli nie jest sygnalizowane przez interpreter może być bardzo czasochłonne a czasami wręcz frustrujące. Jakiś czas temu spotkałem się z takim problemem, który wynikł z używania 2 edytorów na 2 różnych maszynach. Na Windows korzystałem zamiennie z Vim oraz Programmers Notepad (tab = 4 spacje), pod linuxem wyłącznie z Vim bo tylko na tyle pozwalał interface konsolowy.<br />
W pewnym momencie doszło do kolizji. Z jakiegoś powodu część wcięć przesunęła się w lewo &#8211; czyli znikły. Na całe szczęście 90% błędów zostało wykrytych przez interpreter. Od razu zaznaczam że nie przeprowadziłem pełnej analizy problemu, ale coś mi podpowiadało że to wina Tab w Vim. Poniżej przedstawiam w jaki sposób zamieniać wszystkie tabulacje na 4 spacje. Komendy można umieścić w .vimrc (linux) czy też w _vimrc jeśli korzystamy z Windows:</p>
<pre class="brush: python">
set tabstop=4
set shiftwidth=4
set expandtab
</pre>
<p>Na sam koniec warto dodać, że mimo iż Vim może być postrzegany jako stary edytor, trudny w użyciu a posługują się nim tylko starzy wyjadacze-programiści z poprzedniej epoki, to ma on wiele funkcji których nie oferuje nawet Notepad++, a programowanie bez odrywania rąk od klawiatury jest o wiele mniej męczące. Polecam cheatsheet: http://www.qitty.net/lnx/vim-cheatsheet.png</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/07/vim-spacje-zamiast-wciec/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>.NET słowa kluczowe out,ref</title>
		<link>http://piotr.doniec.eu/devlog/2010/05/net-slowa-kluczowe-outref/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/05/net-slowa-kluczowe-outref/#comments</comments>
		<pubDate>Sat, 08 May 2010 10:24:32 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C#/.NET]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[beginning c#]]></category>
		<category><![CDATA[keywords]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=490</guid>
		<description><![CDATA[Znalazłem ostatnio trochę czasu aby dokładniej przyjrzeć się .NET i na własnej skórze przekonać się czy jest warty więcej niż Java. Dotąd napisałem tylko dwa proste programik wykorzystują tę platformę &#8211; aplikację MDI obsługująca skromną bazę danych przechowującą informację o osobach opartą na plikach binarnych, oraz obsługę portu rs232. Pamiętam że sposób programowania nie powalił]]></description>
			<content:encoded><![CDATA[<p>Znalazłem ostatnio trochę czasu aby dokładniej przyjrzeć się  .NET i na własnej skórze przekonać się czy jest warty więcej niż Java. Dotąd napisałem tylko dwa proste programik wykorzystują tę platformę &#8211; aplikację MDI obsługująca skromną bazę danych przechowującą informację o osobach opartą na plikach binarnych, oraz obsługę portu rs232. Pamiętam że sposób programowania nie powalił mnie wtedy na kolana, przypominało to raczej tylko trochę uproszczone C++. Oczywiście skorzystałem z całkiem fajnego mechanizmu właściwości(properties) i upraszczającej życie pętli foreach, stworzyłem nawet własną kontrolkę, ale wszystko to było robione w pośpiechu i nie pozwoliło wniknąć głębiej. Teraz postanowiłem nadrobić zaległości i jestem mile zaskoczony.<br />
<span id="more-490"></span><br />
To co tak naprawdę skłoniło mnie do wypożyczenia książki i studiowania jej od samego początku to możliwość łączenia kodu napisanego w C++(/CLI) z kodem zarządzanym napisanym w .NET. Miło jest móc połączyć wysokopoziomowe programowanie logiki aplikacji z niskopoziomowym dostępem do funkcji systemu operacyjnego Windows takich jak dostęp do kamery czy przechwytywanie komunikatów.<br />
Ponieważ książkę czytam od deski, zostałem zmuszony do przypomnienia podstawowych konstrukcji programistycznych takich jak metody czy proste klasy, ale poznałem przy tym kilka ciekawych słów kluczowych umożliwiających kontrolowanie modyfikacji danych.</p>
<p><strong>Modyfikator out</strong><br />
Modyfikatorem out można oznaczyć dowolną liczbę parametrów metody. Nie ma przy tym znaczenia kolejność, parametry zmodyfikowane przez out mogą wystąpić zarówno na początku listy w środku jak i na końcu. To słowo kluczowe definiuje tzw. parametr wyjściowy. Wykonanie funkcji wymaga zapisania wartości do parametru wyjściowego. </p>
<pre class="brush: csharp">
        public static void Dodawanie(out int sum, int x, int y, out int ssum)
        {
            sum = x + y;
            ssum = sum * sum;
        }
</pre>
<p>Jeśli kompilator nie znajdzie prawidłowego(co można wymusić komentując linię ssum = sum*sum) przypisania wygeneruje błąd i poinformuje nas o tym komunikatem: </p>
<blockquote><p>&#8222;The out parameter &#8216;ssum&#8217; must be assigned to before control leaves the current method&#8221;</p></blockquote>
<p>Modyfikator out, może trochę przypominać mechanizm znany z C polegający na przekazywaniu wskaźnika jako parametru funkcji. Jednak w przypadku C# mamy pewność że po wykonaniu podprogramu, w parametrze wyjściowym znajdzie się jakąś wartość, co chroni nas przed nieprzyjemnym komunikatem <em>&#8222;Segmentation fault&#8221;</em>. Istnieje jeszcze jedna różnica wpływająca na korzyść platformy .NET, mianowicie sposób wywołania. Nie ma tu magicznych zaklęć nie trzeba się domyślać który parametr to wskaźnik i jak został przekazany, ponieważ trzeba to jawnie określić. Kompilator umożliwi uruchomienie programu tylko wtedy gdy wszystkie wywołania funkcji zostaną opisane zgodnie z ich deklaracjami/definicjami, znakomicie wpływa to na czytelność kodu:</p>
<pre class="brush: csharp">
        static void Main(string[] args)
        {
            int sum, ssum;
            int a = 5, b = 6;

            Dodawanie(out sum, a, b, ssum);       // FAIL !
            Dodawanie(out sum, a, b, out ssum); // OK !

            Console.WriteLine(&quot;Suma {0} + {1} = {2}, ({0} + {1})^2 = {3}&quot;, a, b, sum, ssum);
            Console.ReadLine();
        }
</pre>
<p><strong>Modyfikator ref</strong><br />
Działanie modyfikatora ref również jest związane z wywołaniem metod. Jednakże jego zastosowanie ma sens tylko w odniesieniu do obiektów które w łańcuchu dziedziczenia nie mają klasy System.ValueType, a więc takich które tworzone są na stercie i nie są przekazywane przez wartość ale przez referencję. Podobnie jak w przypadku Javy, modyfikacje wykonane na takim obiekcie pozostają aktualne po zakończeniu metody, o czym napisałem we wpisie <a href="http://piotr.doniec.eu/devlog/2009/03/pass-by-value-w-javie/">Pass-by-value w javie</a>. Dla przypomnienia: tak naprawdę przekazywana jest nie referencja a jej kopia, z tego powodu dozwolona jest zmiana stanu obiektu ale przypisanie referencji do innego obiektu już nie. Aby lepiej zrozumieć zagadnienie przedstawiam prosty przykład prezentujący wspomnianą funkcjonalność:</p>
<pre class="brush: csharp">
class Punkt
{
  public int x;
  public int y;
}

class Program
{

  public static void CopyReference(Punkt p)
  {
    p.x = 0;
    p.y = 0;

    p = new Punkt();
    p.x = 200;
    p.y = 200;
  }

static void Main(string[] args)
{
  Punkt p1 = new Punkt();
  p1.y = 100;
  p1.x = 100;

  Console.WriteLine(&quot;Przed wykonaniem CopyReference: p1.x = {0}, p1.y = {1}&quot;, p1.x, p1.y);
  CopyReference(p1);
  Console.WriteLine(&quot;Po wykonaniem CopyReference: p1.x = {0}, p1.y = {1}&quot;;, p1.x, p1.y);
  Console.ReadLine();

  }
}
</pre>
<p>W wyniku wykonania programu powinniśmy zobaczyć na ekranie następujący wynik:</p>
<blockquote><p>
Przed wykonaniem CopyReference: p1.x = 100, p1.y = 100<br />
Po wykonaniem CopyReference: p1.x = 0, p1.y = 0
</p></blockquote>
<p>Aby osiągnąć zamierzone działanie wystarczy dodać modyfikator ref, zarówno do definicji metody, jak i do jej wywołania pdobnie jak ma to miejsce w przypadku &#8222;out&#8221;:</p>
<pre class="brush: csharp">
public static void OrigReference(ref Punkt p)
{
  p.x = 0;
  p.y = 0;

  p = new Punkt();
  p.x = 200;
  p.y = 200;
}
</pre>
<p>Po wykonaniu tak zmodyfikowanej metody, pola x oraz y obiektu p1 będą przechowywały wartość (200, 200)<br />
AFAIK w Javie takich możliwości nie ma, może konstrukcje takie nie są szczególnie przydatne, ale w .NET w razie czego są i można je wykorzystać co pozytywnie wpływa na moja dotychczasową ocenę tej platformy.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/05/net-slowa-kluczowe-outref/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Uruchamianie metod klas w nowych wątkach w c++ i pthreads</title>
		<link>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 10:47:17 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[pthreads]]></category>
		<category><![CDATA[qnx]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[wielowątkowość]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=471</guid>
		<description><![CDATA[Podczas pisania kolejnego projektu w języku c++ natknąłem się na interesujący problem. Program docelowo miał działać na systemie czasu rzeczywistego zatem jego celem było również zapoznanie z różnymi mechanizmami RTOS. Pierwszy problem pojawił się przy korzystaniu z mechanizmu wielowątkowości, pewnie byśmy się nie dowiedzieli o jego istnieniu gdybyśmy nie zdecydowali się na programowanie obiektowe, ale]]></description>
			<content:encoded><![CDATA[<p><img src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/04/logo.gif" alt="qnx_rtos" title="qnx_rtos" width="106" height="45" class="alignright size-full wp-image-483" />Podczas pisania kolejnego projektu w języku c++ natknąłem się na interesujący problem. Program docelowo miał działać na systemie czasu rzeczywistego zatem jego celem było również zapoznanie z różnymi mechanizmami RTOS. Pierwszy problem pojawił się przy korzystaniu z mechanizmu wielowątkowości, pewnie byśmy się nie dowiedzieli o jego istnieniu gdybyśmy nie zdecydowali się na programowanie obiektowe, ale po kolei&#8230;<br />
<span id="more-471"></span><br />
Każdy kto programował w C++ korzystając z biblioteki Boost::Threads napewno wie że aby uruchomić metodę obiektu w nowym wątku wystarczy przeciążyć operator () i każdy obiekt takiej klasy zaczyna z powodzeniem udawać funkcję. Dzięki temu można taki obiekt przekazać do konstruktora boost::thread. Poniższy przykład obrazuje taką sposób działania:</p>
<pre class="brush: cpp">
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation.  William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided &quot;as is&quot; without express or implied warranty.

#include &lt;boost/thread/thread.hpp&gt;;
#include &lt;;boost/thread/xtime.hpp&gt;;
#include &lt;iostream&gt;;

struct thread_alarm
{
    thread_alarm(int secs) : m_secs(secs) { }
    void operator()()
    {
        boost::xtime xt;
        boost::xtime_get(&amp;xt, boost::TIME_UTC);
        xt.sec += m_secs;

        boost::thread::sleep(xt);

        std::cout &lt;&lt; &quot;alarm sounded...&quot; &lt;&lt; std::endl;
    }

    int m_secs;
};

int main(int argc, char* argv[])
{
    int secs = 5;
    std::cout &lt;&lt; &quot;setting alarm for 5 seconds...&quot; &lt;&lt; std::endl;
    thread_alarm alarm(secs);
    boost::thread thrd(alarm);
    thrd.join();
}
</pre>
<p>Jednak ten sposób nie działa w przypadku korzystania z natywnego mechanizmu wielowątkowości dostępnego w każdym systemie *nix. Biblioteka pthreads nie radzi sobie z wywołaniem przeciążonego operatora (). Problem trzeba było rozwiązać jak najszybciej, żeby projekt mógł ruszy dalej. Dlatego powstał ten sprytny &#8222;work-around&#8221; umożliwiający uruchomienie dowolnej metody obiektu w nowym wątku. Jest to właściwie funkcja proxy, takie proste a ułatwia życie:</p>
<pre class="brush: cpp">
template&lt;class T&gt;
struct ThreadParams
{
	T *obj;
	void *params;
};

template&lt;class T, void* (T::*method)(void*)&gt;
void* run_thread(void *params)
{
	ThreadParams&lt;T&gt; *t = static_cast&lt;ThreadParams&gt;&lt;T*&gt;(params);
	T* obj = static_cast&lt;T*&gt;(t-&gt;obj);
	(obj-&gt;*method)(t-&gt;params);
	return NULL;
}
</pre>
<p>Dodatkowy wkład pracy jaki należy włożyć aby wykorzystać powyższy kod ogranicza się właściwie tylko do wypełnienia struktury ThreadParams:</p>
<pre class="brush: cpp">
class Test
{
public:
	void* fun(void* params) {
	printf(&quot;Hello World! \n&quot;);
	printf(&quot;Params: %d\n&quot;, reinterpret_cast&lt;int&gt;(params));
	pthread_exit(NULL);
	}
 };

 int main() {

	pthread_t tid;
	void* status;
	Test test;
	ThreadParams&lt;Test&gt; params;

	params.obj = &amp;test;
	params.params = reinterpret_cast&lt;void&gt;(123);

	pthread_create(&amp;tid, NULL, run_thread&lt;Test, &amp;Test::fun&gt;, (void*)(&amp;params));
	pthread_join(tid, &amp;status);
 }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/04/uruchamianie-metod-klas-w-nowych-watkach-w-c-i-pthreads/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prosty przykład wykorzystania Java Servlets, JPA, Oracle 10XE i Glassfish v3</title>
		<link>http://piotr.doniec.eu/devlog/2010/02/prosty-przyklad-wykorzystania-java-servlets-jpa-oracle-10xe-i-glassfish-v3/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/02/prosty-przyklad-wykorzystania-java-servlets-jpa-oracle-10xe-i-glassfish-v3/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 20:03:41 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[glassfish]]></category>
		<category><![CDATA[jee]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=408</guid>
		<description><![CDATA[Celem tego wpisu jest pokazanie w jaki sposób stworzyć dynamiczną prostą aplikację WWW wykorzystującą technologię Java Servlets pobierającą dane z lokalnie dostępnej bazy danych Oracle 10g XE z wykorzystaniem JPA. Całość ma obsługiwać Glassfish v3. Struktura relacyjna w bazie danych jest bardzo prosta, ale wystarczająca do zapoznania z JPA &#8211; składa się z tabeli zawierającej]]></description>
			<content:encoded><![CDATA[<p>Celem tego wpisu jest pokazanie w jaki sposób stworzyć dynamiczną prostą aplikację WWW wykorzystującą technologię Java Servlets pobierającą dane z lokalnie dostępnej bazy danych Oracle 10g XE z wykorzystaniem JPA. Całość ma obsługiwać Glassfish v3.<br />
Struktura relacyjna w bazie danych jest bardzo prosta, ale wystarczająca do zapoznania z  JPA &#8211; składa się z tabeli zawierającej dane studentów takie jak imię, nazwisko i z z tabeli opisującej grupy dziekańskie. Obie tabele powiązane są relacją wiele-do-jednego, także grupa może składać się z wielu studentów, natomiast każdy student przynależy do dokładnie 1 grupy.<br />
<span id="more-408"></span><br />
Na wstępie zaznaczam, że jestem początkujący w tej dziedzinie. Jeśli ktoś bardziej doświadczony, znajdzie jakieś nieścisłości lub błędy to proszę o pozostawienie komentarza. Chętnie poprawię i przy okazji czegoś się nauczę.<br />
Opisana wyżej struktura bazy danych jest reprezentowana przez dwie encje połączone relacją i wygląda to następująco:<br />
<center><img src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/02/jpa_entities1.jpg" alt="jpa_entities" title="jpa_entities" width="516" height="165" class="alignnone size-full wp-image-427" /></center></p>
<p>Java Persistence Api (JPA) jest wykorzystywane do mapowania encji zapisanych w bazie danych (wiersze tabeli) na ich obiektową reprezentację również nazywaną encją. Zbieżność terminów może powodować konsternację dlatego w dalszej części wpisu przez pojęcie encja należy rozumieć tylko odpowiednio opisaną klasę w języku Java.<br />
W ogólnym wypadku każda klasa spełniająca wymogi JavaBean tj. posiadająca bezparametrowy konstruktor oraz metody get i set dla pól może zostać przekształcona w encję. Dla przykładu, Grupa może zostać opisana przez taki komponent:</p>
<pre class="brush: java">
package eu.doniec.piotr.bean

public class Grupa {
    private Long id;

    private String nazwa;
    private String opis;

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getNazwa() { return nazwa; }
    public void setNazwa(String nazwa) { this.nazwa = nazwa; }
    public String getOpis() { return opis; }
    public void setOpis(String opis) { this.opis = opis; }
}
</pre>
<p>Modyfikacja do postaci encji, możliwej do wykorzystania przez JPA do obsługi danych zawartych w tabeli Grupy polega na opisaniu klasy metainformacjami &#8211; adnotacjami z pakietu javax.persistence. Gotowa klasa przedstawia się następująco:</p>
<pre class="brush: java">
package eu.doniec.piotr.persistence;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@NamedQuery(
    name=&quot;findAllGroups&quot;,
    query=&quot;SELECT g FROM Grupa g&quot;
)
@Table(name=&quot;GRUPY&quot;)
public class Grupa implements Serializable {

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String nazwa;
    private String opis;

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getNazwa() { return nazwa; }
    public void setNazwa(String nazwa) { this.nazwa = nazwa; }
    public String getOpis() { return opis; }
    public void setOpis(String opis) { this.opis = opis; }
}
</pre>
<p>Podobnie sytuacja wygląda z klasą Studenta, choć tu sytuacja jest trochę inna. Struktura bazy danych wymaga aby tabela STUDENCI posiadała ograniczenie FOREIGN_KEY na dodatkowe pole GRUPA_ID. W takiej sytuacji w ramach encji Student umieszczamy odwołanie do encji Grupa. Właściwość ta jest dodatkowo oznaczona adnotacją @ManyToOne oznaczającą właśnie że wielu studentów może przynależeć do jednej grupy.</p>
<pre class="brush: java">
package eu.doniec.piotr.persistence;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.ManyToOne;
import javax.persistence.JoinColumn;

@Entity
@NamedQuery(
    name=&quot;findAllStudents&quot;,
    query=&quot;SELECT s FROM Student s&quot;
)
@Table(name=&quot;STUDENCI&quot;)
public class Student implements Serializable {
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long nr_indeksu;

    private String imie;
    private String nazwisko;

    @ManyToOne
    private Grupa grupa;

    public Long getNr_indeksu() { return nr_indeksu; }
    public void setNr_indeksu(Long nr_indeksu) { this.nr_indeksu=nr_indeksu; }
    public String getImie() { return imie; }
    public void setImie(String imie) { this.imie = imie; }
    public String getNazwisko() { return nazwisko; }
    public void setNazwisko(String nazwisko) { this.nazwisko = nazwisko; }
    public Grupa getGrupa() { return grupa; }
    public void setGrupa(Grupa grupa) { this.grupa = grupa; }
}
</pre>
<p>Encje są zdefiniowane, pozostało jeszcze je wykorzystać. W tym celu powstanie servlet, który wyświetli nr indeksu, nazwisk i przydział studenta do grupy. W celu wykorzystania stworzonych obiektów trzeba utworzyć obiekt EntityManager&#8217;a, a raczej &#8222;wstrzyknąć&#8221; go do aplikacji &#8211; uzyskuje się to annotacją @PersistenceContext. Utworzony w ten sposób EntityManager jest zarządzany przez kontener aplikacji tzw. container-managed. Sensowne wydaje się wstrzyknięcie go w klasie implementującej ServletContextListener i zapisanie w kontekście servletu, w ten sposób łatwo będzie się do niego dostać:</p>
<pre class="brush: java">
package eu.doniec.piotr.listeners;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.ServletContext;

import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;

@WebListener()
public class ContextListener implements ServletContextListener {

    @PersistenceContext
    private EntityManager em;

    private ServletContext context;

    public void contextInitialized(ServletContextEvent sce) {
        context = sce.getServletContext();
        context.setAttribute(&quot;EntityManager&quot;, em);
    }

    public void contextDestroyed(ServletContextEvent sce) {
        context.removeAttribute(&quot;EntityManager&quot;);
    }
}
</pre>
<p>Na tym etapie, pozostało już tylko stworzenie serwletu i konfiguracja połączenia z bazą danych. Ostatni, prymitywny fragment kodu wypisuje na ekran nr indeksu, nazwisko i nazwę grupy do której zapisany jest student.</p>
<pre class="brush: java">
package eu.doniec.piotr.servlets;

import eu.doniec.piotr.persistence.Student;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.persistence.EntityManager;
import javax.persistence.Query;

@WebServlet(name=&quot;studenci&quot;, urlPatterns={&quot;/studenci&quot;})
public class Studenci extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType(&quot;text/html;charset=UTF-8&quot;);
        PrintWriter out = response.getWriter();
        try {
            EntityManager em = (EntityManager)getServletContext().getAttribute(&quot;EntityManager&quot;);
            Query q = em.createNamedQuery(&quot;findAllStudents&quot;);

            out.println(&quot;&lt;html&gt;&quot;);
            out.println(&quot;&lt;head&gt;&quot;);
            out.println(&quot;&lt;title&gt;Servlet studenci&lt;/title&gt;&quot;);
            out.println(&quot;&lt;/head&gt;&quot;);
            out.println(&quot;&lt;body&gt;&quot;);
            out.println(&quot;&lt;h1&gt;Servlet studenci at &quot; + request.getContextPath () + &quot;&lt;/h1&gt;&quot;);

            out.println(&quot;&lt;table&gt;&quot;);
            out.println(&quot;&lt;tr&gt;&lt;th&gt;Numer indeksu&lt;/th&gt;&lt;th&gt;Nazwisko&lt;/th&gt;&lt;th&gt;Grupa&lt;/th&gt;&lt;/tr&gt;&quot;);

            List studenci =  q.getResultList();
            for (Iterator iter = studenci.iterator(); iter.hasNext();) {
                Student s = (Student) iter.next();
                out.println(&quot;&lt;tr&gt;&quot;);
                out.println(&quot;&lt;td&gt;&quot; + s.getNr_indeksu() +&quot;&lt;/td&gt;&quot;);
                out.println(&quot;&lt;td&gt;&quot; + s.getNazwisko() + &quot;&lt;/td&gt;&quot;);
                out.println(&quot;&lt;td&gt;&quot; + s.getGrupa().getNazwa() +&quot;&lt;/td&gt;&quot;);
                out.println(&quot;&lt;/tr&gt;&quot;);
            }

            out.println(&quot;&lt;/body&gt;&quot;);
            out.println(&quot;&lt;/html&gt;&quot;);
        } finally {
            out.close();
        }
    } 

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
}
</pre>
<p>Plik persistence.xml:</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;persistence version=&quot;1.0&quot; xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd&quot;&gt;
  &lt;persistence-unit name=&quot;baza-danych-nauczyciela-pu&quot; transaction-type=&quot;JTA&quot;&gt;
    &lt;provider&gt;oracle.toplink.essentials.PersistenceProvider&lt;/provider&gt;
    &lt;jta-data-source&gt;jdbc/bazanauczyciela&lt;/jta-data-source&gt;
  &lt;/persistence-unit&gt;
&lt;/persistence&gt;
</pre>
<p>Sposób stworzenie źródła danych dla Oracle pod Glassfish wystarczająco dobrze opisany jest tu: <a href="http://technology.amis.nl/blog/1276/configuring-a-oracle-datasource-on-glassfish">http://technology.amis.nl/blog/1276/configuring-a-oracle-datasource-on-glassfish</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/02/prosty-przyklad-wykorzystania-java-servlets-jpa-oracle-10xe-i-glassfish-v3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scons &#8211; alternatywa dla Make, Qmake i podobnych</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 12:35:20 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Inne]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=404</guid>
		<description><![CDATA[Scons jest oprogramowaniem którego zadaniem jest ułatwienie budowania binarnej wersji napisanego kodu. Twórcy zachwalają swoje dzieło jako między platformowe, łatwiejsze w użyciu i szybsze. Bazuje na Pythonie i dlatego postanowiłem się nim trochę zainteresować. Pierwsze próby zakończyłem sukcesem. Co mi się bardzo spodobało to możliwość wyboru kompilatora. Mając do dyspozycji g++ z MinGW oraz Visual]]></description>
			<content:encoded><![CDATA[<p>Scons jest oprogramowaniem którego zadaniem jest ułatwienie budowania binarnej wersji napisanego kodu. Twórcy zachwalają swoje dzieło jako między platformowe, łatwiejsze w użyciu i szybsze. Bazuje na Pythonie i dlatego postanowiłem się nim trochę zainteresować.<br />
Pierwsze próby zakończyłem sukcesem. Co mi się bardzo spodobało to możliwość wyboru kompilatora. Mając do dyspozycji g++ z MinGW oraz Visual C++ Compiler, można zadecydować który z nich ma zostać użyty.<br />
Najprostszy plik z instrukcją zdudowania programu to 1 linia:</p>
<pre class="brush: python">
Program(&#039;main.cpp&#039;)
</pre>
<p>Na Windows domyślnie zostanie wykorzystany (o ile dostępny) kompilator Microsoftu. Jeśli jednak chcemy użyć g++, wystarczy dopisać jeszcze jedną linię:</p>
<pre class="brush: python">
env = Environment(tools = [&#039;mingw&#039;], CC = &#039;gcc&#039;, CCFLAGS = &#039;-O2&#039;)
env.Program(&#039;main.cpp&#039;)
</pre>
<p>Piewsze lody przełamane, kolejne próby będą sprawdzały łatwość dołączania zewnętrzych bibliotek jak boost czy qt.</p>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/scons-alternatywa-dla-make-qmake-i-podobnych/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SOAP w Pythonie</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 15:13:44 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[webservices]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=396</guid>
		<description><![CDATA[Mimo że sam język jest uważany za potężny z dostępną dużą ilością bibliotek, to nie do koońca jest to prawda. SOAP w Pythonie niestety ale po prostu leży. Są 2 biblioteki umożliwiające tworzenie webserviców i tak naprawdę 2 które umożliwiają korzystanie z już utworzonych. Ja swoje próby rozpocząłem od soaplib, biblioteki która została porzucona przez]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-400" title="soap_python" src="http://piotr.doniec.eu/devlog/wp-content/uploads/2010/01/soap_python-300x227.jpg" alt="soap_python" width="210" height="159" />Mimo że sam język jest uważany za potężny z dostępną dużą ilością bibliotek, to nie do koońca jest to prawda. SOAP w Pythonie niestety ale po prostu leży. Są 2 biblioteki umożliwiające tworzenie webserviców i tak naprawdę 2 które umożliwiają korzystanie z już utworzonych. Ja swoje próby rozpocząłem od soaplib, biblioteki która została porzucona przez twórców, ale w wyniku tzw. forków w miarę często pojawiają się nowe wersje. Niestety był to błąd.<br />
<span id="more-396"></span><br />
Nowe wersje od niezależnych twórców charakteryzują się większą bądź mniejszą ilością błędów. Najlepszą wersją okazała się wersja <strong>cuker soaplib</strong>, nie spełniała tylko 1 wymogu &#8211; generowania jakiegokolwiek kodu na podstawie WSDL. Jest to pewne nadużycie z mojej strony, biblioteka dostarczyła skrypt o nazwie wsdl2py, ale potrafił on poprawnie sparsować i zinterpretować plik wsdl utworzony tylko przez soaplib, co trzeba przyznać jest lekką &#8222;kichą&#8221;. Szkoda, biblioteka aktywnie rozwijana, wiązałem z nią spore nadzieje &#8211; odpadła.<br />
<strong>Suds</strong> to druga biblioteka związana z SOAP, aktywnie rozwijana, chwalona za łatwość korzystania, niestety przykłady dotyczą tylko tworzenia klinetów, serwerów poprostu tworzyć się nie da? W połączeniu z soaplib mogł by to być całkiem ciekawy duet.<br />
Biblioteka webserwisów dla Pythona <strong>ZSI</strong>,  w założeniu ma umożliwiać tworzenie i korzystanie z różnych webserviców, niestety projekt został porzucony w 2007 roku. Ale mimo to miłe zaskoczenie, dostarczane skrypty wsdl2py i wsdl2dispatch bez problemu radzą sobie z przykładowy wsdl dostępnymi w internecie. Tworzone są 3 pliki które potem można wykorzystać do implementacji serwera i klienta. Jednakże żeby nie było zbyt miło, serwer dostarczony z biblioteką jest jedno wątkowy. Jeśli operacje obsługi żądania jednego klienta są czasochłonne, to na ten czas serwer nie odpowiada na żądania innych klientów. Fatalna sprawa, ale! światełko w tunelu, ZSI można połączyć z Apache&#8217;m poprzez wykorzystanie mod_python ( oczywiście nie mogło być wersji dla python 2.6, na szczęście VS poradziło sobie z kompilacją ). Kolejna ślepa uliczka &#8211; jak bym tworzył stronę WWW. Przychodzi żądanie tworzone są wszystkie klasy a po zakończeniu obsługi usuwane &#8211; nie tak sobie wyobrażałem mój system rozproszony, zamiast w Pythonie mógłbym go napisać w PHP (sic!). Powrót do ZSI i eureka, ktoś bardziej doświadczony w tym języku dopisał kilka linii kodu do źródła i serwer stał się wielowątkowy! Połączenie idealne, wielowątkowość obsługi żądań, nie niszczenie wszystkiego po zakończeniu obsługi, możliwośc wypisywania komunikatów na ekran konsoli.<br />
Źródło rozwiązania: http://osdir.com/ml/python.pywebsvcs.general/2008-06/msg00019.html . Autor wykorzystał co prawda ZSI-2.1-a1, ale poprawka działa również na ostatniej stabilnej wersji ZSI-2.0</p>
<p>Na wszelki, skopiowany kod poprawki poniżej:</p>
<blockquote><p>&#8212; ZSI-2.1-a1/ZSI/ServiceContainer.py 2007-08-08 00:56:37.000000000 +0200<br />
+++ ServiceContainer.py 2008-06-19 13:50:11.000000000 +0200<br />
@@ -5,6 +5,7 @@</p>
<p>import urlparse, types, os, sys, cStringIO as StringIO, thread,re<br />
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer<br />
+from SocketServer import ThreadingMixIn<br />
from ZSI import ParseException, FaultFromException,<br />
FaultFromZSIException, Fault<br />
from ZSI import _copyright, _seqtypes, _get_element_nsuri_name, resolvers<br />
from ZSI import _get_idstr<br />
@@ -30,6 +31,7 @@<br />
SimpleWSResource<br />
SOAPRequestHandler<br />
ServiceContainer<br />
+ ThreadedServiceContainer<br />
&#8222;&#8221;"<br />
class NoSuchService(Exception): pass<br />
class UnknownRequestException(Exception): pass<br />
@@ -141,12 +143,16 @@<br />
return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw)</p>
<p>-def AsServer(port=80, services=()):<br />
+def AsServer(port=80, services=(), threaded=False):<br />
&#8221;&#8217;port &#8211;<br />
services &#8212; list of service instances<br />
+ threaded &#8212; in modo multithread ?<br />
&#8221;&#8217;<br />
address = (&#8221;, port)<br />
- sc = ServiceContainer(address, services)<br />
+ if threaded:<br />
+ sc = ThreadedServiceContainer(address, services)<br />
+ else:<br />
+ sc = ServiceContainer(address, services)<br />
sc.serve_forever()</p>
<p>@@ -467,6 +473,11 @@<br />
def removeNode(self, url):<br />
self._nodes.removeNode(url)</p>
<p>+class ThreadedServiceContainer(ThreadingMixIn, ServiceContainer):<br />
+ &#8221;&#8217;Multithreaded version of ServiceContainer.<br />
+ &#8221;&#8217;<br />
+ pass<br />
+</p>
<p>class SimpleWSResource(ServiceSOAPBinding):</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/soap-w-pythonie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HSSPOJ &#8211; zadanie które nie dawało mi spokoju</title>
		<link>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/</link>
		<comments>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/#comments</comments>
		<pubDate>Fri, 01 Jan 2010 19:37:11 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[Algorytmika]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[spoj]]></category>
		<category><![CDATA[teoria gier]]></category>
		<category><![CDATA[tricky]]></category>
		<category><![CDATA[twierdzenie Sprague-Grundy'ego]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=381</guid>
		<description><![CDATA[Zadanie z konkursu algorytmicznego dla uczniów szkół średnich. Zwróciłem na nie uwagę, gdyż współczynnik poprawnych rozwiązań wynosił lekko ponad 30%, a skoro to konkurs dla licealistów to powinienem sobie dać radę. I tu pierwszy szok, nic z tego&#8230; Wiedza jaką dysponowałem okazała się daleko nie wystarczająca, a próby znalezienia rozwiązania podanego na tacy spełzły na]]></description>
			<content:encoded><![CDATA[<p>Zadanie z konkursu algorytmicznego dla uczniów szkół średnich. Zwróciłem na nie uwagę, gdyż współczynnik poprawnych rozwiązań wynosił lekko ponad 30%, a skoro to konkurs dla licealistów to powinienem sobie dać radę. I tu pierwszy szok, nic z tego&#8230; Wiedza jaką dysponowałem okazała się daleko nie wystarczająca, a próby znalezienia rozwiązania podanego na tacy spełzły na niczym. Co dodatkowo rozbudziło moją ciekawość to fakt że na forach poświęconych programowaniu, nikt nie szuka pomocy.<br />
Zadanie finalnie okazało się rozbudowaną grą Nim, ale bez znajomości jednego twierdzenia teorii gier prawdopodobnie siedziałbym na tym jeszcze dłuuuugo&#8230;<br />
Treść zadania dostępna pod adresem <a href="http://hs.spoj.pl/problems/HS09GAME/">http://hs.spoj.pl/problems/HS09GAME/</a><br />
<span id="more-381"></span><br />
Wspomniane twierdzenie to Twierdzenie Sprague-Grundy&#8217;ego. Gra przestawiona w zadaniu spełnia wszystkie założenia pozwalające na skorzystanie z twierdzenia. W połączeniu z dokładnie omówioną optymalną strategią, opisem pozycji wygrywających i przegrywających w grze Nim, pierwszą część zadania można rozwiązać w zaledwie 9 liniach</p>
<pre class="brush: python">
# gry - lista skladajaca sie z list reprezentujacych gre. Kazda reprezentacja
# gry to kolejna lista zaiwerajaca ilosc &#039;kijkow&#039; na kolejnych stosach
def graj(gry):
    sg = (0, 0, 1, 1, 2, 2, 3)
    for gra in gry:
        g = []
        reszty = []
        for stos in gra:
            reszta = int(stos)%7
            g.append(sg[reszta])
            reszty.append(reszta)
        wynik = reduce(lambda x,y: x^y, g)

        if wynik :
            print &quot;Julia wins.&quot;
        else :
            print &quot;Robert wins.\n&quot;
</pre>
<p>Lekki problem pojawia się przy ustalaniu ruchu wygrywającego. Nie wiem czy istnieje jakieś szybsze rozwiązanie niż takie trochę brute-force&#8217;owe która ja wykorzystałem. Polega ono na stwierdzeniu na jakiej pozycji ( wygrywającej czy przegrywającej ) znalazł by się gracz gdyby nie było jednego stosiku, a następnie obliczeniu czy da się odjąć taką liczbę patyczków żeby zostawić przeciwnika na pozycji przegrywającej.<br />
Dodatkowo oprócz wskazania ruchu wygrywającego należy wskazać ten podczas którego bierze się najwięcej patyczków ze stosu o najmniejszym numerze, co w lekki sposób komplikuje sprawę.:</p>
<pre class="brush: python">
        stos_wygrywajacy = 0;
        licznik = 0
        blokada_5 = False
        blokada_3 = False

        # odwrocenie list, sprawdzanie od konca
        gra_rev = gra[:]
        gra_rev.reverse()

        g_rev = g[:]
        g_rev.reverse()

        reszty.reverse()
        for reszta in reszty:
            # lista reszt bez kolejnych stosow
            tmpr = reszty[:]
            tmpr.pop(licznik)

            # xor wartosci f. Sprague-Grundy&#039;ego
            # bez kolejnych stosow
            tmpg = g_rev[:]
            tmpg.pop(licznik)
            tmpw = reduce(lambda x,y: x^y, tmpg ,0)

            if sg[reszta-5] == tmpw and int(gra_rev[licznik]) &gt;= 5:
                wygrywajacy = 5
                stos_wygrywajacy = len(reszty) - licznik
                blokada_5 = True
            elif sg[reszta-3] == tmpw and int(gra_rev[licznik]) &gt;= 3 and blokada_5 == False:
                wygrywajacy = 3
                stos_wygrywajacy = len(reszty) - licznik
                blokada_3 = True
            elif sg[reszta-2] == tmpw and int(gra_rev[licznik]) &gt;= 2 and blokada_5 == False and blokada_3 == False:
                wygrywajacy = 2
                stos_wygrywajacy = len(reszty) - licznik

            licznik += 1
</pre>
<p>Jeśli ktoś zna szybsze rozwiązanie chętnie je przeanalizuję <img src='http://piotr.doniec.eu/devlog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Zaznaczam, że nie dam sobie głowy uciąć że algorytm jest poprawny, bo nie ma już możliwości zgłoszenia rozwiązania &#8211; upłynęły terminy.</p>
<p><strong><em>EDIT</em></strong>:<br />
Lekko poprawiona wersja, działa trochę szybciej, natomiast i tak nie umożliwia zdobycia maximum punktów. Jesli nie ma jakiejś sztuczki na ruch wygrywający, a podejrzewam że coś jest, to lepiej zakodzić to w C&#8230;</p>
<pre class="brush: python">
        stos_wygrywajacy = 0
        blokada_3 = False
        blokada_2 = False
        licznik = 0
        for reszta in reszty :
            tmpg = g[:]
            tmpg.pop(licznik)
            tmpw = reduce(lambda x,y: x^y, tmpg, 0)

            if sg[reszta-5] == tmpw and int(gra[licznik]) &gt;= 5:
                wygrywajacy = 5
                stos_wygrywajacy = licznik + 1
                break
            elif sg[reszta-3] == tmpw and int(gra[licznik]) &gt;= 3 and blokada_3 == False:
                wygrywajacy = 3
                stos_wygrywajacy = licznik + 1
                blokada_3 = True
            elif sg[reszta-2] == tmpw and int(gra[licznik]) &gt;= 2 and blokada_3 == False and blokada_2 == False:
                wygrywajacy = 2
                stos_wygrywajacy = licznik + 1
                blokada_2 = True
            licznik += 1
</pre>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2010/01/hsspoj-zadanie-ktore-nie-dawalo-mi-spokoju/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Adnotacje w servlet 3.0</title>
		<link>http://piotr.doniec.eu/devlog/2009/12/adnotacje-w-servlet-3-0/</link>
		<comments>http://piotr.doniec.eu/devlog/2009/12/adnotacje-w-servlet-3-0/#comments</comments>
		<pubDate>Sat, 26 Dec 2009 17:43:58 +0000</pubDate>
		<dc:creator>pejotr</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[glassfish]]></category>
		<category><![CDATA[jee]]></category>

		<guid isPermaLink="false">http://piotr.doniec.eu/devlog/?p=369</guid>
		<description><![CDATA[W JSR 315: Java Servlet 3.0 Specification zdefiniowano dodatkowe, nowe adnotacje mające na celu ułatwienie tworzenia aplikacji. Referencyjna implementacja została już zawarta w jednym z &#8222;nocnych wydań&#8221; serwera Glassfish. Dziwi zatem fakt że informacja o tym że servlety nie wymagają już odpowiednich wpisów w deskryptorze rozmieszczenia ( ang. deployment descriptor ) nie została umieszczona w]]></description>
			<content:encoded><![CDATA[<p>W JSR 315: Java Servlet 3.0 Specification zdefiniowano dodatkowe, nowe adnotacje mające na celu ułatwienie tworzenia aplikacji. Referencyjna implementacja została już zawarta w jednym z &#8222;nocnych wydań&#8221; serwera Glassfish. Dziwi zatem fakt że informacja o tym że servlety nie wymagają już odpowiednich wpisów w deskryptorze rozmieszczenia ( ang. deployment descriptor ) nie została umieszczona w oficjalnym tutorialu. Mimo że przykładowe projekty dla serwletów w SDK 6 zostały napisane od nowa żaden z nich nie wykorzystuje nowych adnotacji.<span id="more-369"></span><br />
Dodane adotacje to: @WebServlet, @ServletFilter, @WebServletContextListener, @WebInitParam oraz @MultipartConfig więcej informacji na ich temat można znaleźć w pakiecie javax.servlet.annotation.<br />
Przykładowe wykorzystanie:</p>
<div class="codecolorer-container java mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@WebServlet<span style="color: #009900;">&#40;</span>name<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;HelloWorld&quot;</span>, urlPatterns<span style="color: #339933;">=</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&quot;/helloworld&quot;</span><span style="color: #009900;">&#125;</span>, displayName<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;DISPLAY NAME&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> HelloWorld <span style="color: #000000; font-weight: bold;">extends</span> HttpServlet <span style="color: #009900;">&#123;</span><br />
<br />
@Override<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> doGet<span style="color: #009900;">&#40;</span>HttpServletRequest request, HttpServletResponse response<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throws</span> ServletException, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aioexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">IOException</span></a> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//processRequest(request, response);</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
]]></content:encoded>
			<wfw:commentRss>http://piotr.doniec.eu/devlog/2009/12/adnotacje-w-servlet-3-0/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
