Friday, March 28, 2008

Random generator class

I was involved into a project over the winter where we didn't have any data to fead the system, even though we had the format (or at least a fairly clear idea of it) in which each data file should be. So I wrote a class to randomize the data for creating several different .dat files. I did a bit of digging at the time, and even though I can't recall where I found the list I've used into the Enum, they were at that time the most popular one in the UK. I've had a lot of fun working my head around this, using Enum for the first time!


using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace MonkeyScience
{
class WriteRandomBrokerToFile
{
const string fileName = "members.dat";
const int panelIDStart = 100001;
const int firmIDStart = 1001;
const int firmIDEnd = 1030;
const int firstNameRandomizedMin = 1;
const int firstNameRandomizedMax = 50;
const int lastNameRandomizedMin = 1;
const int lastNameRandomizedMax = 100;
const int telMin = 0;
const int telMax = 9;
const int companyMin = 1;
const int companyMax = 20;
const int wayMin = 1;
const int wayMax = 6;

enum firstNameEnum
{
Jack = 1, Thomas, James, Joshua, Daniel, Harry, Samuel, Joseph, Matthew, Callum,
Luke, William, Lewis, Oliver, Ryan, Benjamin, George, Liam, Jordan, Adam,
Alexander, Jake, Connor, Cameron, Nathan, Kieran, Mohammed, Jamie, Jacob,
Michael, Ben, Ethan, Charlie, Bradley, Brandon, Aaron, Max, Dylan, Kyle, Reece,
Robert, Christopher, David, Edward, Charles, Owen, Louis, Alex, Joe, Rhys
};

enum lastNameEnum
{
Smith = 1, Brown, Wilson, Thomson, Robertson, Campbell, Stewart, Anderson,
MacDonald, Scott, Reid, Murray, Taylor, Clark, Mitchell, Ross, Walker, Paterson,
Young, Watson, Morrison, Miller, Fraser, Davidson, Gray, McDonald, Henderson,
Johnston, Hamilton, Graham, Kerr, Simpson, Martin, Ferguson, Cameron, Duncan,
Hunter, Kelly, Bell, Grant, MacKenzie, MacKay, Allan, Black, MacLeod, McLean,
Russell, Gibson, Wallace, Gordon, Marshall, Stevenson, Wood, Sutherland, Craig,
Wright, McKenzie, Kennedy, Jones, Burns, White, Muir, Murphy, Johnstone, Hughes,
Watt, McMillan, Mcintosh, Milne, Munro, Ritchie, Dickson, Bruce, King, Crawford,
Docherty, Millar, Cunningham, Sinclair, Williamson, Hill, McGregor, McKay, Boyle,
Shaw, Fleming, Moore, Christie, Douglas, Donaldson, McAndrews, MacLean, Forbes,
Mcintyre, Findlay, Jamieson, Aitken, Reilly, Thompson, Hay
};

enum companyNameEnum
{
KPMG = 1, BarchesterHealthcare, Nationwide, RBS,
MorganStanley, CarphoneWarehouse, Deloitte, AmEx,
Mothercare, Cadbury, Atkins, ErnstYoung, Vodafone,
PricewaterhouseCoopers, ThomasCook, DeutscheBank,
GalaBingo, LeonardCheshire, BradfordCouncil, Barclays
};

enum wayEnum
{
Street = 1, Road, Gate, Avenue, Lane, Terrace
};

enum alphaEnum
{
A = 1, B, C, D, E, F, G, H, I, J, K, L, M,
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
};

enum districtEnum
{
North = 1, East, South, West
};

string foreName = string.Empty;
string lastName = string.Empty;
string oldForeName = string.Empty;
string oldLastName = string.Empty;
string telNumber = string.Empty;
string companyName = string.Empty;
string postCode = string.Empty;
string flatNnumber = string.Empty;
string buildingNumber = string.Empty;
string buildingName = string.Empty;
string street = string.Empty;
string district = string.Empty;
string town = string.Empty;
string county = string.Empty;

Random ran = new Random();

public void Write()
{
string ret = null;
Random ram = new Random();
int panelID = panelIDStart;

StreamWriter sWriter = new StreamWriter(fileName);

for (int firmID = firmIDStart; firmID < firmIDEnd + 1; firmID++)
{
for (int i = 0; i < 4; i++)
{
if (foreName == string.Empty || foreName == oldForeName)
{
foreName = this.GetRandomFirstName();
if (lastName == string.Empty || lastName == oldLastName)
{
lastName = this.GetRandomLastName();
ret += string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\r\n",
panelID,
firmID,
foreName,
lastName,
this.GetRandomEmailAddress(foreName, lastName),
this.GetRandomTelNumber(),
this.GetRandomAddress());
panelID++;
oldLastName = lastName;
}
foreName = oldForeName;
}

}
}
sWriter.WriteLine(ret);
Console.WriteLine(ret);
sWriter.Close();
}

private string GetRandomEmailAddress(string foreName, string lastName)
{
companyName = this.GetRandomCompanyName();
string emailAddress = string.Format("{0}.{1}@{2}.com",
foreName,
lastName,
this.GetRandomCompanyName());
return emailAddress;
}

private string GetRandomTelNumber()
{
return telNumber = string.Format("0131 {0}{1}{2} {3}{4}{5}{6}",
ran.Next(telMin, telMax),
ran.Next(telMin, telMax),
ran.Next(telMin, telMax),
ran.Next(telMin, telMax),
ran.Next(telMin, telMax),
ran.Next(telMin, telMax),
ran.Next(telMin, telMax));
}

public string GetRandomFirstName()
{
string name;
return name = Enum.GetName(typeof(firstNameEnum), ran.Next(firstNameRandomizedMin, firstNameRandomizedMax));
}

public string GetRandomLastName()
{
string name;
return name = Enum.GetName(typeof(lastNameEnum), ran.Next(lastNameRandomizedMin, lastNameRandomizedMax));
}

public string GetRandomCompanyName()
{
string name;
return name = Enum.GetName(typeof(companyNameEnum), ran.Next(companyMin, companyMax));
}

public string GetRandomAddress()
{
string name;
return name = string.Format("SR{0} {1}{2}{3}\t{4}\t{5}\tWeasel House\tWeasel {6}\t{7}\tWeaseltown\tWeaselshire",
ran.Next(1, 9),
ran.Next(1, 50),
Enum.GetName(typeof(alphaEnum), ran.Next(1, 26)),
Enum.GetName(typeof(alphaEnum), ran.Next(1, 26)),
ran.Next(1, 15),
ran.Next(1, 9),
Enum.GetName(typeof(wayEnum), ran.Next(wayMin, wayMax)),
Enum.GetName(typeof(districtEnum), ran.Next(1, 4)));
}
}
}


I am looking forward to improve this pet project (creating random list of comma separated item) by taking the Enums out of the code and putting them into on or more xml files.

Tam

Saturday, March 8, 2008

qmapreader.NET - first build (pre-alpha)

This is the first compiled version of the tools available at filefront: http://dashboard.filefront.com/TouristTam/

Thursday, March 6, 2008

qmaptranslator.NET - baby steps with regex

setting up the project I had grandiose Ideas ... :[ that is usually a nooby way to say that I didn't realised how much input I would have to do with this project. So instead I went back to the drawing board and approach the project thinking about making a simple assemly to be run in cmd line only. It should take one argument (that's right) and read through a file (obviously a .map file) line by line, and copy it over when no difference between the original format (mohaa map file) and the target format (cod2 map file).
The idea is to implement a simple read-transform-copy without the time consumming step of loading objects like vertex/polygon/mesh. But currently I have a hard time running a 'simple' regex. :P

Solution to the 'Regex knowledge wall' I've faced earlier on this week:

I've found out a few interesting things about the Regex that I didn't knew about. the first one being that a regex can have named groups. At first I thought: "what the heck is that about?". And guess what?
It is simply put that grouping a few item together in a regex string can be attributed a name. therefore making the retrieval of the item more easely. Sound complicated? here is what I had in mind: Reading a quake .map file (or any of the game based around the same game engine) line by line and matching the read line with a regex, it is possible to manipulate the string read. The .map file format for a brushgives the following for a brush:

// brush 0
{
( 104 128 0 ) ( -72 128 0 ) ( -72 -40 0 ) caulk 64 64 0 0 0 0
( -72 -40 8 ) ( -72 128 8 ) ( 104 128 8 ) caulk 64 64 0 0 0 0
( -72 -40 8 ) ( 104 -40 8 ) ( 104 -40 0 ) caulk 64 64 0 0 0 0
( 104 -40 8 ) ( 104 128 8 ) ( 104 128 0 ) caulk 64 64 0 0 0 0
( 104 128 8 ) ( -72 128 8 ) ( -72 128 0 ) caulk 64 64 0 0 0 0
( -72 128 8 ) ( -72 -40 8 ) ( -72 -40 0 ) caulk 64 64 0 0 0 0
}

it reads as follow:

the curly brackets are grouping the lines in between them. Then for each line the three items in between parenthesis are the Vertices definition (to be understood as point(x, y, z)). the last part is well documented over the internet, it is the texture's name, X offset, Y offset,
rotation, x scale and y scale. Knowing that the regex to match that string is dead easy:

([0-9 \.\-]+\) ([0-9 \.\-]+\) ([0-9 \.\-]+\) [a-z0-9/_]+ [0-9\.\-]+ [0-9\.\-]+ [0-9\.\-]+ [0-9\.\-]+

Here is the trick for named groups; each item (eight of them in this example) can have a "flag" (or "tag") that can be subsequently called, iterating through the retrieved string. The regex string becomes the following:

(?[\t]*)(?\([0-9 \.\-]+\)) (?\([0-9 \.\-]+\)) (?\([0-9 \.\-]+\)) (?[a-z0-9/_]+) (?[0-9\.\-]+) (?[0-9\.\-]+) (?[0-9\.\-]+) (?[0-9\.\-]+) (?[0-9\.\-]+)

I actually found this very handy trick reading the Chapter 24 of the O'Reilly book: "C# 3.0 in a Nutshell" and experiencing with the fantastic small software call Expresso. Needless to say that all my trouble with regex were coming from my noobyness as a programmer. But hey life is a learning experience. :)

Hope this helps.

Tam