Think 2021: New tools have the developer ecosystem and IBM building together Learn more

Behind the code: AI Fantasy Football insights go mobile

ESPN and IBM have teamed up to bring a new level of insight to fantasy football team owners: Watson AI. #FantasyFootballFace. Watson is built on an enterprise grade machine learning pipeline to read, understand, and comprehend millions of documents and multimedia sources about fantasy football. The ESPN Fantasy Football with Watson system has been a significant undertaking with many components.

This article is the fifth in an eight-part series that takes you behind each component to show you how we used Watson to build a fair world-class AI solution.

AI Fantasy Football insights go mobile

Wherever you go, Watson provides fantasy football insights so that you can select your best players no matter where you are in the world. If you are on vacation, a work trip, or in transit, Watson provides clear and interactive experiences so that you can make timely fantasy football decisions. A questionable player’s status can be checked a few minutes before game time through most mobile devices. Any late breaking news that affects predictions or simulations will be reflected and reachable in real time. You can play fantasy football with an AI advantage anywhere in the world to avoid #FantasyFootballFace.

The mobile application can be experienced on iOS, Android, and desktop environments. Each of the JavaScript libraries such as AppMeasurement, Axios, D3, Promise, Fuzzy set, jQuery, Lodash, and timezone that are used within the application is stored on an IBM Content Delivery Network (CDN). In addition, Cascading Style Sheets (CSS), fonts, and images are pulled from the Object Storage origin through the CDN. The billions of users requests never access the origin with a hit ratio of 95.95%. The only time traffic reaches the origin is when data is purged, the Time-To-Live (TTL) expires, or there is a change between the content on the edge and origin. Each of the buckets in Object Storage is a container for a specific type of content. Buzz, deep learning output, evidence, injury reports, player information, score distributions, sentiment, keywords, transaction information, and volume statistics are held within distinct buckets that are separated by region. A total of 39 buckets that are distributed over the United States geography are mapped as CDN origins.

mobile overview

For example, the dallasbuzz bucket in Object Storage is mapped as path /dallas/buzz. The appropriate ports are opened to enable access by each mobile client. A general TTL setting is selected for the expires section on the edge servers. A manual purge can be run through the IBM CDN console or through an application programming interface (API). The browser-based caches are turned off to avoid stale data.

A Domain Name Service (DNS) such as the IBM Cloud DNS can be used to resolve a domain name to an IP address. For fantasy football, a CNAME or Canonical Name was set up so that multiple names referenced the original DNS name. Upon setup, the CDN provides an extra CNAME that was added to our DNS so that the service can be found. Each of the Dallas, London, and Germany region’s content is written to by a Python application. Within the Object Storage origin, a status bucket for the region indicates the last time that the content was updated. The region with the most recent information is selected by the mobile application.

Over a 30-day period, the mobile application imposed over 45 billion hits and consumed over 5.93 PB of AI insights. Most of the traffic was from North America. The region that includes Europe, the Middle East, and Africa was a distant second.


The mobile application code is written using the VueJS JavaScript framework, which allows for a Single Page Application (SPA) experience. VueJS enables the application to be broken into reusable components that communicate with each other by using the publish-subscribe pattern. The following code demonstrates the assigning of VueJS components.

Vue.component('news-analytics', NewsAnalytics);
Vue.component('projections', Projections);  
Vue.component('SelectedPlayersDetails', SelectedPlayersDetails);

The invocation or mounting of VueJS components is dictated by the URL that the VueJS’s router plug-in interprets. In the case of the fantasy football application, the router parses the URL for required fields and in turn the component that is associated with that route will asynchronously fetch data from the CDN using the Axios library. This lets you dynamically view player information based on the URL parameters.

const router = new VueRouter({
            routes: [
                path: '/',
                component: Home,
                children: [
                        path: 'playerCard/:playerid/leagueId/:leagueid/teamId/:teamid'

As mentioned previously based on the component associated with the route, it will be responsible for taking the parsed values and fetching the appropriate data. In this case, the Home component is responsible for doing this. After the JSON data is returned asynchronously from the API call, the Home component emits messages to each of the children components that are listening for this specific event.

//player API method declaration
getPlayer1APIData: function(player1Data) {
        return axios.all([getSentiment(player1Data), getPlayerInfo(player1Data), getPlayers(),
                                     getPlayerEvidence(player1Data), getPlayerVolume(player1Data),
                                    getPlayerProjection(player1Data), getPlayerLikelihood(player1Data),
                    .catch(function(err) {

//player API method invocation
        .then(axios.spread(function(projection, likelihood, keywords, injuryStatus) {

//publish message to children components
Event.$emit('injuryStats’, injuryStatus);
Event.$emit('likelihood’, likelihood);
Event.$emit('projections’, projection);
Event.$emit('keywords’, keywords);

The Axios library provides a convenient way to make multiple Asynchronous JavaScript and XML (Ajax) requests simultaneously, by using the all API in the function declaration to allow multiple response values to be returned. Using the spread API allows for data that is resolved from the originating all request to assign values in the order that the API requests were declared in the function’s parameter signature.

VueJS exposes lifecycle API hooks for developers to control data flow in their respective components. Some often used hooks are mounted, updated, created, and watch. In some cases, the data is inherited by children components through its declarative attributes in the parent components template. At times, this data is not available until after the child component has already mounted due to an API call that has not yet been resolved. In this scenario, invoking the watch hook is useful. When the parent component returns data from an API call, the child component dependent on this data listens for changes to this attribute and updates appropriately to later be reflected in the view.

//Home (Parent Component)
let Home = {
        template: ‘…
                <AutoComplete :items=”player_array”></AutoComplete>

//Autocomplete watch hook
watch: {
             items: function(value, oldValue) {
                  if(value !== oldValue) {
                      //update dependent value
                 this.isLoading = false;

Each time that we change the SPA code, the content is uploaded to the Object Storage origin with curl. The upload is a two-step process. The first curl uploads the HTML file as HTML content. The second curl updates the header information for public access.

curl -X "PUT" "https://<host>/<context>/index.html" \
 -H "Authorization: Bearer <token>" \
 -H "Content-Type: text/html"  \
 --data-binary "@<file>"
curl -X PUT "https://<hostname>/<context>/<file>.html?acl" -H "Authorization: Bearer <token>" -H "x-amz-acl: public-read"

Now that the SPA is uploaded, Watson provides AI insights to anyone on the go with a connection to the Internet. The extended reach of ESPN Fantasy Football with Watson can help you sift through evidential insights from any corner of the world, and in theory, outer space. #WinWithWatson

Check back next time as I discuss the fusion of evidence with the AI pipeline. To find out more, follow Aaron Baughman on Twitter: @BaughmanAaron.

The ESPN Fantasy Football logo is a trademark of ESPN, Inc. Used with permission of ESPN, Inc.