Monday 31 December 2012

1000 Apps Downloaded!

MDF Projects has officially had its 1000th download. The 1000th app was Velocimeter, my speedometer app. It's been a crazy first year of iOS development, and I'm excited to embark on the second one. Also, Happy New Year!

Saturday 29 December 2012

GKHelper: getting GKPlayer data

I'm going to start going over useful methods from my code in order to help people with similar problems, and give myself a form of self assessment. The first method I'm going to go over is the method I use to get GKPlayer objects from player IDs. This code is from my forthcoming turn based Game Center game (name TBD).

For all my Game Center interactions, I have created a singleton manager, named GKHelper. It handles creating the async calls to Game Center, and processes the information when it comes back. It also has several forms of caching to reduce web requests.

GKHelper has a dictionary which it uses to store GKPlayers by playerID. Whenever a GKPlayer object is fetched, it is first stored in this dictionary before being returned. Whenever a GKPlayer is requested via playerID, the dictionary is checked before the request is made. This logic is handled via the following method:


- (GKPlayer*)playerForPlayerID:(NSString*)playerID {
   if(playerID == nil || [playerID isEqualToString:@""]) {
      return nil;
   }
   if(self.playersDict == nil) {
      self.playersDict = [NSMutableDictionary dictionary];
   }
   
   if([self.playersDict objectForKey:playerID]) {
      return [self.playersDict objectForKey:playerID];
   } else {
      [GKPlayer loadPlayersForIdentifiers:[NSArray arrayWithObject:playerID] withCompletionHandler:^(NSArray *players, NSError *error) {
         
         if (error != nil) {
            NSLog(@"Error retrieving player info: %@", error.localizedDescription);
         } else {
            // Populate players dict
            for (GKPlayer *player in players) {
               [self.playersDict setObject:player forKey:player.playerID];
            }
            [self.delegate performSelectorOnMainThread:@selector(playersLoaded) withObject:nil waitUntilDone:NO];
         }
      }];
   }
   return nil;
}


First, the method checks the playerID to make sure it is valid. Then, it checks the dictionary for the specified player. On the case that it cannot find the player, it begins the async web request for the player data, which it then stores upon return. The delegate is then informed on the main thread (since it may return on a background thread) that the players list has been updated (the delegate usually reloads the data in the tableview). After the web request is sent, the function returns nil indicating the player could not be found. The function will get called a second time upon receiving the player info, and the correct information will be retrieved. This function is costly, however, since the async request takes an array of playerIDs, and we're only passing in a single ID.

That's where the next two functions come in.


- (void)getPlayersForMatch:(GKTurnBasedMatch*)match {
   
   NSMutableArray *identifiers = [NSMutableArray array];
   
   for(GKTurnBasedParticipant *participant in match.participants) {
      if(participant.playerID == nil) {
         continue;
      }
      [identifiers addObject:participant.playerID];
   }
   
   [GKPlayer loadPlayersForIdentifiers:identifiers withCompletionHandler:^(NSArray *players, NSError *error) {
      
      if (error != nil) {
         NSLog(@"Error retrieving player info: %@", error.localizedDescription);
      } else {
         // Populate players dict
         for (GKPlayer *player in players) {
            [self.playersDict setObject:player forKey:player.playerID];
         }
         [self.delegate playersLoaded];
      }
   }];
}

- (void)getPlayersForMatches:(NSArray*)matches {
   NSMutableArray *identifiers = [NSMutableArray array];
   
   for(GKTurnBasedMatch *match in matches) {
      for(GKTurnBasedParticipant *participant in match.participants) {
         if(participant.playerID == nil) {
            continue;
         }
         [identifiers addObject:participant.playerID];
      }
   }
   
   [GKPlayer loadPlayersForIdentifiers:identifiers withCompletionHandler:^(NSArray *players, NSError *error) {
      
      if (error != nil) {
         NSLog(@"Error retrieving player info: %@", error.localizedDescription);
      } else {
         // Populate players dict
         for (GKPlayer *player in players) {
            [self.playersDict setObject:player forKey:player.playerID];
         }
         [self.delegate playersLoaded];
      }
   }];
}


These two functions take a GKTurnBasedMatch, and simply fill up the player dictionary with the GKPlayer objects. The first method I call when a new match is created, and the second method is called when the app is first opened, right after the current matches are loaded. They insure that the loadPlayers method is only called once at app loading, and once per new match. There are a few problems with this setup although.

For one, the latter two methods have no way of communicating with the former method regarding making async web requests. In other words, getPlayersForMatches could be called, immediately followed by playerForPlayerID. This would start two async web requests for the same information, with potentially bad results. There's also the case where the async web request fails to get a certain GKPlayer for a playerID, but still calls the delegate's playersLoaded method. Thus, an infinite loop will be formed.

If I ever get around to optimizing these methods, I'll post the new ones below. Also, make sure to comment if you have any questions. Also, sorry about the code formatting, haven't figured out how to make it format properly yet...

Tuesday 11 December 2012

Lego Trains are awesome

Found my old Lego train, so I set it up around the tree. Here are some pictures.




AirBoard Overview

AirBoard is a handy app I made to keep score during spontaneous tournaments that sometimes occur. The app is compatible with an Apple Tv, so when you mirror your iOS device's screen on the ATV, it shows the overall scoreboard.

This allows you to edit the list on the fly, and the secondary screen will update once you're finished. I'm planning to add a boatload of features to this app, such as saving a scoreboard, creating a tournament bracket from a scoreboard, and possibly inter-device communication. The UI assets do need an upgrade though...

Another cool feature is the ability to name the scoreboard by typing directly on the navigation bar.

Screenshots below:



Tuesday 20 November 2012

It's been a while

It's been a long time since I last posted. Since then I've added another app, called Air Board.

Air Board is a handy scoreboard app that takes advantage of linking your iOS device to a secondary screen. When connected to an Apple TV, Air Board will show the top players sorted by score. Updates made on the device are reflected on screen with animations. I'll post some pictures soon.

I'm also working hard on another Game Center based app which will be my best one yet. More info to come.


Tuesday 11 September 2012

Radians is in the AppStore

Radians has been approved by the AppStore, and is available to download. There's a few updates I want to work on, but the app's in a pretty good state. The download link is below:

Radians

Tuesday 4 September 2012

Velocimeter available in the AppStore

Velocimeter is a speedometer app I made and uploaded to the AppStore in a few hours. It shows you how fast you're going, and keeps track of stats like top speed and 0 - 100 time. More features will be added when I have time.

Download the app using the link below!

Velocimeter


Tuesday 28 August 2012

Radians has been submitted to the App Store!

Radians (the name for my map app) has been submitted to the App Store. It's not in a completely stable state, but I think it's ready for public release. There's still several features I want to add in over the months, so look for updates. I haven't yet decided the pricing for the app. Pics below.




Wednesday 30 May 2012

Mapper Update

I've had some issues with compiling the Mapper app on my devices, so I rewrote the app in a new project. I've also added some pretty sweet features. Hopefully I have a release ready version in a few weeks. Pics to come soon.

Sunday 15 April 2012

Article Summarization - Update

This is my last project of my undergrad, so I'm going to try and get it finished this week. I've separated the scripts into a reader and a summarizer. One teaches the algorithm, and the other implements it. I'm slowly growing my corpus day to day. I looked into parsing RSS feeds to increase the corpus size, but I decided I could save more time and retain accuracy by doing it manually. I'm aiming for a corpus that involves 100 articles; right now I'm at 40.

I'm planning on testing different corpus sizes and different algorithms against a grading system of my design. Hopefully I can prove that as the corpus grows, the algorithm gets more effective.

More updates to come.

Tuesday 3 April 2012

Triple Monitors!

I recently purchased an iPad 2 for cheap on eBay, and I've been playing with it for a few days. It's quite fun for games, as well as news with apps like Flipboard.

One of the cooler uses I have for it is as a third monitor for my Air. Using AirDisplay, you can link your iPad as a third monitor. See picture below.

Wednesday 28 March 2012

Mapper - Update

Some major changes have been made to Mapper.

1) Changed the colours of the call and message buttons to green and blue. I didn't like the red call button anymore. I also changed all the buttons to icons instead of text, that looks much cleaner.

2) Added text messaging functionality. It's not voice activated like I originally planned, but I can now text whoever's closest to me. I'm going to put an option on the settings page to set the default message for texts.

3) I added a timer which checks for the closest annotation with a phone number and selects it with animation. Now as I drive, my friends' houses pop up as I drive past them, allowing me to call them with one click. People's addresses are also represented by a house icon.

4) The parking pin is now automatic. I track the user's speed, so I set up an enum to determine if the user is driving, potentially parked, or parked. If the user gets to the parked stage, a green pin is dropped where they parked. The car button now allows the user to lock on to this parking spot and their own location, which is useful when trying to get back to your car. Eventually I want to have the parking check run in the background, so it's always there.

Screenshot below.


Monday 19 March 2012

Symposium Today!

Here's a pic of the symposium set up. Woke up bright and early to set things up.

Saturday 17 March 2012

The Keys to Learning - Update: It Plays!

Hooked up the solenoids with the new bracket, and shaved the touch sensor board beneath it. This is the result.



Friday 16 March 2012

The Keys To Learning - Update

With the symposium coming up this Monday, the piano needed to look its best. Below are pics of the first coat of stain. Looks pretty awesome.

Tuesday 13 March 2012

The Keys To Learning - Update

It's been a while since I've updated on the status of the piano. The outer casing is completed. The whole group has been working together over the past few days to update the software side. The last step on the mechanical side (attaching the solenoids to the frame) will be completed in the next few days. At this point, when the tablet is hooked up to the piano, a user can play a song, and it identifies exactly where they messed up if they made a mistake. Pictures below.

Hooking up the touch sensors to the Arduino so it can tell what was played
The new UI designed my Rohit Rajan and myself. And yes, that is the Song of Time from Zelda.

The bracket to hold the solenoids under the keys. These will pull down the metal pin in the keys to demo the song for users.

Friday 9 March 2012

Moviehub - Updated TableView Cells

Designed a custom table view cell and implemented it with the movie view. Next step is to update the television screens as well. Screenshots below.


Saturday 3 March 2012

iPhone 3G disassembly

So I decided to take apart my old iPhone 3G. Here are the results. The screen on its own looks remarkably like the iPhone 4's screen.

Thursday 1 March 2012

Keys of Learning - update

The piano shell is coming along nicely. Should be finished up tomorrow. It can disassemble completely into separate parts because certain prices are screwed together. The tablet also has a nice slide-in holster so it can be taken out whenever. Pics below.

Monday 27 February 2012

Icon Finder

I stumbled upon this pretty cool site that helps you find icons. Quite useful when making a quick app. Link below.

FindIcons

Wednesday 22 February 2012

Mapper - Map now rotates to follow user's direction

I found a property of the user's current location that shows the direction of motion. On every user update, I rotate the view to reflect the user's new direction. I'll post a more in depth tutorial when I have time. Check out the screenshot below to see it in action.



Tuesday 21 February 2012

WikiSpeedster - update

I've got the refresh URL working, but I'm having some trouble adding speed signs to the database. They don't seem to be received on the other end when I do a subsequent refresh.

I also had a problem with mapView didUpdateUserLocation, as it was only called one time. Turns out I needed to link the mapView object to a map view in the xib. Once I added that in it worked fine. Updated screenshot below.

Article Summarization using Machine Learning

There's nothing more fun than writing a machine learning algorithm while watching Terminator. I decided to take a crack at summarizing tech articles without any knowledge of existing algorithms. I used ruby to make a script that stored memory in one file, and filtered output in another file. The filtered output is somewhat "choppy", but I think it did an alright job. The links to the articles, as well as my summaries can be found below.

Facebook profiles accurately predict job performance

Summary:
profile That s the advice conscientiousness extraversion agreeableness and neuroticism Six months later the researchers compared evaluations of are of course subjective but job seekers shouldn t necessarily worry that they need to clean up their Facebook profile For instance Don Kluemper one of signaled openness to new experiences and adventurousness while also looked at evaluations drawn from Facebook profiles and academic success Kluemper says that report which included a larger sample 244 and found academic Kluemper Despite the studies companies shouldn been enough research yet to definitive connection between profiles and job offers indicator done

Google to sell heads up display by years end

Summary:
data connection tilting scroll month We are told it is very quick learn and once user adept at navigation it becomes second nature almost indistinguishable low resolution built actively discussing and dozens futuristic projects One most rather than like those that people see on smartphones The glasses will send data to looked at about potential business models with Disruptions column last year Apple engineers are also exploring wearable computing but the company is taking a different route focusing on computers that strap around someone s wrist Last week The San Jose Mercury News discovered plans by Google to build a 120 million electronics testing facility that will be involved in testing precision optical technology

Googlighting

Summary:
other just watch video above It s raises some very valid points Change is hard for everyone Switching from Office to Google Docs isn t an easy switch Many features are still missing from Google s productivity suite It s not a direct replacement Typing in the cloud editing Microsoft Office might be disappearing from some shops but others rely on it as much as the office s coffeepot Google will no doubt fire back with its own quirky advert You can always count on Microsoft and Google s marketing department for a good show


It obviously needs some tweaking, but I think it's a start for an hour's work.

Monday 20 February 2012

Keys of Learning

This is my Fourth Year Design project at the University of Waterloo. It's been 8 months in the making, and is due in March. The goal is to provide a better learning mechanism for kids trying to learn how to play the piano. The solution consists of an embedded tablet and Arduino board to process mistakes and show corrections.

Pictured below is the custom shell I'm building to hold the piano. Once it has been built it will be stained either red or blue (or another eye catching color). The main blocker at the moment is installing electromagnets into the keys to actuate their movement (similar to a player piano) for teaching purposes.

Saturday 18 February 2012

WikiSpeedster

I stumbled upon a website called www.wikispeedia.org which aims to store every speed limit sign in the world online. They do this thanks to users who submit data through a smart phone app as they find them. The app links their current location to the speed sign value, which is then stored in the database.

I'm in the process of making my own app to do this; screenshots below. Later on I'm planning on using their database for an app I have in mind. I should have the app finished in a few hours' time, hopefully sometime tomorrow.

Thursday 16 February 2012

Mapper - New Settings page

For now it only controls map type and signing in to social networks. Might add a few more features eventually. I'm using the background from the notification center as the views background. Looks sick.

Wednesday 15 February 2012

Mapper

Mapper is an iPhone application I made to use while I'm driving. I was originally using the native iPhone map, but I got tired of constantly having to find my location repeatedly.

Mapper automatically locks on to your location as you move. It also scans your address book and adds every contact with an address. If that contact has a phone number, that too is displayed on the pin's pop-up box. Clicking on a pin (like in the picture) and clicking call will call that person. Clicking message will record your voice and translate it into text for use in a text message (currently under construction, which is what the play button is for). I've also extended the status bar, adding speed, current city, and temperature. There's also a button that marks your parking spot, which can be useful.

Check for it in the app store in a few months when I get all the features completed.

Zebes

This is my Zebes box, running Ubuntu 11.10. I've set it up a 130GB partition as a Time Machine backup for my Mac. Works pretty well for the time being, but backups seem to be wiped clean every two weeks or so. :/

MovieHub

Several months ago I decided to create MovieHub, a web based controller for the movies stored on my local server, Tourian (which is hooked up to a flatscreen). The server is running WAMP, so it can only be accessed locally. I wrote a php script that scans my movie and TV folder, inserts them in a database to keep track of ratings and play counts, and then displays them using some basic HTML. I also found a handy html parser which I use to search the movie on Google images, and use the first result as the movie poster.

MovieHub web interface 


When the image/title are clicked, the movie begins playing on the TV hooked up to Tourian. This means any device with an internet browser is now a controller. Ont op of this, I've made an iPhone app which does the same thing (I was getting annoyed with looking at the web interface on my iPhone).

MovieHub iPhone interface


One caveat is in order to get VLC to play the movie, VLC needs to be running. This is because I'm using the HTTP interface for VLC (accessible at localhost:8080 or something), which is what the VLC remote uses. This problem only occurs on Windows, since Linux and Mac (?) let you take over the screen.

Hello World!

I'm creating this blog to keep track of all the projects I'm working on. Feel free to send me a message if you want to help out.