1 /// People name generator 2 module namegen.people; 3 4 struct Name 5 { 6 string first; 7 string last; 8 9 string full() const 10 { 11 return first~" "~last; 12 } 13 14 alias full this; 15 } 16 17 Name createName(bool isFemale = false) 18 { 19 Name ret; 20 21 ret.first = selectName(isFemale ? femaleFirst : maleFirst); 22 ret.last = selectName(lastNames); 23 24 return ret; 25 } 26 27 unittest 28 { 29 assert(createName(false) == "Kevin Toll"); 30 assert(createName(false) == "Rob Price"); 31 32 assert(createName(true) == "Erika Ressler"); 33 assert(createName(true) == "Sally Coe"); 34 35 // It is to reset RNDG to initial value 36 rndg = Random(42); 37 } 38 39 private: 40 41 import std.random; 42 43 auto rndg = Random(42); 44 45 string selectName(in NameRecord[] names) 46 { 47 enum cumMax = 90.5f; 48 49 assert(names[$-1].cumulative < cumMax); 50 51 float selected = uniform(0.0f, cumMax, rndg); 52 53 foreach(const ref n; names) 54 { 55 if(n.cumulative > selected) 56 return n.name; 57 } 58 59 assert(false); 60 } 61 62 struct NameRecord 63 { 64 import std.string: isNumeric, capitalize; 65 import std.conv: to; 66 67 string name; 68 float cumulative; 69 70 this(string[] a) 71 { 72 assert(a.length == 4); 73 assert(a[1].isNumeric); 74 assert(a[2].isNumeric); 75 assert(a[3].isNumeric); 76 77 name = a[0].capitalize; 78 cumulative = a[2].to!float; 79 80 assert(cumulative > 0); 81 } 82 } 83 84 // Compile time parsing for big text files is too slow by now, therefore this function is unused 85 NameRecord[] getNamesRecordsCTFE(string filename)() 86 { 87 enum text = import(filename); 88 89 return getNamesRecordsFromText(text); 90 } 91 92 NameRecord[] getNamesRecordsFromText(string text) 93 { 94 string line; 95 NameRecord[] recs; 96 97 foreach(c; text) 98 { 99 if(c != '\n') 100 { 101 line ~= c; 102 } 103 else 104 { 105 import std.array: split; 106 107 recs ~= NameRecord(line.split); 108 line.length = 0; 109 } 110 } 111 112 return recs; 113 } 114 115 const NameRecord[] maleFirst; 116 const NameRecord[] femaleFirst; 117 const NameRecord[] lastNames; 118 119 static this() 120 { 121 immutable maleFirstTextLines = import("dist.male.first"); 122 immutable femaleFirstLines = import("dist.female.first"); 123 immutable lastTextLines = import("dist.all.last"); 124 125 maleFirst = getNamesRecordsFromText(maleFirstTextLines); 126 femaleFirst = getNamesRecordsFromText(femaleFirstLines); 127 lastNames = getNamesRecordsFromText(lastTextLines); 128 } 129 130 unittest 131 { 132 assert(maleFirst[0].name == "James", maleFirst[0].name); 133 assert(maleFirst[1218].name == "Alonso", maleFirst[1218].name); 134 }