Citizen Science

From CompSciWiki
Jump to: navigation, search

Back to the Case Studies homepage

Problem

Each year there is a Christmas bird count, where bird enthusiasts count and report the number and species of birds at their bird feeders as a way of contributing to science (also known as citizen science). Your program will record these sightings and produce a report. Your program will use two parallel arrays: one for the bird species (String) and another for the total counts viewed (int).

Your program should consist of the following three phases:

  • Inputting the bird species
  • Processing sightings
  • Printing the final report

Inputting in Bird Species

The bird species should be read from a file using the getFile method in Assignment 3 and Scanner (remember to include the necessary import statements and to use try/catch). Assume that the first line in the file is the number of species, and that each subsequent line is the name of one bird species. An example file:

10
Abert's Towhee
Alder Flycatcher
American White Pelican
Bristle-thighed Curlew
Cackling Goose
Canada Goose
Canada Warbler
Eastern Meadowlark
Great Blue Heron
King Rail

Print the list of bird species after it is read:

***********************************
Species:
Abert's Towhee
Alder Flycatcher
American White Pelican
Bristle-thighed Curlew
Cackling Goose
Canada Goose
Canada Warbler
Eastern Meadowlark
Great Blue Heron
King Rail
***********************************

Processing Sightings

In a loop, the user should be able to input several sighting reports. Each report should consist of the name of the species (String) and the number observed (int). The program should find the index of the species in the bird species array and use it to update the count array storing the total counts viewed. You can assume valid input. After each report is recorded, the program should print out the new sighting count for that species. Use Scanner for input. The loop should terminate when the user enters “done”. An example of this phase is below:

Enter a sighting report
Alder Flycatcher, 7
Sightings for Alder Flycatcher: 7
Enter a sighting report
King Rail, 4
Sightings for King Rail: 4
Enter a sighting report
Cackling Goose, 5
Sightings for Cackling Goose: 5
Enter a sighting report
King Rail, 11
Sightings for King Rail: 15
done

Printing the Final Report

After the user is finished entering sightings, the program should display all species and their corresponding sighting counts. In this report, the name of the bird with the highest count should be displayed in all capital letters. If there is a tie, it is acceptable to display only one of the most viewed species in all capital letters. Below is an example of the report:

***********************************
Bird Sightings:
Abert's Towhee: 0
Alder Flycatcher: 7
American White Pelican: 0
Bristle-thighed Curlew: 0
Cackling Goose: 5
Canada Goose: 0
Canada Warbler: 0
Eastern Meadowlark: 0
Great Blue Heron: 0
KING RAIL: 15
***********************************

Methods

In addition to the main method and the getFile method from Assignment 3, your program should consist of at least 4 methods. These methods should either use arrays as parameters or return arrays. Potential methods include:

  • A method to read the list of species from a file
  • A method to find the index of a particular species in the array of bird species
  • A method to add new sighting data to the total viewed for a particular species
  • A method to find the index of the species with the highest viewing count
  • A method to display a final report

Testing your program

Test your program using the two sample files provided on the course website. For each sample file, make 8 sighting reports, 2 of which should be for the same species.

Sample File 1

10
Abert's Towhee
Alder Flycatcher
American White Pelican
Bristle-thighed Curlew
Cackling Goose
Canada Goose
Canada Warbler
Eastern Meadowlark
Great Blue Heron
King Rail

Sample File 2

15
Bluebird
Acorn Woodpecker
Northern Pintail
Mallard
Great Egret
Cactus Wren
House Finch
Sandhill Crane
Bald Eagle
King Rail
Whimbrel
Northern Shoveler
Black-Throated Sparrow
Pacific Loon
Western Grebe

Output

Use System.out for output. Follow the format of the output shown above.

 

Origami casestudy.jpg

Solution

This problem is of higher difficulty, so we will assume you know how to read in a file, create and use methods as well as use arrays. If you need to refresh your memory on these topics, feel free to refer to the earlier case studies.

This solution will avoid giving you the exact code right away. The solution code is available at the end of the page. Practice is the best way to learn how to code well, so we urge you to attempt the problem on your own! This will act as a guide to try and help you arrive at a solution. Remember that you may have a different way of approaching the problem, and that is perfectly acceptable!

Declaring Parallel Arrays

As mentioned in the problem description, you will need two parallel arrays. One will store the names of the birds as Strings and one will store the sighting counts for each bird as ints. It is smart to declare these two arrays right away. Since the number of species will be inputted with the data file, the arrays should not be initialized yet. These arrays can be declared in the main method.

String[] species;  // to store the names of the birds
int[] counts;	// to store the sighting counts for each bird

Methods

The following methods should be implemented as static methods that will be called from the main method.

Read in List of Species from File

You can implement this as a single method that returns the instantiated array of bird species, or as two methods.

If you implement it as a single method, all you have to do is use the previously created getFile() from Assignment 3 to read in the file. Then you can use Scanner to read the file contents into the String list of bird names.

Note that the first line of the file will be the number of bird species. This number will be used to instantiate the bird species array before you can start to fill it.

If you choose to implement two methods instead of one, you can organize your methods such that one (i.e, getFile() from Assignment 3) returns the File to the main method.

The second method can accept the File as parameter and read the file into the bird species array. Then you will return the instantiated array to the main method.

However you choose to read in the list of species from the file is fine - as long as it works!

Always test your code. This would be a good point to ensure that your program is working.

Find the Index of a Particular Species (in the array of bird species)

This method should accept the bird species name to be found (String) and the bird species array (String[]) from main.

Given the name in a String of a particular species of bird and the bird species array, loop through the bird species array until you find the given name.

Since we are String matching, you will have to use the string1.equals(string2) method. Note that string1 = string2 will NOT work.

This method should return the index of the element in the bird species array that matches the given bird species name that is to be found.

Add New Sighting Data to the Total Viewed (for a particular species)

The parameters for this method should include the bird species array (String[]) and the sighting count array (int[]).

This method will prompt the user to enter a number of sighting reports. Each sighting report will consist of the bird name along with the number of times viewed.

Note that the sighting count array must be initialized with a size before this method can be called.

Hint. This can be done from main by using the bird species' array.

Recall, from the problem the example:

Enter a sighting report
Alder Flycatcher, 7
Sightings for Alder Flycatcher: 7

Recall, that you may assume valid input. This means that your code does not have to take into account errors such as:

  • Incorrect format.
    Using a colon instead of a comma. e.g. Alder Flycatcher: 7
  • Incorrect bird species name.
    Bird species name is spelled incorrectly. e.g. Ader Flycathc, 7
  • Non-existent bird species. The bird species entered by the user is in the list that has been inputted by the data file.

You can add in error checks for these errors, as it is good practice to do so. In the real world, data files are often not in correct formats. It is much better to handle the error, and provide the user with a message (i.e, with System.out.println) so that the user can correct the error. It is also a good way for yourself as a programmer to debug your program. Error checks can also prevent your program from crashing due to badly formed input.

However, this is not required for this problem.

After printing the "Enter a sighting report" line, you can use Scanner to prompt for user input. Since you want to accept user input you can use the Scanner as follows:

Scanner myScanner = new Scanner(System.in);
// When accepting user input:
String report = myScanner.nextLine();

Note that the user should be prompted for input until he or she enters "done". This means that your loop should terminate once report is equal to "done", otherwise the scanner must ask the user for another line of input after processing the entered String.

Recall, when String matching, you need to use the string1.equals(string2) method.

If the user entered "Alder Flycatcher, 7" this string will now be stored in the String variable report.

Now, you will have to separate this String into the bird species name (String) and the corresponding count of sightings (int).

Here is where parallel arrays become important. The index of the bird species name should be parallel to its count in the sighting count array. So, if Alder Flycatcher is in index 2 of the bird species array, you should have its correspond count (7) in index 2 of the sighting count array.

From this method you can call the (optional) method to find the index of the bird species, which will be discussed next. This method should return the index of the bird species that the user specified. If you choose not to implement the optional method, you can simply include the search in this method. You will simply loop through the bird species array until you find the bird species name that the user entered.

Remember, you are using parallel arrays. The index returned from the method should give you the index of the sighting count array that you should incremenent.

From this method, you can either specify a void return type or return the updated sighting count array.

Find the Index of the Bird Species (Optional)

This method should accept the bird species name (String) along with the bird species array (String[]).

A simple search through the bird species array until a match is found is all that is needed from this method. Remember, you are trying to match the given bird species' name to the list - these are Strings. This means you will need to use the string1.equals(string2) method.

This method is not required as you may insert this search directly into the previous method. However, good programming practices utilize methods. The resulting code will be cleaner, easier to read and understand, and much easier to debug.

Find the Index of the Bird Species (with the highest viewing count)

The parameter for this method is simply the sighting count array (int[]).

This method is simply a search through the sighting count array, finding the largest element and returning that element's index. In order to implement this, you need a simple loop, a variable to store the largest element (int) and a variable to store the index of this element (int).

The largest element will initially be the first element in the array. As you iterate through the array, you should be comparing the current element to the largest element and deciding whether it should be replaced or not.

If the current element is larger, replace the largest element variable with it, and replace the largest element's index variable with the current index.

From this method, you should return the variable the holds the index of the largest element (int).

Display Final Report

The final report format is:

***********************************
Bird Sightings:
[Bird Name]: [count]
[BIRD NAME]: [maxCount]
***********************************

All you need to pass to this method are the two parallel arrays: bird species name array (String[]) and the sighting count array (int[]).

Again, all that is needed is a simple loop to iterate through the arrays. Note that the bird with the maximum number of sightings must be printed in uppercase letters. Recall that you have a method for finding the index of the bird with the maximum number of sighting counts. This method can be used to locate the bird that will have its name in capital letters.

A simple way to convert a String to all capital letters is by using another String method. This method is the string.toUpperCase() method. It returns string in all uppercase letters.

System.out.println can be used to handle the formatting, and volia! Your report will be ready to be printed, you simply need to call this method from main.

Putting it All Together

The solution has been broken down into the main methods required for the program. From the main program, these methods need to be called in the correct order to ensure that all the required parameters exist and have been loaded correctly.

Testing and Debugging Your Code

This program is quite a large program. It requires quite a bit of methods. An advantage to using methods is that methods make debugging much easier. It is much easier to narrow down where a bug in your code is when your code is broken up into methods!

A simple way of debugging is to insert System.out.println() statements into your code. You can print out results from you methods, and compare what is printed to what should be there.

Printing is also a good way of debugging because if your program crashes, but only crashes after a particular print statement, you can narrow down where the bug is occurring.

I highly recommend testing you program iteratively. That is, after you complete a method, compile and run it! Print out the results and see if they are the correct results. This way, when you write the next method, and your program does not compile, you know the problem must be in the method you just wrote - and not the older one that worked correctly!

Be Proud of Yourself and Enjoy Yourself!

When your code compiles, pat yourself on the back.

When your code runs without crashing, pat yourself on the back.

When your code finally prints out the correct results and works properly, pat yourself on the back.

Coding can be tedious! It is hard work. Be proud of your programs.

Remember that although this is homework, it can be fun! If you run into a mental block or if your code simply is not working at the moment, take a break.

Coding can result in some pretty cool programs (video games, anyone?) so if you want to help program the next Call of Duty, coding should be enjoyable!

Solution Code

Remember that this is not the only "correct" solution. You may have a different solution. In fact, you probably will have a slightly different solution!

Code

Solution Code

Back to the Case Studies homepage