Sunday, May 24, 2009

Problems with Practical Web 2.0 Applications with PHP

I wanted to use the code from Quentin Zervaas's book for a website. There is a lot of good material in the book. Unfortunately, the development environment used by Quentin Zervaas must be very different from my development environment.

I could not get the code to work for days. I kept fumbling around and fumbling around trying to figure out what was wrong. The first problem was the index page code was crashing and leaving no log. It took me a while, but the problem was with the EmailLogger code bye Zervaas.

I am running on a Fedora 10 Linux development server. This is a minimally configured virtual machine running on my under powered VM server. This is not a production server. The first problem comes from the minimal configuration. Zervaas wrote the following code in the file "index.php":

$writer = new EmailLogger($_SERVER['SERVER_ADMIN']);

The code is simple enough it passes the "SERVER_ADMIN" name to the EmailLogger function. On a minimally configured system the value of "SERVER_ADMIN" is "root@localhost".

The EmailLogger function calls Zend_Validate_EmailAddress to make sure the email address is valid. The code is shown below:

$validator = new Zend_Validate_EmailAddress();

The default constructor for the Zend_Validate_EmailAddress only allows DNS hostnames. This means that "root@localhost" is not a valid email address using the default parameters when creating Zend_Validate_EmailAddress. This took a long time to figure out.

The solution is to tell the constructor to allow both DNS and local names. The code to do that is below:

$validator = new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_DNS | Zend_Validate_Hostname::ALLOW_LOCAL);

The support site for "Practical Web 2.0 Applications with PHP" does not document the problem with the email validation. The support site did document the next problem I ran into. This was extra slashes at the beginning of each URL. Instead of the URL being "/index" it was "//index". I tracked down the problem quickly. But every solution that made sense to me failed. The support site has two lists of errata for the book. One list is the old and unmaintained list. The other list is the new and maintained list. The new list does not contain the errata listed on the old list.

A more subtle problem is the wording of the errata. The old and unmaintained list of errata states, "When using Zend Framework 1.0.3 URLs will be generated beginning with 2 slashes." What the errata should have said is "When using Zend Framework 1.0.3 or newer URLs will be generated beginning with 2 slashes." I installed the Zend Framework 1.7.8.

I now have a problem with Captcha and image generation. This has been yet another learning experience.

Monday, May 4, 2009

Rounding Error Are an Important Consideration

My background includes a lot of mathematical analysis. I took a lot of numerical analysis at the University of Utah. Many more classes than were actually required because I enjoyed the combination of math and programming. In addition, I was a teaching assistant for the computational physics classes taught as part of the master's of instrumentation program of the physics department. My first job when I left the University of Utah was working on mathematical educational software. My assignment was part of a group creating a system that symbolically solved mathematical problems. I learned a lot. One of the challenges was checking the work of the system. I spent months doing nothing but math. After giving the system a problem it would generate an answer. Often the answer didn't match the solution printed in the book. We had to determine if the computer's answer was actually the correct answer. The system may not have simplified the answer, or not done some trigonometric substitution or maybe the answer in the book was wrong. It was a lot of work. That taught me the importance of mathematical simplification.

Years ago I worked on a respiratory therapy patient demographic and therapy management system. The company's core intellectual property was the set of equations modeling the treatment efficacy. The equations took the raw numbers provided by the medical instruments and the patient demography and created a meaningful human understandable diagnosis. My task was implementing those equations on a new system. I took one look at the equations and knew something was wrong with them. My background in numerical analysis told me curve fitting software created the equations. The curve fitting software mathematically matched the curve but did not simplify the equations. I convinced the professor that created the equations I could simplify them. For the next month I proved symbolically and numerically my simplification of the equations was correct. Imagine working on a month long math test. I proved the error analysis of my equations was significantly smaller than the original equations. More importantly, the resulting program ran more than ten times as fast.

What does all that have to do with XAML, hex grids, and user controls? You would think I would know better. I start working on making a hexagon a user control and what bites me? Rounding errors! I should have known that rounding errors would cause problems.

I started working on converting the shaded hexagon from my previous blog into a user control. I needed to work out the coordinates where to put each hexagon to create a hex grid. I created a column of hexagons. They looked good. I then added a second column, a third, and a fourth. Things looked great as you can see below.

Then I zoomed in a bit. Then I noticed that the hexagons did not always touch. I immediately knew the problem: rounding errors. You can see that below.

Hexagons tile the plane. Unfortunately you cannot tile them in XAML because you can only tile using simple rectangular patterns. I could use more precision. That would make the problem less likely to appear. The other option is just to make the hexagon grid as a series of polygons; each one calculated using as much accuracy as possible. You can see that below.

It looks like all is well with the hex grid. Until I made a simple change: I changed the stroke width to zero. You can see the result below.

Rounding errors are still visible. What does that mean? The short answer is you cannot expect to perfectly replicate a hexagon grid.

Sunday, May 3, 2009

No Geometry Resources in Silverlight 2

I wanted to create a hexagon grid. There is a good article on how to draw a hexagon grid using C# code here.

I wanted to create my grid in XAML. I used Excel to do the calculations. I also used Excel to generate the polygon points statement. The simplest hexagon in XAML I could come up is coded like this:

<Canvas
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="480"
    Height="480"
>
    <Polygon Stroke="#000000" StrokeThickness="1" Points="0,35,20,0,60,0,80,35,60,69,20,69"/>
</Canvas>

That looks like this:

My next step was to set up a nice radial fill. I put the fill as a static resource. The resulting code looks like this:

<Canvas
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="480"
    Height="480"
>

    <Canvas.Resources>
        <RadialGradientBrush 
            x:Key="HexRadialFill"
            GradientOrigin="0.5,0.5" 
            Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
            <RadialGradientBrush.GradientStops>
                <GradientStop Color="LimeGreen" Offset="0" />
                <GradientStop Color="Green" Offset="1" />
            </RadialGradientBrush.GradientStops>
        </RadialGradientBrush>
    </Canvas.Resources>

    <Polygon Stroke="#000000" StrokeThickness="1" Fill="{StaticResource HexRadialFill}"
        Points="0,35,20,0,60,0,80,35,60,69,20,69"/>
</Canvas>

The resulting image looks like:

I now planned on making the polygon a resource. Unfortunately you can't do that in Silverlight 2. I looked into converting the polygon into a path and then putting that as a geometry resource. Alas, Silverlight 2 does not allow geometry resources.

I have a couple of options. I could make the hex a user or custom control. That would allow code reuse. But at this time, I just want a hex grid. The quick and dirty way is to just write some more macros in Excel and generate the entire grid as a bunch of polygon statements. I could do that probably quicker than it took me to write this blog. However, I am dedicated to quality. I would never allow a developer who worked for me to hack out something quick and dirty like that. That means I need to create a user control and code that up. It will take me longer to code up the user control. The advantage is the resulting code will be reusable (even though I doubt I will reuse it).

I now know what it was like to work for me. I am somewhat of a demanding manager. I want things done the right way with no quick and dirty solutions. Now I can say I apply that standard even to my own work.