diff --git a/BadMedicine.Core/BadMedicine.Core.csproj b/BadMedicine.Core/BadMedicine.Core.csproj index 731d9cf..1ba161f 100644 --- a/BadMedicine.Core/BadMedicine.Core.csproj +++ b/BadMedicine.Core/BadMedicine.Core.csproj @@ -7,7 +7,7 @@ Copyright 2019 HIC.BadMedicine Health Informatics Centre - University of Dundee - netstandard2.0 + net7.0 true diff --git a/BadMedicine.Core/BucketList.cs b/BadMedicine.Core/BucketList.cs index c0c3938..26992b2 100644 --- a/BadMedicine.Core/BucketList.cs +++ b/BadMedicine.Core/BucketList.cs @@ -11,7 +11,7 @@ namespace BadMedicine /// public class BucketList { - + readonly List _buckets = new List(); readonly List _probabilities = new List(); @@ -26,9 +26,9 @@ public T GetRandom(Random r) //cache the total _total = _total??_probabilities.Sum(); - int toPick = r.Next(0, _total.Value); + var toPick = r.Next(0, _total.Value); - for (int i = 0; i < _probabilities.Count; i++) + for (var i = 0; i < _probabilities.Count; i++) { toPick -= _probabilities[i]; if (toPick < 0) @@ -37,7 +37,7 @@ public T GetRandom(Random r) throw new Exception("Could not GetRandom"); } - + /// /// Returns a random bucket from the element indices provided (based on the probability of each bucket) @@ -49,21 +49,21 @@ public T GetRandom(IEnumerable usingOnlyIndices, Random r) { var idx = usingOnlyIndices.ToList(); - int total = idx.Sum(t=>_probabilities[t]); - - int toPick = r.Next(0, total); + var total = idx.Sum(t=>_probabilities[t]); + + var toPick = r.Next(0, total); - foreach (int i in idx) + foreach (var i in idx) { toPick -= _probabilities[i]; if (toPick < 0) return _buckets[i]; } - + throw new Exception("Could not GetRandom"); } - + /// /// Adds a new bucket to the list which will be returned using the total ratio (relative diff --git a/BadMedicine.Core/Datasets/Appointment.cs b/BadMedicine.Core/Datasets/Appointment.cs index 78eb9b8..f4deeb2 100644 --- a/BadMedicine.Core/Datasets/Appointment.cs +++ b/BadMedicine.Core/Datasets/Appointment.cs @@ -30,7 +30,7 @@ public class Appointment /// public Appointment(Person testPerson, Random r) { - Identifier = "APPT_" + Guid.NewGuid(); + Identifier = $"APPT_{Guid.NewGuid()}"; StartDate = testPerson.GetRandomDateDuringLifetime(r); } } diff --git a/BadMedicine.Core/Datasets/Biochemistry.cs b/BadMedicine.Core/Datasets/Biochemistry.cs index 2a3f331..2246f79 100644 --- a/BadMedicine.Core/Datasets/Biochemistry.cs +++ b/BadMedicine.Core/Datasets/Biochemistry.cs @@ -20,10 +20,10 @@ public Biochemistry(Random rand) : base(rand) /// public override object[] GenerateTestDataRow(Person p) { - object[] results = new object[13]; + var results = new object[13]; + + var randomSample = new BiochemistryRecord(r); - BiochemistryRecord randomSample = new BiochemistryRecord(r); - results[0] = p.CHI; results[1] = randomSample.Healthboard; results[2] = p.GetRandomDateDuringLifetime(r); diff --git a/BadMedicine.Core/Datasets/BiochemistryRecord.cs b/BadMedicine.Core/Datasets/BiochemistryRecord.cs index 161e089..0cba2f5 100644 --- a/BadMedicine.Core/Datasets/BiochemistryRecord.cs +++ b/BadMedicine.Core/Datasets/BiochemistryRecord.cs @@ -29,7 +29,7 @@ public class BiochemistryRecord /// public string Result; - + /// public string ReadCodeValue; @@ -82,35 +82,35 @@ public BiochemistryRecord(Random r) QuantityUnit = row.QuantityUnit; RangeHighValue = row.RangeHighValue.HasValue ? row.RangeHighValue.ToString():"NULL"; RangeLowValue = row.RangeLowValue.HasValue ? row.RangeLowValue.ToString():"NULL"; - + Healthboard = row.hb_extract; ReadCodeValue = row.ReadCodeValue; } - + private string GetRandomLabNumber(Random r ) { if(r.Next(0,2)==0) - return "CC" + r.Next(0, 1000000); + return $"CC{r.Next(0, 1000000)}"; - return "BC" + r.Next(0, 1000000); + return $"BC{r.Next(0, 1000000)}"; } private void Initialize() { - using (DataTable dt = new DataTable()) + using (var dt = new DataTable()) { dt.Columns.Add("RecordCount",typeof(int)); - + DataGenerator.EmbeddedCsvToDataTable(typeof(BiochemistryRecord),"Biochemistry.csv",dt); - + _bucketList = new BucketList(); foreach (DataRow row in dt.Rows) _bucketList.Add((int)row["RecordCount"], new BiochemistryRandomDataRow(row)); } } - + private class BiochemistryRandomDataRow { public string LocalClinicalCodeValue; @@ -134,10 +134,10 @@ public BiochemistryRandomDataRow(DataRow row) ArithmeticComparator =(string) row["ArithmeticComparator"]; Interpretation =(string) row["Interpretation"]; QuantityUnit =(string) row["QuantityUnit"]; - + RangeHighValue = double.TryParse(row["RangeHighValue"].ToString(),out var rangeLow) ? rangeLow:(double?) null; RangeLowValue = double.TryParse(row["RangeLowValue"].ToString(),out var rangeHigh) ? rangeHigh:(double?) null; - + QVAverage = double.TryParse(row["QVAverage"].ToString(),out var min) ? min:(double?) null; QVStandardDev = double.TryParse(row["QVStandardDev"].ToString(),out var dev) ? dev:(double?) null; @@ -153,7 +153,7 @@ internal string GetQVResult(Random r) { if(QVAverage.HasValue && QVStandardDev.HasValue) return new Normal(QVAverage.Value, QVStandardDev.Value,r).Sample().ToString(); - + return null; } } diff --git a/BadMedicine.Core/Datasets/CarotidArteryScan.cs b/BadMedicine.Core/Datasets/CarotidArteryScan.cs index 1a3ef28..d9d7f16 100644 --- a/BadMedicine.Core/Datasets/CarotidArteryScan.cs +++ b/BadMedicine.Core/Datasets/CarotidArteryScan.cs @@ -24,10 +24,10 @@ public CarotidArteryScan(Random rand) : base(rand) /// public override object[] GenerateTestDataRow(Person p) { - object[] results = new object[68]; - + var results = new object[68]; + var appointment = new Appointment(p,r); - + results[0] = appointment.Identifier; //RECORD_NUMBER results[1] = 0; //R_CC_STEN_A results[2] = 0; //R_CC_STEN_B @@ -74,7 +74,7 @@ public override object[] GenerateTestDataRow(Person p) results[43] = Swap(Math.Max(1, GetGaussianInt(-5, 9)), new[] { 6, 7, 8 }, 1); //L_CC_STENOSIS (lots of 1's some non ones but no 6,7 or 8s results[44] = GetGaussian(0,2); //L_CC_PEAK_SYS results[45] = GetGaussian(0,0.09); //L_GetGaussian(0,2); - results[46] = Swap(GetGaussianInt(1,8),new[]{7},9); //L_IC_STENOSIS + results[46] = Swap(GetGaussianInt(1,8),new[]{7},9); //L_IC_STENOSIS results[47] = GetGaussian(0,4); //L_IC_PEAK_SYS results[48] = GetGaussian(0,4); //L_IC_END_DIA results[49] = Math.Max(1, GetGaussianInt(0, 9)); //L_EC_STENOSIS @@ -177,5 +177,5 @@ protected override string[] GetHeaders() "R_IC_END_DIA" //67 }; } - } + } } diff --git a/BadMedicine.Core/Datasets/DataGenerator.cs b/BadMedicine.Core/Datasets/DataGenerator.cs index 8127b9c..126439a 100644 --- a/BadMedicine.Core/Datasets/DataGenerator.cs +++ b/BadMedicine.Core/Datasets/DataGenerator.cs @@ -28,7 +28,7 @@ public abstract class DataGenerator : IDataGenerator { /// public event EventHandler RowsGenerated; - + /// /// Use for all your random needs to ensure Seed injection support. /// @@ -62,38 +62,36 @@ public virtual bool IsEligible(Person p) /// public void GenerateTestDataFile(IPersonCollection cohort, FileInfo target, int numberOfRecords) { - using(StreamWriter sw = new StreamWriter(target.FullName)) - { - WriteHeaders(sw); + using var sw = new StreamWriter(target.FullName); + WriteHeaders(sw); - Stopwatch stopwatch = new Stopwatch(); - stopwatch.Start(); + var stopwatch = new Stopwatch(); + stopwatch.Start(); - using (var writer = new CsvWriter(sw,CultureInfo.CurrentCulture)) + using (var writer = new CsvWriter(sw,CultureInfo.CurrentCulture)) + { + int linesWritten; + for (linesWritten = 0; linesWritten < numberOfRecords; linesWritten++) { - int linesWritten; - for (linesWritten = 0; linesWritten < numberOfRecords; linesWritten++) - { - foreach (object o in GenerateTestDataRow(GetRandomEligiblePerson(cohort.People,r))) - writer.WriteField(o); - - writer.NextRecord(); - - if (linesWritten % 1000 == 0) - { - RowsGenerated?.Invoke(this,new RowsGeneratedEventArgs(linesWritten + 1, stopwatch.Elapsed,false)); - sw.Flush();//flush every 1000 - } - } + foreach (var o in GenerateTestDataRow(GetRandomEligiblePerson(cohort.People,r))) + writer.WriteField(o); - //tell them about the last line written - RowsGenerated?.Invoke(this, new RowsGeneratedEventArgs(linesWritten,stopwatch.Elapsed,true)); + writer.NextRecord(); - writer.Dispose(); + if (linesWritten % 1000 == 0) + { + RowsGenerated?.Invoke(this,new RowsGeneratedEventArgs(linesWritten + 1, stopwatch.Elapsed,false)); + sw.Flush();//flush every 1000 + } } - - stopwatch.Stop(); + + //tell them about the last line written + RowsGenerated?.Invoke(this, new RowsGeneratedEventArgs(linesWritten,stopwatch.Elapsed,true)); + + writer.Dispose(); } + + stopwatch.Stop(); } @@ -107,12 +105,12 @@ public Person GetRandomEligiblePerson(Person[] people, Random r) { if(people.Length == 0) throw new ArgumentException("Must pass at least 1 person to GetRandomEligiblePerson",nameof(people)); - + var eligible = people.Where(IsEligible).ToArray(); return - eligible.Any() ? eligible[r.Next(eligible.Length)] - //if nobody is eligibile then everyone is! + eligible.Any() ? eligible[r.Next(eligible.Length)] + //if nobody is eligible then everyone is! : people[r.Next(people.Length)]; } @@ -124,9 +122,9 @@ public virtual DataTable GetDataTable(IPersonCollection cohort, int numberOfReco foreach (var h in GetHeaders()) dt.Columns.Add(h); - for (int i = 0; i < numberOfRecords; i++) + for (var i = 0; i < numberOfRecords; i++) dt.Rows.Add(GenerateTestDataRow(GetRandomEligiblePerson(cohort.People,r))); - + return dt; } @@ -155,18 +153,18 @@ private void WriteHeaders(StreamWriter sw) /// /// /// - protected string Concat(Random r, int min, int max, Func generator, string separator) + protected static string Concat(Random r, int min, int max, Func generator, string separator) { - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - int to = r.Next(min, max); - for (int i = 0; i < to; i++) + var to = r.Next(min, max); + for (var i = 0; i < to; i++) sb.Append(generator() + separator); return sb.ToString().Trim(); } - + /// /// returns random number between -1 and 1 with normal distribution (more numbers near 0 than near 1/-1). The standard @@ -177,7 +175,7 @@ public double GetGaussian() { return Math.Min(Math.Max(-1,_normalDist.Sample()),1); } - + /// /// Returns a random date inclusive of the lower bound and exclusive of the upper bound. /// @@ -193,7 +191,7 @@ public static DateTime GetRandomDate(DateTime from, DateTime to, Random r) return from + randTimeSpan; } - + /// /// Returns a date after (or on) . In order to preserve randomisation seeding a constant /// value in 2019 is used instead of DateTime.Now (ensures that data generated doesn't vary with the same seed). @@ -218,9 +216,9 @@ public double GetGaussian(double lowerBoundary, double upperBoundary, int digits if(upperBoundary< lowerBoundary) throw new ArgumentException("lower must be lower than upper boundary"); - double distributionZeroToOne = (GetGaussian() + 1)/2; + var distributionZeroToOne = (GetGaussian() + 1)/2; - double range = upperBoundary - lowerBoundary; + var range = upperBoundary - lowerBoundary; return Math.Round((distributionZeroToOne * range) + lowerBoundary,digits); } @@ -238,7 +236,7 @@ protected int GetGaussianInt(double lowerBoundary, double upperBoundary) /// /// /// - protected int Swap(int randomInt, IEnumerable swapIfIn, int swapFor) + protected static int Swap(int randomInt, IEnumerable swapIfIn, int swapFor) { return swapIfIn.Contains(randomInt) ? swapFor : randomInt; } @@ -249,20 +247,14 @@ protected int Swap(int randomInt, IEnumerable swapIfIn, int swapFor) /// /// /// - public object GetRandomDouble(Random r) - { - switch (r.Next(0, 3)) + public static object GetRandomDouble(Random r) => + r.Next(0, 3) switch { - case 0: - return r.Next(100); - case 1: - return Math.Round(r.NextDouble(),2); - case 2: - return r.Next(10) + "." + r.Next(10); - default: - throw new NotImplementedException(); - } - } + 0 => r.Next(100), + 1 => Math.Round(r.NextDouble(), 2), + 2 => $"{r.Next(10)}.{r.Next(10)}", + _ => throw new NotImplementedException() + }; /// /// Returns a random 'GPCode'. This is a letter followed by up to 3 digits. @@ -280,36 +272,26 @@ public string GetRandomGPCode(Random r) /// /// /// - public char GetRandomLetter(bool upperCase,Random r) - { - if(upperCase) - return (char) ('A' + r.Next(0, 26)); - - return (char)('a' + r.Next(0, 26)); - - } + protected static char GetRandomLetter(bool upperCase,Random r) => (char) ((upperCase?'A':'a') + r.Next(0, 26)); /// /// Returns a random 'status' for a CHI or sometimes null. Values include 'C' (current), 'H' (historical), 'L'(legacy?) and 'R'(retracted?) /// /// /// - public object GetRandomCHIStatus(Random r) - { - switch (r.Next(0, 5)) + protected static object GetRandomCHIStatus(Random r) => + r.Next(0, 5) switch { - case 0: return 'C'; - case 1: return 'H'; - case 2: return null; - case 3: return 'L'; - case 4: return 'R'; - default: - throw new ArgumentOutOfRangeException(); - } - } + 0 => 'C', + 1 => 'H', + 2 => null, + 3 => 'L', + 4 => 'R', + _ => throw new ArgumentOutOfRangeException() + }; /// - /// Reads an embedded resource csv file that sits side by side (in terms of namespace) with the . Will also work + /// Reads an embedded resource csv file that sits side by side (in terms of namespace) with the . Will also work /// if you have an embedded resource file called "Aggregates.zip" which contains the . /// /// @@ -320,41 +302,34 @@ public object GetRandomCHIStatus(Random r) /// public static DataTable EmbeddedCsvToDataTable(Type requestingType,string resourceFileName,DataTable dt = null) { - var lookup = GetResourceStream(requestingType,resourceFileName); - - if (lookup == null) - throw new Exception("Could not find embedded resource file " + resourceFileName); - - + var lookup = GetResourceStream(requestingType,resourceFileName) ?? throw new Exception($"Could not find embedded resource file {resourceFileName}"); var toReturn = dt?? new DataTable(); - using (CsvReader r = new CsvReader(new StreamReader(lookup), new CsvConfiguration(CultureInfo.CurrentCulture) with {Delimiter = ","})) - { - r.Read(); - r.ReadHeader(); + using var r = new CsvReader(new StreamReader(lookup), new CsvConfiguration(CultureInfo.CurrentCulture) with {Delimiter = ","}); + r.Read(); + r.ReadHeader(); - foreach (string header in r.HeaderRecord) - if(!toReturn.Columns.Contains(header)) - toReturn.Columns.Add(header); + foreach (var header in r.HeaderRecord) + if(!toReturn.Columns.Contains(header)) + toReturn.Columns.Add(header); - r.Read(); + r.Read(); - do + do + { + var row = toReturn.Rows.Add(); + foreach (DataColumn col in toReturn.Columns) { - var row = toReturn.Rows.Add(); - foreach (DataColumn col in toReturn.Columns) - { - row[col] = r[col.ColumnName]; - } - } while (r.Read()); - } + row[col] = r[col.ColumnName]; + } + } while (r.Read()); return toReturn; } private static Stream GetResourceStream(Type requestingType, string resourceFileName) { - string toFind = requestingType.Namespace + "." + resourceFileName; + var toFind = $"{requestingType.Namespace}.{resourceFileName}"; //is there an unzipped resource available? var toReturn = requestingType.Assembly.GetManifestResourceStream(toFind); @@ -362,10 +337,10 @@ private static Stream GetResourceStream(Type requestingType, string resourceFile if(toReturn == null) { //see if there is a zipped resource file in the namespaces - string toFindZip = requestingType.Namespace + "." + "Aggregates.zip"; + var toFindZip = $"{requestingType.Namespace}.Aggregates.zip"; var zip = requestingType.Assembly.GetManifestResourceStream(toFindZip); - - MemoryStream memoryStream = new MemoryStream(); + + var memoryStream = new MemoryStream(); //containing a file named resourceFileNamed if(zip != null) @@ -379,8 +354,8 @@ private static Stream GetResourceStream(Type requestingType, string resourceFile s.CopyTo(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); return memoryStream; - } - } + } + } } } return toReturn; @@ -391,386 +366,417 @@ private static Stream GetResourceStream(Type requestingType, string resourceFile /// /// /// - public string GetRandomSentence(Random r) + protected static string GetRandomSentence(Random r) { - switch (r.Next(391)) + return r.Next(391) switch { - case 0: return "A mad prize ghosts the attractive romantic."; - case 1: return "I often see the time 11:11 or 12:34 on clocks."; - case 2: return "Malls are great places to shop; I can find everything I need under one roof."; - case 3: return "Christmas is coming."; - case 4: return "I will never be this young again. Ever. Oh damn' I just got older."; - case 5: return "This is a Japanese doll."; - case 6: return "We have never been to Asia, nor have we visited Africa."; - case 7: return "She was too short to see over the fence."; - case 8: return "Hurry!"; - case 9: return "If I don't like something, I'll stay away from it."; - case 10: return "Wednesday is hump day, but has anyone asked the camel if he's happy about it?"; - case 11: return "She folded her handkerchief neatly."; - case 12: return "I checked to make sure that he was still alive."; - case 13: return "He didn't want to go to the dentist, yet he went anyway."; - case 14: return "There was no ice cream in the freezer, nor did they have money to go to the store."; - case 15: return "Sometimes, all you need to do is completely make an ass of yourself and laugh it off to realise that life isn't so bad after all."; - case 16: return "If the Easter Bunny and the Tooth Fairy had babies would they take your teeth and leave chocolate for you?"; - case 17: return "Cats are good pets, for they are clean and are not noisy."; - case 18: return "The body may perhaps compensates for the loss of a true metaphysics."; - case 19: return "Please wait outside of the house."; - case 20: return "The mysterious diary records the voice."; - case 21: return "There were white out conditions in the town; subsequently, the roads were impassable."; - case 22: return "I love eating toasted cheese and tuna sandwiches."; - case 23: return "Two seats were vacant."; - case 24: return "The clock within this blog and the clock on my laptop are 1 hour different from each other."; - case 25: return "She did her best to help him."; - case 26: return "We need to rent a room for our party."; - case 27: return "Someone I know recently combined Maple Syrup & buttered Popcorn thinking it would taste like caramel popcorn. It didn't and they don't recommend anyone else do it either."; - case 28: return "The river stole the gods."; - case 29: return "Joe made the sugar cookies; Susan decorated them."; - case 30: return "He told us a very exciting adventure story."; - case 31: return "He said he was not there yesterday; however, many people saw him there."; - case 32: return "I really want to go to work, but I am too sick to drive."; - case 33: return "A glittering gem is not enough."; - case 34: return "Abstraction is often one floor above you."; - case 35: return "Sometimes it is better to just walk away from things and go back to them later when you're in a better frame of mind."; - case 36: return "Mary plays the piano."; - case 37: return "She did not cheat on the test, for it was not the right thing to do."; - case 38: return "I would have gotten the promotion, but my attendance wasn't good enough."; - case 39: return "I want more detailed information."; - case 40: return "It was getting dark, and we weren't there yet."; - case 41: return "She borrowed the book from him many years ago and hasn't yet returned it."; - case 42: return "I was very proud of my nickname throughout high school but today- I couldn't be any different to what my nickname was."; - case 43: return "Wow, does that work?"; - case 44: return "When I was little I had a car door slammed shut on my hand. I still remember it quite vividly."; - case 45: return "The waves were crashing on the shore; it was a lovely sight."; - case 46: return "If Purple People Eaters are real' where do they find purple people to eat?"; - case 47: return "Where do random thoughts come from?"; - case 48: return "They got there early, and they got really good seats."; - case 49: return "Everyone was busy, so I went to the movie alone."; - case 50: return "I am never at home on Sundays."; - case 51: return "Should we start class now, or should we wait for everyone to get here?"; - case 52: return "The quick brown fox jumps over the lazy dog."; - case 53: return "A song can make or ruin a person's day if they let it get to them."; - case 54: return "I want to buy a onesie' but know it won't suit me."; - case 55: return "Italy is my favorite country; in fact, I plan to spend two weeks there next year."; - case 56: return "I hear that Nancy is very pretty."; - case 57: return "What was the person thinking when they discovered cow's milk was fine for human consumption' and why did they do it in the first place!?"; - case 58: return "She advised him to come back at once."; - case 59: return "He ran out of money, so he had to stop playing poker."; - case 60: return "My Mum tries to be cool by saying that she likes all the same things that I do."; - case 61: return "The sky is clear; the stars are twinkling."; - case 62: return "She works two jobs to make ends meet; at least, that was her reason for not having time to join us."; - case 63: return "I'd rather be a bird than a fish."; - case 64: return "He turned in the research paper on Friday; otherwise, he would have not passed the class."; - case 65: return "The memory we used to share is no longer coherent."; - case 66: return "Lets all be unique together until we realise we are all the same."; - case 67: return "I am happy to take your donation; any amount will be greatly appreciated."; - case 68: return "The old apple revels in its authority."; - case 69: return "Let me help you with your baggage."; - case 70: return "Sixty-Four comes asking for bread."; - case 71: return "I am counting my calories, yet I really want dessert."; - case 72: return "How was the math test?"; - case 73: return "If you like tuna and tomato sauce- try combining the two. It's really not as bad as it sounds."; - case 74: return "Last Friday in three week's time I saw a spotted striped blue worm shake hands with a legless lizard."; - case 75: return "She wrote him a long letter, but he didn't read it."; - case 76: return "Don't step on the broken glass."; - case 77: return "Check back tomorrow; I will see if the book has arrived."; - case 78: return "I currently have 4 windows open up' and I don't know why."; - case 79: return "Tom got a small piece of pie."; - case 80: return "Is it free?"; - case 81: return "She only paints with bold colors; she does not like pastels."; - case 82: return "Yeah, I think it's a good environment for learning English."; - case 83: return "This is the last random sentence I will be writing and I am going to stop mid-sent"; - case 84: return "We have a lot of rain in June."; - case 85: return "She always speaks to him in a loud voice."; - case 86: return "The lake is a long way from here."; - case 87: return "Writing a list of random sentences is harder than I initially thought it would be."; - case 88: return "I think I will buy the red car, or I will lease the blue one."; - case 89: return "A purple pig and a green donkey flew a kite in the middle of the night and ended up sunburnt."; - case 90: return "The stranger officiates the meal."; - case 91: return "The shooter says goodbye to his love."; - case 92: return "The book is in front of the table."; - case 93: return "Rock music approaches at high velocity."; - case 94: return "He told us a very exciting adventure story."; - case 95: return "We have a lot of rain in June."; - case 96: return "Abstraction is often one floor above you."; - case 97: return "I am happy to take your donation; any amount will be greatly appreciated."; - case 98: return "I hear that Nancy is very pretty."; - case 99: return "I want more detailed information."; - case 100: return "Sometimes, all you need to do is completely make an ass of yourself and laugh it off to realise that life isn't so bad after all."; - case 101: return "Italy is my favorite country; in fact, I plan to spend two weeks there next year."; - case 102: return "I currently have 4 windows open up' and I don't know why."; - case 103: return "The shooter says goodbye to his love."; - case 104: return "Everyone was busy, so I went to the movie alone."; - case 105: return "She was too short to see over the fence."; - case 106: return "I think I will buy the red car, or I will lease the blue one."; - case 107: return "Yeah, I think it's a good environment for learning English."; - case 108: return "The book is in front of the table."; - case 109: return "Writing a list of random sentences is harder than I initially thought it would be."; - case 110: return "The clock within this blog and the clock on my laptop are 1 hour different from each other."; - case 111: return "I am never at home on Sundays."; - case 112: return "The quick brown fox jumps over the lazy dog."; - case 113: return "I love eating toasted cheese and tuna sandwiches."; - case 114: return "How was the math test?"; - case 115: return "Rock music approaches at high velocity."; - case 116: return "She advised him to come back at once."; - case 117: return "There were white out conditions in the town; subsequently, the roads were impassable."; - case 118: return "I am counting my calories, yet I really want dessert."; - case 119: return "She did her best to help him."; - case 120: return "The waves were crashing on the shore; it was a lovely sight."; - case 121: return "The lake is a long way from here."; - case 122: return "Lets all be unique together until we realise we are all the same."; - case 123: return "Let me help you with your baggage."; - case 124: return "Someone I know recently combined Maple Syrup & buttered Popcorn thinking it would taste like caramel popcorn. It didn't and they don't recommend anyone else do it either."; - case 125: return "Christmas is coming."; - case 126: return "The stranger officiates the meal."; - case 127: return "Joe made the sugar cookies; Susan decorated them."; - case 128: return "I often see the time 11:11 or 12:34 on clocks."; - case 129: return "Don't step on the broken glass."; - case 130: return "The sky is clear; the stars are twinkling."; - case 131: return "There was no ice cream in the freezer, nor did they have money to go to the store."; - case 132: return "If you like tuna and tomato sauce- try combining the two. It's really not as bad as it sounds."; - case 133: return "If Purple People Eaters are real' where do they find purple people to eat?"; - case 134: return "It was getting dark, and we weren't there yet."; - case 135: return "Where do random thoughts come from?"; - case 136: return "The river stole the gods."; - case 137: return "Last Friday in three week's time I saw a spotted striped blue worm shake hands with a legless lizard."; - case 138: return "Sixty-Four comes asking for bread."; - case 139: return "When I was little I had a car door slammed shut on my hand. I still remember it quite vividly."; - case 140: return "He turned in the research paper on Friday; otherwise, he would have not passed the class."; - case 141: return "She works two jobs to make ends meet; at least, that was her reason for not having time to join us."; - case 142: return "What was the person thinking when they discovered cow's milk was fine for human consumption' and why did they do it in the first place!?"; - case 143: return "He said he was not there yesterday; however, many people saw him there."; - case 144: return "This is the last random sentence I will be writing and I am going to stop mid-sent"; - case 145: return "Check back tomorrow; I will see if the book has arrived."; - case 146: return "I really want to go to work, but I am too sick to drive."; - case 147: return "Mary plays the piano."; - case 148: return "Should we start class now, or should we wait for everyone to get here?"; - case 149: return "They got there early, and they got really good seats."; - case 150: return "A glittering gem is not enough."; - case 151: return "She only paints with bold colors; she does not like pastels."; - case 152: return "The memory we used to share is no longer coherent."; - case 153: return "If I don't like something, I'll stay away from it."; - case 154: return "A song can make or ruin a person's day if they let it get to them."; - case 155: return "My Mum tries to be cool by saying that she likes all the same things that I do."; - case 156: return "She borrowed the book from him many years ago and hasn't yet returned it."; - case 157: return "Hurry!"; - case 158: return "I checked to make sure that he was still alive."; - case 159: return "Two seats were vacant."; - case 160: return "This is a Japanese doll."; - case 161: return "She folded her handkerchief neatly."; - case 162: return "He didn't want to go to the dentist, yet he went anyway."; - case 163: return "I want to buy a onesie' but know it won't suit me."; - case 164: return "Tom got a small piece of pie."; - case 165: return "Please wait outside of the house."; - case 166: return "He ran out of money, so he had to stop playing poker."; - case 167: return "Wow, does that work?"; - case 168: return "I'd rather be a bird than a fish."; - case 169: return "She wrote him a long letter, but he didn't read it."; - case 170: return "We need to rent a room for our party."; - case 171: return "She always speaks to him in a loud voice."; - case 172: return "Malls are great places to shop; I can find everything I need under one roof."; - case 173: return "Cats are good pets, for they are clean and are not noisy."; - case 174: return "We have never been to Asia, nor have we visited Africa."; - case 175: return "Is it free?"; - case 176: return "I will never be this young again. Ever. Oh damn' I just got older."; - case 177: return "I was very proud of my nickname throughout high school but today- I couldn't be any different to what my nickname was."; - case 178: return "The body may perhaps compensates for the loss of a true metaphysics."; - case 179: return "The mysterious diary records the voice."; - case 180: return "I would have gotten the promotion, but my attendance wasn't good enough."; - case 181: return "Wednesday is hump day, but has anyone asked the camel if he's happy about it?"; - case 182: return "If the Easter Bunny and the Tooth Fairy had babies would they take your teeth and leave chocolate for you?"; - case 183: return "Sometimes it is better to just walk away from things and go back to them later when you're in a better frame of mind."; - case 184: return "She did not cheat on the test, for it was not the right thing to do."; - case 185: return "A purple pig and a green donkey flew a kite in the middle of the night and ended up sunburnt."; - case 186: return "The old apple revels in its authority."; - case 187: return "Tom got a small piece of pie."; - case 188: return "I will never be this young again. Ever. Oh damn' I just got older."; - case 189: return "Should we start class now, or should we wait for everyone to get here?"; - case 190: return "He told us a very exciting adventure story."; - case 191: return "They got there early, and they got really good seats."; - case 192: return "The clock within this blog and the clock on my laptop are 1 hour different from each other."; - case 193: return "Two seats were vacant."; - case 194: return "What was the person thinking when they discovered cow's milk was fine for human consumption' and why did they do it in the first place!?"; - case 195: return "Last Friday in three week's time I saw a spotted striped blue worm shake hands with a legless lizard."; - case 196: return "Please wait outside of the house."; - case 197: return "Everyone was busy, so I went to the movie alone."; - case 198: return "Yeah, I think it's a good environment for learning English."; - case 199: return "Someone I know recently combined Maple Syrup & buttered Popcorn thinking it would taste like caramel popcorn. It didn't and they don't recommend anyone else do it either."; - case 200: return "There was no ice cream in the freezer, nor did they have money to go to the store."; - case 201: return "My Mum tries to be cool by saying that she likes all the same things that I do."; - case 202: return "We have never been to Asia, nor have we visited Africa."; - case 203: return "Malls are great places to shop; I can find everything I need under one roof."; - case 204: return "She borrowed the book from him many years ago and hasn't yet returned it."; - case 205: return "I want more detailed information."; - case 206: return "It was getting dark, and we weren't there yet."; - case 207: return "A purple pig and a green donkey flew a kite in the middle of the night and ended up sunburnt."; - case 208: return "The body may perhaps compensates for the loss of a true metaphysics."; - case 209: return "He turned in the research paper on Friday; otherwise, he would have not passed the class."; - case 210: return "How was the math test?"; - case 211: return "She folded her handkerchief neatly."; - case 212: return "She only paints with bold colors; she does not like pastels."; - case 213: return "This is the last random sentence I will be writing and I am going to stop mid-sent"; - case 214: return "The sky is clear; the stars are twinkling."; - case 215: return "I love eating toasted cheese and tuna sandwiches."; - case 216: return "Hurry!"; - case 217: return "The old apple revels in its authority."; - case 218: return "I'd rather be a bird than a fish."; - case 219: return "If I don't like something, I'll stay away from it."; - case 220: return "I currently have 4 windows open up' and I don't know why."; - case 221: return "Abstraction is often one floor above you."; - case 222: return "Wow, does that work?"; - case 223: return "The book is in front of the table."; - case 224: return "Writing a list of random sentences is harder than I initially thought it would be."; - case 225: return "If the Easter Bunny and the Tooth Fairy had babies would they take your teeth and leave chocolate for you?"; - case 226: return "I checked to make sure that he was still alive."; - case 227: return "She always speaks to him in a loud voice."; - case 228: return "I am happy to take your donation; any amount will be greatly appreciated."; - case 229: return "Wednesday is hump day, but has anyone asked the camel if he's happy about it?"; - case 230: return "Italy is my favorite country; in fact, I plan to spend two weeks there next year."; - case 231: return "A glittering gem is not enough."; - case 232: return "Joe made the sugar cookies; Susan decorated them."; - case 233: return "The stranger officiates the meal."; - case 234: return "He said he was not there yesterday; however, many people saw him there."; - case 235: return "Cats are good pets, for they are clean and are not noisy."; - case 236: return "If you like tuna and tomato sauce- try combining the two. It's really not as bad as it sounds."; - case 237: return "Sometimes, all you need to do is completely make an ass of yourself and laugh it off to realise that life isn't so bad after all."; - case 238: return "Christmas is coming."; - case 239: return "Let me help you with your baggage."; - case 240: return "Sixty-Four comes asking for bread."; - case 241: return "I hear that Nancy is very pretty."; - case 242: return "There were white out conditions in the town; subsequently, the roads were impassable."; - case 243: return "The river stole the gods."; - case 244: return "He ran out of money, so he had to stop playing poker."; - case 245: return "I am counting my calories, yet I really want dessert."; - case 246: return "She did not cheat on the test, for it was not the right thing to do."; - case 247: return "This is a Japanese doll."; - case 248: return "She was too short to see over the fence."; - case 249: return "Check back tomorrow; I will see if the book has arrived."; - case 250: return "She advised him to come back at once."; - case 251: return "Don't step on the broken glass."; - case 252: return "I think I will buy the red car, or I will lease the blue one."; - case 253: return "Where do random thoughts come from?"; - case 254: return "She did her best to help him."; - case 255: return "Sometimes it is better to just walk away from things and go back to them later when you're in a better frame of mind."; - case 256: return "The quick brown fox jumps over the lazy dog."; - case 257: return "A song can make or ruin a person's day if they let it get to them."; - case 258: return "I am never at home on Sundays."; - case 259: return "When I was little I had a car door slammed shut on my hand. I still remember it quite vividly."; - case 260: return "I often see the time 11:11 or 12:34 on clocks."; - case 261: return "The waves were crashing on the shore; it was a lovely sight."; - case 262: return "We need to rent a room for our party."; - case 263: return "He didn't want to go to the dentist, yet he went anyway."; - case 264: return "We have a lot of rain in June."; - case 265: return "The lake is a long way from here."; - case 266: return "I really want to go to work, but I am too sick to drive."; - case 267: return "She works two jobs to make ends meet; at least, that was her reason for not having time to join us."; - case 268: return "I want to buy a onesie' but know it won't suit me."; - case 269: return "Mary plays the piano."; - case 270: return "Is it free?"; - case 271: return "The mysterious diary records the voice."; - case 272: return "Lets all be unique together until we realise we are all the same."; - case 273: return "I would have gotten the promotion, but my attendance wasn't good enough."; - case 274: return "The memory we used to share is no longer coherent."; - case 275: return "She wrote him a long letter, but he didn't read it."; - case 276: return "I was very proud of my nickname throughout high school but today- I couldn't be any different to what my nickname was."; - case 277: return "The shooter says goodbye to his love."; - case 278: return "If Purple People Eaters are real' where do they find purple people to eat?"; - case 279: return "Rock music approaches at high velocity."; - case 280: return "I often see the time 11:11 or 12:34 on clocks."; - case 281: return "What was the person thinking when they discovered cow's milk was fine for human consumption' and why did they do it in the first place!?"; - case 282: return "Christmas is coming."; - case 283: return "A song can make or ruin a person's day if they let it get to them."; - case 284: return "Where do random thoughts come from?"; - case 285: return "We have a lot of rain in June."; - case 286: return "The memory we used to share is no longer coherent."; - case 287: return "If the Easter Bunny and the Tooth Fairy had babies would they take your teeth and leave chocolate for you?"; - case 288: return "She advised him to come back at once."; - case 289: return "The mysterious diary records the voice."; - case 290: return "Let me help you with your baggage."; - case 291: return "Mary plays the piano."; - case 292: return "He ran out of money, so he had to stop playing poker."; - case 293: return "She only paints with bold colors; she does not like pastels."; - case 294: return "Everyone was busy, so I went to the movie alone."; - case 295: return "Sixty-Four comes asking for bread."; - case 296: return "Check back tomorrow; I will see if the book has arrived."; - case 297: return "The quick brown fox jumps over the lazy dog."; - case 298: return "Abstraction is often one floor above you."; - case 299: return "I want to buy a onesie' but know it won't suit me."; - case 300: return "Should we start class now, or should we wait for everyone to get here?"; - case 301: return "Lets all be unique together until we realise we are all the same."; - case 302: return "The shooter says goodbye to his love."; - case 303: return "She borrowed the book from him many years ago and hasn't yet returned it."; - case 304: return "I think I will buy the red car, or I will lease the blue one."; - case 305: return "This is a Japanese doll."; - case 306: return "The sky is clear; the stars are twinkling."; - case 307: return "She wrote him a long letter, but he didn't read it."; - case 308: return "I was very proud of my nickname throughout high school but today- I couldn't be any different to what my nickname was."; - case 309: return "She works two jobs to make ends meet; at least, that was her reason for not having time to join us."; - case 310: return "If Purple People Eaters are real' where do they find purple people to eat?"; - case 311: return "She folded her handkerchief neatly."; - case 312: return "She was too short to see over the fence."; - case 313: return "I am counting my calories, yet I really want dessert."; - case 314: return "Joe made the sugar cookies; Susan decorated them."; - case 315: return "A glittering gem is not enough."; - case 316: return "My Mum tries to be cool by saying that she likes all the same things that I do."; - case 317: return "I hear that Nancy is very pretty."; - case 318: return "He turned in the research paper on Friday; otherwise, he would have not passed the class."; - case 319: return "Please wait outside of the house."; - case 320: return "The lake is a long way from here."; - case 321: return "Hurry!"; - case 322: return "He said he was not there yesterday; however, many people saw him there."; - case 323: return "I checked to make sure that he was still alive."; - case 324: return "Someone I know recently combined Maple Syrup & buttered Popcorn thinking it would taste like caramel popcorn. It didn't and they don't recommend anyone else do it either."; - case 325: return "Wednesday is hump day, but has anyone asked the camel if he's happy about it?"; - case 326: return "I will never be this young again. Ever. Oh damn' I just got older."; - case 327: return "He told us a very exciting adventure story."; - case 328: return "This is the last random sentence I will be writing and I am going to stop mid-sent"; - case 329: return "They got there early, and they got really good seats."; - case 330: return "Malls are great places to shop; I can find everything I need under one roof."; - case 331: return "The waves were crashing on the shore; it was a lovely sight."; - case 332: return "If you like tuna and tomato sauce- try combining the two. It's really not as bad as it sounds."; - case 333: return "She did not cheat on the test, for it was not the right thing to do."; - case 334: return "Don't step on the broken glass."; - case 335: return "I currently have 4 windows open up' and I don't know why."; - case 336: return "The clock within this blog and the clock on my laptop are 1 hour different from each other."; - case 337: return "Sometimes it is better to just walk away from things and go back to them later when you're in a better frame of mind."; - case 338: return "Is it free?"; - case 339: return "We have never been to Asia, nor have we visited Africa."; - case 340: return "There were white out conditions in the town; subsequently, the roads were impassable."; - case 341: return "The old apple revels in its authority."; - case 342: return "She always speaks to him in a loud voice."; - case 343: return "We need to rent a room for our party."; - case 344: return "The river stole the gods."; - case 345: return "The body may perhaps compensates for the loss of a true metaphysics."; - case 346: return "The book is in front of the table."; - case 347: return "Tom got a small piece of pie."; - case 348: return "Writing a list of random sentences is harder than I initially thought it would be."; - case 349: return "It was getting dark, and we weren't there yet."; - case 350: return "The stranger officiates the meal."; - case 351: return "I would have gotten the promotion, but my attendance wasn't good enough."; - case 352: return "I love eating toasted cheese and tuna sandwiches."; - case 353: return "I want more detailed information."; - case 354: return "There was no ice cream in the freezer, nor did they have money to go to the store."; - case 355: return "He didn't want to go to the dentist, yet he went anyway."; - case 356: return "Two seats were vacant."; - case 357: return "Last Friday in three week's time I saw a spotted striped blue worm shake hands with a legless lizard."; - case 358: return "Rock music approaches at high velocity."; - case 359: return "Yeah, I think it's a good environment for learning English."; - case 360: return "Sometimes, all you need to do is completely make an ass of yourself and laugh it off to realise that life isn't so bad after all."; - case 361: return "Cats are good pets, for they are clean and are not noisy."; - case 362: return "When I was little I had a car door slammed shut on my hand. I still remember it quite vividly."; - case 363: return "If I don't like something, I'll stay away from it."; - case 364: return "I really want to go to work, but I am too sick to drive."; - case 365: return "A purple pig and a green donkey flew a kite in the middle of the night and ended up sunburnt."; - case 366: return "I am happy to take your donation; any amount will be greatly appreciated."; - case 367: return "I'd rather be a bird than a fish."; - case 368: return "How was the math test?"; - case 369: return "Italy is my favorite country; in fact, I plan to spend two weeks there next year."; - case 370: return "I am never at home on Sundays."; - case 380: return "Wow, does that work?"; - case 390: return "She did her best to help him."; - - default: return null; - } + 0 => "A mad prize ghosts the attractive romantic.", + 1 => "I often see the time 11:11 or 12:34 on clocks.", + 2 => "Malls are great places to shop; I can find everything I need under one roof.", + 3 => "Christmas is coming.", + 4 => "I will never be this young again. Ever. Oh damn' I just got older.", + 5 => "This is a Japanese doll.", + 6 => "We have never been to Asia, nor have we visited Africa.", + 7 => "She was too short to see over the fence.", + 8 => "Hurry!", + 9 => "If I don't like something, I'll stay away from it.", + 10 => "Wednesday is hump day, but has anyone asked the camel if he's happy about it?", + 11 => "She folded her handkerchief neatly.", + 12 => "I checked to make sure that he was still alive.", + 13 => "He didn't want to go to the dentist, yet he went anyway.", + 14 => "There was no ice cream in the freezer, nor did they have money to go to the store.", + 15 => + "Sometimes, all you need to do is completely make an ass of yourself and laugh it off to realise that life isn't so bad after all.", + 16 => + "If the Easter Bunny and the Tooth Fairy had babies would they take your teeth and leave chocolate for you?", + 17 => "Cats are good pets, for they are clean and are not noisy.", + 18 => "The body may perhaps compensates for the loss of a true metaphysics.", + 19 => "Please wait outside of the house.", + 20 => "The mysterious diary records the voice.", + 21 => "There were white out conditions in the town; subsequently, the roads were impassable.", + 22 => "I love eating toasted cheese and tuna sandwiches.", + 23 => "Two seats were vacant.", + 24 => "The clock within this blog and the clock on my laptop are 1 hour different from each other.", + 25 => "She did her best to help him.", + 26 => "We need to rent a room for our party.", + 27 => + "Someone I know recently combined Maple Syrup & buttered Popcorn thinking it would taste like caramel popcorn. It didn't and they don't recommend anyone else do it either.", + 28 => "The river stole the gods.", + 29 => "Joe made the sugar cookies; Susan decorated them.", + 30 => "He told us a very exciting adventure story.", + 31 => "He said he was not there yesterday; however, many people saw him there.", + 32 => "I really want to go to work, but I am too sick to drive.", + 33 => "A glittering gem is not enough.", + 34 => "Abstraction is often one floor above you.", + 35 => + "Sometimes it is better to just walk away from things and go back to them later when you're in a better frame of mind.", + 36 => "Mary plays the piano.", + 37 => "She did not cheat on the test, for it was not the right thing to do.", + 38 => "I would have gotten the promotion, but my attendance wasn't good enough.", + 39 => "I want more detailed information.", + 40 => "It was getting dark, and we weren't there yet.", + 41 => "She borrowed the book from him many years ago and hasn't yet returned it.", + 42 => + "I was very proud of my nickname throughout high school but today- I couldn't be any different to what my nickname was.", + 43 => "Wow, does that work?", + 44 => "When I was little I had a car door slammed shut on my hand. I still remember it quite vividly.", + 45 => "The waves were crashing on the shore; it was a lovely sight.", + 46 => "If Purple People Eaters are real' where do they find purple people to eat?", + 47 => "Where do random thoughts come from?", + 48 => "They got there early, and they got really good seats.", + 49 => "Everyone was busy, so I went to the movie alone.", + 50 => "I am never at home on Sundays.", + 51 => "Should we start class now, or should we wait for everyone to get here?", + 52 => "The quick brown fox jumps over the lazy dog.", + 53 => "A song can make or ruin a person's day if they let it get to them.", + 54 => "I want to buy a onesie' but know it won't suit me.", + 55 => "Italy is my favorite country; in fact, I plan to spend two weeks there next year.", + 56 => "I hear that Nancy is very pretty.", + 57 => + "What was the person thinking when they discovered cow's milk was fine for human consumption' and why did they do it in the first place!?", + 58 => "She advised him to come back at once.", + 59 => "He ran out of money, so he had to stop playing poker.", + 60 => "My Mum tries to be cool by saying that she likes all the same things that I do.", + 61 => "The sky is clear; the stars are twinkling.", + 62 => + "She works two jobs to make ends meet; at least, that was her reason for not having time to join us.", + 63 => "I'd rather be a bird than a fish.", + 64 => "He turned in the research paper on Friday; otherwise, he would have not passed the class.", + 65 => "The memory we used to share is no longer coherent.", + 66 => "Lets all be unique together until we realise we are all the same.", + 67 => "I am happy to take your donation; any amount will be greatly appreciated.", + 68 => "The old apple revels in its authority.", + 69 => "Let me help you with your baggage.", + 70 => "Sixty-Four comes asking for bread.", + 71 => "I am counting my calories, yet I really want dessert.", + 72 => "How was the math test?", + 73 => "If you like tuna and tomato sauce- try combining the two. It's really not as bad as it sounds.", + 74 => + "Last Friday in three week's time I saw a spotted striped blue worm shake hands with a legless lizard.", + 75 => "She wrote him a long letter, but he didn't read it.", + 76 => "Don't step on the broken glass.", + 77 => "Check back tomorrow; I will see if the book has arrived.", + 78 => "I currently have 4 windows open up' and I don't know why.", + 79 => "Tom got a small piece of pie.", + 80 => "Is it free?", + 81 => "She only paints with bold colors; she does not like pastels.", + 82 => "Yeah, I think it's a good environment for learning English.", + 83 => "This is the last random sentence I will be writing and I am going to stop mid-sent", + 84 => "We have a lot of rain in June.", + 85 => "She always speaks to him in a loud voice.", + 86 => "The lake is a long way from here.", + 87 => "Writing a list of random sentences is harder than I initially thought it would be.", + 88 => "I think I will buy the red car, or I will lease the blue one.", + 89 => "A purple pig and a green donkey flew a kite in the middle of the night and ended up sunburnt.", + 90 => "The stranger officiates the meal.", + 91 => "The shooter says goodbye to his love.", + 92 => "The book is in front of the table.", + 93 => "Rock music approaches at high velocity.", + 94 => "He told us a very exciting adventure story.", + 95 => "We have a lot of rain in June.", + 96 => "Abstraction is often one floor above you.", + 97 => "I am happy to take your donation; any amount will be greatly appreciated.", + 98 => "I hear that Nancy is very pretty.", + 99 => "I want more detailed information.", + 100 => + "Sometimes, all you need to do is completely make an ass of yourself and laugh it off to realise that life isn't so bad after all.", + 101 => "Italy is my favorite country; in fact, I plan to spend two weeks there next year.", + 102 => "I currently have 4 windows open up' and I don't know why.", + 103 => "The shooter says goodbye to his love.", + 104 => "Everyone was busy, so I went to the movie alone.", + 105 => "She was too short to see over the fence.", + 106 => "I think I will buy the red car, or I will lease the blue one.", + 107 => "Yeah, I think it's a good environment for learning English.", + 108 => "The book is in front of the table.", + 109 => "Writing a list of random sentences is harder than I initially thought it would be.", + 110 => "The clock within this blog and the clock on my laptop are 1 hour different from each other.", + 111 => "I am never at home on Sundays.", + 112 => "The quick brown fox jumps over the lazy dog.", + 113 => "I love eating toasted cheese and tuna sandwiches.", + 114 => "How was the math test?", + 115 => "Rock music approaches at high velocity.", + 116 => "She advised him to come back at once.", + 117 => "There were white out conditions in the town; subsequently, the roads were impassable.", + 118 => "I am counting my calories, yet I really want dessert.", + 119 => "She did her best to help him.", + 120 => "The waves were crashing on the shore; it was a lovely sight.", + 121 => "The lake is a long way from here.", + 122 => "Lets all be unique together until we realise we are all the same.", + 123 => "Let me help you with your baggage.", + 124 => + "Someone I know recently combined Maple Syrup & buttered Popcorn thinking it would taste like caramel popcorn. It didn't and they don't recommend anyone else do it either.", + 125 => "Christmas is coming.", + 126 => "The stranger officiates the meal.", + 127 => "Joe made the sugar cookies; Susan decorated them.", + 128 => "I often see the time 11:11 or 12:34 on clocks.", + 129 => "Don't step on the broken glass.", + 130 => "The sky is clear; the stars are twinkling.", + 131 => "There was no ice cream in the freezer, nor did they have money to go to the store.", + 132 => "If you like tuna and tomato sauce- try combining the two. It's really not as bad as it sounds.", + 133 => "If Purple People Eaters are real' where do they find purple people to eat?", + 134 => "It was getting dark, and we weren't there yet.", + 135 => "Where do random thoughts come from?", + 136 => "The river stole the gods.", + 137 => + "Last Friday in three week's time I saw a spotted striped blue worm shake hands with a legless lizard.", + 138 => "Sixty-Four comes asking for bread.", + 139 => "When I was little I had a car door slammed shut on my hand. I still remember it quite vividly.", + 140 => "He turned in the research paper on Friday; otherwise, he would have not passed the class.", + 141 => + "She works two jobs to make ends meet; at least, that was her reason for not having time to join us.", + 142 => + "What was the person thinking when they discovered cow's milk was fine for human consumption' and why did they do it in the first place!?", + 143 => "He said he was not there yesterday; however, many people saw him there.", + 144 => "This is the last random sentence I will be writing and I am going to stop mid-sent", + 145 => "Check back tomorrow; I will see if the book has arrived.", + 146 => "I really want to go to work, but I am too sick to drive.", + 147 => "Mary plays the piano.", + 148 => "Should we start class now, or should we wait for everyone to get here?", + 149 => "They got there early, and they got really good seats.", + 150 => "A glittering gem is not enough.", + 151 => "She only paints with bold colors; she does not like pastels.", + 152 => "The memory we used to share is no longer coherent.", + 153 => "If I don't like something, I'll stay away from it.", + 154 => "A song can make or ruin a person's day if they let it get to them.", + 155 => "My Mum tries to be cool by saying that she likes all the same things that I do.", + 156 => "She borrowed the book from him many years ago and hasn't yet returned it.", + 157 => "Hurry!", + 158 => "I checked to make sure that he was still alive.", + 159 => "Two seats were vacant.", + 160 => "This is a Japanese doll.", + 161 => "She folded her handkerchief neatly.", + 162 => "He didn't want to go to the dentist, yet he went anyway.", + 163 => "I want to buy a onesie' but know it won't suit me.", + 164 => "Tom got a small piece of pie.", + 165 => "Please wait outside of the house.", + 166 => "He ran out of money, so he had to stop playing poker.", + 167 => "Wow, does that work?", + 168 => "I'd rather be a bird than a fish.", + 169 => "She wrote him a long letter, but he didn't read it.", + 170 => "We need to rent a room for our party.", + 171 => "She always speaks to him in a loud voice.", + 172 => "Malls are great places to shop; I can find everything I need under one roof.", + 173 => "Cats are good pets, for they are clean and are not noisy.", + 174 => "We have never been to Asia, nor have we visited Africa.", + 175 => "Is it free?", + 176 => "I will never be this young again. Ever. Oh damn' I just got older.", + 177 => + "I was very proud of my nickname throughout high school but today- I couldn't be any different to what my nickname was.", + 178 => "The body may perhaps compensates for the loss of a true metaphysics.", + 179 => "The mysterious diary records the voice.", + 180 => "I would have gotten the promotion, but my attendance wasn't good enough.", + 181 => "Wednesday is hump day, but has anyone asked the camel if he's happy about it?", + 182 => + "If the Easter Bunny and the Tooth Fairy had babies would they take your teeth and leave chocolate for you?", + 183 => + "Sometimes it is better to just walk away from things and go back to them later when you're in a better frame of mind.", + 184 => "She did not cheat on the test, for it was not the right thing to do.", + 185 => "A purple pig and a green donkey flew a kite in the middle of the night and ended up sunburnt.", + 186 => "The old apple revels in its authority.", + 187 => "Tom got a small piece of pie.", + 188 => "I will never be this young again. Ever. Oh damn' I just got older.", + 189 => "Should we start class now, or should we wait for everyone to get here?", + 190 => "He told us a very exciting adventure story.", + 191 => "They got there early, and they got really good seats.", + 192 => "The clock within this blog and the clock on my laptop are 1 hour different from each other.", + 193 => "Two seats were vacant.", + 194 => + "What was the person thinking when they discovered cow's milk was fine for human consumption' and why did they do it in the first place!?", + 195 => + "Last Friday in three week's time I saw a spotted striped blue worm shake hands with a legless lizard.", + 196 => "Please wait outside of the house.", + 197 => "Everyone was busy, so I went to the movie alone.", + 198 => "Yeah, I think it's a good environment for learning English.", + 199 => + "Someone I know recently combined Maple Syrup & buttered Popcorn thinking it would taste like caramel popcorn. It didn't and they don't recommend anyone else do it either.", + 200 => "There was no ice cream in the freezer, nor did they have money to go to the store.", + 201 => "My Mum tries to be cool by saying that she likes all the same things that I do.", + 202 => "We have never been to Asia, nor have we visited Africa.", + 203 => "Malls are great places to shop; I can find everything I need under one roof.", + 204 => "She borrowed the book from him many years ago and hasn't yet returned it.", + 205 => "I want more detailed information.", + 206 => "It was getting dark, and we weren't there yet.", + 207 => "A purple pig and a green donkey flew a kite in the middle of the night and ended up sunburnt.", + 208 => "The body may perhaps compensates for the loss of a true metaphysics.", + 209 => "He turned in the research paper on Friday; otherwise, he would have not passed the class.", + 210 => "How was the math test?", + 211 => "She folded her handkerchief neatly.", + 212 => "She only paints with bold colors; she does not like pastels.", + 213 => "This is the last random sentence I will be writing and I am going to stop mid-sent", + 214 => "The sky is clear; the stars are twinkling.", + 215 => "I love eating toasted cheese and tuna sandwiches.", + 216 => "Hurry!", + 217 => "The old apple revels in its authority.", + 218 => "I'd rather be a bird than a fish.", + 219 => "If I don't like something, I'll stay away from it.", + 220 => "I currently have 4 windows open up' and I don't know why.", + 221 => "Abstraction is often one floor above you.", + 222 => "Wow, does that work?", + 223 => "The book is in front of the table.", + 224 => "Writing a list of random sentences is harder than I initially thought it would be.", + 225 => + "If the Easter Bunny and the Tooth Fairy had babies would they take your teeth and leave chocolate for you?", + 226 => "I checked to make sure that he was still alive.", + 227 => "She always speaks to him in a loud voice.", + 228 => "I am happy to take your donation; any amount will be greatly appreciated.", + 229 => "Wednesday is hump day, but has anyone asked the camel if he's happy about it?", + 230 => "Italy is my favorite country; in fact, I plan to spend two weeks there next year.", + 231 => "A glittering gem is not enough.", + 232 => "Joe made the sugar cookies; Susan decorated them.", + 233 => "The stranger officiates the meal.", + 234 => "He said he was not there yesterday; however, many people saw him there.", + 235 => "Cats are good pets, for they are clean and are not noisy.", + 236 => "If you like tuna and tomato sauce- try combining the two. It's really not as bad as it sounds.", + 237 => + "Sometimes, all you need to do is completely make an ass of yourself and laugh it off to realise that life isn't so bad after all.", + 238 => "Christmas is coming.", + 239 => "Let me help you with your baggage.", + 240 => "Sixty-Four comes asking for bread.", + 241 => "I hear that Nancy is very pretty.", + 242 => "There were white out conditions in the town; subsequently, the roads were impassable.", + 243 => "The river stole the gods.", + 244 => "He ran out of money, so he had to stop playing poker.", + 245 => "I am counting my calories, yet I really want dessert.", + 246 => "She did not cheat on the test, for it was not the right thing to do.", + 247 => "This is a Japanese doll.", + 248 => "She was too short to see over the fence.", + 249 => "Check back tomorrow; I will see if the book has arrived.", + 250 => "She advised him to come back at once.", + 251 => "Don't step on the broken glass.", + 252 => "I think I will buy the red car, or I will lease the blue one.", + 253 => "Where do random thoughts come from?", + 254 => "She did her best to help him.", + 255 => + "Sometimes it is better to just walk away from things and go back to them later when you're in a better frame of mind.", + 256 => "The quick brown fox jumps over the lazy dog.", + 257 => "A song can make or ruin a person's day if they let it get to them.", + 258 => "I am never at home on Sundays.", + 259 => "When I was little I had a car door slammed shut on my hand. I still remember it quite vividly.", + 260 => "I often see the time 11:11 or 12:34 on clocks.", + 261 => "The waves were crashing on the shore; it was a lovely sight.", + 262 => "We need to rent a room for our party.", + 263 => "He didn't want to go to the dentist, yet he went anyway.", + 264 => "We have a lot of rain in June.", + 265 => "The lake is a long way from here.", + 266 => "I really want to go to work, but I am too sick to drive.", + 267 => + "She works two jobs to make ends meet; at least, that was her reason for not having time to join us.", + 268 => "I want to buy a onesie' but know it won't suit me.", + 269 => "Mary plays the piano.", + 270 => "Is it free?", + 271 => "The mysterious diary records the voice.", + 272 => "Lets all be unique together until we realise we are all the same.", + 273 => "I would have gotten the promotion, but my attendance wasn't good enough.", + 274 => "The memory we used to share is no longer coherent.", + 275 => "She wrote him a long letter, but he didn't read it.", + 276 => + "I was very proud of my nickname throughout high school but today- I couldn't be any different to what my nickname was.", + 277 => "The shooter says goodbye to his love.", + 278 => "If Purple People Eaters are real' where do they find purple people to eat?", + 279 => "Rock music approaches at high velocity.", + 280 => "I often see the time 11:11 or 12:34 on clocks.", + 281 => + "What was the person thinking when they discovered cow's milk was fine for human consumption' and why did they do it in the first place!?", + 282 => "Christmas is coming.", + 283 => "A song can make or ruin a person's day if they let it get to them.", + 284 => "Where do random thoughts come from?", + 285 => "We have a lot of rain in June.", + 286 => "The memory we used to share is no longer coherent.", + 287 => + "If the Easter Bunny and the Tooth Fairy had babies would they take your teeth and leave chocolate for you?", + 288 => "She advised him to come back at once.", + 289 => "The mysterious diary records the voice.", + 290 => "Let me help you with your baggage.", + 291 => "Mary plays the piano.", + 292 => "He ran out of money, so he had to stop playing poker.", + 293 => "She only paints with bold colors; she does not like pastels.", + 294 => "Everyone was busy, so I went to the movie alone.", + 295 => "Sixty-Four comes asking for bread.", + 296 => "Check back tomorrow; I will see if the book has arrived.", + 297 => "The quick brown fox jumps over the lazy dog.", + 298 => "Abstraction is often one floor above you.", + 299 => "I want to buy a onesie' but know it won't suit me.", + 300 => "Should we start class now, or should we wait for everyone to get here?", + 301 => "Lets all be unique together until we realise we are all the same.", + 302 => "The shooter says goodbye to his love.", + 303 => "She borrowed the book from him many years ago and hasn't yet returned it.", + 304 => "I think I will buy the red car, or I will lease the blue one.", + 305 => "This is a Japanese doll.", + 306 => "The sky is clear; the stars are twinkling.", + 307 => "She wrote him a long letter, but he didn't read it.", + 308 => + "I was very proud of my nickname throughout high school but today- I couldn't be any different to what my nickname was.", + 309 => + "She works two jobs to make ends meet; at least, that was her reason for not having time to join us.", + 310 => "If Purple People Eaters are real' where do they find purple people to eat?", + 311 => "She folded her handkerchief neatly.", + 312 => "She was too short to see over the fence.", + 313 => "I am counting my calories, yet I really want dessert.", + 314 => "Joe made the sugar cookies; Susan decorated them.", + 315 => "A glittering gem is not enough.", + 316 => "My Mum tries to be cool by saying that she likes all the same things that I do.", + 317 => "I hear that Nancy is very pretty.", + 318 => "He turned in the research paper on Friday; otherwise, he would have not passed the class.", + 319 => "Please wait outside of the house.", + 320 => "The lake is a long way from here.", + 321 => "Hurry!", + 322 => "He said he was not there yesterday; however, many people saw him there.", + 323 => "I checked to make sure that he was still alive.", + 324 => + "Someone I know recently combined Maple Syrup & buttered Popcorn thinking it would taste like caramel popcorn. It didn't and they don't recommend anyone else do it either.", + 325 => "Wednesday is hump day, but has anyone asked the camel if he's happy about it?", + 326 => "I will never be this young again. Ever. Oh damn' I just got older.", + 327 => "He told us a very exciting adventure story.", + 328 => "This is the last random sentence I will be writing and I am going to stop mid-sent", + 329 => "They got there early, and they got really good seats.", + 330 => "Malls are great places to shop; I can find everything I need under one roof.", + 331 => "The waves were crashing on the shore; it was a lovely sight.", + 332 => "If you like tuna and tomato sauce- try combining the two. It's really not as bad as it sounds.", + 333 => "She did not cheat on the test, for it was not the right thing to do.", + 334 => "Don't step on the broken glass.", + 335 => "I currently have 4 windows open up' and I don't know why.", + 336 => "The clock within this blog and the clock on my laptop are 1 hour different from each other.", + 337 => + "Sometimes it is better to just walk away from things and go back to them later when you're in a better frame of mind.", + 338 => "Is it free?", + 339 => "We have never been to Asia, nor have we visited Africa.", + 340 => "There were white out conditions in the town; subsequently, the roads were impassable.", + 341 => "The old apple revels in its authority.", + 342 => "She always speaks to him in a loud voice.", + 343 => "We need to rent a room for our party.", + 344 => "The river stole the gods.", + 345 => "The body may perhaps compensates for the loss of a true metaphysics.", + 346 => "The book is in front of the table.", + 347 => "Tom got a small piece of pie.", + 348 => "Writing a list of random sentences is harder than I initially thought it would be.", + 349 => "It was getting dark, and we weren't there yet.", + 350 => "The stranger officiates the meal.", + 351 => "I would have gotten the promotion, but my attendance wasn't good enough.", + 352 => "I love eating toasted cheese and tuna sandwiches.", + 353 => "I want more detailed information.", + 354 => "There was no ice cream in the freezer, nor did they have money to go to the store.", + 355 => "He didn't want to go to the dentist, yet he went anyway.", + 356 => "Two seats were vacant.", + 357 => + "Last Friday in three week's time I saw a spotted striped blue worm shake hands with a legless lizard.", + 358 => "Rock music approaches at high velocity.", + 359 => "Yeah, I think it's a good environment for learning English.", + 360 => + "Sometimes, all you need to do is completely make an ass of yourself and laugh it off to realise that life isn't so bad after all.", + 361 => "Cats are good pets, for they are clean and are not noisy.", + 362 => "When I was little I had a car door slammed shut on my hand. I still remember it quite vividly.", + 363 => "If I don't like something, I'll stay away from it.", + 364 => "I really want to go to work, but I am too sick to drive.", + 365 => "A purple pig and a green donkey flew a kite in the middle of the night and ended up sunburnt.", + 366 => "I am happy to take your donation; any amount will be greatly appreciated.", + 367 => "I'd rather be a bird than a fish.", + 368 => "How was the math test?", + 369 => "Italy is my favorite country; in fact, I plan to spend two weeks there next year.", + 370 => "I am never at home on Sundays.", + 380 => "Wow, does that work?", + 390 => "She did her best to help him.", + _ => null + }; } /// @@ -851,7 +857,7 @@ public static void WriteLookups(DirectoryInfo dir) 2,Reversed 3,Not Detected 4,See report text"); - + File.WriteAllText(Path.Combine(dir.FullName, "z_StenosisLookup.csv"), @"Code,CodeValueDescription 1,Normal @@ -861,7 +867,7 @@ public static void WriteLookups(DirectoryInfo dir) 5,Occluded 9,Not seen 6,See report text"); - + File.WriteAllText(Path.Combine(dir.FullName, "z_PlaqueLookup.csv"), @"Code,CodeValueDescription 1,I @@ -1036,7 +1042,7 @@ public static void WriteLookups(DirectoryInfo dir) T7,Sick children's nursing T8,Nursery nursing XSU,Unspecified -XX,Others" +XX,Others" ); diff --git a/BadMedicine.Core/Datasets/Demography.cs b/BadMedicine.Core/Datasets/Demography.cs index dd6b8b9..63b4bae 100644 --- a/BadMedicine.Core/Datasets/Demography.cs +++ b/BadMedicine.Core/Datasets/Demography.cs @@ -20,19 +20,19 @@ public Demography(Random rand) : base(rand) /// public override object[] GenerateTestDataRow(Person person) { - //leave off data load run ID + //leave off data load run ID var values = new object[39]; - + values[0] = person.CHI; values[1] = GetRandomDateAfter(person.DateOfBirth,r);//all records must have been created after the person was born - + if(r.Next(0, 2) == 0) values[2] = true; else values[2] = false; values[3] = "Random record"; - + if(r.Next(0,10 )== 0)//one in 10 records has one of these (an ALIAS chi) values[4] = person.GetRandomCHI(r); @@ -44,8 +44,8 @@ public override object[] GenerateTestDataRow(Person person) var randomAddress = new DemographyAddress(r); - - //if person is dead and dtCreated is after they died use the same address otehrwise use a random one (all records after a person dies have same address) + + //if person is dead and dtCreated is after they died use the same address otherwise use a random one (all records after a person dies have same address) values[10] = person.DateOfDeath != null && (DateTime)values[1]>person.DateOfDeath ? person.Address.Line1: randomAddress.Line1; values[11] = person.DateOfDeath != null && (DateTime)values[1]>person.DateOfDeath ? person.Address.Line2: randomAddress.Line2; values[12] = person.DateOfDeath != null && (DateTime)values[1]>person.DateOfDeath ? person.Address.Line3: randomAddress.Line3; @@ -54,11 +54,11 @@ public override object[] GenerateTestDataRow(Person person) //if the person is dead and the dtCreated of the record is greater than the date of death populate it values[15] = person.GetDateOfDeathOrNullOn((DateTime)values[1]); //pass record creation date and get isdead date back - + //if we got a date put the source in as R if(values[15] != null) values[16] = 'R'; - + if(!string.IsNullOrWhiteSpace(person.Address.Postcode.District)) values[17] = person.Address.Postcode.District.Substring(0, 1); @@ -69,12 +69,12 @@ public override object[] GenerateTestDataRow(Person person) if((char)values[18] == 'A') if (values[8] != null) while (values[8].ToString().Length < 10) - values[8] = values[8] + " "; + values[8] = $"{values[8]} "; - //in healthboard 'B' they give us both forename and suranme in the same field! - and surname is always blank + //in healthboard 'B' they give us both forename and surname in the same field! - and surname is always blank if ((char)values[18] == 'B') { - values[8] = values[8] + " " +values[7]; + values[8] = $"{values[8]} {values[7]}"; values[7] = null; } @@ -85,10 +85,10 @@ public override object[] GenerateTestDataRow(Person person) values[20] = Person.GetRandomSurname(r); if (r.Next(0, 10) == 0) values[21] = Person.GetRandomSurname(r); - + if (r.Next(0, 3) == 0) values[22] = person.GetRandomForename(r); //random gender appropriate middle name for 1 person in 3 - + if (r.Next(0, 5) == 0) values[23] = person.GetRandomForename(r); //alternate forename @@ -117,8 +117,8 @@ public override object[] GenerateTestDataRow(Person person) //an always null field, why not?! values[31] = null; - DateTime gp_accept_date = GetRandomDateAfter(person.DateOfBirth, r); - + var gp_accept_date = GetRandomDateAfter(person.DateOfBirth, r); + //current_gp_accept_date values[32] = gp_accept_date; @@ -127,7 +127,7 @@ public override object[] GenerateTestDataRow(Person person) if (gp_accept_date.Year < 1980) if (r.Next(gp_accept_date.Year - Person.MinimumYearOfBirth) == 0)//the farther back you go the more likely they are to be missing a forename values[8] = null;//some people are randomly missing a forename - + if(r.Next(0,3)==0) { values[33] = GetRandomGPCode(r); diff --git a/BadMedicine.Core/Datasets/DemographyAddress.cs b/BadMedicine.Core/Datasets/DemographyAddress.cs index ce667cc..70a0a13 100644 --- a/BadMedicine.Core/Datasets/DemographyAddress.cs +++ b/BadMedicine.Core/Datasets/DemographyAddress.cs @@ -49,7 +49,7 @@ public DemographyAddress(Random r) //1 in 10 houses does not have a house number if (r.Next(0, 10) != 0) - Line1 = r.Next(0, 100) + " " + Line1; + Line1 = $"{r.Next(0, 100)} {Line1}"; Postcode = DundeePostcodes[r.Next(0, DundeePostcodes.Length)]; diff --git a/BadMedicine.Core/Datasets/HospitalAdmissionsRecord.cs b/BadMedicine.Core/Datasets/HospitalAdmissionsRecord.cs index 050f38e..6acf5bd 100644 --- a/BadMedicine.Core/Datasets/HospitalAdmissionsRecord.cs +++ b/BadMedicine.Core/Datasets/HospitalAdmissionsRecord.cs @@ -12,7 +12,7 @@ namespace BadMedicine.Datasets { /// /// Random record for when a entered hospital. Basic logic is implemented here to ensure that - /// is after and that the person was alive at the time. + /// is after and that the person was alive at the time. /// public class HospitalAdmissionsRecord { @@ -36,7 +36,7 @@ public class HospitalAdmissionsRecord /// public string OtherCondition3 { get; private set; } - + /// public string MainOperation {get;private set;} @@ -68,7 +68,7 @@ public class HospitalAdmissionsRecord static object oLockInitialize = new object(); private static bool initialized = false; - + /// /// Maps ColumnAppearingIn to each month we might want to generate random data in (Between and ) /// to the row numbers which were active at that time (based on AverageMonthAppearing and StandardDeviationMonthAppearing) @@ -81,7 +81,7 @@ public class HospitalAdmissionsRecord private static BucketList ICD10Rows; /// - /// Maps a given MAIN_CONDITION code (doesn't cover other conditons) to popular operations for that condition. The string array is always length 8 and corresponds to + /// Maps a given MAIN_CONDITION code (doesn't cover other conditions) to popular operations for that condition. The string array is always length 8 and corresponds to /// MAIN_OPERATION,MAIN_OPERATION_B,OTHER_OPERATION_1,OTHER_OPERATION_1B,OTHER_OPERATION_2,OTHER_OPERATION_2B,OTHER_OPERATION_3,OTHER_OPERATION_3B /// private static Dictionary> ConditionsToOperationsMap = new Dictionary>(); @@ -97,7 +97,7 @@ public class HospitalAdmissionsRecord public static readonly DateTime MaximumDate = new DateTime(2018,1,1); /// - /// Creates a new record for the given + /// Creates a new record for the given /// /// /// @@ -114,9 +114,9 @@ public HospitalAdmissionsRecord(Person person, DateTime afterDateX, Random r) Person = person; if (person.DateOfBirth > afterDateX) afterDateX = person.DateOfBirth; - + AdmissionDate = DataGenerator.GetRandomDate(afterDateX.Max(MinimumDate), MaximumDate, r); - + DischargeDate = AdmissionDate.AddHours(r.Next(240));//discharged after random number of hours between 0 and 240 = 10 days //Condition 1 always populated @@ -131,7 +131,7 @@ public HospitalAdmissionsRecord(Person person, DateTime afterDateX, Random r) if (r.Next(2) == 0) { OtherCondition2 = GetRandomICDCode("OTHER_CONDITION_2",r); - + //12.5% chance of all conditions if (r.Next(2) == 0) OtherCondition3 = GetRandomICDCode("OTHER_CONDITION_3",r); @@ -147,7 +147,7 @@ public HospitalAdmissionsRecord(Person person, DateTime afterDateX, Random r) if(ConditionsToOperationsMap.TryGetValue(MainCondition,out var operationsList)) { var operations = operationsList.GetRandom(r); - + MainOperation = operations[0]; MainOperationB = operations[1]; OtherOperation1 = operations[2]; @@ -163,13 +163,13 @@ private void Initialize() { ICD10Rows = new BucketList(); - DataTable dt = new DataTable(); + var dt = new DataTable(); dt.Columns.Add("AverageMonthAppearing", typeof(double)); dt.Columns.Add("StandardDeviationMonthAppearing", typeof(double)); dt.Columns.Add("CountAppearances", typeof(int)); lookupTable = DataGenerator.EmbeddedCsvToDataTable(typeof(HospitalAdmissionsRecord), "HospitalAdmissions.csv",dt); - + ICD10MonthHashMap = new Dictionary>> { {"MAIN_CONDITION", new Dictionary>()}, @@ -182,44 +182,44 @@ private void Initialize() //The number of months since 1/1/1900 (this is the measure of field AverageMonthAppearing) //get all the months we might be asked for - int from = (MinimumDate.Year - 1900) * 12 + MinimumDate.Month; - int to = (MaximumDate.Year - 1900) * 12 + MaximumDate.Month; + var from = (MinimumDate.Year - 1900) * 12 + MinimumDate.Month; + var to = (MaximumDate.Year - 1900) * 12 + MaximumDate.Month; foreach (var columnKey in ICD10MonthHashMap.Keys) { - for (int i = from; i <= to; i++) + for (var i = from; i <= to; i++) { ICD10MonthHashMap[columnKey].Add(i, new List()); } } - int rowCount = 0; + var rowCount = 0; //for each row in the sample data foreach (DataRow row in lookupTable.Rows) { //calculate 2 standard deviations in months - int monthFrom = Convert.ToInt32((double) row["AverageMonthAppearing"] - (2 * (double) row["StandardDeviationMonthAppearing"])); - int monthTo = Convert.ToInt32((double) row["AverageMonthAppearing"] + (2 * (double) row["StandardDeviationMonthAppearing"])); + var monthFrom = Convert.ToInt32((double) row["AverageMonthAppearing"] - (2 * (double) row["StandardDeviationMonthAppearing"])); + var monthTo = Convert.ToInt32((double) row["AverageMonthAppearing"] + (2 * (double) row["StandardDeviationMonthAppearing"])); //2 standard deviations might take us beyond the beginning or start so only build hashmap for dates we will be asked for monthFrom = Math.Max(monthFrom, from); monthTo = Math.Min(monthTo, to); //for each month add row to the hashmap (for the correct column and month in the range) - for (int i = monthFrom; i <= monthTo; i++) + for (var i = monthFrom; i <= monthTo; i++) { if(monthFrom < from) continue; if(monthTo > to) break; - + ICD10MonthHashMap[(string)row["ColumnAppearingIn"]][i].Add(rowCount); } - ICD10Rows.Add((int) row["CountAppearances"], (string) row["TestCode"]); + ICD10Rows.Add((int) row["CountAppearances"], (string) row["TestCode"]); rowCount++; } @@ -227,15 +227,15 @@ private void Initialize() operationsTable.Columns.Add("CountOfRecords",typeof(int)); DataGenerator.EmbeddedCsvToDataTable(typeof(HospitalAdmissionsRecord),"HospitalAdmissionsOperations.csv",operationsTable); - + foreach(DataRow r in operationsTable.Rows) { - string key = (string)r["MAIN_CONDITION"]; + var key = (string)r["MAIN_CONDITION"]; if(!ConditionsToOperationsMap.ContainsKey(key)) { ConditionsToOperationsMap.Add(key,new BucketList()); - ConditionsToOperationsMap[key].Add((int)r["CountOfRecords"],new []{ + ConditionsToOperationsMap[key].Add((int)r["CountOfRecords"],new []{ r["MAIN_OPERATION"] as string, r["MAIN_OPERATION_B"] as string, r["OTHER_OPERATION_1"] as string, @@ -248,13 +248,13 @@ private void Initialize() } } } - + private string GetRandomICDCode(string field, Random random) { - + //The number of months since 1/1/1900 (this is the measure of field AverageMonthAppearing) - int monthsSinceZeroDay = (AdmissionDate.Year - 1900) * 12 + AdmissionDate.Month; + var monthsSinceZeroDay = (AdmissionDate.Year - 1900) * 12 + AdmissionDate.Month; return ICD10Rows.GetRandom(ICD10MonthHashMap[field][monthsSinceZeroDay],random); } diff --git a/BadMedicine.Core/Datasets/Maternity.cs b/BadMedicine.Core/Datasets/Maternity.cs index ff479f0..5cf3b8c 100644 --- a/BadMedicine.Core/Datasets/Maternity.cs +++ b/BadMedicine.Core/Datasets/Maternity.cs @@ -35,11 +35,11 @@ public override object[] GenerateTestDataRow(Person p) { var record = new MaternityRecord(p,r); - object[] results = new object[12]; - + var results = new object[12]; + results[0] = p.CHI; results[1] = r.Next(2) == 0 ? 'T': 'F'; - + results[2] = record.Date; // Partner CHI diff --git a/BadMedicine.Core/Datasets/MaternityRecord.cs b/BadMedicine.Core/Datasets/MaternityRecord.cs index 17cfc89..3d637c3 100644 --- a/BadMedicine.Core/Datasets/MaternityRecord.cs +++ b/BadMedicine.Core/Datasets/MaternityRecord.cs @@ -19,10 +19,10 @@ public class MaternityRecord private static BucketList _maritalStatusOld = new BucketList(); private static BucketList _maritalStatusNew = new BucketList(); private static BucketList _specialties = new BucketList(); - + /// public string Location {get;set;} - + /// public string SendingLocation {get;set;} @@ -44,7 +44,7 @@ public class MaternityRecord /// Chi numbers of up to 3 babies involved. Always contains 3 elements with nulls e.g. if twins then first 2 elements are populated and third is null. /// public string[] BabyChi { get; } = new string[3]; - + /// /// The date at which the data collector stopped using numeric marital status codes (in favour of alphabetical) @@ -54,7 +54,7 @@ public class MaternityRecord /// /// Generates a new random biochemistry test. /// - /// The person who is undergoing maternity activity. Should be Female and of a sufficient age that the operation could have taken place during thier lifetime (see + /// The person who is undergoing maternity activity. Should be Female and of a sufficient age that the operation could have taken place during their lifetime (see /// public MaternityRecord(Person p,Random r) { @@ -65,10 +65,10 @@ public MaternityRecord(Person p,Random r) initialized = true; } Person = p; - + var youngest = p.DateOfBirth.AddYears(MinAge); var oldest = p.DateOfDeath ?? p.DateOfBirth.AddYears(MaxAge); - + // No future dates oldest = oldest > DataGenerator.Now ? DataGenerator.Now : oldest; @@ -80,7 +80,7 @@ public MaternityRecord(Person p,Random r) MaritalStatus = Date < MaritalStatusSwitchover ? _maritalStatusOld.GetRandom(r) : _maritalStatusNew.GetRandom(r); BabyChi[0] = new Person(r){DateOfBirth = Date }.GetRandomCHI(r); - + // One in 30 are twins if(r.Next(30) == 0) { @@ -96,7 +96,7 @@ public MaternityRecord(Person p,Random r) private void Initialize() { - using (DataTable dt = new DataTable()) + using (var dt = new DataTable()) { DataGenerator.EmbeddedCsvToDataTable(typeof(Maternity), "Maternity.csv", dt); @@ -113,7 +113,7 @@ private void Initialize() private void AddRow(DataRow row, string key, BucketList bucketList) { var val = Convert.ToString(row[key]); - var freq = row[key + "_RecordCount"]; + var freq = row[$"{key}_RecordCount"]; if(string.IsNullOrWhiteSpace(freq.ToString())) return; diff --git a/BadMedicine.Core/Datasets/Prescribing.cs b/BadMedicine.Core/Datasets/Prescribing.cs index 6302fb1..4cabdb3 100644 --- a/BadMedicine.Core/Datasets/Prescribing.cs +++ b/BadMedicine.Core/Datasets/Prescribing.cs @@ -24,10 +24,10 @@ public Prescribing(Random rand) : base(rand) /// public override object[] GenerateTestDataRow(Person p) { - object[] values = new object[12]; + var values = new object[12]; + + var prescription = new PrescribingRecord(r); - PrescribingRecord prescription = new PrescribingRecord(r); - values[0] = p.CHI; values[1] = p.GetRandomDateDuringLifetime(r); values[2] = prescription.Quantity; diff --git a/BadMedicine.Core/Datasets/PrescribingRecord.cs b/BadMedicine.Core/Datasets/PrescribingRecord.cs index f70194d..219384a 100644 --- a/BadMedicine.Core/Datasets/PrescribingRecord.cs +++ b/BadMedicine.Core/Datasets/PrescribingRecord.cs @@ -18,7 +18,7 @@ namespace BadMedicine.Datasets public class PrescribingRecord { /// - /// every row in data table has a weigth (the number of records in our bichemistry with this sample type, this dictionary lets you input + /// every row in data table has a weight (the number of records in our biochemistry with this sample type, this dictionary lets you input /// a record number 0-maxWeight and be returned an appropriate row from the table based on its weighting /// private static Dictionary weightToRow; @@ -28,17 +28,17 @@ public class PrescribingRecord static PrescribingRecord() { lookupTable = DataGenerator.EmbeddedCsvToDataTable(typeof(PrescribingRecord),"Prescribing.csv"); - + weightToRow = new Dictionary(); - int currentWeight = 0; - for (int i = 0; i < lookupTable.Rows.Count; i++) + var currentWeight = 0; + for (var i = 0; i < lookupTable.Rows.Count; i++) { - int frequency = int.Parse(lookupTable.Rows[i]["frequency"].ToString()); - + var frequency = int.Parse(lookupTable.Rows[i]["frequency"].ToString()); + if(frequency == 0) continue; - + currentWeight += frequency; weightToRow.Add(currentWeight, i); @@ -54,7 +54,7 @@ static PrescribingRecord() public PrescribingRecord(Random r) { //get a random row from the lookup table - based on its representation within our biochemistry dataset - DataRow row = GetRandomRowUsingWeight(r); + var row = GetRandomRowUsingWeight(r); ResSeqNo = row["res_seqno"].ToString(); Name = row["name"].ToString(); @@ -82,11 +82,11 @@ public PrescribingRecord(Random r) private DataRow GetRandomRowUsingWeight(Random r) { - int weightToGet = r.Next(maxWeight); + var weightToGet = r.Next(maxWeight); //get the first key with a cumulative frequency above the one you are trying to get - int row = weightToRow.First(kvp => kvp.Key > weightToGet).Value; - + var row = weightToRow.First(kvp => kvp.Key > weightToGet).Value; + return lookupTable.Rows[row]; } diff --git a/BadMedicine.Core/Datasets/Wide.cs b/BadMedicine.Core/Datasets/Wide.cs index 1913991..24bd299 100644 --- a/BadMedicine.Core/Datasets/Wide.cs +++ b/BadMedicine.Core/Datasets/Wide.cs @@ -43,7 +43,7 @@ protected override string[] GetHeaders() var array = new string[980]; array[0] = "id"; array[1] = "chi"; - + for (var i = 2; i < array.Length; i++) { array[i] = $"col{i}"; diff --git a/BadMedicine.Core/Descriptions.cs b/BadMedicine.Core/Descriptions.cs index 3b5bc19..ea3d93b 100644 --- a/BadMedicine.Core/Descriptions.cs +++ b/BadMedicine.Core/Descriptions.cs @@ -44,15 +44,15 @@ public IEnumerable> GetAll() public IEnumerable> GetAll(string dataset) { var ds = _doc.Root?.Element(_ns + dataset); - + if(ds == null) yield break; foreach(var x in ds.Elements(_ns + "Field")) yield return new KeyValuePair(x.Attribute(_ns + "name").Value,x.Value); } - - + + /// /// Returns the description of the dataset (or null if no metadata exists) /// @@ -62,7 +62,7 @@ public string Get(string dataset) { return _doc.Root?.Element(_ns + dataset)?.Element(_ns + "summary")?.Value; } - + /// /// Returns the description of the dataset (or null if no metadata exists) @@ -81,7 +81,7 @@ public string Get() where T:IDataGenerator /// /// public string Get(string field) where T:IDataGenerator - { + { return Get(typeof(T).Name,field); } @@ -92,14 +92,14 @@ public string Get(string field) where T:IDataGenerator /// /// public string Get(string dataset,string field) - { - return + { + return //return from the dataset fields _doc.Root.Element(_ns + dataset)?.Elements(_ns + "Field")? - + //the one whose name attribute matches .SingleOrDefault(e=>string.Equals(e.Attribute(_ns + "name")?.Value,field,StringComparison.CurrentCultureIgnoreCase))?.Value - + //or from Common if it's not in the dataset. ?? (dataset != "Common" ? Get("Common",field):null); //null if we are already trying Common diff --git a/BadMedicine.Core/IPersonCollection.cs b/BadMedicine.Core/IPersonCollection.cs index c583f4e..caa64fb 100644 --- a/BadMedicine.Core/IPersonCollection.cs +++ b/BadMedicine.Core/IPersonCollection.cs @@ -25,6 +25,6 @@ public interface IPersonCollection /// Number of to generate /// The seed upon which to generate data void GeneratePeople(int numberOfUniqueIndividuals, Random random ); - + } } \ No newline at end of file diff --git a/BadMedicine.Core/Person.cs b/BadMedicine.Core/Person.cs index fb7045f..f4baab1 100644 --- a/BadMedicine.Core/Person.cs +++ b/BadMedicine.Core/Person.cs @@ -5,7 +5,6 @@ // You should have received a copy of the GNU General Public License along with RDMP. If not, see . using System; -using System.Collections.Generic; using System.Text; using BadMedicine.Datasets; @@ -16,7 +15,7 @@ namespace BadMedicine /// public class Person : IEquatable { - + /// public string Forename { get; set; } /// @@ -29,14 +28,14 @@ public class Person : IEquatable public DateTime DateOfBirth = new DateTime(); /// public DateTime? DateOfDeath; - + /// public char Gender { get; set; } /// public DemographyAddress Address { get; set; } /// public DemographyAddress PreviousAddress { get; set; } - + public const int MinimumYearOfBirth = 1914; public const int MaximumYearOfBirth = 2014; @@ -76,7 +75,7 @@ public Person(Random r) Surname = GetRandomSurname(r); DateOfBirth = DataGenerator.GetRandomDate(new DateTime(MinimumYearOfBirth,1,1),new DateTime(MaximumYearOfBirth,1,1),r); - + //1 in 10 patients is dead if (r.Next(10) == 0) DateOfDeath = DataGenerator.GetRandomDateAfter(DateOfBirth, r); @@ -126,9 +125,9 @@ public static string GetRandomSurname(Random r) { return CommonSurnames[r.Next(100)]; } - + /// - /// If the person died before onDate it returns NULL (as of onDate we did not know when the person would die). if onDate is > date of death it + /// If the person died before onDate it returns NULL (as of onDate we did not know when the person would die). if onDate is > date of death it /// returns the date of death (we knew when they died - you cannot predict the future but you can remember the past) /// /// @@ -138,7 +137,7 @@ public static string GetRandomSurname(Random r) //patient is alive today if (DateOfDeath == null) return null; - + //retrospective if (onDate >= DateOfDeath) return DateOfDeath; @@ -157,8 +156,8 @@ private string GetNovelANOCHI(Random r) var anochi = GenerateANOCHI(r); while(_parent != null && _parent.AlreadyGeneratedANOCHIs.Contains(anochi)) - anochi = GenerateANOCHI(r); - + anochi = GenerateANOCHI(r); + return anochi; } @@ -173,8 +172,8 @@ private string GetNovelCHI(Random r) var chi = GetRandomCHI(r); while(_parent != null && _parent.AlreadyGeneratedCHIs.Contains(chi)) - chi = GetRandomCHI(r); - + chi = GetRandomCHI(r); + return chi; } @@ -182,7 +181,7 @@ private string GenerateANOCHI(Random r) { var toreturn = new StringBuilder(); - for (int i = 0; i < 10; i++) + for (var i = 0; i < 10; i++) toreturn.Append(r.Next(10)); toreturn.Append("_A"); @@ -197,9 +196,9 @@ private string GenerateANOCHI(Random r) /// public string GetRandomCHI( Random r) { - string toreturn = DateOfBirth.ToString("ddMMyy" + r.Next(10, 99)); + var toreturn = DateOfBirth.ToString($"ddMMyy{r.Next(10, 99)}"); - int genderDigit = r.Next(10); + var genderDigit = r.Next(10); switch (Gender) { @@ -213,7 +212,7 @@ public string GetRandomCHI( Random r) break; } - int checkDigit = r.Next(0, 9); + var checkDigit = r.Next(0, 9); return toreturn + genderDigit + checkDigit; } @@ -233,20 +232,7 @@ public override bool Equals(object obj) return Equals((Person) obj); } - public override int GetHashCode() - { - unchecked - { - var hashCode = (Forename != null ? Forename.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (Surname != null ? Surname.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (CHI != null ? CHI.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (ANOCHI != null ? ANOCHI.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ Gender.GetHashCode(); - hashCode = (hashCode * 397) ^ (Address != null ? Address.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (PreviousAddress != null ? PreviousAddress.GetHashCode() : 0); - return hashCode; - } - } + public override int GetHashCode() => HashCode.Combine(Forename, Surname, CHI, ANOCHI, Gender, Address, PreviousAddress); private static readonly string[] CommonGirlForenames = new[] { diff --git a/BadMedicine.Core/PersonCollection.cs b/BadMedicine.Core/PersonCollection.cs index 1cf04c7..5e717b7 100644 --- a/BadMedicine.Core/PersonCollection.cs +++ b/BadMedicine.Core/PersonCollection.cs @@ -23,7 +23,7 @@ public void GeneratePeople(int numberOfUniqueIndividuals, Random random) { People = new Person[numberOfUniqueIndividuals]; - for (int i = 0; i < numberOfUniqueIndividuals; i++) + for (var i = 0; i < numberOfUniqueIndividuals; i++) People[i]=new Person(random,this); } } diff --git a/BadMedicine/BadMedicine.csproj b/BadMedicine/BadMedicine.csproj index b154de3..0659d60 100644 --- a/BadMedicine/BadMedicine.csproj +++ b/BadMedicine/BadMedicine.csproj @@ -1,14 +1,12 @@ - net6.0 + net7.0 true false - Exe BadMedicine.Program false - true embedded @@ -34,7 +32,7 @@ - + diff --git a/BadMedicine/Configuration/Config.cs b/BadMedicine/Configuration/Config.cs index de3e46c..df51fc1 100644 --- a/BadMedicine/Configuration/Config.cs +++ b/BadMedicine/Configuration/Config.cs @@ -1,7 +1,6 @@ -namespace BadMedicine.Configuration +namespace BadMedicine.Configuration; + +class Config { - class Config - { - public TargetDatabase Database { get;set; } - } + public TargetDatabase Database { get;set; } } \ No newline at end of file diff --git a/BadMedicine/Configuration/TargetDatabase.cs b/BadMedicine/Configuration/TargetDatabase.cs index 0af8613..0561aa7 100644 --- a/BadMedicine/Configuration/TargetDatabase.cs +++ b/BadMedicine/Configuration/TargetDatabase.cs @@ -1,30 +1,29 @@ using FAnsi; -namespace BadMedicine.Configuration +namespace BadMedicine.Configuration; + +/// +/// Identify the target database and configuration for generated data +/// +public class TargetDatabase { /// - /// Identify the target database and configuration for generated data + /// Which RDBMS the database is (MySQL, Microsoft SQL Server, etc) + /// + public DatabaseType DatabaseType { get; set; } + /// + /// The ConnectionString containing the server name, credentials and other parameters for the connection + /// + public string ConnectionString { get; set; } + + /// + /// The name of database + /// + public string DatabaseName { get; set; } + + /// + /// Set to true to drop and recreate tables described in the Template /// - public class TargetDatabase - { - /// - /// Which RDBMS the database is (MySQL, Microsoft SQL Server, etc) - /// - public DatabaseType DatabaseType { get; set; } - /// - /// The ConnectionString containing the server name, credentials and other parameters for the connection - /// - public string ConnectionString { get; set; } - - /// - /// The name of database - /// - public string DatabaseName { get; set; } - - /// - /// Set to true to drop and recreate tables described in the Template - /// - public bool DropTables { get; set; } + public bool DropTables { get; set; } - } -} +} \ No newline at end of file diff --git a/BadMedicine/Program.cs b/BadMedicine/Program.cs index 4f3b0d0..8eb1615 100644 --- a/BadMedicine/Program.cs +++ b/BadMedicine/Program.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; -using System.Text; using BadMedicine.Configuration; using BadMedicine.Datasets; using CommandLine; @@ -15,194 +13,194 @@ using FAnsi.Implementations.PostgreSql; using YamlDotNet.Serialization; -namespace BadMedicine +namespace BadMedicine; + +class Program { - class Program + private static int returnCode; + public const string ConfigFile = "./BadMedicine.yaml"; + + public static int Main(string[] args) { - private static int returnCode; - public const string ConfigFile = "./BadMedicine.yaml"; + returnCode = 0; - public static int Main(string[] args) - { - returnCode = 0; + Parser.Default.ParseArguments(args) + .WithParsed(static opts => RunOptionsAndReturnExitCode(opts)) + .WithNotParsed(static (errs) => HandleParseError(errs)); - CommandLine.Parser.Default.ParseArguments(args) - .WithParsed(opts => RunOptionsAndReturnExitCode(opts)) - .WithNotParsed((errs) => HandleParseError(errs)); + return returnCode; + } - return returnCode; - } + private static void HandleParseError(IEnumerable errs) + { + returnCode = 500; + } + + private static void RunOptionsAndReturnExitCode(ProgramOptions opts) + { - private static void HandleParseError(IEnumerable errs) + if (opts.NumberOfPatients <= 0) + opts.NumberOfPatients = 500; + if (opts.NumberOfRows <= 0) + opts.NumberOfRows = 2000; + + Config config = null; + + if (File.Exists(ConfigFile)) { - returnCode = 500; + try + { + var d = new Deserializer(); + config = d.Deserialize(File.ReadAllText(ConfigFile)); + } + catch (Exception e) + { + Console.WriteLine($"Error deserializing '{ConfigFile}'"); + Console.Write(e.ToString()); + returnCode = -1; + return; + } } - private static void RunOptionsAndReturnExitCode(ProgramOptions opts) + + var dir = Directory.CreateDirectory(opts.OutputDirectory); + + try { + //if user wants to write out the lookups generate those too + if(opts.Lookups) + DataGenerator.WriteLookups(dir); + + var r = opts.Seed == -1 ? new Random() : new Random(opts.Seed); - if (opts.NumberOfPatients <= 0) - opts.NumberOfPatients = 500; - if (opts.NumberOfRows <= 0) - opts.NumberOfRows = 2000; + //create a cohort of people + IPersonCollection identifiers = new PersonCollection(); + identifiers.GeneratePeople(opts.NumberOfPatients,r); - Config config = null; + var factory = new DataGeneratorFactory(); + var generators = factory.GetAvailableGenerators().ToList(); - if (File.Exists(ConfigFile)) + //if the user only wants to extract a single dataset + if(!string.IsNullOrEmpty(opts.Dataset)) { - try - { - var d = new Deserializer(); - config = d.Deserialize(File.ReadAllText(ConfigFile)); - } - catch (Exception e) + var match = generators.FirstOrDefault(g => g.Name.Equals(opts.Dataset)); + if(match == null) { - Console.WriteLine($"Error deserializing '{ConfigFile}'"); - Console.Write(e.ToString()); - returnCode = -1; + Console.WriteLine($"Could not find dataset called '{opts.Dataset}'"); + Console.WriteLine( + $"Generators found were:{Environment.NewLine}{string.Join(Environment.NewLine, generators.Select(g => g.Name))}"); + returnCode = 2; return; } - } + generators = new List(new []{match}); + } - var dir = Directory.CreateDirectory(opts.OutputDirectory); - - try + // if we are not going to write out to a database + if (config?.Database != null) { - //if user wants to write out the lookups generate those too - if(opts.Lookups) - DataGenerator.WriteLookups(dir); - - Random r = opts.Seed == -1 ? new Random() : new Random(opts.Seed); - - //create a cohort of people - IPersonCollection identifiers = new PersonCollection(); - identifiers.GeneratePeople(opts.NumberOfPatients,r); - - var factory = new DataGeneratorFactory(); - var generators = factory.GetAvailableGenerators().ToList(); - - //if the user only wants to extract a single dataset - if(!string.IsNullOrEmpty(opts.Dataset)) + try { - var match = generators.FirstOrDefault(g => g.Name.Equals(opts.Dataset)); - if(match == null) + //for each generator + foreach (var g in generators) { - Console.WriteLine("Could not find dataset called '" + opts.Dataset + "'"); - Console.WriteLine("Generators found were:" + Environment.NewLine + string.Join(Environment.NewLine,generators.Select(g=>g.Name))); - returnCode = 2; - return; + var instance = factory.Create(g, r); + returnCode = Math.Min(RunDatabaseTarget(identifiers,config.Database, instance,opts.NumberOfRows),returnCode); } - generators = new List(new []{match}); + return; } - - // if we are not going to write out to a database - if (config?.Database != null) + catch (Exception e) { - try - { - //for each generator - foreach (var g in generators) - { - var instance = factory.Create(g, r); - returnCode = Math.Min(RunDatabaseTarget(identifiers,config.Database, instance,opts.NumberOfRows),returnCode); - } - - return; - } - catch (Exception e) - { - Console.WriteLine(e); - returnCode = 3; - return; - } + Console.WriteLine(e); + returnCode = 3; + return; } - else - { - // we are writting out to CSV + } + else + { + // we are writing out to CSV - //for each generator - foreach (var g in generators) - { - var instance = factory.Create(g, r); + //for each generator + foreach (var g in generators) + { + var instance = factory.Create(g, r); - var targetFile = new FileInfo(Path.Combine(dir.FullName, g.Name + ".csv")); - instance.GenerateTestDataFile(identifiers, targetFile, opts.NumberOfRows); - } + var targetFile = new FileInfo(Path.Combine(dir.FullName, $"{g.Name}.csv")); + instance.GenerateTestDataFile(identifiers, targetFile, opts.NumberOfRows); } - - } - catch (Exception e) - { - Console.WriteLine(e); - returnCode = 2; - return; } - returnCode = 0; } - - private static int RunDatabaseTarget(IPersonCollection cohort,TargetDatabase configDatabase, IDataGenerator generator, int numberOfRows) + catch (Exception e) { + Console.WriteLine(e); + returnCode = 2; + return; + } - ImplementationManager.Load(); - ImplementationManager.Load(); - ImplementationManager.Load(); - ImplementationManager.Load(); + returnCode = 0; + } - var server = new DiscoveredServer(configDatabase.ConnectionString, configDatabase.DatabaseType); + private static int RunDatabaseTarget(IPersonCollection cohort,TargetDatabase configDatabase, IDataGenerator generator, int numberOfRows) + { - try - { - server.TestConnection(10000); - } - catch (Exception e) - { - Console.WriteLine($"Could not reach target server '{server.Name}'"); - Console.WriteLine(e); - return -2; - } + ImplementationManager.Load(); + ImplementationManager.Load(); + ImplementationManager.Load(); + ImplementationManager.Load(); + var server = new DiscoveredServer(configDatabase.ConnectionString, configDatabase.DatabaseType); - var db = server.ExpectDatabase(configDatabase.DatabaseName); + try + { + server.TestConnection(10000); + } + catch (Exception e) + { + Console.WriteLine($"Could not reach target server '{server.Name}'"); + Console.WriteLine(e); + return -2; + } - if (!db.Exists()) - { - Console.WriteLine($"Creating Database '{db.GetRuntimeName()}'"); - db.Create(); - Console.WriteLine("Database Created"); - } - else - { - Console.WriteLine($"Found Database '{db.GetRuntimeName()}'"); - } - var tblName = generator.GetType().Name; + var db = server.ExpectDatabase(configDatabase.DatabaseName); - if(db.ExpectTable(tblName).Exists()) - { + if (!db.Exists()) + { + Console.WriteLine($"Creating Database '{db.GetRuntimeName()}'"); + db.Create(); + Console.WriteLine("Database Created"); + } + else + { + Console.WriteLine($"Found Database '{db.GetRuntimeName()}'"); + } - Console.WriteLine($"Found Existing Table '{tblName}'"); + var tblName = generator.GetType().Name; - if(configDatabase.DropTables) - db.ExpectTable(tblName).Drop(); - else - { - Console.WriteLine("Skipping table because it already existed and DropTables is false"); - return -3; - } + if(db.ExpectTable(tblName).Exists()) + { + + Console.WriteLine($"Found Existing Table '{tblName}'"); + + if(configDatabase.DropTables) + db.ExpectTable(tblName).Drop(); + else + { + Console.WriteLine("Skipping table because it already existed and DropTables is false"); + return -3; } + } - Console.WriteLine($"Creating Table '{tblName}'"); + Console.WriteLine($"Creating Table '{tblName}'"); - var dt = generator.GetDataTable(cohort, numberOfRows); - var tbl = db.CreateTable(tblName, dt); + var dt = generator.GetDataTable(cohort, numberOfRows); + var tbl = db.CreateTable(tblName, dt); - Console.WriteLine($"Finished Creating '{tblName}'. It had '{tbl.GetRowCount()}' rows"); - return 0; - } + Console.WriteLine($"Finished Creating '{tblName}'. It had '{tbl.GetRowCount()}' rows"); + return 0; } -} +} \ No newline at end of file diff --git a/BadMedicine/ProgramOptions.cs b/BadMedicine/ProgramOptions.cs index e165326..5832cfc 100644 --- a/BadMedicine/ProgramOptions.cs +++ b/BadMedicine/ProgramOptions.cs @@ -4,43 +4,42 @@ using CommandLine; using CommandLine.Text; -namespace BadMedicine +namespace BadMedicine; + +class ProgramOptions { - class ProgramOptions - { - [Value(0,HelpText = "Output directory to create CSV files in",Required=true)] - public string OutputDirectory { get; set; } + [Value(0,HelpText = "Output directory to create CSV files in",Required=true)] + public string OutputDirectory { get; set; } - [Value(1,HelpText = "The number of unique patient identifiers to generate up front and then use in test data",Default = 500)] - public int NumberOfPatients { get;set; } + [Value(1,HelpText = "The number of unique patient identifiers to generate up front and then use in test data",Default = 500)] + public int NumberOfPatients { get;set; } - [Value(2,HelpText = "The number of rows to generate in test dataset(s)",Default = 2000)] - public int NumberOfRows {get; set; } - - [Option('d',HelpText = "The dataset to generate, must be a class name e.g. 'Demography'")] - public string Dataset{get; set; } + [Value(2,HelpText = "The number of rows to generate in test dataset(s)",Default = 2000)] + public int NumberOfRows {get; set; } - [Option('l', HelpText = "Generate lookup tables for some codes used in the test data")] - public bool Lookups { get; set; } + [Option('d',HelpText = "The dataset to generate, must be a class name e.g. 'Demography'")] + public string Dataset{get; set; } - [Option('s', HelpText = "Seeds the random number generator with a specific number", Default = -1)] - public int Seed { get; set; } + [Option('l', HelpText = "Generate lookup tables for some codes used in the test data")] + public bool Lookups { get; set; } - [Usage] - public static IEnumerable Examples + [Option('s', HelpText = "Seeds the random number generator with a specific number", Default = -1)] + public int Seed { get; set; } + + [Usage] + public static IEnumerable Examples + { + get { - get - { - yield return - new Example("Generate test data", new ProgramOptions { OutputDirectory = @"c:/temp" }); - - yield return - new Example("Generate a custom amount of data", new ProgramOptions { OutputDirectory = @"c:/temp",NumberOfPatients = 5000, NumberOfRows = 20000}); - - yield return - new Example("Generate only a single dataset", new ProgramOptions { OutputDirectory = @"c:/temp",NumberOfPatients = 5000, NumberOfRows = 20000, Dataset = "TestDemography"}); - } - } + yield return + new Example("Generate test data", new ProgramOptions { OutputDirectory = @"c:/temp" }); + + yield return + new Example("Generate a custom amount of data", new ProgramOptions { OutputDirectory = @"c:/temp",NumberOfPatients = 5000, NumberOfRows = 20000}); + yield return + new Example("Generate only a single dataset", new ProgramOptions { OutputDirectory = @"c:/temp",NumberOfPatients = 5000, NumberOfRows = 20000, Dataset = "TestDemography"}); + } } -} + +} \ No newline at end of file diff --git a/BadMedicineTests/BadMedicineTests.csproj b/BadMedicineTests/BadMedicineTests.csproj index 98251ca..665e4a1 100644 --- a/BadMedicineTests/BadMedicineTests.csproj +++ b/BadMedicineTests/BadMedicineTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false embedded diff --git a/BadMedicineTests/BiochemistryTests.cs b/BadMedicineTests/BiochemistryTests.cs index f743a4d..6b69d10 100644 --- a/BadMedicineTests/BiochemistryTests.cs +++ b/BadMedicineTests/BiochemistryTests.cs @@ -5,70 +5,69 @@ using BadMedicine.Datasets; using NUnit.Framework; -namespace BadMedicineTests +namespace BadMedicineTests; + +class TestBiochemistry { - class TestBiochemistry + [Test] + public void Test_CreateABiochemistryRecord() { - [Test] - public void Test_CreateABiochemistryRecord() - { - var record = new BiochemistryRecord(new Random(500)); + var record = new BiochemistryRecord(new Random(500)); - Assert.AreEqual("NULL",record.ArithmeticComparator); - Assert.AreEqual("T",record.Healthboard); - Assert.AreEqual("IF HIGH RISK- EXCLUDE CKD1/2. CHECK FOR HAEMATURIA AND PROTEINURIA",record.Interpretation); - Assert.AreEqual("BC262017",record.LabNumber); - Assert.AreEqual("NULL",record.QuantityUnit); - Assert.AreEqual("451G.",record.ReadCodeValue); - Assert.AreEqual("Blood",record.SampleType); - Assert.AreEqual("eCOM",record.TestCode); - Assert.AreEqual("NULL",record.QuantityUnit); - } - [Test] - public void TestSeed_Biochemistry_SingleRow() - { - var record1 = new BiochemistryRecord(new Random(500)); - var record2 = new BiochemistryRecord(new Random(500)); + Assert.AreEqual("NULL",record.ArithmeticComparator); + Assert.AreEqual("T",record.Healthboard); + Assert.AreEqual("IF HIGH RISK- EXCLUDE CKD1/2. CHECK FOR HAEMATURIA AND PROTEINURIA",record.Interpretation); + Assert.AreEqual("BC262017",record.LabNumber); + Assert.AreEqual("NULL",record.QuantityUnit); + Assert.AreEqual("451G.",record.ReadCodeValue); + Assert.AreEqual("Blood",record.SampleType); + Assert.AreEqual("eCOM",record.TestCode); + Assert.AreEqual("NULL",record.QuantityUnit); + } + [Test] + public void TestSeed_Biochemistry_SingleRow() + { + var record1 = new BiochemistryRecord(new Random(500)); + var record2 = new BiochemistryRecord(new Random(500)); - Assert.AreEqual(record2.ArithmeticComparator,record1.ArithmeticComparator); - Assert.AreEqual(record2.LabNumber,record1.LabNumber); - Assert.AreEqual(record2.TestCode,record1.TestCode); - } - [Test] - public void TestSeed_Biochemistry() - { - var r1 = new Random(500); - var r2 = new Random(500); - var r3 = new Random(500); + Assert.AreEqual(record2.ArithmeticComparator,record1.ArithmeticComparator); + Assert.AreEqual(record2.LabNumber,record1.LabNumber); + Assert.AreEqual(record2.TestCode,record1.TestCode); + } + [Test] + public void TestSeed_Biochemistry() + { + var r1 = new Random(500); + var r2 = new Random(500); + var r3 = new Random(500); - PersonCollection persons1 = new PersonCollection(); - PersonCollection persons2 = new PersonCollection(); - PersonCollection persons3 = new PersonCollection(); + var persons1 = new PersonCollection(); + var persons2 = new PersonCollection(); + var persons3 = new PersonCollection(); - //take one from each random number generator - persons1.GeneratePeople(500,r1); - persons2.GeneratePeople(500,r2); - persons3.GeneratePeople(500,r3); - - var f = new DataGeneratorFactory(); - var generator1 = f.Create(r1); - var generator2 = f.Create(r2); - var generator3 = new Biochemistry(r3); + //take one from each random number generator + persons1.GeneratePeople(500,r1); + persons2.GeneratePeople(500,r2); + persons3.GeneratePeople(500,r3); + + var f = new DataGeneratorFactory(); + var generator1 = f.Create(r1); + var generator2 = f.Create(r2); + var generator3 = new Biochemistry(r3); - - for(int i = 0 ; i < 500;i++) - { - var row1 = generator1.GenerateTestDataRow(persons1.People[r1.Next(persons1.People.Length)]); - var row2 = generator2.GenerateTestDataRow(persons2.People[r2.Next(persons2.People.Length)]); - var row3 = generator3.GenerateTestDataRow(persons3.People[r3.Next(persons3.People.Length)]); - for(int cell = 0;cell < row1.Length;cell++) - { - Assert.AreEqual(row1[cell],row2[cell]); - Assert.AreEqual(row2[cell],row3[cell]); - } + for(var i = 0 ; i < 500;i++) + { + var row1 = generator1.GenerateTestDataRow(persons1.People[r1.Next(persons1.People.Length)]); + var row2 = generator2.GenerateTestDataRow(persons2.People[r2.Next(persons2.People.Length)]); + var row3 = generator3.GenerateTestDataRow(persons3.People[r3.Next(persons3.People.Length)]); + + for(var cell = 0;cell < row1.Length;cell++) + { + Assert.AreEqual(row1[cell],row2[cell]); + Assert.AreEqual(row2[cell],row3[cell]); } } } -} +} \ No newline at end of file diff --git a/BadMedicineTests/BucketListTests.cs b/BadMedicineTests/BucketListTests.cs index 06545c9..b51e5b9 100644 --- a/BadMedicineTests/BucketListTests.cs +++ b/BadMedicineTests/BucketListTests.cs @@ -4,55 +4,54 @@ using BadMedicine; using NUnit.Framework; -namespace BadMedicineTests +namespace BadMedicineTests; + +class BucketListTests { - class BucketListTests + [Test] + public void Test_BucketList_OneElement() { - [Test] - public void Test_BucketList_OneElment() - { - var r = new Random(100); + var r = new Random(100); - BucketList list = new BucketList(); - list.Add(1,"fish"); + var list = new BucketList(); + list.Add(1,"fish"); - Assert.AreEqual("fish",list.GetRandom(r)); - Assert.AreEqual("fish",list.GetRandom(new []{0},r)); - } + Assert.AreEqual("fish",list.GetRandom(r)); + Assert.AreEqual("fish",list.GetRandom(new []{0},r)); + } + + [TestCase(true)] + [TestCase(false)] + public void Test_BucketList_TwoElements(bool passIndices) + { + var r = new Random(100); + var list = new BucketList(); + + //we expect twice as many blue as red + list.Add(1,"red"); + list.Add(2,"blue"); + + var countRed = 0; + var countBlue = 0; - [TestCase(true)] - [TestCase(false)] - public void Test_BucketList_TwoElments(bool passIndices) + for (var i = 0; i < 1000; i++) { - var r = new Random(100); - BucketList list = new BucketList(); - - //we expect twice as many blue as red - list.Add(1,"red"); - list.Add(2,"blue"); - - int countRed = 0; - int countBlue = 0; - - for (int i = 0; i < 1000; i++) + switch (passIndices ? list.GetRandom(r) : list.GetRandom(new[] {0, 1},r)) { - switch (passIndices ? list.GetRandom(r) : list.GetRandom(new[] {0, 1},r)) - { - case "red": - countRed++; - break; - case "blue": - countBlue++; - break; - default: - Assert.Fail(); - break; - } + case "red": + countRed++; + break; + case "blue": + countBlue++; + break; + default: + Assert.Fail(); + break; } + } - Assert.AreEqual(311,countRed); - Assert.AreEqual(689,countBlue); + Assert.AreEqual(311,countRed); + Assert.AreEqual(689,countBlue); - } } -} +} \ No newline at end of file diff --git a/BadMedicineTests/DescriptionsTests.cs b/BadMedicineTests/DescriptionsTests.cs index 07338b4..eaecabd 100644 --- a/BadMedicineTests/DescriptionsTests.cs +++ b/BadMedicineTests/DescriptionsTests.cs @@ -6,83 +6,82 @@ using System.Linq; using System.Text; -namespace BadMedicineTests +namespace BadMedicineTests; + +class DescriptionsTests { - class DescriptionsTests + [Test] + public void Test_GetDescription_Dataset() { - [Test] - public void Test_GetDescription_Dataset() - { - var desc = new Descriptions(); + var desc = new Descriptions(); - StringAssert.Contains("Tayside and Fife labs biochemistry data",desc.Get()); - } + StringAssert.Contains("Tayside and Fife labs biochemistry data",desc.Get()); + } - [Test] - public void Test_GetDescription_Field() - { - var desc = new Descriptions(); + [Test] + public void Test_GetDescription_Field() + { + var desc = new Descriptions(); - StringAssert.Contains("Health Board code",desc.Get("Healthboard")); - StringAssert.Contains("Health Board code",desc.Get("Biochemistry","Healthboard")); - } + StringAssert.Contains("Health Board code",desc.Get("Healthboard")); + StringAssert.Contains("Health Board code",desc.Get("Biochemistry","Healthboard")); + } - [Test] - public void Test_GetDescription_FieldNotFound() - { - var desc = new Descriptions(); + [Test] + public void Test_GetDescription_FieldNotFound() + { + var desc = new Descriptions(); - Assert.IsNull(desc.Get("ZappyZappyZappy")); - Assert.IsNull(desc.Get("Biochemistry","ZappyZappyZappy")); - } - [Test] - public void Test_GetDescription_FieldNotFoundAndDatasetNotFound() - { - var desc = new Descriptions(); - Assert.IsNull(desc.Get("Happy","ZappyZappyZappy")); + Assert.IsNull(desc.Get("ZappyZappyZappy")); + Assert.IsNull(desc.Get("Biochemistry","ZappyZappyZappy")); + } + [Test] + public void Test_GetDescription_FieldNotFoundAndDatasetNotFound() + { + var desc = new Descriptions(); + Assert.IsNull(desc.Get("Happy","ZappyZappyZappy")); - Assert.IsEmpty(desc.GetAll("Happy")); - } + Assert.IsEmpty(desc.GetAll("Happy")); + } - /// - /// This tests when the field is in CommonFields not under the dataset - /// - [Test] - public void Test_GetDescription_ChiField() - { - var desc = new Descriptions(); - StringAssert.Contains("Community Health Index (CHI) number is a unique personal identifier ",desc.Get("chi")); - StringAssert.Contains("Community Health Index (CHI) number is a unique personal identifier ",desc.Get("Biochemistry","chi")); - } + /// + /// This tests when the field is in CommonFields not under the dataset + /// + [Test] + public void Test_GetDescription_ChiField() + { + var desc = new Descriptions(); + StringAssert.Contains("Community Health Index (CHI) number is a unique personal identifier ",desc.Get("chi")); + StringAssert.Contains("Community Health Index (CHI) number is a unique personal identifier ",desc.Get("Biochemistry","chi")); + } - [Test] - public void Test_GetAllDescriptions_Biochemistry() - { - var desc = new Descriptions(); + [Test] + public void Test_GetAllDescriptions_Biochemistry() + { + var desc = new Descriptions(); - Assert.GreaterOrEqual(desc.GetAll().ToArray().Length,5); - Assert.GreaterOrEqual(desc.GetAll("Biochemistry").ToArray().Length,5); - Assert.GreaterOrEqual(desc.GetAll("Common").ToArray().Length,1); + Assert.GreaterOrEqual(desc.GetAll().ToArray().Length,5); + Assert.GreaterOrEqual(desc.GetAll("Biochemistry").ToArray().Length,5); + Assert.GreaterOrEqual(desc.GetAll("Common").ToArray().Length,1); - foreach(var kvp in desc.GetAll()) - { - Assert.IsTrue(!string.IsNullOrWhiteSpace(kvp.Key), "Found null key"); - Assert.IsTrue(!string.IsNullOrWhiteSpace(kvp.Value),"Found null description for" + kvp.Key); - } + foreach(var kvp in desc.GetAll()) + { + Assert.IsTrue(!string.IsNullOrWhiteSpace(kvp.Key), "Found null key"); + Assert.IsTrue(!string.IsNullOrWhiteSpace(kvp.Value),"Found null description for" + kvp.Key); } + } - [Test] - public void Test_GetAllDescriptions_AllDatasets() - { - var desc = new Descriptions(); + [Test] + public void Test_GetAllDescriptions_AllDatasets() + { + var desc = new Descriptions(); - var factory = new DataGeneratorFactory(); - foreach(var g in factory.GetAvailableGenerators()) - { - Assert.IsNotNull(desc.Get(g.Name),"Dataset '{0}' did not have a summary tag",g.Name); - Assert.IsNotEmpty(desc.GetAll(g.Name),"Dataset '{0}' did not have at least one column description",g.Name); - } + var factory = new DataGeneratorFactory(); + foreach(var g in factory.GetAvailableGenerators()) + { + Assert.IsNotNull(desc.Get(g.Name),"Dataset '{0}' did not have a summary tag",g.Name); + Assert.IsNotEmpty(desc.GetAll(g.Name),"Dataset '{0}' did not have at least one column description",g.Name); } } -} +} \ No newline at end of file diff --git a/BadMedicineTests/MaternityTests.cs b/BadMedicineTests/MaternityTests.cs index 9edb654..8016046 100644 --- a/BadMedicineTests/MaternityTests.cs +++ b/BadMedicineTests/MaternityTests.cs @@ -7,70 +7,69 @@ using System.Linq; using System.Text; -namespace BadMedicineTests +namespace BadMedicineTests; + +class MaternityTests { - class MaternityTests + [Test] + public void Test_IsEligible() { - [Test] - public void Test_IsEligible() - { - var r = new Random(100); - var pc = new PersonCollection(); - pc.GeneratePeople(100,r); - - var m = new Maternity(r); - - Assert.IsTrue(pc.People.Where(m.IsEligible).All(e=>e.Gender == 'F')); - Assert.LessOrEqual(pc.People.Count(m.IsEligible),47, "Expected less than 50:50 due to restrictions on both Gender and age"); - } + var r = new Random(100); + var pc = new PersonCollection(); + pc.GeneratePeople(100,r); - [Test] - public void Test_GetDataTable() - { - var r = new Random(100); - var m = new Maternity(r); + var m = new Maternity(r); - var pc = new PersonCollection(); - pc.GeneratePeople(100,r); + Assert.IsTrue(pc.People.Where(m.IsEligible).All(e=>e.Gender == 'F')); + Assert.LessOrEqual(pc.People.Count(m.IsEligible),47, "Expected less than 50:50 due to restrictions on both Gender and age"); + } - //get 50k records - var dt = m.GetDataTable(pc,50000); - Assert.AreEqual(50000,dt.Rows.Count); + [Test] + public void Test_GetDataTable() + { + var r = new Random(100); + var m = new Maternity(r); - int countFromPopularLocation = dt.Rows.Cast().Count(row => row["SendingLocation"].Equals("T101H")); - int countFromRareLocation = dt.Rows.Cast().Count(row => row["SendingLocation"].Equals("T306H")); + var pc = new PersonCollection(); + pc.GeneratePeople(100,r); - Assert.Greater(countFromPopularLocation,0); - Assert.Greater(countFromRareLocation,0); + //get 50k records + var dt = m.GetDataTable(pc,50000); + Assert.AreEqual(50000,dt.Rows.Count); - // should be more from popular location - Assert.Greater(countFromPopularLocation , countFromRareLocation); + var countFromPopularLocation = dt.Rows.Cast().Count(row => row["SendingLocation"].Equals("T101H")); + var countFromRareLocation = dt.Rows.Cast().Count(row => row["SendingLocation"].Equals("T306H")); - // like a lot more! - Assert.Greater(countFromPopularLocation , countFromRareLocation * 10); - } + Assert.Greater(countFromPopularLocation,0); + Assert.Greater(countFromRareLocation,0); - [Test] - public void Test_MaternityRecord() - { - var r = new Random(100); - var m = new Maternity(r); + // should be more from popular location + Assert.Greater(countFromPopularLocation , countFromRareLocation); - var pc = new PersonCollection(); - pc.GeneratePeople(100,r); + // like a lot more! + Assert.Greater(countFromPopularLocation , countFromRareLocation * 10); + } - var eligible = pc.People.Where(m.IsEligible); - var dict = eligible.ToDictionary(k=>k,v=>new MaternityRecord(v,r)); + [Test] + public void Test_MaternityRecord() + { + var r = new Random(100); + var m = new Maternity(r); + + var pc = new PersonCollection(); + pc.GeneratePeople(100,r); - //gave birth after being born themselves - Assert.IsTrue(dict.All(kv=>kv.Key.DateOfBirth < kv.Value.Date)); + var eligible = pc.People.Where(m.IsEligible); + var dict = eligible.ToDictionary(k=>k,v=>new MaternityRecord(v,r)); - //no future dates - Assert.IsTrue(dict.All(kv=> kv.Value.Date <= DataGenerator.Now)); + //gave birth after being born themselves + Assert.IsTrue(dict.All(kv=>kv.Key.DateOfBirth < kv.Value.Date)); + //no future dates + Assert.IsTrue(dict.All(kv=> kv.Value.Date <= DataGenerator.Now)); - } } -} + +} \ No newline at end of file diff --git a/BadMedicineTests/NuspecIsCorrectTests.cs b/BadMedicineTests/NuspecIsCorrectTests.cs index c159851..e1740f3 100644 --- a/BadMedicineTests/NuspecIsCorrectTests.cs +++ b/BadMedicineTests/NuspecIsCorrectTests.cs @@ -9,97 +9,96 @@ using System.Linq; using System.Text.RegularExpressions; -namespace BadMedicineTests +namespace BadMedicineTests; + +/// +/// Tests to confirm that the dependencies in csproj files (NuGet packages) match those in the .nuspec files and that packages.md +/// lists the correct versions (in documentation) +/// +class NuspecIsCorrectTests { - /// - /// Tests to confirm that the dependencies in csproj files (NuGet packages) match those in the .nuspec files and that packages.md - /// lists the correct versions (in documentation) - /// - class NuspecIsCorrectTests - { - static string[] Analyzers = new string[] { "SecurityCodeScan" }; + static string[] Analyzers = new string[] { "SecurityCodeScan" }; - [TestCase("../../../../BadMedicine.Core/BadMedicine.Core.csproj", null, "../../../../Packages.md")] - public void TestDependencyCorrect(string csproj, string nuspec, string packagesMarkdown) - { - if(csproj != null && !Path.IsPathRooted(csproj)) - csproj = Path.Combine(TestContext.CurrentContext.TestDirectory,csproj); - if(nuspec != null && !Path.IsPathRooted(nuspec)) - nuspec = Path.Combine(TestContext.CurrentContext.TestDirectory,nuspec); - if(packagesMarkdown != null && !Path.IsPathRooted(packagesMarkdown)) - packagesMarkdown = Path.Combine(TestContext.CurrentContext.TestDirectory,packagesMarkdown); + [TestCase("../../../../BadMedicine.Core/BadMedicine.Core.csproj", null, "../../../../Packages.md")] + public void TestDependencyCorrect(string csproj, string nuspec, string packagesMarkdown) + { + if(csproj != null && !Path.IsPathRooted(csproj)) + csproj = Path.Combine(TestContext.CurrentContext.TestDirectory,csproj); + if(nuspec != null && !Path.IsPathRooted(nuspec)) + nuspec = Path.Combine(TestContext.CurrentContext.TestDirectory,nuspec); + if(packagesMarkdown != null && !Path.IsPathRooted(packagesMarkdown)) + packagesMarkdown = Path.Combine(TestContext.CurrentContext.TestDirectory,packagesMarkdown); - if (!File.Exists(csproj)) - Assert.Fail("Could not find file {0}", csproj); - if (nuspec != null && !File.Exists(nuspec)) - Assert.Fail("Could not find file {0}", nuspec); + if (!File.Exists(csproj)) + Assert.Fail("Could not find file {0}", csproj); + if (nuspec != null && !File.Exists(nuspec)) + Assert.Fail("Could not find file {0}", nuspec); - if (packagesMarkdown != null && !File.Exists(packagesMarkdown)) - Assert.Fail("Could not find file {0}", packagesMarkdown); + if (packagesMarkdown != null && !File.Exists(packagesMarkdown)) + Assert.Fail("Could not find file {0}", packagesMarkdown); - // - Regex rPackageRef = new Regex(@" + var rPackageRef = new Regex(@" - Regex rDependencyRef = new Regex(@" + var rDependencyRef = new Regex(@"", package, version); - } + private object BuildRecommendedDependencyLine(string package, string version) + { + return string.Format("", package, version); + } - private object BuildRecommendedMarkdownLine(string package, string version) - { - return $"| {package} | [GitHub]() | [{package}](https://www.nuget.org/packages/{package}) | | | |"; - } + private object BuildRecommendedMarkdownLine(string package, string version) + { + return $"| {package} | [GitHub]() | [{package}](https://www.nuget.org/packages/{package}) | | | |"; } -} +} \ No newline at end of file diff --git a/BadMedicineTests/PersonTests.cs b/BadMedicineTests/PersonTests.cs index 71dc4fe..cbc6935 100644 --- a/BadMedicineTests/PersonTests.cs +++ b/BadMedicineTests/PersonTests.cs @@ -4,64 +4,63 @@ using System.Collections.Generic; using System.Text; -namespace BadMedicineTests +namespace BadMedicineTests; + +class PersonTests { - class PersonTests + [Test] + public void TestPerson_Seed() { - [Test] - public void TestPerson_Seed() - { - Random r1 = new Random(500); - Random r2 = new Random(500); - - var p1 = new Person(r1); - var p2 = new Person(r2); - - Assert.AreEqual(p1.Forename,p2.Forename); - Assert.AreEqual(p1.Surname,p2.Surname); - Assert.AreEqual(p1.DateOfBirth,p2.DateOfBirth); - Assert.AreEqual(p1.DateOfDeath,p2.DateOfDeath); - Assert.AreEqual(p1.CHI,p2.CHI); - Assert.AreEqual(p1.PreviousAddress?.Line1,p2.PreviousAddress?.Line1); - Assert.AreEqual(p1.PreviousAddress?.Line2,p2.PreviousAddress?.Line2); - Assert.AreEqual(p1.PreviousAddress?.Line3,p2.PreviousAddress?.Line3); - Assert.AreEqual(p1.PreviousAddress?.Line4,p2.PreviousAddress?.Line4); - Assert.AreEqual(p1.PreviousAddress?.Postcode,p2.PreviousAddress?.Postcode); + var r1 = new Random(500); + var r2 = new Random(500); + + var p1 = new Person(r1); + var p2 = new Person(r2); + + Assert.AreEqual(p1.Forename,p2.Forename); + Assert.AreEqual(p1.Surname,p2.Surname); + Assert.AreEqual(p1.DateOfBirth,p2.DateOfBirth); + Assert.AreEqual(p1.DateOfDeath,p2.DateOfDeath); + Assert.AreEqual(p1.CHI,p2.CHI); + Assert.AreEqual(p1.PreviousAddress?.Line1,p2.PreviousAddress?.Line1); + Assert.AreEqual(p1.PreviousAddress?.Line2,p2.PreviousAddress?.Line2); + Assert.AreEqual(p1.PreviousAddress?.Line3,p2.PreviousAddress?.Line3); + Assert.AreEqual(p1.PreviousAddress?.Line4,p2.PreviousAddress?.Line4); + Assert.AreEqual(p1.PreviousAddress?.Postcode,p2.PreviousAddress?.Postcode); + + + Assert.AreEqual(p1.Address.Line1,p2.Address.Line1); + Assert.AreEqual(p1.Address.Line2,p2.Address.Line2); + Assert.AreEqual(p1.Address.Line3,p2.Address.Line3); + Assert.AreEqual(p1.Address.Line4,p2.Address.Line4); + Assert.AreEqual(p1.Address.Postcode,p2.Address.Postcode); + } + + [Test] + public void TestPersonCollection_Seed() + { + var r1 = new Random(500); + var r2 = new Random(500); + + var p1 = new Person(r1); + var p2 = new Person(r2); - - Assert.AreEqual(p1.Address.Line1,p2.Address.Line1); - Assert.AreEqual(p1.Address.Line2,p2.Address.Line2); - Assert.AreEqual(p1.Address.Line3,p2.Address.Line3); - Assert.AreEqual(p1.Address.Line4,p2.Address.Line4); - Assert.AreEqual(p1.Address.Postcode,p2.Address.Postcode); - } + Assert.AreEqual(p1.Forename,p2.Forename); + Assert.AreEqual(p1.Surname,p2.Surname); + Assert.AreEqual(p1.DateOfBirth,p2.DateOfBirth); + Assert.AreEqual(p1.DateOfDeath,p2.DateOfDeath); + Assert.AreEqual(p1.CHI,p2.CHI); + Assert.AreEqual(p1.PreviousAddress?.Line1,p2.PreviousAddress?.Line1); + Assert.AreEqual(p1.PreviousAddress?.Line2,p2.PreviousAddress?.Line2); + Assert.AreEqual(p1.PreviousAddress?.Line3,p2.PreviousAddress?.Line3); + Assert.AreEqual(p1.PreviousAddress?.Line4,p2.PreviousAddress?.Line4); + Assert.AreEqual(p1.PreviousAddress?.Postcode,p2.PreviousAddress?.Postcode); - [Test] - public void TestPersonCollection_Seed() - { - Random r1 = new Random(500); - Random r2 = new Random(500); - - var p1 = new Person(r1); - var p2 = new Person(r2); - - Assert.AreEqual(p1.Forename,p2.Forename); - Assert.AreEqual(p1.Surname,p2.Surname); - Assert.AreEqual(p1.DateOfBirth,p2.DateOfBirth); - Assert.AreEqual(p1.DateOfDeath,p2.DateOfDeath); - Assert.AreEqual(p1.CHI,p2.CHI); - Assert.AreEqual(p1.PreviousAddress?.Line1,p2.PreviousAddress?.Line1); - Assert.AreEqual(p1.PreviousAddress?.Line2,p2.PreviousAddress?.Line2); - Assert.AreEqual(p1.PreviousAddress?.Line3,p2.PreviousAddress?.Line3); - Assert.AreEqual(p1.PreviousAddress?.Line4,p2.PreviousAddress?.Line4); - Assert.AreEqual(p1.PreviousAddress?.Postcode,p2.PreviousAddress?.Postcode); - - Assert.AreEqual(p1.Address.Line1,p2.Address.Line1); - Assert.AreEqual(p1.Address.Line2,p2.Address.Line2); - Assert.AreEqual(p1.Address.Line3,p2.Address.Line3); - Assert.AreEqual(p1.Address.Line4,p2.Address.Line4); - Assert.AreEqual(p1.Address.Postcode,p2.Address.Postcode); - } + Assert.AreEqual(p1.Address.Line1,p2.Address.Line1); + Assert.AreEqual(p1.Address.Line2,p2.Address.Line2); + Assert.AreEqual(p1.Address.Line3,p2.Address.Line3); + Assert.AreEqual(p1.Address.Line4,p2.Address.Line4); + Assert.AreEqual(p1.Address.Postcode,p2.Address.Postcode); } -} +} \ No newline at end of file diff --git a/BadMedicineTests/TestAdmissionTests.cs b/BadMedicineTests/TestAdmissionTests.cs index 7e446f1..5ddf043 100644 --- a/BadMedicineTests/TestAdmissionTests.cs +++ b/BadMedicineTests/TestAdmissionTests.cs @@ -4,52 +4,51 @@ using BadMedicine.Datasets; using NUnit.Framework; -namespace BadMedicineTests +namespace BadMedicineTests; + +public class TestAdmissionTests { - public class TestAdmissionTests + [Test] + public void Test_GetRandomIcdCode() { - [Test] - public void Test_GetRandomIcdCode() - { - //Seed the random generator if you want to always produce the same randomisation - var r = new Random(100); + //Seed the random generator if you want to always produce the same randomisation + var r = new Random(100); + + //Create a new person + var person = new Person(r); + + //Create test data for that person + var a = new HospitalAdmissionsRecord(person,person.DateOfBirth,r); + + Assert.IsNotNull(a.Person.CHI); + Assert.IsNotNull(a.Person.DateOfBirth); + Assert.IsNotNull(a.Person.Address.Line1); + Assert.IsNotNull(a.Person.Address.Postcode); + Assert.IsNotNull(a.AdmissionDate); + Assert.IsNotNull(a.DischargeDate); + Assert.IsNotNull(a.MainCondition); + } - //Create a new person - var person = new Person(r); + [Test] + public void Test_Performance() + { + var r = new Random(100); + var person = new Person(r); - //Create test data for that person - var a = new HospitalAdmissionsRecord(person,person.DateOfBirth,r); + var swSetup = Stopwatch.StartNew(); + //first is always slow + var first= new HospitalAdmissionsRecord(person,person.DateOfBirth,r); - Assert.IsNotNull(a.Person.CHI); - Assert.IsNotNull(a.Person.DateOfBirth); - Assert.IsNotNull(a.Person.Address.Line1); - Assert.IsNotNull(a.Person.Address.Postcode); - Assert.IsNotNull(a.AdmissionDate); - Assert.IsNotNull(a.DischargeDate); - Assert.IsNotNull(a.MainCondition); - } + Console.WriteLine($"Setup took{swSetup.ElapsedMilliseconds}ms"); - [Test] - public void Test_Performance() + var sw = Stopwatch.StartNew(); + for (var i = 0; i < 100000; i++) { - var r = new Random(100); - var person = new Person(r); - - var swSetup = Stopwatch.StartNew(); - //first is always slow - var first= new HospitalAdmissionsRecord(person,person.DateOfBirth,r); - - Console.WriteLine("Setup took" + swSetup.ElapsedMilliseconds + "ms"); + var a = new HospitalAdmissionsRecord(person,person.DateOfBirth,r); + } - var sw = Stopwatch.StartNew(); - for (int i = 0; i < 100000; i++) - { - var a = new HospitalAdmissionsRecord(person,person.DateOfBirth,r); - } + Console.WriteLine($"Remainder took:{sw.ElapsedMilliseconds}ms"); - Console.WriteLine("Remainder took:" + sw.ElapsedMilliseconds +"ms"); - - } - } -} + +} \ No newline at end of file diff --git a/BadMedicineTests/TestGetDataTable.cs b/BadMedicineTests/TestGetDataTable.cs index 719d763..9c2a0e6 100644 --- a/BadMedicineTests/TestGetDataTable.cs +++ b/BadMedicineTests/TestGetDataTable.cs @@ -4,38 +4,37 @@ using BadMedicine.Datasets; using NUnit.Framework; -namespace BadMedicineTests +namespace BadMedicineTests; + +class TestGetDataTable { - class TestGetDataTable + [Test] + public void Test_GetDataTableForAllDatasets_ReturnsCorrectRowCount() { - [Test] - public void Test_GetDataTableForAllDatasets_ReturnsCorrectRowCount() - { - var factory = new DataGeneratorFactory(); + var factory = new DataGeneratorFactory(); - //there should be some supported datasets - Assert.Greater(factory.GetAvailableGenerators().Count(),0); + //there should be some supported datasets + Assert.Greater(factory.GetAvailableGenerators().Count(),0); - var r = new Random(500); + var r = new Random(500); - var people = new PersonCollection(); - people.GeneratePeople(5000,r); + var people = new PersonCollection(); + people.GeneratePeople(5000,r); - //each dataset - foreach (Type t in factory.GetAvailableGenerators()) + //each dataset + foreach (var t in factory.GetAvailableGenerators()) + { + try + { + var instance = factory.Create(t, r); + var dt = instance.GetDataTable(people,500); + Assert.AreEqual(500,dt.Rows.Count); + } + catch (Exception e) { - try - { - var instance = factory.Create(t, r); - var dt = instance.GetDataTable(people,500); - Assert.AreEqual(500,dt.Rows.Count); - } - catch (Exception e) - { - throw new Exception("Test failed for Type '" + t.Name + "'",e); + throw new Exception($"Test failed for Type '{t.Name}'",e); - } } } } -} +} \ No newline at end of file diff --git a/BadMedicineTests/UltraWideTests.cs b/BadMedicineTests/UltraWideTests.cs index dd28365..2663a47 100644 --- a/BadMedicineTests/UltraWideTests.cs +++ b/BadMedicineTests/UltraWideTests.cs @@ -3,24 +3,23 @@ using BadMedicine.Datasets; using NUnit.Framework; -namespace BadMedicineTests +namespace BadMedicineTests; + +class UltraWideTests { - class UltraWideTests + [Test] + public void TestUltraWide() { - [Test] - public void TestUltraWide() - { - var r1 = new Random(500); + var r1 = new Random(500); - PersonCollection persons = new PersonCollection(); - persons.GeneratePeople(500, r1); + var persons = new PersonCollection(); + persons.GeneratePeople(500, r1); - var f = new DataGeneratorFactory(); - var generator = f.Create(r1); + var f = new DataGeneratorFactory(); + var generator = f.Create(r1); - using var dt = generator.GetDataTable(persons, 500); - Assert.AreEqual(20000, dt.Columns.Count); - Assert.AreEqual(500, dt.Rows.Count); - } + using var dt = generator.GetDataTable(persons, 500); + Assert.AreEqual(20000, dt.Columns.Count); + Assert.AreEqual(500, dt.Rows.Count); } -} +} \ No newline at end of file diff --git a/BadMedicineTests/WideTests.cs b/BadMedicineTests/WideTests.cs index 3952f44..20ac23e 100644 --- a/BadMedicineTests/WideTests.cs +++ b/BadMedicineTests/WideTests.cs @@ -3,24 +3,23 @@ using BadMedicine.Datasets; using NUnit.Framework; -namespace BadMedicineTests +namespace BadMedicineTests; + +class WideTests { - class WideTests + [Test] + public void TestWide() { - [Test] - public void TestWide() - { - var r1 = new Random(500); + var r1 = new Random(500); - PersonCollection persons = new PersonCollection(); - persons.GeneratePeople(500, r1); + var persons = new PersonCollection(); + persons.GeneratePeople(500, r1); - var f = new DataGeneratorFactory(); - var generator = f.Create(r1); + var f = new DataGeneratorFactory(); + var generator = f.Create(r1); - using var dt = generator.GetDataTable(persons, 500); - Assert.AreEqual(980,dt.Columns.Count); - Assert.AreEqual(500, dt.Rows.Count); - } + using var dt = generator.GetDataTable(persons, 500); + Assert.AreEqual(980,dt.Columns.Count); + Assert.AreEqual(500, dt.Rows.Count); } -} +} \ No newline at end of file diff --git a/Datasets.doc.xml b/Datasets.doc.xml index 344913a..d8bb4d7 100644 --- a/Datasets.doc.xml +++ b/Datasets.doc.xml @@ -52,7 +52,7 @@ - Unique identifier of the second contributor of genetic material for the babie(s) being born or null if baby is a clone + Unique identifier of the second contributor of genetic material for the babies being born or null if baby is a clone @@ -152,7 +152,7 @@ - Annonymous identifier that has replaced the identifiable CHI. Typically represented as aaa1234567 where the first three letters uniquely identify a project (allowing for project specific anonymisation) + Anonymous identifier that has replaced the identifiable CHI. Typically represented as aaa1234567 where the first three letters uniquely identify a project (allowing for project specific anonymisation) @@ -162,7 +162,7 @@ - If the patient is dead then this date will be filled in with the date it occured + If the patient is dead then this date will be filled in with the date it occurred @@ -182,12 +182,12 @@ - The date the patient registerd with the GP (when the chi record was created). + The date the patient registered with the GP (when the chi record was created). - 1 if the record is still active in the given healthboard (e.g.. Tayside) or 0 if a more recent record exists in another healthboard (i.e. they are known to have moved out of the area or if ISD no longer supplies the record). Note that if your research project only covers Tayside then you would not nessesarily get a record with 1 if they moved to Glasgow but would still get the old record from Tayside with 0 for current record. + 1 if the record is still active in the given healthboard (e.g.. Tayside) or 0 if a more recent record exists in another healthboard (i.e. they are known to have moved out of the area or if ISD no longer supplies the record). Note that if your research project only covers Tayside then you would not necessarily get a record with 1 if they moved to Glasgow but would still get the old record from Tayside with 0 for current record. @@ -197,7 +197,7 @@ - Indicates that the chi number recorded (in the chi field) is out of date and that the person should actually be known by this alias. This occurs when a patient doesn't know thier chi or is unable to + Indicates that the chi number recorded (in the chi field) is out of date and that the person should actually be known by this alias. This occurs when a patient doesn't know their chi or is unable to supply it (e.g. an emergency appointment while on holiday). @@ -308,7 +308,7 @@ - The date when the patient moved from thier previous address to the current address. + The date when the patient moved from their previous address to the current address. @@ -773,20 +773,20 @@ Carotid ultrasound tests for blocked or narrowed carotid arteries, which can inc - The primary presenting condition and the reason for hospitalisation. This is either an ICD10 code or an ICD9 code. ICD9 codes are preceeded by a minus symbol to distinguish them. + The primary presenting condition and the reason for hospitalisation. This is either an ICD10 code or an ICD9 code. ICD9 codes are preceded by a minus symbol to distinguish them. - The second condition for hospitalisation. This is either an ICD10 code or an ICD9 code. ICD9 codes are preceeded by a minus symbol to distinguish them. + The second condition for hospitalisation. This is either an ICD10 code or an ICD9 code. ICD9 codes are preceded by a minus symbol to distinguish them. - The tertiary condition for hospitalisation. This is either an ICD10 code or an ICD9 code. ICD9 codes are preceeded by a minus symbol to distinguish them. + The tertiary condition for hospitalisation. This is either an ICD10 code or an ICD9 code. ICD9 codes are preceded by a minus symbol to distinguish them. - The forth condition for hospitalisation. This is either an ICD10 code or an ICD9 code. ICD9 codes are preceeded by a minus symbol to distinguish them. + The forth condition for hospitalisation. This is either an ICD10 code or an ICD9 code. ICD9 codes are preceded by a minus symbol to distinguish them. @@ -837,7 +837,7 @@ Carotid ultrasound tests for blocked or narrowed carotid arteries, which can inc - Generates a dataset with 20,000 columns of data in a veriety of formats. This is useful for testing very wide tables that are too wide for most RDBMS without special treatment (e.g. SPARSE columns). + Generates a dataset with 20,000 columns of data in a variety of formats. This is useful for testing very wide tables that are too wide for most RDBMS without special treatment (e.g. SPARSE columns). @@ -847,7 +847,7 @@ Carotid ultrasound tests for blocked or narrowed carotid arteries, which can inc - Generates a dataset with 980 columns of data in a veriety of formats. This is useful for testing very wide tables that still fit into most RDBMS without special treatment (e.g. SPARSE columns). + Generates a dataset with 980 columns of data in a variety of formats. This is useful for testing very wide tables that still fit into most RDBMS without special treatment (e.g. SPARSE columns).