"A human being should be able to change a diaper, plan an invasion, butcher a hog, conn a ship, design a building, write a sonnet, balance accounts, build a wall, set a bone, comfort the dying, take orders, give orders, cooperate, act alone, solve equations, analyze a new problem, pitch manure, program a computer, cook a tasty meal, fight efficiently, die gallantly. Specialization is for insects." (Robert A. Heinlein)

Wednesday, 24 December 2008

Merry Christmas

No code, no screenshots this time ... simply the warmest MERRY CHRISTMAS to everybody who happens to read my blog. 
(Update 31/12)
And happy new year too!

Thursday, 18 December 2008

Merry (fractal) Christmas

This is my first Christmas as a blogger and, an old coder like me couldn't help not to post some Christmas related piece of code. I spent some of my spare time, mainly while travelling by train, writing a small java program to draw a fractal tree and I finally tuned it to produce something resembling a Christmas tree.
The algorithm used is fairly simple:  just draw a branch (a segment) and then attach some others branches to it calling recursively the same branch method. Recursive calls are stopped when branch length falls below a giver value. to make the final result a little more realistic a little randomness is added and branch color is decided on the basis of branch length.
The result is far from being satisfying (and lightyears far from artistic results as in here) but I don't think I'll get something better before Christmas.
  
Here is the code of the tree drawing class while the user interface was generated by the Netbeans plugin with only minimal manual coding needed.
package ph.mm.demo.fractals;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Random;

/**
 *
 @author user
 */
public class TreePainter {

    Graphics2D graphics = null;
    private double scale = 0.42;
    private double scale2 = 0.49;
    private double angle =115;
    private double minLength = 3;
    private double rangle = 0;
    private double split = 0.6;
    private double noise = 0.05;
    private long seed = 3214;
    private Random rnd=null;
    private double x0=200;
    private double y0=350;
    private double x1=200;
    private double y1=200;
    float colScale = 0;
            
        
    public TreePainter(Graphics g) {
        graphics = (Graphics2D)g;
        graphics.setBackground(Color.BLACK);
        graphics.clearRect(00500500);
        rangle=Math.toRadians(angle);
        rnd = new Random(seed);
        colScale = (float)(1/(y0-y1));
    }
   
    public void paint(){
        Line2D l = new Line2D.Double(x0, y0, x1, y1);
        branch(l);
    }
    
    public void branch(Line2D l){
        Rectangle2D r = l.getBounds2D();
        double size = Math.sqrt(r.getWidth()*r.getWidth() + r.getHeight()*r.getHeight());
        graphics.setColor(getCol(size));
        graphics.draw(l);
        
        if(size>minLength){
            double cAngle=0;
            cAngle = Math.acos((l.getX2()-l.getX1())/size);
            System.out.println(size+ ", " + Math.toDegrees(cAngle));
            if(l.getY1()>l.getY2()) cAngle=-cAngle;
            
            Point2D pSplit = new Point2D.Double(l.getX1() (l.getX2()-l.getX1())*split,
                                                l.getY1() (l.getY2()-l.getY1())*split);
            Point2D pEnd1 =  new Point2D.Double(l.getX2() + size*scale*getNoise()*Math.cos(cAngle)
                                                l.getY2() + size*scale*getNoise()*Math.sin(cAngle));
            Point2D pEnd2 =  new Point2D.Double(l.getX2() + size*scale*getNoise()* Math.cos(cAngle*getNoise()+rangle)
                                                l.getY2() + size*scale*getNoise()*Math.sin(cAngle*getNoise()+rangle));
            Point2D pEnd3 =  new Point2D.Double(l.getX2() + size*scale*getNoise()* Math.cos(cAngle*getNoise()-rangle)
                                                l.getY2() + size*scale*getNoise()*Math.sin(cAngle*getNoise()-rangle));
            Point2D pEnd4 =  new Point2D.Double(pSplit.getX() + size*scale2*getNoise()* Math.cos(cAngle*getNoise()+rangle)
                                                pSplit.getY() + size*scale2*getNoise()*Math.sin(cAngle*getNoise()+rangle));
            Point2D pEnd5 =  new Point2D.Double(pSplit.getX() + size*scale2*getNoise()* Math.cos(cAngle*getNoise()-rangle)
                                                pSplit.getY() + size*scale2*getNoise()*Math.sin(cAngle*getNoise()-rangle));
            branch(new Line2D.Double(l.getP2(), pEnd1));
            branch(new Line2D.Double(l.getP2(), pEnd2));
            branch(new Line2D.Double(l.getP2(), pEnd3));
            branch(new Line2D.Double(pSplit, pEnd4));
            branch(new Line2D.Double(pSplit, pEnd5));
        }
        
    }
    
    private double getNoise(){
        return (rnd.nextDouble()-0.5)*2*noise+1;
    }
    
    private Color getCol(double size){
        if(size<minLength)
            return new Color(0.05F0.5F0.2F);
        else if(size<minLength*2)
            return new Color(0.05F,0.4F0.1F);
        else if(size<minLength*10)
            return new Color(0.05F,0.3F0.3F);
        else
            return new Color(0.3F,0.3F0.1F);
    }
            
}

Tuesday, 25 November 2008

New toy: Ubiquity

There are so many toys in the 'net and so little time to play with!  I first read about this tool from here almost a month ago.
Ubiquity is a Firefox plugin that let you perform a great variety of operations, simply by typing a command. You can , for example, search on the most famous search engines, send a mail or translate a word.You simply have to activate it with it's hot-key (ctrl-space) and type what you need.
This alone would make of Ubiquity an handy tool, if you do not like put your hands off the keyboard to search what you need in menus and bookmarks using the mouse,  what makes of Ubiquity a really enjoyable toy is how easily you can write your own commands.
Just type "command-editor" to get a simple but effective web based editor where you can write your Ubiquity commands with Javascript. No compiling or deploy is needed you can run your command in Ubiquity as soon as you have written it.
Here is my own ubiquity command to reverse a stringselected or passed as parameter. It's only a step beyond a 'hello world' program but it shows quite well how Ubiquity works.
    /* This is a template command */     
CmdUtils.CreateCommand({               
      name: 
"reverse",           
      icon: 
"http://example.com/example.png",       
      homepage: 
"http://example.com/",       author: name: "MM", email: "MM@mm.com"},       license: "LGPL",
      description: "reverse example",
      help: "just reverse a string",
      takes: {"input": noun_arb_text},
      preview: functionpblock, input ) {
        var template = "result will be: ${result}";
        pblock.innerHTML = CmdUtils.renderTemplate(template, {"result": reverse(input)});
      },
      execute: function(input) {
        CmdUtils.setSelection("You selected: " + input.html);
      }

      function reverse(in){
         var res = "";
         for(var i=in.length;i>0;i++){
              res = res + in(i);
          }
         return res;
      }
    });
More details about programming with Ubiquity on its wiki.

Thursday, 13 November 2008

Installed CVS

I've just installed CVS on PIII 550. I don't really write so much code to need a versioning system at home, but it's still an interesting experiment and also an easy way to share sources between laptop and desktop computer. I did it mainly following instructions from this howto.
first I installed CVS and XINETD with apt-get command:
sudo apt-get install cvs
sudo apt-get install xinetd
 then I added to xinetd the cvs configuration file
vim /etc/xinetd.d/cvspserver
here is the file content
service cvspserver
{
     port = 2401     
     socket_type = stream
     protocol = tcp
     user = root
     wait = no
     type = UNLISTED
     server = /usr/bin/cvs
     server_args = -f --allow-root /var/lib/cvs pserver
     disable = no
}
after restarting xinetd:
sudo /etc/init.d/xinetd start 
I added two users to the machine (for the two computers that are going to use CVS) and added them to the src group.
(adding only CVS users would be safer but this is only a home network server so why worry about it?)
sudo adduser --no-create-home eeepc900
sudo adduser --no-create-home sempron2400 
sudo addgroup eeepc900 src
sudo addgroup sempron2400 src
and, at last, I configured Eclipse to use the CVS server

Wednesday, 5 November 2008

Generating random people with PostgreSQL

I just installed PostgreSQL on my PIII550 linux 'server' and I used the SQL example from my last post to do some test. Only the random select query and the procedure needed some little rework due to the different syntax:
Here is the random selection query
SELECT NAME, SEX,
                   CURRENT_DATE - CAST(RANDOM()*365.25*100 AS INTEGER) AS DOB,
                  (SELECT SURNAME FROM SURNAMES ORDER BY RANDOM() LIMIT 1) AS SURNAME
FROM NAMES ORDER BY RANDOM() LIMIT 1;
 Here is the procedure:
CREATE OR REPLACE FUNCTION FILL(IN NUM INT) RETURNS VARCHAR(1) AS $$
    DECLARE
          N INTEGER;
       BEGIN
              N:=NUM;
             WHILE N > 0 LOOP
                  INSERT INTO PEOPLE(NAME,SEX,DOB,SURNAME)
                  SELECT NAME, SEX,
                                     CURRENT_DATE - CAST(RANDOM()*365.25*100 AS INTEGER) AS DOB,
                                   (SELECT SURNAME FROM SURNAMES ORDER BY RANDOM() LIMIT 1) AS SURNAME
                 FROM NAMES ORDER BY RANDOM() LIMIT 1;
                N := N - 1;
       END LOOP;
       RETURN 'T';
END; $$
LANGUAGE PLPGSQL;
(Update)
Forgot to say it takes about seven seconds to insert ten thousands rows ... quite faster than MySQL.

test=# SELECT NOW();SELECT FILL(10000);SELECT NOW();
now
——————————-
2008-11-09 17:32:53.985751+01 (1 row)
fill
——
T
(1 row)
now
——————————-
2008-11-09 17:32:59.359207+01
(1 row)
test=#

Friday, 31 October 2008

Populating a table with random people


It happened I had  to  fill a table with realistic but not real people data.Here how did I managed it (ported to MySQL sintax).
First lets create a people table like this :
CREATE TABLE PEOPLE(NAME VARCHAR(20),
                                     SURNAME VARCHAR(20),
                                     SEX VARCHAR(1),
                                     DOB DATE);
Then create tables with sample names and surnames:
CREATE TABLE NAMES(NAME VARCHAR(20), SEX VARCHAR(1));
CREATE TABLE SURNAMES(SURNAME VARCHAR(20));
And fill them with some values:
INSERT INTO NAMES(NAME,SEX) VALUES('Jhon','M');
INSERT INTO NAMES(NAME,SEX) VALUES('Jack','M');
INSERT INTO NAMES(NAME,SEX) VALUES('Jeff','M');
INSERT INTO NAMES(NAME,SEX) VALUES('Judy','F');
INSERT INTO NAMES(NAME,SEX) VALUES('Jade','F');
INSERT INTO NAMES(NAME,SEX) VALUES('Jane','F');
INSERT INTO SURNAMES(SURNAME) VALUES('Red');
INSERT INTO SURNAMES(SURNAME) VALUES('White');
INSERT INTO SURNAMES(SURNAME) VALUES('Green');
Now we'll be able to get a single random person with a query like this:
SELECT NAME, SEX,
           CURDATE() - INTERVAL RAND()*365.25*100 DAY AS DOB,
                 (SELECT SURNAME FROM SURNAMES ORDER BY RAND() LIMIT 1) AS SURNAME
FROM NAMES ORDER BY RAND() LIMIT 1;
We can write a simple procedure to populate the table with the desired number of rows:
CREATE PROCEDURE FILL(IN NUM INT)
   BEGIN
       WHILE NUM > 0 DO
          INSERT INTO PEOPLE(NAME,SEX,DOB,SURNAME)
          SELECT NAME, SEX,
                            CURDATE() - INTERVAL RAND()*365.25*100 DAY AS DOB,
                         (SELECT SURNAME FROM SURNAMES ORDER BY RAND() LIMIT 1) AS SURNAME
         FROM NAMES ORDER BY RAND() LIMIT 1;
         SET NUM = NUM-1;
      END WHILE;
END;
We can call this procedure like this:
mysql> call FILL(10000);
Query OK, 1 row affected (40.73 sec)
A ten thousand people population in forty seconds (on PIII at 550Mz) is not bad.
Of course many improvements can be done like adding a random place of birth (based on a table of places) or making date of birth distribution more realistic.