// 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); } } }