PhoneChainer backend

Hi all,

I've written a backend which will take phone clues and generate
placenames from the areacode. Areacode data (from free sources on the
web) for the UK and US is provided.

I'm not sure how to setup the path to the areacode data. How should I do
What kind of clue should this generate? Address? Keyword? Textblock? Or
should we consider a new keyword such as "place"? My own feeling is that
a "place" keyword for places which aren't full addresses is a good idea.

Longer term ideas:
I'd like to integrate this with Edd's lat/long work (generate lat/long
clues). Maybe do similar things with postcode / zip code data as well. 
More detailed data for the US might be useful, the area codes seem
pretty big. I like the idea of dashboard doing useful things (e.g. maps)
with geographic data, I think that has a lot of potential.

Please let me know what you think.



Attachment: areacodes.tar.bz2
Description: application/bzip

// GNOME Dashboard
// PhoneChainerBackend.cs: 
// Author:
//         Dave Rodgman <davidr sucs org>

using System;
using System.IO;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;

namespace Dashboard {

	class PhoneChainerBackend:Backend {

		public override bool Startup () {
			Name = "Phone Chainer";

			// FIXME - this needs to be sorted out. Not sure of the best way to do it.
			String path = "areacodes";

			StreamReader sr;
			SortedList table;

			DirectoryInfo dir = new DirectoryInfo (path);
			foreach (FileInfo file in dir.GetFiles ("areacodes.*.csv")) {
				String Country;
				try {
					sr = new StreamReader (new FileStream (file.FullName, FileMode.Open));

					Country = sr.ReadLine ().Substring (1).Trim (null);
					if (!codeToAreaTable.ContainsKey (Country))
						codeToAreaTable.Add (Country, new SortedList ());
					table = (SortedList) codeToAreaTable [Country];

					RegularExpressions.Match intlCodes = Regex.Match (sr.ReadLine (), @"#\+(\d+)\s*(\d*)");
					table.Add ("CountryCode",   intlCodes.Groups [1].Captures [0].ToString ());
					table.Add ("CountryPrefix", intlCodes.Groups [2].Captures [0].ToString ());
				catch (Exception e) {
					Console.WriteLine ("PhoneChainer: Could not load area codes database: " + file.FullName);

				String line, code, area;
				Regex extractData = new Regex (@"\x22(?<code>\d+)\x22,\x22(?<town>[^\x22]+)\x22", RegexOptions.Compiled);

				while ((line = sr.ReadLine ()) != null) {
					if (line [0] == '#')

					try {
						RegularExpressions.Match m = extractData.Match (line);

						area = m.Groups ["town"].Captures [0].ToString ();
						code = m.Groups ["code"].Captures [0].ToString ();
						if ((area.Length == 0) || (code.Length == 0))
							throw new Exception ();
					catch (Exception e) {
						Console.WriteLine ("PhoneChainer: error in {0} areacode data, line: {1}", Country, line);

					if (code.Length < minCodeLength)
						minCodeLength = code.Length;

					// We permit multiple towns per area code
					if (!table.ContainsKey (code))
						table.Add (code, new ArrayList ());
					((ArrayList) (table [code])).Add (area);
				Console.WriteLine ("PhoneChainer: Loaded {0} area codes", Country);
			Console.WriteLine ("PhoneChainer backend started");

			this.SubscribeToClues ("phone");
			this.Initialized = true;

			return true;

		private Hashtable codeToAreaTable = new Hashtable ();
		private int minCodeLength = 999999;

		private ArrayList lookupArea (String originalNumber) {
			ArrayList result = new ArrayList ();

			String number = Regex.Replace (originalNumber, @"[^\d\+]", "");

			if (number.Length == 0)
				return result;

			IDictionaryEnumerator ie = codeToAreaTable.GetEnumerator ();
			while (ie.MoveNext ()) {
				SortedList table = (SortedList) (ie.Value);
				String code;

				// deal with international prefixes
				if (number [0] == '+') {
					code = number.Substring (1);
					if (!code.StartsWith ((String) (table ["CountryCode"])))
					code = table ["CountryPrefix"] + code.Substring (((String) (table ["CountryCode"])).Length);
				} else
					code = number;

				String key = null;
				for (int len = minCodeLength; len <= code.Length; len++) {
					int i = table.IndexOfKey (code.Substring (0, len));
					if (i == -1)
					key = code.Substring (0, len);

				if (key == null) continue;

				foreach (String town in (ArrayList) table [key])
				result.Add (town + ", " + ie.Key);
			return result;

		public override BackendResult ProcessCluePacket (CluePacket cp) {
			BackendResult result = new BackendResult (this, cp);

			foreach (Clue clue in cp.Clues) {
				if (!ClueTypeSubscribed (clue))

				ArrayList areas = lookupArea (clue.Text);

				foreach (String a in areas) {
					Clue areaClue = new Clue ("keyword", a, 10, clue);	// FIXME is this the right cluetype?
					result.AddChainedClue (areaClue);
			return result;

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]