package com.boardgamegeek.ui.model; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.support.annotation.NonNull; import android.support.v4.util.Pair; import com.boardgamegeek.io.BggService; import com.boardgamegeek.provider.BggContract; import com.boardgamegeek.provider.BggContract.Games; import com.boardgamegeek.provider.BggContract.Plays; import com.boardgamegeek.util.PreferencesUtils; import com.boardgamegeek.util.SelectionBuilder; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class PlayStats { public static final String[] PROJECTION = { Plays.SUM_QUANTITY, Plays.ITEM_NAME, Games.GAME_RANK }; private static final int SUM_QUANTITY = 0; private static final int GAME_NAME = 1; private static final int RANK = 2; private static final int MIN_H_INDEX_GAMES = 2; private static final int MAX_H_INDEX_GAMES = 6; private int numberOfPlays = 0; private int numberOfGames = 0; private int numberOfQuarters = 0; private int numberOfDimes = 0; private int numberOfNickels = 0; private int hIndex = 0; private int hIndexCounter = 1; private final List<Pair<String, Integer>> hIndexGames = new ArrayList<>(); private final Stack<Pair<String, Integer>> hIndexGamesStack = new Stack<>(); private int postIndexCount = 0; private int priorPlayCount; private int top100count = 0; public static PlayStats fromCursor(Cursor cursor) { return new PlayStats(cursor); } private PlayStats(Cursor cursor) { init(cursor); } private void init(Cursor cursor) { if (cursor == null || !cursor.moveToFirst()) { return; } do { int playCount = cursor.getInt(SUM_QUANTITY); String gameName = cursor.getString(GAME_NAME); int rank = cursor.getInt(RANK); numberOfPlays += playCount; numberOfGames++; if (playCount >= 25) { numberOfQuarters++; } else if (playCount >= 10) { numberOfDimes++; } else if (playCount >= 5) { numberOfNickels++; } if (rank >= 1 && rank <= 100) { top100count++; } if (hIndex == 0) { hIndexGamesStack.push(new Pair<>(gameName, playCount)); if (hIndexCounter > playCount) { hIndex = hIndexCounter - 1; int preIndexCount = 0; while (!hIndexGamesStack.isEmpty()) { Pair<String, Integer> game = hIndexGamesStack.pop(); if (preIndexCount < MIN_H_INDEX_GAMES) { hIndexGames.add(0, game); if (game.second != hIndex) { preIndexCount++; priorPlayCount = game.second; } } else //noinspection StatementWithEmptyBody if (preIndexCount >= MAX_H_INDEX_GAMES) { //do nothing } else if (game.second == priorPlayCount) { hIndexGames.add(0, game); preIndexCount++; } } } hIndexCounter++; } else { if (postIndexCount < MIN_H_INDEX_GAMES) { hIndexGames.add(new Pair<>(gameName, playCount)); postIndexCount++; priorPlayCount = playCount; } else //noinspection StatementWithEmptyBody if (postIndexCount >= MAX_H_INDEX_GAMES) { // do nothing } else if (playCount == priorPlayCount) { hIndexGames.add(new Pair<>(gameName, playCount)); postIndexCount++; } } } while (cursor.moveToNext()); } @NonNull public static Uri getUri() { return Plays.CONTENT_URI.buildUpon() .appendQueryParameter(BggContract.QUERY_KEY_GROUP_BY, BggContract.Plays.OBJECT_ID) .build(); } @NonNull public static String getSelection(Context context) { String selection = SelectionBuilder.whereZeroOrNull(Plays.DELETE_TIMESTAMP); if (!PreferencesUtils.logPlayStatsIncomplete(context)) { selection += " AND " + Plays.INCOMPLETE + "!=?"; } if (!PreferencesUtils.logPlayStatsExpansions(context) && !PreferencesUtils.logPlayStatsAccessories(context)) { selection += " AND (" + Games.SUBTYPE + "=? OR " + Games.SUBTYPE + " IS NULL)"; } else if (!PreferencesUtils.logPlayStatsExpansions(context) || !PreferencesUtils.logPlayStatsAccessories(context)) { selection += " AND (" + Games.SUBTYPE + "!=? OR " + Games.SUBTYPE + " IS NULL)"; } return selection; } @NonNull public static String[] getSelectionArgs(Context context) { List<String> args = new ArrayList<>(); if (!PreferencesUtils.logPlayStatsIncomplete(context)) { args.add("1"); } if (!PreferencesUtils.logPlayStatsExpansions(context) && !PreferencesUtils.logPlayStatsAccessories(context)) { args.add(BggService.THING_SUBTYPE_BOARDGAME); } else if (!PreferencesUtils.logPlayStatsExpansions(context)) { args.add(BggService.THING_SUBTYPE_BOARDGAME_EXPANSION); } else if (!PreferencesUtils.logPlayStatsAccessories(context)) { args.add(BggService.THING_SUBTYPE_BOARDGAME_ACCESSORY); } return args.toArray(new String[args.size()]); } @NonNull public static String getSortOrder() { return Plays.SUM_QUANTITY + " DESC, " + Games.GAME_NAME + " ASC"; } public int getNumberOfPlays() { return numberOfPlays; } public int getNumberOfGames() { return numberOfGames; } public int getNumberOfQuarters() { return numberOfQuarters; } public int getNumberOfDimes() { return numberOfDimes; } public int getNumberOfNickels() { return numberOfNickels; } public int getHIndex() { return hIndex; } public int getTop100Count() { return top100count; } public List<Pair<String, Integer>> getHIndexGames() { return hIndexGames; } }