Hi! I'm Jorik and my senior independent project is creating an app, RootOn, which will help boost community engagement with high school sports games. My interest in programming began in middle school with robotics, but I have since worked on projects using Java, Python, and now Swift (the language used for iOS). On the athletic side, I play for the St. Stephen's Soccer Academy and Lonestar SC, and I will continue playing D1 soccer next year at Yale. As one of many students interested in the performances of our St. Stephen's sports teams, I have noticed how difficult it can be to follow along with our teams' seasons. It is not only difficult to find scores, but it can also be tricky to find and remember game times and locations. Therefore, I hope to create an interactive app that will make viewing schedules, scores, and live streams easy and organized.
To give context, I had the idea for this project the summer before junior year. At that point, I had 0 proficiency in Swift code, although I had worked on some projects in Python and Java. Over the course of junior year, I spent many months learning Swift and then around Spring Break of junior year I began working on this app. While I managed to achieve a solid foundation for the app, there were still a lot of missing pieces. Since the end of junior year, I have not had the time to work on this app as much as I would have liked...until now.
So, I began this week by making a long list of all the missing pieces I could think of. Most of the work can be divided into 4 categories: layout, authentication, aesthetics, and functionality. Layout includes the general framework of the app, such as how many tabs should be at the bottom or what the ideal layout for each page is. Authentication, which is typically based in Firebase (backend cloud computing services and application development platforms provided by Google), involves the process of creating an account and signing in. This extends to sending verification emails and recognizing schools from email domains. Functionality is just adding every feature that I want and ensuring that it works. Finally, aesthetics is what comes after functionality, and it involves a long list of minor tweaks to slightly improve the design and user experience.
This week, I began by getting XCode, the Apple program for developing apps, up and running. After reviewing my old code to brush off the dust, I began attacking one of my largest looming challenges: The Manager Problem. My goal here was to set up the framework for distinguishing manager accounts from normal student accounts. In practice, this means that I need to be able to assign the manager role to specific accounts, and these accounts then have special functions. I accomplished this by restricting the manager functions to specific userIDs within the code. For example, the "create scoreboard" button will only be shown if your user ID is listed as a manager. However, this can only be a placeholder because it requires the code to be changed manually every time I want to add a manager. Instead, I need it to be stored in Firestore instead so managers can add other managers themselves instead of waiting on me.
Next, I began battling another looming challenge: The RSVP Problem. My goal here was to have an RSVP button for each game, such that when clicked (A) your username is added to an audience list that everyone can see and (B) Firebase stores which games you RSVP'd to. My main issue here was that within the view model for each post, the only user variable stored is that of the post's author. Therefore, I struggled to figure out how to draw the current user's name. However, after some brainstorming with Dr. Wortham I realized that I could draw the current user from the Firebase authentication database, and this worked out very nicely.
Finally, the last looming challenge for this week: The Fetching Problem. Right now, when you open the app it loads all posts in the database, then automatically filters through school names and the game date. Only then does it display the scoreboards. For now, this works, but once there are high quantities (thousands, tens of thousands) of scoreboards in the database, it will take a long time to load ALL of the posts and THEN filter. Therefore, I want to filter by school as I load so that the program only has to load all St. Stephen’s games. To solve this issue, I used a pre-filter on the fetch posts that only fetches posts with the same school name as the user. It compares the school name of the current user with the school field for each post in the firebase storage and then loads them.
On top of attacking these problems, I did a lot of work on aesthetics. This included but was not limited to (A) Creating an array of all schools in the SPC and uploading photos of the school logo so that when you enter opponent the school logo will automatically pop up (B) redesigning the home page, changing the font, changing header color, resizing and realigning text (C) changing the "add scoreboard" button design (D) updating the design for each scoreboard to include live ticker and new full-time result design.
I used this week to make major progress on aesthetics and complete the solution to one of my major looming concerns: The Manager Problem. I spoke about this in my week one writing, but the idea was for a user to fall into one of three categories: admin, manager, or student. For St. Stephen's, there might be 1-3 admins. An admin is a user who can (A) create posts (B) edit every post and (C) add/remove managers. A manager is a user who can (A) create posts and (B) edit their own posts. A student cannot create or edit posts, only comment in the chat feed and photo gallery. In order to achieve this functionality, I created a new users array in the Firebase database. Although users are automatically stored, it is kept in an authorization database that is difficult to access/manipulate. Instead, I created a function such that when you create an account, your email is added to the users array, and each email has a subcollection for three booleans: admin, manager, and student. If you are an admin (admin is set to true), you can submit other users to become managers. This will go into the database and set the manager bool to true for the email account given. However, since this is not stored in the actual user, but rather a representation of the user, I had to be nifty with the app design. Say I want a button to only exist for managers, I cannot say "if user is manager..." but rather "does this email exist in the array of all emails where manager is set to true". Ultimately, I attempt was a success and I'm very happy to have that solved.
Next I added a TON of aesthetic tune-ups and small pieces of functionality. Here's a list:
Main Color Theme: change main color theme to black/grey
New Scoreboard Look: update look to include a gradient, nicer colors. RED = HOME ; GRAY = AWAY
Pin header: when you scroll, the St. Stephen's header and calendar part should be pinned to top of screen.
Refresh button: When pressed, the refresh button should update all scores and info.
Return To Today button: if you are looking at games on a different day, you can press this button to automatically return to the current day instead of having to click through the calendar again
Custom Opponents: instead of just selected opponents from an array of SPC schools, you can now type a custom opponent.
Chat Problems: previously I was having issues with the chat feed because after you sent one chat it wouldn't refresh properly and you couldn't send more. I fixed that problem. I also redesigned the look so it looks like a chat feed instead of a comment section. Your own texts are blue and every text has user email and a timestamp.
Scoreboard Look For No-Score Sports: For sports that don't have a score (golf, swimming, track, etc.) I changed the look of the scoreboard so there is no score and no opponent displayed.
Edit Page: improved overall aesthetics
Manage/Profile Page combined: combined the manager and profile page so that you can see your account info and log out on the same page where you can see all the games you are RSVP'd to.
More Random Aesthetic Touch Ups
To the juniors reading this, I can very highly recommend doing a Senior Independent Project if you have something concrete that you want to explore. I have been wanting to intensely work on this app for 2 years, and now I finally have the opportunity to spend tons of time on it which makes me super happy. I think that part of this project is finding out what work you truly enjoy and that is invaluable as you prepare to take off into your adult life and plan your future career.
Now, at the end of week 3, I feel like I am approaching the finish line. I have made tremendous advances towards completing the minimum viable product, and only have a few small quirks to work out. If you see the first few images below from my Notes App, you can read through everything that I was able to check off this week. While there were many miscellanious tasks as well, the main focus of this week's efforts was email verification, a discover tab, and score confirmation.
Email Verification: My app needs email verification because every user is rooted to an email address. When you post a photo or comment, that post is linked to your unique email. If an admin wants to add you as a manager, they enter your email address. Therefore, it is vital that users cannot create an account with an email that is not their own. In order to add email verification to the app, I first had to figure out how I can have my app send emails. The very simplest form of email verification would be that my app sends a random code to the email address that the user enters. However, getting an app to send an email is not as simple as it might sound. With Firebase, sending an email to a user requires first creating a user...logic that is quite counterintuitive, because we only want to create a user after they verify an email. However, there was no way around this. Now, when you try to create an account it will create a user with the email address, password, and school code provided, but it will note that you are not yet verified and hold you on a verification page. Once you open the link that is sent to your email, you are marked as verified and are passed into the main app view. After hours and hours of researching and all types of failed attempts, I got this to work. See below to see the final product with aesthetic touchups.
Discover Tab: Once I figured out email verification (super happy about this), I added a discover tab to my app. While on the main games tab you can see all the games happening every day, users may want to see when the next girl's lacrosse game is. The Discover Tab allows users to filter by sport, level, and gender to find specific games. While the functionality for this was actually surprisingly simple, the aesthetic design with the filter buttons took longer than expected to get right.
Score Confirmation: The biggest addition I made to the scoreboard this week was score confirmation logic. Before my changes, a live ticker would be displayed on a scoreboard for two hours after the scheduled start of a game. Once these 2 hours were up, the live ticker would change to say "FT" for full-time. There are two problems with this: (1) The manager of the scoreboard may not have entered the actual final score yet, so the "FT" score displayed is incorrect and (2) The game may have ended after 1.5 hours and the final score is correct, but the live ticker will still run for 30 minutes. To fix this, I added a "Final Score" button. When pressed, a verification checkmark appears under "FT," and even if the two hours are not over, the game is ended. If the 2 hours are over and the score has not been verified, a yellow warning signal is displayed under "FT"
UP NEXT:
Photos: Photos have been a nightmare so far, and are the main quirk that I still need to work on. The progress I made after hours and hours of tinkering this week include aesthetic reformatting, faster loading, and an expanded full screen view when you press on a photo in the gallery. I also added delete functionality and refreshability. However there are still some problems:
You can only upload photos, not videos
You can only upload 1 photo at a time
You can only upload from camera roll, not take a picture directly from your camera.
Photos cannot be saved to camera roll
Notifications: All though I spent a few hours trying to figure out push notifications, I did not have any success. Next week, I will try to implement push notifications so users are notified when games begin, scores/information are changed, chats are sent, or photos are posted.
Exciting Games: Some games should be marked as "exciting" either because of a high number of RSVPs, a tight scoreline, or a very active chat feed. Rivalry games and playoff games are also exciting. These games should have a special color, and users should receive a push notification that there is an exciting game happening.
Change Schools: Under the Manage Tab, the user should be able to enter a new school code to change schools.
Data Security: Might remove the list of audience members to protect user security. Also need to make sure that all data in firestore is safe and can't be hacked into easily.
Terms and Conditions / Privacy Policy: Write up all the legal documentation for my app. Users must acknowledge these before creating an account
APP STORE: Get the app published on the App Store
Above: Screenshots of my notes app with to-do list
Above: The create account page, the verification page (what you see after you press "create account"), and the verification email you receive.
Above: The Discover Tab
Above: Confirmed scoreboards marked with a green check, unconfirmed scores with a yellow warning. The red button is only visible to the creator of the scoreboard.
Above: While I think the visual design still needs some work, here you can see the main info tab, the gallery tab, and the chat feed that is created within every scoreboard.
This was the first week I really began to feel like I was running out of time. While I am happy with my pace, the closer I get to the finish line the more turns I realize that there are. While I did expect this, I underestimated how seemingly trivial things can take up so many hours. I often look at a page of my app and I just feel like something about the design is off. Fixing it might take 5-10 hours. When I want to add new functionality, I always have to check for bugs, data being stored, aesthetics, etc. App development truly is a super time-consuming process. That said, it is also super fun!
Last week, I made a list of what still needs to be done. I will now explain in depth how tackling these challenges went, and which new challenges I realized I had forgotten about.
Photos: Last week, I was having a few different problems with photos. I could only upload 1 at a time, and photos could not be saved to the camera roll. With Firestore, the photo storage program I am using, loading times are so long that I decided uploading more than one photo at a time wouldn't make sense anyway. Therefore, the only pressing challenge was figuring out how to allow users to save photos to their camera roll. For hours, I searched through StackOverflow, Apple Developer, YouTube tutorials, and Reddit threads, but to no avail. For some reason, nothing I attempted worked. Finally, however, I realized that the problem was not in my code, but in my project permission settings. After adding the "Privacy - Photo Library Additions Usage Description" iOS target property, it worked! All of that time spent for a 10-second solution...such is programming.
Notifications: I spent 10+ hours this week trying to figure out notifications, but only had partial success. Although notifications might seem simple, they are actually half-simple and half-super complex. I say this because there are two types of notifications:
Local Notifications: Simple. You can think of local notifications as timers that you set. Say I go into my app and set a timer for 30 minutes, then after 30 minutes the app will send me a notification that the timer finished. However, in my case, this only kind of works. When you open the app, all of the future scoreboards are loaded, and each of them has a gametime stored. I can arrange the code so that loading these games starts the timer, and you are then notified when a game starts. However, this only works if you open the app after the scoreboard was created. Basically, you always have to be the one starting the timer for your own notifications, even if it happens automatically when you open the app. Right now, I have it set so that all users receive a notification every day at 11am to "check out todays games." They are also notified 30 minutes in advance for every game. Where local notifications don't work is live updates. When say, a score changes, I will never be notified because there is no timer involved. Someone scoring cannot be predicted weeks in advance like a game time.
Push Notifications: Complex. Push notifications, which are connected to a server, can do what local notifications can't. I could, for example, write up a message from the backend and send it to all of my app's users as a notification. However, I have not yet figured out how notifications can be sent automatically when variables like scores change within my app. For some reason, I couldn't find any helpful documentation on this online.
Exciting Games: Unfortunately, recognizing exciting games is really only helpful if I can figure out push notifications. Then, I can alert users when there is an exciting game happening.
I did not spend a significant amount of time with any of my remaining objectives: changing schools, data security, terms & conditions, privacy policy, and app store approval/publishing. However, I did begin to tackle a big hurdle I forgot to mention last week: The Payment Scheme. The whole payment situation needs to be considered at multiple different levels:
Why Charge Money??? While I could not make any money off this app, I have too strong of an entrepreneurial mindset to allow that. Furthermore, storing large amounts of data and owning an apple developer account (which is necessary to publish apps) will cost me hundreds of dollars a year. Also, as I will soon discuss, I don't feel bad because the app will be free for students.
Ads, Subscription, or 1-Time Fee: In both the subscription and 1-time fee models, the fee is not payed by the students, but by the school. When registering a school, a school administrator pays a certain fee, and I set up the school's profile and admin account from the backend. They are then given a school code to share with their student body and everything is set into motion. First, I will rule out the 1-time fee. For me, 1-time fees are sticky because I cannot plan ahead well. Since storing data costs money, I do not know how this will develop over the years, and I might be held liable if I want to close down the app. With a subscription or add model, I would be able to feed whatever I create, and could cancel people's subscriptions if anything comes up. While choosing an ad model would be simpler, I don't like that choice because it makes the user's experience worse. What I have decided on is doing either only subscription, or letting users choose between an ad model and a subscription model.
In App Purchases: This week, I spent 5+ hours adding in-app purchases to my app. To create an account, users need to enter a school ID. I have added a "Register Your School" button that takes users to a form. There, they can fill out a form which includes their school and email. This form is meant for school administrators. I will use the results to manually contact any administrators who reach out. Their account will then be verified as an admin, and the in-app subcription purchase page will be unlocked.
EXTRA STUFF: On top of everything I've described, I also added some small bits of functionality and aesthetics here and there. I improved the aesthetic of the individual match view so that the bottom section is a darker and cleaner palate. For the Chat Feed, I updated the formatting to emulate text messages. Messages can be dragged horizontally to reveal the timestamp, the users email is much smaller, and messages now have like button. Also, I updated the profile page such that all of the profile tasks (sign out, clear schedule, terms and conditions, privacy policy, changing schools, editing managers, managing subscription, and deleting account) are all hidden behind the profile picture. When tapped on, all of those buttons slide out from underneath. This makes the view much more aesthetically pleasing. Also, I brightened up the red color to make it more appealing. Finally, I learned how to make pages refreshable. Although I kept the refresh button, the main page, gallery page, and chat feed can all be refreshed just by swiping down. Since I posted so many pictures last week, I will save the next round of screenshots for next week.
We're here! 2 years of on-and-off work plus 5 weeks of extremely intense and dedicated programming have culminated in a viable product! My main goal this week was to, as my previous statement suggests, bring RootOn to a point where it can be published. This included testing all sorts of edge cases for bugs, making sure every single piece of data was stored, making sure the aesthetic design was sound, adding all necessary features, and more.
Here is a simplified framework of how the app works:
What I accomplished this final week:
Notifications: cleaned up notifications such that every time you launch the app old notifications disappear. Users are now notified every day at 11:10 am (advisory time) to check RootOn for today's games.
New Profile Display: To clean up the profile tab, I hide user school, email, sign out button, and delete account button under the profile picture, when you tap on the profile picture, it slides out from underneath. This gives a cleaner look to the app and gives mroe space for the scoreboard index.
Payment System: temporarily removed for the beta testing process. I will reinstate it once it launches to the app store.
Admin: Admins can now edit anything and everything, as well as delete anything and everything.
Sharing Editing permission: Much like a google doc, managers of scoreboards can now share editing permissions with any user. The original creator or the admin cannot have their editing rights removed. This way, a coach can share editing rights with, say, an enthusiastic parent, who can then update scores accurately.
Saving data: went through rigorous testing of everything that requires data to be stored/updated. I had missed some spots where managers editing the main info of a game was not being saved properly.
Miscellaneous other aesthetic cleanups and fixing bugs.
Here are some screenshots from RootOn, which will be available soon on Testflight:
Above all, I'm super grateful for the opportunity to work on a senior independent project. I would like to thank Dr. Blount, Ms. Olmstead, and Dr. Wortham in particular for their mentorship, guidance, and feedback throughout this process. I would also like to thank Mr. McCain and Ms. Rainey for their support and enthusiasm in putting RootOn to use for St. Stephen's. Although I have been working on this project on-and-off since I had the idea 2 years ago, I have been waiting for an opportunity like this to fully dedicate myself to programming and making it a reality. As you can see from the screenshots and weekly updates, I was able to make tremendous progress in a relatively short amount of time.
In my experience, app development is all about problem-solving. I either think of a function that I want to add to my app or I realize that something isn't working as it should. Making the necessary adjustments can take hours and hours, or they can take seconds. This constant challenge keeps you on your toes at all times, and it requires you to find creative solutions. All in all, I had a great time and look forward to publishing RootOn to the app store over the summer!