<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-34763567</id><updated>2012-01-21T17:41:42.241Z</updated><category term='Javascript'/><category term='maths'/><category term='memoization'/><category term='peer to peer'/><category term='SVG'/><category term='github'/><category term='algorithm'/><category term='algorithms'/><category term='image to icon'/><category term='networking'/><category term='client / server'/><category term='cognitive psychology'/><category term='c#'/><category term='c# spec-anaylsis'/><category term='foldl'/><category term='Zoom'/><category term='antivirus'/><category term='Drag'/><category term='SVGWeb'/><category term='AI'/><category term='database design'/><category term='haskell'/><category term='object thinking'/><category term='Sudoku'/><category term='programming in haskell'/><category term='pomodoro'/><category term='firewall'/><category term='addresses'/><category term='failure'/><category term='c++'/><category term='WPF'/><category term='rant'/><category term='adaptive protection'/><category term='Neural Networks'/><title type='text'>Mojo's software development blog</title><subtitle type='html'>I write software. Mostly in PHP and C#, but I occasionally delve elsewhere.

I'm keeping a web log of my activities.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-34763567.post-4485401793748268019</id><published>2011-10-19T02:38:00.002Z</published><updated>2011-10-19T02:38:51.604Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='object thinking'/><category scheme='http://www.blogger.com/atom/ns#' term='cognitive psychology'/><title type='text'>Object Thinking - Objects have actions</title><content type='html'>This post follows on from &lt;a href="http://mojoai.blogspot.com/2011/09/object-thinking-objects-neurological.html"&gt;Object Thinking - Objects: a neurological basis&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="western" style="font-style: normal;"&gt;The paper being reviewed is &lt;i&gt;Micro-affordance: The potentiation of components of action by seen objects &lt;/i&gt;(Ellis and Tucker, 2000)[1]&lt;i&gt;.&amp;nbsp;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt; &lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The paper focuses on two experiments. The first is concerned with power and precision micro-affordance, and the second with wrist rotation micro-affordance.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;In the first experiment the participants were told to memorise objects as they were shown them. They were then tested on the objects halfway through the experiment and at the end. During the memorisation phase, whenever they heard a tone, the participant was to either squeeze a cylindrical button with their whole hand, or pinch a small button between their index finger and thumb.&lt;br /&gt;&lt;br /&gt;The type of grip response would be dependant on the type of tone; high or low. So there were two mappings known to the participants: high – large grip, low – small grip, and high – small grip, low – large grip. There were also two unknown mappings: high – large object, low – small object, and high – small object, low large object.  &lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;Each participant was assigned one mapping from each of the two groups and this was sustained throughout the experiment.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;In the results from the experiment there was a statistically significant positive correlation between grip type and object type.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;The second experiment was set up much the same as the first. The differences were that instead of large or small grips, the participant would make clockwise or anticlockwise wrist rotations dependant on tone, and the objects were categorised as ones more easily grasped with an anticlockwise or clockwise wrist rotation.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;The results showed a statistically significant positive correlation between wrist rotation and object type.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;The paper classifies micro-affordance (MA) as the state of an observer that gives rise to stimulus-response compatibility (SRC) between what the viewer sees and what actions they perform regardless of their intention. The theory is meant as a solution to the symbol grounding problem. (The reference to this problem in the paper is Harnad, 1990[2].)&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;The paper explains that SRC is demonstrated in many previous experiments, by various researchers, in forced choice reaction time tests. For example an advantage is gained when reaching for something on the left with the left hand, and similarly for the right. In fact an advantage is gained even in non-reaching tasks, where the location of the stimulus gives an advantage when it is on the same side as the response, this is known as the Simon Effect.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;Previous experiments by Ellis and Tucker show that location is not the only action related feature encoded in this way.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;This preparedness for action is thought to be a coordination of the what and where pathways in the brain.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;The paper reports that the theoretical implications of the results of the study are:&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;div class="western" style="font-style: normal;"&gt;MA are different  from Gibsonian affordance in that they suggest the affordance is  encoded in the viewer's nervous system (not the object being  viewed), they only apply to grasping, and only grasping appropriate  to the object.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western" style="font-style: normal;"&gt;SRC works because  what is being responded to is unrelated to what is causing the  compatibility effect. SRC theories suggest that stimulus → response options elicit particular mental codes, so the location of  an object elicits a left or right handed response. MA, however, can  be evoked without evoking a coherent action.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;This means that MA  should interfere with SRC experiments.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;SRC effects have been  modelled as ecological relations between visual properties and  actions. They have also been modelled as effect codes that can be  combined into whole actions.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;MA and these two  approaches share the assumption that a compatibility effect arises  from visual objects and possible, real-world actions that can be  performed on them.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;MA diverges from the  ecological approach by retaining representation of objects, and from  effect codes by having a direct connection between vision and  action. MA diverges from both because it states that actions are  potentiated whenever an object is seen, regardless of the intention  of the viewer.&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div class="western" style="font-style: normal;"&gt;Developmentally,  MA fits in well with the popular theory of Neural Darwinism.  Development of adaptive behaviours requires integration of sensory  and motor processes. The paper proposes learning coordinated actions  result from gradual adaption of the neuron groups involved. This  leads to coupling of motor and sensory systems.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The implication of the  experiments is that MA reflect the involvement of the motor  components of the global mapping, which have come to represent  visual objects.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="western" style="font-style: normal;"&gt;So what does this tell us about how natural object thinking is? Object thinking requires that you understand the objects your are working with in terms of the behaviours that they can perform. You need to be able to create your objects so that discovering what behaviours are available is intuitive — i.e. when others come to your API they aren't spending hours going through the documentation, they can just get on and use it.&lt;br /&gt;&lt;br /&gt;Ellis and Tucker show that the brain is well suited to understanding and preparing for expected behaviours. When we see an object, we immediately know the actions that the object has available, and are primed to use them.&lt;br /&gt;&lt;br /&gt;This implies that once we have a good understanding of a problem domain, we should be able to model the behaviours of the objects in the domain intuitively, and anyone else with a good understanding of the problem domain will be able to intuitively discover each object and its behaviours.&lt;br /&gt;&lt;br /&gt;The behaviour driven aspects of object thinking are intrinsic to how the human mind works at the brain level.&lt;br /&gt;&lt;br /&gt;[1] Micro-affordance: The potentiation of components of action by seen objects; Rob Ellis, Mike Tucker. British Journal of Psychology (2000), 91, 451-471&lt;br /&gt;[2] Harnad, S. (1990). The symbol grounding problem. Physica D, 42, 335±346. (As sited in [1])&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-4485401793748268019?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/4485401793748268019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=4485401793748268019' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/4485401793748268019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/4485401793748268019'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2011/10/object-thinking-objects-have-actions.html' title='Object Thinking - Objects have actions'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-9219064863520941994</id><published>2011-09-22T20:50:00.000Z</published><updated>2011-10-19T02:40:25.377Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='object thinking'/><category scheme='http://www.blogger.com/atom/ns#' term='cognitive psychology'/><title type='text'>Object Thinking - Objects: a neurological basis</title><content type='html'>&lt;br /&gt;&lt;div class="western" style="font-style: normal;"&gt;This follows on from my post &lt;a href="http://mojoai.blogspot.com/2011/07/object-thinking-is-natural-way-to-think.html"&gt;Object Thinking is the natural way to think. Introduction&lt;/a&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;This post deals with how the brain perceives the world as objects.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;A neurologicalperspective of how perception work, via studying perceptualdisorders, is covered in chapter two of Neuropsychology: from theoryto practice [1]. This is a review of that chapter.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;Studying perceptualdisorders tell us how we work by looking at damaged brains in people,or damaging brains in animals, and seeing how that affects what isperceived.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The chapterconcentrates largely on visual perception, due to “the naturaldominance of our visual sensory system”. It starts out byidentifying two major pathways in the brain, the “what” pathway,which is responsible for identification of objects, and the “where”pathway, which is responsible for location position and motion. Thesewere originally identified in monkeys in 1983 by Mishkin, Ungerleiderand Macko. Milner and Goodale (1995) expanded on this model toexplain that the “where” pathway is dedicated to the preparationof movement.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;This demonstrates thathumans understand the world as objects and actions.&amp;nbsp;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The chapter goesonto explain that these two pathways are linked, essentially the flowof data goes primary visual cortex → “what” pathway → “where”pathway → motor cortex. The system also gets feedback, via otherpathways, from interactions with the environment to aid in learning.This of course means that we get better at performing actions themore we do them.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The next section of thechapter deals with sensation versus perception. It is notparticularly relevant to this discussion. In short summary: sensationoccurs before perception, and is not consciously recognised. Invision the sensation pathways are those that link the retina to thevisual cortex. People with damage to these pathway will not noticethat they don't see something, unless they are made aware of itappearing and disappearing from view.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;Discussion of thehierarchy of the visual cortex follows on. This has quite a strongneurological focus, and describes a lot of the brain's structure inthis area. The key point relevant here is that the brain is modularand parallel, which means that human thinking is modular andparallel, which is clearly analogous to separation of concerns. Theparallelism is accomplished through pathways that allow feedbackbetween modules. This could be thought of as message passing,although it might be a stretch to say it scales up to consciousthought.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;Next the chapterdiscusses what certain disorders show us about visual perception. Thetwo types of disorder covered are apperceptive agnosia – acondition that means the patient has a difficulty distinguishingbetween objects – and associative agnosia – in which the patientis unable to recognise objects or their functions. &lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;Apperceptive agnosia,and its milder counter part; categorisation deficit, give strongevidence that the mind perceives the world as objects. People withthese disorders cannot discern one object from another. This impedesproblem solving, as the person with the condition does not know howto act on what they see. In fact, in the case of apperceptiveagnosia, it can be equivalent to blindness, as those with thecondition find it easier to navigate with their eyes shut.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;Associative agnosia,prevents people from being able to recognise objects or theirfunctions. This class of agnosia can affect any of the senses. Thebook focuses on vision.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;People with associativeagnosia can copy (e.g. by drawing) and match objects, but they cannotrecognise. So it appears that primary perceptual processing isintact.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The current theory forwhat causes this agnosia is that the “what” pathway has becomedisconnected from the memory store for associative meaning. Peoplewith this condition can write something down, such as their name oraddress, but are completely unable to read it back. This is clearevidence that we use background knowledge to solve problems.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The chapter gives anexample (p. 53) of a patient, with associative visual agnosia, whocan only tell what a banana is after eating it, and even then onlythrough logical deduction: “...and here I go right back to thestage where I say well if it's not a banana, we wouldn't have thisfruit.”&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The next section of thechapter discusses object and face recognition. The focus is on howthis works at a neurological level, and the difference between facerecognition and object recognition. The key point it makes is thatthe left hemisphere of the brain deals with parts of objects, and theright deals with objects as a whole. (Faces, are a special case,however, as they seem to be perceived as a whole, and not as parts,i.e. most of facial recognition is done in the right hemisphere.) Thebrain is set up to understand about composition.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The rest of the chapterfocuses on describing top down (using past experience to influenceperception) and bottom up (working from first principles) processingof visual information, and come to a conclusion about how the leftand right hemispheres interact to give what we see meaning.Essentially they work together, the left hemisphere identifyingobjects and the meaning of objects, while the right analysesstructural form, orientation and does holistic analysis of an object.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;So, in conclusion, the chapter lays out clearly that human beings perceive the world as objects, even at a neurological level. This is our nature. Thus is makes sense when designing software to think of our problem space in terms of the objects in it.&amp;nbsp;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;The next section will deal with why action is integral to how we think about the world, and can be found here:&amp;nbsp;&lt;a href="http://mojoai.blogspot.com/2011/10/object-thinking-objects-have-actions.html"&gt;Object Thinking - Objects have actions&lt;/a&gt;.&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western" style="font-style: normal;"&gt;[1] Neuropsychology: from theory to practice, David Andrewes (2001, Psychology Press)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-9219064863520941994?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/9219064863520941994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=9219064863520941994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/9219064863520941994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/9219064863520941994'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2011/09/object-thinking-objects-neurological.html' title='Object Thinking - Objects: a neurological basis'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-3573433009119898824</id><published>2011-07-09T16:57:00.010Z</published><updated>2011-09-26T12:43:05.934Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='object thinking'/><category scheme='http://www.blogger.com/atom/ns#' term='cognitive psychology'/><title type='text'>Object Thinking is the natural way to think. Introduction</title><content type='html'>&lt;span style="font-size: large;"&gt;Preface&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;I don't know why I'm up so early on a Saturday, but I am. *yawn*. So I've been writing a paper reviewing other texts, to explain why Object Thinking is the natural way to think.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;I am doing this because I do not want to lose an internet argument. I know. I've already lost. Both side have. That's how internet arguments work.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;The argument is at &lt;a href="http://programmers.stackexchange.com/"&gt;Programmers&lt;/a&gt;, particularly my answer to the question &lt;a href="http://programmers.stackexchange.com/questions/59387/is-oop-hard-because-it-is-not-natural/59479#59479"&gt;"is OOP hard because it is not natural?"&lt;/a&gt; &lt;a href="http://programmers.stackexchange.com/users/13612/sk-logic"&gt;SK-Logic&lt;/a&gt; is zealously anti OO, and I am equally zealously pro OO.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;Then the other day I was discussing what I'm writing with &lt;a href="http://programmers.stackexchange.com/users/2567/pierre-303"&gt;Pierre 303&lt;/a&gt;, in the Programmers' chat room, and he suggested that I make it into several 'blog articles, because then it would be easier to digest. I agree, so that's what I'm doing. I still don't know why I'm up so early, but at least I'm doing something.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;div class="western"&gt;Object Thinking; it's been around for decades as a paradigm for software design, but what is it? When presented with a problem, someone usingobject thinking will start to decompose the problem into discretesections that can interact with each other. You could, for example, be forced to change the tyre on your car. A simple task, certainly, but to do it you must understand the tools and relevant components of your car, and how they need to work together to achieve your goal.&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;/div&gt;&lt;div class="western"&gt;It might take several attempts to achieve a finegrained enough understanding to effectively solve the problem. Yourfirst pass at the above example might leave you with the idea to takethe wheel off your car. A second thinking might make you realise thatyou need to lift the car off the floor to do that, and so on.&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;/div&gt;&lt;div class="western"&gt;One thing that can give you a head start insolving a problem using object thinking is background knowledge.Knowing about your problem domain, what the objects in it are capableof, makes it easier to plan how to use them. Not knowing enough cancause issues, however, if assumptions are made based on incompleteknowledge.&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;/div&gt;&lt;div class="western"&gt;For example: You are asked to stick a poster tothe wall, without leaving holes in the wall. You are given a hamster,newspaper and some Blu Tack®, along with the poster. If you don'tknow what Blu Tack® is for then your understanding of the problemdomain is incomplete and you could end up using  the hamster to chewup newspaper into balls, and use those to stick the poster to thewall.&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;It is also important to note that not everythingpresent in your problem domain will necessarily be used to solve theproblem. So, in the previous example, you might not use the newspaperor hamster at all (or, of course, you might find the hamster solutionbetter, as it reuses the newspaper, which is more ecological).&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;/div&gt;&lt;div class="western"&gt;So how does this apply to software design?Software is just “algorithms and data structures”, right? Well,at the end maybe, but you've still got to design it. Software is theoutput of people's attempt to solve a problem. Solving a problem withobject thinking is the natural way, as this series of posts hopes todemonstrate, because it uses people's natural problem solvingtechniques.&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;/div&gt;&lt;div class="western"&gt;Object thinking is a core tenet of Object OrientedDesign (OOD), a well known software design paradigm. The inventors ofOOD set out to fix what they saw are the main problem with softwaredesign – software design was taught to make people think likecomputers, so that they could write software for computers. &lt;/div&gt;&amp;nbsp; &lt;br /&gt;&lt;div class="western"&gt;A book that extensively covers the meaning andpractical aspects of object thinking is Object Thinking by David West(2004, Microsoft Press). In it he likens the way that traditionalprogrammers use OOD to writing lots of small COBOLprogrammes [1]. Objects in this sense have been turned into datastructures with algorithms wrapped around them. While modularisingcode is better than having one large function, it only makesdesigning software a little easier. It still focuses the attention ofthe design on how a computer works and not how the problem should be solved.&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;So what makes reasoning about large systemseasier? Focusing on the problem space and decomposing it into severalsmaller problems helps. But what is easier to think about? Is iteasier to think how those problems translate into code? Perhaps inthe short term, but you will end up solving the same problems overand over again, and your code will probably be inflexible.&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;/div&gt;&lt;div class="western"&gt;Would it be better to think about software designthe same way you think about solid world problems? That way you canuse your innate problem solving skills to frame and express yourdesign.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;It turns out that the way people reason about realworld problems is to break them down into smaller parts, using theirbackground understanding of the problem space, take the parts of theproblem space and treat them as objects that can do things and havethings done to them, and find way for the objects to interact. [2]&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;/div&gt;&lt;div class="western"&gt;This works well because people like toanthropomorphise objects, so that they can imagine the object doingthings under its own agency, even if in the end it's a person causingthe action.[3]&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;&lt;/div&gt;&lt;div class="western"&gt;How can you be sure this is how you think, and istherefore the more sensible way to approach software design? Well itturns out that there is an oft ignored backwater science known asCognitive Psychology, and scientists in this field have been studyingpeople for decades, to find out how they work.&lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="western"&gt;Future posts in this series will review certain cognitive psychology and neuropsychology texts and expand on how this applies to object thinking. The end goal is to demonstrate that object thinking is innate and therefore the best strategy for designing software.&lt;br /&gt;&lt;br /&gt;Next post in the series:&amp;nbsp;&lt;a href="http://mojoai.blogspot.com/2011/09/object-thinking-objects-neurological.html"&gt;Object Thinking - Objects: a neurological basis &lt;/a&gt; &lt;/div&gt;&lt;div class="western"&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;References&lt;/span&gt;&lt;br /&gt;[1] Object Thinking, D. West (2004, Microsoft Press) p9&lt;br /&gt;[2] &lt;a href="http://en.wikibooks.org/wiki/Cognitive_Psychology_and_Cognitive_Neuroscience/Problem_Solving_from_an_Evolutionary_Perspective#How_is_a_problem_represented_in_mind.3F"&gt;Problem Solving from an Evolutionary Perspective&lt;/a&gt;&lt;span style="font-size: small;"&gt; visited 9th July 2011&lt;/span&gt;&lt;br /&gt;[3] Object Thinking, D. West (2004, Microsoft Press) p101&lt;br /&gt;&lt;br /&gt;Blu-Tack is a registered trademark of &lt;a href="http://www.bostik.co.uk/"&gt;Bostik&lt;/a&gt;. I am not affiliated with Bostik.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-3573433009119898824?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/3573433009119898824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=3573433009119898824' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/3573433009119898824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/3573433009119898824'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2011/07/object-thinking-is-natural-way-to-think.html' title='Object Thinking is the natural way to think. Introduction'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-3154135244829796313</id><published>2011-04-29T12:09:00.001Z</published><updated>2011-04-29T12:19:44.349Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='client / server'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><category scheme='http://www.blogger.com/atom/ns#' term='networking'/><title type='text'>Networking client / server example</title><content type='html'>At work I have been writing a lot of code relating to sending data over a TCP connection.&lt;br /&gt;&lt;br /&gt;I have also seen a couple of questions, recently, on Stack Overflow asking about why networking code wasn't working. Unfortunately I didn't have time to answer them, but it did make me think that there must be a dearth of good samples of networking code online.&lt;br /&gt;&lt;br /&gt;Allow me to make that dearth one sample fewer! (Does that make sense?)&lt;br /&gt;&lt;br /&gt;For the full listing visit my Github repository: &lt;a href="https://github.com/Mellen/Networking-Samples"&gt;https://github.com/Mellen/Networking-Samples&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One problem, that sparked my interest, was how to to keep the server running &lt;a href="http://stackoverflow.com/questions/5715269/constantly-running-server"&gt;when a client disconnects&lt;/a&gt;. Because the server needs to know when a client disconnects, and not just choke and die. A client disconnecting is not an exceptional circumstance.&lt;br /&gt;&lt;br /&gt;The first problem is to not let the server die when a client disconnects, the second is to keep the server looking for new connections, so that it can be a server.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Keep it alive! &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My solution to the disconnection problem got generalised to both the client and the server classes, because it makes sense to not have the client die if the server disappears. The user might want to try to reconnect.&lt;br /&gt;&lt;br /&gt;You'll find this code in the file NetworkSampleLibrary/NetworkStreamHandler.cs&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;protected void ReadFromStream(object worker, DoWorkEventArgs args){    BackgroundWorker streamWorker = worker as BackgroundWorker;    NetworkStream stream = args.Argument as NetworkStream;    try    {        HandleStreamInput(stream);    }    catch (Exception ex)    {        if (ex is IOException || ex is ObjectDisposedException || ex is InvalidOperationException)        {            streamWorker.CancelAsync();        }        if (ex is IOException || ex is InvalidOperationException)        {            stream.Dispose();        }        if (StreamError != null)        {            StreamError(ex, stream);        }    }}&lt;/div&gt;&lt;br /&gt;You might have noticed that the method is an event handler. More on that below.&lt;br /&gt;&lt;br /&gt;As you can see, there are three types of exception that can happen if a client disconnects from the server: &lt;a href="http://msdn.microsoft.com/en-us/library/system.io.ioexception.aspx"&gt;IOException&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/system.objectdisposedexception.aspx"&gt;ObjectDisposedException&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.invalidoperationexception.aspx"&gt;InvalidOperationException&lt;/a&gt;. I found this out through trial and error.&lt;br /&gt;&lt;br /&gt;The most common exception that gets thrown when a client disconnects is IOException. This is because the server will be trying to read from the client when it leaves.&lt;br /&gt;&lt;br /&gt;Because of the threaded nature of the system, ObjectDisposedExceptions gets thrown when another exception gets thrown and the server still tries to read from the stream in the mean time.&lt;br /&gt;&lt;br /&gt;I'm not entirely sure why InvalidOperationException gets thrown, and it doesn't happen a lot, but it is always when the client disconnects.&lt;br /&gt;&lt;br /&gt;My strategy is to catch all exceptions, deal with the disconnection exceptions by disposing of the stream if necessary and cancelling the process that reads from the stream, then raising an event that contains the exception and the stream that threw it. I could create a custom exception here, but I settled on an event just in case something that wouldn't catch an exception wanted to know about it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;All are welcome&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The next part of the puzzle is to make sure that more than one client can connect to your server.&lt;br /&gt;&lt;br /&gt;This is achieved in the NetworkServer class. This can be found at NetworkServerSample / NetworkServer.cs&lt;br /&gt;&lt;br /&gt;The pertinent parts are listed below: &lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;public NetworkServer(int port){    _listener = new TcpListener(IPAddress.Any, port);    _listener.Start();    _listener.BeginAcceptTcpClient(AcceptAClient, _listener);    DataAvilable += SendDataToAll;    StreamError += (ex, stream) =&amp;gt;        {            if (ex is IOException || ex is InvalidOperationException || ex is ObjectDisposedException)            {                _streams.Remove(stream);                Console.WriteLine("lost connection {0}", ex.GetType().Name);            }            else            {                throw ex;            }        };}private void AcceptAClient(IAsyncResult asyncResult){    TcpListener listener = asyncResult.AsyncState as TcpListener;    try    {        TcpClient client = listener.EndAcceptTcpClient(asyncResult);        Console.WriteLine("Got a connection from {0}.", client.Client.RemoteEndPoint);        HandleNewStream(client.GetStream());    }    catch (ObjectDisposedException)    {        Console.WriteLine("Server has shutdown.");    }    if (!_disposed)    {        listener.BeginAcceptTcpClient(AcceptAClient, listener);    }}private void HandleNewStream(NetworkStream networkStream){    _streams.Add(networkStream);    BackgroundWorker streamWorker = new BackgroundWorker();    streamWorker.WorkerSupportsCancellation = true;    streamWorker.DoWork += ReadFromStream;    streamWorker.RunWorkerCompleted += (s, a) =&amp;gt;                                        {                                            if (_streams.Contains(networkStream) &amp;amp;&amp;amp; !a.Cancelled)                                            {                                                streamWorker.RunWorkerAsync(networkStream);                                            }                                        };    streamWorker.RunWorkerAsync(networkStream);}&lt;/div&gt;&lt;br /&gt;In the constructor, the server is set up to listen on a particular port for incoming connections and handle the connection requests asynchronously. It also creates an event handler for when the network stream throws an exception, as explained above. This makes sure that the stream is removed from the list of streams, so that it doesn't try to get disposed of when the server is disposed, and that no data gets broadcast down it.&lt;br /&gt;&lt;br /&gt;The method that deals with the asynchronous requests for connection (AcceptAClient) has to make sure that the server hasn't been disposed of when the connection attempt is made, hence the try-catch block. Once the connection request has been handled then the method starts listening for another connection attempt. This is all it takes, essentially asynchronous recursion.&lt;br /&gt;&lt;br /&gt;The HandleNewStream method also uses asynchronous recursion to read each message from the client. It sets up a &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx"&gt;BackgroundWorker&lt;/a&gt; instance that asynchronously calls the ReadFromStream method in the previous section, and when the work is complete, the worker will call the method again, so long as the stream is in the list of streams on the server and the worker has not been cancelled.&lt;br /&gt;&lt;br /&gt;That's the meat of the server. Accepting and handling input from more than one client is achieved with a list and asynchronous recursion. Dealing with clients disconnecting is done with exception handling and events.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-3154135244829796313?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/3154135244829796313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=3154135244829796313' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/3154135244829796313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/3154135244829796313'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2011/04/networking-client-server-example.html' title='Networking client / server example'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-7674303068020905613</id><published>2011-04-28T21:47:00.003Z</published><updated>2011-04-28T21:56:12.563Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='maths'/><title type='text'>Really basic programming maths (part 1)</title><content type='html'>So I've been trying to mentally do hexadecimal addition. I've found that I'm not very good at it.&lt;br /&gt;&lt;br /&gt;I'm going to slowly explain how I go about working stuff out, with the hope that it will stick in my head and get easier. (Binary is written with the most significant bit first, and all numbers are unsigned.)&lt;br /&gt;&lt;br /&gt;First of all there is how to think about numbers in binary and hex.&lt;br /&gt;&lt;br /&gt;Decimal numbers get split up into multiples of powers of ten.&lt;br /&gt;&lt;br /&gt;For example 4181 can be broken down as:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;4 x 10&lt;sup&gt;3&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;1 x 10&lt;sup&gt;2&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;8 x 10&lt;sup&gt;1&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;1 x 10&lt;sup&gt;0&lt;/sup&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Remembering that all numbers raised to 0 are 1.&lt;br/&gt;&lt;br /&gt;This applies to both binary and hexadecimal too.&lt;br /&gt;&lt;br /&gt;So 0xFEED breaks down to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;F(15) x 10(16)&lt;sup&gt;3&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;E(14) x 10(16)&lt;sup&gt;2&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;E(14) x 10(16)&lt;sup&gt;1&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;D(13) x 10(16)&lt;sup&gt;0&lt;/sup&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt; The numbers in parenthesis are the decimal representations of the hexadecimal numbers.&lt;br /&gt;&lt;br /&gt;And 0b1101 breaks down to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;1(1) x 10(2)&lt;sup&gt;3&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;1(1) x 10(2)&lt;sup&gt;2&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;0(0) x 10(2)&lt;sup&gt;1&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;1(1) x 10(2)&lt;sup&gt;0&lt;/sup&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt; The numbers in parenthesis are the decimal representations of the binary numbers.&lt;br /&gt;&lt;br /&gt;Next up is the easy way to transition from hex to binary and back.&lt;br /&gt;&lt;br /&gt;Since an individual hex digit takes up to a maximum of four bits, all hex numbers can be represented as collections of four bit numbers.&lt;br /&gt;&lt;br /&gt;So 0x4432 can be broken down into 0b0100, 0b0100, 0b0011, 0b0010&lt;br /&gt;&lt;br /&gt;This can be reversed. Say you have the 32bit number 0b10011100110100110101101011110011.&lt;br /&gt;&lt;br /&gt;If you break it down into four bit chunks you get: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;0b1001&lt;/li&gt;&lt;li&gt;0b1100&lt;/li&gt;&lt;li&gt;0b1101&lt;/li&gt;&lt;li&gt;0b0011&lt;/li&gt;&lt;li&gt;0b0101&lt;/li&gt;&lt;li&gt;0b1010&lt;/li&gt;&lt;li&gt;0b1111&lt;/li&gt;&lt;li&gt;0b0011&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Each chunk can be represented as a hex digit: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;0x9&lt;/li&gt;&lt;li&gt;0xC&lt;/li&gt;&lt;li&gt;0xD&lt;/li&gt;&lt;li&gt;0x3&lt;/li&gt;&lt;li&gt;0x5&lt;/li&gt;&lt;li&gt;0xA&lt;/li&gt;&lt;li&gt;0xF&lt;/li&gt;&lt;li&gt;0x3&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Which gives us the number 0x9CD35AF3.&lt;br /&gt;&lt;br /&gt;The difficult part comes in getting that number as decimal.&lt;br /&gt;&lt;br /&gt;To do it from hex, you need to add up all the powers of sixteen that there are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;9 x 16&lt;sup&gt;7&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;12 x 16&lt;sup&gt;6&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;13 x 16&lt;sup&gt;5&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;3 x 16&lt;sup&gt;4&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;5 x 16&lt;sup&gt;3&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;10 x 16&lt;sup&gt;2&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;15 x 16&lt;sup&gt;1&lt;/sup&gt;&lt;/li&gt;&lt;li&gt;3 x 16&lt;sup&gt;0&lt;/sup&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Which turns out to be: 2631097075. Not easy to calculate in your head. To do it from binary would take even longer as you would need to add up all the powers of two from 31 to 0.&lt;br /&gt;&lt;br /&gt;Thus endeth part one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-7674303068020905613?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/7674303068020905613/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=7674303068020905613' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/7674303068020905613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/7674303068020905613'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2011/04/really-basic-programming-maths-part-1.html' title='Really basic programming maths (part 1)'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-4762590980317786364</id><published>2010-12-13T22:31:00.000Z</published><updated>2010-12-13T22:31:52.028Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='database design'/><category scheme='http://www.blogger.com/atom/ns#' term='addresses'/><title type='text'>Addresses in databases</title><content type='html'>&lt;style&gt;th,td{    padding: 4px;}&lt;/style&gt;&lt;br /&gt;Whenever I see something like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: none repeat scroll 0% 0% rgb(255, 255, 193); border-style: groove; margin-left: 20px; padding-right: 10px; width: 330px;"&gt;&lt;ul style="list-style-type: none; text-align: right;"&gt;&lt;li&gt;Address Line 1: &lt;input type="-&amp;quot;text&amp;quot;" /&gt;&lt;/li&gt;&lt;li&gt;Address Line 2: &lt;input type="-&amp;quot;text&amp;quot;" /&gt;&lt;/li&gt;&lt;li&gt;Address Line 3: &lt;input type="-&amp;quot;text&amp;quot;" /&gt;&lt;/li&gt;&lt;li&gt;City: &lt;input type="-&amp;quot;text&amp;quot;" /&gt;&lt;/li&gt;&lt;li&gt;Country: &lt;input type="-&amp;quot;text&amp;quot;" /&gt;&lt;/li&gt;&lt;li&gt;Post Code: &lt;input type="-&amp;quot;text&amp;quot;" /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;br /&gt;I want to find the database designer and smack them.&lt;br /&gt;&lt;br /&gt;What is it about addresses that make people think that they don't need normalising?&lt;br /&gt;&lt;br /&gt;No! Of course! The solution to storing addresses is to create a table and force all addresses to fit into five lines plus a postal code. Brilliant. Really smart.&lt;br /&gt;&lt;br /&gt;There is one mandatory field in the address: country. That's the only one. Everyone lives in a country. I don't want to get into stupid arguments like "Wales isn't a country it's a principality", etc., when you put it in an address it's a country.&lt;br /&gt;&lt;br /&gt;You know something people know? How many lines there are in their address. So don't force them to have 3, 4, 5, xty mumble-jillion, or however many you think is sufficient.&lt;br /&gt;&lt;br /&gt;This is what I want to see from now on:&lt;br /&gt;&lt;br /&gt;&lt;div style="background: none repeat scroll 0% 0% rgb(255, 255, 193); border-style: groove; margin-left: 20px; padding-right: 10px; width: 330px;"&gt;&lt;b&gt;Address&lt;/b&gt;&lt;br /&gt;&lt;input type="text" /&gt;&lt;br /&gt;&lt;input type="button" value="Add a line" /&gt;&lt;/div&gt;&lt;br /&gt;If you do the post / zip / whatever code search thing, then great, but be sure to store the address lines in a sensible manner.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;address_id&lt;/th&gt;&lt;th&gt;line_id&lt;/th&gt;&lt;th&gt;text&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;My House Name&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;My Street Name&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;My City Name&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;My Post Code&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;My Country&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-4762590980317786364?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/4762590980317786364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=4762590980317786364' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/4762590980317786364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/4762590980317786364'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/12/addresses-in-databases.html' title='Addresses in databases'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-7498011624219369938</id><published>2010-12-02T16:43:00.001Z</published><updated>2010-12-02T16:43:33.186Z</updated><title type='text'>Re: quick idea</title><content type='html'>It's not trivial. There is no easy way to convert a file like jpg/png/gif into icon format. Arbitraried!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-7498011624219369938?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/7498011624219369938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=7498011624219369938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/7498011624219369938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/7498011624219369938'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/12/re-quick-idea.html' title='Re: quick idea'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-8330113557379387796</id><published>2010-11-14T18:34:00.000Z</published><updated>2010-11-14T18:34:56.937Z</updated><title type='text'>No coding Sundays</title><content type='html'>I've decided that I'm going to not code on Sundays.&lt;br /&gt;&lt;br /&gt;I'll try and cut out Stack Overflow too, except for next Sunday because that is my 99th consecutive day. I NEED MY BADGE.&lt;br /&gt;&lt;br /&gt;Sundays will be given over to something else. Anything else.&lt;br /&gt;&lt;br /&gt;It's not that I've stopped loving coding. I think I love it too much. I'm going to see what else there is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-8330113557379387796?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/8330113557379387796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=8330113557379387796' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/8330113557379387796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/8330113557379387796'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/11/no-coding-sundays.html' title='No coding Sundays'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-3265618017998046665</id><published>2010-10-22T08:54:00.002Z</published><updated>2010-10-22T08:54:48.367Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='image to icon'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Quick idea</title><content type='html'>I think it should be trivial to make an png/jpeg/gif/bmp -&amp;gt; icon creator&lt;br /&gt;&lt;br /&gt;I'm going to work to one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-3265618017998046665?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/3265618017998046665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=3265618017998046665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/3265618017998046665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/3265618017998046665'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/10/quick-idea.html' title='Quick idea'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-4320496176905146863</id><published>2010-10-08T21:24:00.003Z</published><updated>2010-10-09T17:36:18.056Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='Sudoku'/><category scheme='http://www.blogger.com/atom/ns#' term='algorithm'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Solving Sudoku</title><content type='html'>I was chatting with my manager the other day, just shooting the breeze, and we got on to how he knocked together a python script to prove to his girlfriend that programmatically solving sudoku puzzles is easy.&lt;br /&gt;&lt;br /&gt;I disagreed for a moment and then realised I was thinking of generating sudoku puzzles, which we agreed isn't easy.&lt;br /&gt;&lt;br /&gt;I had tried to make a sudoku helper app before, to practice MVVM and WPF, but had messed up in some calculation or other. Probably at the point where I was calculating which block a square was in. Anyway I had deleted that one, but my boss had spurred my interest in doing it again.&lt;br /&gt;&lt;br /&gt;I'm a better programmer than I was that first time - I understand both WPF and MVVM better now, so this little solver is pretty sweet. (Unless you look at the code.)&lt;br /&gt;&lt;br /&gt;It has all the features I need. I can fill in the known numbers, delete mistakes, and click a button to solve the unknowns (once the knowns are in place).&lt;br /&gt;Sometimes you don't even need the button, since the programme eliminates possibilities as you type. One puzzle I tried was solved before I typed in all the known numbers!&lt;br /&gt;&lt;br /&gt;So my amazing solver has two simple algorithms doing the solving:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Each square has an event that fires when its number of possible values reaches 1, either programmatically or by user intervention. This event is subscribed to by all the squares related to it (row, column, block), and so each related square will remove this value from their possible values list. This can cause a chain reaction of updates, solving the sudoku puzzle when enough knowns are typed in.&lt;/li&gt;&lt;li&gt;If elimination alone doesn't do the job then the second algorithm is just a button click away. I might have over thought this one:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;Create a list of squares that have at least 2 possible values, sorted in ascending order of number of possible values&lt;/li&gt;&lt;li&gt;Take the first square and find all the squares in the same block&lt;/li&gt;&lt;li&gt;Add theses squares to a checked block list&lt;/li&gt;&lt;li&gt;Flatten the lists of potential values into one list&lt;/li&gt;&lt;li&gt;Find any unique values in that list&lt;/li&gt;&lt;li&gt;If there are any unique values then these represent solved squares so break out of the loop and update the squares related to those values.&lt;/li&gt;&lt;li&gt;If there isn't a unique value then repeat 3, 4 and 5 for the row, then the column of the current square.&lt;/li&gt;&lt;li&gt;If after that there still isn't a unique value, move onto the next square that hasn't been checked yet.&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;If at the end of the second algorithm a number hasn't been updated then the programme lets the user know that it needs more knowns, otherwise it starts the second algorithm again until all the squares are filled. &lt;br /&gt;&lt;br /&gt;I know what you're thinking. You're thinking that if a user makes a mistake inputting a value, then when they delete it and input a new value the possible values list for the related squares will be wrong. Fear not! Deleting a value fires an event that does the opposite of inserting a value, so things go back to the way they were. Phew!&lt;br /&gt;&lt;br /&gt;If you want to look at the code it's on github here: &lt;a href="http://github.com/Mellen/SudokuSolver"&gt;http://github.com/Mellen/SudokuSolver&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The code is c#. The project is a Visual Studio 10 project, that runs on the .NET 4.0 framework. It even has a couple of unit tests. Yes, I'm &lt;i&gt;that &lt;/i&gt;guy. I unit test toy projects.&lt;br /&gt;&lt;br /&gt;The executable is available from github: &lt;a href="http://github.com/downloads/Mellen/SudokuSolver/SudokuSolver1.0.2.zip/qr_code"&gt;SudokuSolver1.0.2.zip&lt;/a&gt;. It requires .NET version 4.0.&lt;br /&gt;&lt;br /&gt;Anyway! This was a fun little diversion. I makes me happy that I got it right the second time.&lt;br /&gt;&lt;ol&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-4320496176905146863?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/4320496176905146863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=4320496176905146863' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/4320496176905146863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/4320496176905146863'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/10/solving-sudoku.html' title='Solving Sudoku'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-9084373153550634798</id><published>2010-09-20T18:31:00.000Z</published><updated>2010-09-20T18:31:50.062Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='c# spec-anaylsis'/><title type='text'>Thinking about learning</title><content type='html'>So, my lack knowledge needs to take a bit of a beating.&lt;br /&gt;&lt;br /&gt;If I'm to get significantly better at writing C#, I need to understand the specification.&lt;br /&gt;&lt;br /&gt;It seems like a daunting task, but I think if I try and tackle a point at a time, writing small programmes to demostrate my understanding, I'll get a much deeper understanding of how my programmes hang together and how to write them better.&lt;br /&gt;&lt;br /&gt;Wish me luck!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-9084373153550634798?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/9084373153550634798/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=9084373153550634798' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/9084373153550634798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/9084373153550634798'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/09/thinking-about-learning.html' title='Thinking about learning'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-79587662131258113</id><published>2010-08-28T19:49:00.000Z</published><updated>2010-08-28T19:49:43.568Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='algorithms'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><title type='text'>Learning to see patterns in my own behaviour</title><content type='html'>&lt;p&gt;So, a week and a half ago I was looking at a question on Stack Overflow (&lt;a href="http://stackoverflow.com/questions/3510586/algorithm-to-calculate-the-number-of-combinations-to-form-100"&gt;Algorithm to calculate the number of combinations to form 100 &lt;/a&gt;). I set about solving it in Haskell, and came up against a block to my success:&lt;/p&gt;&lt;p&gt;Given a list of numbers &lt;span class="code"&gt;xs&lt;/span&gt; and another number &lt;span class="code"&gt;n&lt;/span&gt;, generate a list of all the possible combinations lists of length &lt;span class="code"&gt;n&lt;/span&gt; that contain the numbers from &lt;span class="code"&gt;xs&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;So, given the list &lt;span class="code"&gt;[1,2]&lt;/span&gt; and the number &lt;span class="code"&gt;3&lt;/span&gt;, the function should generate this list of lists: &lt;span class="code"&gt;[[1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]]&lt;/span&gt;&lt;/p&gt;&lt;p&gt;I was pretty sure that this had been done before, but because I'm trying to get better at deducing algorithms, I'm stubborn, and I'm doing this for fun I decided to figure out the algorithm for myself.&lt;/p&gt;&lt;p&gt;It wasn't as easy as it seemed.&lt;/p&gt;&lt;p&gt;I sat down and wrote out the outputs for a few different sets of inputs, I looked at them, I looked some more. I could see a couple of patterns, namely that &lt;span class="code"&gt;(length of xs)&lt;sup&gt;n&lt;/sup&gt;&lt;/span&gt; is the length of the final output and that you could create a rectangle of answers with width &lt;span class="code"&gt;length of xs&lt;/span&gt; and height &lt;span class="code"&gt;(length of xs - 1)&lt;sup&gt;n&lt;/sup&gt;&lt;/span&gt;. Neither of these were helpful.&lt;/p&gt;&lt;p&gt;I left the problem alone for a while, hoping that time would give me perspective. I was surprised how hard I was finding it to find the pattern.&lt;/p&gt;&lt;p&gt;Today I came back to it with a fresh brain and time to kill. I took a walk to the park, sat down, started to write out the output where the input is a list of length 3, and &lt;span class="code"&gt;n&lt;/span&gt; as 3. As I was writing, I had the realisation that the way to solve this was to figure out the algorithm of how to write it down. The problem in my previous examples of output was that I hadn't written it in a good enough pattern. I started writing out the output for a different input a list of length 4, with &lt;span class="code"&gt;n&lt;/span&gt; of 4 (256 items, for those keeping count). This time I was very systematic about how I wrote out the output. I got to the 44th list in the list and stopped to see if I could see it yet. I could: the last element in the individual lists was repeating every 4 items.&lt;/p&gt;&lt;p&gt;I stood up and, as is my wont when I am thinking, I started pacing. I must have looked a little unhinged, as I was pacing in a small circle around my bag.&lt;/p&gt;&lt;p&gt;It took me a few minutes, but eventually I figured out how to represent what I was seeing in my written output as an algorithm: the first time through, each item of &lt;span class="code"&gt;xs&lt;/span&gt; is appended to an empty list, for each subsequent time through, each item in &lt;span class="code"&gt;xs&lt;/span&gt; is appended to each list in the list of lists.&lt;/p&gt;&lt;p&gt;In Haskell, I came up with this function to do the work:&lt;/p&gt;&lt;p class="code"&gt;makeallsets :: Integral a =&gt; [a] -&gt; a -&gt; [[a]]makeallsets xs n = mas (addtoonelist [] xs) xs (n - 1) where mas yss _ 0        = yss       mas yss xs (n + 1) = mas (addtoeachlist yss xs) xs n        where addtoeachlist [] xs       = []              addtoeachlist (ys:yss) xs = (addtoonelist ys xs) ++ (addtoeachlist yss xs)       addtoonelist ys []     = []       addtoonelist ys (x:xs) = (x : ys) : (addtoonelist ys xs)&lt;/p&gt;&lt;p&gt;This allowed me to create an answer to the Stack Overflow problem. (Although there's no point posting it for 3 very good reasons: 1. it's not in the target language (which is Scala); 2. It uses the brute force approach; 3. There is already a better answer.)&lt;/p&gt;&lt;p&gt;Score 1 for perseverance!&lt;/p&gt;&lt;p&gt;P.s. if anyone would like to show me a better way, I'd be very glad to hear it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-79587662131258113?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/79587662131258113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=79587662131258113' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/79587662131258113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/79587662131258113'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/08/learning-to-see-patterns-in-my-own.html' title='Learning to see patterns in my own behaviour'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-5409871747974295923</id><published>2010-07-25T10:20:00.000Z</published><updated>2010-07-25T10:20:55.673Z</updated><title type='text'>Update to ToDoList</title><content type='html'>&lt;p&gt;I have made an update to the ToDoList WPF application I wrote some time ago.&lt;/p&gt;&lt;p&gt;&lt;a href="http://github.com/downloads/Mellen/To-Do-List/ToDo1.2.0.0.zip"&gt;ToDoList version 1.2.0.0&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;Changes:&lt;/h3&gt;&lt;ul&gt;    &lt;li&gt;Created a ViewModel for the To Do List object and To Do List items.&lt;/li&gt;    &lt;li&gt;Setup templates in the MainWindow XAML that display the ViewModel.&lt;/li&gt;    &lt;li&gt;Added in an edit window.&lt;/li&gt;    &lt;li&gt;Added in a context menu for items that allows for editing, deletion and marking as done.&lt;/li&gt;    &lt;li&gt;Added in edit and delete functionality.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I think the final addition will be to allow users to view done items. I'll get around to this at some point :D&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-5409871747974295923?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/5409871747974295923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=5409871747974295923' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/5409871747974295923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/5409871747974295923'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/07/update-to-todolist.html' title='Update to ToDoList'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-2925971436851834182</id><published>2010-05-05T13:47:00.010Z</published><updated>2010-05-05T20:49:50.548Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='memoization'/><title type='text'>Memoizing functions in c++</title><content type='html'>&lt;p&gt;I was thinking about &lt;a href="http://en.wikipedia.org/wiki/Memoization"&gt;memoization&lt;/a&gt;, and how I'd not yet used it. I thought this was a bad thing simply because not using it might lead to me forget about it. So I'm putting together this blog post to help me solidify the concept.&lt;/p&gt;&lt;p&gt;A long while a go I realised a simple fact about square numbers: x² = (x-1)² + (x-1) + x, x ∈ &lt;b&gt;N&lt;/b&gt;. I.e. for any positive integer its square is the square of the previous integer plus the previous integer plus itself. (e.g. 17*17 = 16*16 + 16 + 17)&lt;/p&gt;&lt;p&gt;This is something that is unlikely to be interesting or useful, except that I can use it to demonstrate memoization.&lt;/p&gt;&lt;p&gt;From the above formula you can write a recursive function:&lt;/p&gt;&lt;p class="code"&gt;int square(int n){    if(1 == n)    {        return 1;    }    return (square(n - 1) + (n - 1) + n);}&lt;/p&gt;&lt;p&gt;As you can see this is a very long winded way to get the square of a number, and not a function that would ever be used in reality, but it is a good candidate for memoization.&lt;/p&gt;&lt;p&gt;Memoization in this instance is very easy. Simply add in a static &lt;span class="code"&gt;map&amp;lt;int, int&amp;gt;&lt;/span&gt; and update it for each number you haven't calculated yet:&lt;/p&gt;&lt;p class="code"&gt;int square(int n){ static std::map&amp;lt;int, int&amp;gt; results; if(1==n) {  return 1; } if(0 == results[n]) {  results[n] = square(n-1) + n-1 + n; } return results[n];}&lt;/p&gt;&lt;p&gt;It might be that you'll want to make the &lt;span class="code"&gt;results&lt;/span&gt; variable on the heap with some sort of smart pointer, so that it automatically deletes itself, but other than that this second version should give a performance increase over the original.&lt;/p&gt;&lt;p&gt;I carried out some simple timing tests with &lt;span class="code"&gt;std:clock()&lt;/span&gt;. The programme had to calculate the squares from 1 to 32767 using the memoized and non memoized functions, in a loop:&lt;/p&gt;&lt;div&gt;&lt;span onclick="toggleCode('testCode')" style="color: blue; cursor: pointer; text-decoration: underline;"&gt;toggle test code&lt;/span&gt;&lt;br /&gt;    &lt;p id="testCode" class="hideCode"&gt;#include &amp;lt;map&amp;gt;#include &amp;lt;ostream&amp;gt;#include &amp;lt;ctime&amp;gt;int calcSqr(int);int calcSqrSlow(int);int main(){ clock_t start1 = std::clock(); for(int i = 1; i &lt;= 32767; ++i) {  calcSqrSlow(i); } clock_t start2 = std::clock(); std::cout &amp;lt;&amp;lt; "Ticks taken (slow): " &amp;lt;&amp;lt; start2 - start1 &amp;lt;&amp;lt; std::endl; clock_t start3 = std::clock(); for(int i = 1; i &lt;= 32767; ++i) {  calcSqr(i); } clock_t start4 = std::clock(); std::cout &amp;lt;&amp;lt; "Ticks taken (memo): " &amp;lt;&amp;lt; start4 - start3 &amp;lt;&amp;lt; std::endl; return 0;}int calcSqrSlow(int n){ if(1 == n) {  return 1; }  return (calcSqrSlow(n - 1) + (n - 1) + n);}int calcSqr(int n){ static std::map&amp;lt;int, int&amp;gt; results;  if(1==n) {  return 1; }  if(0 == results[n]) {  results[n] = calcSqr(n-1) + n-1 + n; }  return results[n];}&lt;/p&gt;&lt;/div&gt;&lt;p&gt;Ticks taken for the normal function: 3120&lt;br/&gt;Ticks taken for the memoized function: 78&lt;/p&gt;&lt;p&gt;Obviously this test was biased towards the memoized function, but I really did it to show the potential benefits of memoizing a function where the results can be reused.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-2925971436851834182?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/2925971436851834182/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=2925971436851834182' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/2925971436851834182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/2925971436851834182'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/05/memoizing-functions-in-c.html' title='Memoizing functions in c++'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-4883320005823974797</id><published>2010-03-23T22:59:00.010Z</published><updated>2010-05-05T20:59:35.058Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Drag'/><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Zoom'/><category scheme='http://www.blogger.com/atom/ns#' term='SVG'/><category scheme='http://www.blogger.com/atom/ns#' term='SVGWeb'/><title type='text'>SVG + Javascript drag and zoom</title><content type='html'>Recently I've been working on a project that uses SVG (&lt;a href="http://en.wikipedia.org/wiki/Svg"&gt;Scalable Vector Graphics&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I have been using SVGWeb (&lt;a href="http://code.google.com/p/svgweb/"&gt;http://code.google.com/p/svgweb/&lt;/a&gt;) so that the SVG will work in all the major browsers.&lt;br /&gt;&lt;br /&gt;It is a fantastic library and I am so grateful to the people who work on it.&lt;br /&gt;&lt;br /&gt;The things I found difficult were figuring out how to get zooming with the mouse wheel and dragging to work. I had it working in Firefox, using its native SVG renderer, however SVGWeb does things differently. It took me a while to work out how. I'm going to share what I found here. (Hooking the mouse wheel is actually explained on the SVGWeb mailing list: &lt;a href="http://groups.google.com/group/svg-web/browse_thread/thread/fcc7573769813e0c/329fd28f126f1575?lnk=gst&amp;amp;q=mouse+wheel#329fd28f126f1575"&gt;Mouse  Wheel Events&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;With dragging, I knew I needed to store the old X and Y values of the position of the mouse and take the difference between them and the new mouse position. For some reason setting global variables for the old X and Y values didn't quite work - the delta was very small, approximatley 7.5 times too small.&lt;br /&gt;&lt;br /&gt;With zooming, the SVGWeb library doesn't pick up the mouse wheel event. The way to get around this is to attach the mouse wheel event to the container tag (e.g. &lt;p class="code"&gt;div&lt;/p&gt;) that is surrounding the &lt;p class="code"&gt;object&lt;/p&gt; tag that is holding the SVG on the HTML page.&lt;br /&gt;&lt;br /&gt;On to the code!&lt;br /&gt;&lt;br /&gt;I did not come up with the Javascript - I took it from various places; mostly the SVGWeb mailing list entry above and the "photos" demo that comes with SVGWeb. &lt;br /&gt;&lt;br /&gt;This is the main HTML and Javascript for the page that is holding the SVG:&lt;br /&gt;&lt;br /&gt;&lt;span onclick="toggleCode('mainHTML')" style="color: blue; cursor: pointer; text-decoration: underline;"&gt;toggle code&lt;/span&gt;&lt;br /&gt;&lt;p class="hideCode" id="mainHTML"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;title&amp;gt;SVG Example&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;meta name="svg.render.forceflash" content="true" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;link rel="SHORTCUT ICON" href="favicon.ico" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;body onload="loaded()"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;div id="svgContainer"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;!--[if IE]&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;object id="svgImage" src="example.svg" classid="image/svg+xml" width="100%" height="768px"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;![endif]--&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;!--[if !IE]&amp;gt;--&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;object id="svgImage" data="example.svg" type="image/svg+xml" width="100%" height="768px"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;!--&amp;lt;![endif]--&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/object&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;script type="text/javascript" src="svg/src/svg.js" data-path="svg/src/" &amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;function loaded()&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;hookEvent("svgContainer", "mousewheel", onMouseWheel);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;function hookEvent(element, eventName, callback)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; if(typeof(element) == "string")&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;element = document.getElementById(element);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; if(element == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; if(element.addEventListener)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if(eventName == 'mousewheel')&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; element.addEventListener('DOMMouseScroll', callback, false); &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;element.addEventListener(eventName, callback, false);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; else if(element.attachEvent)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;element.attachEvent("on" + eventName, callback);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;function cancelEvent(e)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;e = e ? e : window.event;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if(e.stopPropagation)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;e.stopPropagation();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if(e.preventDefault)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;e.preventDefault();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;e.cancelBubble = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;e.cancel = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;e.returnValue = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;function onMouseWheel(e)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var doc = document.getElementById("svgImage").contentDocument;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;e = e ? e : window.event;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;doc.defaultView.onMouseWheel(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return cancelEvent(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;This is the SVG and Javascript:&lt;br /&gt;&lt;br /&gt;&lt;span onclick="toggleCode('mainSVG')" style="color: blue; cursor: pointer; text-decoration: underline;"&gt;toggle code&lt;/span&gt;&lt;br /&gt;&lt;p class="hideCode" id="mainSVG"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&amp;gt;&lt;br /&gt;&amp;lt;svg version="1.0" xmlns="http://www.w3.org/2000/svg" onload="loaded()" id="svgMain" &amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;script type="text/javascript" language="javascript"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;![CDATA[&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var isDragging = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var mouseCoords = { x: 0, y: 0 };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var gMain = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function loaded()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var onloadFunc = doload;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (top.svgweb) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; top.svgweb.addOnLoad(onloadFunc, true, window);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; onloadFunc();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function doload()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; hookEvent('mover', 'mousedown', onMouseDown);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; hookEvent('mover', 'mouseup', onMouseUp);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; hookEvent('mover', 'mousemove', onMouseMove);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; hookEvent('mover', 'mouseover', onMouseOver);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; gMain = document.getElementById('gMain');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; gMain.vScale = 1.0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; gMover = document.getElementById('mover');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; gMover.vTranslate = [50,50];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; setupTransform();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function onMouseDown(e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; isDragging = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function onMouseUp(e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; isDragging = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function onMouseOver(e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; mouseCoords = {x: e.clientX, y: e.clientY};&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function onMouseMove(e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(isDragging == true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var g = e.currentTarget;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var pos = g.vTranslate;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var xd = (e.clientX - mouseCoords.x)/gMain.vScale;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var yd = (e.clientY - mouseCoords.y)/gMain.vScale;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; g.vTranslate = [ pos[0] + xd, pos[1] + yd ];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; g.setAttribute("transform", "translate(" + g.vTranslate[0] + "," + g.vTranslate[1] + ")");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; mouseCoords = {x: e.clientX, y: e.clientY};&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return cancelEvent(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function setupTransform() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; gMain.setAttribute("transform", "scale(" + gMain.vScale + "," + gMain.vScale + ")");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function hookEvent(element, eventName, callback)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(typeof(element) == "string")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; element = document.getElementById(element);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(element == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(eventName == 'mousewheel')&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; element.addEventListener('DOMMouseScroll', callback, false); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; element.addEventListener(eventName, callback, false);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function cancelEvent(e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e = e ? e : window.event;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(e.stopPropagation)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e.stopPropagation();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(e.preventDefault)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e.preventDefault();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e.cancelBubble = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e.cancel = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e.returnValue = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; function onMouseWheel(e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e = e ? e : window.event;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var wheelData = e.detail ? e.detail * -1 : e.wheelDelta / 40;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if((gMain.vScale &amp;gt; 0.1) || (wheelData &amp;gt; 0))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; gMain.vScale += (0.02 * wheelData);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; setupTransform();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return cancelEvent(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ]]&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/script&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g id="gMain"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;g transform="translate(50,50)" id="mover"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;circle stroke-width="2" stroke="black" cx="0" cy="0"&amp;nbsp; r="20" fill="red"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;text font-family="verdana" text-anchor="middle" transform="translate(0,40)" fill="black" stroke-width="1" font-size="12" &amp;gt;Drag me!&amp;lt;/text&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/g&amp;gt;&lt;br /&gt;&amp;lt;/svg&amp;gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;There is some overlap in the Javascript presented there, this is just to keep things simple if you're copy/pasting this to test for your self.&lt;br /&gt;&lt;br /&gt;This Javascript in the main file passes the mouse wheel event info to the SVG document:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;function onMouseWheel(e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; var doc = document.getElementById("svgImage").contentDocument;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; e = e ? e : window.event;&lt;br /&gt;&amp;nbsp;&amp;nbsp; doc.defaultView.onMouseWheel(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp; return cancelEvent(e);&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br/&gt;The rest of the important Javascript is in the SVG document.&lt;br/&gt;&lt;br /&gt;To get dragging to work, first define a global object to hold position information:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;var mouseCoords = { x: 0, y: 0 };&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;When the mouse moves over the desired element, update the object:&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;function onMouseOver(e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mouseCoords = {x: e.clientX, y: e.clientY};&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;There also needs to be a global boolean to switch dragging on and off. I called mine &lt;p class="code"&gt;isDragging&lt;/p&gt;. Toggle dragging when the mouse is up or down on the element.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;function onMouseDown(e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; isDragging = true;&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;function onMouseUp(e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; isDragging = false;&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;When moving the mouse with dragging on, change the position of the element and update the object. Notice that the delta is being divided by the scale. This prevents the movement from becoming erratic.&lt;br /&gt;&lt;br /&gt;&lt;p class="code"&gt;function onMouseMove(e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;if(isDragging == true)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var g = e.currentTarget;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var pos = g.vTranslate;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var xd = (e.clientX - mouseCoords.x)/gMain.vScale;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;var yd = (e.clientY - mouseCoords.y)/gMain.vScale;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;g.vTranslate = [ pos[0] + xd, pos[1] + yd ];&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;g.setAttribute("transform", "translate(" + g.vTranslate[0] + "," + g.vTranslate[1] + ")");&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;mouseCoords = {x: e.clientX, y: e.clientY};&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return cancelEvent(e);&lt;br /&gt;}&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;And that's how it works.&lt;br /&gt;&lt;br /&gt;Here is the example working: &lt;a href="http://www.matthewellen.co.uk/SVGExample.html"&gt;http://www.matthewellen.co.uk/SVGExample.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-4883320005823974797?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/4883320005823974797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=4883320005823974797' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/4883320005823974797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/4883320005823974797'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/03/svg-javascript-drag-and-zoom.html' title='SVG + Javascript drag and zoom'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-542090654241068421</id><published>2010-03-05T12:52:00.002Z</published><updated>2012-01-17T10:31:55.447Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='pomodoro'/><category scheme='http://www.blogger.com/atom/ns#' term='github'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>Pomodoro!</title><content type='html'>I've been feverishly subscribing to blogs recently after I realised I'm only really reading channel9.&lt;br /&gt;&lt;br /&gt;I've got so much reading to do it's unreal. I've got through about 50 .NET posts so far and I've got 50 more to go, before I'm caught up. I've also got about 50 PHP posts to read too.&lt;br /&gt;&lt;br /&gt;In my .NET blogs I came across this entry: &lt;a href="http://www.developingfor.net/productivity/you-say-tomato-i-say-pomodoro.html"&gt;You say tomato i say pomodoro&lt;/a&gt; at the developing for .NET blog. The post outlines a simple way to help manage your time effectively. It has inspired me to create a little timer app and a todo list app.&lt;br /&gt;&lt;br /&gt;The timer app is really simple: it's a picture of a tomato with a button on it that minimises the app to the notification area and sets a timeout period. Once the period is reached (the length is set in the config file) then the app pops back up and plays a sound at you. I've put the code over at GitHub: &lt;a href="http://github.com/Mellen/Pomodoro"&gt;code for Pomodoro timer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The todo list app is equally simple, just a list view and list item entry controls. On close it writes to a file. The source is also at GitHub: &lt;a href="http://github.com/Mellen/To-Do-List"&gt;code for To Do List&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;update&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I've uploaded the binaries for each, so you don't have to compile them!&lt;b&gt; &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://github.com/downloads/Mellen/To-Do-List/ToDoList.zip"&gt;To Do List executable&lt;/a&gt;&lt;br /&gt;&lt;a href="http://github.com/downloads/Mellen/Pomodoro/Pomodoro.zip"&gt;Pomodoro executable&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-542090654241068421?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/542090654241068421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=542090654241068421' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/542090654241068421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/542090654241068421'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/03/pomodoro.html' title='Pomodoro!'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-649442734948140497</id><published>2010-02-09T21:44:00.013Z</published><updated>2010-05-05T20:48:30.146Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='foldl'/><category scheme='http://www.blogger.com/atom/ns#' term='programming in haskell'/><title type='text'>dec2int and foldl</title><content type='html'>&lt;p&gt;So, I'm trying to learn Haskell (as well as about functional programming) and I have a book I'm using: &lt;a href="http://www.cambridge.org/uk/catalogue/catalogue.asp?isbn=9780521692694"&gt;Programming in Haskell&lt;/a&gt; by &lt;a href="http://www.cs.nott.ac.uk/~gmh/"&gt;Graham Hutton&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;At the end of each chapter there are exercises.&lt;/p&gt;&lt;p&gt;Chapter 7 is about &lt;a href="http://en.wikipedia.org/wiki/Higher-order_function"&gt;higher-order functions&lt;/a&gt; and one of the exercises is to create a function &lt;span class="code"&gt;dec2int&lt;/span&gt; which is of the type &lt;span class="code"&gt;dec2int :: [Int] -&gt; Int&lt;/span&gt; and takes a list of decimal numbers (i.e. numbers 0 to 9); so given the input &lt;span class="code"&gt;[1,2,5,7]&lt;/span&gt; &lt;span class="code"&gt;dec2int&lt;/span&gt; would output &lt;span class="code"&gt;1257&lt;/span&gt;. The other stipulation is that the function must use &lt;span class="code"&gt;foldl&lt;/span&gt;.&lt;/p&gt;&lt;h2&gt;Step 1 &lt;span style="font-size:smaller"&gt;- define dec2int recursively&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;My first thought in solving this problem was that I wanted to have a working &lt;span class="code"&gt;dec2int&lt;/span&gt; function.&lt;/p&gt;&lt;p class="code"&gt;dec2int [] = 0dec2int (x:xs) = x*10^(length xs) + dec2int xs&lt;/p&gt;Not very efficient, obviously, as it has to call length for each call to the function, but it works and gives a general idea as to how to write the function.&lt;h2&gt;Step 2 &lt;span style="font-size:smaller"&gt;- define dec2int to the letter but not the spirit of the problem&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;I spent quite some time trying to understand &lt;span class="code"&gt;foldl&lt;/span&gt; as it's described in the book. &lt;span class="code"&gt;foldl&lt;/span&gt;'s type is &lt;span class="code"&gt;foldl :: (a-&gt;b-&gt;a)-&gt;a-&gt;[b]-&gt;a&lt;/span&gt;. A recursive definition looks like this (taken from the book)&lt;/p&gt;&lt;p class="code"&gt;foldl f v [] = vfoldl f v (x:xs) = foldl f(f v x) xs&lt;/p&gt;&lt;p&gt;So the function &lt;span class="code"&gt;f&lt;/span&gt; that's passed into &lt;span class="code"&gt;foldl&lt;/span&gt; has to take a default value, a current value, and return a value that can be used in the function in place of the default value.&lt;/p&gt;&lt;p&gt;My first successful attempt at this does not seem to me to be in keeping with the spirit of the problem:&lt;/p&gt;&lt;p class="code"&gt;xANDpos :: [a] -&gt; [(a,Int)]xANDpos [] = []xANDpos (x:xs) = (x,len):xNp len xs               where len = length xs                     xNp _ [] = []                     xNp (pos + 1) (x:xs) = (x,pos):xNp pos xsdec2int :: [Int] -&gt; Intdec2int xs = foldl dec2int' 0 (xANDpos xs)           where dec2int' n (x,pow) = n + x*10^pow&lt;/p&gt;&lt;p&gt;&lt;span class="code"&gt;f&lt;/span&gt; in this instance is &lt;span class="code"&gt;dec2int'&lt;/span&gt;. &lt;span class="code"&gt;xANDpos&lt;/span&gt; is a function that takes a list of something and returns a list of tuples of something and its position in the list, if the list were reversed. Not the best name for the function.&lt;/p&gt;&lt;p&gt;I don't think this is in the spirit of the problem because, while it does accomplish the goal, it adds an extra section of recursion when recursion is meant to be being handled by foldl.&lt;/p&gt;&lt;h2&gt;Step 3 &lt;span style="font-size:smaller"&gt;- this time with spirit&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;It took some time, but I finally realised that my first function wasn't the only way to get to the answer. The final version is a lot simpler than the second, and therefore more beautiful.&lt;/p&gt;&lt;p class="code"&gt;dec2int :: [Integer] -&gt; Integerdec2int = foldl d2i 0        where d2i n x = n*10 + x&lt;/p&gt;&lt;p&gt;This is also a lot quicker - it doesn't traverse the list multiple times. As you can see, I've changed the type of the function, slightly, to allow for bigger numbers to be produced.&lt;/p&gt;&lt;p&gt;Here is a worked example of how the function functions:&lt;/p&gt;&lt;p class="code"&gt;dec2int [3,7,0,4,2] = foldl d2i 0 [3,7,0,4,2]= foldl d2i(d2i 0 3 = 0*10 + 3) [7,0,4,2]= foldl d2i(d2i 3 7 = 3*10 + 7) [0,4,2]= foldl d2i(d2i 37 0 = 37*10 + 0) [4,2]= foldl d2i(d2i 370 4 = 370*10 + 4) [2]= foldl d2i(d2i 3704 2 = 3704*10 + 2) []= foldl d2i 37042 []= 37042&lt;/p&gt;&lt;p&gt;The function can also be written as a one liner, using lambda: &lt;span class="code"&gt;dec2int = foldl(\n x -&gt; n * 10 + x) 0&lt;/span&gt; however I think the other version is more readable.&lt;/p&gt;&lt;p&gt;The problem I encountered here was that my first assumption was incorrect, i.e. the function I came up with in step 1 was not the only way to solve the problem using recursion.&lt;/p&gt;&lt;p&gt;Lesson learned!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-649442734948140497?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/649442734948140497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=649442734948140497' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/649442734948140497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/649442734948140497'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2010/02/dec2int-and-foldl.html' title='dec2int and foldl'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-2498151453454667638</id><published>2009-11-06T11:12:00.002Z</published><updated>2009-11-06T11:13:36.162Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='failure'/><title type='text'>Neural Network failure</title><content type='html'>I have deleted the posts regarding the neural network class as the class didn't work - I couldn't solve the XOR problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-2498151453454667638?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/2498151453454667638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=2498151453454667638' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/2498151453454667638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/2498151453454667638'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2009/11/neural-network-failure.html' title='Neural Network failure'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-8832448418057869008</id><published>2008-05-13T18:42:00.008Z</published><updated>2010-02-10T11:22:30.365Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='firewall'/><category scheme='http://www.blogger.com/atom/ns#' term='antivirus'/><category scheme='http://www.blogger.com/atom/ns#' term='adaptive protection'/><category scheme='http://www.blogger.com/atom/ns#' term='peer to peer'/><title type='text'>Adaptive Protection</title><content type='html'>One thing that has fascinated me for the last few years has been the thought that instead of these centralised, hub like antivirus (and anti-malware, anti-spyware, etc.) systems and firewalls that work on a per computer/network basis, we could have an adaptive peer to peer system.&lt;br /&gt;&lt;br /&gt;At this point in time I think there are three major uses for the internet. Number one is business, number two is socialising and number three is sharing data. Although I suppose three encapsulates both one and two.&lt;br /&gt;&lt;br /&gt;The only downsides to the internet are crime and government. I'm not about to try and fix governance of the internet except to say that peer to peer trumps centralised control, and I'll hopefully convince you of that in this blog, if not this post.&lt;br /&gt;&lt;br /&gt;There are two types of crime on the internet; mostly on the web and in email, but they also feature in other applications. The first is digital crime like trojans, spyware, etc. The second type is confidence tricks, like when on ebay someone sells you a DVD allegedly signed by Ron Jeremy and it's just a blank DVD with a squiggle on it, and there's nothing to prove it is what it is. The latter type of crime is rife in a walks of life. Digital crime, however, can only happen on computers.&lt;br /&gt;&lt;br /&gt;So now we get to the point of my post: adaptive protection from digital crime.&lt;br /&gt;&lt;br /&gt;Our current model for protection is one where we install some software, be it a firewall, script blocker, antivirus programme or whatever and allow it to run. Every so often the software will call home, either automatically, or because we tell it too, and it will update how it works. This is what we do and it means that we are always one step behind the attackers.&lt;br /&gt;&lt;br /&gt;Let me throw some crazy, metaphorical idealism at you.&lt;br /&gt;&lt;br /&gt;The internet is like fertiliser. It's not a living thing its self, it doesn't change as such. Its purpose is always to be the place where ideas can grow and evolve. The applications of the internet: bit torrent, web, ftp, usenet, gopher, finger, etc., are all lifeforms that evolve, or become endangered or extinct (to over extend the metaphor). Essentially we (users) behave like seed carriers; we increase the population of an application by spreading it around, getting others to use it, a lot like corn or carrots.&lt;br /&gt;&lt;br /&gt;The other applications, the ones that are less than favourable for most users, are also able to flourish in this fertiliser. Like weeds, I suppose, or maybe bacteria or fungi. So like sensible farmers we deploy pesticides to kill them off, which work fine until they evolve and we have to make a better pesticide, and so on and so on.&lt;br /&gt;&lt;br /&gt;We have one advantage over bio-technologists, though. If we start doing mad scientist type experiments to try and create programmes that can behave in a way that is adaptive and can help wipe out the undesirable programmes, we can't cause ecological disaster, like DDT or engineering resistant plants might.&lt;br /&gt;&lt;br /&gt;My basic premise is that the best way to beat the viruses et al. is through co-operation and on the fly adaptation, via implementing a new internet application. Rather than an application that considers the internet as a place to guard against, create an internet application that wants to defend its turf.&lt;br /&gt;&lt;br /&gt;It would have to be an application that runs in the background of your computer, and is able to understand what should be happening and what shouldn't, and how to prevent these things. Once recognition of a problem takes place and action is taken then the programme would need to propagate that information to neighbours to help them identify similar problems.&lt;br /&gt;&lt;br /&gt;You cannot define all the rules up front. You can, however, define how to define rules, and let evolution take its course. This is one area I think that evolutionary computing will excel in. It is perfectly suited to coming up with solutions that involve iterative design over many generations.&lt;br /&gt;&lt;br /&gt;I haven't done enough reading around operating systems to be able to implement such a system, but the idea is most intriguing. I also haven't read around in the adaptive protection literature, so I don't know how far along this research is. It is definitely something I will be getting involved in.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-8832448418057869008?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/8832448418057869008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=8832448418057869008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/8832448418057869008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/8832448418057869008'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2008/05/adaptive-protection.html' title='Adaptive Protection'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-2662428172276102363</id><published>2007-12-15T12:19:00.000Z</published><updated>2007-12-15T12:25:53.380Z</updated><title type='text'></title><content type='html'>It seems I'm not very good at keeping on track.&lt;br /&gt;&lt;br /&gt;I keep getting distracted by things and don't do enough work on my AI stuff.&lt;br /&gt;&lt;br /&gt;It's not that I haven't done any work, but I've started a new project and I haven't progressed at all on the mini project. This is partly due to not having unpacked my Linux box after moving house, but also because my social life has improved after moving.&lt;br /&gt;&lt;br /&gt;The new project isn't getting much work done on it either, but I don't want to discuss it yet, as it in the really really early stages. It's currently being developed on Windows XP, but it should be easy enough to port it to Linux when the time comes.&lt;br /&gt;&lt;br /&gt;Merry Christmas to anyone reading this!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-2662428172276102363?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/2662428172276102363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=2662428172276102363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/2662428172276102363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/2662428172276102363'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2007/12/it-seems-im-not-very-good-at-keeping-on.html' title=''/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-2058313868996051522</id><published>2007-08-01T22:38:00.000Z</published><updated>2007-08-01T22:43:13.605Z</updated><title type='text'>Minor Update</title><content type='html'>It's been a lot longer than I had planed since my last post.&lt;br /&gt;&lt;br /&gt;I have made steps towards a neural network for solving sudoku, but I hit a snag when I came to generating test sudoku on the fly, then I got distracted with other AI research I'm doing and updating my website and stuff going on in my non-digital life.&lt;br /&gt;&lt;br /&gt;I haven't got beyond my snag, so I have no real update, other than to say I have created a simple class for single layer neural networks&lt;br /&gt;&lt;br /&gt;My other AI research has lead me to investigate Information Theory. I'm finding it very complicated so far, not having a degree in mathematics, but I'm sure I'll figure it out in time.&lt;br /&gt;&lt;br /&gt;For now, you'll have to wait, while I decide if I should use canned sudoku grids or work to finish my generator.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-2058313868996051522?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/2058313868996051522/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=2058313868996051522' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/2058313868996051522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/2058313868996051522'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2007/08/minor-update.html' title='Minor Update'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-7694903420177824051</id><published>2007-04-09T20:12:00.000Z</published><updated>2007-04-09T20:20:11.840Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Sudoku'/><category scheme='http://www.blogger.com/atom/ns#' term='Neural Networks'/><title type='text'>New Mini Project</title><content type='html'>It's been a long while since I've been motivated to do any development.&lt;br /&gt;&lt;br /&gt;I've finally come up with a small enough project that I should be able to do over a few weeks.&lt;br /&gt;&lt;br /&gt;My main project: finishing the robot football AI, will be put on hold while I get back into the swing of C++ and Linux (slackware).&lt;br /&gt;&lt;br /&gt;This mini project is a very simple neural network that will be limited to two layers (no need for complex learning algorithms). I will train the network to recognise sudoku puzzles, and hopefully I'll be able to get it to fill in novel puzzles.&lt;br /&gt;&lt;br /&gt;The network code will be a lot simpler than the code I used for my Masters' thesis, with two one dimensional arrays of doubles for the input and output, and a single two dimensional array of doubles for the connections.&lt;br /&gt;&lt;br /&gt;I'll post the code as bits get completed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-7694903420177824051?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/7694903420177824051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=7694903420177824051' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/7694903420177824051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/7694903420177824051'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2007/04/new-mini-project.html' title='New Mini Project'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-116147143464576766</id><published>2006-10-21T22:55:00.001Z</published><updated>2011-05-07T22:13:39.776Z</updated><title type='text'>3D thing source</title><content type='html'>OK! the source can be found at &lt;a href="http://www.matthewellen.co.uk/index.php?page_name=portfolioitem&amp;amp;item=dynamicmotion"&gt;http://www.matthewellen.co.uk/index.php?page_name=portfolioitem&amp;amp;item=dynamicmotion&lt;/a&gt;&lt;a href="http://www.matthewellen.co.uk/portfolio/dynamicmotion.xml"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-116147143464576766?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/116147143464576766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=116147143464576766' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/116147143464576766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/116147143464576766'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2006/10/3d-thing-source.html' title='3D thing source'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-116146943783751688</id><published>2006-10-21T22:17:00.000Z</published><updated>2006-11-07T21:48:32.639Z</updated><title type='text'>Unveiling</title><content type='html'>Ok! It's done.&lt;br /&gt;&lt;br /&gt;It's not quite how I said it would be. There are no collisions, but everything else is there. All the nodes have the same mass, so there was no need to include that in the model.&lt;br /&gt;&lt;br /&gt;To download the finished product goto &lt;a href="http://www.geocities.com/griffle_the_waffle/ppi/"&gt;http://www.geocities.com/griffle_the_waffle/ppi&lt;/a&gt; and click on the products link in the left hand menu. The first product is the one you want, although you might want to try out the others too.&lt;br /&gt;&lt;br /&gt;I'll post links to the source in a bit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-116146943783751688?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/116146943783751688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=116146943783751688' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/116146943783751688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/116146943783751688'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2006/10/unveiling.html' title='Unveiling'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-116081582804669873</id><published>2006-10-14T08:43:00.000Z</published><updated>2006-11-07T21:49:06.179Z</updated><title type='text'>Warm up exercises</title><content type='html'>&lt;p&gt;Right, today I'm going to start a simpler project:&lt;br /&gt;&lt;br /&gt;I'm going to try to make an l-system style programme, but without any branches. Also each node will be of a certain type, that will be attracted to one type and repel its self from another. The attraction/repulsion will cause acceleration based on the mass of the nodes.&lt;/p&gt;The nodes will be able to collide with eachother, and will also be enclosed within  a cube, so they will bounce of the sides of that too.&lt;br /&gt;&lt;p&gt;The l-system part will be how I control the number of nodes - each type will beget two of two other types. You will be able to increase and decrease the number of nodes as whole layers, in a binary way i.e. 1, +2, +4, +8, etc.&lt;/p&gt;I know I'm meant to be making AI software, but this idea excites me more than thoroughly designing a neural network designer.&lt;br /&gt;&lt;p&gt;The idea struck me after conversing with &lt;a href="http://x00021665.blogspot.com/"&gt;Baz&lt;/a&gt; of &lt;a href="http://www.elitebastards.com/"&gt;Elitebastards&lt;/a&gt; fame. He introduced me to an l-system that used repelling to form its shape. It looked pretty cool, so much so I wanted to do something like it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-116081582804669873?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/116081582804669873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=116081582804669873' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/116081582804669873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/116081582804669873'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2006/10/warm-up-exercises.html' title='Warm up exercises'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-34763567.post-115895855854155966</id><published>2006-09-22T20:09:00.000Z</published><updated>2006-10-21T22:53:24.840Z</updated><title type='text'>Starting afresh</title><content type='html'>&lt;b&gt;Post 1: the least important post.&lt;/b&gt;&lt;br/&gt;&lt;br/&gt;This is the start of my blog. I'm creating a blog about developing AI software. If you have no interest in AI software, or me, turn back now. This will only make you turn blind.&lt;br/&gt;&lt;br/&gt;Since this is the first post, I will tell you what I shall be developing first: An Artificial Neural Network Designer.&lt;br/&gt;&lt;br/&gt;I have already taken the first steps, I have decided what it will be able to do:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Load a network&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Save/save as&lt;/li&gt;&lt;li&gt;Create a new network&lt;/li&gt;&lt;li&gt;Add a neuron&lt;/li&gt;&lt;li&gt;Remove a neuron&lt;/li&gt;&lt;li&gt;Edit neuron properties&lt;/li&gt;&lt;li&gt;Add a neuron group&lt;/li&gt;&lt;li&gt;Remove a neuron group&lt;/li&gt;&lt;li&gt;Edit group properties&lt;/li&gt;&lt;li&gt;Add a neuron to a group&lt;/li&gt;&lt;li&gt;Remove a neuron from a group&lt;/li&gt;&lt;li&gt;Add connections: N-&gt;N, N-&gt;G, G-&gt;N, G-&gt;G&lt;/li&gt;&lt;li&gt;Removing connections&lt;/li&gt;&lt;li&gt;Create activation functions (AFs)&lt;/li&gt;&lt;li&gt;Edit AF properties&lt;/li&gt;&lt;li&gt;Remove AFs&lt;/li&gt;&lt;li&gt;Set network bias&lt;/li&gt;&lt;/ul&gt;&lt;font&gt;And since I want to get things right this time, I'm going full force with UML.&lt;br/&gt;&lt;br/&gt;Anyway, wish me luck.&lt;br/&gt;&lt;/font&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34763567-115895855854155966?l=mojoai.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mojoai.blogspot.com/feeds/115895855854155966/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=34763567&amp;postID=115895855854155966' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/115895855854155966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/34763567/posts/default/115895855854155966'/><link rel='alternate' type='text/html' href='http://mojoai.blogspot.com/2006/09/starting-afresh.html' title='Starting afresh'/><author><name>Mojo</name><uri>http://www.blogger.com/profile/11704648978910126233</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
