« August 2009 | Main | October 2009 »
September 30, 2009
Moving busstop!
It can't have been more that a year ago that a new bus stop was provided for us at "The Spa" ... or rather a new bus shelter and some nice, slip proof kerbstones; the bus stop had been there when we moved to Melksham in 1999 and probably for many years prior to that.
Imagine my surprise, then, to find that our lovely new bus stop is marked up with yellow paint for removal from its current location to a new spot 20 yards or so up the road, to make way - it would appear - for a new pedestrian crossing. It's all a part of the Melksham Oak Community School works as it's on the main pedestrian drag out there, and a wider crossing is wise. But you would have thought that a bit more joined up thinking would have been involved rather than put it in, tear it out, put it in again elsewhere. I wonder if this is at taxpayer's expense, or at the expense of bus passengers.
Posted by gje at 06:19 PM | Comments (0)
Related topics: via article database
More about Graham Ellis of Well House Consultants
September 29, 2009
Not just a PHP program - a good web application
A very busy week so far ... station pickups, a PHP course, hosting an external luncheon meeting and hotel guests at Well House Manor, and providing a venue for, and attending, a meeting of the presidents of some of the local chambers of commerce to discuss towns working together. And it's only just the end on Tuesday. Wednesday will bring ... well, you'll read some of it here.
On Monday, I "tunnelled" through PHP, producing a piece of code that worked for a benign user who put in sensible data. It coughed slightly with 'silly' values - it was obvious it had failed, and it looked really crappy - but it wasn't actually an injection attack risk. ("No - It's not nice - I will NOT publish it here"). And on Tuesday morning, I took that code and I said DESIGN MATTERS - for the user, and for the maintenance programmer ... and I came up with the following list which I chose to implement to a lesser or greater extent - at least to an illustrative degree:
1. Code should be commented for programmer
2. Page should include instructions for the user
3. Forms should include a submit button, even if they only have a single input box which submits on "enter"
4. Code should echo user inputs
5. First page should not perform submission actions on nothing
6. Fields should usually be sticky
7. Data should be validated
8. Data should be secure against injection attacks
9. Common code should be grouped into functions
10. Generated HTML should conform to selected standard (XHTML?)
11. Program and design elements should be separated
12. Error messages should be good 'uns
You see - it's not JUST about making the algorithms accessible and workable - it's much MUCH more. Come to think of it ... as I write this note, I see that there are a few more things I should have done / documented. Some have been done already - second nature - others aren't actually present in my demo.
13. Help window
14. Search Engine Optimisation
15. Make it interesting
16. Should look good and be corporate branded!
17. Should provide support contact
18. Should provide links back to the calling ap / rest of site
Have a look at the running application. Have a look at the source code. See if you can work out which of those extras I have done something towards, and which are on my potential "to do" list.
There's a huge difference between a PHP script and a good web based application!
Posted by gje at 11:46 PM | Comments (0)
Related topics: via article database
Useful link: PHP training
September 27, 2009
Tcl scripts / processes on a web server via CGI
If you have programs / scripts / processes written in Tcl, you can run them on your web server via the Common gateway Interface, possibly with a bit of topping and tailing to read data from a form rather than via gets commands, and to ensure that the output does get the right headers attached to it and is 'proofed' against nasty injection attacks.
In response to a query received on this subject, I've installed Tcl on our live server today so that you can run a script to try it out. The source code of the web page that you'll need to fill in is here and that submits via CGI to a Tcl script source here. You can run the demonstration here.
There's a second Tcl / CGI / web demonstration here ... that link will take you to the source code, and when you've seen what it does you can run it.
We briefly mention using Tcl on a web server on our Tcl Programming Course. I won't pretend it's a major part of the public course - it isn't - but if the subject is important to you, plan to stick around on the last day and I'll cover some more CGI stuff with you. Private courses are tailored ... and I can spend a lot longer on CGI on those courses if you wish.
Posted by gje at 04:08 PM | Comments (0)
Related topics: via article database
Useful link: Tcl training
Diluting History
Our web site keeps a dynamic log of accesses to our main URLs, together with key words and phrases associated with the URLs. It's a lot more than a web access log, as images such as this one
are indexed under "Fish Pass Chippenham" as that's the "alt" tag that's associated with the image on some of our pages, and on most of the 'html' pages the indexing text excludes the page decoration but includes the content. And each time a URL is visited by a 'live' user, we count that access to keep tabs on what's popular, and we also do so by training course module. Again, it's much more than just the web server logs.
Why do we do all this work?
Firstly and foremost, so that we can provide a sitemap to the search engines in which we can weight the relative importance of our pages for them, based on the section of the web site the pages are in, the number of times they're accessed, their age and other factors of our choosing.
Secondly, so that we can provide additional search facilities on our site - this is currently in a test form, but if you follow this link you'll see the way we can list resources on our site that reference "Lacock" ... starting with what we consider to be our most important pages (not necessarily the most important pages for that term, though!)
Thirdly, so that we can highlight top resources for a particular module on that module page. We're using a look and feel that should be familiar to anyone who looks theough search engine results (that's nearly everyone, right?):
Python Programming - The fundamentals in depth, and an introduction to applications such as GUI design and Data Munging.
This course starts at the fundamentals ... http://www.wellho.net/course/ypfull.html [course] |
Learning to Program in Python - The fundamentals in depth, and an introduction to applications such as GUI design and Data Munging.
This course starts ... http://www.wellho.net/course/ylfull.html [course] |
In all object oriented languages, you have a facility called inheritance where you can define one type of thing ("class of object") based on another, ... http://www.wellho.net/mouth/1819_Cal ... ctors.html [short article] |
In (Object Oriented) programming terms, Inheritance is used to define a type of data (an object ) which behaves like another type of data with some ... http://www.wellho.net/solutions/python-i ... tance.html [longer article] |
The constructor you'll normally override (and call when you create an object) in Python is called __init__, but there is also a method called __new__ ... http://www.wellho.net/mouth/1146_-ne ... ives-.html [short article] |
Do you find some of the OO terminolgy baffling? Once you've learnt about constructors and methods, inheritance, overloading and polymorphism and statics, ... http://www.wellho.net/mouth/1217_Wha ... sses-.html [short article] |
I started the counters some 9 months ago ... and we've been steadily counting page visits since that time. But there's something of a problem there; it means that pages that were called up heavily six months ago now have an undue weight, and that up and coming new pages are taking a long time to be decently rated on the prime mover for this work - which is our sitemap. It's rather like they started in the air, then they got put into water and became more sluggish in their reaction. Then cooking oil, then treacle and eventually tar. So what was originally a responsive and positive system was becoming quite the reverse - a hinderance.
The solution - an interim solution that I'll be applying every month or two - is to dilute the access counters. Add more water to the mix, make the tar far more 'runny' for a while. Yes, it will thicken up again over coming weeks, but at least the current sitemap.xml file has changed very little right away, but it will adjust far quicker over the coming week. And to dilute the access counters ... a simple SQL line:
mysql> update cn_content set nstores = 1 + nstores/10;
Basically, dividing all the accesses to a tenth of their previous significance, but ensuring that none of them is allowed to fall off the scale to a "zero". I do have a copy of my 'before' and 'after' sitemaps; the factors have changed straight away, but not greatly so. The history remains, all be it in a diluted form, and that's exactly what's needed for a dynamic site such as ours.
Posted by gje at 09:26 AM | Comments (0)
Related topics: via article database
Operator overloading - redefining addition and other Perl tricks
What does addition actually mean? It means different things depending on what you're adding together, and in Perl you can redefine additions - and other operators - on objects of types which you define. This is known as operator overloading, and there's a complete code example here.
So ... how do you do it? Within your class, call up the overload program to redirect the operator that you're overloading to a sub of your choice. And provide that sub - with two parameters passed in through @_ for the two objects being added. Within the sub you should check that you really do have objects (my example is kept simple and does not have this check) and if you do, construct a new object that's a combination of the inputs.
I've chosen - for my example - to stack boxes which have an "x" and a "y" dimension; the new combined box when you add two of them together has an "x" which is the sum of the two "x"es, and a "y" which is the greater of the two "y"s.
Operators can be overloaded in Python too (example) and in C++ (example), but not in PHP, which is a loosely typed language.
Illustation ... I might look for a clever title like "adding pieces to a jigsaw puzzle" ... but actually these are delegates on a private Perl course at our training centre and hotel, relaxing during the evening in the old fashioned way by doing a jigsaw. Our courses provide not only the lectures and practical sessions, but also a chance to get to know your colleagues better, and to exchange ideas with other delegates learning the same subject.
Posted by gje at 12:45 AM | Comments (0)
Related topics: via article database
Useful link: Perl training
September 26, 2009
Which version of MySQL am I running?
Oh be careful - that is a VERY dangerous question. Do you mean "what version is my MySQL server" or "what version of the mysql client program am I running?" I'll show you how to find answers to both questions.
What version is my MySQL server?
Use the select command, and run the version function within it:
mysql> select version();
+-------------+
| version() |
+-------------+
| 5.0.51a-log |
+-------------+
1 row in set (0.02 sec)
Your MySQL server is the program that's know as mysqldand is run as a daemon (linux / unix term) or service (Windows term). It may be run directly, or instigated via a scripts such as mysqld_safe or safe_mysqld
What version of the mysql client am I running?
Simply run the mysql client with the -V (that's a capital V) option:
-bash-3.2$ mysql -V
mysql Ver 14.12 Distrib 5.0.45,
for redhat-linux-gnu (i386) using readline 5.0
-bash-3.2$
The mysql client program is a small utility that lets you type in SQL commands at the keyboard and have them routed to the mysql server, and then handles and displays the results. It's ironic that the program that bears the name of the product (mysql) is such a tiny part of the whole!
Posted by gje at 08:59 PM | Comments (0)
Related topics: via article database
Useful link: MySQL training
Weekend and Christmas Promotion - Well House Manor Hotel, Melksham
We've been busy at weekends at Well House Manor this summer - a notable increase in business, and this weekend we have returning guests once again, which is always a good sign. But we're conscious that, as autumn comes, fewer people will be coming to the area for holidays and weddings and we should be shouting loud and long about some of the fantastic things that are going on that make us a year round destination. And to encourage you to come and stay, we're offering a Winter and Christmas special - stay for two or more nights including a night outside the working week and we'll offer you - well - here's the Special Deal Link!
So what things ARE going on?
The bus right outside Well House Manor takes you into Bath (don't bother with the Park and Ride - use US as the Park and Ride!). There's the Bath Christmas Market - this year from 26th November to 6th December inclusive - with a wide variety of stalls from presents to food and drink, all in the grounds of Bath Abbey.
Also in Bath, why not go and watch Bath Rugby? The ground is just across the river from the City Centre - so you can watch a fixture, shop, do some sightseeing ... stop for a meal and drink afterwards, and come back on the mid evening or the late bus!
Right through December, Melksham's Christmas lights are perhaps one of the best display's you'll see anywhere - and that's less than half a mile from Well House Manor.
Father Christmas comes to Melksham too - this December, I understand he'll be in the town on Sunday, 6th December - travelling on the 17:15 train to Swindon and returning for 19:00. If you've got grandchildren in Melksham, why not stay with us that weekend and take them for a treat - to meet Santa - on Sunday evening?
Salisbury, Bath, Devizes, Lacock. Marlborough, Malmesbury and Melksham itself. Stonehenge and Avebury. There's plenty so see at each of these places - you'll find they're rewarding out of season - a chance to wander alone through the stones at Avebury, to eat in the "Red Lion" in Lacock when the friendly local atmosphere has come back, to visit the Abbey in Bath and the Cathedral in Salisbury.
We've got just five rooms - "probably the best hotel rooms in Melksham" according to some of our regulars - and we look forward to welcoming you this winter, whether you're here for one of the special events we've listed above, or for your own special break. Book online here (enter the coupon code "Weekend") if you'll be with us for two nights over a weekend or Christmas and want the special rate!), see our hotel web site here, or call us on 01225 709638 or 0800 043 8225, or email info@wellho.net.
Final picture - breakfast at Well House Manor
Posted by gje at 01:33 PM | Comments (0)
Related topics: via article database
A Winter Weekend Special at Well House Manor
Keywords ... Hotel ... Melksham ... Wiltshire ... Weekend Break ... Christmas ... Visiting Bath ... En-suite ... Luxury Rooms
Stay with us for 2 or more nights (including a Friday or Saturday night) from October to February, or for any 2 or more nights over Christmas and the New Year (23rd December to 3rd January period) at the special rate of 70 pounds, per room, per night ... including our continental breakfast, 50 channel TV, internet access, unlimited soft drinks / teas / coffees. All of our rooms are double or twin bedded, and let for single or double adult occupancy; we're an ideal base if you're visiting friends or relatives in Melksham, or taking a weekend away and seeing Bath, Lacock, Caen Hill or many of the other attractions and historic places around.
Regular rates - £90.00 per room (double occupancy), £80.00 per room (single occupancy), per night, including our continental breakfast: Freshly squeezed orange and grapefruit juice. Cereals, yoghurts, actimel, fresh fruit. Brown and white bread and toast, croissants, rolls and mini-danish. Hams, other meats and cheeses. Butter, marmalade, marmite, honey and jams. Teas and freshly ground coffees (Americano, Espresso, Cappuccino, etc).
We are five minutes walk from Melksham Town Centre. We have plenty of parking, or if you prefer to use public transport the bus stops right outside (services 272 and 273 to / from Bath and Devizes). Keycards give you access to the hotel and your room at any time through your stay. Checkin from 3 p.m. to 10 p.m, but if you let up know ahead of time you arrive earlier or later. Evening meals may be ordered for delivery from local 'takeaways' - Indian, Chinese, Kebabs, Pizza and Fried Chicken can all be delivered, and there's a wide variety of other takeaways in the town too. You're welcome to eat your food in our restaurant or in your room ... and we provide bottle openers, corkscrew, glasses. We are not licensed, but you're welcome to bring in your own alcohol ... from the off license that's just two doors up the road from us, or from elsewhere.
Well House Manor web site - www.wellhousemanor.co.uk. Secure online booking here (enter special code "Weekend" to show the special rate). Further information - email me or call us on 01225 709638 or 0800 043 8225
If you have found this through our technical blog ... YES - hotel guests do have access to our library of 700 open source books, and you're welcome to ask the staff your Internet programming questions - they'll know the answer, or know who to ask!
Posted by gje at 12:42 PM | Comments (0)
Related topics: via article database
What is a JVM, a JRE, a JDK - components of the core Java Environment
Your Java class files run on a JVM - a "Java Virtual Machine" which is a program that reads the instructions in the (binary) class file and performs them. Although the class files are "architecture independent" - in other words, the same class file will work on an Intel and a PowerPC chip, and on Linux, Unix and Windows, the JVM is NOT portable in this way and you must have the right one for your system.
The JVM is the running "engine" of Java, but just as most of us don't just buy an engine, we buy a complete car ... so it is with Java. Most of us need a JRE - a "Java Runtime Environment" which is a JVM plus all the standard classes which are needed to support our own piece of code. Even in a simple read / calculate / report program, you'll need to load in other standard classes to do jobs like handle command line data, convert a String of characters into a number, and produce output to the current window. All of those standard methods are in the JRE.
Most users of Java programs will simply be running classes through a JVM with the support of a JRE, but the developers of Java programs will also need a way to turn the programs they write, in the "English-like" Java language stored in text files which can be edited easily - into those binary class files which run very mcuh quicker that a language that runs straight from the text (a 'truely interpretive language') but are impractical to edit. And those developers need not only the JVM and the supporting JRE, but also a JDK - that's a "Java Development kit" which amongst other things includes the java compiler program (javac) to convert english-like source into quickly-run binary.
Notes...
1. "JSP"s - which are Java Server Pages, run on a web server, include Java source code within the web page. This means that if you're running JSPs on your web server, even if you're not developing any code / pages yourself, you will need the full JDK loaded ... onto not only your test and development servers, but also your production server!
2. You'll very often compile your Java code on a different computer to the one it's finally going to run on - your programmer's computer is really the one that you should be creating / maintaining programs on, and that should NOT be your live server. However, you must have a complete set of all the classes that your Java code calls up when it runs on your development machine - not only is that sensible because it lets you test your code (ALWAYS test even the smallest of changes - that advise comes from experience!) but also Java insists as it won't let you compile something if the classes that the compiled code relies on aren't available for it to check your code 'against'.
JINI, JMX, JXTA, JAXB, JAXP, JAXR, SAAJ, JAX-RPC, JNI, JAXM ... are all extra technologies that you may wish to use in addition to your 'core Java'. Most of the ones I have listed are additional bundles of class files (known as "packages") which provide extra functionality for Java without the developer having to write it himself. They're accessed via method calls through their API (Application Programmer Interfaces) and to make good use of them, you need to (a) load them, (b) read the documentation / look at the samples and (c) understand something about what they actually do.
The AWT, Swing, and many other elements are also extra technologies, but these particular examples are classes / packages that are bundled with the JRE distribution, so there's no need (in these cases) to download and install them separately.
Posted by gje at 07:17 AM | Comments (0)
Related topics: via article database
Useful link: Java training
September 25, 2009
Looking inside Java classes - javap and javadoc
javap is a program that looks inside a Java class and reports on all the methods and variables that are exposed by that class ... so it's looking at a Java class's object format.
javadoc is a program that analyses Java source code and reports on all the methods that are exposed by that class.
javap is command line based, but javadoc produces a whole web site in HTML format ... here's the javap output from our "Time" class from this week:
Dorothy-2:java grahamellis$ javap Time
Compiled from "Time.java"
public class Time extends java.lang.Object{
public int hour;
public int minute;
public int second;
public static int howmany;
public Time(int, int, int);
public Time(int, int);
public int getsid();
public int gethour();
public void setforward(int);
public java.lang.String getdef();
public int getgap(Time);
public static int getcount();
static {};
}
And here's part of the javadoc output from the same class:
Explore the full javadoc tree from this week if you wish. It's in HTML, using frames (so I can't easily provide you with a link to the intermediate pages without doctoring files and URLs!) but it WILL take you all the way from Adam to Zoe!
Posted by gje at 04:09 PM | Comments (0)
Related topics: via article database
Useful link: Java training
Sorting Collections of Objects in Java
The examples that I wrote / finished yesterday ended up with a program called "Zoe" in Java, which read all the records in an access log file, created an object for each of them (which, sensibly would have been called a Hit but we called a "Zoe"), and reported on that object creation.
To finish off that example this morning, I sorted the objects (and I chose to do so based on the web server returned status codes, and where they were the same, the visiting host name), and printed them out. Th efollowing changes were made to the source code:
1. Set the class to implement "Comparable" which means that we have added a compareTo method which returns an integer (-ve, 0, +ve)
2. Called Collections.Sort on the ArrayList object (Collections.Sort is a static method of the Collection object type in java.util)
3. Provided a toString method so that we can easily display an Aileen (that's the new name of the class that I used as I wanted to leave Zoe available for delegates to look back at the intermediate stage) object.
4. Looped through our ArrayList after sorting in to output all the members in it.
In code terms:
public class Aileen implements Comparable {
Within the main program / test harness:
Collections.sort(Visits);
for (int k=0; k<Visits.size(); k++) {
System.out.println(Visits.get(k));
}
And new methods within the class:
public int compareTo(Object that) {
// Can we differentiate by status?
int newstate = this.status - ((Aileen)that).status;
if (newstate != 0) return newstate;
// If we can't, differentiate on host name
return (this.Host.compareTo(((Aileen)that).Host));
}
public String toString() {
String rezult = Host + " " + /* Request + " " + */
Time + " " + status;
return rezult;
}
You can sorted other ordered collection types in Java using the same mechanism, but you cannot sort any of the Hash types (Hash, HashMap, HashSet) - if you want their members in order, copy the keys to a Vector or an ArrayList.
You can also provide a Comparator object as a parameter to your call to Collections.Sort; be default, objects are sorted into what is know as their natural sort order by reference to the compareTo method, but if you provide Comparators you can have different ways of sorting them.
Full source code here.
Posted by gje at 02:21 PM | Comments (0)
Related topics: via article database
Useful link: Java training
September 24, 2009
Exceptions in Java - why and how
Although it's common practise to include a static main test program in a class, it's something that newcomers can have some difficulty following ... so we don't do it too early on the course - we keep classes and programs that use those classes (even if they are just test programs) each in their own classes and file. But today - the fourth day of Learning to Program in Java, we started to load the test harness into the class. The first example was in the program we called "Wendy" which also showed how base classes inherit from the Universal superclass, and how methods like toString can be overridden to allow objects to be easily printed.
Here are the four (quite major!) extra examples I wrote today:
| Wendy.java | Test program within a class |
| Xena.java | Example with and without exception handling |
| Yvonne.java | Directory listing, file i/o and formatting demo |
| Zoe.java | StringTokeniszer, ArrayList and Exception demonstration |
Exceptions are a vital part of Java, and although we have a complete module on them in our training notes, I see I've only ever skirted around the subject on my Blog .... so here's a bit more.
Principle of exceptions
When you run a piece of code, it may or may not do what you want / come up with the sort of result you were looking for. In many older languages, you had to check a return status from each function call to see if it really had worked, or look for some 'cardinal' or special value that was returned - which made for messy code - not quite spaghetti, but certainly Pasta ;-).
Exceptions take out the need for checking every single action for a status - you can group together a whole series of operations and say "Try this" ... with the code jumping to a block that processes any error - a "catch" block - which mops up any problems.
You can also throw exceptions yourself - if you're writing a function that analyses an Apache log file line and creates an object from it BUT the line of data isn't actually a valid log file line, for example, you can throw an exception. And if you're running a function who's role it is to return the number of children that Jerry has, but you don't know, you can raise and throw an exception rather than passing back an impossible integer value that the calling program has to check for.
Excpetions can be handled by the function in which they occur, or can be passed back to the calling code. This is rather like having a child that's got a problem (needs the loo). You can either let the child sort the problem out itself, or have it pull on the coattails of the calling function - "Mum - I need to GO!!!". Of course, if Mum is busy she can then pass on the problem to Granny ...
Exceptions in Java
Here's a simple piece of code that takes 4 command line arguments - two names and two ages - and tells people how much longer they must work:
for (int k=0; k<4; k+=2) {
int retire = 65 - Integer.parseInt(args[k+1]);
System.out.println(args[k] + " can retire in "
+retire+" years"); }
It works well enough if you put sensible values in:
Dorothy-2:java grahamellis$ java Xena Bob 23 Roberta 26
Bob can retire in 42 years
Roberta can retire in 39 years
Dorothy-2:java grahamellis$
but put in too few values, or fail to have numbers as the 2nd or 4th parameters, and it generates some serious errors. Here's the same code, rewritten to catch the possible exceptions and act on what it has caught:
for (int k=0; k<4; k+=2) {
retire = 999;
try {
retire = 65 - Integer.parseInt(args[k+1]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("I've run out of data");
break;
} catch (NumberFormatException anything) {
System.out.println("Wanted no.; got str\n" +
anything);
retire = 50; // Assume whole working life!
} catch (Exception e) {
System.out.println("Summat else failed");
break;
}
System.out.println(args[k] +
" can retire in "+retire+" years");
}
You'll note that we have chosen to catch some specific types of exception first, but then the more general "Exception" as a safety net. If we run out of arguments on the command line, we break out of the for loop as there's no point in going on to generate more error messages, but if we simply have a problem getting a number out of a field, we do carry on to trying out later fields. It's amazing just how much care is needed even in exception handling - the blocking is every bit as important as the block structure of while and if.
The full source of the example above, together with some output samples in both its original (unchecked) and properly checked forms, is here.
Posted by gje at 05:34 PM | Comments (0)
Related topics: via article database
Useful link: Java training
Where is my Java class?
Exception in thread "main" java.lang.NoClassDefFoundError: Gerald
OK - so where did Java look, and where should it have looked?
Java looks for classes in each of the locations in the CLASSPATH environment variable in turn - each of those locations being either a directory or a .jar file which contains a directory structure.
Within Java classes, import statements may be added which will have Java look in those extra locations relative to each member of the CLASSPATH. Take a look at this diagram:

With three elements on the CLASSPATH, and four imports in a class, further classes will be loaded from 3 * (4 + 1) = 15 different places [Don't forget that there's always an implicit import *; to load from current package!]. It's little wonder, then, that if you get your CLASSPATH and imports wrong that you'll be left asking "where did it load THAT form" or "why couldn't it find THAT?"
There's a further layer - as shown in the diagram - that classes and class members may be generally visible (i.e. public)or they may also be restricted - to protected, to package (the default and never stated) or private ... so that another reason that your class can't be loaded can be that it's there ... but the JVM's not allowed to use it.
While we're on packages and classes:

In essence, a "package" is a directory of code and a "class" is a file of code. The example shows some of the classes and packages that are provided with the standard Java Runtime Environment (JRE). They're all in the java package (extended ones in the enterprise edition are in javax), which has subpackages such as lang (general language stuff), io (input / output) and util (utilities). Withing java.lang you have a whole lot of classes such as String - or its full name java.lang.String ... in this case, Strings handling unicode character strings.
Posted by gje at 08:33 AM | Comments (0)
Related topics: via article database
Useful link: Java training
Viv.java uses unchecked or unsafe operations - explanation and cure
Are you getting Java compiler messages like this?
Dorothy-2:java grahamellis$ javac Viv.java
Note: Viv.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Dorothy-2:java grahamellis$ javac -Xlint Viv.java
Which when you expand the warning with -Xlint gives:
Dorothy-2:java grahamellis$ javac -Xlint Viv.java
Viv.java:20: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.ArrayList
trowbridge.add(new Rolf("First Great Western",75,3,60));
^
If so, let me explain.
Java's collection classes - such as ArrayLists and Vectors - can hold any type of object, and the mechanisms of the base Java language allow yo to put in any object - including ones that may not be appropriate to a particular use. Alas - Java is NOT a language that trusts the programmer and the compiler wails that there may be a problem (if you're a good programmer, there probably isn't a problem!).
The problem is caused by a declaration such as this:
java.util.ArrayList trowbridge =
new java.util.ArrayList();
and can be overcome by telling java what sort of objects you expect to be in the ArrayList so that it can satisfy itself by making the checks on you. Here's how you tell it:
java.util.ArrayList<Peter> trowbridge =
new java.util.ArrayList<Peter>();
(I'm my example, I have objects of class "Peter" ... Peter is actually an abstract class, and the objects are really "Rolf"s and "Steve"s.
From Java Bootcamp. See source code of this and other early examples on this course (as run this week) here
See also Java Generics
Posted by gje at 06:47 AM | Comments (0)
Related topics: via article database
Useful link: Java training
Java Programming Fundamentals
Java Programming Fundamentals - sample programs from "hello world" through to objects, inheritance, arrays, packages and utility classes!
This week, I'm running a small Learning to Program in Java course ... and I have taken advantage of the small group size to write a co-herent series of new examples of the basics - showing not only how code works, but also how it is developed. I've uploaded all the examples into a single module, and they're also available through the following links
| Adam.java | Hello World, and command line input |
| Bernie.java | static method (function) calls |
| Chloe.java | First use of variables and conditionals |
| Daniel.java | Integer Calculation |
| Edward.java | Shared code - load and run method from another class |
| Fred.java | Reading user input from keyboard |
| Glenda.java | loop, with break and continue |
| Hilary.java | Passing values in and out of a local method |
| Irene.java | Arrays - setup, fill, pass, process, length |
| Julie.java | Array of arrays (i.e. 2 dimensional array) |
| Keith.java | Using a class |
| Lenny.java | Static Methods, comparing objects |
| Margaret.java | String handling example |
| Niamh.java | loading a method from a class in a package |
| Orlando.java | Class within a package |
| Peter.java | underlying (base) class |
| Quentin.java | Calling in an extended class |
| Rolf.java | Extended class |
| Steve.java | A second extended class |
| Time.java | Base class for examples up to Lenny |
| Trevor.java | Polymorphism - an array of different objects |
| Ulrika.java | An array of objects |
| Viv.java | An ArrayList - an extendable array |
| WellHouseInput.java | Reading from the keyboard or a file |
Posted by gje at 06:01 AM | Comments (0)
Related topics: via article database
Useful link: Java training
September 23, 2009
Automating access to a page obscured behind a holding page
Question: "I have a web page that I visit which sends me an initial response to say that it's working on the results, and then the results appear a few seconds later. I want to use an automed process / program on my computer to visit this page and store the final results, rather than having to access it through the browser. How can I do this?"
What an excellent question - we've all visited pages that come back and say 'I'm working on those results' then 'here are you final results' a few seconds later, and wouldn't it be great to be able to call them up automatically to script the accesses to the page - that way you could make good use of some excellent resources.
The answer comes in two stages. Firstly - you need to understand which of several ways the server is sending the intermediate pages. It could be sending out a single multipart response, with a pause between each of the sections (that's server push). It could be sending out a series of pages, each one as a separate request from the client (that's client pull), or it could be sending out an initial page that includes Javascript which reads further data back from the server via an AJAX type connection. The particular example that I was asked to look at was client pull, and I wrote a short server side script to illustrate that. You can run it here and see the source code (it's in PHP) here. The source code is full commented!
Secondly (and really that is second - you must understand how your server is working before you try to script the front of it!), use a module such as Perl's LWP::UserAgent to automate the access to it. I've written a full example here which scripts the connection to the service that I've written as a demonstration in the paragraph above ... when I run it, the results I get are as follows:
-bash-3.2$ perl coojar
Intermediate: Running ... 0 seconds gone
Intermediate: Running ... 5 seconds gone
Intermediate: Running ... 10 seconds gone
Intermediate: Running ... 15 seconds gone
Intermediate: Completed ...
04:13:51 up 3 days, 12:18, 1 user, load average: 0.18, 0.13, 0.16
FINAL RESULT: Completed ...
04:13:51 up 3 days, 12:18, 1 user, load average: 0.18, 0.13, 0.16
-bash-3.2$
Once again, the code is fully commented - so have a look at the source to see how it works. One thing of note is the concept of a cookie jar - this is the object in memory in which all the cookies are stored. We have chosen fot this particular application to have our own independent set of cookies rather than to share the ones that another browser has on the same client machine, but there are other Perl modules which let you connect to / share the cookie files (cookie jars) or other browsers. The setting of the agent name in the program is no more that a user politeness in most cases; please note that if you're runningthis against our server, you do need to specify an agent name, as we have additional security traps in place and defaulted LWP clients - intentionally - don't work with this script.
LWP::UserAgent is a very powerful automated browsing module and there are other examples in our trainee / source code directory ... including:
Simple LWP browser for testing
Grabbing current currency exchange rates
Validating all links from a page
Checking a static site for changes
Do remember whenever you use LWP::UserAgent that you are writing an automata, and you should check the robots.txt file at the server to ensure that your activities are acceptable to the server's operator. See here and here for more about robots.txt.
Posted by gje at 04:34 AM | Comments (0)
Related topics: via article database
September 22, 2009
Variable names like i and j - why?
Q: Why do people use variable names like "i" and "j" for loop counters? I thought that you were supposed to use longer, desciptive names!
A1: Fortran (FORmula TRANslator) was one of the prevalent programming languages in the 1960s and 1970s, at a time when many programming techniques, algorithms and methodologies were being developed, and in Fortran, variable names starting with I J K L M and N were implicitly integer, and all others (A to H and O to Z) implied float. So it was natural to START your loop variables - which tended to be integers as they counted up through discrete array members - with one of these default letters.
A2: Loop variables are set up and used within a very restricted (small) area of your program, but are intensively referred to within that area. Giving them a long name which you have to keep repeating leads to code that's needlessly stretched and can actually be more confusing that shorter code. Think about it ... in the wider real, we refer to our queen as "Elizabeth" but I'll bet that in the small local environment of home at Windsor Sandringham Balmoral Buck House, her Phil calls her Betty or even Bee.
Posted by gje at 12:13 PM | Comments (0)
Related topics: via article database
Hello World - a good traditional start to a Java course
All programming courses, it seems, start with a "Hello World" program. It's almost a tradition and while I'm not one of those people who follows traditions just for their sake, traditions usually are founded on good reason. This one is, and we follow it!
When you come new to a programming language, you want to see an overview of the picture of how it works very quickly. You want to see how to write the source code, what the shortest program looks like, and also how to store, compile (if necessary) and run the program. You want to make sure that all your tools such as compilers, virtual machines (whatever they are / if your need them) and run time libraries exist and are correctly loaded, and that everything is on the right path and with the right permissions. Most of these things will be automatically there in most cases ... but you need to be reassured and to check with the shortest of programs. Take the car out for a test drive before you start any real journeys!
On yesterday's Learning to Program in Java course, we started off with a look at the Java environment - JVM, JRE, JDK and put components such as the java compiler and jvm ('java') into place. Then we wrote this simple program into a file called Adam.java
public class Adam {
public static void main(String [] args) {
System.out.println("Ello Wurld");
}
}
and compiled and ran it:
Dorothy-2:java grahamellis$ javac Adam.java
Dorothy-2:java grahamellis$ java Adam
Ello Wurld
Dorothy-2:java grahamellis$
It might all look very basic - but even here there are some traps to catch the unwary - for example:
• To compile you do give the extension as you're giving a file name in the current directory.
• To run, you do NOT give an extension as it's looking for a path on the CLASSPATH which may be a file, or it may be within a jar.
During the course, I said a lot more - filled the class in on lots of other things and had them writing other and more complex code once we had the test drive out of the way. With Java , a language that's really very much better for the substantial application that the one liner, the structuring into functions is vital from day one, as is the interfacing to other resources and by the middle of the day we had progressed from a program called Adam to oe called Chloe - with command line inputs, variables, calculations, internal methods and more. If you want to take a look at Chloe, she's here.
Posted by gje at 08:30 AM | Comments (0)
Related topics: via article database
Useful link: Java training
September 21, 2009
Sanity checking the price, and selling up to increase income
"Does that LOOK right?" It's a question I always ask myself before I present a critical piece of information - such as a bill - to someone. The sanity checking in this was is something which was taught to me (and taught well, because it has stuck and is useful) many years ago when learning to use a slide rule, where you have to mentally calculate the order of magnitude of a result, although you read of the actual numbers to 2 or 3 decimal places.
But I think I'm unusual in asking "does that look right?". Out to lunch today - just myself and one delegate on the learning to program in Java day that precedes the Java Bootcamp course, I was taken aback to be charged over 18 pounds for a soft drink and a "lunch special" for two of us ... my estimate would have been (2 x lunch at five pounds, 2 drinks at two pounds) 14 pounds. However, in front of a delegate, I'm loathe to challenge a bill which could be right - and surely the barman would spot anything silly?
Anyway ... I looked at my receipt, a little shocked at the price, as we say down and noted three halves of lager shandy on my bill. Now that was the point at which I did take the bill back up, and ask if it was right; it wasn't, and the barman went away to correct it and brought back a new receipt and four pounds. He didn't seem surprised, and it was more of "yes, that's wrong, I'll correct it" rather than "I am SO sorry ..." ((At least it wasn't "You're too late - you paid it"))
Am I making a mountain out of a molehill? Perhaps, and perhaps I'm being unfair to the Xxxx's Xxxx, where the food was nice, the service fast enough for lunchtime, and the prices - including those in the extra menu that the barman helpfully (!) pressed on my delegate ("selling up") weren't out of the question for a lunch with more delegates on another date. But there's certainly a note of 'check the bill, expect to be sold up towards more expensive food' which leaves it as a less appropriate lunch place for us. For others - for example the three old ladies, sat in the window with their three halves of lager shandy for which I had unwittingly paid, it's probably ideal.
Posted by gje at 04:46 PM | Comments (0)
Related topics: via article database
September 20, 2009
Autumn Fruits and Bristol Old Station
Where can we go today?

There's a wide choice of places on offer ...

... some of which have a chequered and interesting history (and those of you who know something about your history of Bristol will recognise that this covered car park was once the gateway to the City

But it's autumn, and it's much more colourful to take a short walk in the country and pick some of the fruit:

Rose Hips

Blackberries

And hawthorn berries
Posted by gje at 02:33 AM | Comments (0)
Related topics: via article database
September 19, 2009
Further North - long summer days and lovely countryside
I live further north than the city of Moose Jaw, Saskatchewan at 50°37' [Latitude]. And much further north than Ottawa, where I was cautioned against walking 400 yards to a restaurant in deep winter because of the bitter cold. Ottawa is at 45°24'. Where I live is 51°32' North.
Living so far north, the days in winter are short, and in summer are long - the seasons here are much more extreme that they are in Washington DC, or Florida or Los Angeles ... a fact I was reminded of today when I got an email commenting on something I had said about "shorter days" - in fact, in summer I can awaken at 4 a.m. and it'll be light outside, and it will still be light at 9 O'clock in the evening. And in winter, the clocks have fallen back by an hour to let the school children get to school in the light ... to spring forward about six months later, with the purpose of giving those same children, on holiday in July and August so that they can help their parents with the harvest, extra time to do their chores in the fields.
The seasons, long nights and short days then short nights and long days, have always been a part of my life - so I don't really think about them. It's commonplace in some seasons to be going to sleep in the light, and common in other seasons to drag yourself out of bed before ever the first glimmer of light is visible over the horizon. And it always been such a part of my life that I'll often overlook the fact that our part of the work is unusual in having so much developed activity so far north. Tokyo is "deep south" at 35°40' and Beijing also quite southern at 39°55' ; looking north to where Russia meets the Pacific at Vladivostok, and you're still only at 43°10'.
Where do I live - perhaps surprisingly after this build up, I live in Southern England - on the same parallel as London, and in a temperate climate that I would compare more to somewhere like Sacramento at 38°35' ; the 'trick' of living so far North, and yet in such a climate suitable for human habitation, comes from the Gulf Stream - that flow of warm water which flows across the Atlantic from the Sargasso Sea (vaguely in the Caribbean, I recall from school lessons many years ago), up past Ireland and Scotland and on up to Scandinavia, which is perhaps why the major cities that I found further north of us were the Norsk ones - Oslo, Stockholm, Helsinki and Reykjavik.
Our long and short days, and at the same time our mild climate, are both blessings. You can tell when you fly into a British airport that you're arriving in the United Kingdom before you even touch down - bases on how green everything is. And it's a great spot for a vacation too. The "Old Country" with so much history, and all packed into such a small space too. A day's driving will get you from the South of England to the North of Scotland but for one problem - you'll want to stop and see so many things along the way!
The images I've added into this article are taken at our hotel - "Well House Manor" - or within a very few miles; it's a lovely part of the UK and although our main market is business visitors to the town, we're also delighted to welcome guests who are in England to see places like Lacock - a village dating from the 13th Century, and where the positive / negative photographic process was invented (5 miles), the world heritage site of Bath just 12 miles away, and with a direct bus running there from right outside our front door, and Longleat, Stonehenge, Salisbury and many more places of interest.
With our business connections, our hotel is especially well set up to welcome early checkins by visitors arriving through London's airports as early as 7 O'Clock, and as Lisa is American we're also very well tailored to helping with things that first time visitors to Europe may find a little new. Graham and Chris have lived most of their lives in Wiltshire, but are well travelled - it all leads to a winning combination.
Here's hoping that, dear readers, I may have tempted a few of you to add Wiltshire, England to you "I want to go there sometime" list. And if I have done so, I hope you'll stop by to say "hi" ... or if the accommodation that we offer suits you, that you'll stop with us. If you'll be stopping, it's best to book in advance though - the combination of a mild northern climate, a lovely heritage, and a hotel that's run with the guests to the fore is a winning combination, and we can get full. I'm checking guests in tonight - 4 rooms already arrived, and the fifth set due any minute. In fact, I think that might be a car I hear now on the gravel path.
Posted by gje at 07:41 PM | Comments (0)
Related topics: via article database
Removal of technical resources from this site
"Will you ever be removing any of these resources?" A question asked in all seriousness by a delegate on the course I was concluding in Friday, as he looked through the huge range of pages we have here.
I'm not a politician, so I can answer a question simply - the answer is "No - I can't see circumstances in which I would pull material."
Ah - but there's a slight simplification there; if you're seeing this through the http://www.wellho.net/horse/ URL - the front page of "The Horse's Mouth" blog - the it will disappear in the next few days - it'll be gone from this page by the 28th September 2009. But it WILL be accessible through the archive http://www.wellho.net/mouth/2410_Removal-of-technical-resources-from-this-site.html now, and for the foreseeable future.
As I write articles ... as program samples get added to the site too ... it grows. And pictures get added too. I can quote some impressive figures. But this does mean that however we index content, any article that starts off easy to find in a short index is going to get harder to find over time, as the tree that you want gets mixed up in other woods. We do categorise by topic - so you can use our two level directory structure via our modules page, or a pancake listing via our global index page. Our latest newsletter will give you links to the latest five blog articles on each of a dozen subject categories, with an option to expand a category of your choice and see all article.
Where material becomes seriously outdated ... (there are some articles that fall into that category already) and it's not obvious from the text, I'll go back in and add updates, or cautions to the reader. But never (well hardly ever) pull material - I guess I would if someone withdrew copyright permission from an image I have used, or if one of our scam articles turned out to be unfounded ...
Posted by gje at 05:25 PM | Comments (0)
Related topics: via article database
September 18, 2009
TypeError: super() argument 1 must be type, not classobj (Python)
If you've got an error message like this, you've called up a method from the base class of your object using "new style classes", but the base class is an "old style class". The full error message looks something like this:
Traceback (most recent call last):
File "cl_n.py", line 24, in <module>
testgroup = [train("First Great Western cl 150",80,2)]
File "cl_n.py", line 10, in __init__
super(train,self).__init__(about)
TypeError: super() argument 1 must be type, not classobj
Here's the full failing source code of my example:
class pubtrans:
def __init__(self,about):
self.info = about
def getabout(self):
return self.info
def getvehicles(self):
return 1
class train(pubtrans):
def __init__(self,about,vehicle_capacity,coaches):
super(train,self).__init__(about)
self.vc = vehicle_capacity
self.nc = coaches
def getcapacity(self):
return self.vc * self.nc
def getvehicles(self):
return self.nc
class bus(pubtrans):
def __init__(self,about,vehicle_capacity):
super(bus,self).__init__(about)
self.vc = vehicle_capacity
def getcapacity(self):
return self.vc
if __name__ == "__main__":
testgroup = [train("First Great Western cl 150",80,2)]
testgroup.append(bus("First Avon and Somerset",81))
testgroup.append(bus("Faresaver",29))
testgroup.append(train("South West Trains cl 159",75,3))
format = "%-30s %4d %d"
tpc = 0
tvc = 0
for option in testgroup:
text = option.getabout()
pass_count = option.getcapacity()
veh_count = option.getvehicles()
tpc += pass_count
tvc += veh_count
print format % (text, pass_count, veh_count)
print format % (" --- TOTAL ---",tpc,tvc)
The problem is that the base class is an old style class because it's defined without any inheritance, whereas the extended classes / derived classes / subclasses are using the new style super call. There are two ways of solving the problem.
The first (and infinitely preferable) is to switch to new style classes by having the base class inherit from object - it's as easy as changing:
class pubtrans:
to
class pubtrans(object):
The second option (not recommended, as it retains old style classes which are not supported in Python 3) is to call up the constructor of the base class directly rather than using the super call. In other words, in my example the two lines:
super(train,self).__init__(about)
super(bus,self).__init__(about)
would both become:
pubtrans.__init__(self,about)
The complete source code of the new style example is here and of the old style example is here.
P.S. It runs, when corrected, like this:
Dorothy-2:2 grahamellis$ python cl_o.py
First Great Western cl 150 160 2
First Avon and Somerset 81 1
Faresaver 29 1
South West Trains cl 159 225 3
--- TOTAL --- 495 7
Dorothy-2:2 grahamellis$
Posted by gje at 10:18 PM | Comments (0)
Related topics: via article database
Useful link: Python training
September 17, 2009
Robust user input (exception handling) example in Python
One of the questions in the "exceptions" section of the Python Course asks my delegates to "Graham Proof" a piece of code:
first = int(input("First number: "))
second = int(input("Second number: "))
print "Sum is "+str(first+second)
The idea is that I come round the room and put really awkward inputs into customer's programs, as would a hacker or a non-thinking user. Not only is there a need to trap exceptions, but input should be changed to raw_input, and the input / error handling delegated to a function so that an error on the second input doesn't push the user back to remaking the first input, nor does it result in code duplication. Here is what I came up with:
def getval(pr):
while 1:
try:
result = raw_input(pr+" ")
val = float(result)
return val
except EOFError:
print "Ran out of Data"
exit()
except:
print "nah"
first = getval("first number")
second = getval("second number")
print "Sum is "+str(first+second)
A further comment on the EOFError. On some systems, you can continue to read even if you've received an EOF - RedHat Fedora Linux being one of them. On others, such as my Mac with OS X, reading past the end of file results in the code returning a further EOF without checking / waiting so see if there's any more data. My code above deals with the case on both types of operating system ...
Posted by gje at 08:02 PM | Comments (0)
Related topics: via article database
Useful link: Python training
September 16, 2009
Testing code in Python - doctest, unittest and others
The doctest and unittest modules of Python allow you to provide test harnesses for your classes / packages. Designing applications from the bottom up, you'll want to ensure that each of your code levels works and works well. You'll want to provide an example of what it should do for the next level or programmer up, and you may want to be able to run the code time and time again - perhaps to test some device or algorithm you're plugging in underneath - and get a test report out from that.
With the doctest module, you initially run the python class from the interactive command line and the cut and paste the interaction into a documentation string. When you then run the code to test it, the doctest module checks that the test reproduces the same output that's in the docstring. There's an example here.
The unittest module requires you to write a series of test methods, each starting with the word "test" in their name and including code that asserts what conditions they should find after completion - perhaps an equality, or a certain value exists somewhere in a list. And at the end of all the tests, the module produces a report of which tests passed and failed. There are examples of unittest code here and here
Here's an example of unittest - I have added another test to the source code examples above (which test the system's random module!) and in this first case it all worked.
92:1 grahamellis$ python utter
testchoice (__main__.TestSequenceFunctions) ... ok
testflop (__main__.TestSequenceFunctions) ... ok
testsample (__main__.TestSequenceFunctions) ... ok
testshuffle (__main__.TestSequenceFunctions) ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.007s
OK
92:1 grahamellis$
Now altering the code to assert that 42 is a number that can be found in a list of suffled numbers from 0 to 10 (which clearly it is not!) I got the following result:
92:1 grahamellis$ python utter
testchoice (__main__.TestSequenceFunctions) ... ok
testflop (__main__.TestSequenceFunctions) ... FAIL
testsample (__main__.TestSequenceFunctions) ... ok
testshuffle (__main__.TestSequenceFunctions) ... ok
======================================================================
FAIL: testflop (__main__.TestSequenceFunctions)
----------------------------------------------------------------------
Traceback (most recent call last):
File "utter", line 21, in testflop
self.assert_(element in self.seq)
AssertionError
----------------------------------------------------------------------
Ran 4 tests in 0.100s
FAILED (failures=1)
92:1 grahamellis$
Python also has a profiler module that allows you to see your code coverage, and you should always remember to add a short test harness onto the end of your modules to ensure that the module, when loaded stand alone, is selfvalidating. There's an example here.
Posted by gje at 07:41 PM | Comments (0)
Related topics: via article database
Useful link: Python training
September 15, 2009
Pound Sign in Python Program
How do I get a pound sign up in Python? A regular question ans the regular answer is to use a unicode string:
>>> saying = u'It will cost \u00a310.00'
>>> print saying
It will cost £10.00
>>>
Which is all well and good, but people want to be able to type the pound sign into the source code too. But that gives problems.
Source code file:
92:1 grahamellis$ cat ff
val = "it cost £9.00"
print val
92:1 grahamellis$
And when I try to run that, I get:
92:1 grahamellis$ python ff
File "ff", line 1
SyntaxError: Non-ASCII character '\xc2' in file ff on line 1, but no
encoding declared; see http://www.python.org/peps/pep-0263.html
for details
92:1 grahamellis$
Well - it tells me to declare the coding, so I will. That's a comment in a special format in one of the first two lines of the source file. Here's a modified source file:
# -*- coding: utf-8 -*-
uv = u'That will cost you £1340.00'
print uv
And it runs beautifully
92:1 grahamellis$ python ahha
That will cost you £1340.00
92:1 grahamellis$
See also The Pyhon Unicode HowTo ... but note that the # -*- coding: latin-1 -*- example there isn't the one for the pound sign (It also produced an umlauted A!) and you want utf-8
Posted by gje at 05:59 PM | Comments (0)
Related topics: via article database
Useful link: Python training
September 14, 2009
But I am reading from a file - no need to prompt (Perl)
If you're writing a script that calls for user input, you had better prompt the user ... otherwise, the terminal / window will appear to hang and the user won't know what's going on. However - if you're reading your answers from a pre-prepared file or piping them in from another process, all of these immediately answered prompts will look really odd on the output.
In perl, you can use the -t file test, but on a file handle to see if that file handle is connected to an interactive device, or is not interactive. Most commonly, it's used on STDIN. Here's a demo program:
# See if we are using an interactive input ...
# If we are, prompt the user. If not, just read
if (-t STDIN) {
print "How much? "; }
chop($value = <STDIN>);
print "You paid $value too much\n";
Samples of this running, interactive with the prompt:
Dorothy-2:perl grahamellis$ perl sinter
How much? 33
You paid 33 too much
Dorothy-2:perl grahamellis$
And non-interactive:
Dorothy-2:perl grahamellis$ echo 55 | perl sinter
You paid 55 too much
Dorothy-2:perl grahamellis$
Illustration - A delegate uses one of our machines during a practical session on a Perl training course.
Posted by gje at 06:27 PM | Comments (0)
Related topics: via article database
Useful link: Perl training
September 13, 2009
Low Sun - Autumn is here
The days are rapidly getting shorter - as we head for Michaelmas, when there's 12 hours of light and 12 hours of dark ... then on towards the time of the year with the shortest days at Christmas. Goodness - I'm talking "Christmas" already.
This afternoon, I took a short walk in the fields behind our home (something I'm prone to do far more often now that we have a dog, and one who understands the word "Walkies" too!). And the sun is getting lower, earlier, leading to some spectacular photos. The buzzard (I'm told it's a buzzard) that nested in the trees on the field's edge this summer was soaring over the field, dramatically lit by the sun behind.
Only a few weeks ago, it seems, the grass crop in the field was turned into hay, but already there's a good new crop of clover and thistles, and the odd confused buttercup or two is flowering as well.
Both Thursday and Friday of last week, I met visitors off the 19:11 arrival at Melksham - again very much in the low light, as we head to the time of year when it won't be possible to photograph a train in daylight there. Let's hope that with some movements we've seen in our campaign, and all the support we have that this will be the last winter with this depressing state of affairs. Come Lady Day in March, longer days will bring back light on the trains, and come May there's perhaps the best chance yet of a decent service.
Posted by gje at 05:04 PM | Comments (0)
Related topics: via article database
September 12, 2009
Hotel Booking Scam / Cost of calls to 070 numbers
In my email, a juicy hotel booking ... 10 days for five double rooms ... which we shall not be accepting.
|
Dear Sir/Ma, I am Andrea Paula,I write to introduce our Ministry " His Grace Ministries". Our main importance of sending this mail is to crave your sense of honesty and sincerity with respect to this enquiry. We want to enquire from you if you can book an accommodation for the Church team who will be arriving Evangelical Program. We would be most appreciative if you would be willing to do so. Number of Guest: 10 |
We welcome ... genuine visitors to Melksham, except this one is not genuine (have a look here for other reports). The email goes on:
|
For prompt action, we would be very grateful, if you can send with the total cost for of the accommodation to effect the prepayment and the following details: 1. TOTAL COST FOR THE ACCOMMODATION (In $USD Currency) We would be expecting your prompt response so that we can forward our Credit Card Details for prepayment. Thank you and God Bless, |
If past experiences reported elsewhere are to be followed, it goes on like this:
a) Booking made and payment taken (note - they want to prepay).
b) Booking cancelled, refund made (to a different account at client's request)
c) Bank says original payment was on stolen card / had another problem and revokes the payment to the hotel. But by this time there's no way to revoke the refund.
Don't be comforted by the UK phone number on the end of the email:
|
PHONE LINES: |
Those are to personal numbers ... UK numbers which can then be routed anywhere in the world ... with the bill being picked up by the caller.
To quote The Register "Callers to personal numbers have in the past called 070 numbers thinking they are mobiles and have been shocked at the sometimes high cost of making the call. [snip] Calls to personal numbers from mobile phones can cost as much as £2 for a 10 or 15 second call."
So ... let's see. The scam can cost you serious money to set up a deal. And theny you're out of pocket when you get stung for the refund. And while you have had those five rooms booked, you've lost further income by turning away other potential bookings. Nasty, Nasty, Nasty!
Posted by gje at 06:21 PM | Comments (0)
Related topics: via article database
September 11, 2009
Automated Browsing in Perl
I'm reminded on today's Perl course just how powerful some of the modules are, and how much you can do in so little code.
LWP::UserAgent turns your Perl into an automated browser .. the following four lines reading the robots.txt off my web site.
use LWP::UserAgent;
$connex = new LWP::UserAgent("agent" => "007");
$response = $connex->get("http://www.wellho.net/robots.txt");
print $response->decoded_content;
Posted by gje at 05:15 PM | Comments (0)
Related topics: via article database
Useful link: Perl training
September 10, 2009
Back Tomorrow
The most incredibly busy week - a five day Perl course, and five evening meetings too. The web server has been down for a few hours this evening (don't know why yet - network problems at our web space provider by the looks of things), so no more than a holding post tonight!
Posted by gje at 10:22 PM | Comments (0)
Related topics: via article database
September 08, 2009
Are you wanting to learn PHP?
Are you wanting to learn PHP? Select a course that starts and ends at the right points!
You may (or may not) already know all the background stuff about web sites. And you may (or may not) have programmed a computer before. So you'll want to select the course with the correct starting point - one which neither assumes knowledge you don't have, nor makes you sit through stuff you already know.
You may be providing a fairly regular site running some small interactive pages, or you may be writing / running a major web based application. You may (or may not) need to know about Object Oriented PHP, you may need to know about AJAX (client - server interaction), web2 (where your server will contact other servers while handling requests), etc. So you'll want to select the course that takes you through the correct subjects to the right end point - one which covers everything you need, but does not keep you at our training centre, paying us money, through advanced topics that are un-necessary for you
We offer a range of courses - with different start and end points that help us match each individual's needs as closely as possible. There are three ways into the central "PHP Programming" subjects depending on your background, and advanced courses to take you beyond those base subjects, but only if you need that.
Here - in answer to an email I have just answered - are the courses:
1. Our "Technology for PHP" day - covers the pre-requisites for PHP rather than the language / system itself. It introduces HTML, web site structure, basics of computer programming and design, SQL databases and a host of other subjects which all get brought together within interactive web sites of the sort that you may develop under PHP. This is very much a 'lead in' day for newcomers to the technology - perhaps graphic artists who have been tasked with taking over or developing a web site that uses or will use PHP, and who need to start quickly in all the online technologies. These days, the course runs as required, typically for a single delegate, as a lead in to the "Learning to program in PHP" or "PHP Programming courses" - the next two I'll talk about. Cost for the Technology for PHP day is 350.00 + VAT
2. "Learning to Program in PHP" is a five day course for delegates who are familiar with web site set up / technology, but have never programmed before - it runs regularly at our Melksham, Wiltshire training centre. Full details here.
3. As an ALTERNATIVE to No. 2 ... "PHP Programming" is a course for delegates who have programmed before, but in other languages and perhaps not for web sites. It is 4 days long, and runs regularly at our training centre, sharing the final 4 days of the "learning to program" course - no. 2. See here.
4. Our "PHP Technology workshop" is a two day advanced course covering how to take PHP a step further - making the best of the language with graphics, multipage applications, site templating, and much more - see here.
5. Object Oriented Programming in PHP is a single day that covers OO (data driven programming) and how it's implemented and best used in PHP. Like the "technology workshop", this is another advanced course which takes you beyond the PHP programming / learning to program in PHP course. It is described in detail here
By offering courses in this way, we can come very close to providing the ideal agenda for most people. But everyone is different so it can never be exact - and the economics wouldn't mean we could sensibly train everyone on their own private course. But if you have a group of delegates - typically four or more - we can (and will) run a tailored private course at our training centre or at your offices which will be even more cost effective than places on public courses. See some priced examples ... PHP course in Cambridge, Private PHP training, Leeds, PHP class in Scotland, Learn PHP in Northern Ireland.
Posted by gje at 08:05 AM | Comments (0)
Related topics: via article database
Useful link: PHP training
September 07, 2009
Firefighting with Perl
If the building is blazing, you'll go right ahead and put the fire out with the extinguisher. Hopefully you'll have been trained to use the right sort of extinguisher on the right fire, but you won't leave the fire to blaze just because the "date last serviced" record has become smudged and you don't know if the extinuisher is technically overdue for overhaul - you can soon chuck it to one side if it fails!
At times, Perl can be a bit of a fire extinuguisher - a language that you'll use to plug the emergency gaps, get a quick answer to a one-off question that's needed in response to the MD's call out from a meeting, etc. Questions like "why is our web server running slowly - are there particular pages draining the c.p.u." and "how many people have visited our newsletter page since we sent out the mailing last week?"
Such code need not be pretty; it can be hacked together and provided that it works, comments / readability / maintainability / design can - temporatily - go out of the window. But even when you're writing firefighting code, ALWAYS check that your results are correct
Finding the slow server records
Both of the questions that I raised above have been asked of me ... the "slow server" one at 3 a.m. when responses were dreadful ... and I wanted to find all access records in the current log file that stepped back in time six seconds or more (records are logged in the order of completion, but the time stamps are the access start time!)
The code remains in our server's live log directory to this day. It is "sort of" documented by being names "slow.pl" which is a bit of a clue, and I have inset my loops. A print statement that I used in early debugging remains commented out, and there is no validation to check that the log file really is present. Here's the code in its current state - intentionally left available in case the particular file re-ignites:
open (FH,"access_log");
$osid = 0;
while (<FH>) {
$l++;
($h, $m, $s) = /(\d\d):(\d\d):(\d\d)/;
$sid =$s + 60*$m + 3600 * $h;
if ($osid) {
$moved = $sid - $osid;
if ($moved < -6) {
print "$moved $l ";
print;
}
}
# print "$moved\n";
$osid = $sid;
}
It's a cool autumn morning, all is quiet and the logs were tidied up a couple of hours ago by our night porter, affecionally known as 'cron' ... so there have been absolutely no issues yet today. A typical 'Unix Utility' working on the 'no news is good news' paradigm:
-bash-3.2$ perl slow.pl
-bash-3.2$
Counting unique visitors to a particular area
Let's look at the other question - "how many people have come to our newsletter". This is really one-off code at the moment:
#!/usr/bin/perl -na
m!GET /newsletter/! and $counter{$F[0]}++;
m!GET /newsletter/! and $tc++;
END {
$th = keys(%counter);
foreach $ho(sort(keys(%counter))) {
print "$ho $counter{$ho}\n"; }
print "Total hits $tc ... hosts $th\n"; }
How does that work?
I run it with the input files named on the command line, and the -n switch reads each line of each file it turn into $_, which is then matched against the regular expression(s) and counted if they match - actually counted twice, once in a table (hash) by the visitor's IP address - the first field on the line which has been autosplit into @F by the -a switch.
Once all the lines have been read, the END block is run once, listing all the IP addresses in order, together with counts per IP, then the final (desired) results - total accesses and total DIFFERENT hosts accessing - are printed out:
-bash-3.2$ ./pgnl ac_2009082* ac_2009083* ac_200909*
snip
89.124.xxx.xxx 4
92.237.xxx.xxx 104
92.239.xxx.xxx 4
Total hits 2823 ... hosts 131
-bash-3.2$
Even there, the numbers need to be checked somewhat and read with care; each 'newsletter' hit from a 'real' visitor is four accesses - the main newsletter and 3 graphics in the same directory, and the total of 131 hosts includes our own test machines, and also crawlers such as Google. The fulllist / IP numbers gave me further clues, and I was able to say that I estimated that beween 110 and 120 people had clicked through. Expressed as a percentage of the number of emails, and considering that's people who oepned teh email and took a further step as well, I have to say I'm quite pleased.
Back to the Perl code
Would I be proud to supply this code as part of a contract? No. But am I happy with what it allowed me to do very quickly. Absolutely. I used to say that "what took me a week in C now takes me a day in Perl". That's changed, somewhat: "What took me a week now takes me a morning in Perl".
Posted by gje at 08:22 AM | Comments (0)
Related topics: via article database
Useful link: Perl training
September 06, 2009
Websitemediasolution and a goldfish called Carl Johnson
I think I've seen it said that goldfish have a very short memory.
About a week ago, I got an email that was better produced than most unsolicited emails that I get - and as we are in the Web site and web development business, the title was close enough to that of a genuine enquiry for me to carefully open it and have a quick look through. OK - it became clear fairly quickly that it was a bulk email (spam) with all the usual tell tail characteristics that I won't bother to list. I brushed it aside, re-assured by the last paragraph:
This email has been sent as a one-off so we won't contact you again unless you want us to. If you aren't interested in our services simply ignore this email and we won't bother you again
I wasn't assured by the fact that he wouldn't bother us again (I didn't believe it), but by the disclaimer being formed in such a way that clearly indicated this was just one email of a veritable flood sent out by Carl - probably not his/her real name.
Why so I say that Carl is a goldfish? Because within 10 days, he's forgotten his promise not to bother us again and has sent us another, identical email - and it's identical down to the same promise.

I wouldn't do business with a goldfish. Too much need to repeat myself. Too much need to repeat myself. Too much need to repeat myself. Carl Johnson of Websitemediasolution claims to provide high search engine rankings. Let's play him at his own game and see if we can get this page ranker higher that his. So, goldfish style, I'll mention his name - Carl - and his surname - Johnson - and his company - webmediasolution - a few times.
Fish pics from Hillier Gardens and their own site
Posted by gje at 07:45 PM | Comments (0)
Related topics: via article database
Signwriting is dead. Long live the sign.
Have you noticed that there's a sign up telling you everything you must and must not, may and may not, can and cannot do? And there are so many signs up there that seem to have been put up without giving thought to who will be reading them, why, and what they'll get from them. Let's see some.
I suppose that in some parts, people are in the habit of trying to run people over ... so there is a need for signs telling people to drive carefully. Oh come off it - when did you last go out and think "It's Tuesday - I'll drive dangerously!"
OK ... so there's a brass step. Is that telling me to be careful because there's a step (what does that material matter), or is the sign writer telling me that I need to be careful because it is brass. Perhaps he is proud that it is brass ... I don't know!
Situated right beside a public footpath, where I'm sure that everyone passing by except me knows what a "Class B Entry Procedure" is, so can draw a proper conclusion as to whether or not they're allowed. I was just left flummoxed!
This looks like a good deal, advertised at our local station. Get an off peak ticket, and visit some great London attractions. Just one problem - First Great Western have withdrawn all the off peak trains, so here's a magnificent advert for a product you can's make any use of. Marketing own goal!
Let's see ... people are not allowed to park in the station area as it has to be left for the public. Lemme see now - I thought that the public were people too. Just occasionally, the railways let the cat out of the bag and admit that they think that their customers are subhuman. Nice one, Tony!
And while we're on site signs, this one has appeared on several sites in Melksham recently. One copy was behind a wire grill, so that you couldn't actually read it. And another was right at a temporary pinch-point where vehicles were passing close by ... you had take your life and limb in hand to read the sign ... and allow a good few minutes to do so too, including time to bend over and read the fine print at the bottom. Wouldn't it be more effective to simple say "We'll do this work carefully and considerately of everyone around, their businesses and the environment"
Another works sign. "Put it in print on a sign, and you make it true, even if it is a lie". The businesses round the back of these road works are clearly NOT open as usual. They're hard to get to at the moment, they're darker and noisier, they've had their power unexpecterdly cut off. But - hey - the sign says "open AS USUAL", so that's all right, isn't it?
The law requires no smoking signs. It was a good idea to have them everywhere for a few weeks when the smoking ban came in, but what purpose to the No Smoking signs that festoon everywhere fulfil these days? Is it more that simply being there to meet the legal requirement for the signs? We didn't have no smoking signs at Well House Manor until the ban came in ... and we had no problem with people smoking. But we've still had to put these signs up ... to tell people what they already know
OK - that's just plain careless, or amusing .. or they didn't have room for the "M"!
Let's finish with a couple of better examples ... things you might not have guessed at, and simple signs to boot which are clear and easily read ...
... even if you do wonder what buses have to do with falling rocks.
Posted by gje at 04:49 PM | Comments (0)
Related topics: via article database
Easing off in our 50s?
From my mailbox:
"Now that I'm 50, I'm looking to ease off on the IT which is turning into far more work that I anticipated. Also have a farm, where I have seriously been thinking of relocating to, and planting fruit trees. Would continue to do some software work, but hopefully less than now. Maybe just limited to those installations still under support contracts. But I also worry that the farm will turn into more work than planned, and that I'll end up having to do more software work than expected... And, well, you get the idea. More work instead of less. I am wondering if perhaps you are doing something similar, with the hotel instead of a farm? If so, has it worked out as you planned, or do you find yourself in the situation I am worried about, with more work instead of less?
Dear Jim,
Your email made me chuckle when it arrived. I read that you are wondering about whether to start reducing the amount of IT / Consultancy work you do, and ease off into running a different business. You ask if it's more relaxed and easier going in this newer style of ours, or if life becomes busier. Well - I'll answer for us / our business, and let you draw any parallels there may be between guests and fruit trees.
Why did I chuckle? Because it was around 06:30 in the morning when I got your email, and I had just read my other emails telling me that Lisa has been up until 03:30 waiting for the last guests to check in, and that Chris had arrived for work at 05:30, let himself in, and had tripped over the baggage of the guests ... who had arrived at 04:30, knocked and been let in by other guests, and had slept in the lounge as there was a phone problem on the line that should have reached Lisa. My phone rang - Chris - a couple of minutes later; he was preparing for breakfast for 20 people and wanted to check what we should do to compensate our 04:30 arrivals for being unable to reach us and having to sleep in the lounge after their nightmare journey (12 hour delay!) to us. With all this going on, I was a 2 hour drive away, as I was giving a 2 day course in Python and staying in someone else's hotel.
The answer to "has life become easier" is a resounding NO. The move from a training centre - which we used to refer to as a "daytime hotel" because we still had to help with all the customers travel plans, daytime needs, etc, to a 24 x 7 facility with overnight accommodation / beds has added a huge workload and extra staff. But it has added a new dimension to the enjoyment too - meeting new people and a wider variety of people, and if you are gregarious, very laid back, and able to handle the unexpected well ("think on your feet"), it can be very rewarding - emotionally, but not usually financially - it's very hard work for relatively small reward. And the days are long. I am now - quarter past six on Saturday afternoon - answering emails / doing computer work at the hotel, waiting for the guests who expected to be here at about 4. A phone call a few minutes ago (people don't always phone!) told me they're later than they expected and will be here at around 7. We'll see!
We are a different setup to the one you described to me, so our experiences may not be totally relevant. Trainees on our courses - the reason that we set up in the first place - are usually the easiest of customers on the hotel 'side'. They arrive the evening before the course, usually within an hour or two of the time they estimate when they book, and they make few extra / unusual requests during their stay - probably because we're set up for exactly their sort of visitor so everything is well in place for them.
Other business visitors to the area - people sent to us by local companies, or who are visiting those companies, are also great guests. When they book directly with us, we have a clear e.t.a. and many of them are regulars too, so we know (and note) how they'll be arriving; where flights from the USA are delayed, we'll have an inkling they'll be late, and if they are flying in on the 'redeye' we'll know and have their rooms ready early.
Where booking come through agencies, we have less detail ahead of time and that can lead to some long waits. Murphy's law of hotel keeping states that if you give up waiting for a guest and lock the door at 10 O'clock he'll arrive at five past, but if you leave the door open until 10:30, he'll turn up at 10:40.
Trainees and other business visitors stay for a few days, often stay away from home, and are thoughtful of the hotel owner / operator from their arrival - an utter pleasure to have, and rooms turnovers are typically easy.
Leisure guests travel far less frequently. So they're not as good as planning their visit and sometimes need a lot more attention. Their plans change more often. They get mixed up between rooms with two smaller beds and one larger bed. They get lost on the way here. They are less predictable as to their breakfast time, and they'll tend not to appreciate that we don't have a line of taxis outside just waiting for guests (we are just five rooms!). And there tends to start by taking a much more "master / servant" approach with us until they feel comfortable. But such guests can - and usually are - very rewarding to have around; once they get to know us and the place they can become far firmer friends. They have far more time to chat (sometimes they want to talk) and they're much more likely to be wanting local information / interested in what's happening around. This can be either a nightmare or a joy depending on 'the staff', and all three of our customer facing team who meet up face to face with the customers are ones for whom it's a joy.
Parties ... such as groups of people meeting up at the Hotel for local weddings ... are even more of an organisational issue. We have learned the hard way that The Bride might want to organise everything, including the accommodation, herself. BUT ... she doesn't normally do much organising, and Great Aunt Mildred who she hasn't seen for 20 years keeps changing her plans and the whole thing can become chaotic. In everyone's interest, we have come up with a somewhat regimented scheme (see here) where we'll hold the rooms until a certain date, where the guests book with us directly which means that we know what time they'll be arriving, and the bride can concentrate on her closer issues, and that rooms are sold at full price with quantity discount only being applied when the guests are actually here, as it avoids issues with some rooms cancelled at the last minute because there has been a family argument.
We also have to bear in mind that a party booking ALL our rooms for one night will mean that we're probably going to be very 'light' the nights before and after. A full hotel one night might seem good, but if they are all in for just one night, it means up to 8 sets of bedding and towels to be washed. Remember too that a lot of makeup is worn to weddings and other celebrations (which tends to get all over sheets and towels), and the party will be back from the event very late into the night, possibly having lost their keys.
My guests have arrived ... about a quarter to seven. Taxi booked for them for quarter past seven, and I'm clearing up before they leave. Lovely, friendly, couple - most of our guests are. They expect to be back in very late, and have been told breakfast is 8 til 10. Chris will be in to deal with all the breakfasts from 7:30, and I suspect that it will run on past 10. We're laid back, quite happy to do that.
Jim, I may have painted a picture there which doesn't thrill you / doesn't look like easing off. And that's intentional - it's not easy. But it is fun / rewarding / a way of life that has a lot of pleasures. We love introducing people to our town.
The morning after I got back from my training trip, (this morning, but it's been a long day!) I came over to the hotel and caught up with Chris who had been working that 05:30 shift when so much had happened. I was checking that he was OK with it. Yes - very much so; he deals with situations well and handles things well for the customers and for us too - practical solutions to the occasional 'issues' and very knowledgeable abouy how to handle situations because fewer and fewer are 'first time' things now. And as he say "it's reward to be able to help and sort things out - it certainly keeps the job interesting".
Carriages in five minutes. I'll shut down this computer and send the email from home when I get there. We love it - but it's not for everyone.
Graham
P.S. The training business is very busy too. I do have a few days that I'm not booked in October, places on public Perl, Java and PHP courses this month, and hotel rooms vacancies where I look forward to welcoming business, leisure and wedding guests.
Posted by gje at 02:33 AM | Comments (0)
Related topics: via article database
September 05, 2009
From Lymington by train - last of the slammers
It seems like half a lifetime ago (probably because it was half a lifetime ago) that I commuted to school on the electric trains of the Southern Region of British Rail(ways) ... trains with doors that the passengers opened and closed for themselves, just like your door at home, without the aid of electrical / hydraulic systems. The doors needed a hefty shove to make them work, as there was a safety catch to work too - so they were known as "slam door trains" ... a name which has transformed into the current term "slammers". In my days, I used 4EPB units (5001 upwards) and with some 2EPBs (5701 upward) to strengthen them, with 4CEP and the occasional 4BEP unit ... with a few very modern (in those days) 4VEP units getting onto our lines around 1970, having spread from the Western and Central division to South East ... the lines from Petts Wood and Orpington outward (School and work at Seiscom) to Sevenoaks from 1966 to 1971 and 1972 to about 1975, and inwards to Sydenham Hill from 1962 to 1966 and London, including the long lost station at Holborn Viaduct, from 1972 to 1976. So there's a huge nostalgia - a childhood - wrapped up in those slammers. The healthy feeling of a door well slammed, the partial and timid half rattle if it hasn't closed properly, which left the handle at 45 degrees as a warning to staff looking along the train that it was not ready to go. In those days, the doors were not centrally locked, but everyone knew the system and accidents were infrequent.
On Thursday evening, I caught the 18:14 from Lymington Pier to Brockenhurst, tipped off that the line is being operated by the very last two 'slammers' running on the main commercial railway network ... and I was not disappointed. A journey back in time - yet still the smoothest of rides, and the fresh sea air wafting through the carriage rather than the air conditioned and perhaps germ laden offering of a hermetically sealed modern unit - I have see numbers like "444" and "450" for the replacements. Some things have changed; the doors are now centrally locked so that the guard (sorry - "conductor") can stop you opening the doors at 60 m.p.h. and the 4CIG had shrunk to a 3CIG, with the intermediate trailer which, as I recall, had doors for every compartment, having disappeared [Added correction - I was thinking that the Lymington trains were 4VEP not 4CIG originally - the 4CIG were on the Brighton line in my days].
From Lymington Pier, where the "Ugly Duckling" ferries run to and from the Isle of Wight, the line crosses the end of the yacht-encrusted harbour. Glorious, picturesque views of the boats, the ferries, the sea and the sky had my shutter clicking through a long series of images which - in the olden days of the CIGs would have meant an expensive bill at Boots for developing and printing. These days it leaves me asking "what can I do with all of these pictures?" some of which - such as this one here - capture the glory of the late summer evening at the British Seaside. The picture feels timeless, but the trains are set to be replaced by something more plastic (and diesel powered during the week, too) from next May, so it's not as timeless as we think. Next year, this picture won't be possible as the 18:14 from the Pier will be a sealed sardine can called a "158" - not a bad train, but not such a loveable one.
With my specific 'practical useage' rather then 'enthusiast' background to rail operation and knowledge, I have posted a follow up thread concerning the background to the switch away from heritage stock here where I am soliciting comment. Although it would be logical to operate the whole network on a few standard train models, there are some odd and unusual issues that make it appropriate at times to leave odd-ball specials (it's always been the case, and there are others such as Cardiff Bay with a 'bubblecar' unit) and I am flumoxed at the need to take a step across (retrograde?) to diesel.
I recall going to an evening's celebration of the local railway service in a town local to us in Wiltshire, and seeing picture after picture of trains - even though we were really there to celebrate the whole railway - and wondering "why". And yet I found myself the other night creating something of a pictorial record of the CIGs ... not only of them at Lymington Pier, Lymington Town and Brockenhurst, but also the trains themselves, the aspects of the compartments which - to this day - I recognise as being so characteristic that show me a picture out of content and I'll identify them. The picture here is the door / entrance. You can tell it's a CIG because of the beading around the door, the lack of an internal latch, the colour of the seats. And I could tell an EPB and the others too. But these memories will fade, so I have put a whole series of pictures, and at far higher resolution that I usually upload, on our "share" pages - you can find them here here and here
Part of my reasoning is the horrid realisation I had a couple of months ago when I was hunting for EPB pictures and they were truely had to find, and the discovery that not one Bullied EPB had been preserved; a unit had been put aside, but had then mouldered. (There is a BR style 2EPB at the East Kent railway - [picture] which would make a fine extra unit on 'the Lymington'. And I'm aware that preservation is life extension, not the creation of a limitless life. See Forest of Dean - comments for example.
Brockenhust is the end of the run for the 'slammers' these days - so after just 10 minutes across the New Forest from Lymington, the train draws to a halt in the segregated bay platform and passengers must change to catch onward services to Southampton, Basingstoke or London, to Bournemouth, Poole or Weymouth, or to Reading, Birmingham and Manchester. The 'Old lady' - Unit 1497 - take a five minute brake, loads in fresh set of commuters, people heading for holidays on the Isle of Wight, before heading off into the sunset down the branch again.
Posted by gje at 02:53 PM | Comments (0)
Related topics: via article database
Two days of demonstration scripts in Python
I've spent the last two days introducing Python to a group of nine delegates (and, naturally, enjoying doing so). As I usually do, I have wrote a lot of new examples to show not only how the language and programs work, but also the thought process behind writing them. At the delegate's request, I have added the examples onto our web site --- linkable by the delegates (and anyone else who cares to take a look) from the following list:
EARLY DEMONSTRATIONS
early python demonstration - using, re-using, copying variables
first real application - simple calculation
FUNCTIONS, FROMs and IMPORTS
A file of functions for 'from' or 'import'
file to be included to bring in application globals
loading application globals
How EVERYTHING is an object - even functions!
Hiding algorithms in functions - 'encapsulation'
Using a generator to avoid a large intermediate list - control
lists of functions, lambdas, callbacks (posh/flexible ways to use functions)
Generator function to prevent need for intermediate list
LISTS
ways of looping through a list
Some early list demonstrations!
Lists, lists of lists, mutable and immutable
generatings lists of 365 elements to convert day of year to month and day
Use of xrange rather than range to avoid huge intermediate lists
Trying to modify a tuple
FILES and OTHER DATA INPUT / OUTPUT
A one-liner to print a file's contents
File read and write - program 'samples' every 10th line of a log file
Reading a file line by line (good for huge files)
Reading a web page 'as if it was a local file'
Running an operating system command via a pipe
STRINGS and REGULAR EXPRESSIONS
Some examples of the % (string formatting) operator
Regular Expression to extract data from log file (and dictionary analyse)
OBJECTS
First steps in Object definition and use
Sample class with test harness too
Converting a file on disc to a list of objects in memory
I will add some notes, based on comments received about some of my examples recently. These are little demonstration programs. I would use standards such as a variable naming standard in 'live' programs - to avoid confusion about spelling and what variables do later. I would comment my programs far better. I would include documentation strings. I would validate user input .... I talk about such things at great length on ALL courses because they are vital! but in some of these early examples, they would extend the course running time and pad out the source code so that it was hard to find the real nubbs!
OK ... If you want to learn Python / see me set up things like this and fully understand the examples, the course you need is Learning to program in Python if you have never programmed before, or Python Programming if you are converting from C, C++ or some other language
P.S. - come back here in a few hours / I'll go through and sort the programs into a more logical order, and add a few comments to the sources. But I know there is one delegate who is BUS-ting to get on ;-) I have been back ... sorted the examples into a more sensible order above, and added comments into most of them so that when you click on the link you'll find them better documented. Enjoy!
Posted by gje at 08:25 AM | Comments (0)
Related topics: via article database
Useful link: Python training
September 04, 2009
A first demonstration of OO, including polymorphism
"Object Oriented" often means big and heavy code even for the first example application demos ... since OO works really well when you're meeting requirements beyond those which are small enough to be described as 'trivial'. So I'm very pleased with this little demonstration in Python which shows - all in one file - the definition of four different classes, the building of a list of objects of various different sorts, and then a loop that goes through all the objects using 'polymorphism' to ensure that the right accessor code is run on the right piece of data.
Scenario - monthly bills need to be multiplied by 12 for the annual cost, Council tax bills come in 10 instalments, and annual payers get a 10% discount.
class monthly:
def __init__(self,xxx):
self.val = xxx
def yearly(self):
return self.val * 12
class annual:
def __init__(self,xxx):
self.val = xxx
def yearly(self):
return self.val * 0.9
class council:
def __init__(self,xxx):
self.val = xxx
def yearly(self):
return self.val * 10
# ----------------------------
david = monthly(25)
john = monthly(14)
gerry = annual(125)
lisa = council(112)
debtors = (david, john, gerry, lisa)
for debtor in debtors:
print debtor.yearly()
Please note - this code is BELOW my minimum standards for a live application. I would expect to see comments, I would expect better variable naming, and I would use inheritance to save the need for a duplicated constructor.
Sample output:
92: grahamellis$ python accts
300
168
112.5
1120
92: grahamellis$
Posted by gje at 07:49 AM | Comments (0)
Related topics: via article database
September 03, 2009
Lymington, New Forest - some pictures
A long day ... but I couldn't want for a nicer crowd to train, nor a nicer town to be in for the evening. The days are drawing in, but I did manage to get a few pictures in the last couple of hours.







More picture ... Brockenhust and the New Forest, Lymington and the trains between them.
Posted by gje at 08:09 PM | Comments (0)
Related topics: via article database
September 02, 2009
Great Western Route Utilisation Strategy - Draft for Consultation
A call from Brunel Radio in Swindon yesterday asked for my to give brief comment on the "Draft Great Western RUS" that had been published 4 hours earlier. But what is a RUS, why is it of interest to local radio listeners {{ and how do people expect me to make meaningful comment on 192 pages within hours of them being published? }}
Let's try for some answers.
What is the RUS? "Route Utilisation Strategy", to give it its full title. It's the long term goals of Network Rail, the public owned organisation who look after the railway's infrastructure, who are looking ahead ten years and further and planning what sort of traffic they expect the railways to be carrying, and so they are looking to plan to have enough track capacity, signalling, etc to be able to handle it.
Why is of interest to local radio listeners? Probably because it's of great interest to anyone who's likely to be travelling in five to twenty five years time. Looking (as thoroughly as time has allowed so far) I have seen alternative diagrams for the line from Swindon via Melksham to Westbury and Salisbury - showing options on one train per DAY and one train per HOUR. That would make such an enormous difference - the difference between a service that is frankly moribund because the outward and return trains are highly unlikely to suit more than a handful of people, and a busy turn up and go type service, soaking up several coachfulls of people every hour.
And it should be of interest to anyone locally because it's now in a consultation period where inputs are being solicited up until mid November. I know I have been cynical in the past about consultations being simply a way that politicians get boxes ticked to say they are doing what the public wants, but I have a feeling here that strong inputs just might help to set the tone. In any case - like your vote - don't waste it!
I can't answer how people expect me to read 192 pages in 3 hours - especially when I have a day job - but I do know that over the next 2 months I'll be delving further into the RUS. I've already opened a a thread on the First Great Western Coffee Shop asking people what the site could / should do to help point forward.
Personally? I'm working forward towards something much more modest, but much shorter term for the "TransWilts" line, about which I'll be saying more in a few days. And I've got meetings on 19th September and 3rd October in relation to the RUS ... good time to work with the other "Coffee Shop" members to formulate a response from the passenger's viewpoint. You may well ask "who are you to formulate such a response" - well, The Coffee Shop has 600 members, the TransWilts campaign has 700 supporters. There's some overlap, but that's well over 1000 people. Small beer, but the overall group has a good age / gender / place / background spread, and I would be looking forlornly around to find any other independent group to speak for so many members of the travelling public.
Pictures - Chippenham Station, showing a platform face with no track; it works while the trains are all on time, but woe betide any train that has to wait here for the single track to Trowbridge. Bristol Temple Meads, where there are gaps of many hours between services at some of the platforms ... and yet major congestion as the 15 platforms funnel down to just 2 lines to Weston, 2 lines to Bath and 2 lines to Filton. And two pictures of Melksham, Formerly a double track line that took in the six largest towns in Wiltshire, there is now but a single track, with but a single morning train each way and a single evening train each way. Rail use growth continues ... services need to be put back in to use capacity and meet requirements, and capacity need to be enhanced in some places to avoid future bottlenecks - and that's what the Rus is all about.
Posted by gje at 05:30 PM | Comments (0)
Related topics: via article database
September 01, 2009
Dynamic / changing images on your web page
There are a number of different ways to provide dynamic (changing) images within a web page ... but as they're mostly client side technology based, they're not something I commonly get involved in. However, just yesterday I was thinking of using exactly such a dynamic image in my post telling you about the new "Of Course", and this morning, completely disconnected, I have a question on the subject in my mailbox.
So ... there are a number of ways to produce dynamic images:
• using animated .gif files where the various frames are built into one image (but note that the .jpg standard does NOT have the capability)
• using JavaScipt (see source and running example
• using Flash (Example here on Well House Manor site)
• using a server push or client pull slide show ... you can see that sort of thing source code here and running here.
I'm not going to start putting working copies of each of those techniques in this article ... too many moving images can make for a somewhat annoying page, and I have yet to find a manufacturer of dynamic paper on which you can print them and keep the movement ;-) ...
Posted by gje at 02:47 PM | Comments (0)
Related topics: via article database
Writing with our customers words
I write "Korn Shell" rather than "ksh", and "regular expression" rather than "regex". When it comes to "new lines" there is a gap between the words - I don't write "newlines". I try to avoid using words like "today" as I write, as that leaves the reader scrambling for the authored date - on the same lines, I chuckle at the street name "New Road" in Chippenham, which is now attached to a street one of the more mature parts of the town.
All this is to do with the longivity and professional look of the site, but it does have it's down side - it's not all a bunch of daffodils. For search engines trawl our site, and index us under the words we use, rather than under the short hand and abbreviations that others use ... and where we should be better found, we may not be.
Analysing our log files (we use the Apache http Server's combined format rather than the common format), we can see the search terms that people used prior to following a link to our site. Where that search term contains a start= parameter, we're being told that this wasn't a first page hit ... and where someone has gone to the trouble to navigate forward from the first result page, it indicates a determination to find material that's not quite as easy to find as one might expect and if the search terms are ones that are indeed relevant to our site we should take a careful look at our wording.
I remember some of those English games at school that I was so bad at - making up a story with certain words or sentences in it. And I wonder if I should try that here - writing a blog that includes "Choosing implementing newlines save text rename today dynamic cpu display ksh regex" ... all of which are relevant words or abbreviations coming up on secondary result pages. The problem with THAT is that it might help bring people along ... but under the wrong wording.
If you have arrived here via a search, using some of the words that I have mentioned, you'll be wanting to click on one of the following links ;-)
programs implementing vector class in java
mysql query result save in text php
choosing an image to display and html
perl count newlines
java programme to find a substring in main string
rename database mysql
perl get today's file
jigsaw source code c++
increasing cpu tomcat
java two dimensional dynamic array
image php display
unix ksh for loop
ksh regex example
windows and perl
linux administration with bash and perl scripts
There are, Of Course, some search terms where we are rightfully on an obscure back page. Hatfield to Central London commuting isn't really what this site is about, people looking for horse fountain may not find what they're looking for, and I really don't want too many people arriving via a search for sample of a draft letter to the company requesting training make a booking and ask for discount, since our training course pricing policy is to offer a single COMPETITIVE price in the first place, rather than to pitch it high and then offer a wide a complex range of reductions. See here (public courses) and here (private courses)
Posted by gje at 07:59 AM | Comments (0)
Related topics: via article database