ca.zadrox.dota2esportticker.util.MatchDetailLoader.java Source code

Java tutorial

Introduction

Here is the source code for ca.zadrox.dota2esportticker.util.MatchDetailLoader.java

Source

/*
 * Copyright 2014 Nicholas 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.
 */

package ca.zadrox.dota2esportticker.util;

import android.content.AsyncTaskLoader;
import android.content.Context;
import android.net.Uri;

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import ca.zadrox.dota2esportticker.data.http.match.model.Livestream;
import ca.zadrox.dota2esportticker.data.http.match.model.Match;
import ca.zadrox.dota2esportticker.data.http.match.model.Player;
import ca.zadrox.dota2esportticker.data.http.match.model.RecentMatch;
import ca.zadrox.dota2esportticker.data.http.match.model.Team;
import ca.zadrox.dota2esportticker.data.http.match.model.Vod;

/**
 * Created by Acco on 10/29/2014.
 */
public class MatchDetailLoader extends AsyncTaskLoader<Match> {

    private static final String BASE_URL = "http://www.gosugamers.net";
    private final String TAG = MatchDetailLoader.class.getSimpleName();

    Match mMatch;
    String mUrl;

    public MatchDetailLoader(Context context, String url) {
        super(context);
        mUrl = url;
    }

    @Override
    protected void onStopLoading() {

        cancelLoad();

    }

    @Override
    public void deliverResult(Match data) {
        if (isReset()) {

            if (mMatch != null) {
                onReleaseResources(mMatch);
            }
        }

        super.deliverResult(data);
    }

    @Override
    protected void onReset() {
        super.onReset();

        onStopLoading();

        if (mMatch != null) {
            onReleaseResources(mMatch);
            mMatch = null;
        }
    }

    @Override
    public void onCanceled(Match data) {
        super.onCanceled(data);

        onReleaseResources(data);
    }

    @Override
    protected void onStartLoading() {
        if (mMatch != null) {
            deliverResult(mMatch);
        } else {
            forceLoad();
        }
    }

    @Override
    public Match loadInBackground() {
        try {

            if (mMatch == null) {
                mMatch = new Match();
            }

            OkHttpClient okHttpClient = new OkHttpClient();
            String rawHtml = okHttpClient.newCall(new Request.Builder().url(mUrl).build()).execute().body()
                    .string();

            //            try {
            //                trimmedHtml = rawHtml.substring(
            //                    rawHtml.indexOf("<div class=\"box box-match-page\">"),
            //                    rawHtml.indexOf("<div id=\"comments\" class=\"box\">")
            //                );
            //            } catch (StringIndexOutOfBoundsException e) {
            //                LogUtils.LOGD(TAG, "Error fetching match data substring.");
            //                e.printStackTrace();
            //                try {
            //                    trimmedHtml = rawHtml.substring(
            //                        rawHtml.indexOf("<div id=\"col1\" class=\"rows\">"),
            //                        rawHtml.indexOf("<div id=\"col2\" class=\"rows\">")
            //                    );
            //                } catch (StringIndexOutOfBoundsException e1) {
            //                    LogUtils.LOGD(TAG, "Error fetching match data, attempting slow method.");
            //                    e1.printStackTrace();
            //                    // unknown how this will work...
            //                    trimmedHtml = rawHtml;
            //                }
            //            }

            // match basic data

            setupMatchData(rawHtml);

            // gosubet stats

            setupGosubetStats(rawHtml);

            // recent match perf

            setupRecentMatchPerf(rawHtml);

            // livestreams

            setupLivestreamUrls(rawHtml);

            // vods and players present

            setupGamebox(rawHtml);

            // now check steamapi for possible matches of teamnames/players

            return mMatch;

        } catch (IOException e) {
            LogUtils.LOGD(TAG, "Likely no internet reception, or timed out");
            e.printStackTrace();
        } catch (StringIndexOutOfBoundsException e2) {
            LogUtils.LOGD(TAG, "Error fetching match data.");
            e2.printStackTrace();
        }
        return null;
    }

    private void setupGamebox(String trimmedHtml) {
        try {
            String gameBoxHtml = trimmedHtml.substring(trimmedHtml.indexOf("<div id=\"tab-content-wrapper\">"));

            Document d = Jsoup.parse(gameBoxHtml);

            ArrayList<Vod> vods = new ArrayList<Vod>();

            ExecutorService executorService = Executors.newFixedThreadPool(10);

            // Videos
            Elements videoElements = d.getElementsByClass("video");
            for (Element vE : videoElements) {

                String vodDesc = vE.getElementsByClass("vod-desc").first().text();
                String vodUrl = "http://www.youtube.com/watch?v=" + vE.getElementsByTag("img").first().attr("src")
                        .replace("https://i.ytimg.com/vi/", "").replace("/1.jpg", "");

                vods.add(new Vod(vodUrl, vodDesc));
            }

            HashSet<Player> teamOnePlayers = new HashSet<Player>();
            HashSet<Player> teamTwoPlayers = new HashSet<Player>();

            Elements gameTabElements = d.getElementsByClass("match-game-tab-content");
            for (Element gTE : gameTabElements) {
                if (!gTE.getElementsByClass("novod-error").isEmpty() && gTE.getElementsByClass("novod-error")
                        .first().text().equals("This game was not played.")) {
                    LogUtils.LOGD(TAG, "entered here...");
                    continue;
                }
                Elements oL = gTE.getElementsByClass("opponent-left").first().getElementsByClass("player");
                Elements oR = gTE.getElementsByClass("opponent-right").first().getElementsByClass("player");

                for (Element p : oL) {
                    Player tP = new Player();
                    tP.name = p.getElementsByTag("a").first().text();

                    if (tP.name.contains("Default Win") || tP.name.contains("Default Loss")
                            || tP.name.contains("Winner Bracket") || tP.name.contains("Loser Bracket")) {
                        continue;
                    }

                    if (!teamOnePlayers.contains(tP)) {

                        tP.profilePageUrl = BASE_URL
                                + p.getElementsByTag("a").first().attr("href").replaceAll("\\r\\n|\\r|\\n", "");

                        tP.isStandin = p.ownText().contains("*");

                        //                    futures.put(tP.name, executorService.submit(
                        //                            new FetchPlayerImageUrl(tP.profilePageUrl)));

                        teamOnePlayers.add(tP);
                    }
                }
                for (Element p : oR) {
                    Player tP = new Player();
                    tP.name = p.getElementsByTag("a").first().text();

                    if (tP.name.contains("Default Win") || tP.name.contains("Default Loss")
                            || tP.name.contains("Winner Bracket") || tP.name.contains("Loser Bracket")) {
                        continue;
                    }

                    if (!teamTwoPlayers.contains(tP)) {

                        tP.profilePageUrl = BASE_URL
                                + p.getElementsByTag("a").first().attr("href").replaceAll("\\r\\n|\\r|\\n", "");

                        tP.isStandin = (p.ownText().equals(" *") || p.ownText().equals("* "));

                        //                    futures.put(tP.name, executorService.submit(
                        //                            new FetchPlayerImageUrl(tP.profilePageUrl)));

                        teamTwoPlayers.add(tP);

                    }
                }
            }

            executorService.shutdown();
            executorService.awaitTermination(5000, TimeUnit.MILLISECONDS);

            mMatch.teamOne.players = new Player[teamOnePlayers.size()];
            mMatch.teamTwo.players = new Player[teamTwoPlayers.size()];

            int i = 0;
            for (Player player : teamOnePlayers) {
                //player.profileImageUrl = BASE_URL + futures.get(player.name).get();
                mMatch.teamOne.players[i] = player;
                i++;
            }

            i = 0;
            for (Player player : teamTwoPlayers) {
                //player.profileImageUrl = BASE_URL + futures.get(player.name).get();
                mMatch.teamTwo.players[i] = player;
                i++;
            }

            mMatch.vods = vods.toArray(new Vod[vods.size()]);

        } catch (StringIndexOutOfBoundsException e) {
            LogUtils.LOGD(TAG, "No Gamebox");
        } catch (InterruptedException e2) {
            LogUtils.LOGD(TAG, "Error fetching vod data");
        } catch (Exception e3) {
            LogUtils.LOGD(TAG, "Error dealing with futures");
            e3.printStackTrace();
        }
    }

    private void setupLivestreamUrls(String trimmedHtml) {

        try {
            String livestreamHtml = trimmedHtml.substring(trimmedHtml.indexOf("<div class=\"tab-wrapper\">"),
                    trimmedHtml.indexOf("<div class=\"tab-wrapper tab-wrapper-bg\">"));

            Document d = Jsoup.parse(livestreamHtml);

            Elements streamTabs = d.getElementsByClass("stream-tab");
            Elements streamTabContent = d.getElementsByClass("vod-wrap");

            ArrayList<String> langs = new ArrayList<String>();
            ArrayList<String> titles = new ArrayList<String>();
            ArrayList<String> streamUrls = new ArrayList<String>();

            for (int i = 0; i < streamTabs.size(); i++) {
                Element sT = streamTabs.get(i);
                Element sTC = streamTabContent.get(i);

                try {
                    Element twitchElement = sTC.getElementsByTag("object").first();

                    String url = "http://www.twitch.tv/"
                            + (Uri.parse(twitchElement.attr("data")).getQueryParameter("channel"));

                    streamUrls.add(url);
                    langs.add(sT.getElementsByClass("lang").first().text());
                    titles.add(sT.ownText().replaceAll(" \\- LIVE!", ""));

                    continue;
                } catch (Exception e) {
                    LogUtils.LOGD(TAG, "Stream isn't twitch");
                }

                try {
                    Element streamElement = d.getElementsByTag("iframe").first();

                    if (streamElement == null) {
                        continue;
                    }

                    String url = streamElement.attr("src");

                    if (url.contains("hitbox") || url.contains("huomao")) {
                        continue;
                    }

                    streamUrls.add(url);
                    langs.add(sT.getElementsByClass("lang").first().text());
                    titles.add(sT.ownText().replaceAll(" \\- LIVE!", ""));

                    continue;
                } catch (Exception e) {
                    LogUtils.LOGD(TAG, "Stream isn't covered by iframe interpreter");
                }
            }

            if (titles.size() > 0) {
                Livestream[] livestreams = new Livestream[titles.size()];
                for (int i = 0; i < titles.size(); i++) {
                    livestreams[i] = new Livestream(langs.get(i), titles.get(i), streamUrls.get(i));
                }
                mMatch.livestreams = livestreams;
            }

        } catch (StringIndexOutOfBoundsException e) {
            LogUtils.LOGD(TAG, "No Livestreams");
        }
    }

    // TODO: get h2h matchup data.
    private void setupRecentMatchPerf(String trimmedHtml) {
        try {
            String teamOneRecentPerfHtml = trimmedHtml.substring(trimmedHtml.indexOf("<div class=\"opp1-perf\">"),
                    trimmedHtml.indexOf("<div class=\"opp2-perf\">"));

            String teamTwoRecentPerfHtml = trimmedHtml.substring(trimmedHtml.indexOf("<div class=\"opp2-perf\">"),
                    trimmedHtml.indexOf("<div class=\"both-perf\">"));

            ArrayList<RecentMatch> recentMatchesTeamOne = new ArrayList<RecentMatch>();
            ArrayList<RecentMatch> recentMatchesTeamTwo = new ArrayList<RecentMatch>();

            Elements tOne = Jsoup.parse(teamOneRecentPerfHtml).getElementsByClass("match-list-row");

            Elements tTwo = Jsoup.parse(teamTwoRecentPerfHtml).getElementsByClass("match-list-row");

            for (Element eo : tOne) {

                recentMatchesTeamOne.add(new RecentMatch(
                        eo.getElementsByTag("strong").first().text().replaceAll(" ?\\.?\\-?-?Dot[aA][\\s]?2", ""),
                        eo.getElementsByTag("span").first().text(),
                        BASE_URL + eo.getElementsByTag("img").first().attr("src"),
                        BASE_URL + eo.getElementsByTag("a").first().attr("href")));

            }

            for (Element et : tTwo) {

                recentMatchesTeamTwo.add(new RecentMatch(
                        et.getElementsByTag("strong").first().text().replaceAll(" ?\\.?\\-?-?Dot[aA][\\s]?2", ""),
                        et.getElementsByTag("span").first().text(),
                        BASE_URL + et.getElementsByTag("img").first().attr("src"),
                        BASE_URL + et.getElementsByTag("a").first().attr("href")));

            }

            mMatch.teamOne.recPerf = recentMatchesTeamOne.toArray(new RecentMatch[recentMatchesTeamOne.size()]);
            mMatch.teamTwo.recPerf = recentMatchesTeamTwo.toArray(new RecentMatch[recentMatchesTeamTwo.size()]);

        } catch (Exception e) {
            LogUtils.LOGD(TAG, "No team recentperf");
        }
    }

    private void setupGosubetStats(String trimmedHtml) {
        String gosuBetHtml = null;

        try {
            gosuBetHtml = trimmedHtml.substring(trimmedHtml.indexOf("<div id=\"tab-gb\">"),
                    trimmedHtml.indexOf("<div id=\"tab-ib-rares\">"));

            Elements nodes = Jsoup.parse(gosuBetHtml).getElementsByClass("percentage");

            if (nodes.size() == 3) {
                mMatch.teamOne.gosubetWin = nodes.get(0).text();
                mMatch.teamOne.gosubetTie = nodes.get(1).text();
                mMatch.teamTwo.gosubetTie = nodes.get(1).text();
                mMatch.teamTwo.gosubetWin = nodes.get(2).text();
            } else {
                mMatch.teamOne.gosubetWin = nodes.get(0).text();
                mMatch.teamTwo.gosubetWin = nodes.get(1).text();
            }

            //LOGD(TAG, "teamOneGosubet-teamTwoGosubet: " + teamOneGosubet + ":" + teamTwoGosubet);

        } catch (IndexOutOfBoundsException e) {
            LogUtils.LOGD(TAG, "Gosubet % unavailable via one method, trying other... ");
            try {
                gosuBetHtml = trimmedHtml.substring(trimmedHtml.indexOf("<div id=\"tab-gb\">"),
                        trimmedHtml.indexOf("<div class=\"match-games-streams\">"));

                Elements nodes = Jsoup.parse(gosuBetHtml).getElementsByClass("percentage");

                if (nodes.size() == 3) {
                    mMatch.teamOne.gosubetWin = nodes.get(0).text();
                    mMatch.teamOne.gosubetTie = nodes.get(1).text();
                    mMatch.teamTwo.gosubetTie = nodes.get(1).text();
                    mMatch.teamTwo.gosubetWin = nodes.get(2).text();
                } else {
                    mMatch.teamOne.gosubetWin = nodes.get(0).text();
                    mMatch.teamTwo.gosubetWin = nodes.get(1).text();
                }

            } catch (IndexOutOfBoundsException e1) {
                LogUtils.LOGD(TAG, "Gosubet % unavailable via one method, trying other... ");
                try {
                    gosuBetHtml = trimmedHtml.substring(trimmedHtml.indexOf("<div id=\"tab-gb\">"),
                            trimmedHtml.indexOf("<div class=\"match-performance\">"));

                    Elements nodes = Jsoup.parse(gosuBetHtml).getElementsByClass("percentage");

                    if (nodes.size() == 3) {
                        mMatch.teamOne.gosubetWin = nodes.get(0).text();
                        mMatch.teamOne.gosubetTie = nodes.get(1).text();
                        mMatch.teamTwo.gosubetTie = nodes.get(1).text();
                        mMatch.teamTwo.gosubetWin = nodes.get(2).text();
                    } else {
                        mMatch.teamOne.gosubetWin = nodes.get(0).text();
                        mMatch.teamTwo.gosubetWin = nodes.get(1).text();
                    }

                } catch (IndexOutOfBoundsException e2) {
                    LogUtils.LOGD(TAG, "No Gosubet % available");
                }
            }
        }
    }

    private void setupMatchData(String trimmedHtml) {
        mMatch.teamOne = new Team();
        mMatch.teamTwo = new Team();

        String opponentHtml = null;
        try {
            opponentHtml = trimmedHtml.substring(trimmedHtml.indexOf("<div class=\"match-opponents\">"),
                    trimmedHtml.indexOf("<div class=\"match-extras\">"));

            Element opponentOne = Jsoup.parse(opponentHtml).getElementsByClass("opponent1").first();
            Element opponentTwo = Jsoup.parse(opponentHtml).getElementsByClass("opponent2").first();

            mMatch.teamOne.teamUrl = BASE_URL + opponentOne.getElementsByTag("a").attr("href");
            mMatch.teamTwo.teamUrl = BASE_URL + opponentTwo.getElementsByTag("a").attr("href");

        } catch (IndexOutOfBoundsException e) {
            LogUtils.LOGD(TAG, "Couldn't get team links.");
        }

        String matchInfoBoxHtml = null;
        try {
            matchInfoBoxHtml = trimmedHtml.substring(trimmedHtml.indexOf("<p class=\"vs\">"),
                    trimmedHtml.indexOf("<p class=\"datetime\">"));
        } catch (IndexOutOfBoundsException e) {
            LogUtils.LOGD(TAG, "Page does not have a score yet.");
            return;
        }

        Document d = Jsoup.parse(matchInfoBoxHtml);

        Elements scorebox = d.getElementsByClass("vs").first().getElementsByTag("span");

        String teamOneScore = "0";
        String teamTwoScore = "0";

        try {
            teamOneScore = scorebox.get(2).text();
            teamTwoScore = scorebox.get(3).text();
        } catch (IndexOutOfBoundsException e) {
            LogUtils.LOGD(TAG, "No final scores, trying to get interim scores");
            try {
                teamOneScore = Character.toString(scorebox.get(1).text().charAt(0));
                teamTwoScore = Character.toString(scorebox.get(1).text().charAt(4));
            } catch (Exception e2) {
                LogUtils.LOGD(TAG, "No interim scores, game must not have started yet.");
            }
        }

        mMatch.teamOne.score = teamOneScore;
        mMatch.teamTwo.score = teamTwoScore;

    }

    protected void onReleaseResources(Match match) {
        // For a simple List<> there is nothing to do.  For something
        // like a Cursor, we would close it here.
    }

    private class FetchPlayerImageUrl implements Callable<String> {
        private String mUrl;

        public FetchPlayerImageUrl(String url) {
            mUrl = url;
        }

        @Override
        public String call() throws Exception {
            OkHttpClient okHttpClient = new OkHttpClient();

            String rawHtml = okHttpClient.newCall(new Request.Builder().url(mUrl).build()).execute().body()
                    .string();

            String imageLink = rawHtml.substring(rawHtml.indexOf("<div class=\"playerImage\"") + 55,
                    rawHtml.indexOf("<div class=\"playerNameHolder\">") - 11);

            //LOGD("FetchPlayerImageUrl", "ImageUrl: " + imageLink);

            return imageLink;
        }
    }
}