FizzBuzz

June 30th, 2012    Posted in Discussion

FizzBuzz is an old coding test used to make sure that interviewees are capable of solving basic coding problems.
The test is thus:
Write a program to count from 1 to 100, when it is on a multiple of 3 have it print Fizz, when it is on a multiple of 5 have it print Buzz. If it is on a multiple of both 3 and 5 have it print FizzBuzz.

The code for this in a simple C++ application is:

 

int main ()
{
	int i = 1;
 
	while (i<101)
	{
		cout<<"\n"<<i<<": "<<endl;
 
		if (i%3==0)
		cout<<"Fizz";
		if (i%5==0)
		cout<<"Buzz";
 
		i++;
	}
 
}

When I came across FizzBuzz and it’s solution I thought the same thing that I think when I see any application: How can I port this to Android?

So I decided to make a version of FizzBuzz on Android which would really Fizz and Buzz!

So here it is: FizzBuzz for Android.

Coding FizzBuzz for Android turned out to me be much more challenging than I expected:
The UI in android cannot be written to directly from an Activity’s onCreate or onResume methods, however a background function should never execute UI code.
Also when sound files are played they are played by a background service and the system for checking their completion is complicated and better suited to longer audio files. Fizz and Buzz have static lengths and I never want to play Buzz before Fizz, so a logical solution is to wait for 250ms after launching Fizz before launching Buzz.
Also in order to have the lines arrive in a steady order and not have any audio play over other audio I determined that it would be best for every line to take 1 second.
Both the wait for Buzz and the 1 second line wait require a sleep or wait, neither of these functions should be run in the UI thread.

The solution I found was to launch a Runnable as a thread.

The runnable contains the logic and launches the Fizz sound, it also uses another thread to launch the Buzz sound. When the runnable needs to output a new line to the table it uses runonuithread().

public class FizzBuzzActivity extends Activity {
	private MediaPlayer fizzMP, buzzMP;
	private TableLayout displayTable;
	private String srowText, srowNumb;
 
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		displayTable = (TableLayout) findViewById(R.id.table);
		fizzMP = MediaPlayer.create(FizzBuzzActivity.this, R.raw.fizz);
		buzzMP = MediaPlayer.create(FizzBuzzActivity.this, R.raw.buzz);
		new Thread(mUpdate).start();
	}
 
	private Runnable mUpdate = new Runnable() {
		public void run() {
			for (int i = 1; i < 101; i++) {
				srowText = "";
				srowNumb = i + "|";
 
				srowText = "";
				if (i % 3 == 0) {
					fizzMP.start();
					srowText += "Fizz";
				}
 
				if (i % 5 == 0) {
					srowText += "Buzz";
					new Thread(new Runnable() {
						@Override
						public void run() {
							try {
								Thread.sleep(250);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
							buzzMP.start();
 
						}
					}).start();
				}
 
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						TableRow newRow = new TableRow(FizzBuzzActivity.this);
						TextView rowNumb = new TextView(FizzBuzzActivity.this);
						TextView rowText = new TextView(FizzBuzzActivity.this);
						rowNumb.setText(srowNumb);
						rowText.setText(srowText);
						newRow.addView(rowNumb, 0);
						newRow.addView(rowText, 1);
						displayTable.addView(newRow,
								new TableLayout.LayoutParams(
										LayoutParams.FILL_PARENT,
										LayoutParams.WRAP_CONTENT));
					}
				});
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
 
			}
 
			complete(buzzMP, fizzMP);
		}
 
		void complete(MediaPlayer MP1, MediaPlayer MP2) {
			MP1.release();
			MP2.release();
		}
	};

 

The Audio samples I used in FizzBuzz were clipped from files on SoundBible.com and the Source Code for FizzBuzz is available on GitHub.

It’s amazing how much you can learn doing a simple little project like this one.

-Rory

Comments Off

Discussion: How to add Target Selection for Capture Route Activity

June 27th, 2012    Posted in Discussion

Lots of college stuff was going on, so I wasn’t able to work on Shortest Walking Route for a while.

Now thankfully things have died down.

My first concern is tackling Target Selection for Capture Route Activity:

When the user chooses “Capture Route” on the Home Screen, they should be asked where they are going. When they get to that location Location Service should automatically turn off and play a sound to let the user know.

I’ve thought up a few ways to do the transition and drawn them out, please have a look and comment or message me to let me know what you think of them:

Idea 1: When the user clicks on “Capture Route” it opens Target Selection Activity (an activity with a big map, like Display Routes), which shows the user a Selection List (like the one currently in Display Routes Activity). If the user chooses to create a new target, then the  Selection List dissapears and they choose a location in the view underneath.

Upside: as the use taps on different potential selections I can have the map behind the Selection List zoom to the location they are choosing, this should make it easier to be sure that the right location is being chosen.

Idea 2:  When the user clicks on “Capture Route” it opens a Selection List dialog over the Home screen, in this dialog the user can choose one of the saved targets ore choose to create a new target.

If the user chooses an existing target they go on to Capture Route, if they choose to create a new target they are brought instead to map where they can choose a location to be a target.

Upside: If the user is frequently choosing the same targets then this will skip the Target Selection screen which will make the process of starting a Route Capture quicker.

Idea 3: keep the relationship between Home and Capture Route Activity the same, show the Selection List in Capture Route Activity and pass the user out to Target creation if they they opt to add a new Target.

 

Please let me know what you think of these ideas, and if you have any other ideas I should be considering.

-Rory

Comments Off

Sample Result

May 22nd, 2012    Posted in Uncategorized

 

Today I stopped my car in a driveway and turned Capture Route on, I captured myself driving from there to work. I drove up the hill to foggy Killiney and back down through Ballybrack Village. (Blue Line, Route 10)

Yesterday I stopped in that same driveway and started a capture which took me down to the Graduate Roundabout and down Church Road. (Green Line, Route 9)

 

Doing this gave me two clean routes, with their starting and ending points roughly the same, with their last points being just before I drove into the underground carpark in Cherrywood.

By tapping on these final points I can view the information stored for the routes.

From these results we can see that the route over the hill is around 560m shorter, but the higher speeds on the other route even it out.

I’ll have to capture the route through Killiney again without the fog and see how if it makes a difference.

 

Please give SWR v0.0.11 a go and let me know what results you get!

-Rory

Comments Off

Version 0.0.11

April 30th, 2012    Posted in Version Update

Changelog

1. BUGFIX: Fixed bug where Capture Route would stop when it temporarily lost control of the GPS.

2. BUGFIX: FixOpenHelper should no-longer accidentally leave any cursors open.

3. FEATURE: Display Route now shows far fewer GPS fixes in order to reduce jagged lines caused by inaccuracy.

4. FEATURE: Display Route now calculates distance travelled and average speed and displays them.

5. FEATURE: Display Route now spreads it’s RouteItemizedOverlay by distance instead of by number of fixes, this should even them out better.

Download Version 0.0.11

Details:

1. Although it was meant to be persistent when the LocationService lost control of the gps system (for example when another application used the GPS while it was running) then it would be automatically restarted but it would not know which route it was recording to. I worked-around this by storing the current route in SharedPreferences and pulling it out again if the service was restarted.

2. I was seeing some warnings about cursors being left open, these were not causing errors because I was closing the Open Helper that created them. I changed how some of my functions in FixOpenHelper were written to stop this by using  DatabaseUtils and closing unneeded cursors.

3. I wanted to start measuring distance and the best way I could think of was to measure the distances between the points and add them up. Before I could do that I had to get rid of points which were scattered all over the place, if I measured those the distance would seem much greater than it was. My solution to this was to edit DisplayRoutesActivity to reject any point that was less than 3 times it’s accuracy away from another point. This straightened the points out nicely.

4. The distance is now measured while the route is being processed to the screen, this is why the full length is only displayed on the final point. The average speed is calculated in FixOpenHelper by using an SQLite function to average all the speed values recorded for the route, because of this it is unlikely that the average speed will match up with the distance and time displayed.

5. Because I now have a measurement of distance I was able to change how my itemspreader (which spreads the clickable dots along the routes) works, previously it placed an Overlay Item every 25 accepted fixes, now it instead places a point whenever it is more than 300m from the last point.

 What’s Next:

  • I’ve been thinking about how I’m going to implement target selection, and the way I see it I’ll need two new tables, I need a table of routes, which will store meta information about the routes, and a table of targets which will store the target locations.
  • Implement a thread to calculate the length of a route after it is recorded.
  • Create a custom dialog for the clickable Overlay Items so I can better separate qualities of the whole route, from qualities of the point selected. I tried to separate these by putting the former into the title of the dialog, but it has a limit to the amount it can contain.
Comments Off

Version 0.0.10 Raphael ‘Satellite’ Savina Edition

April 13th, 2012    Posted in Version Update

A few days ago I was talking to my good friend Raphael Savina and he made a feature request:

Raphael wanted to be able to view his Routes against a satellite image instead of a map.

I had already discovered that you could easily turn satellite images on and off with this code:

MapView.setSatellite(true/false);

So I made a deal with Raphael: if he would draw me a satellite I would write the code and get the version up ASAP.

Raphael promptly supplied me with a lovely drawing of a satellite and I made the necessary changes to DisplayRouteActivity and displayroutes.xml to turn the icon in the titlebar of Display Routes into a functional button.

And the result is Version 0.0.10 of Shortest Walking Route.

Note:

I’ve edited all of my icons to better fit into the Menu Icon Guidelines, which has resulted in the application icon going from being slightly bigger than it should be to slightly smaller.

What’s Next:

  • Adding a Target function so you can tell Shortest Walking Route where you are going and have it terminate the gps capture when you get there.
  • Tuning down the number of GPS fixes captured to more efficiently represent a route.
  • Finding more useful information about routes to display
Comments Off

Version 0.0.9

April 8th, 2012    Posted in Version Update

With Version 0.0.9 I have finally implemented a ListView to display new gps fixes as they are captured. This took quite some doing and there a lot of changes because of this.

Now instead of the CaptureRouteActivity taking care of location services they are managed by a custom service called LocationService. When LocationService receives an update it does not directly update the ListView but instead stores the fix in the database and calls:

contentResolver.notifyChange(baseUri, null);

This (through FixProvider) notifies CaptureRouteFragment that an update is available to route which is being displayed in the ListView, CaptureRouteFragment then updates as soon as it can.

Because of these changes Capture Route should now be much more stable and reliable. Also you can now use Capture Route in landscape mode.

On the Display Routes side not much has changed, I have removed the giant burritos from my April Fools gag and fixed a bug where when removing routes the last route would stay visible after you had removed it. (but only until you touched the screen)

This occurred because the command:

MapView.invalidate();

Was not being called to let the MapView know that it had changes it needed to display. I have remedied this.

Version 0.0.9 is available for download, and I would greatly appreciate any feedback.

What’s Next:

  • Adding a Target function so you can tell Shortest Walking Route where you are going and have it terminate the gps capture when you get there.
  • Tuning down the number of GPS fixes captured to more efficiently represent a route.
  • Finding more useful information about routes to display
Comments Off

Version 0.0.8 Burritos And Blues Edition

April 1st, 2012    Posted in Important Note, Version Update

 I am very excited to announce that with Version 0.0.8 Shortest Walking Route is now officially supported by Dublin’s Fastest Growing Burrito Chain: Burritos And Bues!
As part of this exciting new partnership you can now see the locations and opening hours of Ireland’s best burrito shops whenever you look at the Display Routes screen  of Shortest Walking Route!

Install Version 0.0.8 on your Android device right now to see for yourself!

Note:
  • If you have used previous versions of this application you may notice that your routes look more messy in Display Routes. This is because I have disabled filtering of GPS data when it is going to be displayed and started filtering it while it is being captured instead. This should save space in the database (as useless data is no-longer kept there) and help resolve some stability issues.
  • In order to let new users get the most up-to-the-minute information about Burritos And Blues opening hours, I have changed the application to allow users to go directly in Display Routes without capturing a route first.
What’s Next:
  • Fun!
  • Excitement!
  • Really Wild Things!
  • ListView!

 

Update: The maps weren’t working properly in the version I originally posted. Should be fine now.

Comments Off

Version 0.0.7

March 28th, 2012    Posted in Version Update

Just a quick post to link to the latest version.

 

Download Here.

Comments Off

Version 0.0.6

March 24th, 2012    Posted in Version Update

Just a little update this time.

I noticed a problem with the Capture Route ending routes and starting a new one when the next GPS fix arrived.

This was caused by a bit of code I put in to the onStop() to clean up when the application was killed from the outside. I’ve moved this to the onDestroy() which should still retain the function without disrupting how the application is working. This change brought to you by the Android Activity Lifecycle.

I’ve also added a persistent notification to be displayed while Capture Route is running. This should help prevent people accidentally leaving the GPS capture running and wasting battery life.

Unfortunately because I implemented the notification using a future compatible tool called NotificationCompat.Builder, it has tripled the size of Shortest Walking Route to 161.22kb.

So please, download and install Version 0.0.6 and let me know what problems  you find or features you want.

What’s Next:

Back to work on filtering out inaccurate results and getting the paths to display information about themselves when they are tapped.

Comments Off

Version 0.0.5

March 19th, 2012    Posted in Version Update

Quite a few updates in this version:

Capture Route now has a Start/Stop Button at the top which will allow you to record routes as long as you like.

 

I’ve now implemented Display Routes, which can be accessed from SWR’s home screen once you have captured at least one route with Capture Route.

Display Routes will allow you to select the routes you want to see and it will draw them to screen in random colours. Unfortunately the colours are not stored, so every time you change your selections the colours will be randomly changed.

 

The route selection is done with this alert dialog which is set to always appear in the top right corner of the screen. This is to allow users on larger devices like Android Tablets to see the changes they are making on the map while they are making them.

These choices are persistently stored in Android’s Shared Preferences as characters in a String, which is my way of getting around the fact that Android does not allow arrays to be stored in Shared Preferences.

Please give Version 0.0.5 a go and let me know if you run into any issues.

If you are interested in how this application works please follow the link to GitHub on the right-hand side of the screen. The full source-code is available there. If any part of it is unclear to you, please let me know.

Note:

  • Capture Route has no way of stopping itself yet, and there is no notification to tell you it is running in the background. If you have it running you will see the icon to tell you that GPS is running.
  • I’m not filtering or smoothing the routes when placing them on the map, so you will see some very low-accuracy data and jagged, indirect lines.
  • Later on I’m going to be changing this so all routes will have a target and the data you record with this version will have to be discarded, so don’t record anything you want to keep forever!

What’s Next:

  • I need to work on getting information about the routes to pop-up when you tap on them.
  • I’ll also be looking at cleaning up the routes when they are displayed. (I think not displaying the very poor accuracy fixes will be a good starting place).

Comments Off