Wednesday, 29 December 2010

PythonCE for Windows CE

I'm playing with the PythonCE library for Windows CE devices, and I'm building a little graphic application (GUI) with it just to be sure that the chosen technology is the appropriate. I've always used the embedded VC++ and VB and I think it's time to move on and try new things. I've tested this library on my DELL Axim x50.

Firstly, you have to download the PythonCE library for your device. Download PythonCESetup.exe from sourceforge. Once downloaded, you have to execute the PythonCESetup.exe and it automatically will install the PythonCE on your WindowsCE device.

Once done, your pocket device will have installed the python command line:
Then, for executing graphical applications, we need to install the TKinter library. You'll succeed if you follow the next instructions to install the TKinter library on your pocket device:

Using TKinter for Windows CE:

To use Tkinter you have to download this additional software Tkinter.zip and unpack it on your PDA.
  1. The following archive contains 2 folders: "Windows" and "tcl8.4.3". Put all the files in "Windows" in the "Windows" folder of your PDA.
  2. Create a "lib" folder in the "Program files" folder of your PDA.
  3. Inside the "tcl8.4.3" folder in your archive you will find two folders: "library" and "tk8.4". Copy the "tk8.4" folder into the "lib" folder you just created on your PDA.
  4. Copy all the files in "library" into a folder named "tcl8.4" you will create inside the same "lib" folder.
If  you succeed, you can execute the next example and try it on our device:

from Tkinter import * 

def onCanvasClick(event):                  
    print 'Got canvas click', event.x, event.y, event.widget

root = Tk()
root.title('MyAPP')
canv = Canvas(root, width=100, height=100)
img = PhotoImage(file='\\My Documents\\logo.gif')
canv.create_image(240,250, image=img, anchor=CENTER)
obj1 = canv.create_text(50, 30, fill="red", text='text1')
obj2 = canv.create_text(50, 70, fill="red", text='text2')
widget = Label(root, text='This is a Label')
widget.config(bg='black', fg='yellow')             
widget.pack(expand=YES, fill=BOTH)
canv.bind('<Double-1>', onCanvasClick)                  
canv.pack()
root.mainloop()

Output Example:

Related links:

Tuesday, 21 December 2010

Building today the schools of tomorrow

This post is dedicated to Richard Gerver who attended the Global Education Forum held in Madrid this year, where different topics related to education were discussed. This video is the last one published in Redes about building today the schools of tomorrow (in Spanish).

"In The XXI century the only thing we know for sure is that it's going to be very different. Now the industry needs more imagination, more creativity, more skilled workers to work together, with a different mentality, a mentality more open to suggestions from others on their team". 
Philip Hudson
Director SEK Catalonia
More videos:

Changing education paradigms

This post is dedicated to Ken Robinson an its "Changing education paradigms". "Creativity expert Sir Ken Robinson challenges the way we're educating our children. He champions a radical rethink of our school systems, to cultivate creativity and acknowledge multiple types of intelligence".

Enjoy the video!.

Monday, 20 December 2010

Piecewise function plotter

I've been working lately on a front-end application to draw and generate the piecewise-defined functions that are mainly used for the input fuzzy sets. This application is developed with Delphi and for generating the outputs it uses the GNUplot and the LateX equation editor. The application is called Thundax Piecewise v1.1 and you can download it from here. This win32 installation package contains the required files to work with the GNUplot. This software is for academical purposes and with it you can define the piecewise-defined functions without wasting your time trying to draw the graphs and the equations.

Using the application:
If you want to get the equations from the previous image, you only need to add the points (x,y) (defined as 4 points per graph), add the equation description, the range and the number of samples:
The description of the parameters:
  • Points per graph: default value = 4. Number of points that are used to define the function:
  • Range-x: Default value [0:30]. Range to be displayed at x-axis.

  • Range-y: Default value [-0.1:1.1]. Range to be displayed at y-axis.
  • Samples: default value = 1. Number of samples for the x-axis. In a range from 1 to 10 with a sample of 1 it will show all the numbers.

Once everything is done, you just need to let the application generate the graph output automatically using GNUPlot (If the function is not plotted, check the script and execute it into the GNUplot command prompt):
And then copy-and paste the output script to Latex editor and get the piecewise function for each one:
The only thing the applications does, is to parse the input data and transform it as scripts for the GNUplot and Latex. The conversion is pretty simple and the scripts examples are like these:
GNUPlot Script example:
cold(x)=(x<=40? 0: cold2(x))
cold2(x)=(x<=40 & x > 40? 1: cold3(x))
cold3(x)=(x<=50 & x > 40? -0.1*x + 5: cold4(x))
cold4(x)=(x<=50 & x > 50? 1: cold5(x))
cold5(x)=(x>50? 0:0)
cool(x)=(x<=40? 0: cool2(x))
cool2(x)=(x<=55 & x > 40? 0.066667*x  -2.666667: cool3(x))
cool3(x)=(x<=55 & x > 55? 1: cool4(x))
cool4(x)=(x<=65 & x > 55? -0.1*x + 6.5: cool5(x))
cool5(x)=(x>65? 0:0)
justright(x)=(x<=60? 0: justright2(x))
justright2(x)=(x<=65 & x > 60? 0.2*x  -12: justright3(x))
justright3(x)=(x<=65 & x > 65? 1: justright4(x))
justright4(x)=(x<=70 & x > 65? -0.2*x + 14: justright5(x))
justright5(x)=(x>70? 0:0)
warm(x)=(x<=65? 0: warm2(x))
warm2(x)=(x<=75 & x > 65? 0.1*x  -6.5: warm3(x))
warm3(x)=(x<=75 & x > 75? 1: warm4(x))
warm4(x)=(x<=85 & x > 75? -0.1*x + 8.5: warm5(x))
warm5(x)=(x>85? 0:0)
hot(x)=(x<=80? 0: hot2(x))
hot2(x)=(x<=90 & x > 80? 0.1*x  -8: hot3(x))
hot3(x)=(x<=90 & x > 90? 1: hot4(x))
hot4(x)=(x<=90 & x > 90? 1: hot5(x))
hot5(x)=(x>90? 0:0)
set yrange[-0.1:1.1]
set xtics 0, 15
set grid
set samples 1001
bind Close "exit gnuplot"
plot [40:90] cold(x) ,cool(x) ,justright(x) ,warm(x) ,hot(x) 

Notice that we use the function bind Close "exit gnuplot" to bind the exit of the application once the user has closed the plotted graph. (And I think this function is available since version 4.4).
Latex Script example:
cold(x)=\begin{Bmatrix}{0}&\mbox{if}& x\leq40\\{1}&\mbox{if}& 40< x \leq40\\{-0.1*x + 5}&\mbox{if}& 40< x \leq50\\{1}&\mbox{if}& 50< x \leq50\\{0}&\mbox{if}& x > 50\end{matrix}\\
cool(x)=\begin{Bmatrix}{0}&\mbox{if}& x\leq40\\{0.066667*x  -2.666667}&\mbox{if}& 40< x \leq55\\{1}&\mbox{if}& 55< x \leq55\\{-0.1*x + 6.5}&\mbox{if}& 55< x \leq65\\{0}&\mbox{if}& x > 65\end{matrix}\\
justright(x)=\begin{Bmatrix}{0}&\mbox{if}& x\leq60\\{0.2*x  -12}&\mbox{if}& 60< x \leq65\\{1}&\mbox{if}& 65< x \leq65\\{-0.2*x + 14}&\mbox{if}& 65< x \leq70\\{0}&\mbox{if}& x > 70\end{matrix}\\
warm(x)=\begin{Bmatrix}{0}&\mbox{if}& x\leq65\\{0.1*x  -6.5}&\mbox{if}& 65< x \leq75\\{1}&\mbox{if}& 75< x \leq75\\{-0.1*x + 8.5}&\mbox{if}& 75< x \leq85\\{0}&\mbox{if}& x > 85\end{matrix}\\
hot(x)=\begin{Bmatrix}{0}&\mbox{if}& x\leq80\\{0.1*x  -8}&\mbox{if}& 80< x \leq90\\{1}&\mbox{if}& 90< x \leq90\\{1}&\mbox{if}& 90< x \leq90\\{0}&\mbox{if}& x > 90\end{matrix}\\

I'm still working on this project and for the next milestone I'll try to add the Weighted average method to calc the area of the graph and the ability to save the data of the project.

Related links:

Friday, 10 December 2010

Building my own Delphi Physics Engine part II

Going on with my DPE (Delphi Physics Engine) I've improved my old version (Building my own Delphi Physics Engine Part I) of the Jansen Mechanism by creating the rest of the legs displaced 120º each one. I've been fixing the damping level of the framework just to be sure that the movements are as realistic as possible. In this version, the movement is quite realistic and we can trace the movement of the leg by plotting the kinetic analysis:

A physics engine is computer software that provides an approximate simulation of certain simple physical systems, such as rigid body dynamics (including collision detection), soft body dynamics, and fluid dynamics, of use in the domains of computer graphics, video games and film. Their main uses are in video games (typically as middleware), in which case the simulations are in real-time. The term is sometimes used more generally to describe any software system for simulating physical phenomena, such as high-performance scientific simulation. Wikipedia.

Here you can see the CGI result with the hanging version of the Jansen mechanism with one leg and with three legs:

And the final version with the development of the Jansen machine. In this version (Thundax Test Forces v2.exe) if you press 'p' the machine will start walking and if you want to change direction, you only need to press the 'z'.

What's next?. Now I'll try to reproduce different physics systems and show how it goes. The Easy Java Simulations tool, offers a wide range of examples that I would like to try.
Enjoy the learning!.

Related Links:

Friday, 3 December 2010

Building my own Delphi Physics Engine part I

 These days I've been working on my own Delphi Physics Engine based on the very well known APE (ActionScript Physics Engine) with some improvements that will help developers to build models very fast. In this beta version I've done the following improvements:
  • Enhance user performance.
  • Drastic reduction of Memory leaks.
  • Improve the interoperability between objects.
  • Improve maths algorithms to collision detection.
  • Use the VLO GDI Render to perform the drawing of the shapes.
In this first insight into the Engine, I'm going to show you a model of the Jansen mechanism, a kinetic sculpture that can move with the help of several pairs of legs.


I've built my own model taking advantage of the physic engine and imagination!.
Here you can see my own model:
The movement is still not very well performed, but it's due to the measures of the different parts of the sculpture. As for the calculation points, I've used the next template:
You can download the demo project from here (Thundax Test Forces). To play with the application, you only need to press 'z' to start the kinetic sculpture, and as for the objects below the sculpture, press 'd' and you'll force a collision between two objects.

The next days I'll be improving the model (you can see the kinetic analysis that is plotted below the sculpture) and adding the extra foot to perform a fully movement.

Enjoy the learning!.

Related links:

Tuesday, 30 November 2010

DelphiDoom for Delphi fans

I've recently found Delphi Doom, an adaptation from the original UNIX Doom C source code to Delphi. The project was finished in 2005 but the latest deploy was released on 3 March 2008 (Version: 1.0.2 build 383). I've been tinkering with it and it's been great!. It cast me back when I was young, trying to pass all the levels by killing some hideous and very nasty monsters. This Application is a WIN32 port of the famous Doom game created by ID Software. The main difference of DelphiDoom is that is written in the Pascal programming language. The source code has been translated from C to Pascal. In addition many new features have been added to to expand the old engine features and take advantage of capabilities of modern computers. Remember that you need the IWAD file just for being able to pay. The IWAD file is the file which contains all of the game data for a complete game.

Enjoy the game!.

Thursday, 18 November 2010

2d Physics with Delphi

I'm modelling a series of objects with some physics and mathematics and I found interesting to talk about the library I am using: Delphi APE. This fantastic library available for Delphi  (Windows) and Lazarus (Linux) allows very simple task as powerful as gravity, collision processes, grouping behaviour and general process. Great the job done by Alex cove and others like Vincent and Jeremy who helped him to make the conversion to Delphi.
This great library which I'm testing with Delphi 2010 is very easy to use and it shows a very interesting example combining different elements and letting them play. You can download the library from here, and test the different modelled items. The results are very well done and with simple steps we can achieve things like this:

Another interesting library is the one done by Algoryx called Phun.:


Related articles:

Wednesday, 17 November 2010

Alpha-beta pruning algorithm with Delphi

I'm trying to get round to writing more often and to do my own research with some interesting and complicated algorithms. Given to my great passion for different types of algorithms, in AI , I have found one very interesting and here you can get it build with Delphi 2010. With this solution, you'll be able to add values to the leaves and run the algorithm to find the nodes that will be evaluated and others that will be pruned. I've used my little framework to build the structure (using a GDI render) and then only focus on the algorithm that was the important part. Alpha-beta pruning is a search algorithm which seeks to reduce the number of nodes that are evaluated in the search tree by the minimax algorithm. It is a search with adversary algorithm used commonly for machine playing of two-player games (Tic-tac-toe, Chess, Go, etc.). It stops completely evaluating a move when at least one possibility has been found that proves the move to be worse than a previously examined move. Such moves need not be evaluated further. Alpha-beta pruning is a sound optimization in that it does not change the result of the algorithm it optimizes (Algorithmist.com). 

The pseudo-code is quite simple, and it looks like this:
The structure of the application is very simple and the most difficult part is the simulation process where you need to draw every step of the algorithm.
You can download the application from here (Thundax Alpha-beta pruning) and play with it to understand how the algorithm works.
This video shows the execution of the program:
The code of the algorithm is explained as follows:

Alpha-beta algorithm:
function TViewMinimax.alphabeta(Node: TNode; alpha: integer; beta: integer): integer;
var
    i: integer;
    ret: integer;
begin
    if Node.isLeaf then
        ret := Node.Value
    else
    begin
        for i := 0 to Node.children.Count - 1 do
        begin
            alpha := max(alpha, -alphabeta(Node.children.Items[i], -beta, -alpha));
            case Node.player of
                tMAX:
                    begin
                        Node.Value := alpha;
                        SetAlpha(Node, alpha);
                        Node.visited := true;
                    end;
                tMIN:
                    begin
                        Node.Value := -alpha;
                        SetBeta(Node, alpha);
                        Node.visited := true;
                    end;
            end;
            if beta <= alpha then
                Break;
        end;
        ret := alpha;
    end;
    result := ret;
end;

Drawing the nodes by using a pre-order method for iterating the binary tree:
procedure TViewMinimax.Draw;
begin
    preorder(Self.FMinimax.root);
end;

procedure TViewMinimax.preorder(root: TNode);
begin
    if Assigned(root) then
    begin
        if root.children.Count > 0 then
        begin
            DrawLine(root, root.children.Items[0]);
            DrawLine(root, root.children.Items[1]);
            preorder(root.children.Items[0]);
            preorder(root.children.Items[1]);
        end;
        DrawRectangle(root);
    end;
end;

procedure TViewMinimax.DrawRectangle(Node: TNode);
begin
    Fcanvas.Font.Name := 'Arial';
    Fcanvas.Brush.Style := bsSolid;
    if Node.visited then
        Fcanvas.Brush.Color := clRed
    else
        Fcanvas.Brush.Color := clWhite;
    if Node.selected then
        Fcanvas.Brush.Color := clGreen;
    Fcanvas.Pen.Width := 2;
    Fcanvas.Pen.Color := clBlack;
    Fcanvas.Rectangle(Node.position.x - gap, Node.position.y - gap, Node.position.x + gap, Node.position.y + gap);
    Fcanvas.TextOut(Node.position.x - 5, Node.position.y - 5, Inttostr(Node.Value));
    Fcanvas.Brush.Color := clWhite;
    if (Node.isLeaf) and (Node.Order <> 0) then
        Fcanvas.TextOut(Node.position.x - 5, Node.position.y + 15, Inttostr(Node.Order));
    if not Node.isLeaf then
    begin
        case Node.player of
            tMAX:
                begin
                    if Node.alpha <> 0 then
                        Fcanvas.TextOut(Node.position.x - 65, Node.position.y - 10, Inttostr(Node.Order) + ': a=' + Inttostr(Node.alpha));
                    if Node.newAlpha <> 0 then
                        Fcanvas.TextOut(Node.position.x - 65, Node.position.y + 5, Inttostr(Node.NewOrder) + ': a=' + Inttostr(Node.newAlpha));
                end;
            tMIN:
                begin
                    if Node.beta <> 0 then
                        Fcanvas.TextOut(Node.position.x - 65, Node.position.y - 10, Inttostr(Node.Order) + ': ß=' + Inttostr(Node.beta));
                    if Node.Newbeta <> 0 then
                        Fcanvas.TextOut(Node.position.x - 65, Node.position.y + 5, Inttostr(Node.NewOrder) + ': ß=' + Inttostr(Node.Newbeta));
                end;
        end;
        if Node.text <> '' then
        begin
            Fcanvas.Brush.Color := clyellow;
            if (Node.newAlpha = 0) and (Node.Newbeta = 0) then
                Fcanvas.TextOut(Node.position.x - 53, Node.position.y + 5, Node.text)
            else
                Fcanvas.TextOut(Node.position.x - 53, Node.position.y + 20, Node.text)
        end;
    end;
end;

Setting up the Minimax Algorithm:
procedure TForm1.Start1Click(Sender: TObject);
var
    vminimax: TViewMinimax;
    minimax: TMinimax;
    words: TStringList;
    alpha, beta: integer;
begin
    minimax := TMinimax.Create;
    if Edit1.Text <> '' then
    begin
        words := TStringList.Create;
        SplitTextIntoWords(Edit1.Text, words);
        minimax.AddNumbers(words);
    end;
    minimax.CreateTree;
    Memo1.Lines.Clear;

    Image1.Canvas.Brush.color := clwhite;
    Image1.Canvas.Rectangle(0, 0, Image1.Width, Image1.Height);

    vminimax := TViewMinimax.Create(Self.Image1.Canvas, minimax, Memo1);
    if CheckBox1.Checked then
        vminimax.time := 1000
    else
        vminimax.time := 0;
    alpha := alphavalue;
    beta := betavalue;

    vminimax.Draw;
    Self.Image1.Canvas.TextOut(951, 25 - 5, 'MAX');
    Self.Image1.Canvas.TextOut(951, 127 - 5, 'MIN');
    Self.Image1.Canvas.TextOut(951, 228 - 5, 'MAX');
    Self.Image1.Canvas.TextOut(951, 328 - 5, 'MIN');

    Start1.Enabled := false;
    CheckBox1.Enabled := false;
    vminimax.alphabeta(minimax.root, alpha, beta);
    vminimax.Draw;
    Start1.Enabled := true;
    CheckBox1.Enabled := true;

    FreeAndNil(words);
    FreeAndNil(minimax);
    FreeAndNil(vminimax);
end;

Splitting the text into numbers (comma separated values):
procedure SplitTextIntoWords(const S: string; words: TstringList);
var
    startpos, endpos: Integer;
begin
    Assert(Assigned(words));
    words.Clear;
    startpos := 1;
    while startpos <= Length(S) do
    begin
        while (startpos <= Length(S)) and (S[startpos] = ',') do
            Inc(startpos);
        if startpos <= Length(S) then
        begin
            endpos := startpos + 1;
            while (endpos <= Length(S)) and not (S[endpos] = ',') do
                Inc(endpos);
            words.Add(Copy(S, startpos, endpos - startpos));
            startpos := endpos + 1;
        end;
    end;
end;

Related links:

Friday, 12 November 2010

Wednesday, 10 November 2010

Genetic Algorithms (GA)

This semester I am improving knowledge in terms of Artificial Intelligence and one of the concepts that most captivated me was the resolution of problems using genetic algorithms. These are based on coding the problem in chromosomes and genes into packages. After applying a series of functions, we need to mutate the population to reach our goal. and find the best solution. The definition from wikipedia is: "The genetic algorithm (GA) is a search heuristic that mimics the process of natural evolution. This heuristic is routinely used to generate useful solutions to optimization and search problems. Genetic algorithms belong to the larger class of evolutionary algorithms (EA), which generate solutions to optimization problems using techniques inspired by natural evolution, such as inheritance, mutation, selection, and crossover".
Basically the algorithm works like this:


There are several examples on the net which uses GA to solve common problems such as these:
One of the examples that best shows the use of GA is the solution from Roger Alsing where the algorithm is trying to copy an image generating polygons. These polygons are created in a population of chromosomes and they try to evolve to fit the source image. I've been playing with it and it's great!. You can download the source code and the binaries from here.


Here you can see the results of playing with the application:

Genetic Vectorizer Example by Roger Alsing:

Using my image (40h of running time):

using Einstein image (20h of running time):
Video showing the start of the algorithm:


In the video you can see the different steps the algorithm is doing by creating a population of chromosomes as polygons and trying to fit them by shape and by colour from the source image. The result of the application is the image shown  above.


Sodorace game:
Sodarace is the on-line Olympics pitting human creativity against machine learning in a competition to design robots that race over 2D terrains using the Sodaconstructor virtual construction kit.

Enjoy the learning!.

Related articles:

Outstanding videos of robots

Due to the recent contributions of the scientific community about robots, here are a collection of the best videos I found on the Web. It's amazing how technology improves and the number of mysteries that lie ahead. In the following videos we can see the different robots built by Boston Dynamics (for me the most outstanding are the Big Dog and Little Dog). And we can also find the new Actroid-F presented recently in the AIST Lab Fair and other different examples of robots.




Boston Dynamics: Big Dog:

Boston Dynamics: Little Dog:

Actroid-F in AIST Open Lab:
 

Transformer Robot:

I hope you enjoy the astonishing videos!

Wednesday, 3 November 2010

David McCandless: The beauty of data visualization

This is an interesting video from TED talking about the beauty of data visualization. David McCandless turns complex data sets (like worldwide military spending, media buzz, Facebook status updates) into beautiful, simple diagrams that tease out unseen patterns and connections. Good design, he suggests, is the best way to navigate information glut -- and it may just change the way we see the world.

Presentation of the new Rad Studio XE and the new Visual Studio 2010 in Barcelona

On November 24 will be held this seminar in Barcelona, which conveniently will show us the new features of the new RAD Studio XE, Delphi XE, C++ Builder XE, Delphi Prism XE and RadPHP XE. I'll take this opportunity to learn in a practical way the latest additions, see examples of operation, contact other users, chat with the team and meet interesting Danysoft promotions. I'm also attending the Visual Studio 2010 presentation which will show us practical themes that are awakening the community of developers. The new ASP.NET , the MVC Framework and the new features included in the WCF (Windows Communication Foundation) will be the discussed topics.

I'll see you there!.

Related topics:

Thursday, 21 October 2010

Delphi Unicode Migration

One of my colleagues found this interesting document about migrating Delphi versions. I'm sure is very useful and this will help us to release a stable version before we move on to Delphi XE.

Check out this SlideShare Presentation:
Other interesting document: Reasons to migrate from Delphi 7 to Delphi 2009:

Wednesday, 20 October 2010

Tuesday, 19 October 2010

Clean Code: A Handbook of Agile Software Craftsmanship

It recently arrived at my hands the book from Robert C. Martin: Clean Code. Martin presents a revolutionary paradigm in his book: A Handbook of Agile Software Craftsmanship. Martin has teamed up with his colleagues from Object Mentor to distil their best agile practice of cleaning code “on the fly” into a book that will instil within you the values of a software craftsman and make you a better programmer-but only if you work at it.
Clean Code is divided into three parts. The first describes the principles, patterns, and practices of writing clean code. The second part consists of several case studies of increasing complexity. Each case study is an exercise in cleaning up code-of transforming a code base that has some problems into one that is sound and efficient. The third part is the pay-off: a single chapter containing a list of heuristics and “smells” gathered while creating the case studies. The result is a knowledge base that describes the way we think when we write, read, and clean code. Source: Clean Code Handbook

Monday, 18 October 2010

Keeping track of a list by comparing it.

Due to my last application developed, I had to compare a list by scanning it and then present the results by including if any item was added or removed. For accomplish this task I've developed a little unit that is able to compare the list and show the results in a TMemo.

//@Author Jordi Coll
//@2010

unit uListCompare;

interface

uses
    Classes, SysUtils;

type
    TListCompare = class(TObject)
        private
            FList2: TStringList;
            FList1: TStringList;
            procedure SetList1(const Value: TStringList);
            procedure SetList2(const Value: TStringList);
        public
            property List1: TStringList read FList1 write SetList1;
            property List2: TStringList read FList2 write SetList2;
            constructor Create();
            destructor Destroy(); override;
            procedure DumpList();
            function ExistInList1(s: string): boolean;
            function ExistInList2(s: string): boolean;
    end;

implementation

{ TListCompare }

constructor TListCompare.Create;
begin
    FList1 := TStringList.Create;
    FList2 := TStringList.Create;
end;

destructor TListCompare.Destroy;
begin
    FreeAndNil(FList1);
    FreeAndNil(FList2);
    inherited;
end;

procedure TListCompare.DumpList;
var
    i: Integer;
begin
    if List2.Count = 0 then
    begin
        for i := 0 to List1.Count - 1 do
        begin
            List2.Add(List1[i]);
           log('New Item ->' + List1[i]);
        end;
    end
    else
    begin
        for i := 0 to List1.Count - 1 do
        begin
            if not ExistInList2(List1[i]) then
                log('New Item ->' + List1[i]);
        end;
        for i := 0 to List2.Count - 1 do
        begin
            if not ExistInList1(List2[i]) then
                log('Item doesn''t exist ->' + List2[i]);
        end;
        List2.Clear;
        for i := 0 to List1.Count - 1 do
            List2.Add(List1[i]);
    end;
end;

function TListCompare.ExistInList1(s: string): boolean;
var
    found: boolean;
    i: Integer;
begin
    i := 0;
    found := false;
    while (i < FList1.Count) and (not found) do
    begin
        found := FList1[i] = s;
        inc(i);
    end;
    result := found;
end;

function TListCompare.ExistInList2(s: string): boolean;
var
    found: boolean;
    i: Integer;
begin
    i := 0;
    foundt := false;
    while (i < FList2.Count) and (not found) do
    begin
        foundt := FList2[i] = s;
        inc(i);
    end;
    result := found;
end;

procedure TListCompare.SetList1(const Value: TStringList);
begin
    FList1 := Value;
end;

procedure TListCompare.SetList2(const Value: TStringList);
begin
    FList2 := Value;
end;

end.

The only thing you have to do is fill the List1 with your items and then execute the procedure DumpList that will dump the information from List1 to List2 and will compare it to show the differences. This object can be called in a thread or a controlled loop.

Killing suspicious processes

As a result of an experiment, we found out that one process was being run in my local machine by an unknown user and this trigger my curiosity to know more about this and which actions I could do to fix it. Firstly, I decided to monitor the process and gather data from it by using some Delphi API libraries and secondly, build a little application to kill the process and keep a little log just in case. The application is called Thundax Suspicious process watcher v1.1 and it's able to filter processes by unknown/known users and apply actions to them.
Once the application is found (by the process to inspect text box) the utility kills the process and shows the resulted information. We can also force the killing system to the known processes and use it to force the end of and application by filtering it by name and user name.
In the next picture you can notice that I've terminated the execution of the notepad.exe by simply adding it name and process user name (me).
The application core is based on two parts, the first one that is able to search for the applications that are being run in your machine and the second one that is able to kill a process by its PID. Here you can get the implemented code:

Get process list:
procedure ProcessList();
var
    hProcSnap: THandle;
    pe32: TProcessEntry32;
    Domain, User: string;
    listItem: TListItem;
begin
    hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPALL, 0);
    if hProcSnap = INVALID_HANDLE_VALUE then
        Exit;
    pe32.dwSize := Sizeof(ProcessEntry32);
    ListView1.Clear;
    listCompare.List1.Clear;
    if Process32First(hProcSnap, pe32) = True then
        while Process32Next(hProcSnap, pe32) = True do
        begin
            if GetUserAndDomainFromPID(pe32.th32ProcessID, User, Domain) then
            begin
                if RadioButton2.Checked then
                begin
                    listItem := ListView1.Items.Add;
                    listItem.Caption := pe32.szExeFile;
                    listItem.SubItems.Add(IntToStr(pe32.th32ProcessID));
                    listItem.SubItems.Add(User);
                    listItem.SubItems.Add(Domain);
                    listCompare.List1.Add(pe32.szExeFile);
                    if AnsiUpperCase(pe32.szExeFile) = AnsiUpperCase(Edit2.text) then
                    begin
                        if Edit3.text <> '' then
                        begin
                            if AnsiUpperCase(User) = AnsiUpperCase(Edit3.text) then
                            begin
                                Log('Application founded ->' + AnsiUpperCase(Edit2.text));
                                if CheckBox3.Checked then
                                begin
                                    KillProcess(pe32.th32ProcessID);
                                    Sleep(300);
                                    Log('Application killed ->' + AnsiUpperCase(Edit2.text));
                                end
                            end;
                        end
                        else
                        begin
                            Log('Application founded ->' + AnsiUpperCase(Edit2.text));
                            if CheckBox3.Checked then
                            begin
                                KillProcess(pe32.th32ProcessID);
                                Sleep(300);
                                Log('Application killed ->' + AnsiUpperCase(Edit2.text));
                            end
                        end;

                    end;
                end
            end
            else
            begin
                if RadioButton1.Checked then
                begin
                    // Suspicious Items
                    listItem := ListView1.Items.Add;
                    listItem.Caption := pe32.szExeFile;
                    listItem.SubItems.Add(IntToStr(pe32.th32ProcessID));
                    listItem.SubItems.Add('UNKNOW');
                    listItem.SubItems.Add('UNKNOW');
                    listCompare.List1.Add(pe32.szExeFile);
                    if AnsiUpperCase(pe32.szExeFile) = AnsiUpperCase(Edit1.text) then
                    begin
                        Log('Application founded ->' + AnsiUpperCase(Edit1.text));
                        if CheckBox2.Checked then
                        begin
                            KillProcess(pe32.th32ProcessID);
                            Sleep(300);
                            Log('Application killed ->' + AnsiUpperCase(Edit1.text));
                        end
                    end;
                end
            end;
            Application.ProcessMessages;
        end;
    CloseHandle(hProcSnap);
end;

function GetUserAndDomainFromPID(ProcessId: DWORD; var User, Domain: string): Boolean;
var
    hToken: THandle;
    cbBuf: Cardinal;
    ptiUser: PTOKEN_USER;
    snu: SID_NAME_USE;
    ProcessHandle: THandle;
    UserSize, DomainSize: DWORD;
    bSuccess: Boolean;
begin
    Result := false;
    ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, false, ProcessId);
    if ProcessHandle <> 0 then
    begin
        if OpenProcessToken(ProcessHandle, TOKEN_QUERY, hToken) then
        begin
            bSuccess := GetTokenInformation(hToken, TokenUser, nil, 0, cbBuf);
            ptiUser := nil;
            while (not bSuccess) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) do
            begin
                ReallocMem(ptiUser, cbBuf);
                bSuccess := GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf, cbBuf);
            end;
            CloseHandle(hToken);

            if not bSuccess then
            begin
                Exit;
            end;

            UserSize := 0;
            DomainSize := 0;
            LookupAccountSid(nil, ptiUser.User.Sid, nil, UserSize, nil, DomainSize, snu);
            if (UserSize <> 0) and (DomainSize <> 0) then
            begin
                SetLength(User, UserSize);
                SetLength(Domain, DomainSize);
                if LookupAccountSid(nil, ptiUser.User.Sid, PChar(User), UserSize, PChar(Domain), DomainSize, snu) then
                begin
                    Result := True;
                    User := StrPas(PChar(User));
                    Domain := StrPas(PChar(Domain));
                end;
            end;

            if bSuccess then
            begin
                FreeMem(ptiUser);
            end;
        end;
        CloseHandle(ProcessHandle);
    end;
end;

Kill process by PID:
procedure KillProcess(pid: integer);
var
    h: THandle;
begin
    try
        h := OpenProcess(PROCESS_TERMINATE, false, pid);
        try
            if h <> 0 then
                TerminateProcess(h, 0);
        finally
            CloseHandle(h);
        end;
    except
        ShowMessage('Error');
    end;
end;

Let me know if you have any doubt about the program or any improvement!.

Related links:

Friday, 1 October 2010

Working with Microsoft Excel (.xlsx) files in Delphi 2010

Due to the improvement of the new format of Microsoft office 2007 files (.docx, .xlsx based on xml) the way we use to access this documents has changed. Instead of using OLE we can use the power of Delphi and the type library Borland (TLB Files).
In this article we'll talk about how to create the TLB files and the code we need to access the .Excel (.xlsx file) of the example I've created.
First of all, we need to import the components via -> Component -> Import a Type Library. Once we are there, we need to select the "Microsoft Excel 12.0 Object Library" and go on with the import. Mark the "Generate component wrappers" check-box and finally add the component to the working unit. This will generate the Excel_TLB.pas.
Once we have integrated this file into our project, we need to go on with importing the second component: Component -> Import a Type Library and then install the "Microsoft Office 12.0 Object Library". This will generate the Office_TLB.pas (this unit is necessary because it's used by Excel_TLB.pas).

1 - Knowing the number and name of the sheets of the Workbook.
The following code will open a excel file and will load all the sheets into a combo box. Even though it represents a small portion of code, the library is quite complicated to use.

procedure TForm1.LoadCombo();
var
    XLSXReader: Excel_TLB.TExcelApplication;
    newWorkbook: Excel_TLB._Workbook;
    objXLS: Excel_TLB.TExcelWorkbook;
    objSheet: Excel_TLB.TExcelWorksheet;
    i: Integer;
begin
    newWorkbook := XLSXReader.Workbooks.Add('C:\book1.xlsx', GetUserDefaultLCID);
    objXLS := Excel_TLB.TExcelWorkbook.Create(nil);
    objXLS.ConnectTo(newWorkbook);
    objSheet := Excel_TLB.TExcelWorksheet.Create(nil);
    for i := 1 to objXLS.Worksheets.count do
    begin
        objSheet.ConnectTo(objXLS.Worksheets[i] as _Worksheet);
        ComboBox1.Items.Add(objSheet.Name);
    end;
    newWorkbook.Close(false, EmptyParam, EmptyParam, GetUserDefaultLCID);
    FreeAndNil(objXLS);
    FreeAndNil(objSheet);
end;

2 - Accessing to Excel fields.
The following example will get the objSheet and will get all the data from the sheet and will dump into a dataset to display then the result into a grid.
procedure TForm1.Open(Sender: TObject);
var
    XLSXReader: Excel_TLB.TExcelApplication;
    newWorkbook: Excel_TLB._Workbook;
    objXLS: Excel_TLB.TExcelWorkbook;
    objSheet: Excel_TLB.TExcelWorksheet;
    objWrapper: TExcelWrapper;
begin
    newWorkbook := XLSXReader.Workbooks.Add('C:\book1.xlsx', GetUserDefaultLCID);
    objXLS := Excel_TLB.TExcelWorkbook.Create(nil);
    objXLS.ConnectTo(newWorkbook);
    objSheet := Excel_TLB.TExcelWorksheet.Create(nil);
    objSheet.ConnectTo(objXLS.Worksheets['sheet1'] as _Worksheet);
    objWrapper := TExcelWrapper.Create(objSheet);
    if cdsExcel.Active then
        cdsExcel.Close;
    objWrapper.FillDataSet(cdsExcel);
    cdsExcel.Open;
    cdsExcel.First;
    newWorkbook.Close(false, EmptyParam, EmptyParam, GetUserDefaultLCID);
end;

Then the code for getting the data from the sheet:

procedure TExcelWrapper.FillDataSet(var cdsExcel: TClientDataSet);
var
    count: Integer;
    i: Integer;
    bFinished, correct: boolean;
    Value: String;
begin
    if Assigned(FSheet) then
    begin
        try
            cdsExcel.DisableControls;
            count := 0;
            i := 2;
            LastModule := '';
            bFinished := false;
            while not bFinished do
            begin
                Value := FSheet.Cells.Item[i, 1];
                if Value = '' then
                    count := count + 1
                else
                begin
                    count := 0;
                    cdsExcel.Append;
                    cdsExcel.FieldByName('Column1').AsString := FSheet.Cells.Item[i, 1];
                    cdsExcel.FieldByName('Column2').AsString := FSheet.Cells.Item[i, 2];
                    cdsExcel.FieldByName('Column3').AsString := FSheet.Cells.Item[i, 3];
                end;
                if count > 2 then
                    bFinished := true;
                i := i + 1;
            end;
            cdsExcel.Post;
        finally
            cdsExcel.EnableControls;
        end;
    end;
end;

3 - Things to take into account.
You need to remember that the library creates an instance of Excel application, and you must close all the opened connections using the Close procedure.

newWorkbook.Close(false, EmptyParam, EmptyParam, GetUserDefaultLCID); 
 

Thursday, 30 September 2010

Reflexion time - Adaptation is the Key

First of all, I would like to thank all the positive comments I've received for my Blog. I'm truly happy because they inspire me to keep publishing interesting topics related with Delphi, Technology and Science. I can see that the page is widely visited throughout the world and the rate of daily visitors is quite good, but the users don't leave any feedback and sometimes this is a little disappointing. Anyway, I'll keep writing and doing my own research in order to improve myself and sharing my knowledge to the world.
Now I'm immersed on a reflexivity's period, thinking about job opportunities, new projects and new interesting articles to publish. This month I've been working on new interesting projects, migrating versions from Delphi 2007 to Delphi 2010, doing a big rewrite of code due to its internal changes with Indy10 and other new features like generics and working with parameters (I'm eager to test the new Delphi XE, but as soon as I finish the other projects). I've been as well working on a new system to improve the usability of working with Microsoft Office 2007 files such as Excel files (.xlsx) and Word files (.docx),  and some other projects as a photographer doing a catalogue for a company!. As you can see this month has been pretty hectic and I never stop running. I have other projects in mind that I need to put into gear, but I need some time to meditate about them, but I'll keep you posted!.
I've been providing services as a technological consultant to some companies in order to improve their IT departments in a wide range of aspects like: security, collaborative work and documentation. And all these experiences have been very rewarded to put into practise all the things learned during the last three years.
With all of this, I just want to motivate you, and remember to do what you love to achieve all what you want. I've been following this simple rule and everything is working fine. I can't complain of anything!.

Here you can see a very interesting video showing the power of adaptation:


Don't hesitate to comment in the blog and feel free to contact me through the web.
If you have time, you can take a look at my portfolio and check out my passion for photography!.

Thursday, 16 September 2010

LeanKit Kanban

This week I've been working with the LeanKit Kanban, a very interesting approach for using Kanban boards in Agile development. All of you know about my interests with the Agile approach, and I think that this interesting and free (limited) tool will help you to keep track of your daily work.

Here you can see a mock up of my kanban board:


In the Jesse Liberty blog, you can find a very interesting description of the Kanban tool:

What Kanban Does For You

What is not obvious in looking at the board is how quickly it reveals bottlenecks, where I’m wasting time, and how to be as effective as possible.  The fact that it is all very visual, that you are moving these cards around and can see at a glance all the relevant information, makes it very easy to see what is stuck, and what is moving nicely.

LeanKit Kanban has a number of features that I don’t personally use, but would have killed for in previous projects, such as advanced analytics that include diagrams for Cycle time, cumulative flow, process efficiency, work distribution and more.  The analytics allow a team to answer such critical questions  as “what is holding the project back?” and ”when will this item be ready?” with high confidence.

I do use the notification capabilities, which turns what is usually a “polling” exercise in frustration into an “interrupt-driven” management approach; much better.

The bottom line, for me, though, is that each “card” carries its entire history, its description, its priority, its due date and everything else I need to know about a sub-feature.  That is very clean and it fits well with the way I work.
Jesse Liberty.