Caldash Web App Final Report
Github: https://github.com/EzzySri/CalDash
Website: caldash.herokuapp.com
Webcast: http://youtu.be/ko8UHuMdacM
Everyday, one has mandatory and flexible events. Mandatory events can be things like class, meetings, or work which requires us to be in specific places at fixed times. Flexible events, well, are more flexible. For example, a person might want to get a haircut, but doesn’t really care when in the day he gets one. Thus, among all the events we face in one day, what is the best way to schedule these flexible events in order to save the most time possible? We created Caldash to solve this problem. Caldash is a calendar app manages your flexible and mandatory events and finds the best schedule that minimizes your walking distance throughout the day.
Currently, we have built out the core of this idea. Caldash can currently optimize events on a current day to minimize distance traveled. However, we cannot currently optimize on any other heuristic, such as minimizing gaps between events or minimizing driving distance as opposed to walking distance. In addition, by the nature of our algorithm, we can only schedule events on every half hour to reduce the number of total possible events and thus the search tree we need to explore in order to find the best schedule. In addition, we tried to generate multiple schedules so that the user can pick the one he likes the best, but this also made the algorithm too slow to run on Heroku. However, Caldash is still very good at what it does currently. It can almost always find the best schedule to save you from walking up those treacherous Berkeley hills.
We used Rails for the backend. At the core of our app, we need to create and then find an optimal schedule events. Creating events is really easy in Rails due to its MVC principles. However, optimizing schedules proved to be the hardest part of the backend. We initially thought we could reduce our problem to the Traveling Salesman Problem since we were essentially trying to find the shortest path between a bunch of locations. However, we had the additional problem that the Traveling Salesman Problem assumes that you can travel from any node in the graph to any other node. In our situation, we couldn’t because only some events can happen after other events, and placements of events were highly dependent on where other events were placed. After realizing this, we tried a different approach. We tried every combination of events that had a distance less than the best schedule’s distance we had found. For example, if we are trying to schedule five events and we found a schedule that has a distance of 500 meters, then we know we can immediately stop exploring any placement of events that has a distance greater than 500 meters. We used euclidean distance to calculate the distance between any two locations.
If we were going to restart the project, we would not have used Rails. While Rails allowed us to quickly create the CRUD portion of our application and provided a bunch of awesome libraries to help us deploy onto Heroku, the major bottleneck for our project was the speed of the optimization algorithm. Because we do explore a significant portion of the search tree that grows exponentially, we had to place a lot of limits that impedes on the user’s experience, such as only allowing the user to place events on every half hour. If we used a faster language that allowed for concurrency (Ruby has the GIL that only allows one thread to execute at a time) such as Scala or Java, we could potentially make the algorithm faster and thus the app better.
We also deployed our final app onto Heroku. Heroku made it insanely easy for us to get something on the web for free. We had to do a bit of refactoring so that Heroku knew how to host our app, but after that, we only had to type git push heroku master to deploy to production. We didn’t explore other features of heroku such as various addons or dyno scalings because those features required money. In future projects, we would use Heroku again, especially if we had a budget that allowed us to use the additional features.
For the front end, React and Flux are the pillars of this portion of the project. Essentially, React is the UI layer while Flux is the data layer. We learned that the benefit of React in reducing complicated program flow is at its best when we strictly maintain the design as the following. The UI side registers actions with the data layer as a set of API endpoints. The triggered actions cause the states at the data layer to change. After all changes are finished, the changes present themselves unidirectionally to UI components from the top down, from which point the React Diff Algorithm takes over.
We add on to the tested benefits, continuing from the discussion we had in the last milestone report. Firstly, it reduces redundant calls to setState. As the web app grows larger, we found that stores become interdependent on computation of data. For example, the Google Map needs current event form input to render the location on the map. Without a store layer, we would need to manage the changes in state in the UI layer itself by passing and receiving states. This complicates program flow and we would end up with more calls to setState simply because it is hard to see the best course of actions in terms of achieving a set of computation. With stores, we are isolated from changes in UI and the computation becomes a traditional program with object representations, class hierarchies and modules and not a web app mixed with css and DOM manipulation, thus allowing us to reason in the same way as when we first learned programming. As a future goal, we will adopt stronger software engineering principles to the front end such as utilizing object factories and class inheritance in Javascript to allow the codebase to scale as we implement more complicated features.
Secondly, isolating the data layer to approximate a traditional program allows us to apply familiar design principles that are not easily relatable in web programming. For example, we did our best to separate computation from service calls. This is because although there are many service calls, the underlying computations tend to be similar. Hence, these computations involving data structures are abstracted out as services themselves to achieve a layered design. Later in the project, we found that many features that we decided to add did not involve refactoring existing codes at all but just adding a few lines of service calls to the same underlying computations. This is not necessarily the case in other frameworks such as Ember, in which actions are contained in controllers when developers are more in the mindset of delivering the result of an action than applying traditional design principles. To summarize, the separation of concerns allow developers to take consideration of the data layer as a whole when delivering an action.
As a note on the feasibility of our idea at its current form, we want to outline several future additions in the next few iterations. Firstly, we need to expand it to cater to a larger set of use cases. One of them is supporting multiple modes of transport. Right now the algorithm assumes walking as the only form of transport, which is not the kind of day that people need optimization for. This is because the reduction in distance and time is not significant enough to counter the efforts needed to enter the event information. Secondly, our initial goal is to build an intelligent app that would take of more repetitions spent in entering events. This includes features such as auto-suggestions for the events that user will engage in for the day by finding regular patterns in his usage, and for event-aware suggestions such as restaurant recommendation in the proximity. They do not have to be very good, but do transform most of the event input into an easy drag-and-drop experience. It is likely that a normal user will have a high energy barrier to schedule his day and hence reducing the efforts for a typical day can improve usage. Thirdly, we need to add standard features that integrate with other productivity tools such as exporting the schedules to Google calendars and especially moving our service onto mobile devices.