website.openeng.anki.Statistics.java Source code

Java tutorial

Introduction

Here is the source code for website.openeng.anki.Statistics.java

Source

/****************************************************************************************
 * Copyright (c) 2014 Michael Goldbach <michael@m-goldbach.net>                         *
 *                                                                                      *
 * This program is free software; you can redistribute it and/or modify it under        *
 * the terms of the GNU General Public License as published by the Free Software        *
 * Foundation; either version 3 of the License, or (at your option) any later           *
 * version.                                                                             *
 *                                                                                      *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
 *                                                                                      *
 * You should have received a copy of the GNU General Public License along with         *
 * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
 ****************************************************************************************/
package website.openeng.anki;

import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;

import website.openeng.ui.SlidingTabLayout;
import website.openeng.anim.ActivityTransitionAnimation;
import website.openeng.anki.stats.AnkiStatsTaskHandler;
import website.openeng.anki.stats.ChartView;
import website.openeng.anki.widgets.DeckDropDownAdapter;
import website.openeng.libanki.Collection;
import website.openeng.libanki.Stats;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import timber.log.Timber;

public class Statistics extends NavigationDrawerActivity implements DeckDropDownAdapter.SubtitleListener {

    public static final int TODAYS_STATS_TAB_POSITION = 0;
    public static final int FORECAST_TAB_POSITION = 1;
    public static final int REVIEW_COUNT_TAB_POSITION = 2;
    public static final int REVIEW_TIME_TAB_POSITION = 3;
    public static final int INTERVALS_TAB_POSITION = 4;
    public static final int HOURLY_BREAKDOWN_TAB_POSITION = 5;
    public static final int WEEKLY_BREAKDOWN_TAB_POSITION = 6;
    public static final int ANSWER_BUTTONS_TAB_POSITION = 7;
    public static final int CARDS_TYPES_TAB_POSITION = 8;

    private Menu mMenu;
    private SectionsPagerAdapter mSectionsPagerAdapter;
    private ViewPager mViewPager;
    private SlidingTabLayout mSlidingTabLayout;
    private AnkiStatsTaskHandler mTaskHandler = null;
    private View mMainLayout;
    private ArrayList<JSONObject> mDropDownDecks;
    private DeckDropDownAdapter mDropDownAdapter;
    private Spinner mActionBarSpinner;
    private static boolean sIsSubtitle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Timber.d("onCreate()");
        sIsSubtitle = true;
        super.onCreate(savedInstanceState);

        mMainLayout = getLayoutInflater().inflate(R.layout.activity_anki_stats, null);
        initNavigationDrawer(mMainLayout);
        setContentView(mMainLayout);
        startLoadingCollection();
    }

    @Override
    protected void onCollectionLoaded(Collection col) {
        Timber.d("onCollectionLoaded()");
        // Add drop-down menu to select deck to action bar.
        mDropDownDecks = getCol().getDecks().allSorted();
        mDropDownAdapter = new DeckDropDownAdapter(this, mDropDownDecks);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayShowTitleEnabled(false);
        mActionBarSpinner = (Spinner) findViewById(R.id.toolbar_spinner);
        mActionBarSpinner.setAdapter(mDropDownAdapter);
        mActionBarSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                selectDropDownItem(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                // do nothing
            }
        });
        mActionBarSpinner.setVisibility(View.VISIBLE);

        // Setup Task Handler
        mTaskHandler = new AnkiStatsTaskHandler(col);

        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);
        mViewPager.setOffscreenPageLimit(8);
        mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
        mSlidingTabLayout.setViewPager(mViewPager);
        AnkiStatsTaskHandler.createFirstStatisticChooserTask(col, mViewPager);

        // Dirty way to get text size from a TextView with current style, change if possible
        float size = new TextView(this).getTextSize();
        mTaskHandler.setmStandardTextSize(size);
        // Prepare options menu only after loading everything
        supportInvalidateOptionsMenu();
        mSectionsPagerAdapter.notifyDataSetChanged();

        // set the currently selected deck
        String currentDeckName;
        try {
            currentDeckName = getCol().getDecks().current().getString("name");
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        if (sIsWholeCollection) {
            selectDropDownItem(0);
        } else {
            for (int dropDownDeckIdx = 0; dropDownDeckIdx < mDropDownDecks.size(); dropDownDeckIdx++) {
                JSONObject deck = mDropDownDecks.get(dropDownDeckIdx);
                String deckName;
                try {
                    deckName = deck.getString("name");
                } catch (JSONException e) {
                    throw new RuntimeException();
                }
                if (deckName.equals(currentDeckName)) {
                    selectDropDownItem(dropDownDeckIdx + 1);
                    break;
                }
            }
        }
    }

    @Override
    protected void onResume() {
        Timber.d("onResume()");
        selectNavigationItem(R.id.nav_stats);
        super.onResume();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        mMenu = menu;
        //System.err.println("in onCreateOptionsMenu");
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.anki_stats, mMenu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // exit if mTaskHandler not initialized yet
        if (mTaskHandler == null) {
            return true;
        }
        switch (mTaskHandler.getStatType()) {
        case Stats.TYPE_MONTH:
            MenuItem monthItem = menu.findItem(R.id.item_time_month);
            monthItem.setChecked(true);
            break;
        case Stats.TYPE_YEAR:
            MenuItem yearItem = menu.findItem(R.id.item_time_year);
            yearItem.setChecked(true);
            break;
        case Stats.TYPE_LIFE:
            MenuItem lifeItem = menu.findItem(R.id.item_time_all);
            lifeItem.setChecked(true);
            break;
        }

        return super.onPrepareOptionsMenu(menu);

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // The action bar home/up action should open or close the drawer.
        // ActionBarDrawerToggle will take care of this.
        if (getDrawerToggle().onOptionsItemSelected(item)) {
            return true;
        }
        int itemId = item.getItemId();
        switch (itemId) {
        case R.id.item_time_month:
            if (item.isChecked())
                item.setChecked(false);
            else
                item.setChecked(true);
            if (mTaskHandler.getStatType() != Stats.TYPE_MONTH) {
                mTaskHandler.setStatType(Stats.TYPE_MONTH);
                mSectionsPagerAdapter.notifyDataSetChanged();
            }
            return true;
        case R.id.item_time_year:
            if (item.isChecked())
                item.setChecked(false);
            else
                item.setChecked(true);
            if (mTaskHandler.getStatType() != Stats.TYPE_YEAR) {
                mTaskHandler.setStatType(Stats.TYPE_YEAR);
                mSectionsPagerAdapter.notifyDataSetChanged();
            }
            return true;
        case R.id.item_time_all:
            if (item.isChecked())
                item.setChecked(false);
            else
                item.setChecked(true);
            if (mTaskHandler.getStatType() != Stats.TYPE_LIFE) {
                mTaskHandler.setStatType(Stats.TYPE_LIFE);
                mSectionsPagerAdapter.notifyDataSetChanged();
            }
            return true;
        case R.id.action_time_chooser:
            //showTimeDialog();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void selectDropDownItem(int position) {
        mActionBarSpinner.setSelection(position);
        if (position == 0) {
            sIsWholeCollection = true;
        } else {
            sIsWholeCollection = false;
            JSONObject deck = mDropDownDecks.get(position - 1);
            try {
                getCol().getDecks().select(deck.getLong("id"));
            } catch (JSONException e) {
                Timber.e(e, "Could not get ID from deck");
            }
        }
        mSectionsPagerAdapter.notifyDataSetChanged();
    }

    /**
     * @return text to be used in the subtitle of the drop-down deck selector
     */
    public String getSubtitleText() {
        return getResources().getString(R.string.statistics);
    }

    public AnkiStatsTaskHandler getTaskHandler() {
        return mTaskHandler;
    }

    public ViewPager getViewPager() {
        return mViewPager;
    }

    public SectionsPagerAdapter getSectionsPagerAdapter() {
        return mSectionsPagerAdapter;
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        //this is called when mSectionsPagerAdapter.notifyDataSetChanged() is called, so checkAndUpdate() here
        //works best for updating all tabs
        @Override
        public int getItemPosition(Object object) {
            if (object instanceof StatisticFragment) {
                ((StatisticFragment) object).checkAndUpdate();
            }
            //don't return POSITION_NONE, avoid fragment recreation.
            return super.getItemPosition(object);
        }

        @Override
        public Fragment getItem(int position) {
            Fragment item = StatisticFragment.newInstance(position);
            ((StatisticFragment) item).checkAndUpdate();
            return item;
        }

        @Override
        public int getCount() {
            return 9;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();

            switch (position) {
            case TODAYS_STATS_TAB_POSITION:
                return getString(R.string.stats_today).toUpperCase(l);
            case FORECAST_TAB_POSITION:
                return getString(R.string.stats_forecast).toUpperCase(l);
            case REVIEW_COUNT_TAB_POSITION:
                return getString(R.string.stats_review_count).toUpperCase(l);
            case REVIEW_TIME_TAB_POSITION:
                return getString(R.string.stats_review_time).toUpperCase(l);
            case INTERVALS_TAB_POSITION:
                return getString(R.string.stats_review_intervals).toUpperCase(l);
            case HOURLY_BREAKDOWN_TAB_POSITION:
                return getString(R.string.stats_breakdown).toUpperCase(l);
            case WEEKLY_BREAKDOWN_TAB_POSITION:
                return getString(R.string.stats_weekly_breakdown).toUpperCase(l);
            case ANSWER_BUTTONS_TAB_POSITION:
                return getString(R.string.stats_answer_buttons).toUpperCase(l);
            case CARDS_TYPES_TAB_POSITION:
                return getString(R.string.stats_cards_types).toUpperCase(l);
            }
            return null;
        }
    }

    public static abstract class StatisticFragment extends Fragment {

        //track current settings for each individual fragment
        protected long mDeckId;
        protected boolean mIsWholeCollection;

        protected ViewPager mActivityPager;
        protected SectionsPagerAdapter mActivitySectionPagerAdapter;

        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        protected static final String ARG_SECTION_NUMBER = "section_number";

        /**
         * Returns a new instance of this fragment for the given section
         * number.
         */
        public static StatisticFragment newInstance(int sectionNumber) {
            Fragment fragment;
            Bundle args;
            switch (sectionNumber) {
            case FORECAST_TAB_POSITION:
            case REVIEW_COUNT_TAB_POSITION:
            case REVIEW_TIME_TAB_POSITION:
            case INTERVALS_TAB_POSITION:
            case HOURLY_BREAKDOWN_TAB_POSITION:
            case WEEKLY_BREAKDOWN_TAB_POSITION:
            case ANSWER_BUTTONS_TAB_POSITION:
            case CARDS_TYPES_TAB_POSITION:
                fragment = new ChartFragment();
                args = new Bundle();
                args.putInt(ARG_SECTION_NUMBER, sectionNumber);
                fragment.setArguments(args);
                return (ChartFragment) fragment;
            case TODAYS_STATS_TAB_POSITION:
                fragment = new OverviewStatisticsFragment();
                args = new Bundle();
                args.putInt(ARG_SECTION_NUMBER, sectionNumber);
                fragment.setArguments(args);
                return (OverviewStatisticsFragment) fragment;

            default:
                return null;
            }

        }

        @Override
        public void onResume() {
            super.onResume();
            checkAndUpdate();

        }

        public abstract void invalidateView();

        public abstract void checkAndUpdate();

    }

    /**
     * A chart fragment containing a ChartView.
     */
    public static class ChartFragment extends StatisticFragment {

        private ChartView mChart;
        private ProgressBar mProgressBar;
        private int mHeight = 0;
        private int mWidth = 0;
        private int mSectionNumber;

        private int mType = Stats.TYPE_MONTH;
        private boolean mIsCreated = false;

        private AsyncTask mCreateChartTask;

        public ChartFragment() {
            super();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            setHasOptionsMenu(true);
            Bundle bundle = getArguments();
            mSectionNumber = bundle.getInt(ARG_SECTION_NUMBER);
            //int sectionNumber = 0;
            //System.err.println("sectionNumber: " + mSectionNumber);
            View rootView = inflater.inflate(R.layout.fragment_anki_stats, container, false);
            mChart = (ChartView) rootView.findViewById(R.id.image_view_chart);
            if (mChart == null)
                Timber.d("mChart null!!!");
            else
                Timber.d("mChart is not null!");

            //mChart.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

            mProgressBar = (ProgressBar) rootView.findViewById(R.id.progress_bar_stats);

            mProgressBar.setVisibility(View.VISIBLE);
            //mChart.setVisibility(View.GONE);

            // TODO: Implementing loader for Collection in Fragment itself would be a better solution.
            if ((((Statistics) getActivity()).getTaskHandler()) == null) {
                // Close statistics if the TaskHandler hasn't been loaded yet
                Timber.e("Statistics.ChartFragment.onCreateView() TaskHandler not found");
                getActivity().finish();
                return rootView;
            }

            createChart();
            mHeight = mChart.getMeasuredHeight();
            mWidth = mChart.getMeasuredWidth();
            mChart.addFragment(this);

            mType = (((Statistics) getActivity()).getTaskHandler()).getStatType();
            mIsCreated = true;
            mActivityPager = ((Statistics) getActivity()).getViewPager();
            mActivitySectionPagerAdapter = ((Statistics) getActivity()).getSectionsPagerAdapter();
            mDeckId = CollectionHelper.getInstance().getCol(getActivity()).getDecks().selected();
            mIsWholeCollection = sIsWholeCollection;

            if (!sIsWholeCollection) {
                try {
                    Collection col = CollectionHelper.getInstance().getCol(getActivity());
                    List<String> parts = Arrays.asList(col.getDecks().current().getString("name").split("::"));
                    if (sIsSubtitle)
                        ((AppCompatActivity) getActivity()).getSupportActionBar()
                                .setSubtitle(parts.get(parts.size() - 1));
                    else
                        getActivity().setTitle(parts.get(parts.size() - 1));
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
            } else {
                if (sIsSubtitle)
                    ((AppCompatActivity) getActivity()).getSupportActionBar()
                            .setSubtitle(R.string.stats_deck_collection);
                else
                    getActivity().setTitle(getResources().getString(R.string.stats_deck_collection));
            }
            return rootView;
        }

        private void createChart() {

            switch (mSectionNumber) {
            case FORECAST_TAB_POSITION:
                mCreateChartTask = (((Statistics) getActivity()).getTaskHandler())
                        .createChart(Stats.ChartType.FORECAST, mChart, mProgressBar);
                break;
            case REVIEW_COUNT_TAB_POSITION:
                mCreateChartTask = (((Statistics) getActivity()).getTaskHandler())
                        .createChart(Stats.ChartType.REVIEW_COUNT, mChart, mProgressBar);
                break;
            case REVIEW_TIME_TAB_POSITION:
                mCreateChartTask = (((Statistics) getActivity()).getTaskHandler())
                        .createChart(Stats.ChartType.REVIEW_TIME, mChart, mProgressBar);
                break;
            case INTERVALS_TAB_POSITION:
                mCreateChartTask = (((Statistics) getActivity()).getTaskHandler())
                        .createChart(Stats.ChartType.INTERVALS, mChart, mProgressBar);
                break;
            case HOURLY_BREAKDOWN_TAB_POSITION:
                mCreateChartTask = (((Statistics) getActivity()).getTaskHandler())
                        .createChart(Stats.ChartType.HOURLY_BREAKDOWN, mChart, mProgressBar);
                break;
            case WEEKLY_BREAKDOWN_TAB_POSITION:
                mCreateChartTask = (((Statistics) getActivity()).getTaskHandler())
                        .createChart(Stats.ChartType.WEEKLY_BREAKDOWN, mChart, mProgressBar);
                break;
            case ANSWER_BUTTONS_TAB_POSITION:
                mCreateChartTask = (((Statistics) getActivity()).getTaskHandler())
                        .createChart(Stats.ChartType.ANSWER_BUTTONS, mChart, mProgressBar);
                break;
            case CARDS_TYPES_TAB_POSITION:
                mCreateChartTask = (((Statistics) getActivity()).getTaskHandler())
                        .createChart(Stats.ChartType.CARDS_TYPES, mChart, mProgressBar);
                break;

            }
        }

        @Override
        public void checkAndUpdate() {
            //System.err.println("<<<<<<<checkAndUpdate" + mSectionNumber);
            if (!mIsCreated)
                return;
            int height = mChart.getMeasuredHeight();
            int width = mChart.getMeasuredWidth();

            //are height and width checks still necessary without bitmaps?
            if (height != 0 && width != 0) {
                Collection col = CollectionHelper.getInstance().getCol(getActivity());
                if (mHeight != height || mWidth != width
                        || mType != (((Statistics) getActivity()).getTaskHandler()).getStatType()
                        || mDeckId != col.getDecks().selected() || mIsWholeCollection != sIsWholeCollection) {
                    mHeight = height;
                    mWidth = width;
                    mType = (((Statistics) getActivity()).getTaskHandler()).getStatType();
                    mProgressBar.setVisibility(View.VISIBLE);
                    mChart.setVisibility(View.GONE);
                    mDeckId = col.getDecks().selected();
                    mIsWholeCollection = sIsWholeCollection;
                    if (mCreateChartTask != null && !mCreateChartTask.isCancelled()) {
                        mCreateChartTask.cancel(true);
                    }
                    createChart();
                }
            }
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }

        @Override
        public void invalidateView() {
            if (mChart != null)
                mChart.invalidate();
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            if (mCreateChartTask != null && !mCreateChartTask.isCancelled()) {
                mCreateChartTask.cancel(true);
            }
        }
    }

    public static class OverviewStatisticsFragment extends StatisticFragment {

        private WebView mWebView;
        private ProgressBar mProgressBar;
        private int mType = Stats.TYPE_MONTH;
        private boolean mIsCreated = false;
        private AsyncTask mCreateStatisticsOverviewTask;

        public OverviewStatisticsFragment() {
            super();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            setHasOptionsMenu(true);
            View rootView = inflater.inflate(R.layout.fragment_anki_stats_overview, container, false);
            AnkiStatsTaskHandler handler = (((Statistics) getActivity()).getTaskHandler());
            // Workaround for issue 2406 -- crash when resuming after app is purged from RAM
            // TODO: Implementing loader for Collection in Fragment itself would be a better solution.
            if (handler == null) {
                Timber.e("Statistics.OverviewStatisticsFragment.onCreateView() TaskHandler not found");
                getActivity().finish();
                return rootView;
            }
            mWebView = (WebView) rootView.findViewById(R.id.web_view_stats);
            if (mWebView == null)
                Timber.d("mChart null!!!");
            else
                Timber.d("mChart is not null!");

            //mChart.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

            mProgressBar = (ProgressBar) rootView.findViewById(R.id.progress_bar_stats_overview);

            mProgressBar.setVisibility(View.VISIBLE);
            //mChart.setVisibility(View.GONE);
            createStatisticOverview();
            mType = handler.getStatType();
            mIsCreated = true;
            mActivityPager = ((Statistics) getActivity()).getViewPager();
            mActivitySectionPagerAdapter = ((Statistics) getActivity()).getSectionsPagerAdapter();
            Collection col = CollectionHelper.getInstance().getCol(getActivity());
            mDeckId = col.getDecks().selected();
            mIsWholeCollection = sIsWholeCollection;
            if (!sIsWholeCollection) {
                try {
                    List<String> parts = Arrays.asList(col.getDecks().current().getString("name").split("::"));
                    if (sIsSubtitle)
                        ((AppCompatActivity) getActivity()).getSupportActionBar()
                                .setSubtitle(parts.get(parts.size() - 1));
                    else
                        getActivity().setTitle(parts.get(parts.size() - 1));
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
            } else {
                if (sIsSubtitle)
                    ((AppCompatActivity) getActivity()).getSupportActionBar()
                            .setSubtitle(R.string.stats_deck_collection);
                else
                    getActivity().setTitle(getResources().getString(R.string.stats_deck_collection));
            }
            return rootView;
        }

        private void createStatisticOverview() {
            AnkiStatsTaskHandler handler = (((Statistics) getActivity()).getTaskHandler());
            mCreateStatisticsOverviewTask = handler.createStatisticsOverview(mWebView, mProgressBar);
        }

        @Override
        public void invalidateView() {
            if (mWebView != null)
                mWebView.invalidate();
        }

        @Override
        public void checkAndUpdate() {
            if (!mIsCreated) {
                return;
            }
            Collection col = CollectionHelper.getInstance().getCol(getActivity());
            if (mType != (((Statistics) getActivity()).getTaskHandler()).getStatType()
                    || mDeckId != col.getDecks().selected() || mIsWholeCollection != sIsWholeCollection) {
                mType = (((Statistics) getActivity()).getTaskHandler()).getStatType();
                mProgressBar.setVisibility(View.VISIBLE);
                mWebView.setVisibility(View.GONE);
                mDeckId = col.getDecks().selected();
                mIsWholeCollection = sIsWholeCollection;
                if (mCreateStatisticsOverviewTask != null && !mCreateStatisticsOverviewTask.isCancelled()) {
                    mCreateStatisticsOverviewTask.cancel(true);
                }
                createStatisticOverview();
            }
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            if (mCreateStatisticsOverviewTask != null && !mCreateStatisticsOverviewTask.isCancelled()) {
                mCreateStatisticsOverviewTask.cancel(true);
            }
        }

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
            Timber.i("Statistics:: Statistics - onBackPressed()");
            Intent data = new Intent();
            if (getIntent().hasExtra("selectedDeck")) {
                data.putExtra("originalDeck", getIntent().getLongExtra("selectedDeck", 0L));
            }
            setResult(RESULT_CANCELED, data);
            finishWithAnimation(ActivityTransitionAnimation.RIGHT);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}