« November 2006 | Main | January 2007 »

December 31, 2006

Modernising from tables to cascading style sheets

I've been updating some web pages these last few days. Our web site traces its origins back to 1997 (when we registered wellho.com) and although it's all changed many times since then, there are underlying elements which have been getting a bit long in the tooth. Whole loads of tables that we have spent many sleepless evening debugging are moving aside for cascading style sheets, tags are being updated to the modern standards (matching, quoted parameters, low case tag names, deprecated tags removed) and navigation aids are being updated - when we had 80 pages it was easy enough to find things, but there's now over 8000!

Navigation's a huge issue, in fact. We've so much good technical material out there, but how do people find the right pages within our site?

This evening, I've just released the first of our new-look pages in the solutions centre. See here for an example. And watch the site move across over the next few days to pages that have more content per screen and are more logically navigable. We hope you'll stop and browse a lot more pages in 2007, and book a few more courses than in 2006. Which, however, was our busiest year to date.

Happy New Year, everyone!

Posted by gje at 09:25 PM | Comments (0)


Related topics: via article database
More about Graham Ellis of Well House Consultants

December 30, 2006

Search engine placement - long term strategy and success

"Whenever I search for anything in Melksham, I keep coming back to your site". So say some of our friends; new contacts tend to be along the lines of "So YOU are the ones behind that web site I keep finding".

We encourage the search engines to index our pages, and we know that many of our technical and local area pages ARE read, used, appreciated. It's quite intentional and it does help keep us in touch with past students, to make contact with potential new ones, and to help (for free) those who are too distant from us or who don't need a full course just for one answer.

What places site "A" above site "B" in search engine rankings? There are whole books on the subject, algorithms change over time, and there's a great deal of secrecy in order to keep the playing field level. There's amateurs who will tell you they know the technical secrets, and charge you for their thoughts. There are professionals who do know at least some of the current detail. But I think the real, long term keys to success are as follows:

a) Provide plenty of useful and accessible content
b) Follow the philosophies of the web
c) Make your information search engine friendly

Providing useful and accessible content is no magic, short term thing. I mean providing original text, information that people will be seeking, with plenty of links around the site so that it's reachable. And the information should be updated as necessary and not allowed to go stale either. If in doubt, provide more information and more pages rather than less - we're amazed at the number of visitors who arrive through obscure searches at slightly surprising pages. And your human readers who arrive at your main pages don't HAVE to follow your "History of Beanacre" link, nor your "Beanacre A350 traffic" link if they're just looking for your B&B, do they?

The philosophy of the web is 'open' and 'more'. Wondering whether to put in a link to the local Tourist Information Centre? Why not? You can always have it pop up in a fresh window if you don't want to loose your visitors, but better to have the link than not. You'll be 'rated' by the search engines as a real part of the web (and the whole word 'web' does encourage networking pages!) and your ranking will be helped. But don't go over the top and provide what's just a 'link farm' either.

Should you do the 'technical stuff' like robots.txt files, metatags with descriptions and keywords? I would answer 'yes' even through people argue about the need for an empty robots file, and about which engines use the metatgs. It can do no harm ... and it might do a whole lot of good. And help the search engines by keeping content well apart from style and any script you need.

Are these magic keys to guaranteed engine placement? Of course they're not - but they will help tip the balance in your favour. The cost, though, is a lot of time invested now and in the future. Search Engine placement is rather like driving a big oil tanker. You start the propellor going and at first nothing appears to be happening. You just sit there and wonder whether you actually flicked the switch. But then, very gradually, you start to see movement. And, given some time, you're headed in the right direction. Now you had better be careful to avoid the rocks ...

Posted by gje at 12:25 PM | Comments (0)


Related topics: via article database

Christmas Season Piccies

Mainly for family and friends around the world ... a few random pictures grabbed recently ... you'll recognise who's who, I'm sure, from the Christmas Eve get-together.

Oh - those last two pictures. The Melksham lemon crop, 2006, and Cribbs Causeway shopping centre, Bristol, during the after-Christmas sales!

Posted by gje at 12:23 PM | Comments (0)


Related topics: via article database

Copy multiple files - confusing error message from cp

Thought you might like me to share this one ...

Copying a whole series of files into a directory (Linux, Unix, OS X) using cp, you give a whole series of source files followed by the name of the target directory. Add the -r option is you want to specify subdirectories to be copied recursively in your input.

So this should work, eh?

grahamellis$ cp -r whc.css images grgen.php ~/back_20061229/htaccess
usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-pv] src target
cp [-R [-H | -L | -P]] [-f | -i | -n] [-pv] src1 ... srcN directory
grahamellis$

What an odd result. Is the -r option wrong? No - that's not the problem. In my opinion, there's a bug in cp in that the usage line is incomplete, but that's not the real problem. The real problem was that I specified an existing file name as the target for my copy, and cp won't copy a whole series of files into one.

If I correct my command (by specifying a target directory name), it works perfectly:
grahamellis$ cp -r whc.css images grgen.php ~/back_20061229
grahamellis$

Footnote - if you want to preserve file ownerships as you copy them, use tar instead of cp. You need administrator access (i.e. be logged in as root) to do this.

Posted by gje at 09:59 AM | Comments (0)


Related topics: via article database

Moving files between Windows / DOS and Linux / Unix

Text files written on a Windows or DOS operating system use a carriage return character (ASCII decimal equivalent 13) followed by a line feed (ASCII decimal equivalent 10) as their line terminator, but on Linux, Unix and OS X systems, just the line feed character is used. And sometimes you'll find that there's just a carriage return character used - I've seen it this morning with a DreamWeaver generated Style sheet, for example.

If you're transferring text files around, you'll want / need to convert them in some way, but is you're transferring binary files (such as .jpg) , conversion will damage the content beyond redemption.

Here's a tiny utility that I use - a Perl program that converts a text file that's on a Unix / Linux / OS X box from an alien format to the local format.

#!/usr/bin/perl -p
s/\r\n?/\n/g;

Yes - that's it! Makes use of Perl's topicalisation and awk mode command line options. The source code with comments is available here. I called it cv, put it in a directory on my executable path, and made it executable ... and here's a test:

grahamellis$ od -c fiddle.txt
0000000 L i n e 1 \r \n L i n e 2 \r \n
0000020
grahamellis$ cv fiddle.txt > faddle.txt
grahamellis$ od -c faddle.txt
0000000 L i n e 1 \n L i n e 2 \n
0000016
grahamellis$

Other ways of converting ...
• if you transfer files through FTP in ASCII mode, the changes will be made during the transfer (and if you transfer a binary file in ASCII mode, you'll produce a damaged copy!)
• if you read files into certain utilities / editors, they'll convert the input for you silently and / or work in an alien mode. This applies to vim and wordpad, but notepad can't cope.
• Utilities dos2unix and unix2dos are available on some operating systems.

Posted by gje at 09:16 AM | Comments (0)


Related topics: via article database

Useful link: Linux training

December 29, 2006

Well House Manor and Beechfield House, Hotels, Melksham

"We've gone from a flood to a famine of good accommodation in Melksham" - so we've been saying for the last year or two ... to the extent that we opened Well House Manor as our training centre and business hotel accommodation in October. We're already getting returning / regular Hotel guests, usually requesting "the same room I had last time".

So it's with some trepidation I noticed that Beechfield House, just under 4km from us and a long-established country house hotel, is under new ownership and undergoing development; not a surprise as Beechfield was an option we looked at. But after giving it thought, I think this is good news for the area and will have only marginal effect on our business; our course guests rarely chose Beechfield in the past even though it was included on our lists on an equal footing, citing pricing and location as deciding factors. Looking at the "new", it'll be great to have a really posh local hotel offering formal dining, beauty treatments, swimming pool, four poster beds, celebration party hosting, and even weddings.

We wish the new team at Beechfield all the best in their venture, and hope to be able to mutually refer enquirers where appropriate in the future.

Illustration - Bedroom 5 at Well House Manor

Posted by gje at 07:52 AM | Comments (0)


Related topics: via article database

December 28, 2006

Dates, times, clickable diarys in PHP

It's that quiet week between Christmas and the New Year that's an excellent chance to catch up - a little - on some of the things that are important but have been abandoned in the mad rush of urgent things these last 9 months. Like writing a booking system and like - I hope - spending long overdue quality time with close family tomorrow. Shopping with the masses in Bristol ... I can't wait ;-).

"The customer is King" and "Keep it simple". Not mantras to be adhered to without though, boy good foundation stones against which new designs should be reviewed, and we've been doing some web site designing these last few days. I've been up since - what - around 5 this a.m.; took a constitutional nap in the afternoon, but then got inspiration in the early evening and was (frankly) rushing code for a diary / calendar generator in PHP when the phone-in order of hot and sour soup and Singapore rice noodles arrived from the Peking Kitchen at around 19:30.

"Keep it simple". People want to click on a calendar for their hotel arrival date ... a great way to start their booking. And what's easier than a diary that's updated to start TODAY ... every day? Nice simple script - try it out here and you'll find a source code if you want to use it. You're very welcome - but a link back would be much appreciated - that's to http://www.wellho.net ...

Posted by gje at 08:16 PM | Comments (0)


Related topics: via article database

Useful link: PHP training

December 27, 2006

Passing GET parameters through Apache mod_rewrite

If you're using Apache mod_rewrite to redirect a series of URLs to a single script, did you know that you can pass values entered onto a form via the GET method through as well? Simply add on %{QUERY_STRING} onto the end of your new URL. You'll need to add a ? into the target URL to ensure that the query string is taken as such .... and you can even add more parameters if you wish.

Here's how we divert all requests to .htm, .html, .php, .php4 and .php5 files in a directory to a single script called b.php; we pass in any parameters the user filled in on his web page, and we generate an extra request parameter called pagename that contains ... of course ... the name of the page requested.

RewriteEngine On
RewriteRule ^(.*)\.htm b.php?pagename=$1&%{QUERY_STRING}
RewriteRule ^(.*)\.php b.php?pagename=$1&%{QUERY_STRING}

Posted by gje at 01:05 PM | Comments (3)


Related topics: via article database

December 26, 2006

Date conversion - PHP

A simple piece of code to show you some examples of date reformatting in PHP. Frequently, you'll get dates in a format such as the ones I've started with here and want to re-arrange them, or do something more sophisticated.

My first re-arrangement simply explodes the date string and reforms it. My second converts it into seconds from 1st January 1970 (and I've taken the hour of 12, Midday, to complete the parameters to mktime) then reformats it with the date function.

<?php

$dates = array("2006-10-12","2004-05-08","2007-07-21");

foreach ($dates as $timestamp) {
  $parts = explode("-",$timestamp);
  print "<p>Date is $parts[2]/$parts[1]/$parts[0]</p>";

  $thatis = mktime(12,0,0,$parts[1],$parts[2],$parts[0]);
  $nicedate = date("l, jS F Y",$thatis);
  print "<p>Date is $nicedate</p>";

}
?>

The results:

Date is 12/10/2006
Date is Thursday, 12th October 2006
Date is 08/05/2004
Date is Saturday, 8th May 2004
Date is 21/07/2007
Date is Saturday, 21st July 2007

All done with easy function calls ... as we say in PHP "There's a function to do that"

Posted by gje at 05:35 PM | Comments (1)


Related topics: via article database

Useful link: PHP training

December 25, 2006

Friends and family

Last night, we visited family near Bristol, and stopped in Bath for a quick bite on the way home. The City was rapidly emptying as everyone headed out for Christmas, but we found Nando's in the cinema complex open and a great meal was had by all.

"I hope you don't mind me bothering you, but I came on one of your Perl courses 5 years ago". It's Tony, who also (if my information is right) came to learn Java with us too ... recalling the thanksgiving dinner we had one evening during the course and telling me how he remembered his time with us. Tony - I'm delighted you 'bothered us'; always good to meet up again with someone I've had the pleasure of teaching, great to know that you have great memories of the course. You really made my evening. "Come as a student, leave as a friend" say our coffee mugs.

What a great start to Christmas - an evening with family and friends.

Happy Christmas, everyone!

Posted by gje at 05:48 AM | Comments (1)


Related topics: via article database

December 24, 2006

Apache httpd and Apache Tomcat together tips

Many sites run two web servers - Apache httpd is ideal for plain HTML documents and scripts / programs that are single pages, run rarely, not all linked in together. Whereas Tomcat is an application container that suits applications that are run by tens of people all at the same time - great for banking, student record handling systems, big document and data portals ....

Do you choose one or the other? Not usually - you can run them both and then connect them - see the connector story for details.

During the last course I gave before Christmas, we connected the two servers using mod_proxy, using mod_jk, and even using mod_rewrite to share out the Tomcat load between multiple Tomcat servers. Links - description and link to sample configuration files.

Here's a handful of extra tips.

1. Why not point both httpd AND Tomcat's Document Root at the same directory? That way, you can keep your application in one place and configure your connector to forward ONLY servlets and .jsp-s. The result is an application that's easy to maintain, but at the same time is efficiently using the most efficient server for each element.

2. In early testing and at time you've been reconfiguring, it's worth turning your Tomcat off to test the httpd element rather than starting your tests with everything switched on. The uncommon httpd response codes that you'll get tell you heaps about what's going on.
502 - Bad Gateway. httpd is trying to forward to an non-running Tomcat
503 - Application not available. httpd has forwarded to Tomcat, but Tomcat can't provide the application - typically it's not running.
500 - Internal server error. Your httpd forwarding isn't configured right?

3. When doing a fresh restart of Tomcat with a major upgrade of applications, or after a series of tests that have generated a confusing array of intermediate files that could get carried over to the live application, you can delete the work and temp subdirectories in Tomcat. But, please, only do this when Tomcat is stopped!

Posted by gje at 08:43 AM | Comments (0)


Related topics: via article database

December 23, 2006

Stirling at night

Just back from Stirling, Scotland ... a long day's drive. And it's a little ironic that I found myself in this beautiful place that I'd never stopped in before ... wanting to take pictures, on the shortest day of the year, and fully occupied, training, during the day.

Let's try some night photography:

That's the old bridge over the river, with the castle in the background
Stirling Castle
And the centre of Stirling with Christmas lights.

Posted by gje at 08:55 PM | Comments (0)


Related topics: via article database

December 22, 2006

Old dog, old tricks

The families' internal flight connecting to Heathrow was cancelled due to fog, and they were told by the airline that if they took a taxi there, they could connect on to their long haul flight which was running. A mad dash later, 600 pounds poorer, they got to Heathrow but found they were too late for their connection. "The next available flight is in 15 days" said the airline.

I don't believe everything I read or hear and it strikes me that any airline - even BA who were named in this case - would be very foolish and customer-uncaring to offer such a dreadful alternative in what are, admittedly, difficult days for them. But actually, I believe this case.

I've been at Heathrow it was - let me see - a 14th December. Had my flight cancelled due to ice. "Next flight we can put you on - 28th December". Most unhelpful - "we're not to blame for the weather and can't do anything else". But ... we managed to transfer our tickets and fly out on 15th December with another airline ... loads of empty seats and I wonder how many other people's holidays were ruined that year, needlessly, and are being ruined this (again needlessly), by an airline who don't care enough about their customers to offer the best available alternatives.

Posted by gje at 01:41 AM | Comments (0)


Related topics: via article database

December 21, 2006

Room at the Inn, Guy at the station

I'm posting this on Wednesday but dating it for Thursday as I don't expect I'll have much of a chance to be on line on the actual day. The last working two days before Christmas see me in Stirling, Scotland and the drive looks like it will be foggy and icy.

For a trip to Scotland, I'm in the habit of breaking my journey on the way up at a pre-booked roadside hotel near to destination, but then leaving the booking open on my way back as I don't know how far I'll be safe to drive at the end of a course. But I've made an exception this week - I'll still be north of the Border on Friday night and I'm already booked. After all, this is the time of year when, historically, there was no room at the Inn ... it brings it to me that Christmas is just a few days away. And I expect that all the world and his Aunt will be travelling at the weekend!

Last Sunday evening, I popped by Melksham Station to see whether or not anyone is using the new 19:51 to Swindon - I can't myself see the market for the Sunday service as provided, but want to be fair to the operator is he HAS got this right. Three people got off; one looked lost and was hanging around the station clearly not knowing where he was going. He asked me where he could get a taxi ... didn't know the town, and I'm thinking first time in Melksham. I directed him but he sounded unsure. "Where are you headed" I asked. "Stoke-on-Trent". Wow - not what expected -it's 150 miles. "My money would only get me this far and I'm going to get a taxi and my friends will pay when I get there". And "can you give me a lift to the town". And ... I'm ashamed of myself. I declined. He looked fit but I wasn't sure if he was really with it. Wasn't sure if I ... well - might have been taking a risk. Odd things worried me and so I 'passed by on the other side'.

I don't profess to any religion - in fact I'm decidedly against. However, there are some good teachings and some codes of behaviour to learn from, even though others are abhorrent. Religious holiday periods such as that one coming up do give us a time to think, to contemplate, to set ourselves on a forward path - we'll be doing that over the next two weeks. And I hope that we'll run forward well in 2007 ... I hope I don't make too many errors of judgement such as the cowardly one I feel I made at the station the other day, and I hope that young man reached Stoke-on-Trent successfully and without too many more slaps in his face.

Posted by gje at 01:42 AM | Comments (0)


Related topics: via article database

December 20, 2006

Meet the neighbours

Last night, we held our 'neighbours reception' at Well House Manor. There are 8 adjoining properties, another half dozen or so facing us across the road and some others very close by. Our place would probably have been replaced by 23 dwelling units but for their effective campaigns against planning applications, a section of the neighbours form a powerful lobby that we really want to have on our 'side'. I'm delighted to report that the most concerned of their questions related to how long we intent to be here - they were checking that our business isn't just a short stay of execution.

As soon as you see the hotel reception desk, here with Martin (left) and Christine (right) waiting to greet guests, you realise that we're no temporary setup. And whilst we encouraged our guests to wander through the hotel unaccompanied, we *did* catch the odd comment that made it sound as if they were choosing their favourite bedrooms and 'moving in' - and I understand that's a sure sign of approval on viewings.

"When do you open?". "When do you start running courses here?" A couple of questions asked of me last night. Well actually we've been open for over 2 months and our courses have been running here since October. So clearly we're so quiet that we're not even noticed. And that's good news for everyone; we're going to have a happy and busy 2007, and 2008, and ... yes, beyond ... at Well House Manor.

Posted by gje at 09:05 AM | Comments (0)


Related topics: via article database

December 19, 2006

.pdf files - upload via PHP, store in MySQL, retrieve

There's a common requirement to manage binary data - upload from a user, store, bring back in a web page. And where you have a substantial number of pieces of data - a lot of .pdf documents, .jpg or .gif images, or even Word documents, you'll wish to store them in a database with the potential for keyword and title fields to help in your indexing, and for efficiency of data structure.

Forms can easily be written to upload binary files - although you do need to remember to set the encoding type. PHP can handle the received data and put it to an SQL database ... and can front the retrieval too. The code is short in each case, but I wouldn't say it's simple - you need to understand a lot of what's going on. If you would like to look at my scripts to learn from them ... they're available:

Upload form
Script to store uploaded .pdf to a database
Script to return latest .pdf for you to view

You're even welcome to try out the scripts - upload form which runs the store script when submitted and retreive latest .pdf.

Note - (a) This will also work with .jpg and .gif files if you change the header call in the pdfget script. (b) Please be careful what you upload in our test script - until another upload is done, the world can read it. (c) We offer an alternative image upload example here with more useful tips on binary data upload and handling.

Posted by gje at 11:26 PM | Comments (0)


Related topics: via article database

Useful links: PHP training, MySQL training

December 18, 2006

One Thousand Posts and still going strong

Can you believe it? In the two and a half years I've been writing here I have posted no fewer than ONE THOUSAND items and articles - ranging from the frivolous to the serious, and from the long to the short, and from daily life to highly technical tips.

Why do I do it? Because it gives me a chance to think, to get my thoughts together. I can come up with new working to describe some technical issue that I keep being asked about (and a trainer, of all people, needs to do that). I can give thought to issues that are quite beyond the Open Source world ... be it to the local police's policy on its proactive anti-drink-drive campaign and consolidate opinion, or to finding a picture of a donkey suitable to illustrate a point I was making at the time. And - I admit it - because I enjoy writing. Now there's a rum'un for one who did his very best to avoid English prep at school and can be classified in the lower percentiles of traditional letter writers.

What do I NOT post about? I've refused an offer of a T-shirt that has "I'm blogging it" emblazoned across the chest. That's because, when I talk with you socially or on business, I'm not making notes of juicy incidents to tell the world about. Family will note little reference to them - and that's out of respect for their privacy in both cases. The ups and downs of family life, sicknesses, healths, arguments and financial ups and downs, curious domestic arrangements and custody battles are much more interesting when read about celebrities in "Hello" than they would be here. But I will occasionally turn the corner over when there's a special, positive family occasion. And I hope that family - and now staff - and customers will accept my thanks for their support on this blog and on so much else - I couldn't do without them.

Memorable posts and subjects? My mind springs straight to my post on "technical loneliness" where I commented on how fortunate I am that Lisa understand what I do and how so many people in our business spend their whole days deeply involved in a project, to go home and be unable to share it with family. That one really struck a chord. There's many more - I picked a few random posts as I was reading back in writing today, and every post returned a memory. And, it seems, articles such as my item on MySQL Left Joins and how they differ from normal MySQL joins has struck a chord with others too. Each week, nearly 1000 hits arrive at the page that has that article archived, and we get a flow of "thank you" reviews that helps make it worth while.

So who reads me? More people than I think. Google is an avid reader, but I don't count him or her - although I do count the ladies and gentlemen (s)he sends my way. I'm sure some of them wonder what on earth they have come to! A lot of Well House customers read, too - perhaps they're more on the technical tips whereas family, and extended family read the more personal and thought-ish stuff. Every so often I'm taken a back by a comment that tells me that someone quite unexpected, who I would have felt had little time to visit here, has been and then remembered some of the least significant detail.

"The power of the net". Will it bring World Peace? Probably not, but it certainly brings the world closer. I was emailing, on a technical issue, with a lady Dr in Iraq just before George and Tony invaded. And that sure brought the human aspects closer to home; it didn't seem like a distant country any more. Nearer to home, the power of the net and the power of the word in places like this has been brought home by our 'Save the train' campaign. I would scarcely have thought that we would be facilitators that lead to questions to the Transport minister, or that I would have railway staff approaching me to thank me for the visibility it has helped bring the case. The power of the net also brings us new customers, and helps keep us in touch with existing ones. [[Graham waves "hello"]]. Let's face it, people don't walk up Spa Road in Melksham and knock on a door in the hope of finding a PHP or Python course - they need to establish confidence in the supplier, plan ahead, and book, then (we hope) tell their friends and colleagues. On Friday evening, another trainer dropped by to see our new place. He's looking for work at a time we're rushed off our feet and I Lisa and I found ourselves asking "what's the difference" when he left. And we came up with our enthusiasm, our training structure, our flexibility and support of our customer base as some of the keys. And our support is offered through the power of the net.

Will I carry on? What a silly question I'm asking myself - of course I will ;-) ... But in all seriousness, yes, I will. In writing this article, I've asked myself the question and concluded 'steady as she goes'. Fine tuning. Perhaps a drop off in the article rate over Christmas (but then I always say that and just miss the odd day), but the formula is there and there's still more left out that goes in.

So, at 1000 articles, let me thank YOU may readers, for taking an interest, being here, making it worthwhile. And here's to the next 1000 - who knows what subjects will come up tomorrow, let alone next year. I certainly don't!

-- Graham

Articles mentioned:
Looking for a donkey
MySQL, join and left join
Save the Train
Technical Loneliness
Drink Drive

Posted by gje at 06:32 PM | Comments (0)


Related topics: via article database

Cascading and the buses

1. Public transport services are operated around these parts by the First Group.

2. The 272 bus is operated by Faresaver.

3. Town buses in Melksham are run by Frome Minibuses.

4. If you see a white bus around, it will be the Seend Shuttle

We cascade information in real life. My initial statement sets as broad brush approach, telling you that you'll find, unless otherwise stated, that First will be your public transport operator. But then you'll find that the broad brush statement is overwritten in some specific cases by alternative information - and that extra information may be provided by route, by zone, or because it's a specific bus. And that's very much how cascading style sheets work.

You set a general attribute - let's say the color of the text and foreground - to be purple (hey, that's one of First's colours). You then override the text for all paragraphs - green for example. That's going to represent Frome Minibuses. Paragraphs with a certain label (i.e. belonging to a class) are overwritten with a dirty cream colour - just as buses labelled 272 are run by FareSaver. And finally there's a specific white bus which is the Seend Shuttle.

Style:

* {color: purple;}
p {color: green;}
.r272 {color: olive;}
#seend {color: white;}

Now that was just colour. We can go on and lay attributes such as size of bus, whether it's subsidised by the county council, whether it has low floors, and whether the service runs on a Sunday over the top, each with different cascading requirements and you can see just how complex both public transport in Wiltshire and Cascading Style Sheets can become.

And you'll also learn "KISS" - keep it simple, stupid. For your own sanity, and for the sanity of the users of the service, there should be a clear logic to what's implemented and provided so that the results are understandable and acceptable to all.

Posted by gje at 06:05 PM | Comments (0)


Related topics: via article database

The year of the exploding projector

2006 has been the year of the exploding projector. A BenQ exploded on me in February in Dublin, and our old, old Sony popped out on me today. But then we do use the kit hard ...

Posted by gje at 05:39 PM | Comments (0)


Related topics: via article database

Most recent file in a directory - PHP

Want to report the most recently updated file in a directory in PHP? It's the sort of thing we all want to do, but in a variety of modified forms, quite often ... here's a code snippet to do it for you:

$dir = "/home/wellho/public_html/demo";
$pattern = '\.(html|php|php4)$';

$newstamp = 0;
$newname = "";
$dc = opendir($dir);
while ($fn = readdir($dc)) {
  # Eliminate current directory, parent directory
  if (ereg('^\.{1,2}$',$fn)) continue;
  # Eliminate other pages not in pattern
  if (! ereg($pattern,$fn)) continue;
  $timedat = filemtime("$dir/$fn");
  if ($timedat > $newstamp) {
    $newstamp = $timedat;
    $newname = $fn;
  }
}
# $timedat is the time for the latest file
# $newname is the name of the latest file

You'll note that I have provided separate varaibles for the directory to be searched and a regular expression that's to be used for filtering file names - you'll always want to skip over . and .., and you'll normally want to ensure that backup files, hidden data, etc, don't get logged.

The code that uses $newname and $timedat later on needs to take care of the case in which they're null / empty - i.e. if you've looked through a directory that didn't contain anything.

The source code is available here in full, and you can run the script here. Note that the time / date report is the server time / date and not the time / date from the country you happen to be browsing in.

Posted by gje at 07:16 AM | Comments (0)


Related topics: via article database

Useful link: PHP training

December 17, 2006

Setting your colour theme through PHP

Although we usually think of PHP as a server side language concerned with databases and the driving of applications, it's also of great use in controlling the use's look and feel ... indeed, I've just written a number of examples of how PHP can be used to select a set of colours (themes) for the user. Here's the sort of code that you might find in the PHP page.

<?php if ($_REQUEST[colset] == 1) { ?>
body {color: navy; background: olive;}
.person {}
.toptit {font-size: 140%; color: purple;}
.total {color: maroon;}
<?php } else { ?>
body {color: yellow; background: black;}
.person {}
.toptit {font-size: 120%; color: aqua;}
.total {color: green;}
<?php } ?>

The use of a themed approach rather than providing controls over individual attributes means that the page provider can select appropriate combinations and allow the user to quickly and easily switch between the - the opposite alternative of providing controls on a per-attribute basis may give far greater flexibility, but it also gives rise to a system that it's longwinded for the user to change, and a system in which the user can, potentilly, hit on a totally inappropriate combination.

See - source code and code demonstration

Our new course module also includes a step by step guide to generating separate style sheets through PHP - ideal for a shared-style web site, and vital if you're concerned with flexible coding to meet the UK's DDA (Disability Discrimination Act)

Update - I've added a complete example into the new course module that combines PHP, style themes, cookies and a pulldown menu to change the themes. See here for the source code and here to run the code

Posted by gje at 04:10 PM | Comments (0)


Related topics: via article database

Useful link: PHP training

Ruby's case - no break

It has always struck me that switch statements in languages like C, PHP, Tcl and Java are very longwinded and clumsy, with a need for blocks and blocks, and every case having to end with a break (or equivalent) to stop multiple cases being run via a drop-through. I can understand why they were written that way in the first place but ... ouch.

Ruby's case / where, then, is a breath of fresh air. Easy block structure, multiple options allowed (and a special === test that helps make the case selection easy) and no need for those breaks either!

Larry Wall has steadfastly refused requests for a switch in Perl as you don't need it and ... he agrees with me ... it's clumsy. But Perl 6 will have a given alternative with when clauses which works in a similar way to the superb Ruby solution. My hat off to Matz and Larry.

Posted by gje at 10:13 AM | Comments (0)


Related topics: via article database

Useful link: Ruby training

Training on Cascading Style Sheets

There are certain technologies such as Cascading Style Sheets (CSS) that I describe as associated technologies - not our bread and butter training business, but never the less subjects that we need to know, quite well and with practical experience too, as part of our work.

These technologies get peripheral reference during our courses, and we'll gladly work with delegates to show how they tie in - in the case of CSS, that's often no more than a reference to a style sheet from within the HTML part of a web page generated by PHP or Perl. But sometimes, delegates wish or need to go deeper, or to integrate more closely. And so we find ourselves writing further training material which ... given further resources .... could become popular in their own right.

Here's such a new potential public course, on Cascading Style Sheets, and the dynamic use of style in PHP. Pre-requisites include both PHP and HTML skills, and the running length would probably be one and a half days.

spacer Introduction to Cascading Style Sheets (module W701) What and Why? Structure. External, embedded and inline styles. Loading Style sheets. What is cascading and how does it work?
spacer Elements of cascading style sheets (module W702) Standard elements. Selectors - element, class, universal, ID and attribute. Pseudoselectors. Document structure and hierarchy. Comments in CSS. Values and Units. Length and colour. Font - families, faces, style, and size. Text transformation, alignment, decoration and spacing.
spacer Page layout with cascading style sheets (module W703) Page layout, margins and padding. Floating objects, inline and block display. Positioning and overflow. Visibility.
spacer Cascading style sheets - putting it all together (module W704) Putting it all together. Tables v Cascading Style Sheets.
spacer Generating CSS through PHP (module H118) Basic steps. Configuring PHP to parse .css. Mime Type text/css. Dynamic input via GET, cookies and SERVER. A worked example. Caching issues.

Would this be useful for a lot of people? Yes, it most certainly WOULD. There's a requirement under the UK's Disability Discrimination law (the DDA) to ensure that all services are at least equally accessible to anyone who might be described as disabled, and that means things like providing font, colour and perhaps layout changes to suit on your web site. And, frankly, that makes business sense too; why not allow people to change the look and feel of your web site to work for them, even if they're fit, health and with excellent sight!

And the hard work is done, The course is written, tested, and we have the experts to present it. Two things hold me back - a lack of time, and a worry that potential delegates couldn't sell the course to their managers and get authorisation to come along and learn the subject; there are some topics that we can really help with but which are hard to justify to non-technical bosses, and I suspect this is one of them.

Hey - if you're interested in learning about CSS and how you integrate it with PHP for an improved look and feel, such as DDA conformance requires, please email me. And we can put on a fabulous "extra" day for you ... or a full private course if there's a group of you. It's a great subject, can do useful things, and I would love to teach you and show you how it can work in your environment.

Posted by gje at 08:34 AM | Comments (0)


Related topics: via article database

December 16, 2006

Positioning with Cascading Style Sheets

I've been busy updating some cascading style sheet demonstrations and adding to material today, including some positioning demonstrations which, I must confess, have been a bit frustrating at time. There's just so much I want to show without producing a great fat book with lots of long examples ... yet at the same time I want valid sample data in the pages. A tall order perhaps? Well - have a look for yourself at what I've done, if you like.

The demonstration page presented.

The list of contents for the module.

HTML source.

CSS source.

Posted by gje at 05:39 PM | Comments (0)


Related topics: via article database

Enthusiastic, but ....

I'm enthusiatic in my support for the TransWilts train services, but I'm not an enthusiast. And I'm not an expert on any aspects of the railways, but I have some expertise on aspects of how the railway runs. Such is the symantics of my ongoing pressures for an appropriate level of train service for the TransWilts line through Melksham.

It's an odd world, where a good question or a strong proposal that has no obvious holes in it elicits attention (perhaps limited just to being logged as a consultation input, but that's another day's story), but a proposal that's perceived as being from someone who's an expert outside the railway industry is deride with the word "amateur" applied.

And it's an odd world where enthusiasm for making good use of train travel is applauded, but taking an interest in which trains are used (even when it relates to timekeeping issues and comfort levels) has one put down as an 'anorak'.

In our training business, we listen our customers - not only do we encourage inputs at any time, but we then analyse and act on those inputs wherever it's appropriate to help us improve our product. With the train business, I get the impression that customer inputs are a necessary data flow to be received and analysed, but it doesn't go much further except in the case of extreme political pressure. Perhaps that's why our delegates agree with our "come as a student, leave as a friend" even after we've had our annual price review, yet companies such as First are getting bucketfuls of stick even before their January price rises have come into effect.

Posted by gje at 05:08 AM | Comments (0)


Related topics: via article database

Adding a member to a Hash in Ruby

In Ruby, you must initialise your variables - in other words, you cannot use the content of a variable that doesn't exist and have the language assume it will be 0, as happened with Perl.

So if - for example - you're using a Hash to keep tabs of a number of counters, you can't just +=1 members and have them automatically created if the dont already exist - you get an exception:

irb(main):001:0> demo = {}
=> {}
irb(main):002:0> demo["Graham"] = 25
=> 25
irb(main):003:0> demo["Graham"] += 1
=> 26
irb(main):004:0> demo["Lisa"] += 1
NameError: undefined method `+' for nil
from (irb):4

The fetch method on a Hash allows you to fetch a value if one exists, but return a default if the element you're looking for is undefined and that's a really effective way of initialising new counters to 0:

irb(main):005:0> demo["Graham"] = demo.fetch("Graham",0) + 1
=> 27
irb(main):006:0> demo["Lisa"] = demo.fetch("Lisa",0) + 1
=> 1
irb(main):007:0>

In some circumstances, the fetch behaviour is what you'll want .... but in others, it's more likely to be better to process the circumstance via an exception with a rescue clause.

Posted by gje at 04:49 AM | Comments (0)


Related topics: via article database

Useful link: Ruby training

Ruby - Totally Topical

Ruby supports topicalisation - the $_ variable being set by certain statements when a piece of code such as gets in a while statement isn't assigned, and the the same variable being used in many other methods - and even as the object on which methods run by default - in following code.

Here's a piece of code that does NOT use topicalisation:

while info = DATA.gets
  iparts = info.split(/\s+/)
  next unless info =~ /Ruby/
  puts iparts[-1]
  end
__END__
Ruby is a great language
Python is a good language
Ruby is a type of gem
Python is a species of snake
Ruby is a colour
Woodland is a group of trees

And here is the same piece of code with the default input and pattern matching space left out everywhere that info occurred above. And split defaults to splitting at white space, so that can be simplified too.

while DATA.gets
  iparts = split
  next unless /Ruby/
  puts iparts[-1]
  end
__END__
Ruby is a great language
Python is a good language
Ruby is a type of gem
Python is a species of snake
Ruby is a colour
Woodland is a group of trees

Whichever way I run that:

grahamellis$ ruby gloop1
language
gem
colour
grahamellis$

Posted by gje at 04:45 AM | Comments (0)


Related topics: via article database

Useful link: Ruby training

December 15, 2006

Melksham Quiz

Q: In what year did Charles Maggs set up a Rope factory in Spa Road, Melksham?

That's one of the questions from a quiz ... where all the answers were numbers ... that I set up for the ladies of the Bowerhill Villager for their Christmas quiz last night. The theme wasn't "Christmas" but there was certainly a "Melksham" element to the quiz.

The idea of the quiz is that all the answers are numbers ... so that you can score each question first, second, third, etc from whoever gets the nearest answer. And that can give you prizes out in order and have a winner for each question.

If you want to try the quiz ...

There's a copy without answers here ... and when you want to know what the answers are, you can take a look at the questionmaster's copy here.

Charles Maggs moved to Melksham and set up his rope factory in 1803, by the way, according to http://www.wiltshire.gov.uk/community/getcom.php?id=158.

Picture - the Masonic Hall in Melksham. More pictures of Melksham ... and of Bowerhill

Posted by gje at 08:12 AM | Comments (0)


Related topics: via article database

You should think you're first in a hotel room

"We want our rooms to appear to be so clean, fresh and new that each guest feels he's the first to use them". A laudable target, but realistically one that's not going to be achievable for every single letting. Never the less, I was shocked to be asked by a delegate this morning "did Axxxxx Dxxxxx stay in my room last week". And I did happen to know that said A.D. had stayed in that room ... about a week previously, and there had been other guests in there in between.

Had A.D.'s colleague - for that's who our new guest is - found one of A's socks under the bed? A bottle of A's distinctive handlotion in the bathroom cupboard? A's hairs in the shower?

No ... it turned out that the radio was set to Radio Cymru ... and THAT was the clue. I think we can be forgiven that one, although I am very conscious that the TVs need to be reset between guests. I've personally found subtitles switched on several times, TV set to analog not Freeview and - well - we should have them such that the "on" button come straight up to a selected channel for each new guest. These are things we're learning in our current 'running in' mode that turns at the turn of the year.

Posted by gje at 04:58 AM | Comments (0)


Related topics: via article database

Ruby v Perl - interpollating variables

When printing in Perl, you can drop a variable into a double quoted string ant it will be interpretter for you:

"--- $number ---"

If you want to perform an operation on the variable, though, it's not as easy - you have to come out of the double quoted string, do the calculation, then start another string:

"--- ",$number + 1," ---"

In Ruby, variable names do NOT start with a $ so you can't simply drop them in to your double quoted string. Instead, you can write #{expression} within the double quotes and that gives you ...

"--- #{number + 1} ---"

And that's fabulous - it gives you the ability to write any expresion you want, or just a simple variable, with a double quoted string and have the same simple syntax for both.

Posted by gje at 04:57 AM | Comments (0)


Related topics: via article database

Useful links: Ruby training, Perl training

puts - opposite of chomp in Ruby

In Ruby, the chomp method removes the last character of a string if it's a line separator. The puts method adds a new line character on to the output unless there's one already present.

In Perl and other languages, a great deal of time and mental agility is expended in remembering where there are (and where there are not) end of line characters, and this practical ("pragmatic") approach in Ruby really makes life easy.

Posted by gje at 04:56 AM | Comments (0)


Related topics: via article database

Useful link: Ruby training

December 14, 2006

Equality in Ruby - == eql? and equal?

The == comparison checks whether two values are equal

eql? checks if two values are equal and of the same type

equal? checks if two things are one and the same object.

How do I remember which is which ... The longer the operator, the more restrictive the test it performs

Example:

irb(main):013:0> val = 17
=> 17
irb(main):014:0> val == 17.0
=> true
irb(main):015:0> val.eql?(17.0)
=> false
irb(main):016:0> val.eql?(17)
=> true
irb(main):017:0> val.equal?(17)
=> true

Posted by gje at 04:49 PM | Comments (0)


Related topics: via article database

Useful link: Ruby training

Cardinal numbers and magic numbers

A cardinal number, in computing terms, is a term that's sometimes used to refer to a fixed condition - in other words, you might call a function with one parameter should of the usual number, and the final value will be assigned a cardinal number that can't occur there in reality. For example, you might call a function into which you input the number of children a person has, and if no value is entered the value could be set to a cardinal 999 that's checked for by the code. Should work, shouldn't it? After all - no-one could have 999 children. And it would work fine until the local headmaster, with a role of 1 short of 100 students, runs it on his hordes

A magic number is formed of certain bytes at the start of a file which signify the content type in the file. For example, the first three bytes of a .gif image file are GIF. The Unix and Linux file command uses magic numbers to identify content type.

Posted by gje at 04:48 PM | Comments (0)


Related topics: via article database

Blessing in Perl / Member variable in Ruby

How do you decide what member variables you have in an object in Ruby? Well - in Perl, you bless a single hash (or, exceptionally, a list or a scaler), but in Ruby you refer to each variable that you wish to be a member of each object using a preceeding @ character.

Perl:

bless \%abc;

Ruby:

@abc = ...

Posted by gje at 04:47 PM | Comments (0)


Related topics: via article database

Useful links: Ruby training, Perl training

Notes from the white board

I come up with my best presentations in front of a class. There's nothing like having the adrennalin flowing to fine tune the way some information is got across, and nothing as good as an inquisitive group of delegate to inspire a new approach. So I end up with some notes on the whiteboard that I REALLY don't want to loose.

These days, I'm using my digital camera to record off the board. Yes, really. It's the best way, for me, to do it. Have you seen those whiteboards that record onto a sheet of paper, about A4 size, off a roll? Yes - I have too, and usually they're sitting in the corner gathering dust in a crusty conference room or just being used, not plugged in, as an expensive shite board. Have you seen those project-and-mark-over PC based systems that let you save you screen? Yes, but they can be awkward to use and you have to be writing / drawing on a designated, lower resolution, area. Thus - the 7.1 Megapixel camera.

But there's no 'perfect' way of recording the board. Ideally, a button pressed would record the board in a manual-quality set of diagrams, with words OCR'd too. My camera has compromised too.

 

Both of these diagrams are readable (just, but then I HAVE squashed them more than I usually would), but the one on the left is flashy and the one on the right is distorted. Personal choice - I'll stand slightly to one side as I take the picture and that'll prevent the flash bounce. If need be, Photoshop could be used to clean up.

Or - as in the case in point here - I can simply use the picture as the basis for typed documentation later ... here goes:

Setting up a web server - critical task excercise

1. Change the DocumentRoot - where the web site home is located - in 2 places in the configuration file. You really don't want the web site data to remain in the same area as the server software

2. Change the User and Group. There are security issues if you leave the user as nobody and the group as -1, especially if your web server is also a file server with somethng like NFS

3. Change the server name and the administrator's email address. Ensures that directories requested without a trailing /, and redirects, work correctly. Also that standard error pages give an appropriate email address for users to contact

4. Set up the error pages. You want to present your user with a professional "page not found" and not the minimal, standard one.

5. Change the log file format to "combined". It's worth adding extra information to your server logs if you're going to actively monitor traffic to your site and want to make best use of the available marketing and search engine information it can provide

6. If you want to run Perl or Python via CGI, turn it on Server side programs are off by default - a good decision as it's a facility you really want to consider carefully before offering

Other things to consider early in the configuration

a) Disable the Apache httpd manual pages??

b) Allow users to override default server settings in httpd.conf via a .htaccess file ??

c) Allow each user to have their own home directory in the form ~username ??

Further notes from the Whitebaord

I also made notes yesterday, via the whiteboard, on the file system structure of Linux and of httpd ... now documented in our solutions centre

Posted by gje at 06:12 AM | Comments (0)


Related topics: via article database

December 13, 2006

Finalist reception - Wiltshire Business of the Year

Last night, we attended a cocktail party thrown for the finalists in the "Wiltshire Business of the Year" competition because ... well, because we're finalists. I understand that there was a record entry this year - the first year we have entered - and that our category which is "Small Business of the year" was the biggest. That figures ... there's a lot of small businesses from Highworth in the North of the county to Mere in the South. So it's quite a feather in our cap to have got this far.

Mark Suddamore, the Managing Director of the newspaper organising the event, made a presentation, and plaques were awarded to all the finalists. As far as I'm personally concerned, entering the competition was an excellent tool through which we could look at the business and say to ourselves "Have we thought of all aspects" and "how do we stand up as others in business see us". So in some ways, the taking place was more important that the achievement of a place in the final, or the certificate. Having said that, it's certainly something that will help with our "street cred".

The event was held at the deVere Hotel in West Swindon (note to organisers - a bit of rush for those of us working up to 5 p.m. from out of town!) and well attended. And the networking opportunity was most welcome. Not necessarily to sell hotel rooms or places on courses (from a marketing viewpoint, such an event doesn't bring potential Open Source trainees together in great numbers!) but rather to look, to listen to others, stories, views, and to learn from them. I came away with the view, re-inforced, to remember both the large AND the small customer. This week, I'm training a medium sided organisation and two very large ones and I'm delighted to be doing so. Next week, I have a minnow. And they're equally important. I confess to being grateful to one of our fellow finalists who were busy assuring me that repeat business is the key in [[names trade]] ... and that means that you provide good service to 'chain' stores and only lip service to the independents. I'm glad we're not in their line - that's not an approach I would wish to take. And, come to think of it I suspect they were up for small business of the year too!

Posted by gje at 07:28 AM | Comments (0)


Related topics: via article database

December 12, 2006

Street Scene

Pre-Christmas street scene in Melksham. Some of the locals decorate their houses and the other locals come around and look over the gates. The point of it? Festive fun, and collecting for charity.

Lights are on from dusk until 22:00 until 5th January. Longford Road, Melksham.

Further pictures in our Wiltshire pages

Update - December 2009 New Official Melksham Christmas lights page here.

Posted by gje at 02:42 PM | Comments (0)


Related topics: via article database

December 11, 2006

Empty seats, Nodding Donkeys and buses

This has been a tough weekend ... with a mountain of Well House Consultants and Well House Manor issues to be dealt with, but with my eyes off that ball rather more than they should have been because of all the events going on with 'the train'. Friday, and the last commuter service. Saturday, the Santa special. And then Sunday, frankly, exhausted to achieve what I needed to do. Oh well - everyone needs a break. Today started - my goodness - on the 06:48, back at Melksham at 07:17 to see how the service was doing.



The 06:19 off Swindon was pretty quiet - just 3 passengers into Melksham where 3 more (myself include) joined.

The 07:08 from Trowbridge was much busier - you can see the passengers here in one of the two coaches of the "nodding donkey" - the Pacer train that appeared on the service for - I think - the first time this morning. I've seen Pacers referred to as "the most hated trains around" because of the rough ride but .. .there WERE passengers on board. It was rather harder to find anyone who'll be on the return journey tonight, and I worry about the loading.

If you want to travel to Swindon at any time other that around quarter past 7, or 8 at night, you now need to take the bus. I did this with the HTV camera crew this morning, and got soaked. Meeting them at 07:30 at Melksham station, I got onto the train at Chippenham that was due into Swindon at 09:10 - a sad journey when, last week, the 07:45 train would have had me there by 08:15. Picture - on the bus with a group of college kids who said it was the most exciting morning for them in an age, and were asking the film crew many questions ... as they (the kids) are doing media studies.

Oh - and I was cold, wet and definitely well exercised too!

Footnote / Background. We have encouraged our customers to use the train service to reach our Melksham training centre over the years, and we've seen a service that's grown dramatically - compound growth of between 7% and 35% per annum depending on which measure you take. That wasn't enough for the powers that be, and the service was slashed last weekend to just 2 trains each way daily, and those at times for which I personally can't see much of a market. At Well House Consultants, we've sponsored the save the train web site to campaign for an appropriate service in the full knowledge, it must be said, that we only had a slim chance of changing the view of the remote and faceless decison makers .... but if you don't try ...

Posted by gje at 03:39 PM | Comments (0)


Related topics: via article database

December 10, 2006

Wellhouse Manor, Hotel, Melksham

One word or two? Is it "Well House Manor", or "Wellhouse Manor". Well - really, it's three separate words but folks do write it either way. We've already got a "Wellhouse Consultants" page on our training site, as s service to anyone who does a search for us in that form and I hope this page does the same for the hotel.

So what should I tell you about Wellhouse Manor in this post?

That it's a business hotel in Melksham, Wiltshire with business services such as internet access available throughout, luxury bedrooms and much more.

That during the week, we're often busy with customers on our training courses, but that we do encourage "pure hotel" booking too if you're visiting one of the other businesses in the town.

That at the weekend, this is a lovely part of the country to visit and we provide an ideal base for Bath, the Marlborough Downs, Longleat and too many other places to mention. All rooms double / twin ... ideal for smoke-free, dog-free, child-free couples who are happy to share a 5 bed hotel with more of the same.

And I suppose I should provide you with ;-) ... the Well House Manor web site itself

Posted by gje at 11:38 AM | Comments (0)


Related topics: via article database

Melksham and Norwich

Perhaps you've come across NORWICH, but have you come across MELKSHAM?

"In the Second World War soldiers used to send letters home to their sweethearts with MELKSHAM written boldly on the back. It stood for May Everyone's Love Know Such Happiness As Mine"

Source - the Knowhere guide

Posted by gje at 06:18 AM | Comments (0)


Related topics: via article database

December 09, 2006

Santa at the station

Santa Claus came with us on the train today from Melksham to Swindon and back .. and there were so many children to see him that he had to get off at Melksham when we got back to finish his rounds.

A great time had by all, and a big THANK YOU to Santa, and to the Melksham Rail Development Group who organised the event.

Posted by gje at 07:54 PM | Comments (0)


Related topics: via article database

Answering ALL the delegate's Perl questions

During courses, questions arise. "I'll get back to that" could make people feel that I'm brushing something off ... except that I explain, early on, that some questions require a great deal of background knowledge to be answered sensibly. And I keep a list of topics that I'll be getting back to on the board. The list is right by the door of the training room, and items get checked off as we go.

Here's the list that's on the board this morning, after the conclusion of a week of Perl training. I'll comment briefly on each subject so that you can get an idea of the sort of extras - the extras that you want - that we typically cover.

modPerl is an improved through-put way of providing a web based application in Perl. As opposed to the more common CGI approach, where a program is started each time a web page is called up, the program is left running within the Web server under modPerl.
Source example and related resources

Directory Parsing. We covered how to parse directories with struscures such as <*> and also opendir, readdir ... also a scheme for recursive directory parsing using a list as a queue.
Source example and related resources


Perl's ref function allows you to see what a scalar contains - whether it contains a reference to a hash (in which case is returns HASH), a reference to a list (ARRAY is returned) or a scalar (in which case you get SCALAR back. Although you won't want to say "what's in this variable" very often, there are times you do so when handling XML.
Source example and related resources


CGI - the Common Gateway Interface - allows Perl code to be run very easily through a web site, even if the original logic was coded for a different environment. We looked at how code is topped and tailed to "webify" and secure it.
Source example and related resources

Huge data and sorting. Sorting efficiency, with intermediate caching, and handling data flows that are so large they can't be stored in memory all at once.
Source example and related resources

An Introduction to Object Oreintation in Perl. Perl's OO offers a great deal - all the things like polymorphism and even multiple inheritance are covered. You can do some unexpected things too like change the type of an object once you've created it, and use polymorphism on a list of objects that aren't even based on the same subclass.
Source example and related resources

The Net::FTP module allows Perl to drive an FTP session in just a few calls.
Source example and related resources

The LWP module - Library for Web Processes - was demonstrated, with a "crawler" application to visit a few pages on a remote web site, mirror them locally and report on any changes.
Source example and related resources

And finally, we can back to look at how Perl uses SQL via DBI and DBD modules. Actually, this is something we do on almost every Perl course, as the requirement is a routine one. The DBD and DBI are tiny droplets of 'glue' that firmly bind the two monoliths of Perl and a database such as MySQL.
Source example and related resources

Delegate leave all switched on and lit up with Perl ... happy that we've provided answers to all the questins that they had, and prepared to extent their knowledge in their own field of work.

Posted by gje at 08:36 AM | Comments (0)


Related topics: via article database

Useful link: Perl training

The last commuter train through Melksham

"We have altered the trains from Monday". "Please check for changes to your trains". "First - Transforming travel". Theses are the messages writ loud in the publicity surrounding the current train timetable changes. And they read positive, don't they?

I was very disappointed on yesterday evening's train from Swindon to Southampton - the very last commuter service on that route - to find that many travellers were unaware that 60% of the already-few trains running south of Chippenham from Sunday are WITHDRAWN, and that commuters from Westbury, Trowbridge and Melksham into Swindon face an extra 90 minutes on their day. Disappointed by, alas, not surprised. Although we've tried, via the "save the train" web site, to reach people, let them know, and have them join us in a campaign for an appropriate service, we're a David v their Goliath.

First have made themselves look like arrogant fools in their casting of an excessively positive light on the new timetable changes - sweeping as far as they can any bad news under the carpet, treating (over the past few weeks especially) passengers on the TransWilts service with contempt as they cancelled the busiest train of the day - the 17:43 from Swindon - time and time again (official target - 98.5% to run. Achieved - around 70% to 80% depending on the time period you take).

As a result of the lack of balanced information, Andrew Griffiths who's their supremo for the line got a tremendous earful from at least one very angry traveller last night. Of course, he's a company man and blames the negatives on the Department for Transport, but at times I do believe that their's a degree of complicity (and perhaps a fair degree) between the DfT and the francishee. And it's all about maximising profits, minimising delays, reducing subsidy. Nothing about the customer. The customers who were in the know on this line asked, long and hard, for amendments to the draft timetable to make their working day a little shorter than what was proposed. Yet First amended the draft into a final timetable that's made the day yet, yet longer. Because, it appears, it lets them run in what's called "marginal time" - time when there's more trains available because, frankly, that's a time when no-one actually wants to travel by train, and alas, that applies to travel via Melksham too.

What will people do as from Monday?

Sxxx will extend his journey time by 25 minutes each way and make a bus-train journey where he currently takes train-train. A crossplatform connection is transformed into a much more awkward one. Fare changes for the new route mean he'll be paying more for the service that will be worse for him.

Wxxx was on the 17:02 from Melksham yesterday, returning to London. It's a very occasional journey for him personally, but various colleagues of his make the journey and use this service from time to time. Next time one of them travels? Well - they're our customers and we'll probably give them a lift to Chippenham station, or have them get a taxi; the evening buses from Melkham don't to to Chippenham station and I am not suggesting to my customers that they drag suitcases the half mile transfer that recommended new route would involve.

Rxxx will set off earlier (06:47 from Frome, as against 07:20) and have to change at Westbury for Swindon. In the evening, the new train is just too late and the new journey home will involve a dogleg via Bath, with 6 flights of stairs and a poor connection.

Gxxx heard of the withdrawal for the first time on yesterday's train. An infrequent (but repeated) traveller from Chippenham to Westbury, with child and heavy baggage, she was too shocked to have any ide at all what she will do in the future. She DOES know the "Bath change" option and doesn't consider it practical.

Axxxxx is one of the Great Western staff. He won't be inconveninced by the change, as he won't need to be in the area when there's no train.

Txxx can't drive. His wife will be driving up to collect him from work each day as there's no viable alternative in his case. He doesn't expect his new situation to remain like that for very long though ....

Illustration - the very last Monday-Friday train to Swindon under the old service pulls out of Melksham

Posted by gje at 07:08 AM | Comments (0)


Related topics: via article database

December 08, 2006

Too much used to Skype

You know you're too much used to Skype when you press "enter" on a forum and expect the line you've just typed to be posted right away!

Posted by gje at 02:47 PM | Comments (0)


Related topics: via article database

Both one team and two

Last night ... a great night was had by all at the skittle evening we arranged at Melksham House - the Cooper Avon sports and social club here in Melksham.


It was a great chance for Lisa and I to thank our team of staff and close helpers for all the hard work they've put in over the past months, with the transformation of "The Old Manor" into Well House Manor, getting the new operation well oiled and running on its feet, and continuing the core business throughout. We really appreciate you all and couldn't have done it without you!

Customers are vital to every business, and none more so than to a training company like ours, which covers a niche market and trades on reputation.

We were delighted to be joined by our customers on this week's Perl course at the Skittles evening, and it was a close-run match between Steve's "Fluffy Bunny Rabbits" and Andrew's "Surfing Life". Honours were split, with the top two bowlers both coming from the lower scoring team.


We've come a long, long way since we moved to Melksham on Christmas Eve in 1999. Little did I image that Well House Consultants would grow such that we could put two skittles teams together just 7 years later - and we've got such a happy team too. Thanks for a great job well done, an enjoyable evening, and making working here so much fun. And here's looking forward to a fantastic 2007, whatever it may bring.

Posted by gje at 05:18 AM | Comments (0)


Related topics: via article database

December 07, 2006

Wiltshire letterboxes

I've been updating our Wiltshire pages overnight, taking the big OPEN SOURCE TRAINING banners off the top so that we can make the pages of more general interest to all our hotel guests.

What to replace the banner by? I started off looking for 740 x 87 pixel images and concluded, rapidly, that that is just too much of a "postbox" to work well even for me, so I've changed over to a selection of 370 x 87s ... here are some of them:
 

 

 

 

 

 

 

 

Have a walk through some of the newly redecorated pages - perhaps start at Melksham where we're based, or Salisbury or Ludgershallor Swindon. And if you want to come and see more, why not stay with us

Posted by gje at 11:05 AM | Comments (0)


Related topics: via article database

String duplication - x in Perl, * in Python and Ruby

In Python and Ruby you can duplicate a string by running the multiply operator (*) on a string object, and in perl you can use the x operator. There have been many times when I've looked at this facility and said to myself "very nice, but isn't that a feature looking for a benefit" - in other words, something that's nice but not much use. Well ... there's always a few cases to disprove such a theory:

s/^(\s+)/"&nbsp;" x length($1)/e;

That's Perl - replace all leading spaces on a line with the same number of leading &nbsp; sequences.

Posted by gje at 02:21 AM | Comments (0)


Related topics: via article database

Useful links: Python training, Ruby training, Perl training

Perl - $_ and @_

Perl's a great language for special variables - variables that are set up without the programmer having to intervene and providing information ranging from the number of lines read from the current input file ($.) through the current process ID ($$) and the operating system ($^O). Other special variables effect how certain operations are performed ($| controlling output buffering / flushing, for example), or are fundamental in the operation of certain facilities - no more so than $_ and @_.

Lets clear a misconception. $_ and @_ are different variables. In Perl, you can have a list and a scalar of the same name, and they refer to unrelated pieces of memory.

$_ is known as the "default input and pattern matching space". In other words, if you read in from a file handle at the top of a while loop, or run a foreach loop and don't name a loop variable, $_ is set up for you. Then any regular expression matches, chops (and lcs and many more) without a parameter, and even prints assume you want to work on $_. Thus:
while ($line = <FH>) {
  if ($line =~ /Perl/) {
    print FHO $line;
    }
  print uc $line;
  }

Shortens to:
while (<FH>) {
  /Perl/ and
    print FHO ;
  print uc;
  }

@_ is the list of incoming parameters to a sub. So if you write a sub, you refer to the first parameter in it as $_[0], the second parameter as $_[1] and so on. And you can refer to $#_ as the index number of the last parameter:
sub demo {
  print "Called with ",$#_+1," params\n";
  print "First param was $_[0]\n";

Note that the English module adds in the ability to refer to the special variables by other longer, but easier to remember, names such as @ARG for @_ and $PID for $$. But use English; can have a detrimental performance effect if you're matching regular expressions against long incoming strings.

Posted by gje at 01:59 AM | Comments (0)


Related topics: via article database

Useful link: Perl training

December 06, 2006

Perl - a list or a hash?

You can hold multiple scalars in either a list or a hash in Perl. A list (signaled by an @ character or [..] around the subscript) is ordered - i.e. the elements are numbered and the order is significant. In contrast, a hash (signalled by a % character or {..} around the subscript) is unordered; the elements are named and the order isn't easily predicted.

Why would anyone want to use a hash if it's not in order? Well - if you want to look things up based on a key it's very easy and very efficient. And if you've keyed data and use lists, it's quite awkward to write the code to keep them in step. Here's an example:

# Using a list - works but bulky

@onco = ("Nathan","Steve","Andrew");
@from = ("London","Romford","Cardiff");

print "Where is ... from ? ";
chop ($name = <STDIN>);

for ($k=0; $k<@onco; $k++) {
  if ($onco[$k] eq $name) {
    print "$name is from $from[$k]\n";
  }
}

# Using a hash - an unordered collection

%pep_tab = ("Nathan" => "Brighton",
  "Steve" => "Walthamstow",
  "Andrew" => "London");

print "Where is ... from ? ";
chop ($name = <STDIN>);

print "$name was from $pep_tab{$name}\n";

It turns out that hashes have many, many other uses too - their very quick look up algorithm is great for anything from checking for a word in a dictionary through to analysing all the client computers registed in your web access log.

Posted by gje at 06:02 PM | Comments (0)


Related topics: via article database

Useful link: Perl training

December 05, 2006

Realistic on line shoot'em up

I understand that there's a new online shoot'em application available. You can raise and lower your gun, aim, file, pull the trigger and kill wildlife during a walk in the woods, all without leaving your living room.

It all seems very realistic and that's not a surprise because it IS real. With the use of a robot and a webcam, it's possible to shoot squirrel in the forest. The bang you hear isn't simulated, it's the gun going off. The blood splattered corpse is real ...

I don't know about you, but I was shocked when I first heard this story; whether it's true or a myth I'm not sure, and I don't know if I want to know. Why on earth would anyone put this application together? Apparently, it's all to do with the equality laws, and the need to provide the same opportunities and experiences for disabled people who can't go out hunting as for able bodied people who can. So I guess that someone considers that makes it all right ...

Posted by gje at 02:24 PM | Comments (0)


Related topics: via article database

CSL, KISS and RTFM

Mary was engrossed in her conversation with her workmates last night. Lisa and I nipped into a near-empty (apart from 8 staff) McDonalds and walked up to the counter and stood there for what felt like an age. I'm guessing that they've got some form of inspection today as the frenetic activity going on was washing, scrubbing and cleaning and not a burger to be seen. Cleaning schedules lay on the counter, the hot apple pie machine looked like it was off ...

Eventually (it seemed), Mary mouched over to the till and asked if she could help us. She was duplexing a little as she spoke to us - some conversation or other about another customer going on with one of her colleagues as she punched our order in, but will did get a cheerful if slightly scruffy half smile that made us feel less like outsiders, and she did notice (once we had paid and she had served our drinks) that the burgers weren't ready and offered to bring them over to us when they were cooked.

Mary's not a bad kid, and I think her heart's probably in the right place, but she lacks guidance; perhaps it's just changing times, or perhaps it's the fact that the local McDonalds is now a franchise where customer service isn't top priority ... but it has got really slack in there. We automatically stepped around the ketchup puddles on the floor and scanned around for one of the cleaner tables. "CSL" says I to Lisa who takes the puzzle I've just set, and whispers "Customer Service Lacking??". Yes, that's good - better than the "Customer Service Lessons" I had originally thought.

"KISS" - Keep it simple, Stupid. See back to the previous post, where I mentioned this one. Better to write simpler but more maintainable code that something that's so clever / short that no-one can understand how it works when it needs fixing or updating

"RTFM" - Read the Manual. I probably shouldn't quote this one, beloved of techincal support teams when they answer a question the feel is obvious for the 10th time in an hour, or when they feel that they're a human book-reader with the job of translating words written in a manual the customer already owns into voice waves over the phone. Frankly, I've a great deal of sympathy for customers who ask and I encourage it ... and a repeated question from many sources may indicate something that's hard to understand or is hidden information when it should be easily at hand. And - heck - ask me. I always enjoy a chat and helping!

Posted by gje at 05:50 AM | Comments (0)


Related topics: via article database

KISS - one action per statement please - Perl

"Nice program, Bill - but the output is a bit verbose. Can you take out some print statements". So said one of my delegates' bosses this week, late in the day just before a new application went live. Alas ... the application fell over just because the print had been removed.

In Perl - that was the language in use - you can assign variables within your print statement, and that's what had been done. So taking out the print caused it to fall over. What you can do and what you should do are two different things, and it requires a thoughtful programmer and an excellent manager to the make the best of coding, apply standards and end up with a maintainable program that fits the user's requirement well.

Sample code - what NOT to write:
foreach $value (1..5) {
  print ("... ");
  print ("Value is now ",$sum+=$value,"\n");
  }
print ("Triangle 5 is $sum\n");

Without the print it becomes:
foreach $value (1..5) {
  print ("... ");
  }
print ("Triangle 5 is $sum\n");

When those are run:
grahamellis$ perl avoidthis
... Value is now 1
... Value is now 3
... Value is now 6
... Value is now 10
... Value is now 15
Triangle 5 is 15
grahamellis$ perl liketheplague
... ... ... ... ... Triangle 5 is
grahamellis$

Does this just apply to print statements? No - anywhere you're undertaking two actions in a single statement is liable to come back an bite you late on.

Don't write $r = $p++; as it changes two variables - much clearer to write $r = $p; $p++;.

Don't use printf. PLEASE. As it both formats and prints. Use instead sprintf and then do a separate print. That way, you have the later flexibility to apply further string manipulation - for example if data originally destined for a command window is now to be output to a browser.

You should not write:
printf ("< %.2f",$maxprice);

But rather:
$poundamount = sprintf ("< %.2f",$maxprice);
print $poundamount;

Because you can enhance the latter as follows:
$poundamount = sprintf ("< %.2f",$maxprice);
$poundamount =~ s/</&lt;/g;
print $poundamount;

We (or rather "I" - I'll take the blame) made the mistake on a previous version of the Well House Consultants web site too - in HTML. The image on the left is 132 pixels wide, and I wanted an 8 pixel space to the right of it. What easier than to add the 8 white pixels to the images? So that's what I did and built up quite an image library ... to find my self well and truely in trouble when we wanted to add the ability to change background colour for users. We ended up, temporarily, with a dirty looking white band to the right of every image and it was only fixed by a rather messy procedure to - guess what - replace the single image with two functions with two images each with a single function.

Are you familiar with KISS (post title) ... if not, see next post!

Posted by gje at 05:25 AM | Comments (0)


Related topics: via article database

Useful link: Perl training

December 04, 2006

Practical polymorphism in action

Polymorphism is the ability of a piece of common code to process a piece of data in different ways depending on its type. It's a great facility, talked about a lot in theory and on courses ... but then what about its practical use? Here's a very simple little example from last week, showing how a file, another process on the computer you're using, and even a remote web page can be read in as data through the same (polymorphic) code with python's readlines method(s).

# Three ALTERNATIVE opens - just use the one you need
# from another process
from os import *
fh = popen("df -k")

# from a remote URL
import urllib
fh = urllib.urlopen("http://www.sheepbingo.co.uk")

# from a local file ...
fh = open("localfile.txt")

# ... whichever way you open your STREAM, you can readlines it!
for info in fh.readlines():
  print info,

Posted by gje at 08:00 AM | Comments (0)


Related topics: via article database

George Hotel and Well House Manor, Melksham

The George Hotel, Melksham, stood on the corner or Lowborne and Bath Road - prime real estate in the town centre; alas, it was demolished around 60 years ago to make way for a modern (then) parade of shops which now are showing their age and considered to something of an eyesore in many of our Vistas. Wouldn't it have been wonderful to have retained something like "The George" or "The Ship" in Mere or "The Antrobus Arms" in Amesbury.

But times move on, and tastes and requirements change. I can tell you of other hotels that Melksham has lost - places like the Regency Hotel - in very recent years. Certainly from our perspective, the Regency wasn't able to offer the services our customers wished to find, and I understand it found a new use away from the hotel trade. These days, good parking, internet access, all rooms en-suite, updated fire precautions and payment by credit card are "de rigour" - vital - at least for the sort of business folks who come on our courses. And they want online access to the hotel.

I look at our own Well House Manor and I go yes, yes, yes. Yes, yes, yes. And - by design - not quite yet! We've been open for 6 weeks and we're 'running in'; the online booking system is to come over Christmas. However, over the weekend Lisa has been working on the web site for "The Manor" and - well - I'll leave you to judge the results but let's just say I'm proud.

Posted by gje at 07:37 AM | Comments (0)


Related topics: via article database

December 03, 2006

Breaking a loop - Ruby and other languages

When you're in a loop there are occasions you want to say get me our of this loop NOW, or "I'm done with the current iteration. And those are the 'classic' break and continue statements from C, C++ and Java. Languages like Perl changed break to last and continue to next ... and added a redo that asks for the current iteration to be rurun.

With me so far?

Now in Ruby ... you have break, you have next, you have redo and you also have retry ... which reenters the top of the loop. Wow - perhaps I had better provide an example?

for i in 1..5
print "How many do you need on day #{i}? "
nneed = gets.chomp.to_i

# next - don't order nothing; move on to next case
next if nneed == 0

# retry - whole thing to be redone on a 999 code
retry if [112,911,999].include?(nneed)

# redo - more than 10 ordered - must be a mistake
if nneed > 10 then print "Too many!\n"; redo; end

# break - code "-1" entered to exit on a short week
break if nneed == -1

print "We'll get #{nneed} on order for day #{i}\n"
end

By the way - if you've not seen much Ruby before, have a look through that example and taste a few of the constructs. It's really neat, and I expect I'll be writing a lot more about it in the future. ;-)

New technical articles on Ruby:
How classes are defined and used
Ruby's Control statements
String functions in Ruby
Ruby Regular Expressions
Modules, Mixins and Comparators

Posted by gje at 06:30 PM | Comments (0)


Related topics: via article database

Useful link: Ruby training

Products that our customers want more of

Perhaps the ultimate "rave review" for some of our new facilities and offerings is the customer who asks for details of our supplier so that he too can get in touch with them about their product for his personal use, or the customer who comes to us on business and returns just for the pleasure.

I'm delighted today, then, to post pictures of some of our supplier's products at Well House Manor, and of our own services that customers are rushing to rebook with alacrity.


Cakes from The Wicked Cake Company


Window Shutters by The California Shutter & Blind Co


Hotel accommodation at Well House Manor, Melksham, Wilts


Private Open Source courses from Well House Consultants

Posted by gje at 04:47 AM | Comments (0)


Related topics: via article database

December 02, 2006

1st, 2nd, 3rd revisited in Ruby

I've been updating some of my Ruby examples today (as one does on a Saturday!) and I thought back to the post I made yesteday concerning 1st, 2nd, 3rd, etc in Python.

Ruby has a case statement, even though Ruby is a bit of a cross between Python and Perl, neither of which supports the structure. Historically, it's been difficult for language authors to come up with a really good multiple way switch but actually the Ruby one is rather smart. Compare this Ruby to the Python code I wrote yesterday:

case value
when 1,21,31
  suffix = "st"
when 2,22
  suffix = "nd"
when 3,23
  suffix = "rd"
else
  suffix = "th"
end

puts "It is the #{value}#{suffix} of the month"

Oh - I'm revising this for the public Ruby course that's running on 14th and 15th December ... places still available at £550.00 (first delegate) and £440.00 (second and subsequent delegate on same running of the course / same order. Maximum of 7 delegates taken, and just 3 rooms available as I write, Hurry hurry hurry!!

Posted by gje at 05:15 PM | Comments (0)


Related topics: via article database

Useful link: Ruby training

December 01, 2006

It's the 1st, not the 1nd 1rd or 1th.

Here's a function in Python that takes the day number in the month (in the range 1 to 31 ...) and returns "st","nd","rd" or "th" as appropriate

somehow(val):
  "Somehow, your time will come"
  ding = (["st","nd","rd"]+["th"]*7)[(val-1) % 10]
  if val/10 == 1: ding = "th"
  return ding

You'll have noted there have been a lot of Python posts here this week .... I'm concluding my second "Programming Python" course of the week today. Next week, it's Perl ... now I wonder what will turn up on the blog!

And with the coming of December, Santa is starting to get into place. He's booked for visits to Melksham on 2nd, 9th and (I understand) the night of 24th. I snapped this festive picture the other day ... and I expect I'll be using it in the new year when I do my "ladder" example on the PHP course - perhaps Santa will end up taking over from Romeo and Juliet in my introductions!

Posted by gje at 07:53 AM | Comments (0)


Related topics: via article database