Archive

Archive for the ‘Programming’ Category

The SimpleXML

March 27th, 2012 No comments

The SimpleXML extensions is intended to provide a “very simple and easily usable toolset”. This description lets you think that is simple to use but a more accurate description is that it lets you use it for for quick and simple cases. The basic example looks good:

$movies = new SimpleXMLElement($xmlstr);
 
/* For each <character> node, we echo a separate <name>. */
foreach ($movies->movie->characters->character as $character) {
   echo $character->name, ' played by ', $character->actor, PHP_EOL;
}

One little issue: $character->name is an object not a regular php string. As a result, you have to cast everywhere as if you use a static language:

if((string) $foo->bar == 'etc') {

or

str_etc((string)$xml->str);

There are also small differences on what functions are available or how they work, depending on what version of PHP you use.

In case of a slightly more complex xml (like some custom data feed) it is an usual approach to convert the xml object to nested array structure. http://php.net/manual/en/book.simplexml.php has a section of user contributed notes that is full of post regarding this action. There are two basic approaches:

$array = json_decode(json_encode($xml), TRUE);
...
// some cleanup if neeed

and some recursive parsing of the xml tree. Both methods kind of work if applied for the right problem. This shows that for the more than basic tasks SimpleXML becomes cumbersome, a nuisance to use.

The extension could be improved a bit to make it more usable but I think a lot of problems come from the nature of the XML format. Most data feed providers do not actually need or use the power/complexity of the XML format and could use a lighter more suitable format. Used data from providers that could easily use csv or json. It is easier to generate, parse, debug and use a lot less bandwidth & processing power all at the cost of sounding less “enterprise”.

Categories: Programming Tags: , ,

PHP foreach and references

September 26th, 2011 No comments

The foreach construct is an usual way to iterate over an array. Since PHP 5, you can also modify the array values using references. Here is one interesting side effect:

<?php
$a = range(1,5);
foreach($a as &$x) {
	$x++;
}
 
foreach($a as $x) {
	echo $x;
}

The output is 23455. This happens because the $x reference remains even after the foreach loop ends. The reference is destroyed if you unset $x after the loop.

This is not very well known. If you have the misfortune to maintain some scripts with a coding style involving little structure, lots of spaghetti code and nested includes than you might be very puzzled by the behavior of a regular foreach loop just because the iterating value was used previously as a reference.

Categories: Programming Tags: ,

Google AI Challenge

June 30th, 2011 No comments

Artificial inteligence(AI) is a complex branch of computer science involving a lot of research by private and academic entities. The Google AI Challenge brings bot writers around a simple and fun idea. The idea is to write a bot to play a strategy game against other bots.

In the next challenge the bots will play an Ants game where they control an ant colony fighting for resources against another colonies. The system is functional but in beta version. There is a set of APIs for most programming languages, a couple of tutorials and the source code for the system itself is available.

The University of Waterloo Computer Science Club is organizing the contest with Google as a sponsor. There are no listed prizes but for people with some spare time it will provide quite enough entertainment value. I hope to have a least a bit of spare time for this and play a bit with it.

Most information is on the forum and there is also a beta site.

Categories: Programming Tags:

Intuitive Zoom with JScrollPane

September 2nd, 2010 2 comments

The problem: Display an image inside a panel and handle different zoom levels. The best approach is to use an already made component. If a component is not available or you just have to write it using only the basic Swing components than might help you save some time.

One approach is to hold a BufferedImage and the zoom level(integer, initial 100) and draw the image with appropriate settings in a JPanel. Overwrite the paintComponent function of a JPanel. Set the size of the panel to match the size of the zoomed image. Add this panel inside a JScrollPane and you have an initial version. Enable double buffering for the resulting panel to have a smooth appearance.

I prefer this approach instead of using a zoomed copy of the image as it saves a lot of memory.

The positions on the drawing panel match the positions on the zoomed image. The coordinates in the original image are calculated using a simple formula:

int imageX = panelX * 100/zoom;

If the zoomed image is smaller than the container than the image will be in the top right corner. Most users will want it in the center of the container. The solution is to wrap the drawing panel inside a centering panel. There a couple of solutions using a custom layout manager, a combination of Box layouts, SpringLayout, etc. A simple solution is the GridBagLayout:

JPanel centeringPanel = new JPanel(new GridBagLayout());
centeringPanel.add(drawingPanel, new GridBagConstraints());

This will center the drawing panel vertically and horizontally.

When changing the zoom, change the size of the drawing panel and call invalidate() and repaint() on the scroll pane view port. Now you have zoom in and zoom out.

You will notice a small problem. The zoom is not very intuitive, it will move the image to the top left corner. A more usable panel would zoom in/out preserving the view on the same area of the image. You need to calculate the new view position. There a couple of ways to do this I will present one of them:

// Save the previous coordinates
int oldZoom = zoom;
Rectangle oldView = scrollPane.getViewport().getViewRect();
// resize the panel for the new zoom
....
// calculate the new view position
Point newViewPos = new Point();
newViewPos.x = Math.max(0, (oldView.x + oldView.width / 2) * newZoom / oldZoom - oldView.width / 2);
newViewPos.y = Math.max(0, (oldView.y + oldView.height / 2) * newZoom / oldZoom - oldView.height / 2);
scrollPane.getViewport().setViewPosition(newViewPos);

You can add many usability improvements and optimizations but what I described here is an easy to implement and usable component that can be used in any application.

Categories: Programming Tags: , ,

How to Create a Pdf in Php Using Tcpdf

December 15th, 2009 No comments

There are several ways to generate PDF files in PHP. Each has its strengths and weaknesses. TCPDF strikes a good balance although it is far from ideal.

The best way to transform some web page to php is to let the user print it. With some free software like PDFCreator, you can get far better results than anything you can achieve using the available php libraries. Sometimes a client really wants this option or you need to generate some kind of report on the fly. This is when TCPDF is a good choice.

There is no special handling to use the library. You can download it, unpack it and include it in your project. For some advanced features, you might need to allow writing in the cache and images folders. To use it, you include the tcpdf.php file and some configuration file. You will need to make a custom configuration for more advanced features but the default one will work in most cases.

require_once('tcpdf/config/lang/eng.php');
require_once('tcpdf/tcpdf.php');

If you use the library from a cronjob or command line you might get this error: PHP Notice:  Undefined variable: k_path_url in tcpdf\config\tcpdf_config.php on line 75

This is where a custom configuration file is useful but the fastest way to fix it is to just initialize that variable ahead of the config file. It will work for most of the tasks.

$k_path_url='';
require_once('tcpdf/config/lang/eng.php');
require_once('tcpdf/tcpdf.php');

The functionality is available using the TCPDF class. I think the OOP approach stops here because there are no other classes used (with a minor exception) and I assume the author took this path to compensate for the lack of name spaces in PHP.

The flow is simple: create a TCPDF class, call its methods to generate pages, text and drawings and then save the content. Here is an example:

<?php
require_once('tcpdf/config/lang/eng.php');
require_once('tcpdf/tcpdf.php');
 
// create new PDF document
$pdf = new TCPDF(); 
 
// set font
$pdf->SetFont('times', '', 16);
 
// add a page
$pdf->AddPage();
 
// print a line
$pdf->Cell(0, 0, 'Some text');
 
// print html formated text
$pdf->writeHtml('Html text:<br /><b>Bold</b>');
 
// draw a circle
$pdf->Circle(30, 30, 10);
 
//Close and output PDF document
$pdf->Output('out.pdf', 'F');

The library includes a set of examples to demonstrate what it can do.

A TCPDF object maintains internal coordinates used to write text and html with Cell and writeHtml. These methods (and some other related) use these coordinates to maintain the flow of text on the page and add new pages if needed.  They also take into consideration the page margins and headers. The drawing functions are relative to the origin of the page and do not use the Cell coordinates system. This will complicate the job for reports requiring a good layout and a lot of drawing.

The html support is limited. The html needs to be well formatted and only a limited set of tags is supported. There is no error handling for unsupported html so in the best case you will only get some strange php warnings like division by zero and others. You will have to specify the width of the table cells to maintain a minimal control of the layout because the tables are not rendered/positioned as in an usual browser.  I advise against using tables to control the layout of the pdf pages. I assume you read something similar as a web developer.

As a conclusion, I avoid generating complex PDF files in php. TCPDF is the best for the task but it has limited functionality, a poor API and little documentation.

Categories: Programming Tags: , ,