Skip to content

Commit

Permalink
Kevin/group 8/day specific activity (#162)
Browse files Browse the repository at this point in the history
**Describe the pull request**
#87 Show statistics for day specific run/Chairlift

**Link to the the issue**

[Issue-187](#87).

**License agreement**
By opening this pull request, you are providing your contribution under
the _Apache License 2.0_ (see [LICENSE.md](LICENSE.md)).

**Note: new dependencies/libraries**
Please refrain from introducing new libraries without consulting the
team.
  • Loading branch information
kevwad authored Apr 8, 2024
2 parents e956cc9 + 5f704cf commit f83e29d
Show file tree
Hide file tree
Showing 10 changed files with 560 additions and 7 deletions.
3 changes: 3 additions & 0 deletions src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ limitations under the License.
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/OpenTracksTheme">
<activity
android:name=".ui.aggregatedStatistics.daySpecificStats.DaySpecificActivity"
android:exported="false" />
<activity
android:name=".ui.aggregatedStatistics.SeasonStats.RunAndChairStatActivity"
android:exported="false" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@
import java.io.File;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import java.util.Date;
import java.text.SimpleDateFormat;
import de.dennisguse.opentracks.BuildConfig;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Altitude;
Expand Down Expand Up @@ -267,6 +270,21 @@ public Track getTrack(@NonNull Track.Id trackId) {
}
return null;
}
public Track getTrack(@NonNull Date date) {
long millisecondsSinceEpoch = date.getTime();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate modifiedLocalDate = localDate.plusDays(1);
Date modifiedDate = Date.from(modifiedLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
long millisNextDaySinceEpoch = modifiedDate.getTime();

String query = TracksColumns.STARTTIME + ">? AND " + TracksColumns.STARTTIME + "<=?";
try (Cursor cursor = getTrackCursor(query, new String[]{Long.toString(millisecondsSinceEpoch), Long.toString(millisNextDaySinceEpoch)}, TracksColumns._ID)) {
if (cursor != null && cursor.moveToNext()) {
return createTrack(cursor);
}
}
return null;
}

public Track getTrack(@NonNull UUID trackUUID) {
String trackUUIDsearch = UUIDUtils.toHex(trackUUID);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package de.dennisguse.opentracks.data.models;

import androidx.annotation.NonNull;

import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.ArrayList;
import java.util.Optional;

public class TrackSegment {

private static final String TAG = TrackSegment.class.getSimpleName();
private TrackPoint.Id id;
@NonNull
private final Instant time;

private List<TrackPoint> trackPoints;

public TrackSegment(@NonNull Instant time) {
this.time = time;
trackPoints = new ArrayList<>();
}

public void addTrackPoint(TrackPoint point) {
this.trackPoints.add(point);
}

public int getTrackPointCount() {
return trackPoints.size();
}

public Boolean hasTrackPoints() {
return !trackPoints.isEmpty();
}

public double getInitialElevation() {
Optional<TrackPoint> firstPoint = trackPoints.stream().findFirst();
if (firstPoint.isPresent()) {
TrackPoint point = firstPoint.get();
return point.getAltitude().toM();
}
return 0;
}

public long getDisplacement() {
long displacement = 0;
for (TrackPoint point: trackPoints) {
if (point.hasAltitudeGain()) {
displacement += point.getAltitudeGain();
}

if (point.hasAltitudeLoss()) {
displacement += point.getAltitudeLoss();
}
}

return displacement;
}
public Distance getDistance() {
if (trackPoints == null) {
return null;
}
TrackPoint first = trackPoints.get(0);
TrackPoint last = trackPoints.get(trackPoints.size() - 1);
return last.distanceToPrevious(first);
}

public Duration getTotalTime(){

if(trackPoints == null){
return null;
}
TrackPoint startTime = trackPoints.get(0);
TrackPoint endTime = trackPoints.get(trackPoints.size() - 1);

return Duration.between(startTime.getTime(), endTime.getTime());
}

public double getSpeed(){
// in m/s
double totalDistance = getDistance().toM();
long totalTime = getTotalTime().toSeconds();
return totalDistance/totalTime;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.ui.aggregatedStatistics.SeasonStats.SeasonStatActivity;
import de.dennisguse.opentracks.ui.aggregatedStatistics.daySpecificStats.DaySpecificActivity;
import de.dennisguse.opentracks.util.StringUtils;

public class AggregatedStatisticsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Expand Down Expand Up @@ -93,22 +94,32 @@ public void onClick(View v) {
}
});

viewBinding.runsAndLiftsButton.setOnClickListener(new View.OnClickListener(){
viewBinding.runsAndLiftsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){
Intent intent=new Intent(v.getContext(), CalendarActivity.class);
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), CalendarActivity.class);
intent.putExtra("Display Fields", "Runs and Lifts");
v.getContext().startActivity(intent);
}
});
viewBinding.elevationAndSpeedButton.setOnClickListener(new View.OnClickListener(){
viewBinding.elevationAndSpeedButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){
Intent intent=new Intent(v.getContext(), CalendarActivity.class);
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), CalendarActivity.class);
intent.putExtra("Display Fields", "Elevation and Speed");
v.getContext().startActivity(intent);
}
});

viewBinding.calendarButton.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
Context context = viewBinding.getRoot().getContext();
Intent intent = new Intent(context, DaySpecificActivity.class);
context.startActivity(intent);
}
});
}

public void setSpeed(AggregatedStatistics.AggregatedStatistic aggregatedStatistic) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package de.dennisguse.opentracks.ui.aggregatedStatistics.daySpecificStats;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import de.dennisguse.opentracks.AbstractActivity;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TrackListActivity;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.TrackPointIterator;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.models.TrackSegment;
import de.dennisguse.opentracks.databinding.DaySpecificActivityBinding;

import java.time.format.DateTimeFormatter;
import java.time.LocalDate;
import java.util.Date;
import java.time.ZoneId;
import java.util.List;
import java.util.ArrayList;

public class DaySpecificActivity extends AbstractActivity {

private DaySpecificActivityBinding viewBinding;
private static final String TAG = DaySpecificActivity.class.getSimpleName();
public static final String EXTRA_TRACK_DATE = "track_date";
private Date activityDate;
private ContentProviderUtils contentProviderUtils;
private Track.Id trackId;
private List<TrackSegment> trackSegments;
private DaySpecificAdapter dataAdapter;

private String fallbackDate = "2024-03-09";


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
trackSegments = new ArrayList<>();
contentProviderUtils = new ContentProviderUtils(this);
handleIntent(getIntent());
updateTrackSegments();
setSupportActionBar(viewBinding.bottomAppBarLayout.bottomAppBar);

dataAdapter = new DaySpecificAdapter(this, viewBinding.segmentList);
dataAdapter.swapData(trackSegments);
viewBinding.segmentList.setAdapter(dataAdapter);
viewBinding.segmentListToolbar.setTitle(fallbackDate);
}

@Override
protected void onStart() {
super.onStart();
}

@Override
protected void onResume() {
super.onResume();
updateTrackSegments();
dataAdapter.swapData(trackSegments);
}

public void updateTrackSegments() {
if (trackId == null) {
return;
}
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
TrackSegment currentSegment = null;
while (trackPointIterator.hasNext()) {
TrackPoint nextPoint = trackPointIterator.next();

switch (nextPoint.getType()) {
case SEGMENT_START_AUTOMATIC:
case SEGMENT_START_MANUAL:
if (currentSegment != null) {
trackSegments.add(currentSegment);
}
currentSegment = new TrackSegment(nextPoint.getTime());
break;

case SEGMENT_END_MANUAL:
trackSegments.add(currentSegment);
currentSegment = null;

case TRACKPOINT:
if (currentSegment != null) {
currentSegment.addTrackPoint(nextPoint);
}
break;

default:
Log.d(TAG, "No Action for TrackPoint IDLE/SENSORPOINT while recording segments");
}
}
}
}

private void showNoTracksFoundToast() {
finish();
Toast.makeText(DaySpecificActivity.this, "No Tracks found for date: " + fallbackDate + "\n Please import GPX file from Moodle", Toast.LENGTH_LONG).show();
}
private Date getFallbackDate() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate localDate = LocalDate.parse(fallbackDate, formatter);
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
}

private void handleIntent(Intent intent) {
Date dateFromCalendar = intent.getParcelableExtra(EXTRA_TRACK_DATE);
if (dateFromCalendar == null) {
Log.e(TAG, DaySpecificActivity.class.getSimpleName() + " needs EXTRA_TRACK_ID.");

// None provided, we will assume a specific date on our own
activityDate = getFallbackDate();
} else {
activityDate = dateFromCalendar;
}

Track track = contentProviderUtils.getTrack(activityDate);
if (track == null) {
showNoTracksFoundToast();
} else {
trackId = track.getId();
}
}

@Override
protected View getRootView() {
viewBinding = DaySpecificActivityBinding.inflate(getLayoutInflater());
return viewBinding.getRoot();
}
}
Loading

0 comments on commit f83e29d

Please sign in to comment.