URF Stats is a web application I submitted as an entry to the [Riot Games API Challenge] (http://na.leagueoflegends.com/en/news/community/contests/riot-games-api-challenge). Since the purpose of the contest was to do something cool with the Riot API in the wake of the League of Legends April Fool's day [URF mode] (http://leagueoflegends.wikia.com/wiki/Ultra_Rapid_Fire), the app displays various match statistics like champion win rates and item purchases aggregated over 12 days of URF.
For the collection, persistence, and analysis of match information, we chose the background job processor [Sidekiq]
(http://sidekiq.org/), which conveniently ran off of the app's Rails codebase. In the first stage, the
job read the randomized URF match ids and fetched match JSON using a [bespoke Riot API REST client]
(https://github.com/carsomyr/urf_stats/blob/master/lib/riot/api/client.rb) built on top of [Faraday]
(https://github.com/lostisland/faraday). The results were persisted to the database as [
(https://github.com/carsomyr/urf_stats/blob/master/db/schema.rb#L65-71)es. In the second stage, the [
(https://github.com/carsomyr/urf_stats/blob/master/lib/urf_stats/workers/stat_worker.rb) job aggregated individual
Stats quantized by region and
day. As a side effect of computing summary statistics, a bunch of [associated quantities]
(https://github.com/carsomyr/urf_stats/blob/master/lib/urf_stats/champion_accumulator.rb#L63-64) like champion wins and
item purchases were also saved.
The purpose of the Ember.js frontend app was to enable a high level of user interactivity while remaining robust. Although lower-level libraries like jQuery could in theory have had the same effect, in practice it's not possible to manually keep views in sync with user inputs and browser events. In particular, the app showcases the following interactions:
- Changing the region, date, or sort order sets their corresponding button state to
active(depressed). Furthermore, the app's query parameters will change and cause it to request fresh, parameterized models from the server.
- Typing in champion and item names will initiate requests to the server and update search results in real time.
- Narrowing champion search results to exactly one will display splash art for that champion.
In creating the app, we benefited a great deal from reusability: A building block like [
wrapped every champion or item's image and intelligently linked the appropriate wiki page.
Stylistically, we applied Twitter Bootstrap's classes and responsive grid to achieve a clean look and decent usability on mobile devices. We placed a particular emphasis on the responsive aspect and ensured that [even data tables collapsed gracefully] (https://github.com/carsomyr/urf_stats/blob/master/app/assets/stylesheets/data_table.less) on small screens.
The app at www.urfstats.io is running in the Amazon Web Services (AWS) cloud. We use EC2
for compute (on a
c3.large instance), Route 53 for DNS management (whose name servers answer for
EBS for snapshotting database files and transferring them across instances. To provision a new machine with the
necessary configuration for supporting Rails and Sidekiq background jobs, we used Chef combined
with proprietary cookbooks and data management techniques. On top of that configured state, [Capistrano]
(http://capistranorb.com/) was used for repeat deployments.
To test the app:
- Change into the project root directory.
- Copy the
config/*.ymland fill in the appropriate values.
createdb -- urf_stats(assuming PostgreSQL).
bundle exec rake db:migrate.
bundle exec rake db:seed(this populates the database with static champion, item, and rune/mastery data).
bundle exec rakefor RSpec tests.
To try the app locally, run
bundle exec rails s.
Copyright 2015 Roy Liu Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.