diff --git a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/LeaderboardActivity.java b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/LeaderboardActivity.java index 7a212c61c..74c79d703 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/LeaderboardActivity.java +++ b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/LeaderboardActivity.java @@ -20,8 +20,6 @@ public class LeaderboardActivity extends AppCompatActivity { - private int numberOfUsers = 10; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -72,25 +70,26 @@ public void onPageScrollStateChanged(int state) { backButton.setOnClickListener(v -> onBackPressed()); + // The default number of ranks shown is 10. + // Please check the LeaderboardAdapter's fields if you wish to change the default. + tenButton.setBackgroundColor(optionSelectedColor); + tenButton.setOnClickListener(v -> { - numberOfUsers = 10; - leaderboardPagerAdapter.setNumberOfUsers(numberOfUsers); + leaderboardPagerAdapter.changeLargestNumberRankToDisplay(10); findViewById(R.id.btnTen).setBackgroundColor(optionSelectedColor); findViewById(R.id.btnTwentyFive).setBackgroundColor(optionAvailableColor); findViewById(R.id.btnAll).setBackgroundColor(optionAvailableColor); }); twentyFiveButton.setOnClickListener(v -> { - numberOfUsers = 25; - leaderboardPagerAdapter.setNumberOfUsers(numberOfUsers); + leaderboardPagerAdapter.changeLargestNumberRankToDisplay(25); findViewById(R.id.btnTen).setBackgroundColor(optionAvailableColor); findViewById(R.id.btnTwentyFive).setBackgroundColor(optionSelectedColor); findViewById(R.id.btnAll).setBackgroundColor(optionAvailableColor); }); allButton.setOnClickListener(v -> { - numberOfUsers = 0; - leaderboardPagerAdapter.setNumberOfUsers(numberOfUsers); + leaderboardPagerAdapter.changeLargestNumberRankToDisplay(0); findViewById(R.id.btnTen).setBackgroundColor(optionAvailableColor); findViewById(R.id.btnTwentyFive).setBackgroundColor(optionAvailableColor); findViewById(R.id.btnAll).setBackgroundColor(optionSelectedColor); @@ -129,13 +128,13 @@ public void onNothingSelected(AdapterView parent) { everyoneButton.setBackgroundColor(optionSelectedColor); averageButton.setOnClickListener(v -> { - leaderboardPagerAdapter.setCurrentLeaderboardType(LeaderboardFragment.LeaderboardType.Average); + leaderboardPagerAdapter.setCurrentLeaderboardRankingListType(LeaderboardFragment.RankingListType.AVERAGE); averageButton.setBackgroundColor(optionSelectedColor); bestButton.setBackgroundColor(optionAvailableColor); }); bestButton.setOnClickListener(v -> { - leaderboardPagerAdapter.setCurrentLeaderboardType(LeaderboardFragment.LeaderboardType.Best); + leaderboardPagerAdapter.setCurrentLeaderboardRankingListType(LeaderboardFragment.RankingListType.BEST); averageButton.setBackgroundColor(optionAvailableColor); bestButton.setBackgroundColor(optionSelectedColor); }); diff --git a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/LeaderboardPagerAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/LeaderboardPagerAdapter.java index 4c3351e1b..d5cc5a532 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/LeaderboardPagerAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/LeaderboardPagerAdapter.java @@ -12,6 +12,7 @@ import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.ui.leaderboard.leaderboardFragment.AverageMovingSpeedLeaderboardFragment; +import de.dennisguse.opentracks.ui.leaderboard.leaderboardFragment.LeaderboardAdapter; import de.dennisguse.opentracks.ui.leaderboard.leaderboardFragment.MaxSpeedLeaderboardFragment; import de.dennisguse.opentracks.ui.leaderboard.leaderboardFragment.DistanceLeaderboardFragment; import de.dennisguse.opentracks.ui.leaderboard.leaderboardFragment.LeaderboardFragment; @@ -23,7 +24,10 @@ public class LeaderboardPagerAdapter extends FragmentPagerAdapter { private MaxSpeedLeaderboardFragment maxSpeedLeaderboardFragment; private AverageMovingSpeedLeaderboardFragment averageMovingSpeedLeaderboardFragment; private LeaderboardFragment currentLeaderboardFragment; - private LeaderboardFragment.LeaderboardType currentLeaderboardType; + private LeaderboardFragment.RankingListType currentRankingListType; + + // Please remove this boolean once the Leaderboard is able to use read data + private boolean altTestData; public LeaderboardPagerAdapter(FragmentManager fm) { super(fm); @@ -33,11 +37,11 @@ public LeaderboardPagerAdapter(FragmentManager fm) { averageMovingSpeedLeaderboardFragment = new AverageMovingSpeedLeaderboardFragment(); currentLeaderboardFragment = movingTimeLeaderboardFragment; - currentLeaderboardType = LeaderboardFragment.LeaderboardType.Average; + currentRankingListType = LeaderboardFragment.RankingListType.AVERAGE; refreshLeaderboardFragmentData(); } - public enum LeaderboardType { + public enum LeaderboardFragmentType { MOVING_TIME(0, "Moving Time"), DISTANCE(1, "Distance"), MAX_SPEED(2, "Max Speed"), @@ -47,7 +51,7 @@ public enum LeaderboardType { private final int value; private final String title; - private LeaderboardType(int value, String title) { + private LeaderboardFragmentType(int value, String title) { this.value = value; this.title = title; } @@ -61,75 +65,92 @@ public String getTitle() { } } + /** + * Sets the currentLeaderboardFragment based on the sent position and + * keeps the Ranking list it is meant to show on-screen up to date (without refreshing). + * @param position The position corresponding to the desired LeaderboardFragment child class you want to switch to. + */ public void setCurrentLeaderboardFragment(int position) { - if (position == LeaderboardPagerAdapter.LeaderboardType.MOVING_TIME.value) + if (position == LeaderboardFragmentType.MOVING_TIME.value) currentLeaderboardFragment = movingTimeLeaderboardFragment; - else if (position == LeaderboardPagerAdapter.LeaderboardType.DISTANCE.value) + else if (position == LeaderboardFragmentType.DISTANCE.value) currentLeaderboardFragment = distanceLeaderboardFragment; - else if (position == LeaderboardPagerAdapter.LeaderboardType.MAX_SPEED.value) + else if (position == LeaderboardFragmentType.MAX_SPEED.value) currentLeaderboardFragment = maxSpeedLeaderboardFragment; - else if (position == LeaderboardPagerAdapter.LeaderboardType.AVERAGE_MOVING_SPEED.value) + else if (position == LeaderboardFragmentType.AVERAGE_MOVING_SPEED.value) currentLeaderboardFragment = averageMovingSpeedLeaderboardFragment; - currentLeaderboardFragment.setDisplayedRankingList(currentLeaderboardType); + currentLeaderboardFragment.setDisplayedRankingList(currentRankingListType); } @Override public int getCount() { - return LeaderboardPagerAdapter.LeaderboardType.values().length; + return LeaderboardFragmentType.values().length; } @Override public Fragment getItem(int position) { - // Return the appropriate Fragment for each tab position - if (position == LeaderboardPagerAdapter.LeaderboardType.MOVING_TIME.value) + // Return the appropriate LeaderboardFragment for each tab position + if (position == LeaderboardFragmentType.MOVING_TIME.value) return movingTimeLeaderboardFragment; - else if (position == LeaderboardPagerAdapter.LeaderboardType.DISTANCE.value) + else if (position == LeaderboardFragmentType.DISTANCE.value) return distanceLeaderboardFragment; - else if (position == LeaderboardPagerAdapter.LeaderboardType.MAX_SPEED.value) + else if (position == LeaderboardFragmentType.MAX_SPEED.value) return maxSpeedLeaderboardFragment; - else if (position == LeaderboardPagerAdapter.LeaderboardType.AVERAGE_MOVING_SPEED.value) + else if (position == LeaderboardFragmentType.AVERAGE_MOVING_SPEED.value) return averageMovingSpeedLeaderboardFragment; return currentLeaderboardFragment; } @Override public CharSequence getPageTitle(int position) { - if (position == LeaderboardPagerAdapter.LeaderboardType.MOVING_TIME.value) - return LeaderboardPagerAdapter.LeaderboardType.MOVING_TIME.getTitle(); - else if (position == LeaderboardPagerAdapter.LeaderboardType.DISTANCE.value) - return LeaderboardPagerAdapter.LeaderboardType.DISTANCE.getTitle(); - else if (position == LeaderboardPagerAdapter.LeaderboardType.MAX_SPEED.value) - return LeaderboardPagerAdapter.LeaderboardType.MAX_SPEED.getTitle(); - else if (position == LeaderboardPagerAdapter.LeaderboardType.AVERAGE_MOVING_SPEED.value) - return LeaderboardPagerAdapter.LeaderboardType.AVERAGE_MOVING_SPEED.getTitle(); - return null; + if (position == LeaderboardFragmentType.MOVING_TIME.value) + return LeaderboardFragmentType.MOVING_TIME.getTitle(); + else if (position == LeaderboardFragmentType.DISTANCE.value) + return LeaderboardFragmentType.DISTANCE.getTitle(); + else if (position == LeaderboardFragmentType.MAX_SPEED.value) + return LeaderboardFragmentType.MAX_SPEED.getTitle(); + else if (position == LeaderboardFragmentType.AVERAGE_MOVING_SPEED.value) + return LeaderboardFragmentType.AVERAGE_MOVING_SPEED.getTitle(); + return ""; } - public void setCurrentLeaderboardType(LeaderboardFragment.LeaderboardType leaderboardType) { - if (leaderboardType == currentLeaderboardType) + /** + * Swaps the Ranking list that the currentLeaderboardFragment is showing in the GUI based on the sent rankingListType. + * @param rankingListType The type of Ranking list that the currentLeaderboardFragment should show in the GUI. + */ + public void setCurrentLeaderboardRankingListType(LeaderboardFragment.RankingListType rankingListType) { + if (rankingListType == currentRankingListType) return; - currentLeaderboardType = leaderboardType; - currentLeaderboardFragment.setDisplayedRankingList(currentLeaderboardType); + currentRankingListType = rankingListType; + currentLeaderboardFragment.setDisplayedRankingList(currentRankingListType); } + /** + * Refreshes the Ranking list data in every LeaderboardFragment in this LeaderboardPageAdapter based off the latest available data. + * Ensures that the currentLeaderboardFragment is still showing the Rankings data it is meant to show as per the user's specifications. + */ public void refreshLeaderboardFragmentData() { List latestLeaderboardData = readLatestLeaderboardData(); movingTimeLeaderboardFragment.updateRankingLists(latestLeaderboardData); distanceLeaderboardFragment.updateRankingLists(latestLeaderboardData); maxSpeedLeaderboardFragment.updateRankingLists(latestLeaderboardData); averageMovingSpeedLeaderboardFragment.updateRankingLists(latestLeaderboardData); - currentLeaderboardFragment.setDisplayedRankingList(currentLeaderboardType); + currentLeaderboardFragment.setDisplayedRankingList(currentRankingListType); } - public void setNumberOfUsers(int numberOfUsers) { - movingTimeLeaderboardFragment.setDisplayAmount(numberOfUsers); - distanceLeaderboardFragment.setDisplayAmount(numberOfUsers); - maxSpeedLeaderboardFragment.setDisplayAmount(numberOfUsers); - averageMovingSpeedLeaderboardFragment.setDisplayAmount(numberOfUsers); - refreshLeaderboardFragmentData(); + /** + * Sets the largest-number Rank that the LeaderboardAdapters can display and + * updates the Ranking list that the currentLeaderboardFragment is showing on the GUI accordingly. + * @param largestNumberRank The largest-number rank that can be shown on-screen by any LeaderboardAdapter. + */ + public void changeLargestNumberRankToDisplay(int largestNumberRank) { + LeaderboardAdapter.setLargestNumberRankToDisplay(largestNumberRank); + currentLeaderboardFragment.setDisplayedRankingList(currentRankingListType); } + private List readLatestLeaderboardData() { - // This is where we get the data from the database for the runs that will be in the leaderboard. + // This is where we get the data "from the database" for the runs that will be in the leaderboard. + // This method can be removed once the leaderboards can use real data. List testData = new ArrayList(); TrackStatistics stats = new TrackStatistics(); @@ -156,11 +177,13 @@ private List readLatestLeaderboardData() { stats.setMovingTime(Duration.ofHours(1)); testData.add(new PlaceHolderTrackUser("User Two", "Steamboat Springs", true, stats)); - stats = new TrackStatistics(); - stats.setTotalDistance(new Distance(1000)); - stats.setMaxSpeed(new Speed(20)); - stats.setMovingTime(Duration.ofHours(3)); - testData.add(new PlaceHolderTrackUser("User Three","Steamboat Springs", true, stats)); + if (!altTestData) { + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(1000)); + stats.setMaxSpeed(new Speed(20)); + stats.setMovingTime(Duration.ofHours(3)); + testData.add(new PlaceHolderTrackUser("User Three","Steamboat Springs", true, stats)); + } stats = new TrackStatistics(); stats.setTotalDistance(new Distance(900)); @@ -174,11 +197,13 @@ private List readLatestLeaderboardData() { stats.setMovingTime(Duration.ofHours(6)); testData.add(new PlaceHolderTrackUser("User Four","Steamboat Springs", true, stats)); - stats = new TrackStatistics(); - stats.setTotalDistance(new Distance(2500)); - stats.setMaxSpeed(new Speed(55)); - stats.setMovingTime(Duration.ofHours(6)); - testData.add(new PlaceHolderTrackUser("User Four","North California CA", true, stats)); + if (!altTestData) { + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(2500)); + stats.setMaxSpeed(new Speed(55)); + stats.setMovingTime(Duration.ofHours(6)); + testData.add(new PlaceHolderTrackUser("User Four","North California CA", true, stats)); + } stats = new TrackStatistics(); stats.setTotalDistance(new Distance(10000)); @@ -186,11 +211,13 @@ private List readLatestLeaderboardData() { stats.setMovingTime(Duration.ofHours(4)); testData.add(new PlaceHolderTrackUser("User Five","North California CA", true, stats)); - stats = new TrackStatistics(); - stats.setTotalDistance(new Distance(1000)); - stats.setMaxSpeed(new Speed(50)); - stats.setMovingTime(Duration.ofHours(1)); - testData.add(new PlaceHolderTrackUser("User Five","North California CA", true, stats)); + if (!altTestData) { + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(1000)); + stats.setMaxSpeed(new Speed(50)); + stats.setMovingTime(Duration.ofHours(1)); + testData.add(new PlaceHolderTrackUser("User Five","North California CA", true, stats)); + } stats = new TrackStatistics(); stats.setTotalDistance(new Distance(1000)); @@ -216,29 +243,117 @@ private List readLatestLeaderboardData() { stats.setMovingTime(Duration.ofMinutes(30)); testData.add(new PlaceHolderTrackUser("User Nine", "North California CA", true, stats)); - stats = new TrackStatistics(); - stats.setTotalDistance(new Distance(154)); - stats.setMaxSpeed(new Speed(150)); - stats.setMovingTime(Duration.ofMinutes(59)); - testData.add(new PlaceHolderTrackUser("User Ten","Steamboat Springs", true, stats)); - - stats = new TrackStatistics(); - stats.setTotalDistance(new Distance(134)); - stats.setMaxSpeed(new Speed(130)); - stats.setMovingTime(Duration.ofMinutes(59)); - testData.add(new PlaceHolderTrackUser("User Eleven","Steamboat Springs", true, stats)); - - stats = new TrackStatistics(); - stats.setTotalDistance(new Distance(159)); - stats.setMaxSpeed(new Speed(120)); - stats.setMovingTime(Duration.ofMinutes(34)); - testData.add(new PlaceHolderTrackUser("User Twelve","Steamboat Springs", true, stats)); + if (!altTestData) { + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(154)); + stats.setMaxSpeed(new Speed(150)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Ten","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(134)); + stats.setMaxSpeed(new Speed(130)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Eleven","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(159)); + stats.setMaxSpeed(new Speed(120)); + stats.setMovingTime(Duration.ofMinutes(34)); + testData.add(new PlaceHolderTrackUser("User Twelve","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(154)); + stats.setMaxSpeed(new Speed(150)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Thirteen","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(134)); + stats.setMaxSpeed(new Speed(130)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Fourteen","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(159)); + stats.setMaxSpeed(new Speed(120)); + stats.setMovingTime(Duration.ofMinutes(34)); + testData.add(new PlaceHolderTrackUser("User Fifteen","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(154)); + stats.setMaxSpeed(new Speed(150)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Sixteen","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(134)); + stats.setMaxSpeed(new Speed(130)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Seventeen","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(159)); + stats.setMaxSpeed(new Speed(120)); + stats.setMovingTime(Duration.ofMinutes(34)); + testData.add(new PlaceHolderTrackUser("User Eighteen","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(154)); + stats.setMaxSpeed(new Speed(150)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Nineteen","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(134)); + stats.setMaxSpeed(new Speed(130)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Twenty","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(159)); + stats.setMaxSpeed(new Speed(120)); + stats.setMovingTime(Duration.ofMinutes(34)); + testData.add(new PlaceHolderTrackUser("User Twenty One","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(154)); + stats.setMaxSpeed(new Speed(150)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Twenty Two","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(134)); + stats.setMaxSpeed(new Speed(130)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Twenty Three","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(159)); + stats.setMaxSpeed(new Speed(120)); + stats.setMovingTime(Duration.ofMinutes(34)); + testData.add(new PlaceHolderTrackUser("User Twenty Four","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(154)); + stats.setMaxSpeed(new Speed(150)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Twenty Five","Steamboat Springs", true, stats)); + + stats = new TrackStatistics(); + stats.setTotalDistance(new Distance(134)); + stats.setMaxSpeed(new Speed(130)); + stats.setMovingTime(Duration.ofMinutes(59)); + testData.add(new PlaceHolderTrackUser("User Twenty Six","Steamboat Springs", true, stats)); + } stats = new TrackStatistics(); stats.setTotalDistance(new Distance(100)); stats.setMaxSpeed(new Speed(90)); stats.setMovingTime(Duration.ofHours(2)); testData.add(new PlaceHolderTrackUser("EXCLUDE ME!","North California CA", false, stats)); + + altTestData = !altTestData; return testData; } diff --git a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/AverageMovingSpeedLeaderboardFragment.java b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/AverageMovingSpeedLeaderboardFragment.java index 52250470e..71bba0269 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/AverageMovingSpeedLeaderboardFragment.java +++ b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/AverageMovingSpeedLeaderboardFragment.java @@ -20,13 +20,15 @@ protected List calculateLatestAverageRankingsData(List { diff --git a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/DistanceLeaderboardFragment.java b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/DistanceLeaderboardFragment.java index c1cae3374..595724df9 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/DistanceLeaderboardFragment.java +++ b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/DistanceLeaderboardFragment.java @@ -20,13 +20,15 @@ protected List calculateLatestAverageRankingsData(List { private List displayedRankingList; + private static int largestNumberRankToDisplay = 10; public LeaderboardAdapter(List displayedRankingList) { this.displayedRankingList = displayedRankingList; } + /** + * Sets the largestNumberRankToDisplay, but does not change the leaderboard that is shown on-screen; + * you need to call setDisplayedRankingList(List rankingListToDisplay) for that. + * @param largestNumberRank The largest-number rank that can be displayed in the on-screen leaderboard. + */ + public static void setLargestNumberRankToDisplay(int largestNumberRank) { + largestNumberRankToDisplay = largestNumberRank; + } + @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { @@ -40,17 +52,46 @@ public int getItemCount() { return displayedRankingList.size(); } - public void setDisplayedRankingList(List displayedRankingList) { - // This if statement is just here to improve efficiency if the user switched LeaderboardFragments but not LeaderboardType - if (this.displayedRankingList == displayedRankingList) + /** + * Changes the list of Rankings that is shown on-screen to the rankingListToDisplay, + * or a filtered version of it if some rankings are restricted from being displayed. + * @param rankingListToDisplay The list of Rankings to be filtered based on the largest-numbered rank we want to show, and displayed in the GUI. + */ + public void setDisplayedRankingList(List rankingListToDisplay) { + List filteredRankingListToDisplay = displayOnlySetAmountOfRanks(rankingListToDisplay); + + // This if statement is just here to improve efficiency if the user switched LeaderboardFragments but not anything else + if (this.displayedRankingList == filteredRankingListToDisplay) return; - this.displayedRankingList = displayedRankingList; + this.displayedRankingList = filteredRankingListToDisplay; - // Since the rankingList could have been remade from the ground up, we have to call notifyDataSetChanged(); + // Since the displayedRankingList could have been remade from the ground up, we have to call notifyDataSetChanged(); notifyDataSetChanged(); } + private List displayOnlySetAmountOfRanks(List rankingListToDisplay) { + // Display all the ranks if all ranks are needed or + // the largest-numbered rank is less than the largest-numbered rank we wish to display. + if (largestNumberRankToDisplay <= 0 || + rankingListToDisplay.get(rankingListToDisplay.size() - 1).getRank() <= largestNumberRankToDisplay) + return rankingListToDisplay; + + // The Top X restriction is based on the Rank, not the User's Ranking. + // If three Users are tied for 25th and we want the Top 25, the three 25th place Rankings should all be shown. + List newRankingListToDisplay = new ArrayList<>(); + for (int i = 0; i < rankingListToDisplay.size(); i++) { + Ranking nextRanking = rankingListToDisplay.get(i); + if (nextRanking.getRank() > largestNumberRankToDisplay) + break; + newRankingListToDisplay.add(nextRanking); + } + return newRankingListToDisplay; + } + + /** + * The class that Rankings are bound to so that they can be shown in the GUI. + */ static class ViewHolder extends RecyclerView.ViewHolder { ImageView avatar; TextView usernameText; diff --git a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/LeaderboardFragment.java b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/LeaderboardFragment.java index d81649cab..8771e71de 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/LeaderboardFragment.java +++ b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/LeaderboardFragment.java @@ -18,6 +18,9 @@ import de.dennisguse.opentracks.data.models.Ranking; import de.dennisguse.opentracks.ui.leaderboard.LeaderboardPagerAdapter; +/** + * The base class for every Leaderboard supported by OpenTracks. + */ public abstract class LeaderboardFragment extends Fragment { private static DecimalFormat scoreDecimalFormat; @@ -26,16 +29,13 @@ public abstract class LeaderboardFragment extends Fragment { private List averageRankingList; private List bestRankingList; - private int displayAmount = 0; - public LeaderboardFragment() { leaderboardAdapter = new LeaderboardAdapter(new ArrayList<>()); - } - public enum LeaderboardType { - Average, - Best; + public enum RankingListType { + AVERAGE, + BEST; } @Nullable @@ -50,54 +50,41 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c return view; } + /** + * Reads the sent latestLeaderboardData to rank every user in the latestLeaderboardData by the average of their scores across their provided tracks + * that they are willing to share with the public. + * What exactly the "score" is depends on the child class that implements this method. + * @param latestLeaderboardData The leaderboard data that this LeaderboardFragment's Average Ranking list will be based on. + * @return A list of Average Rankings calculated from the sent latestLeaderboardData, in order from first to last. + */ protected abstract List calculateLatestAverageRankingsData(List latestLeaderboardData); - protected abstract List calculateLatestBestRankingsData(List latestLeaderboardData); - - public void setDisplayAmount(int newDisplayAmount){ - this.displayAmount = newDisplayAmount; - } - - public void displayOnlySetAmount() { - // Display all the ranks - if (this.displayAmount <= 0) - return; - - int currentDisplayAmount = this.displayAmount; - - // Average Ranking List - // In case there is less rankings then the requested amount - if (this.averageRankingList.size() < currentDisplayAmount) - currentDisplayAmount = this.averageRankingList.size(); - - List newAverageRankingList = new ArrayList<>(); - for (int i = 0; i < currentDisplayAmount; i++) { - newAverageRankingList.add(this.averageRankingList.get(i)); - } - this.averageRankingList = newAverageRankingList; - // Best Ranking List - // In case there is less rankings then the requested amount - currentDisplayAmount = this.displayAmount; - if (this.bestRankingList.size() < currentDisplayAmount) - currentDisplayAmount = this.bestRankingList.size(); + /** + * Reads the sent latestLeaderboardData to rank every user in the latestLeaderboardData by their best score across their provided tracks + * that they are willing to share with the public. + * What exactly the "score" is depends on the child class that implements this method. + * @param latestLeaderboardData The leaderboard data that this LeaderboardFragment's Best Ranking list will be based on. + * @return A list of Best Rankings calculated from the sent latestLeaderboardData, in order from first to last. + */ + protected abstract List calculateLatestBestRankingsData(List latestLeaderboardData); - List newBestRankingList = new ArrayList<>(); - for (int i = 0; i < currentDisplayAmount; i++) { - newBestRankingList.add(this.bestRankingList.get(i)); - } - this.bestRankingList = newBestRankingList; - } + /** + * Updates every Ranking list stored in this LeaderboardFragment using the sent latestLeaderboardData. + * @param latestLeaderboardData The data that every Ranking list stored in this LeaderboardFragment will be based on. + */ public void updateRankingLists(List latestLeaderboardData) { this.averageRankingList = calculateLatestAverageRankingsData(latestLeaderboardData); this.bestRankingList = calculateLatestBestRankingsData(latestLeaderboardData); - - displayOnlySetAmount(); } - public void setDisplayedRankingList(LeaderboardType leaderboardType) { - if (leaderboardType == LeaderboardType.Average) + /** + * Changes the Ranking list that this LeaderboardFragment is displaying in the GUI. + * @param rankingListType The type of Ranking list that this LeaderboardFragment ought to display. + */ + public void setDisplayedRankingList(RankingListType rankingListType) { + if (rankingListType == RankingListType.AVERAGE) leaderboardAdapter.setDisplayedRankingList(averageRankingList); - else if (leaderboardType == LeaderboardType.Best) + else if (rankingListType == RankingListType.BEST) leaderboardAdapter.setDisplayedRankingList(bestRankingList); } @@ -107,15 +94,25 @@ protected static DecimalFormat getScoreDecimalFormat() { return scoreDecimalFormat; } + /** + * A class that assists with calculating average scores by allowing the statistic that is being + * tracked as a "score" to be summed outside of the PlaceHolderTrackUser. + */ protected class SummedStatTrackUser { private LeaderboardPagerAdapter.PlaceHolderTrackUser placeHolderTrackUser; private int sumFactorCount; + private Object scoreSum; public SummedStatTrackUser(LeaderboardPagerAdapter.PlaceHolderTrackUser placeHolderTrackUser) { this.placeHolderTrackUser = placeHolderTrackUser; sumFactorCount = 1; } + public SummedStatTrackUser(LeaderboardPagerAdapter.PlaceHolderTrackUser placeHolderTrackUser, Object scoreSum) { + this(placeHolderTrackUser); + setScoreSum(scoreSum); + } + public LeaderboardPagerAdapter.PlaceHolderTrackUser getPlaceHolderTrackUser() { return placeHolderTrackUser; } @@ -127,5 +124,13 @@ public int getSumFactorCount() { public void incrementSumFactorCount() { sumFactorCount++; } + + public Object getScoreSum() { + return scoreSum; + } + + public void setScoreSum(Object scoreSum) { + this.scoreSum = scoreSum; + } } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/MovingTimeLeaderboardFragment.java b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/MovingTimeLeaderboardFragment.java index 1b7fd38e4..1dd9dab21 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/MovingTimeLeaderboardFragment.java +++ b/src/main/java/de/dennisguse/opentracks/ui/leaderboard/leaderboardFragment/MovingTimeLeaderboardFragment.java @@ -18,12 +18,11 @@ protected List calculateLatestAverageRankingsData(List new SummedStatTrackUser(trackUser)); + statsMap.computeIfAbsent(trackUser.nickname, k -> new SummedStatTrackUser(trackUser, trackUser.trackStatistics.getMovingTime().abs())); SummedStatTrackUser existingRecord = statsMap.get(trackUser.nickname); - existingRecord.getPlaceHolderTrackUser().trackStatistics.setMovingTime( - existingRecord.getPlaceHolderTrackUser().trackStatistics.getMovingTime().plus( - trackUser.trackStatistics.getMovingTime() - ) + Duration oldDuration = (Duration)existingRecord.getScoreSum(); + existingRecord.setScoreSum( + oldDuration.plus(trackUser.trackStatistics.getMovingTime()) ); existingRecord.incrementSumFactorCount(); } @@ -36,7 +35,8 @@ protected List calculateLatestAverageRankingsData(List calculateLatestAverageRankingsData(List { @Override public int compare(SummedStatTrackUser user1, SummedStatTrackUser user2) { - return user2.getPlaceHolderTrackUser().trackStatistics.getMovingTime().compareTo( - user1.getPlaceHolderTrackUser().trackStatistics.getMovingTime()); + Duration user1MovingTime = (Duration) user1.getScoreSum(); + Duration user2MovingTime = (Duration) user2.getScoreSum(); + return user2MovingTime.compareTo(user1MovingTime); } }