diff --git a/025_Work_with_variable_data/025_csharp.md b/025_Work_with_variable_data/025_csharp.md index 06b126b..dbdca22 100644 --- a/025_Work_with_variable_data/025_csharp.md +++ b/025_Work_with_variable_data/025_csharp.md @@ -702,3 +702,298 @@ folder code for this exercise. Type exit, at the app menu, to end the program and then close the terminal panel. + +--- + +## Exercise + +### Add dog search + +In this exercise, you add the feature "Display all dogs with a specified +characteristic" (menu item #2) to the application. The exercise uses the +solution project from the previous exercise that added suggestedDonation data. + +> Note +> This is a "minimal viable product" (MVP) feature. A MVP feature is intended +to be a simple working prototype of a feature that enables quick and easy +delivery. A MVP is not usually a final product, it is intended to help you work +through an idea, test it, and gather further requirements. + +The search feature prompts the user for a single search input term (or phrase) +that describes a characteristic desired in a pet to adopt. Then, the +descriptions for adoptable dogs are searched for exact matches of the user +input. Information about the dogs that match are output to the console. If no +matches are identified, then a message "None of our dogs are a match" is +displayed along with the search term used. + +The tasks that you complete during this exercise are: + +- Gather user input for the pet characteristic search term +- Loop through the animals array and identify "dogs" +- For each dog, search the pet description for a term match +- Display the dogs that have a term match + +#### Gather user input for the pet characteristic search + +Review the menu switch statement following comment #5 in the Project.cs code. +You discover the code that displays the "*UNDER CONSTRUCTION*" message. + +Delete the code +`Console.WriteLine("\nUNDER CONSTRUCTION - please check back next month to see progress.");` +between `case "2":` and the +`Console.WriteLine("Press the Enter key to continue.");` +statement so the code matches the following sample: + +```cs +case "2": + // Display all dogs with a specified characteristic + Console.WriteLine("Press the Enter key to continue."); + readResult = Console.ReadLine(); + break; +``` + +Add code to gather user input for the `dogCharacteristic` string. Gather the +input requires a `while` loop that continues to prompt the user until they +submit an input. The loop instructs the user to "*Enter one desired dog +characteristic to search for*". Entering an empty string repeats the loop. +Place the following code following `case "2":` just before the `break;` +statement as shown: + +```cs +case "2": + // Display all dogs with a specified characteristic + string dogCharacteristic = ""; + while (dogCharacteristic == "") { + // have the user enter physical characteristics to search for + Console.WriteLine($"\nEnter one desired dog characteristics to search for"); + readResult = Console.ReadLine(); + if (readResult != null) { + dogCharacteristic = readResult.ToLower().Trim(); + } + } + Console.WriteLine("Press the Enter key to continue."); + readResult = Console.ReadLine(); + break; +``` + +Review the added code. The main features of the `case "2":` code include: + +- The code starts with a string declaration `string dogCharacteristic = "";` +that is scoped to `case "2":`. You won't be able to utilize `dogCharacteristic` +anywhere outside of the case statement code. +- After `Console.ReadLine()` gathers user input as `dogCharacteristic` it +ensures value isn't null, and sets the string to lowercase and trims the +surrounding spaces. +- If `dogCharacteristic` has a null value, then the loop repeats gathering +input. + +Save your code, then compile by using `dotnet build` in the TERMINAL (you can +refer to the steps in the previous exercise) and fix any errors. + +Run the code by using `dotnet run`. + +Test the search term input functionality of the app by entering `2` to select +Menu Option "2" searching. + +Press "**Enter**" without entering data at the "*Enter one desired dog +characteristic to search for*" prompt. The program should return to the "Enter +one desired dog characteristics to search for" prompt. + +The program should return to the prompt until characters are entered. + +At the prompt test search term entry "*golden*". The program should return to +the menu without error. + +At the menu, type "Exit" to exit the program. + +#### Identify which animals are dogs + +Now you add a feature to search using the user input `dogCharacteristic` within +the dog descriptions following the previous code under `case "2"`. But first +you need to identify the dogs. + +At the end of `case "2"` code, just before the code +`Console.WriteLine("\n\rPress the Enter key to continue");`, which is before the +`break;`, add the following code: + +```cs +// #6 loop through the ourAnimals array to search for matching animals +for (int i = 0; i < maxPets; i++) { + if (ourAnimals[i, 1].Contains("dog")) { + // #7 Search combined descriptions and report results + } +} +``` + +Take a minute to examine the loop added to the end of the `case "2":` code. + +The code filters for "dogs" using `ourAnimals[i,1]`, where `animalSpecies` data +is stored. If `animalSpecies` is storing "*dog*" then the code moves into the +brackets of the if statement where the search of the combined descriptions can +occur. + +Compile your code by using `dotnet build` and fix any errors. + +#### Search the combined description information of dogs + +The previous code ensures that you search only dog descriptions. Now you need +to search the dog descriptions and output information about matches. + +While thinking about the descriptions, you realize there are two descriptions +`animalPhysicalDescription` and `animalPersonalityDescription`. After +consulting, the team decides that a combined description is appropriate for the +search. + +> Note +> Some developers refer to the addition of requirements during development as +"scope creep." Although combining the descriptions is not a lot of work, it +still adds time and complexity. For this reason, you should let the team know +that added requirements will likely delay the completion of the project. + +#### Combine the dog descriptions to make it easier to search + +You need to declare a string, `dogDescription` to hold the combined data that +originated from `animalPhysicalDescription` and `animalPersonalityDescription`. + +Declare `dogDescription` just before comment #6 with the following code: + +```cs +string dogDescription = ""; +``` + +Now you can use the `dogDescription` string declared you need to populate it +with the two descriptions for each animal + +Using the `dogDescription` variable populate it with `animalPhysicalDescription` +and `animalPersonalityDescription`. + +Add the following code after comment # 7: + +```cs +dogDescription = ourAnimals[i, 4] + "\n" + ourAnimals[i, 5]; +``` + +#### Search the combined descriptions of dogs and display + +Now you add the search for `dogCharacteristic` in the combined data of +`dogDescription`. You need to add an if statement to determine if you have a +match for the search for each dog. + +Update the code following comment #7, after +`dogDescription = ourAnimals[i, 4] + "\n" + ourAnimals[i, 5];` with the code: + +```cs +if (dogDescription.Contains(dogCharacteristic)) { + Console.WriteLine($"\nOur dog {ourAnimals[i, 3]} is a match!"); + Console.WriteLine(dogDescription); +} +``` + +Examine the previous code example, when the if statement finds a match for +`dogCharacteristic` in `dogDescription` a message about the dog match and +description is output to the console. You still need to account for the "no matches found" message. + +Add the code `noMatchesDog = true`: + +Add the following code just before comment #6: + +```cs +bool noMatchesDog = true; +``` + +Now you can track when no matches are found with this tracking variable. When +the default is set to `true` that means "it's true that no dogs match for the +search." Now, when a dog is found you can "flip" the `noMatchesDog` from `true` +to `false` + +In the brackets of the `if (dogDescription.Contains(dogCharacteristic))` +statement, add the following code: + +```cs +noMatchesDog = false; +``` + +Review that your code within the brackets of +`if (dogDescription.Contains(dogCharacteristic))` was entered properly. + +You should have the following code: + +```cs + if (dogDescription.Contains(dogCharacteristic)) { + Console.WriteLine($"\nOur dog {ourAnimals[i, 3]} is a match!"); + Console.WriteLine(dogDescription); + noMatchesDog = false; + } +``` + +Finally, you need to create code that decides if the "no matches found" message +should be written to the console. + +At the end of `case "2"` code, just before the code +`Console.WriteLine("\n\rPress the Enter key to continue");`,which is before the +`break;`, add the following code: + +```cs +if (noMatchesDog) { + Console.WriteLine("None of our dogs are a match found for: " + dogCharacteristic); +} +``` + +That's the the final code for this exercise! + +Save your changes. + +#### Check your work + +At the TERMINAL command prompt, to build your project code, enter the following +command: `dotnet build`. + +If there are errors you need read the error messages, trouble shoot and make +fixes or review the solution code in the "Final" folder. + +Run your project code in the terminal with `dotnet run`. + +When the code runs two menu items are displayed. + +At the menu, enter "`2`" and "Enter" to test the dog search repeatedly. + +```txt + - Enter nothing as input to test the null entry behavior + - Enter "scuba" as input to test the "match not found" + - Enter "golden" to get two matches + - Enter "medium" to get one match +``` + +If everything worked as expected in both steps, congratulations! Otherwise, +look for the errors by checking the exercise steps. If needed, start over or +check the Final folder code for solution code to this exercise. + +Type `exit`, at the app menu, to end the program and then close the terminal +panel. + +--- + +### Summary + +You updated the pet adoption application in this guided project to support +single term search functionality, improve readability of output, and add a +suggested donation to descriptions. + +In this module, you practiced your ability to: + +- Apply iteration statements to gather data input. +- Use data processing. +- Format data output. +- Choose the correct data types and safely converting data types. +- Create two dimensional arrays of numbers and strings. +- Search data in arrays to display or update data. +- Modify and build complex strings from multiple data sources, and format data +for display across regions. + +You delivered functionality to your Contos pet app team, including: + +- Gather the pet characteristic search term input. +- Iterate through the animals array and identify "dogs." +- Search the description for a term match, for each dog. +- Display the dogs that have a term match. +- Provide suggested donation data formatted in local currency. diff --git a/025_Work_with_variable_data/GuidedProject/Own/Program.cs b/025_Work_with_variable_data/GuidedProject/Own/Program.cs index cc71f21..0d07a20 100644 --- a/025_Work_with_variable_data/GuidedProject/Own/Program.cs +++ b/025_Work_with_variable_data/GuidedProject/Own/Program.cs @@ -1,4 +1,4 @@ -int max_pets = 8; +const int max_pets = 8; bool exit = false; string? selection; const string WIP = "Under Construction - please check " + @@ -36,8 +36,9 @@ string[] options = { "1", "2", "3", "4", "5", "6", "7", "8", "exit" }; string[] nickname = { "lola", "loki", "fuzz", "boby", "gogo", "besti" }; string[] species = { "cat", "dog", "bee", "pig", "fly", "rat", "bat" }; string[] abcd = { "a", "b", "c", "d" }; +decimal[] donations = { 85.00M, 49.99M, 40.00M, 45.00M }; int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8 }; -string[,] our_animals = new string[max_pets, 6]; +string[,] our_animals = new string[max_pets, 7]; Random rand = new Random(); var clear = Console.Clear; @@ -60,6 +61,11 @@ int rand_int(int[] choices) { return choices[indx]; } +decimal rand_dec(decimal[] choices) { + int indx = rand.Next(choices.Length); + return choices[indx]; +} + string get_uniq_id(string[,] animals) { for (int i = 0; i < max_pets - 4; i++) { bool uniq_id = false; @@ -90,6 +96,7 @@ void populate_animals_array() { our_animals[i, 3] = $"{rand_int(nums)}"; our_animals[i, 4] = rand_str(personality); our_animals[i, 5] = rand_str(nickname); + our_animals[i, 6] = $"{rand_dec(donations):C2}"; } } @@ -100,9 +107,11 @@ void press_enter(string msg = "\n\tPress 'Enter' to continue") { void print_pets(string[,] animals) { clear(); + int outher_length = animals.GetLength(0); + int inner_length = animals.GetLength(1); print(separator); - for (int j = 0; j < animals.GetLength(0); j++) { - string[] animal = new string[6]; + for (int j = 0; j < outher_length; j++) { + string[] animal = new string[inner_length]; for (int k = 0; k < animals.GetLength(1); k++) { animal[k] = animals[j, k]; } @@ -120,10 +129,12 @@ void print_pet(string[] pet) { string year_word = age > 1 ? "years" : "year"; string desc = pet[2]; string perso = pet[4]; + string donation = pet[6]; print($@" ID: {id} SPECIE: {specie} NAME: {name} AGE: {age} {year_word} DESCRIPTION: {desc} PERSONALITY: {perso} + SUGGESTED DONATION: {donation} {separator}"); } } @@ -140,7 +151,8 @@ int availability(string[,] animals) { } string get_input(string text = "Please enter your text: ", - bool integer = false, + bool is_integer = false, + bool is_money = false, string[]? opts = null) { bool invalid = true; while (invalid) { @@ -148,11 +160,17 @@ string get_input(string text = "Please enter your text: ", string? usr_in = Console.ReadLine(); if (!string.IsNullOrEmpty(usr_in) && usr_in.Trim() != "") { string resp = usr_in.Trim(); - if (integer) { + if (is_integer) { int temp_int; if (int.TryParse(resp, out temp_int)) { return resp; } + } else if (is_money) { + decimal temp_dec; + if (decimal.TryParse(resp, out temp_dec)) { + resp = $"{temp_dec:C2}"; + return resp; + } } else if (opts != null) { resp = resp.ToLower(); if (opts.Contains(resp)) { @@ -175,9 +193,10 @@ string get_input(string text = "Please enter your text: ", void add_new_pet(string[,] animals, int slots) { int at_indx = max_pets - slots; string id = $"{rand_str(abcd)}{rand_int(nums)}"; - string specie = get_input("Enter pet specie: ", false, species); + string specie = get_input("Enter pet specie: ", false, false, species); string name = get_input("Enter the pet name (? if unknown): "); int age = Int32.Parse(get_input("Enter pet age (-1 if unknown): ", true)); + string donation = get_input("Enter suggested donation: ", false, true); string desc = get_input("Enter the physical description (? if unknown): "); string perso = get_input("Enter pet personality (? if unknown): "); animals[at_indx, 0] = specie; @@ -186,6 +205,7 @@ void add_new_pet(string[,] animals, int slots) { animals[at_indx, 3] = age.ToString(); animals[at_indx, 4] = perso; animals[at_indx, 5] = name; + animals[at_indx, 6] = donation; } void ask_new_pet() { @@ -303,6 +323,31 @@ void check_nick_and_perso(string[,] animals) { press_enter(); } +void search_specie_by_desc(string specie, string[,] animals) { + clear(); + bool found = false; + string detail = get_input( + $"Enter one desired {specie} characteristics to search for: " + ); + for (int j = 0; j < animals.GetLength(0); j++) { + if (!string.IsNullOrEmpty(animals[j, 1])) { + if (animals[j, 0] == specie) { + string description = " " + animals[j, 2] + + "\n " + animals[j, 4]; + if (description.Contains(detail)) { + found = true; + print($"\nOur {specie} {animals[j,5]} is a match!"); + print($"{description}"); + print($"{separator}"); + } + } + } + } + if (!found) { + print($"None of our {specie}s are a match found for: {detail}"); + } + press_enter(); +} populate_animals_array(); @@ -336,17 +381,13 @@ while (!exit) { press_enter(); break; case "7": - clear(); - print(WIP); - press_enter(); + search_specie_by_desc("cat", our_animals); break; case "8": - clear(); - print(WIP); - press_enter(); + search_specie_by_desc("dog", our_animals); break; case "exit": - print("\n\tTerminating application\n"); + print("\n\tClosing application\n"); exit = !exit; break; default: