@Nullable
 @Override
 public ScoreNotificationViewModel renderToViewModel(Context context, @Nullable Void aVoid) {
   String header = getNotificationCardHeader(context, EventHelper.shortName(eventName), eventKey);
   String title =
       context.getString(
           R.string.notification_score_gameday_title,
           MatchHelper.getMatchTitleFromMatchKey(context, matchKey));
   return new ScoreNotificationViewModel(
       header, title, getNotificationTimeString(context), getIntent(context), match);
 }
  @Override
  public View getView(Context c, LayoutInflater inflater, View convertView) {
    ViewHolder holder;
    if (convertView == null || !(convertView.getTag() instanceof ViewHolder)) {
      convertView = inflater.inflate(R.layout.list_item_notification_score, null, false);

      holder = new ViewHolder();
      holder.header = (TextView) convertView.findViewById(R.id.card_header);
      holder.title = (TextView) convertView.findViewById(R.id.title);
      holder.matchView = (MatchView) convertView.findViewById(R.id.match_details);
      holder.time = (TextView) convertView.findViewById(R.id.notification_time);
      holder.summaryContainer = convertView.findViewById(R.id.summary_container);
      convertView.setTag(holder);
    } else {
      holder = (ViewHolder) convertView.getTag();
    }

    holder.header.setText(
        c.getString(
            R.string.gameday_ticker_event_title_format,
            EventHelper.shortName(eventName),
            EventHelper.getShortCodeForEventKey(eventKey).toUpperCase()));
    holder.title.setText(
        c.getString(
            R.string.notification_score_gameday_title,
            MatchHelper.getMatchTitleFromMatchKey(c, matchKey)));
    holder.time.setText(getNotificationTimeString(c));
    holder.summaryContainer.setOnClickListener(new GamedayTickerClickListener(c, this));

    MatchListElement renderedMatch =
        mRenderer.renderFromModel(match, MatchRenderer.RENDER_NOTIFICATION);
    if (renderedMatch != null) {
      renderedMatch.getView(c, inflater, holder.matchView);
    }

    return convertView;
  }
  @Override
  public void parseData() throws BasicModel.FieldNotDefinedException {
    mDataToBind.clear();
    if (mAPIData == null || !mAPIData.isJsonArray()) {
      return;
    }
    JsonArray rankingsData = mAPIData.getAsJsonArray();
    if (rankingsData.size() == 0) return;
    JsonArray headerRow = rankingsData.get(0).getAsJsonArray();
    for (int i = 1; i < rankingsData.size(); i++) {
      JsonArray row = rankingsData.get(i).getAsJsonArray();
      /* Assume that the list of lists has rank first and team # second, always */
      String teamKey = "frc" + row.get(1).getAsString();
      String rankingString;
      // use a CaseInsensitiveMap in order to find wins, losses, and ties below
      CaseInsensitiveMap<String> rankingElements = new CaseInsensitiveMap<>();
      for (int j = 2; j < row.size(); j++) {
        rankingElements.put(headerRow.get(j).getAsString(), row.get(j).getAsString());
      }

      String record = EventHelper.extractRankingString(rankingElements);

      if (record == null) {
        Set<String> keys = rankingElements.keySet();
        if (keys.contains("wins") && keys.contains("losses") && keys.contains("ties")) {
          record =
              String.format(
                  "(%1$s-%2$s-%3$s",
                  rankingElements.get("wins"),
                  rankingElements.get("losses"),
                  rankingElements.get("ties"));
          rankingElements.remove("wins");
          rankingElements.remove("losses");
          rankingElements.remove("ties");
        }
      }
      if (record == null) {
        record = "";
      }

      rankingString = EventHelper.createRankingBreakdown(rankingElements);

      Team team = mDb.getTeamsTable().get(teamKey);
      String nickname;
      if (team != null) {
        nickname = team.getNickname();
      } else {
        nickname = "Team " + teamKey.substring(3);
      }

      mDataToBind.add(
          new RankingListElement(
              teamKey,
              row.get(1).getAsString(), // team number
              nickname,
              row.get(0).getAsInt(), // rank
              record,
              rankingString));
    }
    mEventBus.post(new EventRankingsEvent(generateTopRanksString(rankingsData)));
  }
  @Override
  public Notification buildNotification(Context context, FollowsChecker followsChecker) {
    Resources r = context.getResources();

    matchKey = match.getKey();

    String matchTitle = MatchHelper.getMatchTitleFromMatchKey(context, matchKey);
    String matchAbbrevTitle = MatchHelper.getAbbrevMatchTitleFromMatchKey(context, matchKey);

    JsonObject alliances = match.getAlliancesJson();

    int redScore = Match.getRedScore(alliances);
    int blueScore = Match.getBlueScore(alliances);

    // Boldify the team numbers that the user is following.
    Predicate<String> isFollowing =
        teamNumber ->
            followsChecker.followsTeam(
                context, teamNumber, matchKey, NotificationTypes.MATCH_SCORE);
    ArrayList<String> redTeams = Match.teamNumbers(Match.getRedTeams(alliances));
    ArrayList<String> blueTeams = Match.teamNumbers(Match.getBlueTeams(alliances));
    CharSequence firstTeams = Utilities.boldNameList(redTeams, isFollowing);
    CharSequence secondTeams = Utilities.boldNameList(blueTeams, isFollowing);

    // Make sure the score string is formatted properly with the winning score first
    String scoreString;
    if (blueScore > redScore) {
      scoreString = blueScore + "-" + redScore;
      CharSequence temp = firstTeams;
      firstTeams = secondTeams;
      secondTeams = temp;
    } else {
      scoreString = redScore + "-" + blueScore;
    }

    MatchType matchType = MatchType.fromShortType(match.getCompLevel());
    boolean useSpecial2015Format = match.getYear() == 2015 && matchType != MatchType.FINAL;

    String eventShortName = EventHelper.shortName(eventName);
    String template;
    if (useSpecial2015Format) { // firstTeams played secondTeams (for 2015 non-finals matches)
      template = context.getString(R.string.notification_score_teams_played_teams);
    } else if (blueScore == redScore) { // firstTeams tied secondTeams
      template = context.getString(R.string.notification_score_teams_tied_teams);
    } else { // firstTeams beat secondTeams
      template = context.getString(R.string.notification_score_teams_beat_teams);
    }
    CharSequence notificationBody =
        TextUtils.expandTemplate(
            template, eventShortName, matchTitle, firstTeams, secondTeams, scoreString);

    // We can finally build the notification!
    Intent instance = getIntent(context);

    stored = new StoredNotification();
    stored.setType(getNotificationType());
    String eventCode = EventHelper.getEventCode(matchKey);
    String notificationTitle =
        r.getString(R.string.notification_score_title, eventCode, matchAbbrevTitle);
    stored.setTitle(notificationTitle);
    stored.setBody(notificationBody.toString());
    stored.setIntent(MyTBAHelper.serializeIntent(instance));
    stored.setTime(Calendar.getInstance().getTime());
    stored.setMessageData(messageData);

    NotificationCompat.Builder builder =
        getBaseBuilder(context, instance)
            .setContentTitle(notificationTitle)
            .setContentText(notificationBody);

    NotificationCompat.BigTextStyle style =
        new NotificationCompat.BigTextStyle().bigText(notificationBody);
    builder.setStyle(style);
    return builder.build();
  }