Wow! This began well with it taking me about 10 minutes to set up the interactors. It was all down hill after that. I could not wrap my head around the NameSurferEntry class and the NameSurferDataBase class. The instructions seemed to say to make a array list in NameSurferEntry and a database (HashMap?) in NameSurferDataBase, both from the provided data file. That sounded like double handling which was the opposite of what I assumed the course was trying to teach (elegant simple code with no double handling). So after almost wearing out my thinking cap I thought of a possible solution where double handling did not occur: make NameSurferDataBase call on NameSurferEntry(line) where the only thing the main run method in there is going to do is parse each line from the data file. After each line is parsed, it is sent back to the NameSurferDataBase and the actual db is built. A HasMap is built using the bit from NameSurferEntry that is parsed as a name. The values assigned to each key of the HashMap are the decade ranks (put into a array where each of 11 cells represents the decades). The database thus gets created and after that can be used to pull data.
- 14 days to program
Create a program using Java interactors with buttons, text fields and a resizable (and adaptable) graphical display.
Using the data contained in a text file that contains information held as:
- Sam 58 69 99 131 168 236 278 380 467 408 466
the program will display a graph in 10 year intervals between 1900 and 2000 of names vs rank. In the above example, Sam is the name. 1900-1909 is 58, 1910-1929 is 99 etc up until 1991-2000 where name Sam is the 466th most popular name.
The most popular is to be shown at the top of the graph. The least, towards the bottom. A zero score should show the chosen name on the bottom of the graph.
A line should run though each 10 year interval at a decreasing or increasing angle, depending the rising or falling name popularity.
- Mutiple classes are to be used:
- NameSurferGraph (this one goes into a container to allow for the on the fly resizing).
Set up milestones:
- Assemble the GUI interactors
- Implement the NameSurferEntry class
- Implement the NameSurferDataBase class
- Create the background grid for the NameSurferGraph class
- Complete the implementation of the NameSurferGraph classs
For this assignment I resisted getting any hints from solutions available online, though I did need to look at existing code to understand how some things worked.
Creating the Program Including Beta Testing
Started: 25/05/2017. Completed: 20/06/2017. Days taken: 26 days.
Milestone 1: Assemble the GUI interactors
Pretty simple using examples previously supplied as handouts and in the lectures. Here I got stuck calling on mouse events which I do not need and not declaring the object source. After that, things worked.
Milestone 2: Implement the NameSurferEntry class
This meant to store info for a name, i.e the name’s String and then 11 int’s for each of the decades. The assignment states
“The NameSurferEntry class encapsulates the information pertaining to one name in the database. That information consists of two parts:
- The name itself, such as “Sam” or “Samantha”
- A list of 11 values indicating the rank of that name in each of the decades from 1900 to 2000, inclusive”
I already coded a buffered reader at the start. It contains all 4000+ names and holds the entry as “Paul 17 14 13 14 17 17 19 27 40 64 99” as an example but that’s not what we want. We want (potentially), to split the data in the db made by NameSurferDataBase into more detailed units. If so, what’s the point of the DB class if we have already created a db of data? I was looking at lecture 24 and was thinking the NameSurferEntry class was analogous to Songs and the NameSureDataBase was analogous to Albums. I think it’s supposed to the other way around. In any event, why would Milestone 2 be to create the details specific for a name if we have yet to implement the database. I guess it is a good thing I already have. This caused most angst and I wound up stuck on this section, on and off for about two weeks. In the meantime I worked on things I could do (when in had the time) and finally wrapped my head around passing variables between classes.
Perhaps Zoila’s there as a test. All zeros…
With my failure to understand the NameSurferEntry class, I skipped over that for a bit to work on things I did know how to do. The URS requires the user to be able to type the entry in as uppercase, lowercase or a combination and the correct name should be pulled from the database. Initially I codes that into the NameSurfer.java class and then I made my own class with some more functionality.
While working on this I decided to learn how to pass variables between classes (properly). I’d not really understood it while watching lectures, and up until now, just trusted the code to work. Here’s the code I wrote to teach myself how to pass variables. At the end of it. I have a handy class that will also convert strings from any combination of upper and lowercase to first letter is an uppercase and the rest are lowercase, all uppercase and all lowercase.
Being able to do things like this makes me feel not so stupid. From here, it was back trying to nut out the NameSurferEntry vs NameSurferDatabase classes. As stated in the introduction, I finally figured out how (probably, I’ve not done it yet as of 20170614) to write the code.
I got the names parsed fairly quickly. What you see is green is my commented out parseline code from when I was parsing lines and not knowing what I was doing (I built the code while watching a couple of the lectures). It’s wonky at present, but at least the list of names are successfully sucked out of the data file.
After un-commenting my parseline code, it seemed to work. The method in NameSurferDatabase for pulling data from the HashMap was wrong (I knew that before running).
Once I figured out how NameSurferEntry and NameSurferDataBase worked together, it only took about an hour of coding to get that bit of the program up and running. An intermittent bug seemed to run parseline when there was no call to it, but it went away after I called a NameSurferEntry method correctly. I built both of these classes at the same time.
The only thing I did not understand here was how “public String toString()” in the NameSurferEntry class worked. It was needed to get a human readable output from the HashMap (otherwise the results would be blank (not even null), however, the NameSurferDatabase did not appear to call toString. For now I’ll trust that it works. As for the calling methods from within other classes, this’ll probably be an issue at some stage in the future and I’ll need to understand it.
Milestone 3: NameSurferDataBase class
This was built at the same time as the NameSurferEntry class.
Milestone 4: Create the background grid for the NameSurferGraph class
This is meant to encapsulate a GCanvas so it can be redrawn if the screen size is changed.
All we need here are a bunch of GLines and GLabels for the graph
This was bit was easy and resizes as expected.
As an extension, I’d put in a getWidth() check for a predetermined size and decrease the font size.
Milestone 5: Complete the implementation of the NameSurferGraph classs
What this is meant to do is store the details of the names that have been searched, draw the decade ranks to the screen and cycle the colours (4 of them). The y scale is 1000 and a zero result needs to be displayed at the bottom with an asterix next to the name. A negative name hit does not do anything,
Than main things to watch for here was making sure the graph scaled within the range of 1000 and zero ranks correctly drew along the bottom of the screen. I used some coloured GLine’s to track this during testing.
The hardest part was cycling the font colours. Ideally I’d be able to do a if 1, do bla, if 2 etc and use a concatenated string to specify a constant (eg COLOUR1), but it seems Java does not let me use a referenced string as a colour setter.
My thoughts on this were way off. I seemed to get the counter happening as it should, but the colour cycling was very odd. Peeking at other’s code, I saw I should just be using the int that the private void drawSavedNameStats(NameSurferEntry entry, int rankingAndTracker) was using. I therefore renamed it from ranking to rankingAndTracker so it was obvious what I was using the int for.
A little bit of boolean coding after that produced the output below…
The Shipped Program
As required by the assignment.
Packaged Jar file. Extract zipped contents and run the namesurfer.jar file if you have java installed on your system.
With many searches and no clearing, this gets messy fast and could certainly do with having quite a few extensions added.
Program Modifications / Extensions
Change graph to display different symbols for each name, eg *, squares, triangles, circles Allow deletion as well as addition Change font size as the application size changes (should be like a responsive web page so should know how to do) Ensure GLabels do not draw on top of each other. (Shift the up where the result is 0 or between 1000 and 500, down if between 1 and 499)
If I had not spent an age trying to figure out why two classes were supposedly creating two separate databases (which they were not), I would have had a huge amount of time to modify this program.
How to pass variables between classes. (Still a bit iffy on some of this, but have learned a lot).
The value of a pad and some scribbling was again demonstrated.