« July 2009 | Main | September 2009 »
August 31, 2009
`Of Course` is back!
When we started running Perl and Java courses on our own account, we launched the "Of Course" newsletter - a printed piece that rose from 12 to 24 pages in six years, at two editions per year. The latter printed editions were also available for .pdf download as overseas postage costs rose ... and indeed we moved over to electronic means to stay in touch with our customers - primarily through our web site ... as UK costs grew, and postal distribution became a less and less effective way to reach our customers.
But our customers keep telling us how much they enjoyed "Of Course", with its mixture of programming tips and examples, and news of our courses and from Melksham. And we have a lot more news now too, as we opened "Well House Manor" - our new training centre with accommodation - shortly after the last printed piece.
So I'm very pleased to be able to announce the return of "Of Course" - now in purely electronic form - to be published six times a year (every two months). The new "Of Course" takes advantage of the interactive media, allowing to you explore articles that have been added to our web site in each two month period (mainly via my blog) on subjects that are of interest to you ... we have moved a long way forward since we just did Perl and Java (in those days, I thought that Python was a type of snake from Burma, and that a Tomcat was a male feline!)
The current - new - 'Of Course' is available here, with editions for July 2009 here , for May 2009 here and for March 2009 here (and you can step right back through 2008 and 2007 if you wish! Th eissues from 2006 right back to 2002 can be downloaded from here, and you'll find a list of contents for all the printed editions here ... as of writing, we still have a handful of copies of even the first issue.
Posted by gje at 08:24 PM | Comments (0)
Related topics: via article database
More about Graham Ellis of Well House Consultants
August 30, 2009
to Clifton Down and Avonmouth
The pictures I took today are more "record pictures" than ones of any artistic merit or prettiness - we took the day out, and headed for Avonmouth because, like Everest, it's there. I didn't much know what to expect, and the threatening mills that tower above the skyline were dulled for the photographer by the dullness of the day, the station bright in parts yet the railway weed-ridden, and the trains amongst the oldest and most basic running on the main railway system of this country.
Yet there is still a beauty in the curves of the tracks as they bend into the tunnel under Clifton Down, the green of the trees surrounding the cutting and the black circle of the tunnel.
And here and there a bright splash of colour ... here at Montpelier Station where the Graffiti painters have turned to artists.

Further pictures - Avonmouth and Clifton Down.
Posted by gje at 09:44 PM | Comments (0)
Related topics: via article database
August 29, 2009
Computing under the influence of alcohol
If you're a forum moderator, or (as I do) have an enquiry page, you may have noticed how the tone / approach of your members varies at some times of day. Occasionally, it's that the messages are terse in the morning and late afternoon, but longer at other times of day - that's explained by the use of a mobile device while travelling, but a regular keyboard at work at home. But more usually it's the messages in the evening through to those 'early hours' times where you're not sure if the poster has had his / her night's sleep yet, or not, that look different. And the behaviour change can often be explained by the use of recreational drugs, in which I'm going to include alcohol.
"Sorry, Graham - I'd had a couple of jars of ale ..." said a personal message that I received the other day, after I had contacted a forum member to point out that one of his posts could be read as a personal attack on another member. It was in contravention of our Acceptable User Policy (AUP) and the policy of almost every other forum (even if some pretend otherwise), and whilst we all enjoy a drink from time to time, that doesn't make allow us to then post to a different rule set.
Identifying the species
There seem to be various forms of behavioural changes when 'computing under the influence'.
• The honest. The guy or gal who shoots his mouth off - in many ways saying what others may be thinking about the attitude of another member, but going so far as to express that view in a very personal way so that it becomes (technically) a libel. There's a subspecies too, where the honesty comes out with regard to the disclosure of their own personal data. "Where did you learn THAT" they say the next day. Answer "you told me last night!"
• The confused. Some people's posts are hard to follow at the best of times ... but come to the REALLY incomprehensible one and have a look at the time it was posted. There's likely to be a further clue sometimes along the lines of "this came up in a pub quiz". Yeah - right ;-). And unless our confused drunk also falls into one of the next two categories, some really interesting threads can follow.
• The critical. I recall a local woman I used to know for whom there were two ways of going about any task - there was HER way, and there was the WRONG way. But she was quite the exception in that she was like that when sober (well - I don't THINK she was always drunk). There was a degree of validity in some of her ways - they had their merits - but they also had flaws. And we had to waste the most extraordinary amounts of time when she reported us to the authorities for doing things the wrong way which ... after long investigation ... turned out to be perfectly valid. There are those people who will post, or email late at night or fill in web enquiry forms telling you what is wrong with your site. They're always worth reading, but always with a pinch of salt and a strong spread of balance too.
• The aggressive. The woman or man who picks a fight on a forum or by email. Not intend with being critical, they'll threaten you with the law if you 'curtail their freedom of speech', or they'll threaten to 'get you' in a bullying way. Enough said ... very distasteful. Some will just 'moulder' - refuse to do anything (and perhaps not even answer when they get a polite message back), but then look for an opportunity to get their own back on their next binge.
• The ballistic. From time to time, a member's patience snaps on a forum. They get tired of waiting for a fix to technical issues, they get to disagree with the behaviour of other member(s) so strongly that they 'go ballistic'. When you're sober, you send a single email if you want to complain about things, but these Dicks will send 12 copies of the same thing by email, or paste the same block of text, perhaps with different subjects, all over a forum. Oh - and that block is very likely to show them to be honest, critical and aggressive too - it's unlikely to be an advert for the local Carnival. The ballistic drunk's salvo usually backfires ... the 'self destruct' button that forces the web site admin to ban them, and they can be observed for weeks or months thereafter pathetically knocking at the door in case their ban has expired.
• And finally you have the quiet ...the person who you won't see as a problem, who won't waste the moderator / support person's time, but potentially needs and deserves more understanding and support - in serious cases - than all of the others. There are times I can see people hanging around forums / reading blog entries, without comment, for hours on end. And perhaps they then quietly disappear.
How to handle the species
So there you have ... some thoughts (from experience rather than theory) on identifying 'the beast'. What if anything can / should you do?
When I told one batch of rough diamonds that they were making life for everyone else uncomfortable, and taking up a lot of the moderators' time in sorting things out, they suggested that we should simply forward all the emails / messages of complaint to them so that they could answer. That is not an idea that I could go along with!
Another suggestion was made that serious posting breaches should be forgiven for a certain member "because he was drunk at the time". Again - that is NOT one I go along with. In fact, if I were to agree with that, I would be suggesting that drunk driving was OK if the person driving was so drunk he didn't realise he was a danger. It's an abhorrent concept.
I don't think there's any 'one size fits all' solution; 'confused' and to some extent 'honest' and 'critical' can be accepted / even acceptable, and 'quiet' needs no immediate attention but - I have one possible person in mind - is important not to forget. Other cases, perhaps, need a more careful look, and a studying of 'why' to decide how to follow up if at all.
A case study
Let's face it - with over 14,000 visitors to our web site each day, there are bound to be people in all sort of places, at all sorts of times of day, in all sorts of clothing (or perhaps unclothing), hungry and full, rich or poor, and sober or not. And it really doesn't matter to us until they contribute, or pose a threat - and that is only about one in a hundred thousand - rare, but not that rare. Here's a case study
At 21:22 in the evening, a message pops up in my mailbox from someone who I've never corresponded with before, let alone met on a professional basis. He writes: "Thus I now can't help but wonder exactly why you chose to publicize a bit of code that contains large amounts of terrible code patterns? (lack of strictures, warnings; indenting pattern, size; non-scalar filehandles; lack of use English; use of and to emulate if pattern; unclear variable names; flaky use of parens)". Ah - critical, and the time of the evening has me wondering about his state of mind. His message goes on "While this post contained exactly one novel concept for me, the whole rest of it, as it is now, is more than enough to not only steer clear from your services, but also recommend any acquaintances who might consider making use of your services to do the same." OK ... honest, confused and aggressive too.
Part of the tragedy of the confusion is that my correspondent was too confused to have read the bits that say that our examples are reduced in size to demonstrate how mechanisms work (thus - no strict, no warnings, no error handling, no traps for huge input data files ....) and are written during the course to show the type of code delegates will have to maintain rather than some sort of perfect code which few of us (and I suspect not my correspondent "C") would even write. Truth be told, I'm rather surprised that someone who (it later transpires) claims to a be a Perl Guru would find even one novel concept in the code - it was after all a teaching aid and he should have known all of this already
I wrote back the following afternoon, explaining these things in rather more depth than I have done above And I added I have gone back to my article as a result of your email, and adding a brief comment to the above effect - and it's probably something I will expand on in coming days. I would also like to invite you to see what we do for yourself one evening - our delegates come from far and wide, and so we also offer accommodation. Your room will be complimentary for the night - please do arrange a mutually convenient date ahead of time, though, so that I can ensure that I am around and that a room is available.
And I have heard nothing since.
But I do have my server log files to hand ;-) so I went back and reconstructed events
This is what happened - in order
C's very first arrival on our site was at 21:00 on 25th August; his 'referer' was not defined - so it was perhaps a link in an email someone sent him, or he pasted the URL or has set up his browser to hide referers. I don't know about that latter, as there were referers in following URLs.
After looking at a couple of pages, he called up the ask me a question page and 21:12, and took until 21:21 to complete and submit it. He got the "retype this word" (Captcha) right first time ...
After the had written to me, he called up my blog and probably had a good read, as he linked on from it to a course description at 21:47, then all went quiet.
Had he gone to bed?
No - he was back again at 01:30, following a link from a forum where he'd posted a link to our page, and his criticisms too. Hmmm - if I had written to someone to criticise their page, me thinks I would have the good grace to await an answer before slagging them off in public. But of course, if I was a critical drunk I would have probably written a stinging post, secure in the arrogant confidence that I was right ...
And again, at 4 O'Clock in the morning he's following the same link. Looks like a long and lonely night. A completely hypothetical suggestion ... the activity would fit with a falling out with a girlfriend early in the evening, getting drunk and aggressive with friends, and coming home looking to find people to pick on online!
Chronologically, the next events were my adding to the post to make it clearer what it was (and was not) intended to be, and to take some time to explain to C, and to invite him round and clear the air.
I can be pretty sure he got my email - for 30 minutes after I sent it, there was a visit from the same IP / browser to exactly the two pages I had mentioned in the email. Not entirely surprisngly, he didn't bother to acknowledge my email - and that helps me make a further personal judgement of the sort which is against my normal posting policy.
Follow up actions - case study
Will I follow this up further, perhaps posting onto the forum where we were slagged off? No - it's yesterday's story - looks like we were clicked through to about 100 times, and one sad guy's opinion, expressed at a time and in a way that leads me to believe he may have been 'under the influence. But then his story seems to have disappeared, leaving debris of just one comment from A.N. Other - so I suspect that the moderators jumped on him, or perhaps he did an "oh sh*t - what did I do" and tidied up himself. Whichever, he has provided himself as an excellent research subject for seeing just how much you can learn about people on line - it's been a fascinating, and relaxing 'game' or 'puzzle' of the sort I enjoy.
The program that all the fuss was about? It works well, tells me where the biggest file is within a big directory structure - exactly what it was supposed to do. After all, Perl IS the "Practical Extraction and Reporting Language", even if there are some folks under the mis-apprehension that the "P" stands for "Perfect".
Follow up actions - in general
Most of us have "a jar of ale" from time to time - yes, I do as well, and we mostly know our limits when we have had a drink. I will certainly post very little once I've had even a glass of wine, but there have been evenings where a critical issue has left me little choice.
What rules would I want applied to *me*? How does the boot look on the other foot? Well - it calls for an understanding forgiveness the first time for newer members (ballistic excepted?) , and a similar understanding foregiveness for regular members who step over in an unacceptable way just occasioanlly. I'm against a "three strikes and you're out" rule as it seems very biased - excluding the longstanding member who has made 3 errors in 1000 posts, but forgiving the newer member with 10 posts who personally attacked in his 8th post, was guided by the moderator team, and did the same thing in his 10th.
At this level, the problems / issues raised are eminently discussable and resolvable with good humour - sometimes good gets better as well as bad getting worse, and I'm very happy with som eof the loosening effects of alcohol.
But ... once it goes ballistic, once it's agressive then it has to be "sorry - but we have better things to do with our time". An apology can help - something that indicates that we're not just going to go round the same loop next Friday night. On the other hand, threatening emails rather confirm a ban - and a permanent one. But you still have to watch your back. "Imitation is the sincerest form of flattery" they say, and I still smile when I think back to the days I found a grahame posting on another forum, somewhat along the lines of what I would write but grotesquely extrappolating my views. 6 trains a day to Melksham would be sensible. 6 an hour, 24 hours per day - err - is getting a bit silly!
Posted by gje at 01:20 PM | Comments (0)
Related topics: via article database
Reading all our recent news from a single source
1. We've stickied a recent news article on the from page of our site for a while, using the some ewhat mild (some would say inane) text "Recent Article". It's all been good stuff there - upcoming schedules, special deals for delegates, information about how our product really is different and how we look after our customers - hotel, conference and training - making sure that they have a productive and pleasurable experience. What a shame that the inane text has hidden the best articles.
2. Let's face it ... whilst there are an encouraging number of good friends and interested parties who follow the blog on a regular basis, there are many other for whom "daily" is an order of magnitude too often, and even "weekly" is far too much. But those "many" are also our ambassadors, and want to be updated from time to time.
We suspended the Of Course magazine that we had published, twice a year for six years, as this blog took off. Printing and postal costs had risen, and the technology of paper distribution was moving from "old" to "archaic" - and in our internet line of business it really wasn't the way for the future.
'Of Course' is back! It's published bimonthly ... available for viewing from our site, and I'll be notifying regular clients by email. Current edition here and other recent editions ... July 2009 • May 2009 • March 2009 • January 2009
November 2008 • September 2008 • July 2008 • May 2008 • March 2008 • January 2008
November 2007 • September 2007 • July 2007 • May 2007 • March 2007 • January 2007.
Some threads are coming together. I have long talked about using blog articles to put together a regular newsletter - allowing us to reach our customers and prospective clients every couple of months, and providing a link-based system where those of you interested in staying at Well House Manor can link easily to recent articles on that subject, Webmasters and moderators can look at their section, and if you're into Perl or Lua or Python ... there will be a link to a section on YOUR language, without rubbing your nose into my ramblings on Java, Tcl or Ruby!
Stage 1. There's an experimental system up ... link to new, current newsletter. It includes a recently selected "keynote" article that's general, topical and looks forward to the next two months. And also the titles of the five most recent items on each of around 20 subjects so you can find out what else has been going on all from the one page.
Every 2 months, I'll be 'freezing' a newsletter ... so you can refer back if you want to July 2009, May 2009, March 2009 and so on - indeed you can go right back to 2005 if you want (May 2005 for example).
By having an interactive system, we can do much more too. If you find a 'track' that's particularly relevant to you, you can open it up - even at Stage 1 - and see all the previous articles from earlier newsletters too. And beyond stage one, we have all sorts of possibilities such as a regular (2 monthly) mailing, the ability to expand articles in situ and to give precise, and more.
Posted by gje at 09:18 AM | Comments (0)
Related topics: via article database
August 28, 2009
Looking ahead to the Autumn season of training and accommodation
This Autumn, we're running our regular public training courses at Well House Manor - courses in Perl, PHP, Python, Lua, Ruby, C, C++, Tcl, MySQL, Tomcat and Linux [schedule - link]. We still have a maximum group size of eight delegates, we still use our own notes - it's a tried and tested formula through which we train hundreds of delegates each year, so there are no major changed - just minor developments such as our "learning to program in ..." courses which provide extra supportive help for complete newcomers to programming. Prices remain very competitive too, whether you live near Melksham and can commute, or if you stay with us at Well House Manor.
Our Business Hotel - Well House Manor - continues to attract business visitors to Melksham, and we're getting to know quite a number of 'regulars'. For visitors to businesses at Challymead, Hampton Park, or Bowerhill, we offer easy-access nearby accommodation, close to the town centre and will full business facilities. A lighter breakfast ensures you're fresh for the day, and being a business hotel you can come and go as you please - from really early to really late.
Onsite courses (we'll come to you for groups of 5 or more delegates, worldwide), Rooms for business meetings, and leisure hotel guests are also important parts of our ongoing business ... and we look forward to being busy all though to Christmas!
Posted by gje at 08:23 PM | Comments (0)
Related topics: via article database
Lua Regular Expressions
OK - don't believe the headline - Lua doesn't support "Regular expressions" but it does have pattern matching. Why? Because Lua is designed to have a small footprint, and a conventional Regular Expression library would be 'bloat' - the pattern matching that's provided looks similar, and offers 80% of the facilities in 20% of the code. (See the 80 / 20 rule).
You'll find an example of Lua pattern matching here in our courseware examples. A Lua pattern is a string that may include:
• Literal Characters to match exactly - e.g.
Letters, digits and many special chars match exactly
%% means really match a % character (similar for other specials)
• Character groups to match any one character from a group - e.g.
[aeiou] for a lower case vowel
%d means a digit
%a for a letter
%u for an upper case letter
%l for a lower case letter
%s for a space
%S for a non-space (and other capitalisations for opposite groups)
• Anchors to say if you're looking at the start or end of a string - e.g.
^ means "starting with"
$ means "ending with"
• Counts to say how many times to match the previous character - e.g.
+ means one or more of the previous item
? means zero or 0ne character
* means 0 or more or the previous item
- also means 0 or more of the previous item but is SPARSE
• Capture parenthesis to indicate interesting bits to save
There are some examples of iterating through a string to match patterns in Lua here.
Lua's pattern matching is covered on both our Learning to Program in Lua and Lua Programming courses. Illustration - on a private Lua course
Posted by gje at 12:47 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
Giving up on user input - keyboard timeout in Perl
There's an old piece of code that I've used to demontstrate how (in Perl) you can prompt for a user input ... but then time out the input on an alarm signal if the user doesn't enter data within a certain time. The code's [here] if you want to have a look. But let me warn you ... it's one of those thisng that may be somewhat operating system dependent, even though most Perl code is pretty darned portable.
A correspondent writes: "try the code; it hangs after the first warning. The comeon signal handler needs to call the alarm and increment the counter because the code in the main loop that looks to do so is never reached when no entry is typed. a correction would look like [this] (good exercise for student, by the way, so thanks)"
Hmmm ... on the laptops that I'm working on today (Mac OS X / Perl 5.8.x) both versions work perfectly. The second version (from M.K.) illustrates his point, but with a degree of code duplication so it could really do with being tidied up ... and I have not yet tested it across a range of platforms. I'm posting links to both examples, and these notes, because waiting for a user input ... but only for a while, before carrying on ... is a very useful capability, and these notes may be of some help to the reader, even though I have not fully researched the story.
What is does remind me of is that saying:
and the need to check and recheck code across platforms, and HTML and JavaScript across browsers!
Posted by gje at 10:55 AM | Comments (0)
Related topics: via article database
Useful link: Perl training
Checking the database connection manually
For an initial database connectivity test from my own code, I use the mysql client program and 'check out' the commands manually through that. Noting all the parameters, I then check through a piece of code in my target language ... in this brief example from Wednesday, it was Perl:
use DBI;
# From my manual test:
# mysql -h192.168.200.84 -utrainee -pabc123
# use wellho
# select agid,locate,sid from sales
$db_handle = DBI ->
connect("DBI:mysql:wellho:192.168.200.84","trainee","abc123")
or die ("connection failed: $DBI::errstr\n");
$qu_handle = $db_handle -> prepare("select agid,locate,sid from sales");
$qu_handle -> execute;
while (@row = $qu_handle -> fetchrow()) {
print "@row\n";
}
One of the most common questions I get by email from people I have never heard of before relates to getting 3rd Party software running on their own systems. And one of the most common solutions that I suggest is checking out their database connection - changing sample MySQL accounts from user "hello" and password "world" to the name of an account that exists on their system ;-). A short test such as the one above, and done with the knowledge of what each step is doing, can identify these initial connection problems very quickly indeed.
Posted by gje at 04:33 AM | Comments (0)
Related topics: via article database
August 27, 2009
Object Oriented programming - a practical design example
Object Oriented coding makes enormous sense when you're looking at a medium sized or larger application - but it's a complete change of thought process for the traditional structured programmer.
We ran an Object Oriented Programming in PHP course today, and the course concluded with me taking some sample data - web access logs - and starting to specify the classes suited for handling thet data for a variety of reports. Source code is [here].
You'll see that the example is all in a single file. Yes - it is, but that's just for initial testing; the first program is really no more than a test harness to make sure I have the object descriptions right. Before a program based on these classes went live, the classes would be split out into a separate required file ... but NOT to three separate files, as would be the case with a Java application.
As we read in records from the log file, we have to interpret them to make up visit objects. The "bull at a gate" approach to that would be to analyse the records in the main code, at least until we knew what type of object we were going to create. However, I have chosen to code a utility (factory) method within the code that will be within the class file - that way, the analysis code will be shareable between many programs, and will be hidden within (encapsulated in) the class structure. It all leads to a very simple main program file:
$rtab = array();
foreach (file("../weekend/ac_20090522") as $lyne) {
if ($obj = addrecord($lyne)) {
$current_ip = $obj->getip();
if (! $rtab[$current_ip]) {
$rtab[$current_ip] = $obj;
} else {
$rtab[$current_ip]->merge($obj);
}
}
}
foreach (array_keys($rtab) as $king) {
$fp = $rtab[$king] -> getfirstpage();
$pc = $rtab[$king] -> gettimes();
$wot = $rtab[$king] -> getwhat();
print ("From $king - $pc pages. Arrived at $fp - $wot<br>");
}
On our Perl course, we have a section labelled Design MATTERS. How very true - and how very true in PHP as well!
Posted by gje at 05:30 PM | Comments (0)
Related topics: via article database
Making variables persistant, pretending a database is a variable and other Perl tricks
Have a look at this Perl program:
use fyle;
tie $counter,"fyle";
$counter = $counter + 1;
print ("This is access no. $counter\n");
Apart from the rather curious module loaded at the top, this seems to take an undefined variable, set it to one, and print it out. What a - err - pointless (!) program. But:
Dorothy-2:pl grahamellis$ perl bowtie
This is access no. 11
Dorothy-2:pl grahamellis$ perl bowtie
This is access no. 12
Dorothy-2:pl grahamellis$ perl bowtie
This is access no. 13
Dorothy-2:pl grahamellis$ perl bowtie
This is access no. 14
Dorothy-2:pl grahamellis$
What is happening?
Deep within Perl, there are a very limited number of operations that can be performed with a scalar - it can be created and destroyed, it can be read and written ... and that's about it. And these operations can be redefined by a class, and then applied to individual variables via a tie command ... which is what I have done here.
So in my example, the variable is persistent. Inside the class, it's actually stored in a data file that is read each time the variable is read, and overwritten each time a new values is saved to the variable. So it lasts from one run of the program to the next.
The source code shown above is also available here, and the definition of tieing a variable to a filecontents is here.
You can do a lot more with tieing. We have an example of connecting to a flat file database (NDBM) here (that calls up a standard tie class shipped with Perl). There's an example that forces strings in a variable to always be treated as lower case here and here. Finallly, a tie class which maps a file to a hash here.
Another new example / Perl trick ... see here for a short example / explanation of binary data handling in Perl
Posted by gje at 07:06 AM | Comments (0)
Related topics: via article database
Useful link: Perl training
Handling XML in Perl - introduction and early examples
There are hundreds of modules (literally) in Perl for handing XML. Some of them are highly specialised, but others are of much more general use in reading (and in some cases writing) XML streams.
(definition of XML: Extended Markup Language - a tagging system in plain text for marking up data; not really a language, but rather a METAlanguage as it defines the format of the tags, and not which tags are and aren't valid! example of XML: An RSS feed such as [this one] from the blog)
There are really two major 'classes' of XML handlers - those which as "SAX" - a Simple API for XML - where certain data elements trigger a piece of code to be run as the data is traversed, and "DOM" - Domain Object Model - where the data gets stored into memory in a structure within the language - Perl in this case.
Here's a simple SAX style parser example in Perl:
use XML::Parser;
$parser = new XML::Parser(Style => "Subs", Handlers =>
{Char => \&spew} );
$intitle = 0;
$parser -> parsefile('index.xml');
print "done\n";
sub title {
$intitle = 1;
$ti_data = "";
}
sub title_ {
$intitle = 0;
print "We have \"$ti_data\"\n";
}
sub spew {
$intitle and $ti_data .= $_[1];
}
The parser is set up to run the sub of the same name as each tag it enters, and to run a tag of the same name with a trailing underscore at each exit. Only subs for tags of interest need be provided. A separate handler is used for data which come between the tags, and in my "basics" exmple, I have simply used a global within my entry and exit subs to not when I am (and am not) within text or interest. I have pasted sample output onto the end of the full source code.
Additional options in the hash passed into the parser constructor allow you to place all your callback subs in a separate package (the pkg member), and of course you should comment you code well / consider using strict / have better sub names than "spew" ;-) ... my example is (as they mostly are) intended to show the mechanisms and techniques and not fully armoured, heavy, production code.
A SAX parser is a great way to handle large flows of data for extracting just a few specific, but it is not well suited to reforming / editing a piece of XML - for that you need a DOM like model. And the XML::Parser module lets you do that too. Parse as follows:
use XML::Parser;
$parser = new XML::Parser(Style => "Tree");
$struct = $parser -> parsefile('index.xml');
And that creates a list within $struct (which is a reference) of elements, each of which is itself a further list to represent the hierarchy of the tags in the XML, or is a scalar (for data) or hash (for the attributes of an open tag). Handling this structure can be done with quite a short piece of code, but it needs to be recursive / re-entrant, so great care needs to be taken to ensure that my variables are used where the levels are distinct, and our variables / globals / or parameters where data is passed between levels. I have placed an example of such code [here], showing how the same sample RSS data is loaded into memory and then used.
Other modules to handle XML include XML::LibXML (short example [here] and [here - saving changes to an XML document]) and ... in top of that ... XML::LibXSLT, which applies a transformation based on directives is the XSLT language to an XML data set.
With XSLT, the Perl code can be short:
use XML::LibXSLT;
use XML::LibXML;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file("camels.xml");
my $style_doc = $parser->parse_file("camels.xsl");
my $xslt = XML::LibXSLT->new();
my $stylesheet = $xslt->parse_stylesheet($style_doc);
my $results = $stylesheet->transform($doc);
my $output = $stylesheet->output_string($results);
print $output;
See [here] for full source, and [here] for the XSLT specification of the transformation and [here] for the data.
You'll note that XSLT is a programming language itself .. which is an implementation of the XML Metalanguage. In other words, you'll find that even programming structures like loops are defined via tags - from <foreach> through to </foreach> for example. It feels odd and confusing when you first see it - but actually it's a brilliant concept as it means that your language syntax analyser is already written and in use on both that program and the data the program is dealing with.
We do not offer separate XML courses, but we do cover XML on language courses such as Perl for Larger Projects on which the new examples above were written yesterday.
For Python programmers ... the principles are similar. Here are some source examples:
Using SAX (via the standard SAX handler shipped with the Python distribution)
Using DOM (via minidom, also shipped!)
XSLT example in Python, using libxml2 and libxslt.
Posted by gje at 06:21 AM | Comments (0)
Related topics: via article database
Useful link: Perl training
August 26, 2009
Wiltshire / Melksham Weddings - guest accommodation
Let's face it - it's the big day for the bride, and the last thing she wants to be worried about it where her more geographically distant friends and relatives will stay, whether they can get into their hotel rooms early to change before the wedding, and about their other needs. We're getting very familiar with making things very easy ... for both organising brides, and their less-than-organisable extended families. Here's how we do it at Well House Manor in Melksham.
* Let us know early about your wedding, and that you'll be having a lot of friends and relatives stay with us.
* Until 3 clear calendar months before the big day, we'll take telephone bookings, and bookings ONLY from people coming for the "Smith / Jones wedding", for the night in question. These will be subject to our usual terms and conditions, and prices.
* If we're more that 2/3 filled by your guests, we'll turn away any other business for that night, ensuring you have Well House Manor as a private venue
* If we're over 4/5 filled by your guests for the wedding night, we'll only charge them our lower delegate rate for the duration of their stay - that's currently a saving of 20 pounds per night on double rooms.
We'll make every attempt to have as many rooms as possible available for early checkin for guests arriving to change prior to the wedding, and we'll guarantee that at least some rooms will be available much earlier than the usual checkin time. If your guests let us know when we should expect them, then we can make (and promise) individual early arrival arrangements at no extra charge. We can also book transport to the wedding venue from Well House Manor, allowing your guests to leave their cars with us.
Well House Manor offers five double or twin rooms. We are happy to let the rooms for single occupancy, but regret that we cannot accept guests under the age of 14. All rooms are en suite, furnished to a very high standard, and are accessed by a 24 hour keycard system which will also give to access to the hotel at any hour throughout your stay.
Posted by gje at 05:03 AM | Comments (0)
Related topics: via article database
Long job - progress bar techniques (Perl)
Here's a "Perl for Larger Projects" example --- for use in illustrating the "advanced file and directory handling" and "handling huge data set" modules.
Scenario ... I want to go through all the files and directories on a big drive, and find the largest file(s). It will take a while, so I want progress reports, and I want to be able to suppress and ^C (control C) inputs by the user so that the program can't be stopped without very specific actions.
Let's look at the code section by section.
Firstly, set up the %SIG hash so that the ^C signal runs a function called jose and the USR1 signal sets a flag to indicate that it's been received (you rarely do very much in a signal handler, as you don't know exactly when it will be run - it's usual just to get a flag).
sub jose {
print "No way!\n";
$jose_counter++;
die ("\nInsistent little toad!\n") if ($jose_counter > 2) ;
}
$SIG{"INT"} = \&jose;
$jose_counter = 0;
sub sofar {
$sof = 1;
}
$SIG{"USR1"} = \&sofar;
$sof = 0;
print "My ID is $$\n";
Set up a queue to contain a list of all the directories to be traversed. We'll push new directories we find onto it, and we'll shift ones that we've already covered off it ... so that when the queue is empty, we know the whole traversal has been completed. A queue like this is far easier to implement than a circular buffer with two pointers, which is the 'conventional' way of doing the job.
@queue = ("/Users/grahamellis");
$biggest = 0;
$occasional = 0;
By default, Perl buffers output. We want it to flush its buffers every time it write to STDOUT, so that our progress reports come out in a single stream and not spurts of 4k characters
$| = 1;
Get a directory off the list, and read all the things (symbols) it contains:
while ($current = shift (@queue)) {
opendir (DH,$current);
@things = readdir DH;
Loop through the contents ... eliminate the current directory and the parent directory (this is done to avoid an infinite loop of directories) and then check if the item is a directory. If it IS, add it to the queue to be handled later.
foreach $item (@things) {
next if ($item =~ /^\.{1,2}$/);
$filename = "$current/$item";
if (-d $filename) {
push @queue,$filename;
next;
}
Not a directory, so look at the (file) size. Because we just did a -d operation on the file, we can now just use an underscore with the -s; the _ instructs Perl to reuse the results of its last enquiry from the file system ... it will have buffered up all the stat information.
If the file is larger than any already checked, make a note of the name and size:
if (-s _ > $biggest) {
$biggest = -s _;
$bf = $filename;
}
}
Do we need to update the status line? We have chosen to do so once every 50 directories parsed, reporting the name of the latest directory and queue length. We have very strictly ensured that the report will always be the same number of characters long, so there is no chance of "droppings" being left on the end of a report line, and we have used \r to give a carriage return without a line feed.
$occasional = ($occasional + 1) % 50;
if (! $occasional) {
$cur = $current;
length($cur) > 25 and
$cur = substr($cur,length($cur)-25);
printf "Q len %4d - %30.30s\r",@queue+0,$cur;
}
If the USR1 signal has been received during the latest cycle through the loop, report now on the largest file so far, and turn the reporting back off (the signal wants to say "report once" rather than "report every cycle from now on" after all!)
if ($sof) {
print "\nSo far - $biggest, $bf\n";
$sof = 0;
}
}
And at the VERY end, print the results!
print "\nbiggest is $bf, sized $biggest\n";
Full source code [here]
Update - added 26th August I have received an email overnight from a gentleman who points out that my Perl code (above) fails to "use strict", makes poor use of file handles, uses variable names that aren't very good, and so on. He's right - it wasn't claimed to be an example of excellent practise.
The code was written during a course earlier this week, illustrating points as I wrote it, and showing the mechanisms involved without overburdening the source with extras. As usual, some of my delegates have existing code that they have to maintain, and some of the less commonly used structures in my example are there to illustrate those structures ... not because it's necessarily a good idea to use them in production code. If you follow the link to the full source code, you'll find further details as to what this example is (and is not) intended to be.
Posted by gje at 01:16 AM | Comments (0)
Related topics: via article database
Useful link: Perl training
August 25, 2009
Designing your data structures for a robust Perl application
Whatever language you're programming in, design of your data structures is important. You should consider such design ahead of time, and before you start to code - "What am I going to be doing with this data" and "how do I want to access it".
It is easy - VERY easy - to fall into the trap of staring to code without adequate thought (and a diagram) and in language like Perl (especially) which assumes you know what you are doing, and where a few bytes of code can do a lot of work, you can so easily head for trouble if you're unplanned.
So here is a piece of PLANNED code! I am going to be writing code to analyse a log file. It's a web server's access log file, where each request is a separate line in the file, with the first field on each line identifying the visiting client computer.
My data design:
• I want a HASH, keyed by the visiting client computer's identity (IP address).
• the values in that hash are to be references to a LIST of accesses from that client and
• each access record is itself to be a list of individual strings from the incoming access records.
So - in summary - a Hash of lists of lists.
Design done - let's NOW write the setup code!
open (FH,"ac_20090818") or die;
while (<FH>) {
my ($thisip,@otherparts) = split;
push @{$all{$thisip}}, \@otherparts;
}
Do not be mislead by how short that code is - it really does set up the three-tier structure I described. What a good job I HAD described it, though, so that it's easy to handle. Let's now test it, by printing out part of one record and also a summary of the number of visitors:
# For IP address 77.88.28.246, look at the
# 7th hit and tell us the 6th fld.
print ${${$all{"77.88.28.246"}}[6]}[5],"\n";
print $all{"77.88.28.246"}->[6]->[5],"\n";
print $all{"77.88.28.246"}[6][5],"\n";
@visitors = keys %all;
print "Visits from ",@visitors+0," places\n";
and running that:
Dorothy-2:pl grahamellis$ perl actab
/mouth/834_Python-makes-University-Challenge.html?headline=_200
/mouth/834_Python-makes-University-Challenge.html?headline=_200
/mouth/834_Python-makes-University-Challenge.html?headline=_200
Visits from 14872 places
Dorothy-2:pl grahamellis$
What if your code is going to be more than just a few lines long? Are you going to be able to design / recall / easily code structures like these? Probably not - you'll want to use an approach that is more extensible. And that's where you'll take the complicated logic bits inside and hide them ("encapsulate them") within a module or a class - Structured and Object Oriented Programming which allows you to go from small to medium and large applications robustly, and without writing code that becomes a nightmare to enhance.
The example above was written at the end of yesterday's opening day of our Perl for Larger Projects class. I'll be carrying on with it today - moving to an Object Oriented application where each of the layers will be written with more straightforward, verifiable, testable, re-usable code - leading towards an application in which we can extract and report on information about our web site visitors with ease ... and which we can easily enhance and modify as further analyses are required.
Posted by gje at 08:09 AM | Comments (0)
Related topics: via article database
Useful link: Perl training
August 24, 2009
Lead characters on Perl variable names
Perl variable names mostly start with a special character:
$ for a scalar variable - that's a variable that can hold an integer, a float, a string, a reference, or a compiled regular expression (that last not being terribly common).
@ for a list - that's an ordered collection of scalars, indexed from position "0" upwards. Since each individual member is a scalar, it can be an integer, a float ... etc, and it is referenced as an individual variable by a $ in front, and square brackets around the elements.
% for a hash - that's an unordered collection of scalars, indexed by other scalars. A good parallel here is a database table with two columns - one of which is a unique key and the other a value associated with it. Since members are scalars, they are referenced with a $ in front, and curly braces around the individual elements indicate members
& for a code variable - i.e. a "sub". You'll find that the & character is often omitted as a pair of round brackets - with or without a parameter - also indicate "run this code".
NO SPECIAL CHARACTER IN FRONT for a file handle. Conventionally written all in capitals ("I know what I am doing - I really DO intend to use a file handle here!") but they could be written lower case. File handles are used in limited places - open, close, seek, read <xxx>, etc and are really a sort of lightweight object, with handles also being connected to pipes, sockets, etc - they are (in reality) stream handles.
* for a typeglob - a use of "one of each of the above". Again, not very commonly used - the major use is for providing a mechanism for handling an 'array' of files; you can't do this directly with a list as a list is of scalars, and a file handles is not a scalar.
Here's some code including training examples of each of those, and also showing you context - how a list (for example) can be taken as a series of elements, a string made up of all the elements of a list, or the length of a list depending on the code surrounding the reference you make to it. These examples from the Perl for Larger Projects course I am running at present - day one's revision of Perl Basics.
$abc = "jashjkshjkhjkerhjkerhkert";
@stuff = ("Sage","Onion","feathers","foam rubber",66);
%henry = ("August", "Barbados", "September", "New Zealand",
"October", "Tallin", "November", "Hull", "July",
"Hawaii", "June", "Penge", "May", "Cape Town");
# Context Revision ---------------------
$"=", "; # Set separator to ', '
print @stuff,"\n"; # list context
print scalar(@stuff),"\n"; # Scalar context - no. els
print @stuff + 0 ,"\n"; # Scalar context - no. els
print "@stuff","\n"; # double quotish context
print (join(", ",@stuff),"\n"); # MUCH More maintainable.
print "$stuff[1] - @stuff[1] - \n"; # First good, second baaaaad
print @stuff[0,3,4],"\n"; # list slice
print @stuff[1..3,-1,2],"\n"; # list slice - any ole order!
print $#stuff,"\n"; # Index number of top element (i.e. length -1)
# String handling revision ----------------
$him = "John";
$message = "\"Don't do that\" $him said\n";
$message2 = qq("(please) Don't do that" $him said\n);
$message3 = <<"zSfs";
"I would rather you didn't to that " explained $him
"since there is already another dog in the bath and
the two of them will splash fearsomcley"
zSfs
print $message;
print $message2;
print $message3;
# " - a string operator
# ' - a literal string
# ` - run at shell / command level and save result
# Hash Revision ------------------------------
print %henry,"\n";
print (join(", ",%henry),"\n");
for ${widget} (keys(%henry)) {
print "$widget and we visit $henry{$widget}\n";
}
@movals = sort keys %henry;
print "@movals\n";
sub bylength {
length($b) - length($a);
}
@movals = sort bylength keys %henry;
print "@movals\n";
# Special variable types -------------------------
$a = "Henry";
$b = "Whillemena Smith";
$dx = &bylength; # Run a code variable
print "$dx\n";
$stuff = "Goods, Possessions, Chattels";
*nuvver = *stuff; # package deal - @stuff, %stuff, $stuff, &stuff, stuff
print "@nuvver\n";
print "$nuvver\n";
If this is a useful revision, then you're set for the Perl for Larger Projects or Using Perl on the Web courses. If you're thinking "I need to learn this", then please come on our Perl Programming course. There are varients for those who have programmed before, and for complete novices.
To complete my example, here is the output from running that program:
Dorothy-2:pl grahamellis$ perl fred
SageOnionfeathersfoam rubber66
5
5
Sage, Onion, feathers, foam rubber, 66
Sage, Onion, feathers, foam rubber, 66
Onion - Onion -
Sagefoam rubber66
Onionfeathersfoam rubber66feathers
4
"Don't do that" John said
"(please) Don't do that" John said
"I would rather you didn't to that " explained John
"since there is already another dog in the bath and
the two of them will splash fearsomcley"
SeptemberNew ZealandJunePengeJulyHawaiiMayCape
TownNovemberHullOctoberTallinAugustBarbados
September, New Zealand, June, Penge, July, Hawaii, May,
Cape Town, November, Hull, October, Tallin, August, Barbados
September and we visit New Zealand
June and we visit Penge
July and we visit Hawaii
May and we visit Cape Town
November and we visit Hull
October and we visit Tallin
August and we visit Barbados
August, July, June, May, November, October, September
September, November, October, August, June, July, May
11
Sage, Onion, feathers, foam rubber, 66
Goods, Possessions, Chattels
Dorothy-2:pl grahamellis$
Posted by gje at 09:38 PM | Comments (0)
Related topics: via article database
Useful link: Perl training
August 23, 2009
Translation from Ghanaian to English
In response to an email I have just received ... which shouts the subject line DO NOT IGNORE at me ... I'm not ignoring but providing you with a translation!
Hello
Hello
Pardon me for not having the pleasure of knowing your mindset before making you this offer and it is utterly confidential and genuine by virtue of its nature.
I don't know what you will think of this secret deal
I write to solicit your assistance in a funds transfer deal involving US$3.5M.This fund has been stashed out of the excess profit made last 2years by my branch office of the International Commercial Bank of Ghana which I am the manager.
Will you help me launder 3 million illegal dollars?
I have already submitted an approved end-of-the-year report for the year 2007 to my head office here in Accra-Ghana and they will never know of this excess.
We won't be found out
I have since then, placed this amount on a Non-Investment Account without a beneficiary. Upon your response, I will configure your name on our database as holder of the Non-Investment Account. I will then guide you on how to apply to my head office for the Account Closure/bank-to-bank remittance of the funds to your designated bank account.
This is how we'll do it
If you concur with this proposal, I intend for you to retain 30% of the funds while 70% shall be for me.
But I want most of it back for myself
Kindly forward your response to me immediately
With Regards,
George Nduka
+233 24 888 6531
JUST IN CASE anyone has any doubts, this is a scam!
Posted by gje at 08:49 PM | Comments (0)
Related topics: via article database
Public Transport from (and to) Melksham on Sundays
I walked into the Town Centre in Melksham at around 9 O'clock this morning - a bright sunny morning and it was (as you would expect) quietish, but it certainly wasn't deadly quiet. A young gentlemen approach me, asking me for directions to the train station.
If someone asks me for directions, I'll help them if I can - answer their questions, and give them helpful extra tips. But I didn't tell this chap how to get to Melksham Station. Why? Because it wouldn't have sent him to a perfectly adequate platform ... at which no trains were due to call for the next 8 hours, and from where there's no alternative public transport (bus) service either.
"Well - I can give you directions, but there aren't any trains until early evening on a Sunday. [I don't know why I added "on a Sunday" - it would have been an even worse story on Monday to Friday!]. Where are you going?" And he unfolded a sheet of A4 paper, showing that he had to catch First Great Western's bus from Chippenham Station at 09:40.
A further issue - there are 2 buses an hour on Monday to Friday on the Trowbridge - Melksham - Chippenham run. There is one an hour on Saturday. And there are zero per hour on Sunday. Hmmm - talk about being disconnected. "If you're going out for the night, leave your car at home and take a taxi or public transport". "Why not be green and use public transport?" I'll tell you why not on a Sunday morning - because there isn't any!
We got him sorted in the end ... he wouldn't be in Chippenham for that 09:40, but he would be on the next bus out, to Bath at ten to eleven. Here's a complete departure board for Melksham for Sundays
07:45 - to London (Heathrow) and London (Victoria) (From Frome)
10:50 - to Bath (from Devizes)
11:13 - to Devizes and Easterton (From Bath)
12:50 - to Bath (from Easterton and Devizes)
13:13 - to Devizes and Easterton (From Bath)
14:50 - to Bath (from Easterton and Devizes)
15:13 - to Devizes and Easterton (From Bath)
16:50 - to Bath (from Easterton and Devizes)
17:13 - to Devizes and Easterton (From Bath)
17:21 - train to Chippenham and Swindon (from Westbury)
18:31 - train to Westbury (from Swindon and Chippenham)
18:50 - to Bath (from Easterton and Devizes)
19:13 - to Devizes and Easterton (From Bath)
19:52 - train to Chippenham and Swindon (from Westbury)
20:13 - to Devizes and Easterton (From Bath)
20:50 - to Bath (from Easterton and Devizes)
21:05 - to Frome (from London Victoria and Heathrow)
21:50 - to Bath (from Easterton and Devizes)
You might say "I know that's not many services ... but is is Sunday. Yes, it is Sunday. And Sunday afternoon is now the busiest time of the week for long distance travel.
Posted by gje at 04:44 PM | Comments (0)
Related topics: via article database
August 22, 2009
Quiet summer days? I think not!
I was amused at the co-incidence ... to see that one of our most downloaded images in the last 24 hours has been this one, taken st least three years ago at the rear of "404". It's a co-incidence because - just yesterday - I brought that BBQ out of storage in 'The Tack Room' at The Manor, degreased it, set it up in just the same place, and we had our first garden-cooked food at home since 2006! I was less amuse when I investigated just why this picture is so popular - it appears to have been hotlinked from an 'adult' web site which, I surmise, is using random links to increase its street-cred. You can see our current most viewed pictures here, and the most common ones called from places that our not our main sites (usually stolen) here. The listing is constantly updated - and if you want to know how to do it, come on the PHP Techniques Workshop or have a look at the source code
This last week, "The Horse" has been very technical ... and that's because I have been at it, non-stop it seems, since last Sunday morning. August is supposed to be the quiet 'holiday' season in the training business, but you shouldn't entirely believe that. A quiet time at XYZ Engineering is also a good time for the staff to go our and get trained, and it's also an excellent time to consider and plan for work-team wide training for the autumn. So as well as a three day public Python course and a two day Apache HTTP Server and Apache Tomcat Course, I have had very welcome enquiries to be following up; every customer is an individual, training is always an important part of each individual's development need, and so we all make sure we go to great lengths to come up with the very best solution we can offer in each case. It takes time, but it's a good investment for everyone!
Yet the busyness has gone beyond just a typical busy training week. Struck by a significant but quite small minority of delelages who want to learn languages such as Python, PHP and Lua but who have never programmed before, we now add an extra day on the front of the more typical courses (for those who HAVE programmed before) to give the novices a good start and foothold. We expect those extra days to be run on demand, and only prior to a small proportion of course dates. And they WILL run for just one person - it makes huge sense, as that's then another place sold for the rest of the course, and a delegate who's then well able to stay with the course. But anyway - long story - there was an extra Python day at the start of this week - yes, Sunday - with two delegates who were both delighted with the extra, and the quiet learning opportunity provided at Well House Manor.
(Links - Ruby, C anc C++, Perl and Python - more comments about "learning to program" in the particular languages)
Oh - and August is the busy weekend / leisure hotel season too. We welcome such guests to Melksham in Wiltshire, but we're very much aware that they're not people who are travelling frequently - they need / desire extra attention, and whether it's a guest who's scheduled a 3 p.m. arrival and then not shown up till 9, has arrived as 10 a.m. with "can I chackin a bit early?", or phones at 23:30 to check that his reservation is on order, it does add to the welcomed load.
So, dear reader, that is why you've seen little but technical notes in the last week ... but with a hope that we'll be back to a more 50 / 50 balance in the future.
Posted by gje at 11:41 PM | Comments (0)
Related topics: via article database
August 21, 2009
C++, Python, and other training - do we use an IDE
A question from my inbox ... "Do you use Visual Studio, or a similar IDE". And worth a full answer, and one to be shared.
| An IDE or Integrated Development Environment is a piece of software that provides the programmer with tools to manage his / her code, and to help him / her with code authoring through suggested code, templates, and a test area through which code can be written, stepped, traced, etc. |
A good question ... and something we keep under review.
On our public courses, we teach the fundamentals of programming (in any of the languages we cover) using a point and click editor rather than a full IDE ... reasons for this include:
a) We want delegates to appreciate the basics of the language without having them automatically provided by an IDE, sometimes with its own "macro" view of what should be put in (e.g. ask for a class in some IDEs / languages and you get a screenful of template!)
b) There are only a very few languages where one IDE is prevalent in the user base, and we really don't feel it would be best use of our customer's time and money to take time out from the core programming training to cover a tool which they would be less than likely to be using again later.
c) License issues / license costs where an IDE is commercial - it would make a significant price difference, or we would find ourselves tied into a vendor's program to get the IDE at low / no charge, which in many cases would oblige us to market their products.
Having said that , we are very happy for delegates to use their own laptops during our courses / connect to our network, and while they are with us, they are welcome to use their own IDE. Sometimes, that helps highlight issues / differences - only this week, it helped us identify output buffering issues from one particular IDE. And we are also very happy for delegates to download Open Source IDEs such as Eclipse onto our machines, to use / experiment with them, etc. As the tutor, I'm usually around after the course for a couple of hours, and we'll sometimes go "Off piste" and look at special libraries, IDEs, special requirements, etc. If alerted ahead of time, I can be prepared for this too.
For private courses, which are cost effective when you have a group of 4 or more delegates to be trained on the same subject at the same time, we can vary the policy / position somewhat. We do have to be careful of licensing issues, costs, etc, and also that we only take on IDE use / training within the tutor's knowledge. But we can be much more flexible.
I know your enquiry was just a short question, but it's one that deserves a longer answer.
Posted by gje at 05:25 PM | Comments (0)
Related topics: via article database
Useful link: Python training
Using a cache for efficiency. Python and PHP examples
Ask yourself "how long is it (in seconds) from 5.36 a.m. and 20 seconds to 6.04 a.m. and 39 seconds".
Have you worked that out?
Now - how long is it (in seconds) from 5.36 a.m. and 20 seconds to 6.04 a.m. and 39 seconds.
Got that? And how long is it (in seconds) from 5.36 a.m. and 20 seconds to 6.04 a.m. and 39 seconds.
I expect by the third time you came to the same calculation, you already knew the answer and just trotted it out again, without bothering to recalculate it. But if you put such a calculation within a program, to be done time and time again, the computer will almost inevitably repeat the calculation time and time again, which may significantly slow the operation. And if that's likely to happen, it's worth considering caching or storing the result the first time, so that you don't have to recompute in the 2nd, 3rd, 4th ...
Let me ask again "how long is it (in seconds) from 5.36 a.m. and 20 seconds to 6.04 a.m. and 39 seconds". See - you KNOW straight away that it's 1699 seconds, don't you, because the human mind caches.
On Wednesday, I wrote a course example which analysed a log file of over 30 Mbytesi which listed accesses to our web server - nearly 150,000 record from over 14,000 different IP addresses. And I wanted to sort them by the elapsed time from first to last visit from each IP, to give a length of visit - a snippet of the result to look like this:
205.210.222.150 3 600
115.240.214.62 8 600
203.128.4.254 6 599
89.61.24.234 2 599
199.46.149.168 18 599
212.235.67.230 6 596
196.11.235.63 4 596
(Snippet shows visitors who spent between 9 minutes and 55 seconds and 10 minutes between their first and last accesses - so actually people who were probably with us for JUST OVER ten minutes, bearing in mind they would want time to study the final page they found)
My methodology - in Python - was to read the whole file, and create visit objects (lists of accees strings) which were themselves stored in a dictionary. An object method was written to provide the duration of an access by analysing the first and last log lines, converting to seconds and subtracting. Here is the class:
class visit:
def __init__(self,defstring):
self.detail = [defstring]
def hit(self,defstring):
self.detail.append(defstring)
def getcount(self):
return (len(self.detail))
def getduration(self):
if len(self.detail) < 2:
return 0
startinfo = when.findall(self.detail[0])
endinfo = when.findall(self.detail[-1])
thyme = gelap(endinfo) - gelap(startinfo)
if thyme < -200:
thyme += 24 * 3600
return thyme
It worked ... but was a bit slow. With a timer added:
(13.630000000000001, 0.089999999999999997, 0.0, 0.0, 10582027.0)
13 seconds of c.p.u. time - hardly the ens of the world but could do better. And here is better:
class visit:
def __init__(self,defstring):
self.detail = [defstring]
self.cached = 0
def hit(self,defstring):
self.detail.append(defstring)
self.cached = 0
def getcount(self):
return (len(self.detail))
def getduration(self):
if self.cached:
return self.eltime
self.cached = 1
self.eltime = 0
if len(self.detail) < 2:
return 0
startinfo = when.findall(self.detail[0])
endinfo = when.findall(self.detail[-1])
thyme = gelap(endinfo) - gelap(startinfo)
if thyme < -200:
thyme += 24 * 3600
self.eltime = thyme
return thyme
Ironically, the code and objects are more complex. I have added an extra binary flag into each object to note whether or not I have an up to date cache - for I might enquire about an object's duration before it has had all its records added, and if I do I need to expire the out of date calculation. And I have also added a check to see if I need to bother to calculate when the duration is called for, which returns the stored (cached) value if it's already available. Finally, I actually stored the elapsed time value in the object.
But the results are good:
(2.1899999999999999, 0.080000000000000002, 0.0, 0.0, 10582099.23)
I have reduced the program's run time to about one sixth.
You should have an eye open to caching, but it won't always help. When you are sorting a significant number of records by a calculated value, as I was, there will often be a gain. But if you are only using each value a couple of times, you may slow things down a little, or increase the memory footprint so much that you loose any gains. Then ... if you end up caching something that only took 10% of the time anyway, even a 10 fold speed improvement in that part of the code will give you just a scarce-noticed 9% speed-up.
The complete code from the uncached example is [here] and from the cached example is [here].
Caching is also useful in web2 applications, where your web server uses resources from another system on the internet to give a combined report - it picks up exchange rates, blog feeds, status reports such as weather, from other information providers, and includes that data directly or indirectly in its own results. In such cases, the data supplying site will often REQUIRE you to cache the data, which may then fall slightly out of date and you'll have no way of being sure if the data has changed in the intervening time. But with a reasonably frequent check, the data has probably slipped just a little.
Here's a PHP example in which we grab a data feed at a maximum interval of 10 minutes, and we use the file timestamp to note when the most recent retrieval happened:
# Cache - update every 10 minutes (max)
if (time()- filemtime("tfd.txt") > 600) {
$logrecs = file("http://(url obscured)");
$fh = fopen("tfd.txt","w");
foreach ($logrecs as $line) { fputs($fh,$line); }
fclose ($fh);
} else {
$logrecs = file("tfd.txt");
}
This code is included in our live feed from the local train operator (full code [here]) and is only re-collected every 10 minutes. OK - so it may be slighty out when you display it, but it gives a good, live impression. And we have another live page where logged in members have a shorter caching time ... that uses the same data file, so even the casual visitor can sometimes get better updates than the 10 minutes might lead one to believe.
The Python caching example was covered on our Python Programming Course this week, and the PHP and web2 is routinely covered on PHP Techniques.
Posted by gje at 07:25 AM | Comments (0)
Related topics: via article database
Useful links: Python training, PHP training
August 20, 2009
Python - fresh examples of all the fundamentals
Some more new examples in Python - from this week's course.
From my Introduction to Python / simple example to show the power of the language, I present my example that parsed a big data (log) file and counter and sorted by number of accesses the hits from various remote hosts. A long report, ending as follows:
216.129.119.10 549
216.129.119.44 580
66.249.71.164 587
66.249.68.89 2975
217.160.182.81 3215
72.30.142.107 3250
77.88.28.246 4815
66.249.71.55 5457
Dorothy-2:p2 grahamellis$
With the program source available [here].
The some shorter / easier stuff from the first day:
An program to provide a chart of exchange rates - the sort you would give your children when you take them overseas and want to teach them about the local money, and have them work out what is good value. [here].
A short example of how to save a multiline string in a variable in Python. [here].
A prompt ... read ... calculate ... report program in Python. [here].
In Python, you can save yourself writing loops to go through each element of a list by using list methods and operators. We wrote a 'control' example showing how it would work in any language [here], and went on to reduce the looping dramatically [here]. In both cases, the programs produce two lists of 365 elements - representing days of the year. One list has 31 1s, 28 2s and so on - to convert day of year to month of year, and the other list has the numbers 1 to 31, then 1 to 28, and so on, to convert day of year to day of month.
Newcomers often get confused between assigning to the whole of a list (replacing the whole thing) and assigning to an element (replacing just that element and leaving the rest in tact. Our final first day example - [here] illustrates both in source code, with
listname = replacing the whole list and
listname[6] = replacing just the 7th element.
Examples from the second day
Functions, Modules, Packages, and Object Orientation in Python!
In most languages, functions run to completion before they return anything, but in Python you can write a generator which passes back a series of values at yield statements - thus providing an iterator. This is especially useful where you have a big data set - you don't have to read the whole dataset into memory in one go and then process it bit by bit, nor have the read and process in one function. We wrote a 'control' case [here] showing how this would be in a conventional language, and then did it the python way with a generator [here]. You can do this in Lua - using coroutines - too.
The map function converts every member of a list through a function which you pass in as a parameter, and the filter function return you a list of (only) matching itemes, as identified by a callback function in the call. Consider these to be the equivalents of map and grep in Perl if you like ... and see the example source code [here].
As programs grow, you need to separate out your variables into different namespaces - you need to be able to tell "John Smith" from "John Jones" so in Python, you write smith.john of jones.john. And you load namespaces from different files. Example - the file that does the loading [here], and the file it loaded [here] - that latter complete with its own test code to allow you to check it works on its own before integrating it with your main code.
In Java, defining and using a class would be 2 separate files with lots of "public"s and "private"s. And in C++ you would have half a dozen files. Which is why Python's OO model is so sweet - the whole thing can be done in one file - and we have an example [here]. We also have an example with a static (class) variable [here] and we even have examples with multiple classes - look forward to day 3, but they're still potentially all in the one file if they're going to be coded, used and maintained in tandem.
Day 3 - a bit beyond the basics
Some string handling and formatting - [here] is the use of the % operator both for modulo (integer) and formatting - the operator is overloaded - and a regular expression example which shows you how you can split a string at either an exact match, or at a pattern - [here].
Polymorphism and Inheritance - the way data types can all be defined from the same starting point, with only the differences being coded, and then how those subtley different objects can automatically behave in the way designated for them - comes naturally in Python. We have examples [here] which show multiple related classes, and comparators, and [here] showing how they can be wrapped into a module.
Regular expressions ... we cover quite a lot there ... included a new example [here] where I looked for all the postcodes in a string.
Posted by gje at 10:10 PM | Comments (0)
Related topics: via article database
Useful link: Python training
Learning to program - how to jump the first hurdles
From last Sunday ... here are links to the examples of code that I wrote in front of the "Learning to Program in Python" delegates - to show them not only how a program works, but also how I (and other code authors) go from a requirement through to the code that actually does the job. Or, paraphrasing, "a manual is all very well but it doesn't show the process of how the code is developed - you just see the final product, which is of use (but only limited use) if you need to develop code yourself".
Some Early Stuff
Showing operator precedence - how multiplication and division happen before addition and subtraction, but you can alter that using round brackets. [source code]
A first use of conditionals - how you can look at something in your program, and then perform certain tasks based on what you find. This is "if" and "else" (and - depending on the language - elif elsif or elseif). [source code]
And then how you push pieces of code that can be shared between a whole lot of programs out into a separate file that each of those programs can call in. Although you don't think about this naturally when you write your very first programs, you will realise very quickly in your 2nd, 3rd and 4th programs that use the same data that you don't want to recode ... and you don't want to copy and paste either, since you'll end up having to maintain / update multiple copies if you do so. See [source code - calling program] and [source code - shared logic].
The importance of structured or OO programming
I can't stress this enough, even from day 1. You need to write code that will be re-usable and maintainable - a Rembrant and not the dog's dinner.
[here] is a tiny piece of code ... or so it appears at first. In fact, it's a tiny main program that pulls in other bits of code that MIGHT be short or MIGHT be substantial ... but in itself, a very short piece of code to do a job.
That same piece of code is expanded [here] into an example that only runs some of the structured blocks in certain conditions, and is expanded further [here] into code that loops, repeating the operation of one of the structured blocks of code time and time again.
For reference (at this stage), the blocks of code that have the logic hidden within the ("encapsulated") may be found [here].
I have posted further source showing the importance of good variable naming here and of commenting your code here
Looking ahead and motivating the class
Let's face it - you can't learn to program in a day. And a programming language is made up of a large number of different components and concepts which when used together make it powerful. So at the end of the first day's teaching, delegates are seeing something but not the whole picture, and need a beacon to shine ahead and say "this is where we'll be heading by the end of the course in a couple of days".
[here] is an example I wrote at the tail end of Sunday - it's a file parser that went through a log file that's about 30 Mbytes in size and produced me a simple report telling me how many accesses there were in total, and how many to a particular web page. It runs like this:
Dorothy-2:py grahamellis$ python file_first
Whole file was 149307 lines long
Intersting stuff was 11 lines
Dorothy-2:py grahamellis$
You'll spot that a very short piece of code - 21 lines - written at the end of that first day is sufficient to give me a useful analysis of a substantial data flow which wouldn't otherwise have been straightforward. As soon as you have program loops involved, the power of your program increases by an order of magnitude.
It increases by a further order of magnitude when you add in collections - variables that can hold a whole series of values based on a key of some sort; using those, I have been able to expand that previous example to count access to all past blog articles in that log file, rather than just one specific article - so it's a really useful analysis. The sample program, written in front of delegates at the end of the first day to shine a beacon ahead, is [here], and when you run it, it produces a long report ending as follows:
1502 136 Java-sorting-ArrayList-example-generics
255 157 STDIN-STDOUT-STDERR-and-DATA-Perl-file-handles
969 241 Perl-and-
158 937 MySQL-LEFT-JOIN-and-RIGHT-JOIN-INNER-JOIN-and-OUTER-JOIN
Dorothy-2:py grahamellis$
which tells me that the four most popular blog articles (by number of times read) that day were no.s 158, 969, 255 and 1502, that they were read 937, 241, 157 and 136 times ... and that they were about (well - you can see the report for yourselves!).
All of which ain't a bad outcome for new programmers on a Sunday!
Posted by gje at 07:45 AM | Comments (0)
Related topics: via article database
August 19, 2009
At the end of the course

Already, the days are getting shorter. At the end of the Python Course, I walked along the canal with one of our delegates who - wisely - decided to stop an extra night and drive home to East Yorkshire fresh at the start of a new day, rather than drive home tired after a very full four days in which he - and other delegates - went from "what's this programming lark all about" through to having some useful little utilities written and the route ahead planned for develop able, maintainable code!.
The home made Lamb and Rosemary pie at "The Magpies" was lovely, the vegetables ideally crisp, the dog sat quietly (for the most part) under the table while we ate. Although I finish the course exhausted from teaching, I also finish it feeling very rewarded ... there are now people down to the south of our county, in South East London, and up north who have learned a lot, are enthused, and are going to be able to develop themselves further - making good use of Python straight away, and really effective use of it with a bit of practise.
Posted by gje at 11:33 PM | Comments (0)
Related topics: via article database
August 18, 2009
Counting Words in Python via the web
I love writing things in Python - it's a great language for achieving a great deal in a short time. And it works well got Simple CGI scripts.
Today's challenge - to count the number of words (and number of DIFFERENT words) in a piece of text, so give an idea of how much work would be involved in translating it.
Web page onto which to paste the text is here. Source code of the script is here. Source code of the Python program is here.
A word of warning - I have taken great care NOT to echo all the text (protects me against injection attacks) - and you need to do the same on your pages. If you're not sure what I mean, read this blog further or I'll tell you more on the Python Course.
Posted by gje at 05:27 PM | Comments (0)
Related topics: via article database
Useful link: Python training
August 17, 2009
Getting it right from the start - new programmers
From yesterday's "Learning to Program in Python" - an example of splitting your program into manageable chunks, which is SO IMPORTANT with regard to testing and ongoing maintenance that we introduce the subject even on that first day, with some of the early elements of the language.
from utilz import *
# Modular programming!
celc1 = gettemper()
celc2 = gettemper()
current = celc1
while current < celc2:
faren = ctof(current)
reporton(faren)
current = current + 10.0
Our programming course customers have two distinct backgrounds:
• There are those who know a bit about programming and are looking to convert their skills from C to Perl, from VB to PHP or from Shell Scripts to Python - and for them, courses such as Perl Programming, PHP Programming or Python Programming are correct and appropriate.
• There are those who have not programmed before / rusty / never had any programming training, for whom topics such as "what is a variable", "how does a conditional work" and "why should I structure my code / how should I plan to do so" are vitally important. For such delegates, typically coming on the courses to make a major change / advance in what they do, an extra lead-in day to help get them established with the subject, comfortable with some of the basics more gently covered, is a great advantage. And they're often happy to come down a day ahead of the normal week's course to get that extra advantage. Certainly, yesterday with two delegates on learning to program in Python was a great success - 'rave reviews' of what we are doing and how we did it from both students, on what is typically a group of a handful of people, in our quiet location, with the ability to learn anew without disturbance.
See here for a table of courses - the languages we teach, and the "programming in ..." and "learning to program in ..." courses for each.
Posted by gje at 07:02 AM | Comments (0)
Related topics: via article database
August 16, 2009
Alpaca Case or Camel Case
A very first practical program on our Learning to Program in Python course that started today.
Even at this early stage, we teach things like good practise in variable naming - standards such as using a consistent case (e.g. camel case where each intermediate words starts with a capital).
I was looking for a picture of a camel to illustrate this, but I found its near relative, the Alpaca, in Seend Cleeve. I know it doesn't have the humps in the middle that lead to the term "camel case" in the first place, but I expect my readers may allow me at least a little artistic license!
print ("Welcome to learning program in Python")
print ("The shop at the end of the steet is shrinking hours")
print ("We's done")
howOld = input ("Please enter your age: ")
retireAt = 75
toGo = retireAt - howOld
print "You have",toGo,"years to serviette"
Posted by gje at 05:09 PM | Comments (0)
Related topics: via article database
August 15, 2009
Thornham Farm Shop, Seend Cleeve, nr Melksham
The weekend ... and what an excellent opportunity to explore a lane I've often seen off the A361 just down from The Bell near Seend Cleeve.
The track drops off the edge of the hill, across cattle grids and runs unfenced through fields of cows; it's narrow and you pull onto the grass to pass other cars.
At the end of the track is "The Fat Hamster" Cafe, Thornham Farm Shop, an old bus parked up (as extra sleeping quarters?) and some paddocks of animals so that the customers know what they're buying from the shop.
There's quite a range of different breeds of pig at the farm - the butcher proudly telling me what they sold (and me carelessly forgetting). I think there's a Tamworth Red in my pictures, but I don't recall it being mentioned; I do recall mention of "Old Spot"
See Thornham Farm Shop's own web site ... and it's a great half hour's diversion on a Saturday afternoon. See Oklahoma State University for details of pig types (seriously good site) ... and work out which of the ones picture here are Welsh, Gloucestershire Old Spot, Berkshire and Tamworth.
Posted by gje at 06:14 PM | Comments (0)
Related topics: via article database
August 14, 2009
Geocoding - converting address to latitude / Longitude with PHP via Google
We have a 'geocoding' example here, and indeed I was using it earlier today. The idea is that someone enters part of an address on your web site, and you contact Google to look up the latitude and longitude so that you can put it on a map, or calculate a distance from somewhere else. It's very need, but it needs a bit more that a basic knowledge of PHP to debug - you've got multiple servers, security keys and configuration options floating around.
So it was a co-incidence, but no surprise, to find the following in my mail box later on:
|
Dear Sir, While I was searching for a script that allows simple geocoding with google api I found this article in your website: When I tried to test it in my localhost it showed me this error: I don't really know where the problem is; I would appreciate help. |
I've never met the poster ... but the question is well formed (I have tidied up the English for publication here), specific and polite and I want to help ... and to help others who come across the same thing. So - here's my answer:
The problem lies in the attempt to contact Google for the information - in the source code line within the error message you have quoted.
This line can fail for a number of reasons:
a) Your server / PHP may be configured so that it does not allow outgoing http requests
b) Your server may not be correctly resolving the DNS / name of maps.google.com
c) There may be an error in the URL that you have called up at Google, so that you are pointing to a page that does not exist there
d) You may have an extra space or other spurious character in the part of the URL after the ?
e) You may not have the correct / a recognised Google key.
The error message tells me that your problem is (c), but the piece of code in the error message looks correct. The best advise I can offer is to try the lookup on Google directly rather than via your PHP script (make sure that works first). Then try contacting another server from yours - not the Google one with the extra complexity of the key, but something else. Then try bringing the code together. This series of tests will narrow down the problem - tell you if it is one of the five reasons I have suggested or something else - which in turn will let you solve the problem.
Graham
Posted by gje at 10:31 PM | Comments (0)
Related topics: via article database
Useful link: PHP training
August 13, 2009
Error Handling in Lua with assert and pcall
When a function fails in lua, you'll often find that it return a nil value that you can check, or it returns two values, the second of which is an error status / message that tells you what went wrong.
Here's an example:
value = tonumber(stuff)
if value == nil then
print ("Nah!")
else
print ("That is half of ",value * 2)
end
(full source of example)
You can reduce the code somewhat by using the built in assert function to check, generate the message, and exit with a full stack trace - example:
io.write ("How many bits: ")
val2 = tonumber(io.read())
assert(val2 >= 1,"need to have at least one piece")
(full source code of example)
There are times when a lua function will generate an error before it returns to the calling code .. but you want to trap that .. and you can do so via pcall or protected call. Example:
goodun,eachlen = pcall(cutter,val1,val2)
This calls the cutter function with two parameters, and the result is returned into eachlen. The other return variable is a status to tell you whether or not the function worked.
(full source code of example)
Illustration - during a private Lua course at a customer's office. As well as private training courses on site, we run public Lua courses at our Melksham, Wiltshire, UK training centre. See [here].
Posted by gje at 05:46 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
A fresh example - objects the Lua way
One of the requirements we often have in our web server log file analyses is to connect together a series of accesses from a single IP address into a "visit", and this formed an example on Tuesday's Lua course.
In Lua, you can overload (i.e. redefine) operators so that they work differently on tables of different types, and in this case I chose to redefine addition so that it concatenates two visits, allowing all the access log records from a single source to be logically grouped even though there are many different visitors (i.e. IP addresses) coming to our site at the same time:
(This diagram shows you just how wide ranging our visitors are - it's dynamic, showing you the last 15 minutes up to when you loaded the page!)
The log file analysis program comes several days into our Lua Programming course so it's not practical for me to document every line here, but if you already know Lua, you're more than welcome to look at the calling code here and the object definition here. The latter contains a good block of comments!
Posted by gje at 02:45 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
Encapsulating shared code in a Lua module
Have you ever written code like this?
seps = {" "," "," [",'] "','" '," ",' "','" "','"'}
Yes, I have ... in fact, that's code that I wrote on Tuesday during the Lua course; it's an indexed table of the separators used to split down a web access log record that's in the apache httpd combined format.
Am I proud of it?
Not really ... in fact, coding it in front of my delegates, I got it wrong initially and we had to go back and look very carefully at the single and double quotes. BUT once I got it right, it works well enough and there are sufficient comments around for it to be debugged if need be. Having said that, I would rather like to hide it under the carpet, and avoid it tripping up anyone else who stumbles across it.
Firstly - I put the code into a function so that it's lightly wrapped (see here) and can be called / prodded / used without the user being fearful of upsetting the code if he/she cuts and pastes it.
Then, I put the code into a separate module. That's a far heavier wrapping, using a table as a fresh namespace, and leaving only the names of the elements in the table / module / namespace visible to the calling file. The module source code is here and the source of a sample calling program is here
Posted by gje at 02:31 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
Checking if the user has entered a number (Lua)
In Lua, there's a difference between 0 and nil - and that means that you can easily code to ask your user to enter a number, testing the result and allowing him to enter zero as a legitimate value. That may sound like it's no big deal, but you don't want a loop to exit on a premature 0.
Here's code to ask for a numeric response:
io.write("Please enter the age of your dog: ")
stuff = tonumber (io.read())
if stuff then
and you can be assured that the chunk will run even if a zero was entered, but will not run if a non-numeric value is given. [full source code]
That extends very easily into a loop if you need to keep asking until you get a number:
while not stuff do
io.write("Please enter the age of your dog: ")
stuff = tonumber (io.read())
if not stuff then print ("Duh!") end
end
with this code relying on the non-existent variable stuff returning a false at initial entry to the loop. [full source of example]
Posted by gje at 01:49 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
Passing multiple results back from a function - Lua, Python, etc
Have you ever wondered why you can pass in as many parameters as you like to a function, but only return one? It seems rather unfair, doesn't it - especially as you may have lots of results.
In fact, in some languages such as Lua you can pass multiple values back:
a,b,c = symie(4,7,9)
(see source code)
and in others such as Python and Perl you can return one collection which contains multiple items. Here's an example return in Python:
return (net, tax)
and the code that collects the two return values from the function:
shop, taxman = both(amount)
(see source code of function and caller).
Even less directly, you can return hashes, lists or objects in other languages, and in C you can return a pointer to a structure. Perl often sets special global variables (to take what I sometimes describe as 'side effect' results) which are all well and good if you know what is happening, and most languages allow some sort of global variable which is OK if used in extreme moderation!
Posted by gje at 01:12 PM | Comments (0)
Related topics: via article database
Useful links: Python training, Lua training
See this page in French
Would you like to read this page in French? If so you can do so here ... through Google's "Translate" service ... and this is just an example - I can write other links for other languages, or you can move on from French to another language once you've gone to Google.
The extra tag in my page is:
<a target="_blank" rel="nofollow" onclick="window.open('http://www.google.com/translate_p?u='
+encodeURIComponent(location.href)+
'&langpair=en%7Cfr&hl=en&ie=UTF8'); return false;" title="Translate English to French">
<span style="cursor:pointer; cursor:hand;">This page in French</span></a>
Posted by gje at 09:24 AM | Comments (0)
Related topics: via article database
Training, Open Source computer languages
A few days ago, I made a series of postings which summarised our courses in major western European languages - with a view to having the information about our courses available / findable to people who's mother tongue is perhaps Swedish or Italian, but who have good English and could benefit from our more niche courses. A follow up comment "Where is the English Version?" has lead me to this extra post - the same thing in English!
New here? We're authors and providers of a wide range of Open Source training courses, based in Melksham, England. We believe in looking after our customers and giving back to the community too. Whether or not we've trained you, you're welcome to browse our material:
• articles in the solution centre
• tips and updates on The Horse's Mouth
• Question and Answer via the Opentalk Forum.
and there's more about us here.
Or select Open Source subject:
• Python Programming
• PHP Programming
• Perl Programming
• Ruby Programming
• Lua Programming
• Tcl Programming
• C and C++ Programming
• Java Programming
• Linux Operating System
• MySQL Database
• Apache httpd & Tomcat
Features of all our public courses include:
• Presented by our own professional staff tutors
• Maximum course size 8 delegates
• Run at our own custom-fitted training centre
• Residential accommodation available for delegates
• 1 delegate minimum - we always run your booked course
• Training material written by us and revised often
Please browse this site for further details, or email us via info@wellho.net or call us on +44 (0)1225 708225 if you would like to discuss your company or personal requirements.
Our courses are different... [detail]
• A warm welcome the night before
• Complimentary railway station pick up
• No minimum numbers; courses always run
• Run at our own training centre
• Stay with us - we are also a hotel
• Courses presented by the author
• Maximum of just 8 delegates per course
• Post-course support included
Scheduled Courses
Deploying Apache and Tomcat
Deploying LAMP - Linux, Apache, MySQL Perl / PHP / Python
Linux Basics
Linux Administration
Linux Web Server
Learning to program in PHP
Learning to Program in Python
Learning to Program in Java
Learning to program in Lua
Learning to Program in Ruby
Learning to Program in Tcl
Learning to Program in C
Learning to program in C++
Learning to Program in Perl / Perl Programming
Lua Programming
PHP Programming
PHP Techniques
Object Oriented programming with PHP
The MySQL Relational database
Python Programming
Learning to program in Perl / Perl Programming
Using Perl on the Web
Perl for Larger Projects
Programming in C
C++ for C Programmers
C and C++ Programming
Java Bootcamp
Ruby Programming
Tcl Programming
Tcl - the Tk Toolkit
Regular Expressions
Our public courses are presented in English. If you speak good English as a second language, the course will be suitable for you. We also run private course on customer sites, where a good local translation service can ensure that you get the most from the course if you are not an English speaker.
Also available in ... French Spanish Italian German Portugese Dutch Daninsh Norwegian Swedish Finnish.
Posted by gje at 08:45 AM | Comments (0)
Related topics: via article database
All change - Wiltshire Parliamentary
At the weekend, I read that James Gray, the MP for Chippenham, had remarried. And, yesterday, that Michael Ancram, MP for Devizes (which includes Melksham) has taken the decision to stand down at the next general election. Goodness - how times change; four years ago, when I first got more actively involved in local activities, the MP in this blue part of the world seemed almost like a fixture! James Gray will still be standing at the next election - but for North Wilts which does NOT include Chippenham, Melksham will move to the new Chippenham constituency, so it's "all change". Realistically, we'll be represented here by either Duncan Hames or Wilfred Emmanuel-Jones; all three major parties have good local candidates, but realistically the seat is a LibDem / Conservative marginal with (on last general election results) it being wafer-thin to Duncan and the Lib Dems.
I have had the pleasure of meeting Michael a number of times, and he's a lovely, courteous gentleman. I have seen him in effective action in saving the hourly daytime train service at Bedwyn (population 1,800) when it was threatened with a reduction to every two hours, I have read of him in the Middle East working to help negotiate more peaceful times in the areas in and surrounding Israel. And I have seen his parliamentary / defence questions, keeping an eye on the government as is one role of an opposition. I also thank him for the representations he has made on behalf of the train services to the station here at Melksham in his constituency, where (for a population of 23,000) a cut to just 2 trains a day was threatened - and in this case carried through.
The new constituancy boundaries look far more sensible. A cluster of towns - Bradford-on-Avon, Corsham, Chippenham and Melksham form a natural constituency, separate from Devizes - that great open area which previously had add odd finger into West Wilts and its development / much more urban area. North Wilts, again a rural area, is a natural grouping too, with James Gray (at least as I write) standing there. In Westbury (including Trowbridge), there's a fine MP in Andrew Murrison; I am intentionally NOT making any party politics here, but I will say that "there is one very impressive person".
So - I may be up to a year early, but I wish Michael a long and happy retirement (I would love it if he found time as a swansong to help oil a few wheels for Melksham) and I look forward to this time next year when - at least - the layout of the seats in this county will be rather more logical, for the good of the people who live and work here.
Posted by gje at 08:36 AM | Comments (0)
Related topics: via article database
August 12, 2009
Printed Directories - the start of the updating season
I don't know how many business directories there are - but I do know it's the season for all the directory providers to start phoning around and sell spaces in their publications. I have spoken with two in the last two days!
So it's very fortunate that Lisa and I spent Saturday going through the 2008/09 accounts - the Sage listings of the suppliers with whom we had spent money, and saying "is this good value / what are we getting / do we need this service". We don't make huge use of paper directories these days - a list of local taxi firms (for sure), but not much else; we tend to search on line. Are we the norm? Perhaps not, but we're becoming part of a more significant section of the population, and that's the section of the population that's best targeted to our courses and hotel rooms here in Melksham. In other words, the paper directories are selling towards a different market to we're really looking at. And furthermore, we're primarily looking at hotel rooms which are booked ahead (so why would a directory circulated to local homes be right for us?), and to fill rooms between courses in a small hotel, rather than it being the main business at a much larger establishment. Hmmm - starts to look like a poor deal for us.
Let's say we spend 100 pounds on an advert in each of the five printed directories that I know about. That means we need to take (say) 20 extra room nights of bookings in the year as a direct result to break even - you can't just look at the income; you have do deduct supplies, staffing, servicing, washing, cost of sales and count the extra income only after expenses. And then we're likely to find that extra requests come in for the summer weekends that we're already full, for people who (from a short entry) don't know enough about us to make a good choice, and go away disappointed at "no bar" or another of our distinctive niche features that make us a business hotel.
So - a standard answer to people asking us to pay for an entry in their local directory: "It is not well suited marketing for us, and we have made a decision not to advertise in local directories. We appreciate truly comprehensive directories which provide a listing of all local businesses in a category, and we would like to be line-item listed - but if you are merely providing a selective list of people who will "play ball" with you, please count us us. We're too busy to play ball with everyone who wants a game - sorry!"
The pushy saleswoman who wanted an appointment for her rep and kept telling me what a bargain price they were offering missed my point. The rep from the company with whom we HAVE advertised for three years, but who told me we weren't in the current edition, managed to loose the credibility that Robin Stanbrook - our previous contact (who I greatly respect, and for whom I might have made an exception) had built up.
Posted by gje at 08:12 AM | Comments (0)
Related topics: via article database
Ternary operators alternatives - Perl and Lua lazy operators
"If the gender is male, the answer is him, but if the gender is female, the answer is her". A common situation in programming - [is/are], [him/her], [yes/no], [child/children], [ice/water/steam], [public/private] - and C and Perl and PHP provide the "ternary" operator ? and : to provide a shorthand alternative to a code-heavy if/else structure:
$thing = ($stock == 1) ? "item" : "items";
(That's PHP and Perl to set the "thing" variable to item (singular) or items (plural) depending on the value of $stock being equal (or not) to 1.
In Perl, there's always half a dozen ways to do anything, and the same effect can be created using the lazy and and or keywords ... the logic goes something like this:
i) "If both a and b need to be true and we have already discovered that a is false, we don't need to bother to do test b. And indeed to do test b would be inefficient in such a circumstance. Since (a) is a false value, we'll just return that
ii) "If either a or b needs to be true, and we have already discovered that a is true we don't need to bother to do test b. And indeed to do test b would be inefficient in such a circumstance. Since (a) is a true value, we'll just return that
iii) If we have to move on to test the second item in any circumstance, we may as well just return the value of that item as it's going to be a true value if the whole result is true, and a false value if the whole result is false.
Let's see that in action ... here in Perl:
[trainee@easterton a9_2]$ perl
print (16 and 35)
35[trainee@easterton a9_2]$ perl
print (16 or 35)
16[trainee@easterton a9_2]$
So the result is 16 or 35. By extending that to use both and and or, you'll find that you have a very convenient (and I'm sure planned when the language was written) shorthand for if - else:
[trainee@easterton a9_2]$ perl
print (1 and 4 or 9)
4[trainee@easterton a9_2]$ perl
print (0 and 4 or 9)
9[trainee@easterton a9_2]$
The same thing applies (or rather - ALMOST the same thing) in Lua - where it is especially useful as the language does NOT support the ternary operator:
[trainee@easterton a9_2]$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print (1 and 4 or 9)
4
> print (0 and 4 or 9)
4
> print ( false and 4 or 9)
9
>
I say "almost" the same, because in Lua, the number 0 is a true value, as is an empty string. Only the boolean false, and nil, are really false values. And that's ideal in most circumstances, where you want to be able to accept 0 as just another number - indeed, in Perl 6 you'll be able to say that a number is "0 but true" which rather acknowledges the need for a revision of the "0 is false" mantra.
Posted by gje at 07:27 AM | Comments (0)
Related topics: via article database
Useful links: Lua training, Perl training
August 11, 2009
Ten years in Melksham - looking forward to ten more.
It's ten years to the day since we bought "404" - our home in Melksham Spa. An eerie takeover, with contracts being exchanged in the morning and we arrived to accept vacant possession just as the sky darked for the eclipse ... the great, tall Spa building in the half light, and the crows from the rookery in the nearby avenue of trees flying around and crowing (as crows do!) at the unexpected darkness. Ah yes - I remember that day.
404 was a wreck when we took it over. No power, no gas, no toilets, no drains. Collapsing ceilings, and water coming in through the wall from the neighbours in a lead pipe. Which is why it took up until December that year to get it habitable, and until September 2000 for us to run the first of our coures there. But really, we haven't looked back; the decision to leave Easterton was correct. The decision to make our new home in Melksham was spot on. We're happy here, we've grown in ourselves, and the town is now so much home that I can't see up making any move away in the next ten years.
Posted by gje at 04:56 PM | Comments (0)
Related topics: via article database
Businesses effected by road works in Melksham
"Businesses Open as Usual" say the signs on the High Street in Melksham ... currently (and for 14 weeks) a one-way system while various pavement works are being done.
Who wrote that sign? ... for he certainly doesn't know Melksham!
I took my customers into one of the businesses in the effected area at lunch time today. The electricity was off over the busy lunch time period ... no lighting, no way of opening the till and the staff were relearning the art of manual arithmetic. It seemed that the road workers had disconnected a cable and called in the Electric people to fix it. The road people were then saying "don't ask us - it's the electric people ..." and the electric people were saying "it's the road people who done it - we're just fixing it"
The businesses in the High Street are NOT open as usual - they're open and struggling to look after their customers, and to maintain their customer base. The lack of light to see the goods on sale in the shops, no working tills ... and the absence of hot water to make a cup of coffee, and of electricity to cook - in a cafe, at lunchtime - is something that they were not pre-alerted to. The sound of pneumatic drills, and of alarms going off, in the road works is also effecting their businesses.
Perhaps the person who wrote the signs would care to visit the businesses in the High Street, apologise for the effect that the works are having on them, and make some sort of recompense for lost trade. And if he could explain why the similar works at Lidl last winter took a handful of days and didn't result in any road closures / traffic diversions, but these are to take 14 weeks.
Posted by gje at 02:29 PM | Comments (0)
Related topics: via article database
Finding literals rather than patterns in Lua
Lua's string.find looks for a PATTERN ... it's not as big an sophisticated as a regular expression match (but then it's got nothing like as big a footprint!), but neither is it a literal match. So if I want to search a string for - literally - a ".", I need to protect it. I can do this either with a % character, or by providing an extra true parameter to my find, meaning "I really want literals"
Let's look for a dot:
pos,posend = string.find(sed,".",at,true)
if not pos then break end
string.find returns both the start and the end character numbers of the match; in the case of a single literal character match such as mine here, the two values will be identical and indeed I could have left out ,posend save for my desire to provide an illustration.
Complete example source here, courses on the subject here.
Posted by gje at 06:56 AM | Comments (0)
Related topics: via article database
Useful link: Lua training
Dot, dot, dot in Lua - variable length parameter lists
Lua functions can take any number of parameters - the ... (dot,dot,dot) table given as a parameter 'soaking up' all remaining parameters into the indexed section of the table, rather this "*" in front of a parameter in PHP. (In Perl, the whole list appears in @_)
function join (sep,...)
togo = {...}
There are two styles to calling Lua functions - passing in a comma separated list of parameters in round brackets, or combining them into a table in curly braces:
-- Many parameter variety
str1 = join(" ","This","is","a","Program")
-- Two parameter variety
str2 = join(" ",{"This","is","another","Program"})
And the code within the function can tell the styles apart and adapt itself as appropriate by checking the number and/or type of parameters:
if type(togo[1]) == "table" then
See source code of full example
Illustration - delegates on a private Lua course. We run public Lua training courses at our centre in Melksham, Wiltshire, England and private course onsite worldwide.
Posted by gje at 06:38 AM | Comments (0)
Related topics: via article database
Useful link: Lua training
August 10, 2009
The indexed and hashed parts of a Lua table
A Lua table contains both a sequentially indexed section and a hash keyed section (and a few other things too). When you sort the table, you sort only the index keyed section, when you use ipairs you use just the first (indexed) section, but when you use pairs you use the whole table. See source code example.
Because of these two sections, a table is the only Lua native collection object (userdata is available via C), and it is used for Vectors, Lists, Tuples, Arrays, Stacks, queues, dictionaries, associative arrays, hashed and objects. After all, Lua has a tiny footprint at it's great to be able to use a single type in so many ways.
We teach Programming in Lua at our Melksham Training Centre regularly, and can run on site courses in many countries to our standard agenda, or to an agenda tuned for your specific needs.
Posted by gje at 06:34 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
Automatically initialising Lua variables the first time
In Lua, you need to initialise variables before you perform arithmetic on them, but you CAN test them (and if they don't exist, they will return false).
For example, this code initialises a variable to 0 if it doesn't exist, or takes its current value, then adds 1 to it straight away before saving it tack in the same variable.
callcounter = (callcounter or 0 ) +1
See that in use in full source code, within a function where it in effect becomes a static variable , here
Posted by gje at 06:30 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
Reading a data file and sensing EOF in Lua
In Lua, the standard table io includes an io.open code element that lets you open a file. This returns a userdata to you (looks like a table but isn't - it's a C accessible structure) from which you can run the read code. Empty lines return an empty string (in Lua this is a TRUE value, unlike other languages), and at the end of file a nil is returned. See source code
You do need to write your reading loop as while true do, as you are not allowed to assign a value to a variable within the test condition - the = sign is not an operator in the same way that it is in other languages.
Covered on our Learning to Program in Lua course.
Posted by gje at 06:25 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
World Flags in your PHP pages
The world's flags are often used to give a quick visible international indication of countries (sidestepping the issue I had yesterday, where I was translating into ten languages and wanted links to each other language on each page and - well - what IS the Finnish for Italy?)
So I have found an Icon set for free download and installed all the flags - let me test it out by listing (flaggily) the countries I have trained / visited on business/ visited just for pleasure:
. But I suspect there are one or two there which you'll find aren't in the common 'vocab'.
I have also added the flags on our "Do you train in my country?" page at http://www.wellho.net/resources/countries.html, having the server (in PHP checking) that we actually HAVE a flag before we try and send it out. Just missing East Timor, Yugoslavia (but we have several of the countries that have come out of YU in the list above!), Zaire (reason unknown), and Antarctica. By adding this dynamic check into PHP, we're able to add flags and take them away without having to go through and change the script line by line ... and without risk of broken image icons! Here is a code snippet (yes, I am using the MaxMind GeoIPLite API and the array of country codes that it gives me!).
$flower = strtolower($GEOIP_COUNTRY_CODES[$k2]).".png";
if (file_exists("$_SERVER[DOCUMENT_ROOT]/flag/$flower")) {
print "<td class=body><img src=http://www.wellho.net/flag/$flower> ";
} else {
print "<td class=body> ";
}
The flags are in the public domain, so there is no requirement for me to attribute them. However, I would like to thank Mark James for providing them here, and I'm going to quote his copyright statement from another of his icon sets, as I like what he does and how he says it: I love to hear of my work being used, feel encouraged to send an email with a link or screen shot of the icons in their new home to mjames at gmail dot com. This work is licensed under a Creative Commons Attribution 2.5 License. This means you may use it for any purpose, and make any changes you like. All I ask is that you include a link back to this page in your credits if possible.
Posted by gje at 05:30 PM | Comments (0)
Related topics: via article database
Useful link: PHP training
Training Classes in other tongues
Do we train in Finnish or in French, in Dutch or Danish? No - we don't, but many technical people in Finland and France, in the Netherlands and Denmark have English as an excellent second language and can gainfully take our courses - especially those courses which are so niche that there is no alternative available in their first tongue.
I receive a regular 'spam' telling me that my site is not well seen by foreign language search engines, and I acknowledge what it's telling me. But to some extent that's how I want it to be; little point in building up a market for training in, say, Urdu if we can't deliver a course in that language. Yet I WOULD like to reach people who have good English, and who live in our European proximity. I have rationalised that down to adding pages to our site in the main languages of countries that are close to us, with a note on these pages indicating that they're about public courses presented in English, but with the ability (through a translator) to give the course successfully in Spanish or another language. And I have rationalised that I would be pressing the case too far to support languages from further afield, or minority UK languages (on the grounds that people in the UK would be searching in English!)
Here are some links to those pages ...
English French Spanish Italian German Portugese Dutch Daninsh Norwegian Swedish Finnish.
Englanti, Ranska, Espanja, Italia, Saksa, Portugali, Hollanti, Tanska, Norja, Ruotsi ja Suomi
Anglais, français, espagnol, italien, allemand, portugais, néerlandais, danois, norvégien, suédois et finlandais
Englisch, Französisch, Spanisch, Italienisch, Deutsch, Portugiesisch, Niederländisch, Dänisch, Norwegisch, Schwedisch und Finnisch
Engels, Frans, Spaans, Italiaans, Duits, Portugees, Nederlands, Deens, Noors, Zweeds en Fins
Inglés, francés, español, italiano, alemán, portugués, holandés, danés, noruego, sueco y finés
Inglese, francese, spagnolo, italiano, tedesco, portoghese, olandese, danese, norvegese, svedese e finlandese
Inglês, Francês, Espanhol, Italiano, Alemão, Português, holandês, dinamarquês, norueguês, sueco e finlandês
Engelsk, fransk, spansk, italiensk, tysk, portugisisk, hollandsk, dansk, norsk, svensk og finsk
Engelska, franska, spanska, italienska, tyska, portugisiska, nederländska, danska, norska, svenska och finska
Engelsk, fransk, spansk, italiensk, tysk, portugisisk, nederlandsk, dansk, norsk, svensk og finsk
Posted by gje at 07:34 AM | Comments (0)
Related topics: via article database
August 09, 2009
Koulutus, Open Source tietokone kielillä
Uusi täällä? Olemme tekijöiden ja tarjoajien monenlaisia Open Source koulutusta, joka perustuu Melksham, Englannissa. Uskomme huolehtia asiakkaidemme ja antaa takaisin yhteiskunnalle liikaa. Onko olemme koulutettu olet, voit selata materiaali:
• artikkelit ratkaisu keskus
• vinkkejä ja päivitykset The Horse's Mouth
• Kysymys ja vastaus kautta Opentalk foorumi.
ja siellä on enemmän tietoa meistä täällä.
Tai valitse Open Source aihe:
• Python Programming
• PHP-ohjelmointi
• Perl Programming
• Ruby-ohjelmointi
• LUA Ohjelmasuunnittelu
• Tcl Ohjelmasuunnittelu
• C-ja C + +-ohjelmointi
• Java-ohjelmointi
• Linux-käyttöjärjestelmän
• MysQL Database
• Apache httpd & Tomcat
Ominaisuudet kaikkien julkisten Kurssit sisältävät:
• esittämä oma ammattitaitoinen henkilökunta ohjaajia
• Suurin tietenkin koko 8 valtuutettua
• Suorita oman mukautetun-fitted koulutuskeskus
• asuntoloiden käytettävissä delegates
• 1 siirtää vähintään - aina ajaa kirjataan luonnollisesti
• Opetusmateriaali kirjoittanut meille ja tarkistetaan usein
Ole hyvä lukea tätä sivustoa lisätietoja tai lähetä meille sähköpostia kautta info@wellho.net tai soita meille +44 (0) 1225 708225, jos haluat keskustella yrityksesi tai henkilökohtaisia vaatimuksia.
Kursseistamme ovat erilaisia ... [detail]
• Lämpimästi tervetuloa edeltävänä iltana
• Complimentary rautatieasema poimia
• Ei vähimmäismäärä; kursseja aina
• Suorita oman koulutuskeskus
• Pysy meille - me myös hotellin
• Kurssit esittämä kirjailija
• Enintään vain 8 valtuutettua kohti tietenkin
• Post-kurssi tukea sisältyy
Ajoitettu Kurssit
Käyttöönottokustannukset Apache ja Tomcat
Käyttöönottokustannukset LAMP - Linux, Apache, MysQL Perl / PHP / Python
Linux Basics
Linux Administration
Linux Web-palvelin
Oppimisen ohjelma PHP
Learning to Program Pythonilla
Learning to-ohjelman Java
Oppimisen ohjelma LUA
Oppimisen ohjelma Ruby
Oppimisen ohjelma Tcl
Learning to Program C
Learning to-ohjelman C + +
Oppimisen ohjelma Perl / Perl Programming
LUA Ohjelmasuunnittelu
PHP-ohjelmointi
PHP Techniques
Object Oriented ohjelmointi PHP
The MysQL Relaatiotietokanta
Python-ohjelmointi
Oppimisen ohjelma Perl / Perl Programming
Käyttäen Perl Webissä
Perl Laajoissa hankkeissa
Programming in C
C + + C Programmers
C ja C + +-ohjelmointi
Java Bootcamp
Ruby-ohjelmointi
Tcl Ohjelmasuunnittelu
Tcl - TK Toolkit
Säännölliset lausekkeet
Julkisen kurssit esitetään Englanti. Jos puhuu hyvää Englanti on toinen kieli, kurssi on sopiva sinulle. Olemme myös suorittaa yksityisen tietenkin asiakkaiden sivustoja, joissa on hyvä paikallisten käännöspalvelu voidaan varmistaa, että saat kaiken irti aikana, jos et ole Englanti puhujan.
Englanti, Ranska, Espanja, Italia, Saksa, Portugali, Hollanti, Tanska, Norja, Ruotsi ja Suomi
Posted by gje at 03:03 PM | Comments (0)
Related topics: via article database
ldning, Open Source dator språk
Ny här? Vi och leverantörer av ett brett spektrum av Open Source-utbildning, som är baserad i Melksham, England. Vi tror på att ta hand om våra kunder och ge tillbaka till samhället också. Huruvida vi har tränat dig, du är välkommen att bläddra i vårt material:
• artiklar i lösningen centrum
• tips och uppdateringar på Horse's Mouth
• Fråga och Svar via Opentalk Forum.
och det finns mer om oss här.
Eller välj Open Source Ämne:
• Python Programming
• PHP Programmering
• Perl Programming
• Ruby Programming
• Lua Programming
• Tcl Programmering
• C och C + + programmering
• Java-programmering
• Linux operativsystem
• MysQL Database
• Apache httpd & Tomcat
Funktioner för alla våra allmänna kurser inkluderar:
• Presenteras av vår egen personal handledare
• Maximal naturligtvis storleken 8 delegater
• Kör på våra egna specialanpassade monteras utbildningscentrum
• bostäder till delegater
• 1 delegera minst - vi alltid köra din bokade kurs
• Utbildning materialet är skrivet av oss och revideras ofta
Vänligen surfa på hemsidan för mer information, eller skicka ett mail till oss via info@wellho.net eller ring oss på +44 (0) 1225 708225 om du vill diskutera ditt företag eller personliga behov.
Våra kurser är olika ... [detaljer]
• Varmt välkomna kvällen före
• Complimentary järnvägsstation plocka upp
• Inget minimum, kurser alltid köra
• Kör på vårt eget utbildningscenter
• Stanna hos oss - vi är också ett hotell
• Kurser som presenteras av författaren
• Högst bara 8 deltagare per kurs
• Post-kurs som ingår
Schemalagda kurser
Deploying Apache och Tomcat
Deploying LAMP - Linux, Apache, MysQL Perl / PHP / Python
Linux Basics
Linux Administration
Linux Webbserver
Att lära sig att programmera i PHP
Att lära sig programmet i Python
Att lära sig programmet i Java
Att lära sig att programmera i Lua
Att lära sig programmet i Ruby
Att lära sig programmet i Tcl
Att lära sig programmet i C
Att lära sig att programmera i C + +
Att lära sig att programmera Perl / Perl Programming
Lua Programming
PHP Programming
PHP Techniques
Objektorienterad programmering med PHP
Den MysQL relationsdatabas
Python Programming
Att lära sig att programmera i Perl / Perl Programming
Använda Perl på webben
Perl för större projekt
Programmering i C
C + + för C-programmerare
C och C + + programmering
Java Bootcamp
Ruby Programming
Tcl Programmering
Tcl - den Tk Toolkit
Regular Expressions
Våra allmänna kurser presenteras på engelska. Om du talar bra engelska som andra språk, kursen kommer att vara lämpliga för dig. Vi kör även privat kurs i kundernas anläggningar, där en god lokal översättningstjänsten kan se till att du får ut det mesta av kursen om du inte är en Engelsk högtalare.
Engelska, franska, spanska, italienska, tyska, portugisiska, nederländska, danska, norska, svenska och finska
Posted by gje at 02:59 PM | Comments (0)
Related topics: via article database
Opplæring, Open Source datamaskinen språk
Ny her? Vi forfattere og leverer et bredt spekter av Open Source kurs, basert i Melksham, England. Vi tror på utkikk etter våre kunder og gi tilbake til samfunnet også. Om vi har trent deg, du er velkommen til å bla gjennom vår materiale:
• artikler i løsningen sentrum
• tips og oppdateringer på The Horse's Kjeften
• spørsmål og svar via Opentalk Forum.
og det er mer om oss her.
Eller velg Open Source subject:
• Python Programmering
• PHP programmering
• Perl Programming
• Ruby Programming
• lua Programmering
• Tcl Programmering
• C og C + + programmering
• Java-programmering
• Linux operativsystem
• MysQL Database
• Apache httpd & Tomcat
Valg av alle våre offentlige kurs inkluderer:
• Presentert av vårt eget profesjonelt personale veiledere
• Maksimal selvsagt størrelsen 8 delegater
• Kjør på vår egen tilpassede utstyrt treningssenter
• Eiendom overnatting for deltakerne
• 1 representant minst - vi kjører alltid din booket kurs
• Opplæring materialet er skrevet av oss og revideres ofte
Vennligst bla gjennom nettstedet for mer informasjon, eller kontakt oss via info@wellho.net eller ring oss på +44 (0) 1225 708225 hvis du ønsker å diskutere din bedrifts eller personlige behov.
VÃ¥re kurs er annerledes ... [detaljer]
• En varm velkomst natten før
• Complimentary jernbanestasjonen plukke opp
• Ingen minimum tall; kurs kjører alltid
• Kjør på vår egen treningssenter
• Bli med oss - vi er også et hotell
• Kurs presentert av forfatteren
• Maksimum kun 8 deltakere per kurs
• Post-kurs support inkludert
Planlagte Kurs
Distribuere Apache og Tomcat
Distribuere LAMP - Linux, Apache, MysQL Perl / PHP / Python
Linux Basics
Linux administrasjon
Linux Web Server
Lære å programmere i PHP
Learning to Program i Python
Learning to Program i Java
Lære å programmere i lua
Learning to Program i Ruby
Learning to Program i Tcl
Learning to Program i C
Lære å programmere i C + +
Learning to Program i Perl / Perl Programming
Lua Programmering
PHP-programmering
PHP Teknikker
Objektorientert programmering med PHP
Den MysQL relasjonsdatabase
Python Programmering
Lære å programmere i Perl / Perl Programming
Bruke Perl på nettet
Perl for større prosjekter
Programmering i C
C + + for C programmerere
C og C + + programmering
Java BootCamp
Ruby Programming
Tcl Programmering
Tcl - den TK Toolkit
Regular Expressions
Våre offentlige kursene er presentert på engelsk. Hvis du snakker godt engelsk som andre språk, vil være egnet for deg. Vi kan også kjøre private kurs på kunde-områder, hvor en god lokal oversettelse kan sikre at du får mest av kurset dersom du ikke er en engelsk høyttaler.
Engelsk, fransk, spansk, italiensk, tysk, portugisisk, nederlandsk, dansk, norsk, svensk og finsk
Posted by gje at 02:55 PM | Comments (0)
Related topics: via article database
Uddannelse, Open Source computer sprog
Ny her? Vi forfattere og udbydere af en bred vifte af Open Source-kurser, der er baseret i Melksham, England. Vi tror på søger efter vores kunder og give tilbage til samfundet også. Eller ej, vi har trænet dig, er du velkommen til at gennemse vores materiale:
• artikler i opløsningen centrum
• tips og opdateringer på hestens Mouth
• Spørgsmål og Svar via Opentalk Forum.
og der er mere om os her.
Eller vælg Open Source emne:
• Python Programming
• PHP Programmering
• Perl Programmering
• Ruby Programming
• lua Programmering
• Tcl Programmering
• C og C + + Programmering
• Java Programming
• Linux operativsystem
• MysQL Database
• Apache httpd & Tomcat
Karakteristika for alle vores offentlige kurser kan nævnes:
• Præsenteret af vores egne professionelle personale vejledere
• Maksimal naturligvis størrelse 8 delegerede
• Kør på vores egne brugerdefinerede-udstyret uddannelsescenter
• boliger til rådighed for delegerede
• 1 uddelegere minimum - vi altid køre din bestilte naturligvis
• Uddannelse materiale skrevet af os og revideres ofte
Please browse denne hjemmeside for yderligere oplysninger, eller email os via info@wellho.net eller ring til os på +44 (0) 1225 708225, hvis du ønsker at drøfte din virksomhed eller personlige krav.
Vores kurser er forskellige ... [detaljer]
• En varm velkomst aftenen før
• Gratis banegård pick up
• nr. minimum numre; kurser altid løbe
• Kør på vores eget uddannelsescenter
• Hold dig til os - vi er også et hotel
• Kurser præsenteret af forfatteren
• Højst kun 8 delegerede pr kursus
• Post-kursus støtte inkluderet
Planlagte Kurser
Implementering af Apache og Tomcat
Implementering LAMP - Linux, Apache, MysQL Perl / PHP / Python
Linux Basics
Linux Administration
Linux Web Server
Lære at programmere i PHP
Learning to Program i Python
Learning to Program i Java
Lære at programmere i lua
Learning to Program i Ruby
Learning to Program i Tcl
Learning to Program i C
Lære at programmere i C + +
Learning to Program i Perl / Perl Programmering
LUA Programmering
PHP Programmering
PHP Teknikker
Objektorienteret programmering med PHP
Den MysQL relationel database
Python Programming
Lære at programmere i Perl / Perl Programmering
Brug af Perl på nettet
Perl for større projekter
Programmering i C
C + + for C Programmører
C og C + + Programmering
Java Bootcamp
Ruby Programming
Tcl Programmering
Tcl - den Tk Toolkit
Regular Expressions
Vores offentlige kurser præsenteres på engelsk. Hvis du taler godt engelsk som andet sprog, naturligvis vil være egnede til dig. Vi kører også private kursus om kunden lokaliteter, hvor en god lokal oversættelsestjenesten kan sikre, at du får mest muligt ud af kurset, hvis du ikke er en engelsk højttaler.
Engelsk, fransk, spansk, italiensk, tysk, portugisisk, hollandsk, dansk, norsk, svensk og finsk
Posted by gje at 02:52 PM | Comments (0)
Related topics: via article database
Opleiding, Open Source computertalen
Nieuw hier? We auteurs en aanbieders van een breed scala van Open Source opleidingen, gebaseerd op Melksham, Engeland. Wij geloven in de zorg op onze klanten en geven terug aan de gemeenschap ook. Of wij al dan niet hebt getraind u, u bent welkom om naar onze materiaal:
• voorwerpen in de oplossing centrum
• tips en updates over the Horse's Mouth
• Vraag en Antwoord via de Opentalk Forum.
en er is meer over ons hier.
Of kies Open Source onderwerp:
• Python Programming
• PHP Programmering
• Perl Programmeren
• Programming Ruby
• Lua Programmeren
• Tcl Programmering
• C en C + + Programming
• Java Programming
• Linux Operating System
• MysQL Databank
• Apache httpd & Tomcat
Kenmerken van al onze openbare cursussen omvatten:
• Presentatie door onze eigen professionele medewerkers mentoren
• Maximale grootte natuurlijk 8 afgevaardigden
• Run op ons eigen maat uitgerust opleidingscentrum
• woningen beschikbaar voor gedelegeerden
• 1 afgevaardigde minimum - wij altijd uw geboekte cursus
• Opleiding materiaal geschreven door ons en herziene vaak
Kunt u deze site voor nadere informatie, of email ons via info@wellho.net of bel ons op +44 (0) 1225 708225 of u wenst te bespreken uw bedrijf of persoonlijke wensen.
Onze cursussen zijn anders ... [detail]
• Een warm welkom voor de nacht
• Complimentary station af te halen
• Geen minimum nummers; cursussen altijd
• Run op ons eigen opleidingscentrum
• Blijf bij ons - wij zijn ook een hotel
• Cursussen gepresenteerd door de auteur
• Maximum slechts 8 deelnemers per cursus
• Post-gangen ondersteuning inbegrepen
Geplande cursussen
Deploying Apache en Tomcat
Deploying LAMP - Linux, Apache, MysQL Perl / PHP / Python
Linux Basics
Linux Administration
Linux Web Server
Leren programmeren in PHP
Leren programmeren in Python
Leren programmeren in Java
Leren programmeren in Lua
Leren programmeren in Ruby
Leren Programma in Tcl
Leren programmeren in C
Leren programmeren in C + +
Leren programmeren in Perl / Perl Programmeren
Lua Programmeren
PHP Programmering
PHP Technieken
Objectgeoriënteerd programmeren met PHP
De MysQL Relationele database
Python Programming
Leren programmeren in Perl / Perl Programmeren
Het gebruik van Perl op het web
Perl voor grotere projecten
Programmeren in C
C + + voor C programmeurs
C en C + + Programming
Java Bootcamp
Ruby programmeren
Tcl Programmering
Tcl - de Tk Toolkit
Reguliere Expressies
Onze publieke cursussen worden aangeboden in het Engels. Als je spreekt goed Engels als tweede taal, de cursus geschikt voor jou. Wij voeren ook prive cursus over klanten, waar een goede lokale vertaling dienst kan ervoor zorgen dat u het meeste uit de loop als je geen Engels luidspreker.
Engels, Frans, Spaans, Italiaans, Duits, Portugees, Nederlands, Deens, Noors, Zweeds en Fins
Posted by gje at 02:49 PM | Comments (0)
Related topics: via article database
Formação, Open Source computador lÃnguas
Bem-vindo. Novo aqui? Nós somos os autores e fornecedores de uma vasta gama de cursos de formação de código aberto, baseado em Melksham, Inglaterra. Acreditamos em cuidar dos nossos clientes e devolver para a comunidade também. Quer ou não temos treinado, você está livre para navegar em nosso material:
• Artigos no centro da solução
• dicas e atualizações no do cavalo, boca
• Pergunta e Resposta através do Fórum Opentalk.
e não há mais sobre nós aqui.
Ou selecione Open Source assunto:
• Programação Python
• Programação PHP
• Perl Programming
• Programação Ruby
• Lua Programação
• Tcl Programação
• C e C + + Programação
• Programação Java
• Sistema Operacional Linux
• Banco de Dados MySQL
• Apache Tomcat & httpd
CaracterÃsticas de todos os nossos públicos cursos incluem:
• Apresentado por nossa própria equipe profissional tutores
• Máximo curso tamanho 8 delegados
• Executar a nossa própria personalizados-equipado centro de formação
• habitação disponÃvel para os delegados
• 1 delegado mÃnima - sempre que executar o seu curso reservado
• Formação materiais escritos por nós e muitas vezes revisto
Navegue este site para mais informações, envie um e-mail ou através info@wellho.net ou ligue para +44 (0) 1225 708225-nos sobre se gostaria de discutir a sua empresa ou exigências pessoais.
Nossos cursos são diferentes ... [detalhes]
• Uma calorosa recepção na noite anterior
• Complimentary estação ferroviária pegar
• Sem o número mÃnimo; cursos sempre executado
• Executar no nosso centro de formação
• Fique conosco - também somos um hotel
• Cursos apresentados pelo autor
• Máximo de apenas 8 delegados por curso
• Pós-curso apoio incluiu
Cursos Agendados
Deploying Apache e Tomcat
Implantando LAMP - Linux, Apache, MySQL Perl / PHP / Python
Linux Basics
Linux Administração
Linux Web Server
Aprender a programar em PHP
Aprender a programar com Python
Programa de Aprendizagem em Java
Aprender a programar em Lua
Aprender a programar com Ruby
Programa de Aprendizagem em Tcl
Programa de Aprendizagem em C
Aprender a programar em C + +
Programa de Aprendizagem em Perl / Perl Programming
Programação Lua
Programação PHP
PHP Técnicas
Programação Orientada a Objetos com PHP
O MySQL banco de dados relacional
Programação Python
Aprender a programar em Perl / Perl Programming
Usando Perl na Web
Perl para grandes projectos
Programação em C
C + + para programadores C
C e C + + Programação
Java Bootcamp
Ruby Programming
Tcl Programação
Tcl - o Tk Toolkit
Expressões Regulares
Nosso público cursos são apresentados em Inglês. Se você falar bem Inglês como segunda lÃngua, o curso será adequado para você. Também executar privado curso sobre clientes locais, onde um bom local serviço de tradução pode garantir que você obtenha o máximo do curso se você não for um falante Inglês.
Inglês, Francês, Espanhol, Italiano, Alemão, Português, holandês, dinamarquês, norueguês, sueco e finlandês
Posted by gje at 02:45 PM | Comments (0)
Related topics: via article database
Ausbildung, die Open-Source-Sprachen
Willkommen. Neu hier? Wir sind Autoren und Anbieter einer breiten Palette von Open-Source-Schulungen, in Melksham, England. Wir glauben an die Betreuung unserer Kunden und die zurück an die Gemeinde zu. Unabhängig davon, ob wir nicht trainiert haben Sie, Sie sind willkommen, um unser Material:
• Artikel in der Lösung Zentrum
• Tipps und Updates auf The Horse's Mouth
• Frage und Antwort über die Opentalk Forum.
und es gibt mehr über uns hier.
Oder wählen Sie Open-Source-Themen:
• Python-Programmierung
• PHP-Programmierung
• Perl-Programmierung
• Ruby-Programmierung
• Lua Programming
• Tcl-Programmierung
• C und C + +-Programmierung
• Java-Programmierung
• Betriebssystem Linux
• MySQL-Datenbank
• Apache httpd & Tomcat
Funktionen aller öffentlichen Kurse beinhalten:
• Präsentiert von unserem eigenen Personal Tutoren
• Maximale Größe 8 natürlich Delegierten
• Führen Sie in unserem eigenen ausgestattetes Trainingszentrum
• Wohnheim für Delegierte
• 1 Delegierter Minimum - wir immer Ihre gebuchten Kurs
• Training Material von uns überarbeitet und oft
Bitte sehen Sie diese Seite für weitere Details, oder per E-Mail über info@wellho.net oder rufen Sie uns an +44 (0) 1225 708225 Wenn Sie möchten, um Ihr Unternehmen oder Ihre persönlichen Anforderungen.
Unsere Kurse sind anders ... [Detail]
• Ein herzliches Willkommen in der Nacht vor
• Kostenloser Bahnhof abholen
• Keine Mindestanzahl; Kurse immer
• Führen Sie in unserem eigenen Schulungszentrum
• Bleiben Sie mit uns - wir sind auch ein Hotel
• Kurse, die von dem Autor
• Maximum von nur 8 Teilnehmer pro Kurs
• Post-Gang-Support
Geplante Kurse
Einsatz von Apache und Tomcat
Bereitstellen LAMP - Linux, Apache, MySQL Perl / PHP / Python
Linux-Grundlagen
Linux-Administration
Linux-Web-Server
Lernen zu programmieren in PHP
Learning to Program in Python
Lernen, wie man in Java-Programm
Lernen zu programmieren in Lua
Lernen, wie man in Ruby-Programm
Lernen, wie man in Tcl programmieren
Learning to Program in C
Lernen, wie man in C + + programmieren
Learning to Program in Perl / Perl-Programmierung
Lua Programming
PHP-Programmierung
PHP-Techniken
Objektorientierte Programmierung mit PHP
Die relationale Datenbank MySQL
Python-Programmierung
Learning to-Programm in Perl / Perl-Programmierung
Mit Perl auf dem Webserver
Perl für größere Projekte
Programmierung in C
C + + für C-Programmierer
C und C + +-Programmierung
Java-Bootcamp
Ruby-Programmierung
Tcl-Programmierung
Tcl - die Tk Toolkit
Reguläre Ausdrücke
Unsere öffentlichen Kurse werden in Englisch. Wenn Sie sprechen gut Englisch als zweite Sprache, der Kurs wird für Sie geeignet. Wir führen auch private Kunden natürlich auf Seiten, wo eine gute lokale Übersetzungsdienst können sicherstellen, dass Sie das Beste aus dem Kurs, wenn Sie kein Englisch-Sprecher.
Englisch, Französisch, Spanisch, Italienisch, Deutsch, Portugiesisch, Niederländisch, Dänisch, Norwegisch, Schwedisch und Finnisch
Posted by gje at 02:40 PM | Comments (0)
Related topics: via article database
Formazione, Open Source computer lingue
Benvenuto. Nuovo qui? Siamo autori e dei fornitori di una vasta gamma di corsi di formazione Open Source, con sede a Melksham, Inghilterra. Crediamo nella cura dei nostri clienti e restituendo alla comunità troppo. Sia o non abbiamo addestrato voi, siete i benvenuti a navigare nel nostro materiale:
• articoli in centro la soluzione
• consigli e aggiornamenti su The Horse's Mouth
• Domanda e Risposta tramite il Opentalk Forum.
e c'è di più su di noi qui.
Oppure selezionare Open Source oggetto:
• Python Programming
• Programmazione PHP
• Programmazione in Perl
• Programmazione Ruby
• Lua Programmazione
• Programmazione di Tcl
• C e C + + Programmazione
• programmazione Java
• Sistema operativo Linux
• Database MySQL
• httpd Apache & Tomcat
Caratteristiche di tutti i nostri corsi di pubblico comprendono:
• Presentato dal nostro staff professionale tutor
• Massimo corso dimensioni 8 delegati
• Esegui personalizzati presso il nostro centro di formazione-munito
• Case alloggio per i delegati
• 1 delegato minimo - abbiamo sempre eseguire il corso
• Formazione di materiale scritto da noi e spesso rivisto
Si prega di navigare su questo sito per ulteriori dettagli, o via e-mail tramite info@wellho.net oppure chiama il +44 (0) 1225 708225 se volete discutere la vostra azienda o personali esigenze.
I nostri corsi sono diversi ... [dettaglio]
• Un caloroso benvenuto la sera prima
• Complimentary stazione ferroviaria di pick up
• n. minimo numeri; corsi sempre eseguito
• Esecuzione a nostro centro di formazione
• Resta con noi - siamo anche un albergo
• Corsi presentato dall'autore
• Il numero massimo di soli 8 delegati per ogni corso
• Post-corso supporto incluso
corsi programmati
Implementazione e Apache Tomcat
Distribuzione LAMP - Linux, Apache, MySQL Perl / PHP / Python
Nozioni di base di Linux
Linux Amministrazione
Linux Server Web
Imparare a programmare in PHP
Imparare a programmare in Python
Imparare a programmare in Java
Imparare a programmare in Lua
Imparare a programmare in Ruby
Imparare a programmare in Tcl
Imparare a programmare in C
Imparare a programmare in C + +
Imparare a programmare in Perl / Perl Programmazione
Lua Programmazione
PHP Programming
PHP Tecniche
Di programmazione Object Oriented con PHP
Il database relazionale MySQL
Programmazione Python
Imparare a programmare in Perl / Perl Programmazione
Utilizzo di Perl sul Web
Perl per i progetti più grandi
Programmazione in C
C + + per C Programmatori
C e C + + Programmazione
Java Bootcamp
Programming Ruby
Tcl Programmazione
Tcl - la Tk Toolkit
Espressioni regolari
Il nostro pubblico corsi sono presentati in inglese. Se si parla bene l'inglese come seconda lingua, il corso sarà adatto per voi. Abbiamo anche eseguito privato corso di clienti, dove un buon servizio di traduzione locale può garantire che per ottenere il massimo dal corso se non sono un oratore inglese.
Inglese, francese, spagnolo, italiano, tedesco, portoghese, olandese, danese, norvegese, svedese e finlandese
Posted by gje at 02:37 PM | Comments (0)
Related topics: via article database
Formación, de los lenguajes de código abierto
Bienvenido. Nueva aqu� Somos los autores y proveedores de una amplia gama de cursos de formación de código abierto, con sede en Melksham, Inglaterra. Creemos en el cuidado de nuestros clientes y dar a la comunidad también. O no hemos entrenado usted, le invitamos a navegar nuestro material:
• artÃculos en el centro de la solución
• consejos y novedades sobre la boca del caballo
• Preguntas y respuestas a través de la OpenTalk Foro.
y hay más de nosotros aquÃ.
O seleccione Open Source tema:
• Programación Python
• Programación PHP
• Programación en Perl
• Programación Ruby
• Programación Lua
• Programación Tcl
• C y C + + Programación
• Programación en Java
• Sistema Operativo Linux
• base de datos de MySQL
• httpd Apache y Tomcat
CaracterÃsticas de todos nuestros cursos incluyen:
• Presentado por nuestro propio personal profesional tutores
• Máximo tamaño curso 8 delegados
• Ejecutar en nuestro propio centro de formación equipadas
• Residencial alojamiento disponibles para los delegados
• 1 delegado mÃnimo - que siempre se reserva su curso
• Formación de material escrito y revisado por nosotros a menudo
Le invitamos a navegar este sitio web para obtener más información, o envÃenos un correo electrónico a través de info@wellho.net o llámenos al +44 (0) 1225 708225 si desea discutir sus necesidades personales o de empresa.
Nuestros cursos son diferentes ... [detalles]
• Una cálida bienvenida la noche anterior
• Complementarios recoger la estación de tren
• No hay número mÃnimo; cursos siempre se
• Ejecutar en nuestro propio centro de formación
• Quédese con nosotros - que son también un hotel
• Cursos presentados por el autor
• Máximo de sólo 8 delegados por curso
• Post-curso incluye apoyo
Cursos programados
El despliegue de Apache y Tomcat
Desplegar LAMP - Linux, Apache, MySQL Perl / PHP / Python
Linux Básico
Linux Administración
Servidor Web Linux
Aprender a programar en PHP
Aprender a programar en Python
Aprender a programar en Java
Aprender a programar en Lua
Aprender a programar en Ruby
Aprender a programar en Tcl
Aprender a programar en C
Aprender a programar en C + +
Aprender a programar en Perl / Programación en Perl
Programación Lua
Programación PHP
Técnicas de PHP
Programación Orientada a Objetos con PHP
La base de datos relacionales MySQL
Programación Python
Aprender a programar en Perl / Programación en Perl
Uso de Perl en la Web
Perl para proyectos más grandes
Programación en C
C + + C para programadores
C y C + + Programación
Java Bootcamp
Programación Ruby
Tcl Programación
Tcl - la Tk Toolkit
Expresiones regulares
Nuestro público se presentan en los cursos de Inglés. Si usted habla bien Inglés como segundo idioma, el curso será adecuado para usted. También ejecutar privado curso de cliente, en donde un buen servicio de traducción puede asegurar que usted obtenga el máximo provecho de el curso si no es un orador Inglés.
Inglés, francés, español, italiano, alemán, portugués, holandés, danés, noruego, sueco y finés
Posted by gje at 02:33 PM | Comments (0)
Related topics: via article database
Formation, des langages Open Source
Bienvenue. Nouveau? Nous sommes les créateurs et les fournisseurs d'une large gamme de cours de formation Open Source, basée à Melksham, en Angleterre. Nous croyons à s'occuper de nos clients et de redonner à la communauté aussi. La question de savoir si nous avons formé, vous êtes invités à parcourir notre matériel:
• des articles dans le centre de solutions
• des conseils et des mises à jour sur The Horse's Mouth
• Questions et réponses sur le Forum Opentalk.
et il n'y a plus à propos de nous ici.
Ou sélectionnez Open Source sujet:
• Programmation Python
• Programmation PHP
• Programming Perl
• Programming Ruby
• Lua Programming
• Programmation Tcl
• C et C + + Programming
• Programmation Java
• Système d'exploitation Linux
• Base de données MySQL
• httpd Apache et Tomcat
Caractéristiques de tous nos cours incluent:
• Présenté par notre propre personnel professionnel des tuteurs
• la taille maximale des cours de 8 délégués
• Exécuter, à notre propre centre de formation équipé
• Logements disponibles pour les délégués
• 1 délégué minimum - nous avons toujours exécuter vos réservations cours
• Le matériel de formation par écrit et révisé nous souvent
S'il vous plaît consulter ce site pour plus de détails, ou nous envoyer un courriel via info@wellho.net ou appelez-nous au +44 (0) 1225 708225 si vous souhaitez discuter de votre entreprise ou personnels.
Nos cours sont différents ... [détails]
• Un accueil chaleureux de la nuit avant
• Complimentary gare ramasser
• Pas de nombre minimum des cours toujours courir
• Exécuter, à notre propre centre de formation
• Reste avec nous - nous sommes aussi un hôtel
• Les cours présentés par l'auteur
• maximum de 8 délégués par cours
• Post-cours de soutien inclus
Cours réguliers
Déploiement d'Apache et Tomcat
Déploiement LAMP - Linux, Apache, MySQL Perl / PHP / Python
Linux Basics
Administration Linux
Linux Web Server
Apprendre à programmer en PHP
Apprendre à programmer en Python
Apprendre à programmer en Java
Apprendre à programmer en Lua
Apprendre à programmer en Ruby
Apprendre à programmer en Tcl
Apprendre à programmer en C
Apprendre à programmer en C + +
Apprendre à programmer en Perl / Perl Programming
Lua Programming
Programmation PHP
PHP Techniques
La programmation orientée objet avec PHP
La base de données relationnelle MySQL
Programmation Python
Apprendre à programmer en Perl / Perl Programming
Utilisation de Perl sur le Web
Perl pour les grands projets
Programmation en C
C + + pour les programmeurs C
C et C + + Programming
Java Bootcamp
Programming Ruby
Programmation Tcl
Tcl - Tk
Expressions régulières
Nos cours sont présentés en anglais. Si vous parlez bien l'anglais comme langue seconde, le cours sera adapté à votre cas. Nous organisons également des cours privés sur les sites des clients, où un bon service de traduction locales peuvent faire en sorte que vous obtenez le plus de cours si vous n'êtes pas un anglophone.
Anglais, français, espagnol, italien, allemand, portugais, néerlandais, danois, norvégien, suédois et finlandais
Posted by gje at 02:28 PM | Comments (0)
Related topics: via article database
Certification Revisted - Lua
I happened upon a "should you be certified" thread relating to Lua while browsing for quite other Lua topics ... it's here, and the initial post appears to provide a reasonable, if admittedly tilted, set of arguments in favour of certification. As it freely admits, "we're looking to set up certification, so you can expect us to be biased". It makes interesting reading.
One point struck me straight away - by adding "certification" to what a trainer claims of his course, he can charge £££ more, and if he sets up a certification scheme in an open market, he may be able to sell it to lots of others, form something of a community standard, and make £££££££££ on top. Hmmm - and the reasons given in the post are so altruistic - as if butter wouldn't melt in the poster's mouth!
And I see in a follow up: "So it makes me nervous to see someone pop up more or less from nowhere claiming to know enough about Lua to create a certification program. What guarantee do I have that the tests you have developed mean anything at all?" ... and I have quoted that because I couldn't have put it better myself.
In another follow up: "To be honest we sigh when we see some form of certification on a CV, even the MSXX and A+, unless it is relevant to the job and comes from a recognised authority it is just an expensive piece of paper. And that is the catch, no matter how sincere and trustworthy you are who are you to issue a certificate and why should anybody take you seriously." ... and that if anything is saying an applicant with a certificate may actually be harming his chance of getting considered for a job.
Finally, the certification organisation writes "We do not test for any number of other skills that are needed to make a good programmer -- i.e. an understanding of algorithms, architecture skills, general logic skills, customer skills, etc." ... and I note a reply "Then just what are you going to test for? If someone codes the factorial algorithms in 1000 lines of lua code and it compiles are you going to give them a pass when it should have been written in 6 or less? Or are you saying that you can test someone without them having to display any algorithmic ability?" ... and that is VERY poignant with Lua, where the language is small and the algorithms are not built in to standard functions in the same way that they are in Perl or Python or PHP ...
So ... we WILL confirm, at the request of delegates, that they have attended Lua courses, and we will also confirm the course agenda at their request. We can look back at notes on request and confirm, with the delegate's authority, that they kept up / the course wasn't a problem for them. We can't confirm how they got on afterwards. As a review, we can say "had good potential".And on all of our Lua Courses, we'll ensure that we cover not only the language, but the also the techniques you need in order to write good programs using it too. In fact, because of the extras, it looks rather like we'll be providing much more than a certificate proves!.
P.S. Yes, we do charge for our courses, and earn our salaries by doing so. We ARE keen advocates of Lua - passionate about it - but we wouldn't claim that's the only reason that we run the courses. After all, you want us to be around next year too when you have other people to train, don't you?
Posted by gje at 10:29 AM | Comments (0)
Related topics: via article database
Useful link: Lua training
Update - Automatic feeds to Twitter
Anyone who follows updates to this blog via Twitter (http://twitter.com/wellho) may have noticed that the feed stopped a couple of days ago; that's about the time that Twitter was down for a few hours and reporting abuse. ("It wasn't me, Guv - honest!")
It appears that the --basic option in the API is no longer fuctioning and is causing the problem; I have coded around it (a.k.a. removed it) and the automatic feed from new blog entries to Twitter, as I described here, is working again.
Posted by gje at 08:53 AM | Comments (0)
Related topics: via article database
August 08, 2009
Great to be in Melksham
Well - I enjoyed - thoroughly enjoyed - my time in Guadalajara (see blog entry and more pictures) but it's lovely to be back home in Melksham. Looking through a few pictures today for images to illustrate specific articles, I have come across all of these recent ones that I haven't published before, and give you a taste of the town and its character from the local viewpoint. My 'headline' - the welcome the town marquee gave to visitors at the recent West Wilts show.
Melksham is an area of gentle residential housing, with plentiful areas of open space. 200 years ago, it was the largest town for many miles, but then it was something of a quiet backwater through the Victorian era and 20th Century - but now it's growing again. Current population - around 22,000; expected to grow to around 32,000 in the next 15 years.
Although many of the homes are modest, owners proudly look after their houses and gardens, and the quiet streets are ideal for more sheltered living in an area that is broadly crime free, quiet, and where there's a neighbourly sense of community too.
The Riverside Walk, Conigre Mead nature reserve, King George V's field, and the park alongside Clackett's Brook (pictured here) all enhance the spacious feeling that you'll get even just a few hundred yards from the Yown Centre.
Melksham IS a town that dates back to the Domesday Book, and it does have its history. You'll find medieval buildings on Church Walk, you'll find an early Victorian Masonic Lodge in the town centre, you'll find a selection of different churches, and to the South of the town you'll find the Georgian "Melksham Spa"; Melksham was going to be a Spa town to rival Bath, but it didn't quite take off in the same way; these former lodging houses are now private homes, but if you're curious and ask me nicely I can show you around one of them, as I live there.
On the back road towards Lacock, the strip development of Woodrow lies alongside agricultural line with a variety of public footpaths and bridle ways. Some are what I describe as "doggable" (in other words, you can take a dog without having to lift it over styles and gates), others are passable but require you to have strong arms if you've got (as we have) a Greyhound / Staffordshire Bull Terrier cross with you, and others are expeditionary in their use. Here are the "come'omes" as we call them ["wait till the cows come home"] alongside a doggable path in Woodrow.
"The people make the Town". That's the case with Melksham, for sure. Where I used to live, they were just about saying a grudging "Good Morning" back to me when I had lived there for 25 years, but here everyone says a cheery "Good Afternoon". Lisa kids me that a 10 minute bank run in London becomes 2 hours here. The picture ... shows crowds watching the Melksham Carnival floats go by.
It's known as "The Avon", or Avon Rubber. These days, it's actually Cooper Avon Tires - the town's industrial plant beside the river Avon, making rubber tyres for road and racing vehicles. Long established, employees have gone off during the major wars of the last 100 years, and some have given their lives, commemorated in this stone book of remembrance in front of the art deco 1950s building which I think houses the canteen.
Melksham has a variety of bus routes, ranging from the route 14 around the town twice an hour (the ususal service run by this unique minibus), through to the X96 bus to Bradford-on-Avon and Frome, run by the self same bus bus just once a day (and in reallity a service to get it back to its depot at night and back in again in the morning). Hourly service from Chippenham to Trowbridge and from Bath to Devizes form a cross at Melksham (and actually both routes are duplicated by two operators, both running within a few minutes of each other, on Monday through Friday). Oh - the town bus also runs a daily trip to Trowbridge, shown here!
The Kennet and Avon Canal passes near to Melksham - a few hundred yards south of the Bowerhill suburb. Passing from the Thames to the Severn, this canal formed the major transit route from east to west before the coming of the railways, but fell into dereliction by around 1950, and was closed for 40 years. It's now well and truly open again ... here's a scene near Seend.
Looking around, you'll find some things in Melksham that aren't quite the things you'll find in every town ...
... and you'll also find some things that are gems, but not really that unusual - such as our Well House Manor hotel - where we welcome visitors who come to do business in our town, meet the people who live there, and see some of the things we have on offer.
Posted by gje at 07:43 PM | Comments (0)
Related topics: via article database
Melksham - no trains, no southbound buses through the town

There have been NO TRAINS AT ALL to Melksham for a week. And the town centre is closed to southbound traffic, sending the buses around the bypass, and the local "we know where to go" vehicles around the suburban streets. All of which does precious little immediate good for the businesses.
When Bath Road was closed at the turn of the year, the local traders were up in arms about the lost business, and when the railway was previously shut for 10 days in the summer of 2006, we arranged a "welcome back" party with some high profile attendees to help raise the profile, and ensure that we really DID get back a "25 minutes to Swindon" train, rather than a bus that would take about an hour.
At the meeting of the Melksham Railway Development Group last night, we discussed whether we should be welcoming the train back with a brass band (or a metaphorical brass band!) on Monday, and we decided against. We are reasonable confident in the new environment, about which I'll be writing more during this month, that the train WILL come back. On the previous occasion, the atmosphere was such that there was a serious risk of an attempt being made to "sweep it under the carpet" (as has happened at Norton Bridge, Watford West and other places) ... but this time is different. Not only is there sufficient visibility and support that people wouldn't dare to think they could succeed in making the train quietly go away, but also the environment and atmosphere is such that the decision makers have moved away from wanting it to go away, and towards wanting to find ways they can feed and water it, and have the seedling of a service we have at present grow - at least - into a plant that can survive and provide a useful crop of fruit, if not yet into a thumping great oak tree.
So I look forward to the end of the rail and road works, not with trepidation, but towards being able to move forward with the incremental improvements that these temporary closures are allowing to be provided.
Posted by gje at 09:27 AM | Comments (0)
Related topics: via article database
Planning!
When I travelled from home to Saudi Arabia in May, 2006, I planned ahead. Flights were booked, course manuals printed, Visa obtained, contacts established, deposit paid (to us for courses), travel insurance in place before I even left home. "Of Course" or "Prudent", I expect you'll say. And I agree with you.
So why is it that when people start on a major software project, they're tempted to jump in and start writing code from an early point? Shouldn't there be a great deal of planning done before the first programming - checks that what they want to achieve is fully understood, and that it will work and there will be few hidden surprises? Well - it's a very brave analyst / programmer who, half way through a six week project, hasn't written a line of code ;-). But is CAN work.
I recall the "Bill of Materials" module of our "Designer I" CAD product (written by myself, David, Julie and Adam in the 1980s in Fortran, C and Assembler, running on PCs, Linux, Sintran, RSX11M ...) which was specified down to the extent of the user manual being complete before a line of code was written. An excellent module, which did what is said on the box, and worked well for our customers. Th eonly problem I recall was that - having put the manual into the hands of our sales person - we also had orders (and with an impossible tight timescale promised) before any code was in place.
I was reminded of this yesterday, when I was helping with the design of a new project for one of our friends and customers, and although the project will be in PHP, we didn't write a line of PHP all day.
We started off with "Use Case" - looking at what the data held by the system will be, who provides it, who uses it. We extended "use case" somewhat by adding in weights to the various users, both in terms of how much traffic each role will generate, and how sensitive that role is to a 'good' or 'bad' system - the user profile.
Alongside "Use Case", we thought of key features and extensions, looking to think well ahead at an early stage of what the system must do at day 1, what would be really helpful in terms of extra features that will help it be accepted / used / strongly taken up from day 1, what will help make it usable, secure, extensible, manageable and profitable. In my own mind (though not, I will admit, on the paper), I was thinking through how each user will walk through the system - "State Diagrams", and at lunch we talked though with a potential user of such a system about what when would like to see in it / how it could work for her. That's an unscientifically small sample size, I know - but never the less, a first sanity check to say "have we overlooked anything serious here?".
Towards the end of the day, we moved on to a more detailed look at the data to beheld - the structure of the tables. And, in this case, we chose to write the description down in the form of MySQL CREATE TABLE commands, to see how it would work, together with some INSERT commands to actually add data in to the tables. We preceded these commands with a DROP DATABASE and a CREATE DATABASE so that we could try it out, time and again, and we added in a handful of SELECTs so that we can see how - when code is eventually written - the data will be accessed. The file (as it was by the end of the day) is here.
With a solid, tested, thought ahead design for the database, this system can be a big success. Design issues considered / resolved very early include:
a) The main tables, and how they are normalised to avoid data duplication, to avoid multiple values in a single field, and to avoid the storage of calculated results.
b) Table and field names based on a consistent convention so that coding will not be held back by "what did we call that field" or confusion between multiple fields of the same name.
c) Deciding the data types for the central fields early on, and allowing for additional fields to be added easily into each table, preferably getting most of them specified and 'in' early on.
Although each table has an auto_increment id field, we specified record IDs manually in our test data, using a different range of integers for each of the id sets. Thus, the categories of course are numbered from 200 upwards, individual courses from 300 upwards. This is purely for early 'Spike solution' testing so that we can easily see and work through the database logic; come the live system, they'll all start automatically at 1.
I hope to be able to bring you updates on this project from time to time, and perhaps to be a consumer myself in the (not too distant) future - I know it is something I would use if easily available here in Melksham. And it's good to be reminded that the chapter in our Perl Programming Course that's headed "Design Matters" is actually capitalised / styled as "Design MATTERS" - in other words, remember the importance of getting the specification right to begin with!
Posted by gje at 08:46 AM | Comments (0)
Related topics: via article database
August 06, 2009
Learn a new programming language this summer.
Public Courses for newcomers to a language, running in Melksham
Lua - Monday, 10th August 2009 (*) - 3 days
Python - Monday, 17th August (*) - 3 days
Perl - Monday, 7th September (**) - 5 days
Java - Monday 21st September (*) - 4 days
PHP - Monday 28th September (*) - 4 days
More advanced programming courses this month and next:
Perl for Larger Projects - Monday, 24th August - 3 days
Object Oriented PHP - Thursday, 27th August - 1 day
Other public courses this month and next:
Deploying Apache httpd and Tomcat - Thursday, 20th August - 2 days
Deploying Lamp (Linux, Apache httpd, MySQL, Perl/PHP) - Tuesday, 1st September - 4 days.
Linux Basics - Tuesday, 1st September - 1 day
Introduction to Linux Admin - Wednesday, 2nd September - 1 day
Apache httpd - Thursday, 3rd September - 2 days
* - If you have never programmed before, sign up for our "learning to program in xxxx" course, which gives you a day of programming background, tilted towards Lua / Python / Java / PHP as appropriate.
** - the Perl programming course is suitable for newcomers to programming, as well as for programmers with experience in other languages.
All the above courses held at our Melksham, Wiltshire training centre, with group sizes limited to just 8 delegates to ensure that each individual gets the best possible personal gain and tuition. Our courses are niche - delegates travel far and wide - so we offer accommodation at our training centre too - it's our Well House Manor Business Hotel - "probably the nicest hotel rooms in the town" according to some of our guests!
• When you book, you are guaranteed that the course WILL run (and at the venue specified too!)
• All of the above courses run regularly - if you have missed the dates given or they are unsuitable, please click on the link alongside the course for other dates.
• We also run public courses in Ruby, Tcl, MySQL, C and C++ - each is scheduled at least 3 times a year, each coming up in October or November
• for groups of three or more delegates, we can run private courses at Well House Manor or on your site
Posted by gje at 08:51 AM | Comments (0)
Related topics: via article database
Apache, Tomcat, mod_proxy
The Apache httpd web server (a.k.a. "The Apache Server") is essentially a file (web page) server, written for fast performance in C, very reliable, and VERY widely used.
The Apache Tomcat web server (a.k.a. "Tomcat") is essentially a web application container that runs using web protocols. It's written in Java, works well, and is quite widely used as a backend server.
The Apache httpd server is ideal for site with lots of individual files to serve from time to time. The Apache Tomcat server is great for sites with large number of accesses to a handful of scripts. But of course, most real life web sites require a bit of one and some of the other. So in most cases that you'll find a Tomcat, you'll also find an Httpd in front of it, taking all the requests to the domain and passing on (via Apache mod_proxy or mod_jk to Tomcat these days) requests for the major application.
There's an example of an Apache httpd configuration file here that connects Apache httpd to Apache Tomcat via mod_proxy (also includes mod_jk and mod_rewrite examples), and a more complex example using virtual hosts (several domains server by the same server) here.
Our Apache httpd and Tomcat course covers mod_proxy, and (briefly) the additional mod_proxy_balancer which allows a single Apache httpd to pass on requests to several Tomcats (or actually to more httpds or other servers) to do the bulk of the processing. Apache Httpd and Apache Tomcat are two very flexible web server which - when used in combination - provide the platform on which you can run a wide range of sites / applications, and we'll teach you how to make the best of setting up and managing both servers, and linking them together.
Posted by gje at 07:56 AM | Comments (0)
Related topics: via article database
August 05, 2009
What search terms FAIL to bring visitors to our site, when they should?
My web log files, with careful analysis, tell me what search terms brought people to our pages. But what I would really like is to find commonly searched terms which should bring people to us, but do not ... so that I can optimise the site for them. And of course there's nothing in the log files to tell you what these underrated/unrated terms are - or so you might have thought.
With the combined log file format, the Referer string includes the query that the user made (encoded) and also a parameter showing the start point in the results set. Without that parameter inthe referer, you are loking at the start of the result set ... with that parameter, you have a user who has moved on from the first page to a later page of results.
Here are a couple of analyses from yesterday:
4 arrival(s) to /resources/ex.php4?item=h110/mcheck.php
1 - php select radio
1 - php radio exemple
1 - php template for radio
1 - php select from (page starts 10)
That's three users who came to the page in question because their search presented our site on the first page, and one who searched for "php selelct from" who wasn't satisfied with what (s)he found on the first page, and moved on to the second page.
6 arrival(s) to /resources/ex.php4?item=j907/index.jsp
2 - shopping cart jsp
1 - jsp source code for online shop (page starts 30)
1 - shopping cart example jsp
1 - download sample code for shopping cart in jsp
1 - shopping cart jsp example
And that's a page which our patient user, searching for "jsp source code for online shop", didn't reach until the fourth page.
This page start information is a huge clue to lost traffic. With only 4% of our visits being as result of our links being found on 2nd or subsequent pages (see here), we're been shown the tip of an iceberg - and we could do well to trawl through all our second (and later) page arrivals and see if we should be making more effective use of the words that were used in them.
If you're interested in what subjects users have found recently that are not on the first page, look here for Python - Perl - PHP - MySQL - Tcl - Ruby - Lua - Java - Tomcat - Apache - Linux - Shell - Expect - Database - Unix and other topics
Posted by gje at 06:02 PM | Comments (0)
Related topics: via article database
Java Collection Objects in the java.util package
If you want to hold a number of objects in a single composite object, you call it a collection. The Java language itself (without any additional classes) supports arrays, which can hold primitives or objects (example). The java.util package adds a whole further series of classes which can be used to hold multiple objects in various arrangements and with various facilities.
Do note one important limitation - they hold multiple OBJECTS; if you want to hold multiple primitives in a collection, you need to use the data type wrappers - you can find an example that compares a float primitive to a Float object here (and note the different capitalisation - float v Float)
The first collection objects in Java were the Vector, Stack and Hashtable, using the enumeration interface. They have been available from the beginnings of Java. A complete Collection framework was added at Java 1.2, with objects such as ArrayLists, HashSets and HashMaps.
I am noticing a considerable number of visitors arriving at our web site looking for examples of these various classes, so the purpose of this short item is to help put them into context, and provide associated links.
a) The OLDER collection objects - Vector, Stack and Hashtable, are slower in operation but remain a part of the language (not deprecated) because they are Thread Safe. Newer collection objects - ArrayLists, HashSets and HashMaps - run faster but may give you coding issues when you're running threaded code.
b) Vector, Stack and ArrayList are indexed (like an array) from position 0 upwards. Unlike an array, each of them can be extended after it is created, and they can be sorted, have elements added in and taken out from the middle efficiently, and so on. In contrast, Hashtables, HashSets and HashMaps are keyed to another object not an index number, using a "hashing technique". This makes it very efficient indeed to find whether an element already exists and to add new elements, but means that you can NEVER sort them into order. (Instead, you can make an ArrayList of the key names and sort that, using the sorted arraylist to give you a traversal order)
c) The Stack is a special case of a Vector - a subclass - with extra methods isEmpty, push and pop. Although the previous paragraph is correct in saying you can sort (etc) a stack, it would be a peculiar thing to do!
d) The HashSet is a series of keys WITHOUT values. There are times when you want to register merely the existence of a key, rather than assign a value to it - for example, you might want to analyse a web access log file to produce a report (list) of all visiting IP addresses. It turns out that placing each item into a HashSet is the most efficient way to do it, rather than the more obvious way of keeping a list and checking each new item against the list.
Source code examples for the six collections I have mentioned ... HashMap HashSet ArrayList Stack Vector and Hashtable.
Our Learning to Program in Java course (for newcomers to programming) and our Java Bootcamp course (for delegates with prior programming experience) both teach you Java up to and including the level of the utility classes, setting you up with all the fundamentals of the Java language and associated basic extra classes that form a necessary part of most real life applications of the language.
Posted by gje at 10:49 AM | Comments (0)
Related topics: via article database
Useful link: Java training
Looking for a practical standards course
I'm a great believer in coding standards. In well commented code. In a good choice of variable names, of code re-use, and of thinking before you write. There are points which I stress on every course, even if the majority of the time I spend is on the actual language. So I should not have been surprised to have been asked if I could provide a "Good Practice Course" along the lines of the specification below.
I applaud the customer who has asked, I think it will be very worthwhile for them ... BUT I myself don't have the training / knowledge of the formal skills and more academic issues (nor course notes) to deliver, and I have "no bid". I'm very happy to overview / spend a day on these topics. But not a week. Which brought the question "do you know anyone who CAN help?". I know this gets read / found - please get in touch (graham@wellho.net) if you can help - I'll pass on your details and let you talk direct.
Source Code Control
Distributed Version Control (DVC)
[Setup, users, locks, branches, logs, merges]
Testing
TATFT (Test All The $&?#+[\] Time)
BDD/TDD (Behaviour Driven Development / Test Driven Deveopment)
Unit tests
Continuous Integration
Naming conventions
[variables, functions, filenames]
Code Inspections
Design
Unified Modelling Language (UML)
Design Patterns
[Factory, Memoization, Facade, Singleton, Strategy]
MVC (Model, View, Controller)
Documentation
Design documents
Code Structure
DRY principle (Don't repeat yourself)
Code smells
WTF/s
Demeter's Laws
Running Well
Serviceability and efficiency
Analysis of Algorithms
[IO bound, Memory bound, Performance analyisis]
Code to handle code
Metaprogramming
2nd order functions
Continuations
Convention over configuration
DSL (Domain Specific Languages)
I would personally add the following to a genaral programming techniques course:
User support and user documentation. Team communications and co-ordination. WIBNIF (Wouldn't it be nice if). Extreme and pair programming. Library design and maintenance. Backup and contingency. Requirement specification and portability. Security of code - legal and abuse prevention. Inherently stable code. Algorithm design.
Final note - the examples illustrating this course should be in an appropriate Open Source language - I am happy to talk with anyone who's interested in delivering the course about where it would be (long way from Melksham) when it's needed (very soon!) and which language it's in.
Posted by gje at 06:01 AM | Comments (0)
Related topics: via article database
August 04, 2009
Uploading and Downloading files - changing names (Perl and PHP)
When you are uploading a file to a server via http (in Perl or PHP), where is the file saved, and what is it called? And when you download a file, where is it saved on your local disc, and what name is it given? These are not unusual questions, but it can be hard to find the answer, as I was reminded in my in-box overnight:
|
I am located in the USA and am working through your on line public CGI Perl upload and download scripts (up.pl ; down.cgi ; up.html). I have everything working except for one problem - I can't figure out how to preserve the original filenames. I can hard code a filename in both modules and it works fine but I would like to preserve the original filenames after they have been uploaded or downloaded. All downloaded files have the name of the download module i.e. "down.cgi" and uploaded files have to have a hard coded name (e.g. $fnsave="LastUploadedFile") in order to to appear on the server directory although the file seems to be uploading to somewhere. I also can't send the file to anything but the root directory - It just doesn't show up after uploading. It seems like it should not be that difficult but I can't figure it out. Could you assist please? |
My answer is worth sharing:
On the download, (http://www.wellho.net/resources/ex.php4?item=p406/down.pl) you need to add a content-disposition header - I've illustrated that (in a PHP example) at:
http://www.wellho.net/mouth/484_Setting-the-file-name-for-a-downloaded-document.html
and you'll find source code examples (all in PHP, I'm afraid) at:
http://www.wellho.net/resources/ex.php4?item=h109/savepeople.php4
http://www.wellho.net/resources/ex.php4?item=h307/sendimage.php
and
http://www.wellho.net/resources/ex.php4?item=s156/mkexcel.php
On the upload (http://www.wellho.net/resources/ex.php4?item=p406/up.html and http://www.wellho.net/resources/ex.php4?item=p406/up.cgi), again I have some PHP examples and start at:
http://www.wellho.net/solutions/php-example-php-form-image-upload-store-in-mysql-database-retrieve.html
which however is NOT so clear as PHP does the decoding work for you ... so I have modified the Perl scripts that you referred to and uploaded them live onto my side - see
http://www.wellho.net/demo/upfile.html (form to run the demo, which runs)
http://www.wellho.net/cgi-bin/demo/upsend.cgi
and the source code is at:
http://www.wellho.net/resources/ex.php4?item=p406/upfile.html
http://www.wellho.net/resources/ex.php4?item=p406/upsend.cgi
On uploading, you'll find that it's common practise for files to be saved initially to a staging directory and then to be moved / copied - it relates to various issues such as the security implications of any old file that a user can upload being places into your directories straight away, with overwrite and overflow risks, and the ability of people to upload code which - saved to a directory with CGI enabled - could be run, and if the file was malicious code that's an injection attack!
Hopefully this is useful to you ... the comments and references could be useful to others too, and you're not the first one to struggle with this nor will you be the last, so I'm adding it to my blog at http://www.wellho.net/horse to help pull the various answers and resources together. Thanks for the inspiration for this morning!
Posted by gje at 09:10 AM | Comments (0)
Related topics: via article database
Useful links: Perl training, PHP training
August 03, 2009
Helping new arrivals find out about source code examples
On 30th July, nearly 5300 people arrived at source code examples on our web site from Google searches, from 4000 unique IP addresses.
How do I know that? From analysing our log files:
-bash-3.2$ grep 'GET \/resources\/ex\.php.*\.google\.' ac_20090730 | grep -v Googlebot | wc
5382 129055 1832168
-bash-3.2$ grep 'GET \/resources\/ex\.php.*\.google\.' ac_20090730 | grep -v Googlebot | awk '{print $1}' | sort | uniq | wc
4000 4000 56647
-bash-3.2$
... and 30th July was just a typical weekday; the number halves on Saturday and Sunday (down from 4000 to 1594) which confirms to me that the majority of these are genuine professional visitors and not automata.
-bash-3.2$ grep 'GET \/resources\/ex\.php.*\.google\.' ac_20090801 | grep -v Googlebot | awk '{print $1}' | sort | uniq | wc
1594 1594 22433
-bash-3.2$
Do these people find what they're looking for? Now that is a far more difficult question. And to be honest with you (gawd - I hate that phrase - I try to always be honest!), I don't know the answer, nor even how to find out.
I do know that I write about our source code examples here on The Horse's Mouth from time to time, but that the search engines are often landing our visitors at the source code itself, which until a few minutes ago had no link back to the relevant entry here - so a valuable resource that could help people (and has taken a lot of putting together) was underutilised.
There's no way I want to add a manual operation to each source code page to place back links in there, and fortunately the source code pages are all generated by a single PHP script. So I run the following in my business logic:
# File exists - is it described on the blog?
#desc_line = "";
$qblog = mysql_query("select entry_id, entry_title from mt_entry where entry_text like \"%$module/$name%\"");
while ($rro = mysql_fetch_row($qblog)) {
if ($desc_line == "") {
$desc_line = "For further documentation on this example, ";
$pnn = $rro[0]."_".preg_replace('/[^a-z0-9]+/i','-',$rro[1]);
$desc_line .= "<a href=http://www.wellho.net/mouth/$pnn.html>select here</a>";
} else {
$pnn = $rro[0]."_".preg_replace('/[^a-z0-9]+/i','-',$rro[1]);
$desc_line .= " or <a href=http://www.wellho.net/mouth/$pnn.html>here</a>";
}
}
and the following in my web helpers:
<?php if ($desc_line) { ?>
<p style='margin: 10px; border: solid; border-color: teal;'>
<table border=0 cellpadding=4><tr><td>
<?= $desc_line ?></td></tr></table></p>
<?php } ?>
The fact that the blogging software is written in a different language (Perl), and wasn't written by us, doesn't make any difference - we can still write code to access the database, just bearing in mind that it's possible that the format could change on a future major upgrade.
How does this work ... Very Well, Thank You! If I was talking about how a Lua function can return multiple values, I might provide you with a link to the source code here ... and if you follow that link to test it out, you'll find an extra, teal coloured box now provided automatically at the top of the page to allow you to link back to the blog (in its archive form, for permanence!)
For examples that have been 'mentioned in dispatches' several times, you get a series of links (could be improved later!), and for pages which are web examples, there is often a similarly highlighted link to a page where you can actually run the example. A good example of both of these is the Spell Checker in PHP which I wrote three years ago now during quiet evenings on a Perl course in Saudi Arabia.
P.S. Our extra dictionary words are here if you want to find the second bit of that last example ... and by telling you I have automatically added a back link to this page!
Posted by gje at 03:23 AM | Comments (0)
Related topics: via article database
August 02, 2009
Graphics in Lua - an example using the gd library
In answer to the question "how would you generate graphics from Lua?" ... I would (personally) look at a binding to the gd library - http://luaforge.net/projects/lua-gd/ - as this is an excellent library, under the MIT license so there's no issue with ongoing licensing being different to Lua's.
This image is an example produced using the gd module within Lua. The principle is that you create an image using gd.create which returns a table on which you run various methods such as colorAllocate and fillRectangle ... before finishing with a method such as jpeg or png to output the Image.
The complete source code of the program I used to generate the image that illustrates this article is on our web site here. We will give you a brief introduction on our public Lua course; Computer Graphics (and the GD library) are something of a speciality of mine, so if you need to know more, please ask for an "extra day" or alert me ahead of time on a private course, and I'll be delighted to cover the topic!
For graphs (as opposed to graphics), look at http://luagraph.luaforge.net/ which is a binding to the Graphviz library. And there are also OpenGL, SDL and .pdf bindings ... see http://lua-users.org/wiki/LibrariesAndBindings
Posted by gje at 06:35 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
For Lua Programmers AND for Town Planners
I'm always happy to be able to make multiple use of the same piece of work, and so it is with an example written last week.
|
READ THIS SIDE ... I was asked to provide an exercise during the Lua course that related to game playing - where a series of elements (of different types) move forward at a given time interval, depending of their characteristics, other elements around them, and user entered changes. Well - there was no way we could write a complete game in just an hour and a half, but we could put something together that would show the structure. The data file that I put together had different towns as its varying data elements, and as new inhabitants moved into the area, and moved away, they were distributed around the towns according to different algorithms for different types of town. At the start of the application, we set up tables to contain the various operations for each type of town, being careful to ensure that they had the same API so could be used polymorphic ally. We also set up a table for operations common to all towns. At the start of the game / simulation, the town data was read in and interpreted (taking care to eliminate comment and blank lines and to validate the remaining data) and a table was set up for each town, making use of a metatable for each type, and storing a reference to the specific or general town methods in a table member of a standard name. To run the simulation, all we then had to do was to call the appropriate methods in a loop (v being the code for each town in turn, 6000 being the number of extra inhabitants per annum (that should REALLY have been a variable!:
Full source code and data links: We run Lua Programming Courses at our Melksham, Wiltshire training centre - or on your site at almost any location in the world. I am typing this entry at the Airport at Mexico City, while awaiting my ongoing flight ... and it will be posted when I get back home. |
READ THIS SIDE ... Lisa has often commented to me that I shoulds run something like Sim-City on North and West Wiltshire to see how the populations would changed in the future with and without a decent rail service, and with and without road improvements. Alas, there are too many things I don't know and a complex setup to doing that, but it did set a seed of thought in my mind when I was looking for data for a simulation exercise last week. Now I will be the first to admit that my model is rudimentary, many factors are missing, and that my data is suspect but never the less, this simulation (run a number of times with changed data) gives a very interesting insight into the rise and fall of towns and cities. You'll see in tables below that I have printed out some of the initial data for each town, including whether it is scheduled for growth (so there is unlikely to be as much upward pressure on house prices there); the data also includes "trains per hour" - not listed but available in th e associated data file. Newcomers go to where the house prices are good, and where there is excellent access - they don't actually follow government dictat, but you'll see how the government dictat pushes prices up in places like Devizes and Malmesbury, which indirectly limits the growth. Looking forward 20 years, what do we see? Amongst the growth towns, Chippenham and Westbury have grown 80%. Trowbridge has grown nearly 60%, and Warminster just over 60%. Melksham's growth is lower - a shade under 50%, and Corsham's is even lower at just over 40% Looking at the towns where substantial growth was not encouraged in my model, you'll see 8% growth at Bradford-on-Avon and 3% growth at Calne. There's actually a slight shrinkage in Devizes and Malmesbury. That wouldn't mean a lower housing stock - the trend of reducing inhabitants per dwelling is set to carry on into the future, I understand. In the growth towns, house prices have all risen - nearly 50% at both Westbury and Trowbridge (where they started very low) and nearly 30% at Chippeham. At Melksham, they're up just 22% and at Corsham it's very low 15% Looking at the stable towns, Malmesbury house prices have risen by nearly 30%, Devizes by nearly 40%, Calne by 58% and Bradford-on-Avon by an astonishing 70%+ In order to test the behaviour of my model, I also ran it with various different parameters - changing the specification of towns, adding in and taking out rail services, changing the net inflow and annual move-away factors, and running for a longer period. The results were fascinating ... but I have chosen to stop at the 20 years of the RSS for what I comment on / publish here More conclusions below the data ... |
Here is the original data and simulation results from this program / test
Chippenham - 34000 - FAST - 150000
Melksham - 22000 - FAST - 120000
Trowbridge - 28000 - FAST - 120000
Westbury - 11000 - FAST - 130000
Dilton Marsh - 2000 - FAST - 140000
Warminster - 17000 - FAST - 130000
Devizes - 11000 - STABLE - 150000
Calne - 12000 - STABLE - 120000
Corsham - 12000 - FAST - 130000
Bradford-o-A - 9000 - STABLE - 160000
Malmesbury - 4000 - STABLE - 180000
Progression of population every 4 years
2007 2011 2015 2019 2023 2027
Devizes 11000 11009 10975 10902 10793 10653
Warminster 17000 19184 21338 23445 25499 27496
Chippenham 34000 38017 42023 45976 49852 53635
Westbury 11000 12982 14841 16601 18279 19883
Trowbridge 28000 33032 37753 42225 46487 50563
Calne 12000 12263 12411 12466 12446 12366
Dilton Marsh 2000 2169 2346 2527 2708 2888
Bradford-o-A 9000 9355 9570 9683 9718 9693
Malmesbury 4000 3955 3905 3849 3786 3717
Melksham 22000 24154 26357 28572 30772 32942
Corsham 12000 12897 13849 14831 15826 16822
Progression of house prices every 4 years
Devizes 150000 162628 174987 186935 198395 209329
Warminster 130000 141094 150908 159429 166704 172805
Chippenham 150000 161292 171437 180334 187982 194423
Westbury 130000 147625 162328 174624 184870 193332
Trowbridge 120000 136211 149742 161061 170494 178286
Calne 120000 135544 150205 164004 176977 189164
Dilton Marsh 140000 146017 151823 157163 161897 165961
Bradford-o-A 160000 186873 211494 234238 255348 274997
Malmesbury 180000 190626 201256 211715 221894 231720
Melksham 120000 126676 132903 138502 143396 147559
Corsham 130000 134318 138646 142721 146390 149567
Conclusions. Once again, I need to stress that this is just a very simple mathematic model with unverified 'best guess' inputs so you should not read anything into the specific results. But it certainly does provide food for thought.
Did you notice how the two growth towns which have no (or no effective) rail service - that's Corsham and Melksham - fail to grow in spite of the encouragement offered. And that Bradford-on-Avon, not marked for major growth, does grow in spite of the lack of official encouragement, with the highest price rises in the chart.
Looking carefully, you'll see that Bradford-on-Avon has actually hit a ceiling and has started to loose population, and that growth at Corsham and Melksham has accelerated towards the end of the period, whereas at Chippenham and Trowbridge it is tailing off a bit. People are being encouraged to move to Melksham and Corsham due to the share low prices of housing there, and I suspect this would in turn be leading to a population that is actually less affluent / more deprived in what are basically sink towns.
When you think about it ... many of these factors are natural, and I can't say for sure whether the results seem high or low ... which probably means that, for all the guesswork involved, my model may be remarkably close to the mark.
Posted by gje at 03:49 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
How to make a Risotto (PHP build style)
Written on last night's long flight ... posted today
Talking with Gisela, seated next to me on this Mexicana flight, I have learned why my Risottos are always sticky. Basically, wrong ingredients and wrong cooker method!
Here's her recipe, from Buenos Aires via Mexico City ...
Take some carnaroli rice ("none of your oriental stuff").And don't do anything with it. Yet.
Take an onion and finely chop it (same size as rice grains - gee, I'm used to coarse cookery! And fry it in olive oil. When soft, add the rice and cook until transparent - that's just a couple of minutes.
Add 1/3 of a glass of dry white wine. Pour rest of glass into chef's mouth and swallow.
Take some vegetable stock you previously prepared (ouch - if you are following this you are gonna be cursing me now! It's like the PHP installation instructions which say at step 8 "you did remember --enable-so at step 2, didn't you"). Ladle the stock in hot (litle at a time, like making a cream sauce) until it's done.
You're adding stock as it needs it (ah - good example of a feedback loop) and keep stirring for around 20 minutes.
When done, take off cooker and add a couple of cubes of cold butter and 50 ml cream and as much cheese as the customers want ... Parmesan or similar. And other things to taste .. safron to stock, funghi, pollo.
There are so many times that we sit next to someone on a flight, each in whiling away the journey time in our own world. I like those occasions where the Ice is broken - as it was last night - and you spark a brief friendship. If you happen across this, Gisela, I how your 'Masters' comes through, and things go well for you ... whatever country (if any) you settle in.
Posted by gje at 02:25 PM | Comments (0)
Related topics: via article database
Useful link: PHP training
August 01, 2009
Guadalajara - a special tour of a lovely city
One hundred and ninety nine years ago, the Mexicans threw out the Spanish in the war of independence. Ninety nine years ago, the Mexican Civil war deposed a dictator in favour of democracy. And so next year there's going to be the most enormous of celebrations; parts of that involve computer generated videos (one for each week of the year - Battalon 52 project [YouTube Video Link]) and video games for the Wii. And it's the writing of the video games, the background work in C++ and Lua, that has brought me to Mexico.
At the end on Thursday, we all posed for a group shot - it's posted in a previous blog - here is the view that I had:
and that evening I returned, exhausted to my hotel - yet with a feeling of a lot achieved and a job very well worth doing, and well done. I slept long and deep. Friday ... and rather than return direct to the UK, I helped with a couple of coding issues that had arisen in the morning, and then was taken on a tour in the afternoon. There's nothing quite like having a local guide when you're seeing a new place, and it's really refreshing to have a fellow geek, rather than a professional tour leader, to show you the place - for with a personal guide on a similar wavelength, you also get to see other places, and to learn something of the true life and times of Mexico, and of a person in Mexico. But I'm writing here about the tour from 1 p.m. to 5 p.m. including lunch - my goodness, how much can be done in half a day!
First and foremost, Guadalajara is a big city ... and a technological one. The sign on my way in from the airport said "Welcome to Mexico's Silicon Valley", so I rather suspect that future trips to Mexico would also be to the Guadalajara. And It's wired - "Internet" all over the place downtown, heavy traffic, bustling streets. So pictures like this one here really say no more that "look - typical big place" ... could be in the USA, except there are a lot of buses around; just two Metro lines (not sampled) and the new "Macrobus" which is a bone of contention!
With so much history, and an old City, there are memorials and statues all around. There was a limit to what I could take in (and I may ask Daniel a big favour to help me label!) ... but this is Minerva, and this is a roundabout, slightly out from the centre, where Mexicans gather on special occasions / at special times. Everyone is hoping that next year's celebrations will be positive, and nothing which matches the tumult of 200 and 100 years ago.
Daniel had told me he was going to show me the main cathedral in Guadalajara during our walking tour (and he had carefully checked that I was game for a walk) and this magnificent building looked very much like the Cathedral - in fact, I mistook it for that. But, no, this is just a church in a deeply religious Catholic country. I was (personally) glad to learn that the strictures of religion are now somewhat looser - for example, single parents are no longer frowned upon in the way they used to be. But still it would be unusual in Melksham to see people going into a church to pray during the day as was happening here.
The ancient mixes with the modern ... across from the church was a scene that reminds me of Milton Keynes on its side; there were cows like this all over the city at one time, as part of an advertising campaign, and this one has been retained.
Cables being laid into sub-street trunking, and manholes are just left open. I wonder what the health and safety people would have to say about this in the UK - and indeed there were a lot of other times during my visit where the care and expense of avoiding accidents was less thorough than in the UK. "You need to keep your wits about you". I took care to find the emergency exit where I was working, but noted that the back door led me to, basically, a prison cell with a padlock attached to the rear of the building which would have had me cornered in a fire. I noted that we just mopped up the inch of water and carried on when the training room flooded, and that the too-short projector cable was a trip hazard (three of us got good exercise overstepping it all three days).
These are just tourist attractions! But there are yellow cabs, buses and trolley buses too all over the place. Sad, though, to see some of the electric trolley buses being replace by diesel vehicles, and those with robust sounding, meaty engines which had me wondering about their CO2 profiles.
In a typical Spanish Courtyard that's now a museum, you see the ultimate of well polished and maintained floors. There's no shortage of staff here to clean, to mop, to serve, and there's a tremendous mixture of the ancient and the modern, the well looked after and the decrepit - a gap which perhaps you'll see that much more in a poorer country rather than a rich one.
I've only got you halfway down town on this tour, and I'm only a quarter of the way through selecting pictures ... but I think I have given you a taster. Let me tell some more of the story in pictures:












If you would like to see all of those pictures larger, and also many more that I took (and some better ones, excluded just because they are in a different format) please look here.
Friday evening, and I was taken out as a 'Thank you' and farewell dinner, to a Mexican Restaurant - "over the top Mexican" was how they described it ... but it was lovely to have the Salsa prepared at table, to see the Mariachis serenading couples at other tables, and in the courtyard to see the traditional dancing from neighbouring states.
And so, after the sudden darkness that falls each evening because we are so close to the equator, back to my hotel. To fond farewells, to wishing the folks a successful show at SigGraph in New Orleans next week. Abril will have already flown out as I write this. And I must away and pack too; my driver arrives in two hours to take me to the airport, and two flights, a drive, and in a day's time I'm be back in Melksham. And with fond memories of Mexico ... it hadn't been in my list of "top ten countries to visit", but now that I have been here, I know it should have been!
3rd August - Guillermo ('Memo') writes: By the way, I read your blog, it's Mariachi. The pronunciation is said to be a deformation from the English word "Marriage". A long time ago, they were common in any party until the economics kicked in. A Mariachi should be at least an 8-man band! Mariachis dress up in a very similar way to a Charro. That's a recent change. Emilio Azcarraga, the Mexican TV tycoon, view a need for a more flashy style if they wanted to appear in any movie. Sorry for the trivia :) I thought you might enjoy knowing this stuff. Charros hate Mariachis, so one of the things we MUST avoid is having our hero act or be thought as a Mariachi!
I love the trivia! I have corrected the spelling (which originally was incorrect and had (sp?) against it!) and added that further information which may be of interest to others who stumble upon this page!
4th August - I have labelled the images here
For extra pictures taken during the course - see [here]
Posted by gje at 02:03 PM | Comments (0)
Related topics: via article database
New Lua Examples - for last weeks delegates
When I train you, I promise that when I leave (an onsite course) or you leave (a course at Well House Manor), that won't be the last you hear or see of me if you wish for further help. For the Lua group in this course photo, who's course I finished on Thursday, I have already written and blogged a couple of other answers, and I have now uploaded the examples I wrote during the course ... with extra comments added in every case to ensure that they are useful to this group and also to future delegates, and other newcomers to Lua too
This was a bigger group than usual, and I was training them further from base than usual, and through a translation service into Spanish. So it's much more practical for individuals with questions to chat with their colleagues, before getting back in touch through our post course support form straight away. But such further follow up is welcomed.
Here are the examples:
Closure demonstration - see also blog entry
User defined sorting ("postman sort")
Reading lines from a file, various ways
When is the for loop terminations calculated?
Functional / Structured coding - an example
Basics of creating and naming variables
Extracting and counting email addresses from a server log
Block structure in Lua
Looking through all the files in a directory in Lua
Finding what your operating system is
Passing parameters to coroutines - see also blog entry
Lua's string formatting
Pattern matching - anchoring and delimiting
Single, double and square bracket strings
read from keyboard - calculate - write to screen Lua example
What can go in a variable, what are the standard libraries, what are the standard functions in the main namespace? - I have added major comments to this one!
Since the course, I have also added a promised example showing an example of graphics in Lua, and I have written up an extra note on interfacing C and C++ to Lua
The final five files are all parts of the answer to the town simulation exercise (see here for a more complete description):
An answer to the town simulation exercise
Town Specification data
Main Simulation Program
Data (object) type definition
Sample output
Posted by gje at 12:23 PM | Comments (0)
Related topics: via article database
Useful link: Lua training
Passing parameters to a coroutine in Lua
Lua's coroutines, like Python's generators, provide for something which is akin to lightweight threading - rather than a strict functional calling stack, where one function must be completed before another is invoked, you can call a code block (function or method) and have it yield back to the calling routine - i.e. suspend operation - without running to completion.
In Lua ... it works like this:
• You create a coroutine with coroutine.create which you pass a function, and it returns a variable (of type thread) which you use as a parameter to ...
• coroutine.resume; called the first time, this starts the coroutine running until it hits ...
• coroutine.yield which suspends operation and returns control to the resume.
• You enclose your coroutine.resume in a loop, checking for a false return to indicate it has completed.
The question was asked on Thursday's course (and an excellent question) "How do I pass parameters to and from a coroutine, and looking at my stock answers, I realise that the question had hit a slightly embarrassing hole in my resources. Because it isn't obvious, and you WILL want to pass values in and out of the coroutine, considering how closely the co-existent routines are, logically, to each other.
The answer is as follows
1. You CANNOT pass parameters in to the coroutine function in coroutine.create. Thinking about it, it would be illogical to do so at the early stage of defining the routine; you're defining and nit running it after all, so you won't necessarily have your inputs ready anyway!
2. You can pass the parameters to start the co-routine in as the second (and subsequent) parameters to your first coroutine.resume
3. You can pass further data into the coroutine as the second and subsequent parameters to your subsequent coroutine.resume calls, and they will be returned by the coroutine.yield within the coroutine function
4. Data is passed back from the co-routine at each coroutine.yield ... parameters to the yield become the second and subsequent return values from coroutine.resume
Sample program ... source code here ... sample results:
[trainee@easterton toweb]$ lua inco
co 1
hello 1 gerald
dd 11 nil
co 2
hello 2 gerald
dd 11 nil
co 3
hello 3 gerald
dd 11 nil
co 4
[snip]
hello 10 gerald
dd 11 nil
co 11
hello 11 gerald
dd 11 nil
hello nil nil
[trainee@easterton toweb]$
As well as a single co-routine implementation, where it is useful as a data factory, or as a processing member (as in my example code), you can have whole tables of coroutines; they become very useful in simulations, where each coroutine call advances the simulation / makes the next game move for a different character of other game element. (This is just one of the reasons that Lua is making it so big in the games industry at the moment ... and you can simulate not only game movements, but things like town growth too ...)
Posted by gje at 11:09 AM | Comments (0)
Related topics: via article database
Useful link: Lua training
Seeing Guadalajara - a first glimpse downtown
Daniel took me out this afternoon to see something of Guadalajara - I'm here mainly for work, but a planned extra day allowed me to spend a few hours helping with a couple of outstanding issues in interfacing Lua to Visual C++, then just four hours being shown the city (and taking lunch in the middle of that tour).
It's a historic city of some 5 million people, so I should not be surprised that there is a great deal to see (and a travelogue to write up. However, it's the last half past six in July here (so already August in the UK) and I'm off to get ready for an evening with my hosts, so you'll have to make do with the picture above for the moment - it's actually one of 50 I've cropped and tidied in the last hour, so there are plenty more to come.
Posted by gje at 12:10 AM | Comments (0)
Related topics: via article database