This commit is contained in:
ipvg 2024-08-05 00:19:22 -04:00
parent 66f2b231e7
commit 74ae016548
9 changed files with 1362 additions and 0 deletions

View File

@ -0,0 +1,481 @@
# Challenge project
## Work with variable data in C#
Demonstrate your ability to develop a console app that implements data
formatting and using arrays to deliver a multiple term search feature.
### Learning objectives
Apply iteration statements using data input.
- Process data.
- Format data output.
- Choose the correct data types and safely converting data types.
- Create and manipulate string arrays, and sort array data.
- Modify and build complex strings from multiple data sources, and format data
for display.
## Introduction
Suppose you're one of the developers working on the Contoso Pets adoption
application to help find new homes for pets. Your starting version of the
application gathers a single search term used to search the descriptions of
dogs. A single term search is helpful, but the feedback given from the team is
the application needs more search functionality. The team wants you to extend
the search functionality to allow for multiple term searches. Additionally, the
team wants to pilot an update to the "search status" animation that shows
search progress.
In this challenge coding project, your C# data knowledge and skills are applied
for:
- Creating string arrays by splitting strings
- Manipulating array data, iterating through elements in an array, and sorting array data
- Modifying and building strings from multiple data sources
In short, you'll:
- Develop multi-term search functionality for the "dogs" search
- Update the "search status" animation, information and countdown
By the end of this module, you complete an updated version of the Contoso Pets
application that searches all dogs available for adoption using multiple search
terms and an improved search status simulation.
---
### Project specification overview
Update the existing Contoso Pets starter application to include multiple term
search and improved "search status" animation features:
#### Add dog attribute multi-term search
Gather user input for the pet characteristic multiple term search
- Users need to provide search terms separated by commas
- Store the search terms in an array and sort the terms alphabetically
Within the animals array loop that identifies "dogs":
- Iterate through the search terms to search each dog's description
- Search the combined description for a term match
- Output each dog's description where there's one or more terms matched
After exiting the "search Animals" array loop that identifies dogs:
If no dogs were a match for any of the users provided search terms, output a no
dogs matched message.
#### Add "search status" improvements
Update the animation
- Adjust the searchingIcons array to resemble a spinning dial
- Adjust the animation loop so the animation shows a numeric countdown from two to zero (2.., 1.., 0..)
#### Starter code
The starter code project for this challenge project module includes a Program
.cs file that provides the following code features:
The code declares variables used to collect and process pet data and menu item
selections
The code declares the ourAnimals array
The code uses a for loop around an if-elseif-else construct to populate the
ourAnimals array with a sample dataset
The code displays the following main menu options for user selection:
```txt
1. List all of our current pet information
2. Display all dogs with a specified characteristic
Enter menu item selection or type "Exit" to exit the program
```
The application menu code reads the user's menu item selection and displays a
message echoing their selection
Case 1: "List all of our current pet information" displays the sample data for
all animals (two dogs and two cats)
Case 2: "2. Display all dogs with a specified characteristic" is the primary
area where new functionality code is added
- Under Case 2, the starter code identifies dogs and searches for a single
user input term
- Before you search each dog, the console shows a simple "animation" that
simulates a status for searching occurring
Your goal is to update the existing code to develop key features requested by
your team:
- Add dog multiple attribute search
- Update search animation
Use your development environment, and test your application at each stage of
your development process.
#### Setup
Download a
[zip](https://github.com/MicrosoftLearning/Challenge-project-Work-with-variable-data-in-CSharp/archive/refs/heads/main.zip)
file containing the code folders for the challenge project.
Build and run the file entering `dotnet run` in the terminal window.
The menu should display with two options. Enter `1` as shown in the following
terminal example:
```txt
Welcome to the Contoso PetFriends app. Your main menu options are:
1. List all of our current pet information
2. Display all dogs with a specified characteristic
Enter your selection number (or type Exit to exit the program)
1
```
The sample data on the current pets should display followed by the message
`Press the Enter key to continue`
After pressing Enter, the menu should display again. Choose Option `2`, shown
in the following example:
```txt
Welcome to the Contoso PetFriends app. Your main menu options are:
1. List all of our current pet information
2. Display all dogs with a specified characteristic
Enter your selection number (or type Exit to exit the program)
2
Enter one desired dog characteristic to search for
```
Enter "large" for the search term and press "Enter."
Notice the "searching" message as shown:
```txt
searching our dog Nickname: gus for large ...
```
Notice, the message runs before each search of a pet, and the periods
(`., .., ...`) at the end change in an animation. Run the search again if you
missed it.
Once the search ends, press enter to return to the menu. Then type "exit" and
press "Enter" to close the application.
Take a few minutes to become familiar with the Project.cs started code.
Focus on the areas that require updates, search and the animation.
Notice that there are some comments left in the code that indicate where to
place an update.
You're now ready to begin the Guided project exercises. Good luck!
---
### Add multiple term search support
The Contoso Pets app helps find new homes for abandoned pets. The team wants
the search feature improved to let users enter multiple terms when searching
for dogs to adopt.
### Search specification
In this first challenge exercise, you need to update the single term search
feature to allow users to enter multiple search terms separated by commas.
#### Gather multiple search terms from the user
- Allow the user to enter multiple search terms when searching for dogs
- The user needs instructions to "enter the search terms separated by commas"
- Separate out individual search terms from the user entry string and store as
values in an array
- Sort the terms in the array in alphanumeric sort order
#### Identify dogs with descriptions with matches for one, or more, user search term
- As you identify a dog in the `animalsArray`, search for matches for each term
the user has entered
- For a term match, output a message with the dogs name and the term that is
matched
- example: `Our dog Jake is a match for your search for sheppard!`
- When all term searches complete for the current dog description:
- For one or more matches, output the nickname and description for the
current dog
- For one or more matches, track that there has been a match so you know not
to display an "no matches found for any available dogs" message (refer to the
next item)
- After **all** dog searches complete with no matches, display a message "No
matches found for any available dogs"
#### Enforce the following validation rules
- values can't be null
- values can't have zero characters
- any further restriction is up to the developer
#### Code comments
- Numbered code comments in the starter code offer suggestions
- The comments are in a sequential order and only the comments starting with #1, #2, and #3 apply to this exercise of the challenge
#### Sample output
Review the following animated image
Notice the temporary display of "`searching...`" followed by the current term
(example: "`searching...retriever`")
Notice the order the terms appear in search is now in alphanumeric
Notice the messages for matches persist (example:
"`Our dog lola is a chase match!`")
Review the sample output in the following section, "How to check your work", to further clarify how to implement features
### How to check your work
To validate that your code satisfies the specified requirements.
Build and run your app.
> Note
> You can exit the verification test before completing all of the verification
steps if see a result that does not satisfy the specification requirements. To
force an exit from the running program, in the Terminal panel, press Ctrl-C.
After exiting the running app, complete the edits that you believe will address
the issue you are working on, save your updates to the Program.cs file, and
then re-build and run your code.
The terminal command prompt should display as the starting point for the
program
At the command prompt, enter 2 menu:
```txt
Welcome to the Contoso PetFriends app. Your main menu options are:
1. List all of our current pet information
2. Display all dogs with a specified characteristic
Enter your selection number (or type Exit to exit the program)
2
Enter dog characteristics to search for separated by commas
```
At the command prompt, enter large, cream, golden to test when more than one
search term matches the dog descriptions. Verify that the Terminal panel
updates with a message similar to the code output sample:
```txt
Enter dog characteristics to search for separated by commas
large, cream, golden
Our dog Nickname: lola matches your search for cream
Our dog Nickname: lola matches your search for golden
Nickname: lola (ID #: d1)
Physical description: medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.
Personality: loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.
Our dog Nickname: gus matches your search for golden
Our dog Nickname: gus matches your search for large
Nickname: gus (ID #: d2)
Physical description: large reddish-brown male golden retriever weighing about 85 pounds. housebroken.
Personality: loves to have his ears rubbed when he greets you at the door, or at any time! loves to lean-in and give doggy hugs.
Press the Enter key to continue
```
At the command prompt, press the enter key to continue to the main menu
At the command prompt, enter 2 menu:
```txt
Welcome to the Contoso PetFriends app. Your main menu options are:
1. List all of our current pet information
2. Display all dogs with a specified characteristic
Enter your selection number (or type Exit to exit the program)
2
Enter dog characteristics to search for separated by commas
```
At the command prompt, enter big, grey, stripes to test when none of the search
terms match dog descriptions. Verify that the Terminal panel updates with a
message similar to the code output samples:
```txt
Enter dog characteristics to search for separated by commas
big, grey, stripes
None of our dogs are a match for: big, grey, stripes
Press the Enter key to continue
```
If you specified further restrictions for valid entries, run the appropriate
test cases to verify your work.
> Note
> If your code meets the requirements you should be able to complete each step
in order and see the expected results in a single test pass. If you added
additional restrictions, you may need to exit the application and then run a
separate test pass to complete your verification.
Congratulations if you succeeded in this challenge exercise!
---
## Exercise
### Add improved search animation
The Contoso Pets app helps find new homes for abandoned pets. Part of the
request for search feature improvement is to update the animated simulation
indicating search progress.
#### Search animation specification
In this second challenge exercise, you need to update the search animation to
resemble spinning and add a count down (2, 1, 0).
#### Change the current "searching" animation icons
Update the current animation "icons"
`string[] searchingIcons = {". ", ".. ", "..."};`
Use new icons that simulate spinning
You can design the "searching" animation to display "spinning" to work
differently than displayed in the animated image
The "searching..." animation, should continue to be overwritten, after each
animation completes so it stays on the same line, and so that it doesn't
display after the animation stops.
#### Add a countdown to the "searching" animation
Review the previous animated image - note the countdown in the output
"`searching...retriever / 2`"
The previous number "`2`" displays as "`1`", and finally as "`0`", counting down
Update the loop that contains the "searching" animation so that the loop can
display a countdown
##### Code comments
- Numbered code comments in the starter code offer suggestions
- The comments are in a sequential order and only the comments starting with #4, and #5 apply to this exercise of the challenge
#### How to check your work
To validate that your code satisfies the specified requirements, complete the
instruction steps:
Build and run your app.
> Note
> You can exit the verification test before completing all of the verification
steps if see a result that does not satisfy the specification requirements. To
force an exit from the running program, in the Terminal panel, press Ctrl-C.
After exiting the running app, complete the edits that you believe will address
the issue you are working on, save your updates to the Program.cs file, and
then re-build and run your code.
The terminal command prompt should display as the starting point for the
program
At the command prompt, enter 2 menu:
```txt
Welcome to the Contoso PetFriends app. Your main menu options are:
1. List all of our current pet information
2. Display all dogs with a specified characteristic
Enter your selection number (or type Exit to exit the program)
2
Enter dog characteristics to search for separated by commas
```
At the command prompt, enter **golden, big** and press enter to test the search
status messages with animation and countdown
Verify that the console panel updates with temporary "searching" status
messages similar to the code output samples:
```txt
Enter dog characteristics to search for separated by commas
golden, big
searching our dog Nickname: lola for big / 2
```
```txt
searching our dog Nickname: lola for big -- 1
```
```txt
searching our dog Nickname: lola for golden \ 1
```
```txt
searching our dog Nickname: lola for golden * 0
```
All the user entered search terms should display with the "`searching`" spin
animation and countdown for each dog where the "searching our dog..." line in
the output overwrites the previous line to create an animation
Refer to the previous animated image of the running program for more examples
of the "searching" status animation with countdown
Validate after the searching has stopped, the "`searching`" animation and
countdown no longer displays
> Note
> If your code meets the requirements you should be able to complete each step
in order and see the expected results in a single test pass.
Congratulations if you succeeded in this exercise challenge!
- [Challenge](./Challenge-Variable_data/Own/Program.cs)
---
### Summary
Your challenge was to update an application to support multiple term search and
to improve the "search status" information animation.
In this module, you developed code that combines:
- Iterate using data input.
- Process data.
- Format data output.
- Choose the correct data types and safely convert data types.
- Create and manipulate string arrays, and sort array data.
- Modify and build complex strings from multiple data sources, and format data
for display.
You delivered functionality to your Contoso pet app team, including:
- Gather the pet characteristics for multiple search term inputs.
- Store search input terms in a sorted array.
- Display the dogs that have a term match.
- Provide an improved search status animation with a countdown.

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,207 @@
// Final
// ourAnimals array will store the following:
string animalSpecies = "";
string animalID = "";
string animalAge = "";
string animalPhysicalDescription = "";
string animalPersonalityDescription = "";
string animalNickname = "";
string suggestedDonation = "";
// variables that support data entry
int maxPets = 8;
string? readResult;
string menuSelection = "";
decimal decimalDonation = 0.00m;
// array used to store runtime data
string[,] ourAnimals = new string[maxPets, 7];
// sample data ourAnimals array entries
for (int i = 0; i < maxPets; i++) {
switch (i) {
case 0:
animalSpecies = "dog";
animalID = "d1";
animalAge = "2";
animalPhysicalDescription = "medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.";
animalPersonalityDescription = "loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.";
animalNickname = "lola";
suggestedDonation = "85.00";
break;
case 1:
animalSpecies = "dog";
animalID = "d2";
animalAge = "9";
animalPhysicalDescription = "large reddish-brown male golden retriever weighing about 85 pounds. housebroken.";
animalPersonalityDescription = "loves to have his ears rubbed when he greets you at the door, or at any time! loves to lean-in and give doggy hugs.";
animalNickname = "gus";
suggestedDonation = "49.99";
break;
case 2:
animalSpecies = "cat";
animalID = "c3";
animalAge = "1";
animalPhysicalDescription = "small white female weighing about 8 pounds. litter box trained.";
animalPersonalityDescription = "friendly";
animalNickname = "snow";
suggestedDonation = "40.00";
break;
case 3:
animalSpecies = "cat";
animalID = "c4";
animalAge = "";
animalPhysicalDescription = "";
animalPersonalityDescription = "";
animalNickname = "lion";
suggestedDonation = "";
break;
default:
animalSpecies = "";
animalID = "";
animalAge = "";
animalPhysicalDescription = "";
animalPersonalityDescription = "";
animalNickname = "";
suggestedDonation = "";
break;
}
ourAnimals[i, 0] = "ID #: " + animalID;
ourAnimals[i, 1] = "Species: " + animalSpecies;
ourAnimals[i, 2] = "Age: " + animalAge;
ourAnimals[i, 3] = "Nickname: " + animalNickname;
ourAnimals[i, 4] = "Physical description: " + animalPhysicalDescription;
ourAnimals[i, 5] = "Personality: " + animalPersonalityDescription;
if (!decimal.TryParse(suggestedDonation, out decimalDonation)) {
decimalDonation = 45.00m; // if suggestedDonation NOT a number, default to 45.00
}
ourAnimals[i, 6] = $"Suggested Donation: {decimalDonation:C2}";
}
// top-level menu options
do {
// NOTE: the Console.Clear method is throwing an exception in debug sessions
Console.Clear();
Console.WriteLine("Welcome to the Contoso PetFriends app. Your main menu options are:");
Console.WriteLine(" 1. List all of our current pet information");
Console.WriteLine(" 2. Display all dogs with a specified characteristic");
Console.WriteLine();
Console.WriteLine("Enter your selection number (or type Exit to exit the program)");
readResult = Console.ReadLine();
if (readResult != null) {
menuSelection = readResult.ToLower();
}
// switch-case to process the selected menu option
switch (menuSelection) {
case "1":
// list all pet info
for (int i = 0; i < maxPets; i++) {
if (ourAnimals[i, 0] != "ID #: ") {
Console.WriteLine();
for (int j = 0; j < 7; j++) {
Console.WriteLine(ourAnimals[i, j].ToString());
}
}
}
Console.WriteLine("\r\nPress the Enter key to continue");
readResult = Console.ReadLine();
break;
case "2":
// #1 Display all dogs with a multiple search characteristics
string dogCharacteristics = "";
while (dogCharacteristics == "") {
// #2 have user enter multiple comma separated characteristics to search for
Console.WriteLine($"\nEnter dog characteristics to search for separated by commas");
readResult = Console.ReadLine();
if (readResult != null) {
dogCharacteristics = readResult.ToLower();
Console.WriteLine();
}
}
string[] dogSearches = dogCharacteristics.Split(",");
// trim leading and trailing spaces from each search term
for (int i = 0; i < dogSearches.Length; i++) {
dogSearches[i] = dogSearches[i].Trim();
}
Array.Sort(dogSearches);
// #4 update to "rotating" animation with countdown
string[] searchingIcons = { " |", " /", "--", " \\", " *" };
bool matchesAnyDog = false;
string dogDescription = "";
// loops through the ourAnimals array to search for matching animals
for (int i = 0; i < maxPets; i++) {
if (ourAnimals[i, 1].Contains("dog")) {
// Search combined descriptions and report results
dogDescription = ourAnimals[i, 4] + "\n" + ourAnimals[i, 5];
bool matchesCurrentDog = false;
foreach (string term in dogSearches) {
// only search if there is a term to search for
if (term != null && term.Trim() != "") {
for (int j = 2; j > -1; j--) {
// #5 update "searching" message to show countdown
foreach (string icon in searchingIcons) {
Console.Write($"\rsearching our dog {ourAnimals[i, 3]} for {term.Trim()} {icon} {j.ToString()}");
Thread.Sleep(100);
}
Console.Write($"\r{new String(' ', Console.BufferWidth)}");
}
// #3a iterate submitted characteristic terms and search description for each term
if (dogDescription.Contains(" " + term.Trim() + " ")) {
// #3b update message to reflect current search term match
Console.WriteLine($"\rOur dog {ourAnimals[i, 3]} matches your search for {term.Trim()}");
matchesCurrentDog = true;
matchesAnyDog = true;
}
}
}
// #3d if the current dog is match, display the dog's info
if (matchesCurrentDog) {
Console.WriteLine($"\r{ourAnimals[i, 3]} ({ourAnimals[i, 0]})\n{dogDescription}\n");
}
}
}
if (!matchesAnyDog) {
Console.WriteLine("None of our dogs are a match found for: " + dogCharacteristics);
}
Console.WriteLine("\n\rPress the Enter key to continue");
readResult = Console.ReadLine();
break;
default:
break;
}
}
while (menuSelection != "exit");

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Microsoft Learning
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,434 @@
const int max_pets = 8;
bool exit = false;
string? selection;
const string WIP = "Under Construction - please check " +
"back next month to see progress.";
const string separator = "+-------------------------------------" +
"----------------------------------------+";
const string main_menu = $@"{separator}
Welcome to the Contoso PetFriends app. Your main menu options are:
{separator}
1. List all of our current pet information.
2. Assign values to the ourAnimals array fields.
3. Ensure animal ages and physical descriptions are complete.
4. Ensure animal nicknames and personality descriptions are complete.
5. Edit an animal's age.
6. Edit an animal's personality description.
7. Display all cats with a specified characteristics.
8. Display all dogs with a specified characteristics.
Enter menu item selection or type 'Exit' to exit the program
{separator}";
string[] description = {
"big sized female golden colored weighing 20 pounds. housebroken.",
"large dark-brown male siver back weighing 15 pounds. housebroken.",
"small white female weighing about 8 pounds. translucid.",
"medium size male. fluorescent at night.",
"medium size weighing 4 punds, orange with black lines.",
};
string[] personality = {
"friendly",
"loves to have his ears rubbed at any time! loves to lean-in.",
"loves to have her belly rubbed. gives lots of kisses.",
"sauvage and lovelly.",
"mad but cute",
"loves to play with a rope",
};
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", "cat", "cat" };
string[] abcd = { "a", "b", "c", "d" };
string[] icons = { "󰔟", "󱦟", "󱦠" };
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, 7];
Random rand = new Random();
var clear = Console.Clear;
void print(string text, bool new_line = true) {
if (new_line) {
Console.WriteLine(text);
} else {
Console.Write(text);
}
}
string rand_str(string[] choices) {
int indx = rand.Next(choices.Length);
return choices[indx];
}
int rand_int(int[] choices) {
int indx = rand.Next(choices.Length);
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;
while (!uniq_id) {
bool check = true;
string id = $"{rand_str(abcd)}{rand_int(nums)}";
for (int j = 0; j < max_pets - 4; j++) {
if (!string.IsNullOrEmpty(animals[j, 1]) && animals[j, 1] == id) {
uniq_id = false;
check = false;
break;
}
}
if (check) {
uniq_id = true;
return id;
}
}
}
return "?";
}
void populate_animals_array() {
for (int i = 0; i < max_pets - 4; i++) {
our_animals[i, 0] = rand_str(species);
our_animals[i, 1] = get_uniq_id(our_animals);
our_animals[i, 2] = rand_str(description);
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}";
}
}
void press_enter(string msg = "\n\tPress 'Enter' to continue") {
print(msg, false);
Console.ReadLine();
}
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 < outher_length; j++) {
string[] animal = new string[inner_length];
for (int k = 0; k < animals.GetLength(1); k++) {
animal[k] = animals[j, k];
}
print_pet(animal);
}
press_enter();
}
void print_pet(string[] pet) {
if (!string.IsNullOrEmpty(pet[1])) {
string id = pet[1];
string name = pet[5];
string specie = pet[0];
int age = Int32.Parse(pet[3].ToString());
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}");
}
}
int availability(string[,] animals) {
int pet_count = 0;
for (int j = 0; j < animals.GetLength(0); j++) {
if (!string.IsNullOrEmpty(animals[j, 1])) {
pet_count++;
}
}
int slots = max_pets - pet_count;
return slots;
}
string get_input(string text = "Please enter your text: ",
bool is_integer = false,
bool is_money = false,
string[]? opts = null) {
bool invalid = true;
while (invalid) {
print(text, false);
string? usr_in = Console.ReadLine();
if (!string.IsNullOrEmpty(usr_in) && usr_in.Trim() != "") {
string resp = usr_in.Trim();
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)) {
return resp;
} else {
print($"Please enter a valid option (", false);
foreach (string opt in opts) {
print($" {opt} ", false);
}
print(")");
}
} else {
return resp;
}
}
}
return "?";
}
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, 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;
animals[at_indx, 1] = id;
animals[at_indx, 2] = desc;
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() {
clear();
print("Assign values to the ourAnimals array fields");
print(separator);
int slots = availability(our_animals);
print($"\nWe currently have {max_pets - slots} pets that need homes.");
print($"We can manage {slots} more.");
if (slots > 0) {
bool another = false;
do {
string resp = get_input(
"Do you want to enter info for another pet?: "
);
bool invalid = true;
if (resp != "") {
while (invalid) {
switch (resp) {
case "y" or "yes":
add_new_pet(our_animals, slots);
resp = "";
invalid = false;
another = true;
break;
case "n" or "no":
invalid = false;
another = false;
break;
default:
resp = get_input("Please enter [Y]es or [N]o: ");
break;
}
}
}
slots = availability(our_animals);
} while (another && slots > 0);
if (slots == 0) {
print("We have reached our limit on the number of pets that we can manage.");
}
}
press_enter();
}
void check_age_and_desc(string[,] animals) {
clear();
print("\nEnsure animal ages and physical descriptions are complete");
int pet_count = max_pets - (availability(animals));
for (int j = 0; j < pet_count; j++) {
if (animals[j, 3] == "-1") {
print("\n" + separator);
string[] animal = {
animals[j,0], animals[j,1], animals[j,2],
animals[j,3], animals[j,4], animals[j,5]
};
print_pet(animal);
int age = Int32.Parse(
get_input(
$"Enter an age for ID: {animals[j, 1]}" +
" (-1 if unknown): ", true
)
);
animals[j, 3] = age.ToString();
}
if (animals[j, 2] == "?") {
print("\n" + separator);
string[] animal = {
animals[j,0], animals[j,1], animals[j,2],
animals[j,3], animals[j,4], animals[j,5]
};
print_pet(animal);
string desc = get_input(
$"Enter a physical description for ID: {animals[j, 1]}" +
" (? if unknown): "
);
animals[j, 2] = desc;
}
}
press_enter();
}
void check_nick_and_perso(string[,] animals) {
clear();
print("Ensure animal nicknames and personality descriptions are complete");
print(separator);
int pet_count = max_pets - (availability(animals));
for (int j = 0; j < pet_count; j++) {
if (animals[j, 5] == "?") {
print("\n" + separator);
string[] animal = {
animals[j,0], animals[j,1], animals[j,2],
animals[j,3], animals[j,4], animals[j,5]
};
print_pet(animal);
string nick = get_input(
$"Enter a nickname for ID: {animals[j, 1]}" +
"(? if unknown): "
);
animals[j, 5] = nick;
}
if (animals[j, 4] == "?") {
print("\n" + separator);
string[] animal = {
animals[j,0], animals[j,1], animals[j,2],
animals[j,3], animals[j,4], animals[j,5]
};
print_pet(animal);
string perso = get_input(
$"Enter a personality description for ID: {animals[j, 1]}" +
"(? if unknown): "
);
animals[j, 4] = perso;
}
}
press_enter();
}
bool search(string specie, string detail, string[,] animals) {
bool found = false;
for (int j = 0; j < animals.GetLength(0); j++) {
if (!string.IsNullOrEmpty(animals[j, 1])) {
if (animals[j, 0] == specie) {
for (int i=2; i>-1; i--) {
foreach (string icon in icons){
print(
$"\rsearching our {specie} {animals[j, 5]}" +
$" for {detail.Trim()} {icon} {i.ToString()}",
false
);
Thread.Sleep(200);
}
print($"\r{new String(' ', Console.BufferWidth)}", false);
}
string description = " " + animals[j, 2] +
"\n " + animals[j, 4];
if (description.Contains(detail)) {
found = true;
print($"\r{separator}");
print($"Our {specie} {animals[j, 5]} is a match!");
print($"{description}");
}
}
}
}
return found;
}
void search_specie_by_desc(string specie, string[,] animals) {
clear();
bool found = false;
string detail = get_input(
$"Enter {specie} characteristics to search for separated by commas: "
);
if (detail.IndexOf(',') >= 0) {
string[] details = detail.Split(',');
foreach (string characteristic in details) {
found = search(specie, characteristic.Trim(), animals);
}
} else {
found = search(specie, detail, animals);
}
if (!found) {
print($"None of our {specie}s are a match found for: {detail}");
}
print(separator);
press_enter();
}
populate_animals_array();
while (!exit) {
clear();
print(main_menu);
print(" >_", false);
selection = Console.ReadLine();
if (selection != null && options.Contains(selection.ToLower())) {
selection = selection.ToLower();
switch (selection) {
case "1":
print_pets(our_animals);
break;
case "2":
ask_new_pet();
break;
case "3":
check_age_and_desc(our_animals);
break;
case "4":
check_nick_and_perso(our_animals);
break;
case "5":
clear();
print(WIP);
press_enter();
break;
case "6":
clear();
print(WIP);
press_enter();
break;
case "7":
search_specie_by_desc("cat", our_animals);
break;
case "8":
search_specie_by_desc("dog", our_animals);
break;
case "exit":
print("\n\tClosing application\n");
exit = !exit;
break;
default:
print("\n\tPlease read the instructions");
press_enter();
break;
}
} else {
print("\n\tPlease read the instructions");
press_enter();
}
}
Environment.Exit(0);

View File

@ -0,0 +1,188 @@
// ourAnimals array will store the following:
string animalSpecies = "";
string animalID = "";
string animalAge = "";
string animalPhysicalDescription = "";
string animalPersonalityDescription = "";
string animalNickname = "";
string suggestedDonation = "";
// variables that support data entry
int maxPets = 8;
string? readResult;
string menuSelection = "";
decimal decimalDonation = 0.00m;
// array used to store runtime data
string[,] ourAnimals = new string[maxPets, 7];
// sample data ourAnimals array entries
for (int i = 0; i < maxPets; i++) {
switch (i) {
case 0:
animalSpecies = "dog";
animalID = "d1";
animalAge = "2";
animalPhysicalDescription = "medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.";
animalPersonalityDescription = "loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.";
animalNickname = "lola";
suggestedDonation = "85.00";
break;
case 1:
animalSpecies = "dog";
animalID = "d2";
animalAge = "9";
animalPhysicalDescription = "large reddish-brown male golden retriever weighing about 85 pounds. housebroken.";
animalPersonalityDescription = "loves to have his ears rubbed when he greets you at the door, or at any time! loves to lean-in and give doggy hugs.";
animalNickname = "gus";
suggestedDonation = "49.99";
break;
case 2:
animalSpecies = "cat";
animalID = "c3";
animalAge = "1";
animalPhysicalDescription = "small white female weighing about 8 pounds. litter box trained.";
animalPersonalityDescription = "friendly";
animalNickname = "snow";
suggestedDonation = "40.00";
break;
case 3:
animalSpecies = "cat";
animalID = "c4";
animalAge = "";
animalPhysicalDescription = "";
animalPersonalityDescription = "";
animalNickname = "lion";
suggestedDonation = "";
break;
default:
animalSpecies = "";
animalID = "";
animalAge = "";
animalPhysicalDescription = "";
animalPersonalityDescription = "";
animalNickname = "";
suggestedDonation = "";
break;
}
ourAnimals[i, 0] = "ID #: " + animalID;
ourAnimals[i, 1] = "Species: " + animalSpecies;
ourAnimals[i, 2] = "Age: " + animalAge;
ourAnimals[i, 3] = "Nickname: " + animalNickname;
ourAnimals[i, 4] = "Physical description: " + animalPhysicalDescription;
ourAnimals[i, 5] = "Personality: " + animalPersonalityDescription;
if (!decimal.TryParse(suggestedDonation, out decimalDonation)) {
decimalDonation = 45.00m; // if suggestedDonation NOT a number, default to 45.00
}
ourAnimals[i, 6] = $"Suggested Donation: {decimalDonation:C2}";
}
// top-level menu options
do {
// NOTE: the Console.Clear method is throwing an exception in debug sessions
Console.Clear();
Console.WriteLine("Welcome to the Contoso PetFriends app. Your main menu options are:");
Console.WriteLine(" 1. List all of our current pet information");
Console.WriteLine(" 2. Display all dogs with a specified characteristic");
Console.WriteLine();
Console.WriteLine("Enter your selection number (or type Exit to exit the program)");
readResult = Console.ReadLine();
if (readResult != null) {
menuSelection = readResult.ToLower();
}
// switch-case to process the selected menu option
switch (menuSelection) {
case "1":
// list all pet info
for (int i = 0; i < maxPets; i++) {
if (ourAnimals[i, 0] != "ID #: ") {
Console.WriteLine();
for (int j = 0; j < 7; j++) {
Console.WriteLine(ourAnimals[i, j].ToString());
}
}
}
Console.WriteLine("\r\nPress the Enter key to continue");
readResult = Console.ReadLine();
break;
case "2":
// #1 Display all dogs with a multiple search characteristics
string dogCharacteristic = "";
while (dogCharacteristic == "") {
// #2 have user enter multiple comma separated characteristics to search for
Console.WriteLine($"\r\nEnter one desired dog characteristic to search for");
readResult = Console.ReadLine();
if (readResult != null) {
dogCharacteristic = readResult.ToLower().Trim();
Console.WriteLine();
}
}
bool noMatchesDog = true;
string dogDescription = "";
// #4 update to "rotating" animation with countdown
string[] searchingIcons = { ". ", ".. ", "..." };
// loop ourAnimals array to search for matching animals
for (int i = 0; i < maxPets; i++) {
if (ourAnimals[i, 1].Contains("dog")) {
// Search combined descriptions and report results
dogDescription = ourAnimals[i, 4] + "\r\n" + ourAnimals[i, 5];
for (int j = 5; j > -1; j--) {
// #5 update "searching" message to show countdown
foreach (string icon in searchingIcons) {
Console.Write($"\rsearching our dog {ourAnimals[i, 3]} for {dogCharacteristic} {icon}");
Thread.Sleep(250);
}
Console.Write($"\r{new String(' ', Console.BufferWidth)}");
}
// #3a iterate submitted characteristic terms and search description for each term
if (dogDescription.Contains(dogCharacteristic)) {
// #3b update message to reflect term
// #3c set a flag "this dog" is a match
Console.WriteLine($"\nOur dog {ourAnimals[i, 3]} is a match!");
noMatchesDog = false;
}
// #3d if "this dog" is match write match message + dog description
}
}
if (noMatchesDog) {
Console.WriteLine("None of our dogs are a match found for: " + dogCharacteristic);
}
Console.WriteLine("\n\rPress the Enter key to continue");
readResult = Console.ReadLine();
break;
default:
break;
}
} while (menuSelection != "exit");

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -30,3 +30,4 @@ Following
23. [Format alphanumeric data](./023_alphanumeric_data_format/023_csharp.md)
24. [String data type methods](./024_String_data_type_methods/024_csharp.md)
25. [Work with variable data](./025_Work_with_variable_data/025_csharp.md)
26. [Challenge - variable data](./026_Challenge_variabe_data/026_csharp.md)