Click here to Skip to main content
15,897,704 members
Articles / Hosted Services / Azure

GPS Runner Maps: My First Windows Azure Application

Rate me:
Please Sign up or sign in to vote.
4.90/5 (12 votes)
20 Dec 2009CPOL3 min read 55.3K   3.1K   63  
It is "cloud" Web application to display GPS tracks on Google or Bing maps
/*
 * GameWatch - Server Browser for online games
 * Copyright (C) 2003 Rodrigo Reyes <reyes@charabia.net>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 */
using System;
using System.Collections;

namespace GameWatch.Utils.Net
{

    public class BitVectorTrie
    {
	public class Node
	{
	    public ArrayList Children = null;
	    public BitVector Key = null;
	    public Object Data = null;
	}

	public Node Root = new Node();
	
	public BitVectorTrie()
	{
	}

	public void Add(BitVector key, object data)
	{
	    Add(Root, key, data);
	}

	//
	// This Add method attach an object "data" to a node "n" using
	// the BitVector key as path.
	//
	private void Add(Node n, BitVector key, object data)
	{
	    if (n.Key == null)
		{
		    AddAsChildren(n, key, data);
		    return;
		}

	    //
	    // First, calculate the longest common prefix for the key
	    // and the BitVector stored in this node.
	    //
	    int longest = key.LongestCommonPrefix(n.Key);

	    System.Diagnostics.Debug.Assert(longest != 0);

	    if (longest == n.Key.Length)
		{
		    //
		    // If the current node is a perfect prefix of the
		    // key, then remove the prefix from the key, and
		    // we continue our walk on the children.
		    //
		    key = key.Range(longest, key.Length - longest);
		    AddAsChildren(n, key, data);
		    return;
		}
	    else
		{
		    //
		    // Here, n.Key and key share a common prefix. So we:
		    //
		    // - Create a new node with this common prefix
		    //   held there,
		    //
		    // - make n.Key and a new node with key as
		    // children of this new node.
		    BitVector common = n.Key.Range(0, longest);

		    Node c1 = new Node();
		    c1.Key = n.Key.Range(longest, n.Key.Length - longest);
		    c1.Data = n.Data;
		    c1.Children = n.Children;

		    Node c2 = new Node();
		    c2.Key = key.Range(longest, key.Length - longest);
		    c2.Data = data;
		    
		    n.Key = common;
		    n.Data = null;
		    n.Children = new ArrayList();
		    n.Children.Add(c1);
		    n.Children.Add(c2);

		    return;
		}
	}

	//
	// The AddAsChildren() method create a new node with key
	// "key", attach a data "data" to it, and finally link it to
	// the node "n".
	//
	private void AddAsChildren(Node n, BitVector key, Object data)
	{
	    //
	    // If "n" has no children, just add a new one
	    //
	    if (n.Children == null)
		{
		    n.Children = new ArrayList();
		    Node nu = new Node();
		    nu.Key = key;
		    nu.Data = data;
		    n.Children.Add(nu);
		    return;
		}

	    //
	    // From here, the node n already has at least 1
	    // children.


	    /// Check the one that has a common prefix with our key
	    //(if there is none, the bestindex variable stays at -1).

	    int bestindex = -1;
	    int bestlength = 0;
	    for (int i=0; i<n.Children.Count; i++)
		{
		    int b = ((Node)(n.Children[i])).Key.LongestCommonPrefix(key);

		    if (b > bestlength)
			{
			    bestlength = b;
			    bestindex = i;
			}
		}

	    //
	    // The node n has no children that have a common prefix
	    // with our key, so we create a new children node and
	    // attach our data there.
	    if (bestindex == -1)
		{
		    Node c2 = new Node();
		    c2.Key = key;
		    c2.Data = data;
		    n.Children.Add(c2);
		    return;
		}
	    else
		{
		    // There is a children node that can hold our
		    // data: continue our walk with this node.
		    Add(((Node)n.Children[bestindex]), key, data);
		    return;
		}
	}

	public object Get(BitVector key)
	{
	    Node curnode = Root;
	    while (curnode != null)
		{
		    if (curnode.Children == null)
			return null;

		    // Get the best fitting index
		    int bestindex = -1;
		    int bestlength = 0;
		    for (int i=0; i<curnode.Children.Count; i++)
			{
			    int b = ((Node)(curnode.Children[i])).Key.LongestCommonPrefix(key);
			    if (b > bestlength)
				{
				    bestlength = b;
				    bestindex = i;
				}
			}
		    
		    if (bestindex != -1)
			{
			    key = key.Range(bestlength, key.Length - bestlength);
			    curnode = ((Node)curnode.Children[bestindex]);

			    if (key.Length == 0)
				return curnode.Data;
			}
		    else
			{
			    return null;
			}
		}

	    return null;
	}

	//
	// Returns the object held in the node that best matches our
	// key.
	//
	public object GetBest(BitVector key)
	{
	    Node curnode = Root;
	    while (curnode != null)
		{
		    if (curnode.Children == null)
			return curnode.Data;

		    // Get the best fitting index
		    int bestindex = -1;
		    int bestlength = 0;
		    for (int i=0; i<curnode.Children.Count; i++)
			{
			    int b = ((Node)(curnode.Children[i])).Key.LongestCommonPrefix(key);
			    if (b > bestlength)
				{
				    bestlength = b;
				    bestindex = i;
				}
			}
		    
		    if (bestindex != -1)
			{
			    key = key.Range(bestlength, key.Length - bestlength);
			    curnode = ((Node)curnode.Children[bestindex]);

			    if (key.Length == 0)
				return curnode.Data;
			}
		    else
			{
			    return curnode.Data;
			}
		}

	    return null;
	}

	public void DisplayAsTree(Node n, int offset)
	{
	    for (int i=0; i<offset; i++)
		Console.Write("   ");
	    Console.WriteLine("<{0}> = <{1}>", n.Key, n.Data);
	    if (n.Children != null)
		{
		    foreach(Node c in n.Children)
			{
			    DisplayAsTree(c, offset+1);
			}
		}
	}

	static public void Test()
	{
	    BitVector.Test();
	    BitVectorTrie trie = new BitVectorTrie();
	    BitVector v1 = new BitVector();
	    v1.Set(0, true); // v1.Set(1, false);  v1.Set(2, true);
	    trie.Add(v1, "1");

	    v1 = new BitVector();
	    v1.Set(0, false); // v1.Set(1, false);  v1.Set(2, true);
	    trie.Add(v1, "0");

 	    v1 = new BitVector();
 	    v1.Set(0, false); v1.Set(1, false);  //v1.Set(2, false);
 	    trie.Add(v1, "00");

 	    v1 = new BitVector();
 	    v1.Set(0, true); v1.Set(1, true);  //v1.Set(2, false);
 	    trie.Add(v1, "11");

 	    v1 = new BitVector();
 	    v1.Set(0, false); v1.Set(1, true);  v1.Set(2, true);
 	    trie.Add(v1, "011");

	    v1 = new BitVector(255, 8);
 	    trie.Add(v1, "255");

	    v1 = new BitVector(1025, 11);
 	    trie.Add(v1, "1024");

	    v1 = new BitVector(1153, 11);
 	    trie.Add(v1, "1024+1+128");

	    trie.DisplayAsTree(trie.Root, 0);
	    v1 = new BitVector(1025, 11);
	    object result = trie.Get(v1);
	    Console.WriteLine("data: {0} = {1}", v1, result);

	}

    }


    

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer Forthnet
Greece Greece
Software developer and Microsoft Trainer, Athens, Greece (MCT, MCSD.net, MCSE 2003, MCDBA 2000,MCTS, MCITP, MCIPD).

Comments and Discussions