Friday, October 31, 2008

Dynamic tag cloud in silverlight

Trying to build a tag cloud in Silverlight that represents co-occurance as well, heres my first cut:






The code reads my RSS feed and looks at the labels - this should work for any blog..
trying dragging for fun! I'll post the code once I've mad a few more enhancements (and checked my math!)

Thursday, October 30, 2008

Embedding Silverlight in blogger

A post to test embedding of Silverlight applications into blogger






which was achieved by adding to my blogger html template:
<script type="text/javascript" src="http://www.figmentengine.com/assets/script/silverlight.js" ></script>

and then each time I want to embed Silverlight in a post, a holder for the control:
<div id="simplekineticsHost" style="text-align: center;"><object data="data:application/x-silverlight-2," type="application/x-silverlight-2"></object></div>

and some javascript to control the silverlight settings:
<script type="text/javascript">  var host = "http://www.figmentengine.com/";  var source = host + "silverlight/kinetics/simplekinetics.xap";  var parentElement = document.getElementById("simplekineticsHost");  var callbackId = "simplekineticsHost2";  var properties = { width: "500", height: "350", version: "2.0.31005.0"};  var events = {};  Silverlight.createObject(source, parentElement,   callbackId, properties, events);</script>

this was based on this article, with a minor update for the release of silverlight 2.

Wednesday, October 29, 2008

Markov chain code

A follow up to my markov chain posts, here's the code for a generic markov chain in C#:

A markov chain:

/// <summary>
/// Chain implements a markov chain for a type T
/// allows the generation of sequences based on
/// a sample set of T items
/// </summary>
/// <typeparam name="T">the type of elements</typeparam>
public class Chain<T>
{
Link<T> root = new Link<T>(default(T));
int length;

/// <summary>
/// creates a new chain
/// </summary>
/// <param name="input">Sample set</param>
/// <param name="length">window size for sequences</param>
public Chain(IEnumerable<T> input, int length)
{
this.length = length;
root.Process(input, length);
}

/// <summary>
/// generate a new sequence based on the samples first entry
/// </summary>
/// <param name="max">maximum size of result</param>
/// <returns></returns>
public IEnumerable<T> Generate(int max)
{
foreach (Link<T> next in root.Generate(root.SelectRandomLink().Data, length, max))
yield return next.Data;
}

/// <summary>
/// generate a new sequence based on the sample
/// </summary>
/// <param name="start">the item to start with</param>
/// <param name="max">maximum size of result</param>
/// <returns></returns>
public IEnumerable<T> Generate(T start, int max)
{
foreach (Link<T> next in root.Generate(start, length, max))
yield return next.Data;
}
}


consists of links:

/// <summary>
/// parts of a chain (markcov)
/// </summary>
/// <typeparam name="T">link type</typeparam>
internal class Link<T>
{
T data;
int count;
// following links
Dictionary<T, Link<T>> links;

private Link()
{
}

/// <summary>
/// create a new link
/// </summary>
/// <param name="data">value of the item in sequence</param>
internal Link(T data)
{
this.data = data;
this.count = 0;

links = new Dictionary<T, Link<T>>();
}

/// <summary>
/// process the input in window sized chunks
/// </summary>
/// <param name="input">the sample set</param>
/// <param name="length">size of sequence window</param>
public void Process(IEnumerable<T> input, int length)
{
// holds the current window
Queue<T> window = new Queue<T>(length);

// process the input, a window at a time (overlapping)
foreach (T part in input)
{
if (window.Count == length)
window.Dequeue();
window.Enqueue(part);

ProcessWindow(window);
}
}

/// <summary>
/// process the window to construct the chain
/// </summary>
/// <param name="window"></param>
private void ProcessWindow(Queue<T> window)
{
Link<T> link = this;

foreach (T part in window)
link = link.Process(part);
}

/// <summary>
/// process an item following us
/// keep track of how many times
/// we are followed by each item
/// </summary>
/// <param name="part"></param>
/// <returns></returns>
internal Link<T> Process(T part)
{
Link<T> link = Find(part);

// not been followed by this
// item before
if (link == null)
{
link = new Link<T>(part);
links.Add(part, link);
}

link.Seen();

return link;
}

private void Seen()
{
count++;
}

public T Data
{
get
{
return data;
}
}

public int Occurances
{
get
{
return count;
}
}

/// <summary>
/// Total number of incidences after this link
/// </summary>
public int ChildOccurances
{
get
{
// sum all followers occurances
int result = links.Sum(link => link.Value.Occurances);

return result;
}
}

public override string ToString()
{
return String.Format("{0} ({1})", data, count);
}

/// <summary>
/// find a follower of this link
/// </summary>
/// <param name="start">item to be found</param>
/// <returns></returns>
internal Link<T> Find(T follower)
{
Link<T> link = null;

if (links.ContainsKey(follower))
link = links[follower];

return link;
}

static Random rand = new Random();
/// <summary>
/// select a random follower weighted
/// towards followers that followed us
/// more often in the sample set
/// </summary>
/// <returns></returns>
public Link<T> SelectRandomLink()
{
Link<T> link = null;

int universe = this.ChildOccurances;

// select a random probability
int rnd = rand.Next(1, universe+1);

// match the probability by treating
// the followers as bands of probability
int total = 0;
foreach (Link<T> child in links.Values)
{
total += child.Occurances;

if (total >= rnd)
{
link = child;
break;
}
}

return link;
}

/// <summary>
/// find a window of followers that
/// are after this link, returns where
/// the last link if found, or null if
/// this window never occured after this link
/// </summary>
/// <param name="window">the sequence to look for</param>
/// <returns></returns>
private Link<T> Find(Queue<T> window)
{
Link<T> link = this;

foreach (T part in window)
{
link = link.Find(part);

if (link == null)
break;
}

return link;
}

/// <summary>
/// a generated set of followers based
/// on the likelyhood of sequence steps
/// seen in the sample data
/// </summary>
/// <param name="start">a seed value to start the sequence with</param>
/// <param name="length">how bug a window to use for sequence steps</param>
/// <param name="max">maximum size of the set produced</param>
/// <returns></returns>
internal IEnumerable<Link<T>> Generate(T start, int length, int max)
{
var window = new Queue<T>(length);

window.Enqueue(start);

for (Link<T> link = Find(window); link != null && max != 0; link = Find(window), max--)
{
var next = link.SelectRandomLink();

yield return link;

if (window.Count == length-1)
window.Dequeue();
if (next != null)
window.Enqueue(next.Data);
}
}
}


which can be called:

static void Main(string[] args)
{
// sample data set
string seed = Tidy(@"Twinkle, twinkle, little star,
How I wonder what you are!
Up above the world so high,
Like a diamond in the sky!

When the blazing sun is gone,
When he nothing shines upon,
Then you show your little light,
Twinkle, twinkle, all the night.

Then the traveller in the dark,
Thanks you for your tiny spark,
He could not see which way to go,
If you did not twinkle so.

In the dark blue sky you keep,
And often through my curtains peep,
For you never shut your eye,
Till the sun is in the sky.

As your bright and tiny spark,
Lights the traveller in the dark,—
Though I know not what you are,
Twinkle, twinkle, little star.
");

// tokenise the input string
var seedList = new List<string>(Split(seed.ToLower()));
// create a chain with a window size of 4
var chain = new Chain<string>(seedList, 4);

// generate a new sequence using a starting word, and maximum return size
var generated = new List<string>(chain.Generate("twinkle", 2000));
// output the results to the console
generated.ForEach(item => Console.Write("{0}", item));
}

// tokenise a string into words (regex definition of word)
private static IEnumerable<string> Split(string subject)
{
List<string> tokens = new List<string>();
Regex regex = new Regex(@"(\W+)");
tokens.AddRange(regex.Split(subject));

return tokens;
}


Giving output such as:
twinkle, little star,
how i know not twinkle so.

in the sky.

as your tiny spark,
lights the sky!

when the night.

then the traveller in the dark blue sky you never shut your eye,
till the sky.

as your eye,
till the sun is gone,
when he nothing shines upon,
then you are!
up above the dark,
thanks you did not what you are,
twinkle, twinkle, all the sky!


One of the interesting side-effects of tokenizing using a simple regex is that if the input stream is HTML the Markov chain will treat HTML as words as well and therefore not only generate text that looks like the input, but is also formatted like the input - this also works for punctuation.

Programming Books

Trying to build a database of my books, so I cheated and started to compile them using Amazon. Mostly programming books at the moment.



I'll add some more when I get a chance - any recomendations welcome!

Saturday, October 25, 2008

Rotating a string

Code snippet to rotate a string:


static void Main(string[] args)
{
string subject = "abcdefg";

// test harness, check it handles multiples of size and negatives and zero
for (int amount = -subject.Length * 3; amount < subject.Length * 3; amount++)
{
string result = RotateStringTest(subject, amount);

char[] inplace = subject.ToCharArray();

RotateString(inplace, amount);

if (amount % subject.Length == 0)
Debug.Assert(result.CompareTo(subject) == 0);
Debug.Assert(result.CompareTo(new String(inplace)) == 0);
}
}

/// <summary>
/// Rotates a string
/// </summary>
/// <param name="subject">string to rotate</param>
/// <param name="amount">&lt; 0 left, 0 none, &gt; 0 right</param>
/// <returns></returns>
private static void RotateString(char[] subject, int amount)
{
int length = subject.Length;

// negate rotations can be re-expressed as positive amounts
if (amount < 0)
amount = length - (-amount % length);

// 0 rotation mean return unchanged
if (amount % length == 0)
return;

int dest = amount;
char prev = subject[0];

do
{
dest %= length;

Swap(ref subject[dest], ref prev);

dest += amount;
} while (dest != amount);
}

/// <summary>
/// swaps two chars wihout using temp variable
/// </summary>
private static void Swap(ref char a, ref char b)
{
a ^= b;
b ^= a;
a ^= b;
}

/// <summary>
/// Rotates a string test (slow)
/// </summary>
/// <param name="subject">string to rotate</param>
/// <param name="amount">&lt; 0 left, 0 none, &gt; 0 right</param>
/// <returns></returns>
private static string RotateStringTest(string subject, int amount)
{
char[] result = subject.ToCharArray();
int length = subject.Length;

// negate rotations can be re-expressed as positive amounts
if (amount < 0)
amount = length - (-amount % length);

// 0 rotation mean return unchanged
if (amount % length != 0)
{
for (int pos = 0; pos < length; pos++)
{
int dest = (pos + amount) % length;

result[dest] = subject[pos];
}
}

return new String(result);
}


ps this post was really just to test this javascript code hightlighter.. It seems to work very well for both Xaml and C# - cool!

Friday, October 24, 2008

Pentasolve: a problem solving approach.

I'm adopting a new technique today, Pentasolve: a problem solving approach.

Principally this means when faced with a [technical] questions I will attempt to generate five candidate answers.

I will then select the best answer. I'm doing this for a number of reasons:
  • Creativity: It will force me to consider more left-field solutions.
  • Peer pressure: It will allow any "obvious" solutions to have peers that it can be evaluated against.
  • Maturation: This process will give ideas more time to evolve before I fix on one.

Why five? no scientific answer to this - three seems too small (I can always think of three, five forces me to think). More than five seems to be overkill.

I'm about to attempt a relatively complex product development, so I will see if this technique helps or not.

PentasolveTM - solving your problems 5 steps at a time ;-)

Wednesday, October 22, 2008

Silverlight Eyes (Seyes) : eyes follow the mouse in Silverlight (aka xeyes)

Silverlight Eyes (Seyes) watches what you do and reports it to the Boss:

Silverligh Eyes

This code uses two main mechanism to achieve the effect


  1. It uses Polar coordinates to calculate where the focal point is relative to the centre of each eyeball. (Often the problem people look for as finding the angle between two points). The code uses the angle to calculate what direction the pupil should be facing, and uses the radius (or distance) to proportionally move the pupil away from the centre.

  2. It uses clipping to ensure that the pupil is always within the eye ball, which is accomplished by grouping the shapes into a canvas with a clipping region the same size of the eyeball.

The code also allows the user to visualize the calculations taking place by checking/unchecking the checkbox in the top left hand corner. Checking this shows the focal point, the lines of sight from each eye and the key values at the top (angle, distance, start point, end point)



There are a number of implementations of eye movement on the web, however a lot of them do not proportionally move the pupil away from the centre, this means the pupil in these animations are generally stuck at the edge of the eye. If you play with the application you will see that a proportional movement is more realistic - human brains are very good at calculating what other people are looking at based on the pupil positions.



Clipping can be seen in this picture:
Clipping

The Xaml is as expected with the complication of grouping the parts of the eye together using a Canvas, with a Canvas.Clip to stop drawing outside of the eyeball:
<UserControl x:Class="Eyes.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Canvas x:Name="LayoutRoot" Background="White" MouseMove="LayoutRoot_MouseMove" Cursor="Arrow">
<TextBlock Name="TextDebug" Canvas.Left="10" Canvas.Top="0" Width="1000" Height="100" />
<CheckBox Name="ShowCalculation" Canvas.Left="0" Canvas.Top="0"
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed" Canvas.ZIndex="7"
Cursor="Arrow"/>

<Ellipse Canvas.Left="300" Canvas.Top="100" Width="230" Height="300" Stroke="Black" Name="Face" Fill="WhiteSmoke" Canvas.ZIndex="1"/>

<Canvas Canvas.Left="340" Canvas.Top="200" Canvas.ZIndex="2" >
<Ellipse Canvas.Left="0" Canvas.Top="0" Width="60" Height="40" Stroke="Black" Name="LeftEye" Fill="White" Canvas.ZIndex="2" />
<Ellipse Canvas.Left="10" Canvas.Top="10" Width="20" Height="20" Fill="Green" Name="LeftPupil" Canvas.ZIndex="2" />
<Canvas.Clip>
<EllipseGeometry Center="30,20" RadiusX="30" RadiusY="20" />
</Canvas.Clip>
</Canvas>


<Canvas Canvas.Left="420" Canvas.Top="200" Canvas.ZIndex="2" >
<Ellipse Canvas.Left="0" Canvas.Top="0" Width="60" Height="40" Stroke="Black" Name="RightEye" Fill="White" Canvas.ZIndex="2" />
<Ellipse Canvas.Left="10" Canvas.Top="10" Width="20" Height="20" Fill="Green" Name="RightPupil" Canvas.ZIndex="2" />
<Canvas.Clip>
<EllipseGeometry Center="30,20" RadiusX="30" RadiusY="20" />
</Canvas.Clip>
</Canvas>

<Ellipse Canvas.Left="395" Canvas.Top="270" Width="30" Height="40" Stroke="Black" Name="Nose" Fill="DarkGray" Canvas.ZIndex="1"/>

<Ellipse Canvas.Left="380" Canvas.Top="320" Width="60" Height="30" Stroke="Black" Name="Mouth" Fill="DarkGray" Canvas.ZIndex="1"/>

<Ellipse Canvas.Left="10" Canvas.Top="60" Width="10" Height="10" Fill="Red" Name="FocusPoint" Canvas.ZIndex="6" />
<Line Stroke="Red" Name="LineSightLeft" Canvas.ZIndex="5" StrokeDashArray="2 5" />
<Line Stroke="Red" Name="LineSightRight" Canvas.ZIndex="5" StrokeDashArray="2 5" />
</Canvas>
</UserControl>


The code behind simply responds to the mouse moving, for each eye calculates the polar coordinates and then moves the eyeball proportionally towards the mouse:

public partial class Page : UserControl
{
bool showCalcs;

public Page()
{
InitializeComponent();

// default to showing calculations
ShowCalculation.IsChecked = this.showCalcs = true;
}

private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
{
// update UI based on cursor location
Point cursorPoint = e.GetPosition(LayoutRoot);

UpdateUI(cursorPoint);
}

private void UpdateUI(Point cursorPoint)
{
// calculate the location of the focus based using the center of the circle
Point centerPoint = new Point(cursorPoint.X, cursorPoint.Y);

if (this.showCalcs)
FocusPoint.PointSet(new Point(cursorPoint.X - (FocusPoint.Width / 2), cursorPoint.Y - (FocusPoint.Height / 2)));

// focus eyes on point
FocusEye(centerPoint, LeftEye, LeftPupil, LineSightLeft);
FocusEye(centerPoint, RightEye, RightPupil, LineSightRight);
}

private void FocusEye(Point pointFocus, Ellipse eye, Ellipse pupil, Line sight)
{
// the centre of the eye needs to be converted to a global coordinate
// which it's parent has
Point pointStart = new Point(eye.Parent.PointGet().X + (eye.Width / 2), eye.Parent.PointGet().Y + (eye.Height / 2));
Point pointEnd = pointFocus;

// cartesian to polar conversion
double angle = Trigonometry.CalculateAngleInDegreesBetween(pointStart, pointEnd);
double distance = Trigonometry.CalculateDistanceBetween(pointStart, pointEnd);

if (this.showCalcs)
TextDebug.Text = String.Format(" {2:N1}deg {3:N1} {0} {1}", new object[] { pointStart, pointEnd, angle, distance });

// maximum focal distance
const double MAX_DISTANCE = 500d;

// the eye will move away from the center
// of the eye ball proportionally to its maxim view
// reduced by π to keep some of it visible
double pupilDistance = (eye.Width / Math.PI) * (distance / MAX_DISTANCE);

// polar to cartesian conversion
Point pointPupilOffset = Trigonometry.ConvertPolarToPoint(pupilDistance, angle);

// adjust for centre of eyeball and pupil
Point pupilLocation = new Point(
(eye.Width / 2) + pointPupilOffset.X - (pupil.Width / 2),
(eye.Height / 2) - pointPupilOffset.Y - (pupil.Height / 2));

pupil.PointSet(pupilLocation);

if (this.showCalcs)
{
sight.X1 = pointStart.X;
sight.Y1 = pointStart.Y;
sight.X2 = pointEnd.X;
sight.Y2 = pointEnd.Y;
}
}

private void CheckBox_Changed(object sender, RoutedEventArgs e)
{
// show calculations visually
this.showCalcs = ShowCalculation.IsChecked ?? false;

Visibility visibility = (this.showCalcs) ? Visibility.Visible : Visibility.Collapsed;

FocusPoint.Visibility = visibility;
LineSightLeft.Visibility = visibility;
LineSightRight.Visibility = visibility;
TextDebug.Visibility = visibility;

if (this.showCalcs)
LayoutRoot.Cursor = Cursors.None;
else
LayoutRoot.Cursor = Cursors.Arrow;
}
}


The code uses some extension methods, as I started doing in my previous blog entry:

public static class XamlExtensions
{
public static Point PointGet(this DependencyObject sobj)
{
Point point = new Point((double)sobj.GetValue(Canvas.LeftProperty), (double)sobj.GetValue(Canvas.TopProperty));

return point;
}

public static void PointSet(this DependencyObject shape, Point newLocation)
{
shape.SetValue(Canvas.LeftProperty, newLocation.X);
shape.SetValue(Canvas.TopProperty, newLocation.Y);
}

public static Point GetCenterPoint(this Shape shape)
{
Point location = shape.PointGet();

Point centerPoint = new Point(location.X + (shape.Width / 2), location.Y + (shape.Height / 2));

return centerPoint;
}
}


and a helper class for doing the trig:

public class Trigonometry
{
public static double DegreesToRadians(double angle)
{
return ((angle * Math.PI) / 180f);
}

public static double RadiansToDegrees(double angle)
{
return ((angle * 180) / Math.PI);
}

public static double CalculateAngleInDegreesBetween(Point pointStart, Point pointEnd)
{
// difference between points on Y-Axis
// Silverlight Y axis needs to be inverted of cartesian coordinates
double dy = -(pointEnd.Y - pointStart.Y);
// difference between points on X-Axis
double dx = (pointEnd.X - pointStart.X);

// angle of the vector defined by dy, dx
double angleRadians = Math.Atan2(dy, dx);

// results in (-Ï€,Ï€], which needs mapping to [0,2Ï€) by adding 2Ï€ to negative
if (angleRadians < 0)
angleRadians += 2 * Math.PI;

double angleDegrees = RadiansToDegrees(angleRadians);

return angleDegrees;
}

public static double CalculateDistanceBetween(Point pointStart, Point pointEnd)
{
double dySquared = Math.Pow(pointEnd.Y - pointStart.Y, 2);
double dxSquared = Math.Pow(pointEnd.X - pointStart.X, 2);

double distance = Math.Sqrt(dySquared + dxSquared);

return distance;
}


internal static Point ConvertPolarToPoint(double radius, double angleDegrees)
{
double angleRadians = DegreesToRadians(angleDegrees);

double x = radius * Math.Cos(angleRadians);
double y = radius * Math.Sin(angleRadians);

return new Point(x, y);
}
}

Tuesday, October 21, 2008

Moving shapes in Silverlight

Having written the same code too many times, I thought I better start making life more easy for myself. In Silverlight you often want to change the location of a shape (or more correctly a DependancyObject)

The code I kept writing was move the location of a shape, such as in drag-n-drop.

I've written this as an Extension method, giving:
public static class XamlExtensions
{
public static void PointSet(this DependencyObject shape, Point newLocation)
{
shape.SetValue(Canvas.LeftProperty, newLocation.X);
shape.SetValue(Canvas.TopProperty, newLocation.Y);
}
}


which allows:
shape.PointSet(cursorPoint);

rather than
PointSet(shape, cursorPoint);

Monday, October 20, 2008

IMF bails out Iceland, Dublin being renamed

So in answer to my previous post How long can the IMF afford to wait? the answer appears to be two weeks.

On a related note, my brother is convinced he invented the credit crunch joke:

"The capital city of Ireland has been renamed from Dublin to Halving" [due to Ireland's technical recession]

a reference to the previous joke of "Ireland having Europe's fastest growing city - its doubling every year"

omg

Thursday, October 16, 2008

Simple Kinetics in silverlight

Simple kinetics (mechanical) in silverlight, some exploding balls:



XAML:

<UserControl x:Class="SimpleKinetics.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="500" Height="350">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas x:Name="Container">
<Button x:Name="ButtonAdd" Canvas.Top="10" Canvas.Left="8" ClickMode="Release" Content="New balls" Click="ButtonAdd_Click" />
<Rectangle x:Name="Controls" Canvas.Top="0" Canvas.Left="0" Width="75" Height="300">
</Rectangle>
</Canvas>
</Grid>
</UserControl>


code behind:

public partial class Page : UserControl
{
List<Vector> vectors = new List<Vector>();
const int RADIUS = 5;
Random rand = new Random();

public Page()
{
InitializeComponent();

DispatcherTimer timer = new DispatcherTimer();

timer.Interval = new TimeSpan(0, 0, 0, 0, 30);

timer.Tick += new EventHandler(OnTick);

timer.Start();
}

private void OnTick(object sender, EventArgs e)
{
List<Vector> deads = new List<Vector>();
foreach (Vector vector in vectors)
{
vector.Transition();
if (vector.IsDead)
deads.Add(vector);
}

deads.ForEach(dead =>
{
vectors.Remove(dead);
Container.Children.Remove(dead.ellipse);
});
}

private void ButtonAdd_Click(object sender, RoutedEventArgs e)
{
for (int explosions = 0; explosions < rand.Next(10)+1; explosions++)
GenerateExplode();
}

private void GenerateExplode()
{
Point point = new Point(rand.Next((int)Width), rand.Next((int)Height));
for (int i = 0; i < 100; i++)
{
Ellipse ellipse = new Ellipse();
ellipse.Width = RADIUS;
ellipse.Height = RADIUS;
Vector vector = new Vector(rand.Next(360), (rand.Next(30) / 10D) + 0.5D, ellipse);
vectors.Add(vector);

// make it a random colour
ellipse.Fill = new SolidColorBrush(
Color.FromArgb(
255,
GetRandomColour(),
GetRandomColour(),
GetRandomColour()));

// add it to the interface
Container.Children.Add(ellipse);

// put it in a random location
vector.Point = point;
}
}

private byte GetRandomColour()
{
return (byte)rand.Next(byte.MaxValue);
}

private Point Offset(Point inpoint, double offset)
{
Point point = new Point(inpoint.X + offset, inpoint.Y + offset);

return point;
}

private static Point GetPoint(DependencyObject sobj)
{
Point point = new Point((double)sobj.GetValue(Canvas.LeftProperty), (double)sobj.GetValue(Canvas.TopProperty));

return point;
}
}


which depends on my Vector class:

internal class Vector
{
public double direction;
public double magnitude;
public Ellipse ellipse;

public Vector(double direction, double magnitude, Ellipse ellipse)
{
this.direction = direction;
this.magnitude = magnitude;
this.ellipse = ellipse;
}

public Point Point
{
get
{
Point point = new Point((double)ellipse.GetValue(Canvas.LeftProperty), (double)ellipse.GetValue(Canvas.TopProperty));

return point;
}
set
{
ellipse.SetValue(Canvas.LeftProperty, value.X);
ellipse.SetValue(Canvas.TopProperty, value.Y);
}
}

internal void Transition()
{
Point newPoint = CalculateNextPosition();

Point = newPoint;

double fade = ((magnitude * magnitude) / magnitude) / 800d;
ellipse.Fill.Opacity -= fade;
}

public bool IsDead
{
get
{
return !(ellipse.Fill.Opacity > 0);
}
}

private double DegreesToRadians(double angle)
{
return ((angle*Math.PI) / 180f);
}

private double RadiansToDegrees(double angle)
{
return ((angle*180) / Math.PI);
}

private Point CalculateNextPosition()
{
double vx = magnitude * Math.Cos(DegreesToRadians(direction));
double vy = magnitude * Math.Sin(DegreesToRadians(direction));

Point current = this.Point;
double x = current.X + vx;
double y = current.Y + vy;

CheckCollision(vx, vy, x, y);

Point newPoint = new Point(x, y);

return newPoint;
}

private void CheckCollision(double vx, double vy, double x, double y)
{
const int maxX = 500;
const int maxY = 500;

if (x < 0 x > maxX)
vx *= -1;
if (y < 0 y > maxY)
vy *= -1;

magnitude = Math.Sqrt((vx * vx) + (vy * vy));
direction = RadiansToDegrees(Math.Atan2(vy, vx));
}
}

Bezier Silverlight


(use the "+" key to add new segments)

update earlier silverlight application to release version (original post)

Silverlight puzzle update and issues


Updated silverlight puzzle to use the release version of silverlight 2.



The only issue with the upgrade was that using "storyBoard.SkipToFill()" does not stop the animation in the new version - this generated an exception:



A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.dll

Additional information: Operation is not valid on an active Animation or Storyboard. Root Storyboard must be stopped first.



This exception was caused by trying to resue the same animation, in the beta SkipToFill also stopped the animation. Adding a "storyBoard.Stop()" after the SkipToFill() fixed this. However this caused a side-effect. It appears that in the beta SkipToFill actually updates the DependencyProperty, what does this mean?

In my beta code I relied on using the animation to "move" the visual tile from one position to another. In the release version once the animation was removed (i.e. applied to a different object) the tile would snap back to its original position. My work around this was to set the tiles position before the animation - this would mean that the tile would be at the correct location after the animation (or if the animation was removed).

Wednesday, October 15, 2008

Hamlet vs Twinkle, Brown and Cameron

ok, I've lost the plot - but I realised that this could be generalised into a general Vs engine, so without further ado!

Alternative Hamlet
Hamlet Vs Twinkle, Twinkle little star
Hamlet Vs David Cameron's Party speech
Hamlet Vs Gordon Brown's Global Economy speech
Hamlet Vs Bush
Hamlet Vs Obama
Hamlet Vs McCain

must, stop.. but Cameron version very good:

SCENE I. Elsinore. A million victims from alcohol related-attacks.

Sound money; low taxes – and it is a good child and a fair thought to lie between maids' legs.

HAMLET
How much I’ve worked in business alongside great entrepreneurs. I believe to be all around us.

Danes
[Aside] Though this be so.' We pray you, madam.

HAMLET
I'll set those to you like the herald Mercury
New-lighted on a heaven-kissing hill;
No, by strong hand
Of violent birth, but it’s not just for their care so doctors stop answering to Whitehall, no spirit dares stir abroad;
And let him, Horatio: a certain
convocation of politic worms are e'en with losing his wits.

MARCELLUS
Nay, do not know from personal experience just how brilliant and dedicated the people muddied,
Stood challenger on mount of all parties and none who created these safety nets and springboards. But it’s not my meaning: but I
cannot play upon me.

HAMLET
I am afeard you make it.

HAMLET
Why, what from our brother Norway?

QUEEN GERTRUDE
It is 'Adieu, adieu!
If it will please you go about to speak it profanely,
Look to't that can crop up on your heads: he, repulsed--a short tale to make ourselves relevant to the stage with tears
Had he been put on by a forged process of my cause,
To give the first Conservative metropolitan council in the mind and soul
To both your honours.

Hamlet using a Markov chain

Still playing with Markov chains, created a webpage that generates alternative versions of Hamlet, sample excerpt:


SCENE I. Elsinore. A room in Polonius' house.

Enter KING CLAUDIUS, attended
KING CLAUDIUS and POLONIUS

LORD POLONIUS

[Behind] O, ho! do you mark that?

QUEEN GERTRUDE

As kill a king!

FRANCISCO

Nay, I know not:
Is by a sleep to say we end
The ratifiers and props of every word,
They are not the trail of policy so sure
As hush as death, anon the dreadful thunder
Doth all the days i' the church.

KING CLAUDIUS

Give you good night.

Exit POLONIUS

Will you be honest and fair, your honesty should
admit no discourse to your rest; at night we'll hear a play
Let me be accurst!
None wed the second time I kill my husband dead,
Till the foul crimes done in my life,
That I have found
The observed of all your son's distemper.

QUEEN GERTRUDE

Alas, poor Yorick! I knew him, Horatio: welcome, good Marcellus.

The best poor Yorick so far is "Alas, poor Yorick! I knew your father; " - obviously his dad was not a nice guy ;-)

Tuesday, October 14, 2008

Hamlet vs. Twinkle, twinkle, little star

Give a markov chain a childs rhyme, a dash of Hamlet and behold! Hamlet's little star:


a little ere the mightiest julius fell,
the graves stood tenantless and the suits of solemn black,
nor windy suspiration of forced breath,
no, nor the fruitful river in the sky.

as your bright and tiny spark,
he could not see which way to heaven;
whiles, like a diamond in the roman streets:
as stars with trains of fire and dews of blood,
disasters in the same covenant,
and carriage of the land.

bernardo
i think i hear them. stand, ho! who's there?

enter horatio and marcellus,
the rivals of my watch, bid them make haste.

francisco
i think it was about to speak, when the blazing sun is gone,
when he nothing shines upon,
then you show your little light,
twinkle, twinkle,
all the holy vows of heaven
where now it burns, marcellus and bernardo, on their watch,
in the land,
and why such daily cast of brazen cannon,
and foreign mart for implements of war;
why such impress of shipwrights, whose sore task
does not grow alone
in thews and bulk, but, as this temple waxes,
the inward service of the cock.
some say that ever 'gainst that season comes
wherein our saviour's birth is celebrated,
the bird of dawning singeth all night long:
and then, they say, you spirits oft walk in death.

Monday, October 13, 2008

Alliteration algorithm

A function to determine is a string is an alliteration, for example
" as albert asked Anna, an antelope appeared!" is considered to be one.


private static bool IsAnAlliteration(string subject)
{
bool result = true;

char lead = default(char);

bool inWord = false;

foreach (char c in subject)
{
char current = char.ToLower(c);

bool isLetter = char.IsLetter(current);
// lead contains first character in string
// all words should start with lead character
if (lead == default(char) && isLetter)
lead = current;

if (!inWord && isLetter && lead != current)
result = false; // start of new word, but does not start with lead char
else if (!inWord && isLetter && lead == current)
inWord = true; // start of new word starts with lead char
else if (inWord && char.IsWhiteSpace(current))
inWord = false; // end of word found

if (!result)
break;
}
// did we find at least one word
result &= (lead != default(char));

return result;
}

Thursday, October 9, 2008

Banking jokes

some news my brother found funny..

"I hear that the Japanese banks are in trouble.

Origami Bank has just folded and there is something fishy going on at Sushi Bank,
we are hearing that Sumo Bank has gone belly up and Bonsai Bank plans to cut back some of its branches.

Karaoke Bank is up for sale and is going for a song.

Meanwhile, shares in Kamikaze Bank have nose-dived and 500 back-office staff at Karate Bank got the chop."

omg

Investing now? a few words from the unwise

Fibonacci resistance leads us to believe that the golden ratio is shining, but there is a risk of oscillation as the Ichimoku cloud could be coming in Elliott waves.

Stick that in you markov chain and smoke it...

Finance a science? methinks it looks like art.

Permutations and Anagrams

I needed to generate some anagrams, which I know falls into the area Permutations (combinations being altogether the wrong thing for this). There is a nice code sample on Wikipedia that shows how to generate these for an unordered collection.

I implemented a generic class to carry out permutations for me, I changed it to be based on an iterator pattern as often you don't want to generate the whole set, mainly because of the big-oh O(n!), class is therefore:


class Permutation<T>
{
IEnumerable<T> set;

private Permutation()
{
}

public Permutation(IEnumerable<T> set)
{
this.set = set;
}

public IEnumerable<IEnumerable<T>> Mutations
{
get
{
int length = set.Count();

int factorialK = (int)Factorial(length);

for (int k = 0; k < factorialK; k++)
yield return GeneratePermutation(k, set, length);

}
}

private static IEnumerable<T> GeneratePermutation(long k, IEnumerable<T> set, int length)
{
T[] result = set.ToArray();
for (int j = 2; j <= length; j++)
{
k = k / (j - 1);
int dest = (int)(k % j);
int source = j - 1;
if (source != dest)
Swap(ref result[dest], ref result[source]);
}

return result;
}

private static void Swap(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}

private static long Factorial(int n)
{
long result = 1L;

for (int integer = 2; integer <= n; integer++)
result *= integer;

return result;
}
}


which allowed me to write the following code to generate ananagrams:


static void Main(string[] args)
{
string word = "ape";

List<string> anagrams = GenerateAnagrams(word);

anagrams.Sort();

Console.WriteLine("{0} anagrams", anagrams.Count);
anagrams.ForEach(anagram => Console.WriteLine(anagram));
}

private static List<string> GenerateAnagrams(string word)
{
List<string> sets = new List<string>();

Permutation<char> perm = new Permutation<char>(word);
foreach (char[] combo in perm.Mutations)
sets.Add(combo.ToString());

return sets;
}

note that we are taking advantage of string being a char[], for other types such as int would need to be passed as an array, list or similar IEnumerable<T>

Wednesday, October 8, 2008

Minimalistic phone instructions

So I've just got a "free" upgrade to my phone from Orange.

Its the HTC Touch Diamond p3700, a much smaller phone than my previous. It comes in very styled packaging and contains a "quick start" pamphlet from Orange and quick guide to use the touch interface from HTC.

That's all the documentation you get, nothing else. So how the heck do I use it, or more importantly set it up? ah, I found a three step process on the "quick start" cover:
  1. Insert SIM card
  2. Charge phone
  3. Register your Orange phone

That's it, nowhere does it say how the feck to do step 3 - maybe they felt that putting in "ring orange on the freephone registration number" was too helpful, or maybe they realised that if they did this that someone might ask the even more troubling question:

What's the number! argh, its not mentioned anywhere in the packaging! (why would it be since they never told you to ring it in the first place) Anyway I had to look it up on Orange's website, where the following steps are recommended for setting up a new phone:

  1. charge the battery
  2. transfer your personal numbers from your old SIM card to your new phone's memory
  3. call 0800 079 0027 to register your upgrade and new SIM card

Obviously these instructions are too detailed to put in the box..

Monday, October 6, 2008

How long can the IMF afford to wait?

GDP: $20billon
Banking Debt: $120billion
Population: 304,367
Banking debt/person: ~$400,000

Outcome: Iceland either lets the banks fail, or it takes on a massive national debt and promptly defaults, or its trading partners are going to have to allow it to deflate its debt (of course I'm sure that the Netherlands, Germany, UK and USA have lots of spare cash)

not a great set of options...

the question is: can other countries remain solvent? and how long before the IMF has to start propping up countries? of course since they sold most the gold they will have to use.... (wait for it) US government and corporate bonds. Truth is stranger than fiction.