Finished project. Could use some DRYing up though.