Skip to content
This repository has been archived by the owner on Apr 26, 2020. It is now read-only.

Commit

Permalink
Fixed #176
Browse files Browse the repository at this point in the history
  • Loading branch information
DreierF committed Oct 12, 2016
1 parent a634e5d commit 9f58cc5
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 111 deletions.
210 changes: 126 additions & 84 deletions app/src/main/java/de/dreier/mytargets/activities/StatisticsActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@

package de.dreier.mytargets.activities;

import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.Intent;
import android.content.Loader;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.util.LongSparseArray;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

Expand All @@ -30,7 +33,6 @@
import de.dreier.mytargets.fragments.StatisticsFragment;
import de.dreier.mytargets.managers.dao.ArrowDataSource;
import de.dreier.mytargets.managers.dao.BowDataSource;
import de.dreier.mytargets.managers.dao.PasseDataSource;
import de.dreier.mytargets.managers.dao.RoundDataSource;
import de.dreier.mytargets.managers.dao.TrainingDataSource;
import de.dreier.mytargets.shared.models.Arrow;
Expand All @@ -46,14 +48,14 @@
import icepick.Icepick;
import icepick.State;

public class StatisticsActivity extends ChildActivityBase {
public class StatisticsActivity extends ChildActivityBase implements LoaderManager.LoaderCallbacks<List<Pair<Training, Round>>> {

private static final String ROUND_IDS = "round_ids";

@State
boolean showFilter = false;
private ActivityStatisticsBinding binding;
private List<Round> rounds;
private List<Pair<Training, Round>> rounds;

@NonNull
public static IntentWrapper getIntent(Fragment fragment, List<Long> roundIds) {
Expand All @@ -68,27 +70,68 @@ protected void onCreate(Bundle savedInstanceState) {
binding = DataBindingUtil.setContentView(this, R.layout.activity_statistics);
setSupportActionBar(binding.toolbar);

long[] roundIds = getIntent().getLongArrayExtra(ROUND_IDS);
rounds = new RoundDataSource().getAll(roundIds);
binding.progressBar.show();

ToolbarUtils.showHomeAsUp(this);
Icepick.restoreInstanceState(this, savedInstanceState);
binding.distanceTags.setTags(getDistanceTags(rounds));
binding.distanceTags.setOnTagClickListener(t -> applyFilter(rounds));
binding.arrowTags.setTags(getArrowTags(rounds));
binding.arrowTags.setOnTagClickListener(t -> applyFilter(rounds));
binding.bowTags.setTags(getBowTags(rounds));
binding.bowTags.setOnTagClickListener(t -> applyFilter(rounds));
//TODO save filter on rotation

updateFilter();
applyFilter(rounds);
getLoaderManager().initLoader(0, getIntent().getExtras(), this).forceLoad();
}

private List<ChipGroup.Tag> getBowTags(List<Round> rounds) {
return Stream.of(rounds).map(r -> r.trainingId)
.distinct()
.map(tid -> new TrainingDataSource().get(tid).bow)
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.filter, menu);
return true;
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
final MenuItem filter = menu.findItem(R.id.action_filter);
filter.setIcon(showFilter ?
R.drawable.ic_clear_filter_white_24dp :
R.drawable.ic_filter_white_24dp);
filter.setVisible(rounds != null);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_filter:
showFilter = !showFilter;
updateFilter();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

private void applyFilter() {
List<String> distanceTags = Stream.of(binding.distanceTags.getCheckedTags())
.map(t -> t.text).collect(Collectors.toList());
List<Long> arrowTags = Stream.of(binding.arrowTags.getCheckedTags())
.map(t -> t.id).collect(Collectors.toList());
List<Long> bowTags = Stream.of(binding.bowTags.getCheckedTags())
.map(t -> t.id).collect(Collectors.toList());
List<Pair<Target, List<Round>>> filteredRounds = Stream.of(rounds)
.filter(pair -> distanceTags.contains(pair.getSecond().info.distance.toString())
&& arrowTags.contains(pair.getFirst().arrow)
&& bowTags.contains(pair.getFirst().bow))
.map(Pair::getSecond)
.groupBy(value -> new Pair<>(value.info.target.getId(),
value.info.target.scoringStyle))
.map(value1 -> new Pair<>(value1.getValue().get(0).info.target, value1.getValue()))
.collect(Collectors.toList());
boolean animate = binding.viewPager.getAdapter() == null;
final StatisticsPagerAdapter adapter = new StatisticsPagerAdapter(
getSupportFragmentManager(), filteredRounds, animate);
binding.viewPager.setAdapter(adapter);
}

private List<ChipGroup.Tag> getBowTags() {
return Stream.of(rounds)
.map(p -> p.getFirst().bow)
.distinct()
.map(bid -> {
if (bid > 0) {
Expand All @@ -104,10 +147,9 @@ private List<ChipGroup.Tag> getBowTags(List<Round> rounds) {
.collect(Collectors.toList());
}

private List<ChipGroup.Tag> getArrowTags(List<Round> rounds) {
return Stream.of(rounds).map(r -> r.trainingId)
.distinct()
.map(tid -> new TrainingDataSource().get(tid).arrow)
private List<ChipGroup.Tag> getArrowTags() {
return Stream.of(rounds)
.map(p -> p.getFirst().arrow)
.distinct()
.map(aid -> {
if (aid > 0) {
Expand All @@ -123,90 +165,90 @@ private List<ChipGroup.Tag> getArrowTags(List<Round> rounds) {
.collect(Collectors.toList());
}

private void applyFilter(List<Round> rounds) {
List<String> distanceTags = Stream.of(binding.distanceTags.getCheckedTags())
.map(t -> t.text).collect(Collectors.toList());
List<Long> arrowTags = Stream.of(binding.arrowTags.getCheckedTags())
.map(t -> t.id).collect(Collectors.toList());
List<Long> bowTags = Stream.of(binding.bowTags.getCheckedTags())
.map(t -> t.id).collect(Collectors.toList());
List<Round> filteredRounds = new ArrayList<>();
for (Round round : rounds) {
Training training = new TrainingDataSource().get(round.trainingId);
if (distanceTags.contains(round.info.distance.toString())
&& arrowTags.contains(training.arrow)
&& bowTags.contains(training.bow)) {
filteredRounds.add(round);
}
}
binding.viewPager.setAdapter(new StatisticsPagerAdapter(getSupportFragmentManager(),
new PasseDataSource().groupByTarget(filteredRounds)));
}

private List<ChipGroup.Tag> getDistanceTags(List<Round> rounds) {
return Stream.of(rounds).map(r -> r.info.distance)
private List<ChipGroup.Tag> getDistanceTags() {
return Stream.of(rounds)
.map(p -> p.getSecond().info.distance)
.distinct()
.sorted()
.map(d -> new ChipGroup.Tag(d.getId(), d.toString(), true))
.collect(Collectors.toList());
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.filter, menu);
return true;
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.action_filter).setIcon(showFilter ?
R.drawable.ic_clear_filter_white_24dp :
R.drawable.ic_filter_white_24dp);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_filter:
showFilter = !showFilter;
updateFilter();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

protected void updateFilter() {
if (!showFilter) {
Stream.of(binding.distanceTags.getTags())
.forEach(tag -> tag.isChecked = true);
Stream.of(binding.arrowTags.getTags())
.forEach(tag -> tag.isChecked = true);
Stream.of(binding.bowTags.getTags())
.forEach(tag -> tag.isChecked = true);
binding.distanceTags.setTags(binding.distanceTags.getTags());
binding.arrowTags.setTags(binding.arrowTags.getTags());
binding.bowTags.setTags(binding.bowTags.getTags());
resetFilter();
}
binding.filterView.setVisibility(showFilter ? View.VISIBLE : View.GONE);
applyFilter(rounds);
applyFilter();
invalidateOptionsMenu();
}

private void resetFilter() {
Stream.of(binding.distanceTags.getTags())
.forEach(tag -> tag.isChecked = true);
Stream.of(binding.arrowTags.getTags())
.forEach(tag -> tag.isChecked = true);
Stream.of(binding.bowTags.getTags())
.forEach(tag -> tag.isChecked = true);
binding.distanceTags.setTags(binding.distanceTags.getTags());
binding.arrowTags.setTags(binding.arrowTags.getTags());
binding.bowTags.setTags(binding.bowTags.getTags());
}

@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Icepick.saveInstanceState(this, outState);
}

@Override
public Loader<List<Pair<Training, Round>>> onCreateLoader(int i, Bundle bundle) {
final long[] roundIds = getIntent().getLongArrayExtra(ROUND_IDS);
return new AsyncTaskLoader<List<Pair<Training, Round>>>(this) {
@Override
public List<Pair<Training, Round>> loadInBackground() {
final TrainingDataSource trainingDataSource = new TrainingDataSource();
final List<Round> rounds = new RoundDataSource().getAll(roundIds);
LongSparseArray<Training> trainingsMap = new LongSparseArray<>();
Stream.of(rounds).map(round -> round.trainingId)
.distinct()
.map(trainingDataSource::get)
.forEach(training -> trainingsMap.append(training.getId(), training));
return Stream.of(rounds)
.map(round -> new Pair<>(trainingsMap.get(round.trainingId), round))
.collect(Collectors.toList());
}
};
}

@Override
public void onLoadFinished(Loader<List<Pair<Training, Round>>> loader, List<Pair<Training, Round>> data) {
rounds = data;
binding.progressBar.hide();
binding.distanceTags.setTags(getDistanceTags());
binding.distanceTags.setOnTagClickListener(t -> applyFilter());
binding.arrowTags.setTags(getArrowTags());
binding.arrowTags.setOnTagClickListener(t -> applyFilter());
binding.bowTags.setTags(getBowTags());
binding.bowTags.setOnTagClickListener(t -> applyFilter());
//TODO save filter on rotation

updateFilter();
}

@Override
public void onLoaderReset(Loader<List<Pair<Training, Round>>> loader) {

}

private class StatisticsPagerAdapter extends FragmentStatePagerAdapter {
private final List<Pair<Target, List<Round>>> targets;
private final boolean animate;

StatisticsPagerAdapter(FragmentManager fm, List<Pair<Target, List<Round>>> pairs) {
StatisticsPagerAdapter(FragmentManager fm, List<Pair<Target, List<Round>>> pairs, boolean animate) {
super(fm);
targets = pairs;
this.animate = animate;
Collections.sort(targets, (p1, p2) -> p2.getSecond().size() - p1.getSecond().size());
}

Expand All @@ -216,7 +258,7 @@ public Fragment getItem(int position) {
final List<Long> roundIds = Stream.of(item.getSecond())
.map(Round::getId)
.collect(Collectors.toList());
return StatisticsFragment.newInstance(roundIds, item.getFirst());
return StatisticsFragment.newInstance(roundIds, item.getFirst(), animate);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class StatisticsFragment extends Fragment implements LoaderManager.Loader

private static final String ARG_TARGET = "target";
private static final String ARG_ROUND_IDS = "round_ids";
private static final String ARG_ANIMATE = "animate";
private static final String PIE_CHART_CENTER_TEXT_FORMAT = "<font color='gray'>%s</font><br>" +
"<big>%s</big><br>" +
"<small>&nbsp;</small><br>" +
Expand All @@ -83,12 +84,14 @@ public class StatisticsFragment extends Fragment implements LoaderManager.Loader
private ArrowStatisticAdapter adapter;
private FragmentStatisticsBinding binding;
private Target target;
private boolean animate;

public static StatisticsFragment newInstance(List<Long> roundIds, Target item) {
public static StatisticsFragment newInstance(List<Long> roundIds, Target item, boolean animate) {
StatisticsFragment fragment = new StatisticsFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(StatisticsFragment.ARG_TARGET, Parcels.wrap(item));
bundle.putLongArray(StatisticsFragment.ARG_ROUND_IDS, Utils.toArray(roundIds));
bundle.putBoolean(StatisticsFragment.ARG_ANIMATE, animate);
fragment.setArguments(bundle);
return fragment;
}
Expand All @@ -100,6 +103,7 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,

target = Parcels.unwrap(getArguments().getParcelable(ARG_TARGET));
roundIds = getArguments().getLongArray(ARG_ROUND_IDS);
animate = getArguments().getBoolean(ARG_ANIMATE);
rounds = Stream.of(Utils.toList(roundIds))
.map(id -> new RoundDataSource().get(id))
.collect(Collectors.toList());
Expand All @@ -111,7 +115,6 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
binding.arrows.setHasFixedSize(true);
adapter = new ArrowStatisticAdapter();
binding.arrows.setAdapter(adapter);

binding.arrows.setNestedScrollingEnabled(false);

ToolbarUtils.showHomeAsUp(this);
Expand Down Expand Up @@ -151,11 +154,13 @@ private void showLineChart() {
binding.chartView.getAxisRight().setEnabled(false);
binding.chartView.getLegend().setEnabled(false);
binding.chartView.setData(data);
binding.chartView.animateXY(2000, 2000);
binding.chartView.setDescription("");
binding.chartView.getAxisLeft().setAxisMinValue(0);
binding.chartView.getXAxis().setDrawGridLines(false);
binding.chartView.setDoubleTapToZoomEnabled(false);
if(animate) {
binding.chartView.animateXY(2000, 2000);
}
}

private void showPieChart() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,6 @@ public ArrayList<Passe> getAllByTraining(long training) {
return list;
}

public List<Pair<Target, List<Round>>> groupByTarget(List<Round> rounds) {
return Stream.of(rounds)
.groupBy(value -> new Pair<>(value.info.target.getId(), value.info.target.scoringStyle))
.map(value1 -> new Pair<>(value1.getValue().get(0).info.target, value1.getValue()))
.collect(Collectors.toList());
}

@NonNull
private Map<SelectableZone, Integer> getRoundScores(List<Round> rounds) {
final Target t = rounds.get(0).info.target;
Expand Down
Loading

0 comments on commit 9f58cc5

Please sign in to comment.