|
|
I've been trying to go cold turkey. I learnt Emacs when I first started using computers a lot for programming during my masters. We were using Sun boxes and it was that or some weird editor called vi that I couldn't even work out how to enter text in (or exit without shutting down the terminal, I've improved since). Both of my first two jobs involved Unix for a fairly large chunk of the programming so I carried on. Then about two and a half years ago I switched to Windows development, Emacs might have faltered but the development environment was Borland Builder. It was far more pleasant to sit in my 1970s text editor than use Builder for most things (unfortunately you still had to use their IDE for debugging). About 8 months ago there was a switch to Visual Studio .Net which has continued when I moved jobs. Now Emacs had a competitor. Studio's intellisense works, and is useful especially since at first I was using it for C# and having to learn .Net in the process. This was also influence by the fact I had little time or energy for projects outside work so wasn't using Linux/Python/C or something else where I would have used Emacs by habit. Then after a bit of a hiatus I went back to updating (well rewriting) Cookweb. The rewrite was to be in Python (I'd discovered Turbogears and that made the code significantly cleaner than the Tcl I'd been using). But what to use to write it if I was staying away from Emacs? I'd dallied with various editors on the way for stuff that Studio didn't handle as well as straight C++/C#. I'd tried SlickEdit for the third or fourth time in the last few years. It should be good - it has Emacs keystrokes, it's extensible. It never works out. This time I had to many problems with it SQL mode (it refuse to let me enter numerals, not useful) and the keystrokes aren't quite Emacs for some of the stuff I use regularly. I tried UltraEdit but something didn't gel. Actually my favourite was TextPad - small, cheap, does syntax highlighting. This was fine for SQL at work and text but when I got onto Python, I missed things like being able to have a interactive buffer and kept hit the odd Emacs keystroke. I kept at for a week or two but in the end it was just too much. I fled back to Emacs. The flight was aided by (and to an extent triggered) by the discovery of a couple pages that reminded me of the power of Emacs and also indicated ways around some of the more annoying problems I'd had when I was using it (HTML/XML mode problems). Most notably: This message was written for you in Emacs.
There have been a couple of times over the past few of years where I have had cause to model a noisy value that is changing at a constant rate. One of the standard ways of doing this is by using a Kalman Filter, specifically a one dimensional constant velocity Kalman Filter. Unfortunately whilst this is almost as simple as you can get I've never seen the recipe written out. So one every occasion I have to read Greg Welch's tutorial and knock the rust of my maths crunching through the derivation; it's not that it's that hard you just have to remember where you can simplify and assume stuff (and remember useful snippets like covariance matrices are symmetric). Any how here's the recipe: You need to keep track of five numbers, the current estimate of the position x, the current estimate of the velocity v, and the uncertainty of measurements which I'll call Pxx, Pvv, Pxv (technically these are the variance of x, v and their covariance respectively). You need to have initial estimates of these five values. An easy way of doing this is to collect a couple of data points at the beginning, set the estimate of x to the second, v to the rate of change between the two and the uncertainty to some arbitrary value (like 1). (Fiddling with how this method will change the filter's start up behaviour but not the long term effect). You also need to have three values that stay constant: estimates of the measurement noise, R; and estimates for the noise in the real process for the position and velocity ( Nx and Nv respectively). The best way is to get values of these is to get some real data and then run the filter over it at a range of values and pick those that look best. Roughly speaking R tells the filter how much to trust its model against the current estimate. The larger the value the more the model will be trusted so the smoother the predictions, but the slower it will be to update to changes in the process. When I have a chance to format it I plan to post the derivation for this from the base Kalman equations. And by way of a demonstration here's a Python script that you can play with.
from random import normalvariate
##########################################################################
# "Real world" that we're trying to track
class RealWorld:
def __init__(self):
self.position = 0.0
self.velocity = 0.5
self.time_step = 0.01
self.time = 0.0
self.measure = None
# Noise on the measurements
self.measurement_variance = 3.0
# If we want to kink the profile.
self.change_after = 5
self.changed_rate = -0.5
def measure(self):
if self.measure == None:
self.measure = (self.position
+ normalvariate(0, measurement_variance))
return self.measure
def step(self):
self.time += self.time_step
self.position += self.velocity * self.time_step
if self.time >= self.change_after:
self.rate_of_change = self.changed_rate
world = RealWorld()
##########################################################################
# Model
# Estimates
estimate_position = 0.0
estimate_velocity = 0.0
# Covariance matrix
P_xx = 0.1 # Variance of the temperature
P_xv = 0.1 # Covariance of temperature and rate.
P_vv = 0.1 # Variance of the rate
##########################################################################
# Model parameters
position_process_variance = 0.01
velocity_process_variance = 0.01
R = 30.0 # Measurement noise variance
average_length = 30
data = []
for i in range(10000):
world.step()
measurement = world.measurement()
# We need to boot strap the estimates for temperature and
# rate
if i == 0: # First measurement
estimate_position = measurement
elif i == 1: # Second measurement
estimate_velocity = ( measurement - estimate_position ) / world.time_step
estimate_position = measurement
else: # Can apply model
##################################################################
# Temporal update (predictive)
estimate_position += estimate_velocity * world.time_step
# Update covariance
P_xx += world.time_step * ( 2.0 * P_xv + time_step * P_vv )
P_xv += world.time_step * P_vv
P_xx += world.time_step * position_process_variance
P_vv += worl.dtime_step * velocity_process_variance
##################################################################
# Observational update (reactive)
vi = 1.0 / ( P_xx + R )
kx = P_xx * vi
kv = P_xv * vi
estimate_position += (measurement - estimate_position) * kx
estimate_velocity += (measurement - estimate_position) * kv
P_xx *= ( 1 - kx )
P_xv *= ( 1 - kx )
P_vv -= kv * P_xv
print world.time, world.position, measurement, \
estimate_position, estimate_velocity
The font I use for Emacs on Windows is ProFont. To set this I set Emacs.Font in the registry HKEY_CURRENT_USER\Software\GNU\Emacs ( more details). When running with small Windows fonts the value I used was -*-ProFontWindows-normal-r-*-*-11-*-96-96-c-*-iso8859-1. But switching to using large Windows fonts (and higher screen resolution) Emacs refused to run. When triedfrom Windows it just did not start, running from a DOS prompt provided a slightly more helpful message: No fonts match `-*-ProFontWindows-normal-r-*-*-11-*-96-96-c-*-iso8859-1'Upgrading the fonts obviously removes some fonts. Unfortunately working out the magic Unix font specifier on Windows is painful. By a moderately random process I ended up with -*-ProFontWindows-normal-r-*-*-16-*-*-*-c-*-iso8859-1 which seems to be about right.
I had intend to have more wine tasting notes in this blog but haven't got round to writing them up. Anyhow here's some of the highlights of the few weeks, albeit in not a lot of detail. 1997 Clos de Vougeot, Rene Engel. Excellent, pretty much everything you ask for in a Burgundy. This sort of wine reminds you why it is worth spending £50 on a bottle every now and then. 2000 Costasera Amarone, Masi. Very good, I thought this would be a bit young and tannic, in fact whilst it was big, it was very well integrated and smooth. 15% alcohol but you couldn't tell from the taste. Drinking now and would no doubt last. 2001 Pinot Noir, Grosset. Slipping down as I write this. Very elegant, much more Burgundian than new world in style. Dry, red berries, firm acidity. Very drinkable now and would probably last a bit. 2002 Pinot Noir, Clayvin Vineyard. Bit unbalanced, the acidity seemed to dominate and there wasn't a lot of fruit in evidence. Improved a bit with being open. Okay, nothing exciting and not good value at £20+. 2002 Tokay Pinot Gris, Meyer Fonne. Nice and gentle Alsatian Tokay. Some spice, bit of weight. Slipped down very easily. Pretty good for £11. I'm going to a Yalumba dinner tomorrow night organised by Veritas so I'll try and post some notes on that in due course. Wed, Jan. 19th, 2005, 07:33 pm Time Tracker
A couple of years ago I came across a little utility that I think was called tt for tracking how much time you spend doing various tasks. I'd forgotten about it until now. Reading this article about work habits and its statistics about workers only doing an hour and a half a day made me curious. However trying to track tt down proved fruitless, so here is my half hour hack version in Python - well, about half an hour, I couldn't time it until I'd written it :-). Usage is fairly simple. Save the script somewhere on your path as tt, then you can add tasks by using tt add [taskname]. tt start [taskname] starts recording time against that item (stopping any other task that had been in progress). tt stop stop recording time against the current item. tt stats prints the current time statistics.
#!/usr/bin/env python
import sys
import time
import cPickle
import os
def now():
return int(time.time())
class TimeTracker:
def __init__(self):
self.current_task = None
self.start_time = None
self.tasks = {}
def load_state(self, filename):
"Save the current time tracking information."
# This and save_state have a potential race if two instances of this
# are opened at once.
try:
self.__dict__ = cPickle.load(open(filename, 'r'))
except IOError:
# File probably didn't exist. Constructor will have generated
# the boot strap state.
pass
def save_state(self, filename):
"Load the current time tracking information."
cPickle.dump(self.__dict__, file(filename, 'w'))
def add_task(self, task_name):
"Add a task to the list available."
if task_name in self.tasks:
print "A task named %s already exists." % task_name
else:
self.tasks[task_name] = 0
def start_task(self, task_name):
"Start recording time against a task."
if task_name not in self.tasks:
print "Task %s is not recognised." % task_name
return
if self.current_task:
self.suspend_task()
self.current_task = task_name
self.start_time = int(time.time())
def suspend_task(self):
"Stop adding record time for the current task."
time = now() - self.start_time
assert time > 0
if self.current_task:
assert self.current_task in self.tasks
self.tasks[self.current_task] += time
self.current_task = None
def list_tasks(self, show_statistics = False):
"List tasks. Current task is marked with a > in the first column."
if show_statistics and self.current_task:
# Force an update of the statistics for the current task if
# there is one.
self.start_task(self.current_task)
for task in self.tasks.keys():
if task == self.current_task:
print '> ',
else:
print ' ',
print "%15s" % task,
if show_statistics:
time = int(self.tasks[task])
print "%3d:%02d" % ((time / 3600), (time / 60) % 60)
else:
print ''
def print_current(self):
"Print the name of the current task (or None if there isn't one)."
print self.current_task
def print_help(self):
"Print the usage message."
print '%s [cmd] [task]' % sys.argv[0]
print 'Commands supported are:'
for cmd in ['add', 'start', 'stop', 'list', 'stats',
'help', 'current']:
print ' %s' % cmd
def run(self):
filename = os.path.join(os.environ['HOME'], '.ttstate')
self.load_state(filename)
if len(sys.argv) < 2:
self.print_help()
return
action = sys.argv[1]
if action == 'add':
if len(sys.argv) < 3:
print "Need to provide a task name."
return
self.add_task(sys.argv[2])
elif action == 'start':
if len(sys.argv) < 3:
print "Need to provide a task name."
return
self.start_task(sys.argv[2])
elif action == 'stop':
self.suspend_task()
elif action == 'list':
self.list_tasks()
elif action == 'stats':
self.list_tasks(show_statistics = True)
elif action == 'help':
self.print_help()
elif action == 'current':
self.print_current()
else:
print 'Command %s unrecognised.' % action
self.print_help()
self.save_state(filename)
if __name__=="__main__":
tt = TimeTracker()
tt.run()
I thought that it would be fairly easy to allow people to browse the subversion repositories for the various projects I've got. It turned into a bit of saga. It was really the fault of AOLServer nor ViewCVS nor chroot but when you put the three of them together it just got messy. I've written up my experiences.
I'm close to the point that I can put the web scrapbook I've been building live. This is something I've been intending to build for about four years and never quite got round to until a couple of weeks ago. In terms of web applications it is about as simple as you can get, a category index page based on one database table, a view page for the categories based on another table and a minimal user authentication scheme. There are a couple of aspects about the design and implementation that I'm doing as experiments. The first is the URL scheme. The obvious layout would be ${pageroot}/index.xxxfor the main category index list (where xxx is replaced by the standard suffix of your implementation language for dynamic pages, such as jsp, asp, php or whatever). Then ${pageroot}/showcategory.xxx?category_id=...for each of the categories. Instead what I have is a scheme that looks like ${pageroot}/index/and ${pageroot}/category/[id]/One reason for doing this is the good practice guideline given in this W3C technical report, which suggests "use technology independent URIs". (A point further expounded in this article by Tim Berners Lee.) The second is because search engines can be a little bit odd about indexing dynamic pages with the wrong sort of file suffix. It's hard to find out about what the criteria related to this are. Google have a comment about it on their Webmaster's fact and fiction page which boils down to saying they index most things though suffices like .php, .pl and .cgi are noticeable by their absence. Will it have any noticeable difference? I don't know that's part of the experiment. Another aspect is seeing how easy it was to build a service based on those requirements. The second aspect is the simplicity. The code is about 400 lines of TCL plus three database tables (the category list, the comments and the users). The code is about one third the actual HTML strings (yes, they are embedded in TCL; yes, this isn't great design; no, at the minute I don't care), another third is the user authentication and the remainder the actual logic. The design is as simple I could make it. You can add categories, you can add notes to categories and you can delete notes in categories. That's it. You can't delete categories, nor can you edit notes. There's no way around the first of these. The second can be worked around (copy note, change it in the edit box, save it and delete the original). I expect that I will want to add both these features and probably a few others at some point (proper user management, restricted categories and the ability to have a single note in multiple categories are all possibilities). However I want to manage new features by only those that I find I need, rather than ones I think I will need. I also want to try to limit it features where the benefit clearly outweighs the complexity. The combination of these two policies doesn't seem to be a common one, since it combines open source reactive development with commercial pragmatism. The reactive nature of adding needed features is quite close to the open source hacker's scratching an itch , but is less common in commercially driven software which are usually more up front on their design. (Yes, I know these categories aren't completely distinct.) The second aspect is a much more commercial view, although I won't be evaluating benefit and complexity in commercial terms. For commercial software benefit (crudely) is sales and income, and complexity is usually called cost, though the two are roughly equivalent. For open source community software this analysis isn't always performed. Hence the software ends up as a bit of a hodge podge as people add favourite features with little plan. A couple of examples of this are the genealogy software I found the other day which can draw a pie chart of the birth months of all the people in its database, how is this useful? A second is wmFuzzy which has option to push its approximation granularity to months, years or centuries. When I initially added it, I felt it was a harmless gee-gaw and I was glowing with pleasant surprise that someone felt strongly enough to send me a patch. However, when I was recently changing the code to allow internationalization I was slightly cursing its existence as it added a reasonable weight of extra logic. I almost removed it then and I'm still thinking about it as it seems a feature that cost more to maintain than it helps the application.
I've been updating my logic problem solver after a slightly long hiatus. The solver is working quite well and I'm now trying to update the GUI to match. One problem with even the simple GUI is how to allow the user to enter ticks and crosses. Cycling the options doesn't work if you want to solve the problem interactively (which is nice for simple cases), though this is what I tried initially. My current plan is to have crosses entered via clicking and ticks by shift clicking. However wxPython (or even wxWidgets in general) doesn't seem to support an easy way of knowing a button is shift clicked. So I came up with the following that seems to do it.
class wxSquareView(wxBitmapButton):
def __init__(self, parent, *args):
bitmap = bitmap_factory.Create(str(None))
wxBitmapButton.__init__(self, parent, -1, bitmap,
wxDefaultPosition, wxSize(20,20))
self.SetSizeHints(20,20)
#EVT_BUTTON(self, self.GetId(), self.OnClick)
EVT_LEFT_DOWN(self, self.OnDown)
EVT_LEFT_UP(self, self.OnUp)
EVT_ENTER_WINDOW(self, self.OnEnter)
EVT_LEAVE_WINDOW(self, self.OnLeave)
self._was_down = False
self._in = False
def OnClick(self, event):
"""Handle a click event."""
# Just hands off to the controller. We use this function as a
# wrapper so that the controller doesn't have to expect two
# arguments (which is toolkit dependent).
#self.__controller.Execute()
print event
event.Skip()
def OnDown(self, event):
self._was_down = True
self._in = True
event.Skip()
def OnUp(self, event):
if self._was_down and self._in:
if event.ShiftDown():
print "Shift Click"
else:
print "Click"
self._was_down = False
event.Skip()
def OnLeave(self, event):
self._in = False
event.Skip()
def OnEnter(self, event):
self._in = True
event.Skip()
The are some comments in the wxWidget documentation that the mouse leave event can be dodgy on Windows, so I might have to tweak it when I start testing there but it seems to work under Linux.
The reason I started this log was that I had various things, generally about software development, that I sort of felt that I wanted to write down somewhere, not least to force me to try and think them through completely. Unfortunately what I find is I still have the thoughts but don't seem to find time to express them as fully and coherently as I'd like before exposing them to the world, so they languish slightly as half written e-mails to myself. Hopefully with the Christmas holidays arriving shortly there will be time for at least some of them to mature.
A couple of examples. There are a fairly well established set of jokes ridiculing software development as an engineering discipline ("If Microsoft made cars then we'd have to restart the engine every ten miles" sort of thing). When I started along working in software I was ambivalent to these. A couple of years ago I'd have agreed with the sentiment. Now I'm not so sure, not because I believe that its moved on dramatically in that time, but mainly because I wonder whether we don't give the other engineering disciplines slightly more respect than they are due. Maybe.
Another is that I felt a bit strange about writing yesterday's entry saying how I'd originally got the design of wmFuzzy rather wrong. But part of me says I shouldn't, the thing people are very bad at doing is publicizing their failures. This is particularly true in science, you tend to see the breakthroughs and discoveries, but don't hear about the months chasing down the wrong path. This is a pity in some ways, especially in something like science, because saying "I tried that and it didn't work because ..." is a useful guide to the next person. If I remember rightly when Richard Feynman stopped working on superfluids he gave a talk that was described by one listener as one of the most loving expositions of the false steps and problems that had been faced. That listener was one of the three scientists who shortly after, based on Feynman's work, cracked the basic theory of superfluids. How much would they have been delayed if Feynman had considered his work a failure and not published it? (Though I would not suggest that my tinkering with programs is in the same league on any scale!)
Number one. In a somewhat strange coincidence my Linux server at home gave up the ghost (fairly terminally it seems) and within five minutes something seemed to go pear-shaped on our Windows box meaning that Word crashed consiatently after 15 seconds and Pegasus Mail refused to run. Oh well, another server required and another Windows reinstall. Number two. The personal projects I tend to do at home tend to all have a similar pattern of development, namely fits and starts. There will be an initial flurry until it does what I want, and then tend to be ignored for a while and resuscitated every now and then when I get a new itch to scratch with it, or someone sends me a patch or I just feel like playing. One aspect of this is that my viewpoint on how things fit together or should fit together changes tends to change between flurries and it's always interesting to see what I get wrong and what I get right (especially since I usual try to ensure the projects teach me something as well as do whatever I'm after). For instance, in one of the early revisions for wmFuzzy I put in an extra abstraction layer between the approximation code and the display code and had the statement on the webpage saying this should make it easier to port to new displays. Well prior to the last release I ported it to two new displays. One on Windows/Mac based on Konfabulator, no easier because there was no code reuse, Konfabulator widgets are JavaScript, wmFuzzy is C. The second was a text version that just printed to approximation out, this at least used the same code base. Did the abstraction layer make it easier? No. Oops. I'd made various assumptions about the type of display (like it would want to support colour changes), I'd had a couple of howlers in terms of not separating the display logic for breaking the approximation into separate lines out from the formatting logic cleanly. I've now got rid of that abstraction layer and tried to structure things a bit more cleanly, there's a couple of quirks. Will it be easier to add another frontend now? I think so, for two reasons, firstly having done it once I'm more confident of the abstract and secondly, the code is simpler now. Number three. Zeno's paradox for the modern commuter - if the amount you miss the train by halves each day you still never catch the train. (Or the good week version, if the amount you catch the train by halves each day you still always catch the train and get extra time in bed!).
Well it's 6am and my brain's buzzing so consider this a sleep aid for the author (but hopefully not the reader!) One area of software development that I wouldn't say I'm particular comfortable with is user interface stuff. Partly this is lack of practice, which in turn is mainly because a fair number of the mini projects I've done over the years worked reasonably happily from the command line and weren't for anyone else so could be ad hoc. However I have a fair number of ideas I'd like to implement (too many for the time I've got but that's another, longer story) which would involve a GUI so I've been getting more interested in them. Thus articles like this one and bluffer's guides like this by Joel Spolsky are quite useful. In the first of these especially a few thing's hit home. One was Firefox's interactive search, which I use a lot, it's one of the real boons of still using Emacs for my programming that I get this made me realise how much I missed it some other places. Another example he give's was Konqueror's toolbar being to complicated. Again something I'd agree with but interestingly had never bothered me particularly despite the fact when I actually looked at it I couldn't workout what a couple of the buttons did without running Konqueror and looking at the tooltips (print frame and find it turns out), and I wasn't entirely sure if "up" would work as I expected (it does, but given at there are a reasonable number of sites that are layed out in a way that you'd get a directory you would not be allowed to view its a bit of an odd button). But this is probably a part of the problem, if you are fairly computer literature you can be reasonably confident of getting what you want done without being distracted by things not directly relevant (like wierd buttons on the toolbars, I only found out what that paint brush on Excel's does recently after using Excel for almost a decade). This isn't helped by the fact that if you start by writing a program for yourself you are more tolerant of wierd interfaces and even grow to work with them more than improve them for others. Another place I've been reading is Bruce Tognazzini's website. His most recent article talks about companies not listening to customers, even when they have glaring problems with their website, which brings me on to the next topic. I've been vaguely intending to get hold of and read DeMarco and Lister's Peopleware for a while now, and Robert D. Austin's Measuring and Managing Performance in Organizations. Well I finally got round to it this week. Neither seem to be available new in the UK at the minute and Amazon charmingly quoted me the best part of £50 to get Peopleware in paperback secondhand via their market place. Maybe not. Anyhow scratching around I turned up Abebooks, who are a second hand book exchange site. This is the sort of thing the internet and globalisation is great for. Result: I've got a copy of winging its way to me from Long Beach, California. The book cost me the princely sum of £3.75, the postage in comparison seems silly at £7.74 but the combined price is still probably less than I'd pay for a copy if I could find one over here. (Austin's book I found via a secondhand dealer in the UK so isn't as exciting.) What's that got to do with not listening to customers? Well, the Abebooks site is generally pretty good. But has one glaring stupidity in the sign up process. The customer agreement is pretty standard and is of typical length at about 3000 words. However it is displayed in text box that is 30 characters by 5 lines. So you get about 20 words at a time. In fairness they do have a click "here to print" link which will display the text readably. But why show it by default in such a ridiculously small box. When I pointed out to them that this seemed a bit daft, they're response was "We confirm that the box is for quick view." Right, very quick view, in fact you can't even see the entire first sentence. Oh well.
The reason for switching hosting provider for my website recently was to give me a bit more flexibility to do dynamic stuff. This morning I added the first example of this. The wmFuzzy webpage is now dynamic. Not very, but slightly. The time example of reading "quarter to six" rather than "05:44:01" is updated every few minutes (it didn't seem worth do it for every page load). It would be a bit nicer if it didn't land quite so close to the minute change, which is a side effect of using cron for the update (andI have a plan to get round this). The slightly more interesting bits will come when I get the database backed stuff going but I'm not quite there yet. Rather more excitingly because the DNS got updated to point at the new site, I could actually release the new version of wmFuzzy and the initial versions of konFuzzy and Password Maker which I'd been holding off as I didn't want to maintain duplicate websites.
I've been asked a couple of times about a Windows version of wmFuzzy and had an occasional look at doing one. One drawback was that hacking the Windows task bar clock is messy ( possible, but messy) and there's not much space there anyway. The other options were to use the fact that the Windows backdrop can be a web page and embed it there or just have a floating window. But neither really excited me enough to do much about it and I spend much time programming on Windows at home so I never really got round to it. Well, today Konfabulator was released for Windows. This allows little floating widgets to be put on your screen. Since these are a combination of XML and Javascript they're easy to write. Even knowing very little Javascript I was able to hack together something in about fifteen minutes that did pretty much what the first version of wmFuzzy did (peering at some of the provided widgets for to see how they worked). So soon there will be a Windows version (once I finish sorting out the bits like configuration and making it look a bit better). The hardest part? Working out how widget's are packaged. I couldn't find it stated anywhere but it turns out that the widget files are zip archives with a particular directory structure. Thankfully this is a common enough trick (Java .jars and Mozilla extensions do the same) that it was my first guess. The other unstated trick is that you don't have to rebuild the zip/widget file to run the widget, you can just do it from the Windows explorer provided you keep the folder structure right. This makes debugging a lot easier. (Maybe I'll find these in the manual but they aren't in the first few pages and I haven't read any further yet!) Tue, Nov. 9th, 2004, 10:19 am
I'm in the process of moving my website hosting from UKLinux.net to Acorn Hosting. I quite like my UKLinux deal but its never been quite as useful as I hoped. It gives you plenty of space (though I'm running out a having stuck a load of wedding photos up recently), a database (MySQL) and allow you to use Perl or PHP. For a starting place its been very good for the last three years. However I am never really comfortable using Perl and some of the things I've tried have been limited by the installed modules. MySQL is okay but the web interface is a bit clunky so I never really used it. Acorn gives me a lot more as it's a virtual host. I'm also hoping that it will be easier to actually configure things since I'll have ssh rather than just web interfaces and FTP. Besides being a virtual host it has 3Gb of space rather than about 30Mb and a choice of base Linux distribution, all for about £2 more a month than I paid for UKLinux (at current Sterling/Dollar exchange rates). Of course running a virtual host has a cost besides monetary: I've got to learn to administrate it properly. I've set up webservers for intranet sites before but I've never really done much about mail, DNS or that sort of thing. Thankfully (given my one previous failure for a intranet), the lovely people at Acorn deal with the DNS. Postfix seems a reasonably simple SMTP server. But picking up mail from the box isn't quite as obvious. Most of the ports, including 110 (the standard POP3 port), are firewalled, and while I'm could ask for them to be opened I'm quite happy to keep as little as possible open. I use fetchmail at home to pick up my mail from different sites, and that can tunnel through SSH easily. And a quick search turned up Cucipop as a POP3 daemon that ran with zero configuration on Debian. So that's what I'm doing. I'm also renewing acquaintances with AOLServer. Which is generally pretty easy to setup but has a few things that aren't obvious. Most of them are in the documentation somewhere but its not always obvious where, so they've all caused me a little bit of head scratching. - The current published docs on the web seem to be for version 3 and the current version is version 4 but there are docs for each module buried in the source tree.
- You can only have one TCL library per server.
- If you want to use nsperm then you better make sure you've copied the nsperm TCL modules into your TCL library as well as loading the C module in the config file. Failure to have the TCL will have the non-obvious symptom that despite a message saying the module is loaded no authentication is performed.
I'll probably find more in due course.
Turned on the radio over breakfast, the first lyrics that came out where "It's just another manic Monday, I wish it was Sunday, ..."
In a slightly bleary state this morning, that summed it up pretty perfectly. Fri, Oct. 29th, 2004, 11:27 am
This is very cool. Never need Powerpoint again.
Yeah, not exactly the most novel observation, but ran the last article past the inbuilt one on Livejournal, and it objected to "username", its alternatives?
user name, user-name, surname, Usenet, misname, Izanami, inseam, enamor, Esme, arsenate, ursine, tsunami, USN, enzyme, Islam, enema
Most of those I can understand, and my typing isn't great but I'd have to be pretty bad to have meant Islam, arsenate or USN. Sun, Oct. 24th, 2004, 08:37 am More NTL
I was being a bit rude about NTL recently but I have to say that while their phone system will melt your brain, it is a free call and once you get talk to their technical guys, they do know what they're on about and get things sorted quickly and easily. We had a couple of technicians come round yesterday to reconnect us who were pretty efficient despite the fact we hadn't been sent various details that we needed to activate the services by the sales guys. I also had to phone up to get an activation code for Broadband which we hadn't been sent. Except that when I got through the technician just said "nah, don't bother, go to this address, enter you're user-name and password [from our old account]." Bingo everything worked, less than 5 minutes of actual help. (Contrast with my recent experience of Tiscali where I had to explain everything 5 times whilst paying for the call). Hold music: F Sales staff: D Technicians: A
Why do so many sites insist on you signing up if you want to try their services? Surely you want to lower the barrier to entry? Just provide a dummy user account for test purposes. If you're worried about it being abused then just flush everything related to it every couple of hours. I'm much more likely to sign up for something if I can try it properly first. And I'm much more likely to try something if I don't have to go through a sign up process first. This is pretty much the principle behind shareware so it's not exactly a new idea, but not many web services seem to have caught on.
I discovered this in Turkey a few years ago. We were taken round a rug factory as part of a tour group after a visit to Ephesus and at the end was the obligatorily chance to purchase a rug. They were nice rugs but being students we weren't really interested (especially in the really nice silk rugs). We still got the hard sell. I can't remember exactly what the price started out as (£400 odd I think), high enough to be rejected out of hand, even for a fairly plain wool on wool rug. The more we said no the lower the price dropped. We eventually walking out the door when the salesman finally got about £160 and we yielded. I was reminded of this the other day buying a microwave and fridge for the new house. Extend warranties have been widely branded a waste of money but they pay nice commission to the sales staff. Having spent £100 on a microwave and £300 on a fridge/freezer (reduced by £160 because Hotpoint have recently been bought and so changed their logo and this has the old logo, mad, but I'm not complaining!) we were offered the chance of an extended three warranty from Powerhouse for £35 and £70 respectively. No thank you. No, really we don't want it. No, not even if you throw the cheaper one in free with the other one. In the end however we got the microwave covered. Why? because they just gave it to us for free. Presumably the chap got a commission on it and was allowed a certain "freebie" budget. There's only one thing that would have changed our mind about the fridge/freezer warranty. The time to fix. They boasted about "we'll fix it in two weeks." Two weeks! If the fridge/freezer goes, that's a real pain! Now if they'd offered a twenty-four hour service, that would have been more interesting. But I can't complain with free. Even history repeats itself for Powerhouse.
|