4 Aralık 2008 Perşembe

Command pattern in Python


I continue with "x pattern in Python" series, the articles i posted here are not tutorials or some professional learning resource. I poste them here only for myself to rememer the things when i need them :) What is the command pattern and why wee need it ? Well imagine you have a class that controls some operations on files, writing , reading , closing , and maybe many more. In first sight i would complete that like this :


class FileOperator:

def operation1(self):
pass

def operation2(self):
pass

#snip snip snip ....

Well that implementation seems enough for now, but what if we want to supply a simple api to users like that


f = FileOperator()
f.process_command()


Well, with current implementation that doesnt seem to be possible, the current implementation is kind fo static and user has to know the internals of the FileOperator class. If the users want some extra functionality like undo or logging, it will not be very easy to be implemented. And every change that has to be done will effect the current client code which is not cool. Also user may want when call the process_command to execute multiple commands like write_to_file and read_contents and etc. What we will do is again the basic OOP remove the parts that can change in the future. We will remove the executer parts and wiill assing them when we need them. Ok when reading it doesnt seem so easy but the code is easier:

Here is my implementation of the Command Pattern : LINK

After that implementation you will able to do things like that :

def test_me_yo():
"""
Lets see that one
"""
tmp_file = open("some.txt","w")
tmp_file.write("hehehe\n")
tmp_file.close()

#end of initial data
#first lets read the contents of the stuff
fe = FileEditor()
fileman = FileMan("some.txt")
fread = FileReadCommand(fileman)
fwrite=FileWriteCommand(fileman)
fe.set_command(fread)
fe.process_command()

#append some info to the end of it
fe.set_command(fwrite)
fe.process_command("add some text here")
fe.set_command(fread)
fe.process_command()

#lets now go and create an command manager
cm = CommanManager()
cm.add_commanders(fwrite,fread)
fe.set_command(cm)

fe.process_command("\n Add another sting here ")
print "First undo :"
fe.undo_process()
print "Second undo :"
fe.undo_process()
print "Thirrd undo :"
fe.undo_process()

Well it is pretty pluggable design you can combine the commands you like do "undo" all the magic you need. What i learned from Design Patterns is they are based on the same principle "remove the parts that will change in the future" ,separating the concerns is very important ...

2 Aralık 2008 Salı

Template Design Pattern


The next step in DP land is Template Design Pattern, well what is it ? As far as i understood there is nothing special and new under the hood. You have an abstract class with methods to be overriden by its sunclasses. The main difefrence is you have a one or more template methods which draw the flow of the things. A simple example maybe :


class MainClass(object):

def operation1(self):
#do stuff

def operation2(self):
#do stuff

def __template_method(self):
self.operation1()
self.operation2()



What we did here is to supply an API for users to override the operation1 and operation2 but we want to control the overflow by template_method, if you want more extendible structure you may also make it public. Well i know that pattern i have used it in lots of places but didnt know its name :) The new thing i learned from Head First is the hook methods , you make them optional for the client code. For example:

class MainClass(object):

def operation1(self):
#do stuff

def operation2(self):
#do stuff

def hook(self):
pass

def do_you_want_hook(self):
return True

def __template_method(self):
self.operation1()
self.operation2()
if self.do_you_want_hook():
hook()


Ok the difference is if user wants something extra to be executed he/she can override hook and do the extra stuf that is needed there,otherwise that method will not be invoked (well it will be but nothing will happen).
That is all for the template pattern, we know you,you are not new here :)

1 Aralık 2008 Pazartesi

Factory Pattern in Python


Our next step in DP is object factories. Creating objects with if else clauses sometimes may not be very flexible for our programs. Some of the objects may neeed more complex and long initializations other maybe simple etc. Because of that it is cooler to have some methods or some classes that give you the instance you need. For exmple think about a client program which needs a slash directory or file manager. If you're trying to have your program platform independent you should have different versions for Windows and Linux based machines. Therefore when you client is initializing the File manager it should everytime do

if linux:
do sth
else:
do another


But for a framework that is not very flexible and when some code of FileManager changes (some code of initialization) you should change your client code which is not cool. It would be better if you have some class that gives you the instance you need, in our example FilemanagerFactory.get_instance() so client code will not care about the platform and other annoying stuf it will just get the instance it needs. Yep that is factory pattern ...
To demonstrate the factory thing i wrote a simple example that is responsible for creating Validators, if you have a string you get a string validator if you have an integer you have integer valiator and etc . Here is the link: LINK

To test the code you need sth like that :

from pyalgorithm.dp.factory import *

def test_facto():
my_value = "Some_strrrrrrrrr"
factory = ValidatorFactory()
validator = factory.create(my_value)
print validator.validate()

my_value = 11
validator = factory.create(my_value)
print validator.validate()

my_value = 11.12
validator = factory.create(my_value)
if not validator:
print "No object created ..."

Well that is all, factory pattern may not be very important for little projects but if you have to initialize lots of classes it maybe wisw to have some class to do that for you.

29 Kasım 2008 Cumartesi

Singleton Pattern in Python

The Singleton actually is not something very different or new invention. The purpose of it is to have only a single instance of some class so you can have a global point of access which is cool. For now i think i can use it for configuration manager classes, some cool loggers and some context variables. Maybe i will find more of em. The Singleton pattern is a little bit different from one that is in Java. In Java to make a singleton you have to make your constructor private and have some static method to do the instance initialization. In python what you have todo is override the __new__ method of the Singleton candidate. There are lots of examples on the net related with that topic so you can search one before use mine. Actually mine is not written or thought by me i found it also (from aspn CookBook site) :)

Here is the first version i found and think is good : LINK
As you will see there is some time and sleep things in it , i put em there to test what happens when some threaded classes use it. And as you may imagine some of the threads got different references of that Class. Here is the Thread i used :


from threading import *
import time
import thread

class ThreadSingleton(Thread):
"""
A simple thread to work on that
"""
def __init__(self,id):
Thread.__init__(self)
self.id = id

def run(self):
"""
Here initialize the singleton
"""
self.s=Singleton()

print "Im thread %d and %d"%(self.id,id(self.s))
time.sleep(2)

def get_singleton(self):
return id(self.s)



Here is the code that tests it :

def singleton(t="threaded"):
for j in range(100):
threads = []
for i in range(10):
if t!="threaded":
threads.append(ThreadSingleton(i))
else:
threads.append(RealThreadedSingleton(i))

for i in threads:
i.start()

for i in threads:
i.join()

print "The final ids are :"
t0 = threads[0]

for i in threads:
assert t0.get_singleton() == i.get_singleton()

t0.s.destroy()


if j%10 == 0:
print "************** %d COMPLETED **********"%j



After those tests i got some Assertion Errors because some of the threads got different references of the object. What we know from here is that our Singleton is not thread-safe and we should fix it. Here is the threaded version of the Singleton LINK :

To test that new verison i nedded some new ThreadClass to call the new created Singleton :


class RealThreadedSingleton(ThreadSingleton):

def run(self):
"""
Here initialize the singleton
"""
self.s=ThSingleton()

print "Im thread %d and %d"%(self.id,id(self.s))
time.sleep(2)



After final changes i run the tests 1000 times and didnt have any problems. Why we should bother to have Singleton threa-safe , because i'm going to use it in some frameworks that uses threads heavily, so icant be sure when that one will be called. To conclude, when write some cool classes always should think the posibility of theraded usages.

28 Kasım 2008 Cuma

Decorator Pattern in Python


Our next step in DP is Decorator pattern, as u know Python also has some decorator options you can apply to your programs by @ sign. But if you want to apply decoration to classes in object level you have to change the stuff a little bit. I always thought that Java's IO library is very confusing, you create a FileInput class then you put it in a BufferReader and etc. When i read the Decorator chapter in Head First i realized that the Java IO API is using that pattern there. Well why do you need decorator pattern? Lets go from IO API example :
1. You have a normal reader
2. You need a reader that converts the input to lowercase, so what you do is create a new UpperReader
3. You need now a reader that converts input to a sha1 sum , what you do is create a Sha1Reader
4. You need a reader that converts input to uppercase sha1sum , what you do is create a Sha1UpperReader
5. The 4. item can be removed if you used the decorator pattern

Shortly, decorator pattern wraps an object and change its flow before or after the target operation. For the example above you can change the incoming input or process it to sth else.

Here is the implementation i wrote in Python and put on my personal github repo : LINK

A sample usage of above can be like that :

  1. def deco():

  2. from pyalgorithm.dp.decorator import *



  3. print "The normal file reader content"

  4. n = NormalFileReader("some.txt")

  5. print n.read_content()



  6. print "Sha1 sum of the read info"

  7. sh =DecoratoSha1Reader(

  8. NormalFileReader("some.txt")

  9. )

  10. print sh.read_content()



  11. print "Sha1 sum but with upper cases"

  12. up = DecoratoUpperFileReader(

  13. DecoratoSha1Reader(

  14. NormalFileReader("some.txt")

  15. )

  16. )



  17. print up.read_content()



The output is sth like that:

The normal file reader content
Hey im the content!!!

Sha1 sum of the read info
5fd77bd8e4f80ec432c71a09033a7ef51de60448
Sha1 sum but with upper cases
5FD77BD8E4F80EC432C71A09033A7EF51DE60448


Well, it is the end of the today's pattern "decorator man". The post will be a good reference for me when forget the things :)

25 Kasım 2008 Salı

Observer Pattern in Python


Well here are the first things i got from "Head First Design Patterns" book :) I was working on a big web project and have also some small open source projects i try to finish. I stoppped codding on that projects immediately after read the first chapter of the book :) I realized that have big gaps in my programming skills about patterns. What i know now is :

- Knowing OO principles and rules doesnt make u a OO guru.
- Inheritance is not the best way of code reuse.
- Inherit the static parts and use composition for things that can change in the future.
- Less dependency between classes is alway better.

Will add to those more in the future i think.
Ok lets go back to the title of that entry. Sometimes we need to send some notifications to other classes from a specific class. What i would do before knowing the observer pattern would be sth like that. I would define a notifier() method and will call the classes i want to notify :

  1. def notify(self):

  2.    classA.update(args)

  3.    classB.update(args)

  4.    classC.update(args)

  5.  


Ok it seems good for now but wat happens if you want to notify the classes D and E in the future u have to add them to the list above. That means altering the existing code which may not be a good idea. Ok now the classB doesnt want anymore to be notified , so what happens now ? It is very clear that the structure above is not the best for that situation. What we need is a dynamic srtucture which will allow us to add and remove new observers during the runtime without altering the existing code, so that is where the observer pattern comes into the scene ...

Here is the code i wrote to make a simple scenarion for observer pattern on my personal git_repo : LINK
Now we can do sth like that easily :

from pyalgorithm.dp.observer import *



print "I creatte the our subject"

c_s = ConcreteSubject()

c_s.my_x = 22

c_s.my_y =33



print "I notify my subscribers :"

c_s.values_changed() #that can be done dynamic but it is cool for now



print "Lets add a new XObserver"

x_o = ObserverX()

g_o = ObserverGeneral()

c_s.add_observer(x_o)



print "I notify my subscribers :"

c_s.values_changed() #that can be done dynamic but it is cool for now





print "Lets add a new GeneralObserver"

c_s.add_observer(g_o)

print "I notify my subscribers :"

c_s.values_changed() #that can be done dynamic but it is cool for now



print "The X observer doesnt want to know anything about us remove him"

c_s.remove_observer(x_o)



print "I notify my subscribers :"

c_s.values_changed() #that can be done dynamic but it is cool for now

The output for that will be as follow :

I creatte the our subject
I notify my subscribers :
Lets add a new XObserver
I notify my subscribers :
Im X observer and got : 22
Lets add a new GeneralObserver
I notify my subscribers :
Im X observer and got : 22
I got all of them Here is my values 22 and 33
The X observer doesnt want to know anything about us remove him
I notify my subscribers :
I got all of them Here is my values 22 and 33

Well i think it became pretty dynamic ,i have lots of ideas where i can use that pattern. As a conclusion what i can say is that "Head First Design patterns" book is changing my vision to OO programming.

TO BE CONTINUED ...

20 Kasım 2008 Perşembe

Got My Amazon Books




Really excited, i just got my amazon orders two great books. I hope to be better programmer now with those pearls :) The books arrived two weeks later from the estimated date but who cares i got em. One of them is about design patterns and other is about algorithms and programming. Here are the title's of books :

1.Programming Pearls
2. Head First Design Patterns

After finish em will write my reviews :)

29 Ekim 2008 Çarşamba

Recursive fibonacci Case Study

In that post i'm going show u a test that i made about recursive calls in Python compared to other languages. The tests used are Python,Python C extension and Java. I always heard that using recursive calls in Python is not very wise, that time i decided to discover it myself. Well i run the 3 programs to find finacci 40. number and got their times with time command in F9. Tests do not claim anything so do not bother me with garbage :) Here they are :

Python
[makkalot@localhost pyalgorithm]$ time python py_fibo.py 40
The result is : 102334155

real 6m32.110s
user 6m22.153s
sys 0m0.519s



Python_Ex :
[makkalot@localhost fibo]$ time python ex_fibo.py rec 40
The recursive result is : 102334155

real 0m3.039s
user 0m2.902s
sys 0m0.017s



Java
[makkalot@localhost bin]$ time java sorts.FiboMan rec 40
The recursive result is 102334155

real 0m4.053s
user 0m2.755s
sys 0m0.095s

Conclusion : The results suprised me a little bit. I knew that Python as a recursive language is slow but the time above is a disaster. Therefore i know now if i need sth recursive in Python i will write it as a C extension. The java also suprised me because its time was very close to C extension. Those Java guys are getting better, maybe JavaFX may make to become a Java programmer :)

Btw, here are the codes :
Python : Link
C extension : Link
Java : Link

A new Django Site Added to public

In last 2 weeks i've been working as freelancer, searching for people around the world who need Django/Python help for their projects. It is kind of exciting because i meet new people and do different kind of work everytime. Well one of these was injazzat.com a static firm site which was converted to Django site. The guy who was responsible for that site hired me to fix some of bugzz in site. It seemed as an easy stuff there was a few typos some template errors. However when i went deeper into code saw that hardcoded parts that made that job a nightmare :) I spent all my week to fix that mess and now most of the parts are real dynamic and the site follows the DRY :) At the end of work the guy told me that i was the 4th person who tried to fix that site and succeed finally. All previous developers escaped or dissappeared ... The temporary link of site is here ,i dont know if it will be there tomorrow but as reference just put it here. I hope got more exciting projects in the future ...

To conclude , do not write hardcoded programs because someday they will be seen by other people believe me :)

Note : and also thanks to adk for his help with those designer and css stuff

Make Python Smoke


In that post i'm going to talk i little bit (not too much ) about some old computer problems. ı have always been excited bout that kind of problems some of most famous ones are :

* Producers-consumers problem
* Dining philosophers problem
* Sleeping barber problem
* Readers-writers problem

All of them has a main purpose to make computer to solve the problem by using threads/processes and semaphores/locks. When think about those problems always my head is going to explode (hey i'm not so clever) and that is the fun part :) I had OS lessons in university but never had chance to write the implementation of these problems (what a practical school). Therefore i decided to write some of these problems in Python so i can explode my head and have fun with Python. One that i have written is Cigarette smokers problem [1] and put its code on my public git repo so other folks can grab it and play with it. The code is here : Link

To run the code just python cigarrette.py and watch how people smoke and die :) If you discover some deadlock or any other fatal mistake please drop a comment to light me .Have fun!

Resources :
[1]Wikipedia : http://en.wikipedia.org/wiki/Cigarette_smokers_problem
[2]My public git repo : http://github.com/makkalot/pyalgorithm/

16 Ekim 2008 Perşembe

Hash That Diectory - Case Study

Hash That Directory - Use Case

In my spare time i try to finish my pysigner software. My aim for that project was to make a tool similar to keytool (Java). Therefore someone who needs
to add that X.509 stuff in its application can use my pysigner. One of the part that i'm writting now is to collect the sha1sums of a directory so i can sign verify the contents of that directory.
Computing the hashes is really easy you get some data in buffer and call the sha.update() method and then you have the hash. Firstly i have written that
part in normal way. By normal i mean without using threads. After that i thought it would be better to use threads for that purpose because most of the time we do IO operations. That way the python thread manager will switch when i read into buffer and will do the computation in another one ,cool isnt it ? Actually i was expecting a very big difference in times between normal and threaded implementation. Ok talk is cheap give the code and times :

Normal implementation :
[makkalot@acerfedora pysign]$ time python top_level.py
Straight Tester ...

real 9m52.081s
user 2m23.076s
sys 0m51.895s

4 THreaded implemenatation:
[makkalot@acerfedora pysign]$ time python top_level.py
4 Threadded Tester ...

real 10m7.411s
user 1m50.216s
sys 0m42.488s


8 Threaded implementation:
[makkalot@acerfedora pysign]$ time python top_level.py
8 Threadded Tester ...

real 10m23.042s
user 2m42.285s
sys 0m59.676s


The results are really strange are the Python threads a big illusion ? Sometimes i think they are like mastubation nothing real at all :)
BTW, if someone finds a bug and thinks it can be improved plz comment ...

Here is the normal implementation :
Link :
Here is the theraded part :
Link :

25 Ağustos 2008 Pazartesi

Case Study Iterative Fibonacci

Wow, it has been long time and i didnt write anything here. That will be a series of articles in which i will be writing some of the algorithms with (mainly) Python. Sometimes i will implement some of them with Java and some of them as Python C extension. I wont use C++ sorry :) I think it is a failure of the object oriented programming but , that is another story. I like the old school C instead of it. In that series i will compare the written algorithms and codes in some areas; how fast they are (O notation and time),how easy was to write them . Any of the comparisons made here are my personal thoughts about that so , i dont claim anything ...

Python :Link
Time :
[makkalot@localhost pyalgorithm]$ time python py_fibo.py 1000000
Result written into fibo.txt

real 3m47.825s
user 3m46.481s
sys 0m0.391s

Level of writing : I think it was quite easy to implement that computation. Additionally i didnt have to think about large numbers python handled all the stuff for me which was cool .

Python Extension :Link

[makkalot@localhost fibo]$ time python ex_fibo.py 1000000
Result written into fibo.txt

real 3m43.437s
user 3m41.899s
sys 0m0.419s

Level of writing : Ah that one was not easy to write :) Firstly i had some difficulties and memory leaks with Py_INCREF and Py_DECREF stuff. The second problem was the big integers thing, so i had to use some Python stuff which made that problem easier.(I wont write that stuff in pure C no no ...) If someone has better solution here please post ...

Java:Link
Time:
[makkalot@localhost bin]$ time java sorts.FiboMan 1000000
The fibo result is :written to fib.txt

real 5m31.204s
user 5m18.196s
sys 0m8.927s

Level of writing : Yep that was really easy to write. And also Java has some good solution for these big integers so i only used BigInteger class to handle that situation.But, the code is a little bit longer than Python code.

Concluion : I was really suprised when the pure Python code had almost the best time, so i think i can use the iteratve computations in Python. The dissappointment was the C extension i was expecting some really big difference in time. However the reason seems to be used Python.h functions in C extension. And the Java code really suprised me, its time was really acceptable so people who use Java may write their iterative computational solutions without any concern. That wass my fibonacci iterative test. The second of the series will be the recursive solution for fibonacci and my comments about it ...

10 Haziran 2008 Salı

What can save your A.. !

In last 2 weeks i didnt sleep too much, coding about 8-10 hours a day. It is really much but have to do thousands of things. I'm trying to finish my school project,codding for google (the fun part) and also do some extra works. Yes it is too much, but in moments like that there are techonologies that saves our and especially my ass :

- Django saves your ass, you can sell you web site get your 200$ only in 2 days. (no joke)
- Turbogears saves you ass, you power up you ajax based site in couple of days
- Qt saves your ass, you can build your gui stuff in couple of hours for you project that you worked on all 4 months. Even in C++ but that is another story :)
- Python saves your ass you open ipython, and do all the stupid stuff you have to learn and then just dive in real coding,no semicolons, no segafaults,no compilation all great things you can imagine !
-And also vim :) It makes you code like a ninja :)

28 Mayıs 2008 Çarşamba

And GSOC 2008 is on

I didnt have time to post anything about last changes in my life :) Yep i have become a gsoc student that year. I will be working for a very fun Fedora project named "func". It is based on network automation and other shiny stuff like SSL'ed connection and etc. You can check the here for more information. My mentors are great very fun people (mpdehaan and alikins from #func on irc)i think we will achieve interesting results that summer. During my gsoc period i will blog here in English under gsoc2008 label. Let the coding starts :)

8 Mart 2008 Cumartesi

Algoritmaların Programcılara Sitemi


Birisi yolunu kaybeder de buraya gelirse bunu okumasın , bu benim ve paranoyak kişiliğim arasında yaşadığım bir bunalımsal ikilem (ne demekse), dışarı git hava güzel boşver bunları!

Bu girdide beni 2,3 gündür rahatsız eden bir konudan bahsedeyim. Herkes ben de dahil olmak üzere birşeyleri öğrenme ve iş hayatına hazırlanma telaşı içeresinde. Bu telaş içindeyken şu dili öğreneyim , şu teknoloji de CV'imde olsun gibi kaygılar var. Ama aslında programcılığın temeli olan bazı kısımlar ihmal ediliyor. Bunlardan bence en önemlisi de algoritma bilgisidir.

Bu aralar bir yüz tanıma projeseyile uğraşmaktayız ve de gerçekleştirmek için orada bir sürü matematiksel adımları ve algoritmaları anlamak gerekiyor. Onları okurken ne kadar köreldiğimi farkettim, O(n) falan hepsi gitmiş kafamdan. Porgramcılığımız bir "if" ve "for"'a bakmaya başlamış :|. Bence bir programcı ilk adımda programın optimize halini yazamıyor olsa da sonra bunu değişik algoritmalar ile düzeltebilmesi gerekir. Son zamanlarda yazdığım kodlar "hep çalışsın yeter" seviyesinde oluyor. Evet bu da üzüyor beni... Bir programcının elinde algortimlarını tuttuğu bir kütüphanesi olmalı,şu kod bunda nasıl çalışır dediğinde hemen bunu deneyebilmeli. Ve O(n) notasyonları ile hemen performans farklarını ölçebilmelidir. Bunları çalıştığı yer için değil kendisi için yapmalıdır.

Evet bahsettğim gibi sıkıntım büyük, birşeyleri değiştirmek gerekir. Aslında düşünüce, kod içeresinde bir algortima olmasa programcılığın tadıı kalır ki ? Bir veritabanına bağlan ordan veri çek sonra update et ... bunlarla gelişme sağlanamaz. Yapılmışı var kardeşim hasta mısın diyorsanız, hayır diyorum çünkü bu şekilde köreliyoruz. Zaten milletçe de herşeyin yapılmışı var deyip hiçbişey yapmıyoruz. Pardus projesindekiler de bu şekilde düşünseydi bizlere bu kadar çok şey öğreten bu proje de şimdi olmazdı... Neyse konu kaydı yine bir yerlere :)

Şimdi aklıma geldi hergün olmasa da belli aralıklarda öğrendiğim algoritmaları Python (çocuk bahçesi dilim) ile yazayım ve bir yerlere koyayım. Bu şekilde hem körelmemiş oluruz hem de belki ileride birilerinin işine yarar. Evet en azından haftada 2 kez bir algoritma girdisi yapmam gerekiyor buraya , yoksa sonum hiç iyi değil :)

18 Şubat 2008 Pazartesi

Python ve Doğal Dil İşleme

Bu girdiyi uzun zaman önce yazmam gerekiyordu ama işte yoğunluk... Bir yandan özgürlükiçin.com altyapısı diğer yandan dersler derken burası ıssız bir yer oluvermiş. Pardusum'da gezinirken gördüğüm küçük bir script ile bu girdiyi yazma kararı aldım. Okulda bir aralar Doğal Dil İşleme dersi alıyordum ve yazarların ruh hallerini tanıyan birer program yazmamız istendi. Kullanıcıya birtakım html dosyaları veriliyor ve program o yazarın ruh halini söylüyor. Aslında çok zevkli ve zor bir konu. Ben tabii tembelliğimden dolayı yine son akşam ne nasıl yapalım derken oturdum, Python'un NLP (Natural Language Processing) kütüphanesinin dokümanını okumaya başladım. Sonra baktım olmayacak ben yazayım dedim. Kendimce belirlediğim kriterlere göre 1 saatlik süreden sonra ödev hazırdı. (Python sağolsun) Yazar tanıma kriterlerim ise şu şekilde oldu :

-Türkçe'de bulunan bazı ünlem kelimelere ruh hali atandı
-Kullanılan bazı noktalama işaretlerine ruh hali atandı
-Kullanılan bazı html taglarına ruh hali atandı
-Gülücük vs gibi (bunu eklemedim ama bence iyi fikirdi :) )

İşte bu şekilde kendimce birşeyler atadım , sonra tarattğım 10 dosyadan 5,6 doğru belirleniyordu :) Bu şekilde son anda yine bir yusuf yusuf yaratıcılığının sonuçları bunlar... Hoca da diğerlerinden değişik olduğu için beğendi .(Ben, "lan bu ne biçim şey diyecek sanmıştım"). Neyse geçtik Allahtan kodu da buraya koyalım birileri gülücük feature falan ekler :)

İndir