// Spludlow Software
// Copyright © Samuel P. Ludlow 2020 All Rights Reserved
// Distributed under the terms of the GNU General Public License version 3
// Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
// https://www.spludlow.co.uk/LICENCE.TXT
// The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission
// v1.14
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data;
namespace Spludlow.Data
{
///
/// Create fictional Identities
/// Name, Sex, and Date of Birth
/// Call People() for ready made table
/// Needs fixing to pick more common names with less exotic
///
public class Fictional
{
private static string _CacheKey = "Spludlow.Data.Fictional";
private static DataSet _DataSet = null;
[ThreadStatic]
private static Random _Random = null;
static Fictional()
{
_DataSet = (DataSet) Spludlow.Caching.Get(_CacheKey);
if (_DataSet != null)
return;
_DataSet = new DataSet();
string[] fileInfos = new string[]
{
"Family dist.all.last",
"Female dist.female.first",
"Male dist.male.first",
};
string dataDirectory = Spludlow.Config.ProgramData + @"\Data\Fictional";
bool download = false;
if (Directory.Exists(dataDirectory) == false)
{
Directory.CreateDirectory(dataDirectory);
try
{
foreach (string fileinfo in fileInfos)
{
string[] infoParts = fileinfo.Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
string name = infoParts[1];
string url = "http://www2.census.gov/topics/genealogy/1990surnames/" + name;
try
{
Spludlow.Net.Http.GetDataFile(url, dataDirectory + @"\" + name);
}
catch (Exception ee)
{
throw new ApplicationException("Fictional; Problem downloading the 3 files from 'https://www.census.gov/topics/population/genealogy/data/1990_census/1990_census_namefiles.html' to directory: " + dataDirectory, ee);
}
}
download = true;
}
catch
{
Directory.Delete(dataDirectory, true);
throw;
}
}
foreach (string fileinfo in fileInfos)
{
string[] infoParts = fileinfo.Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
string tableName = infoParts[0];
string importFilename = dataDirectory + @"\" + infoParts[1];
if (File.Exists(importFilename) == false)
throw new ApplicationException("Fictional; File not in directory: " + importFilename);
DataTable table = Spludlow.Data.TextTable.ReadText(tableName, new string[]
{
"RankId Name Frequency Cumulative",
"Int32* String Single Single",
});
using (StreamReader reader = new StreamReader(importFilename))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string[] words = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (words.Length != 4)
throw new ApplicationException("Fictional; Bad word count in NameFile line: " + line);
string name = words[0];
float frequency = Single.Parse(words[1]);
float cumulative = Single.Parse(words[2]);
int rankId = Int32.Parse(words[3]);
name = name[0] + name.Substring(1).ToLower();
table.Rows.Add(new object[] { rankId, name, frequency, cumulative });
}
}
_DataSet.Tables.Add(table);
}
Spludlow.Caching.Set(_CacheKey, _DataSet);
if (download == true)
{
List topViews = new List();
foreach (DataTable table in _DataSet.Tables)
{
DataView view = new DataView(table);
view.RowFilter = "RankId <= 100";
topViews.Add(view);
}
Spludlow.Log.Report("Fictional; Downloaded People Names, see atttched top 100s.", topViews.ToArray());
}
}
public static DataSet People(int count)
{
DataSet dataSet = new DataSet();
DataTable table = Spludlow.Data.TextTable.ReadText("People", new string[]
{
"Name Sex DateOfBirth Age",
"String String DateTime Int32",
});
for (int index = 0; index < count; ++index)
{
bool isFemale = Sex();
DateTime dateOfBirth = DateOfBirth(16, 75);
int age = AgeInYears(dateOfBirth);
string name = FullName(isFemale, dateOfBirth);
string sex = (isFemale == true ? "F" : "M");
table.Rows.Add(name, sex, dateOfBirth, age);
}
dataSet.Tables.Add(table);
return dataSet;
}
public static bool Sex() // True is Female
{
if (_Random == null)
_Random = new Random();
return (_Random.Next(2) == 0);
}
public static DateTime DateOfBirth(int minAge, int maxAge)
{
if (_Random == null)
_Random = new Random();
int age = minAge + _Random.Next((maxAge - minAge) + 1);
DateTime date = DateTime.Now.AddYears(-age);
date = date.AddDays(_Random.NextDouble() * -365.25);
return date;
}
public static string FullName()
{
return FullName(Sex(), DateOfBirth(16, 75));
}
public static string FullName(bool isFemale, DateTime dateOfBirth)
{
int age = AgeInYears(dateOfBirth);
StringBuilder name = new StringBuilder();
string firstName = FirstName(isFemale);
string middleName = firstName;
while (middleName == firstName)
middleName = FirstName(isFemale);
name.Append(Honorific(isFemale, age));
name.Append(" ");
name.Append(firstName);
name.Append(" ");
name.Append(middleName);
name.Append(" ");
name.Append(FamilyName());
return name.ToString();
}
public static string FamilyName()
{
return Name("Family");
}
public static string FirstName(bool isFemale)
{
if (isFemale == true)
return Name("Female");
else
return Name("Male");
}
private static string Name(string tableName)
{
if (_Random == null)
_Random = new Random();
DataTable table = _DataSet.Tables[tableName];
int total = table.Rows.Count;
int index = _Random.Next(total);
return (string)table.Rows[index][1];
}
public static string Honorific(bool isFemale, int age)
{
if (_Random == null)
_Random = new Random();
int titleRarety = 100;
if (age < 16)
{
if (isFemale == true)
return "Miss";
else
return "Master";
}
if (age >= 50)
{
if (_Random.Next(titleRarety) == 0)
{
if (isFemale == true)
return "Dame";
else
return "Sir";
}
if (_Random.Next(titleRarety) == 0)
{
if (isFemale == true)
return "Lady";
else
return "Lord";
}
}
if (age >= 35)
{
if (_Random.Next(titleRarety) == 0)
return "Dr";
if (_Random.Next(titleRarety) == 0)
return "Prof";
if (_Random.Next(titleRarety) == 0)
return "Rev";
}
if (isFemale == false)
return "Mr";
if (_Random.Next(100) == 0)
return "Ms";
if (_Random.Next(4) == 0)
return "Miss";
return "Mrs";
}
public static int AgeInYears(DateTime dateOfBirth)
{
return AgeInYears(dateOfBirth, DateTime.Now);
}
public static int AgeInYears(DateTime dateOfBirth, DateTime fromDate)
{
TimeSpan ageSpan = fromDate - dateOfBirth;
return (int)(ageSpan.TotalDays / 365.25);
}
}
}