Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kevin/group 8/day specific activity #162

Merged
merged 11 commits into from
Apr 8, 2024
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