Kubernetes with OpenShift World Tour: Get hands-on experience and build applications fast! Find a workshop!

Watson smack talk within ESPN Fantasy Football

With contributions by Micah Forster, Jeff Gottwald, Sai Gudimetla, Stephen Hammer, John Kent, Jeff Powell, and Tyler Sidell

You have an important matchup in your ESPN Fantasy Football league, and you know you are going to win. If not only to distract your opponent but to express your excitement, it’s time to share your fantasy football prowess with your social network. Within the Watson Insights experience, each owner can engage anyone outside of their league with Watson smack talk. With the press of a social share button, Watson AI Insights about a specific player can be shared over Twitter and Facebook. Custom messages can be included within the social share to increase the magnitude of smack talk. Before a player card is shared, Watson ensures that a noteworthy image has been created to garner the full effect of a social share. Perhaps unintended but important, the sharing of content might even produce enough social reaction for Watson to reconsider new AI Insights for the top fantasy football players.#WinWithWatson #WatsonSmackTalk

In this third article of a 4-part series, we describe the social sharing system architecture, graphics generation, and AI within social share.

Overall ESPN Fantasy Football with Watson Insights architecture

The Watson social sharing of player cards is integrated within the overall ESPN Fantasy Football with Watson Insights experience as shown in Figure 1. The core Python application’s text container, natural language container, multi-media container, and content generation container determine fantasy football insights. The probability of a player to boom, bust, play with an injury, and play meaningful minutes combined with score spreads, buzz, and evidence are saved to Db2 on IBM Cloud. The Node.js application runs and generates JSON content and pushes the results to the IBM Cloud Object Storage origin. The external data for curation is sourced from ESPN, Rotowire, and over 50,000 news sites.

Overall Fantasy Football with Watson Insights architecture with social sharing

Figure 1. Overall Fantasy Football with Watson Insights architecture with social sharing

When we focus on the social sharing system shown in Figure 2, the integration points are the IBM Db2 on Cloud and IBM Cloud Object Storage. The social sharing system pulls AI Insights and player biographic data from Db2 on IBM Cloud. Next, the data is populated within a user interface that is captured within the form of two images: one for Twitter and one for Facebook. The results are then combined into several HTML template files. Both the images and HTML template files are stored in IBM Cloud Object Storage. The content is populated around the world within sets of edge servers for consumer access.

A focus on the social sharing subsystem within the context of the overall architecture

Figure 2. A focus on the social sharing subsystem within the context of the overall architecture

Social share system architecture

Designing and building an at-scale social sharing system for millions of users of the ESPN Fantasy Football platform requires enterprise-grade design principles. The socially sharable assets are precomputed by several node applications and pushed to an ObjectStorage origin. The content is then populated through the IBM Cloud Content Delivery Network (CDN) and the ESPN CDN. When a user presses the share social button, the edge computing device pulls HTML and image files to share on either Twitter or Facebook.

The Node.js application called Social Generator Node.js App pulls data from several sources to begin the social share process. The Node.js app pulls data from the CDN about the top 350 current players including kickers and defenses. The JSON file that contains all of the players is created by a Node.js Content Generation System pulled from AI Insights Db2 on Cloud. The original player source is the ESPN API that is enriched by Watson algorithms and then stored in the AI Insights Db2. The player data is joined with AI Insights from the CDN so the full social share can be generated.

The HTML format file describes the data we are sharing to both Twitter and Facebook. For Facebook, we determine the image width, height, title, URL, description, and the type of the content that will be shared. The overall title of the player card we will share is input into the player card. The Twitter fields we populate include title, referencing site, image URL, and a description of the image. To share to social media, the HTML file is uploaded, which references an image.

The social sharing architecture that generates and pushes content to social networks

Figure 3. The social sharing architecture that generates and pushes content to social networks

The images are generated by a Graphics Capture Node.js application. The application is built with a puppeteer and chromium image. A UI was built to accept parameters that describe a player. For example, the application calls the user interface with the following URL encoded parameters.

(player1=2330&leagueId=<leagueid>&teamId=17&snapshot=true&platform=facebook)

After the user interface loads, the Node.js application uses puppeteer to take a snapshot of the page. After the image has been acquired, we ensure its quality with an AI classifier. If the image passes, we take a snapshot of the Twitter format with the following URL encoded parameters.

(player1=2330&leagueId=<leagueid>&teamId=17&snapshot=true&platform=twitter)

Figure 4 shows the rendered raw image for Facebook from our dedicated UI that supports social sharing.

The user interface joins data together that is captured in the form of images

Figure 4. The user interface joins data together that is captured in the form of images

After each of the player images are created, they are uploaded to ObjectStorage. The URLs for the images are then passed back to the Social Generator Node.js application and inserted into the HTML. The HTML file is uploaded to ObjectStorage with the naming format input into the HTML file. The completed and generated HTML file as the naming format of <playerid>_ESPNFantasyFootball_<year>_<date>-<hour>.html, while the image will contain a format such as socialsharing_<facebook|twitter>_<year>_<playerid>_<date>_<hour>.jpg.

When the HTML files are shared, Figure 5 shows how the social Insights look on social media. Each user is able to input their own comments around the player cards.

Player cards that are generated by pulling together HTML, images and AI Highlights Player cards that are generated by pulling together HTML, images and AI Highlights

Figure 5. Player cards that are generated by pulling together HTML, images, and AI highlights

Graphics capture

The Graphics Capture Node.js app exposes endpoints with a RESTful Swagger interface using Express. When a request for “captureScreen” from the Social Generator Node.js app with a payload that has event name, event year, date, time, team id, player id, league id, first name, and last name is received, the UI shown in Figure 4 is loaded. The UI will load so that a puppeteer instance can take a screen capture with headless Chromium.

For example, when the page loads, we generate an image with code similar to:

let browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
  let page = await browser.newPage();
  await page.goto(webshot_facebook_url);
  await timeout(xxx);
  await page.screenshot({path: imageGrabNameFacebook,clip: {
                x: 0,
                y: 0,
                width: xxx,
                height: xxx
              }});
  await browser.close();

Listing 1. Example code written in Node.js that takes a snapshot of the user interface shown in Figure 4

After the image is captured, the file is pushed to ObjectStorage. When they are available on origin, each image is populated throughout our CDNs. The TTL for each type of content is set to 60 minutes in coordination with the scheduled job within the Social Generator Node.js app. Listing 2 shows a Node.js example.

object_storage_client.putObject(imageGrabNameFacebook,bucketName,'image/jpeg',true)
        .then(
          function(data) {
            //res.send("Success");
            console.log("Pushed Facebook file!")
          },
            function(err) {
              console.log(err);

            }
          );

Listing 2. Several lines of code depict a few Node.js lines that push our data to ObjectStorage

AI in social sharing

Each of the images that are created are quality checked by image recognition on Watson Machine Learning. We are able to train the classifier with 200 samples with an even mixture of positive and negative images. A negative image can occur when a player is still processing, the user interface did not load in enough time before image acquisition, or there is a data problem. We predict if an image is acceptable with an accuracy greater than 90%. If the image is not acceptable, the application tries to acquire another screen capture. On the user experience, we disable the social sharing feature for a player without a high-quality image for both Twitter and Facebook. Listing 3 shows how we classify images within JavaScript.

let classifyParams = {
    images_file: fs.createReadStream(imageGrabNameFacebook),
    classifier_ids: [watsonVisual.classifierKey],
    threshold: 0.1,
  };

  visualRecognition.classify(classifyParams)
    .then(classifiedImages => {
      console.log(JSON.stringify(classifiedImages, null, 2));

      imageClasses = classifiedImages.images[0].classifiers[0].classes

      let max=null;
      for (var i=0 ; i<imageClasses.length ; i++) {
          if (!max || imageClasses[i].score > max.score)
              max = imageClasses[i];
        console.log("class: "+max)
      }
      if (max!=null && "class" in max && max["class"] == "playercard"){
        object_storage_client.putObject(imageGrabNameFacebook,bucketName,'image/jpeg',true)
        .then(
          function(data) {
            //res.send("Success");
            console.log("Pushed Facebook file!")
          },
            function(err) {
              console.log(err);

            }
          );
      }
      else{
        imageGrabNameFacebook = null
      }
  })
  .catch(err => {
      console.log('error:', err);
  });

Listing 3. Example JavaScript code that calls the Watson Machine Learning service to predict the quality of player card image

Tell and show your friends

You can now engage your social networks with Watson Smack Talk. As a team manager, share your excitement about your team with player cards to create your own team’s following.

The next article in this 4-part series will discuss the ESPN Fantasy Football with Watson Insights user experience. Get ready for some React. #WinWithWatson.

Aaron Baughman