checkpoint
This commit is contained in:
parent
b0edefcb4b
commit
0133524fa2
7 changed files with 226 additions and 45 deletions
|
@ -30,8 +30,8 @@ import java.util.*
|
|||
data class Track (
|
||||
val database: Database,
|
||||
val device_id: String,
|
||||
val start_time: Date,
|
||||
val stop_time: Date,
|
||||
var start_time: Date,
|
||||
var end_time: Date,
|
||||
var name: String = "",
|
||||
val trkpts: ArrayDeque<Trkpt> = ArrayDeque<Trkpt>(),
|
||||
var view_latitude: Double = Keys.DEFAULT_LATITUDE,
|
||||
|
@ -135,7 +135,6 @@ data class Track (
|
|||
continue
|
||||
}
|
||||
stats.distance += previous.toLocation().distanceTo(trkpt.toLocation())
|
||||
Log.i("VOUSSOIR", previous.toLocation().distanceTo(trkpt.toLocation()).toString())
|
||||
val ascentdiff = trkpt.altitude - previous.altitude
|
||||
if (ascentdiff > 0)
|
||||
{
|
||||
|
@ -169,8 +168,9 @@ data class Track (
|
|||
{
|
||||
val cursor: Cursor = database.connection.rawQuery(
|
||||
"SELECT lat, lon, time, ele, accuracy, sat FROM trkpt WHERE device_id = ? AND time > ? AND time < ? ORDER BY time ASC",
|
||||
arrayOf(device_id, start_time.time.toString(), stop_time.time.toString())
|
||||
arrayOf(device_id, start_time.time.toString(), end_time.time.toString())
|
||||
)
|
||||
Log.i("VOUSSOIR", "Querying points between ${start_time} -- ${end_time}")
|
||||
val COLUMN_LAT = cursor.getColumnIndex("lat")
|
||||
val COLUMN_LON = cursor.getColumnIndex("lon")
|
||||
val COLUMN_ELE = cursor.getColumnIndex("ele")
|
||||
|
|
|
@ -49,9 +49,8 @@ class TrackFragment : Fragment(), YesNoDialog.YesNoDialogListener
|
|||
name=this.requireArguments().getString(Keys.ARG_TRACK_TITLE, ""),
|
||||
device_id= this.requireArguments().getString(Keys.ARG_TRACK_DEVICE_ID, ""),
|
||||
start_time= iso8601_format.parse(this.requireArguments().getString(Keys.ARG_TRACK_START_TIME)!!),
|
||||
stop_time=iso8601_format.parse(this.requireArguments().getString(Keys.ARG_TRACK_STOP_TIME)!!),
|
||||
end_time=iso8601_format.parse(this.requireArguments().getString(Keys.ARG_TRACK_STOP_TIME)!!),
|
||||
)
|
||||
track.load_trkpts()
|
||||
layout = TrackFragmentLayoutHolder(activity as Context, inflater, container, track)
|
||||
|
||||
// set up share button
|
||||
|
|
|
@ -91,7 +91,7 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener,
|
|||
Keys.ARG_TRACK_TITLE to track.name,
|
||||
Keys.ARG_TRACK_DEVICE_ID to track.device_id,
|
||||
Keys.ARG_TRACK_START_TIME to iso8601_format.format(track.start_time),
|
||||
Keys.ARG_TRACK_STOP_TIME to iso8601_format.format(track.stop_time),
|
||||
Keys.ARG_TRACK_STOP_TIME to iso8601_format.format(track.end_time),
|
||||
)
|
||||
findNavController().navigate(R.id.fragment_track, bundle)
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ class TracklistAdapter(val fragment: Fragment, val database: Database) : Recycle
|
|||
Log.i("VOUSSOIR", "TracklistAdapter prep track ${trackdate}")
|
||||
if (start_time != null && stop_time != null)
|
||||
{
|
||||
val track = Track(database=database, device_id=device_id, start_time=start_time, stop_time=stop_time)
|
||||
val track = Track(database=database, device_id=device_id, start_time=start_time, end_time=stop_time)
|
||||
track.name = "$trackdate $device_id"
|
||||
tracks.add(track)
|
||||
}
|
||||
|
|
|
@ -18,10 +18,15 @@ package org.y20k.trackbook.ui
|
|||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.DatePicker
|
||||
import android.widget.ImageButton
|
||||
import android.widget.TimePicker
|
||||
import android.widget.Toast
|
||||
import androidx.constraintlayout.widget.Group
|
||||
import androidx.core.widget.NestedScrollView
|
||||
|
@ -34,19 +39,17 @@ import org.osmdroid.events.ZoomEvent
|
|||
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
|
||||
import org.osmdroid.util.GeoPoint
|
||||
import org.osmdroid.views.MapView
|
||||
import org.osmdroid.views.overlay.ItemizedIconOverlay
|
||||
import org.osmdroid.views.overlay.OverlayItem
|
||||
import org.osmdroid.views.overlay.TilesOverlay
|
||||
import org.osmdroid.views.overlay.compass.CompassOverlay
|
||||
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider
|
||||
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
|
||||
import org.y20k.trackbook.Keys
|
||||
import org.y20k.trackbook.R
|
||||
import org.y20k.trackbook.Track
|
||||
import org.y20k.trackbook.TrackStatistics
|
||||
import org.y20k.trackbook.helpers.*
|
||||
import java.util.*
|
||||
|
||||
/*
|
||||
* TrackFragmentLayoutHolder class
|
||||
*/
|
||||
//data class TrackFragmentLayoutHolder(private var context: Context, private var markerListener: MapOverlayHelper.MarkerListener, private var inflater: LayoutInflater, private var statusBarHeight: Int, private var container: ViewGroup?, var track: Track): MapListener { TODO REMOVE
|
||||
data class TrackFragmentLayoutHolder(
|
||||
private var context: Context,
|
||||
private var inflater: LayoutInflater,
|
||||
|
@ -54,11 +57,16 @@ data class TrackFragmentLayoutHolder(
|
|||
var track: Track
|
||||
): MapListener
|
||||
{
|
||||
/* Main class variables */
|
||||
val rootView: View
|
||||
val save_track_button: ImageButton
|
||||
val deleteButton: ImageButton
|
||||
val trackNameView: MaterialTextView
|
||||
val track_query_start_date: DatePicker
|
||||
val track_query_start_time: TimePicker
|
||||
val track_query_end_date: DatePicker
|
||||
val track_query_end_time: TimePicker
|
||||
var track_query_start_time_previous: Int
|
||||
var track_query_end_time_previous: Int
|
||||
private val mapView: MapView
|
||||
private var controller: IMapController
|
||||
private val statisticsSheetBehavior: BottomSheetBehavior<View>
|
||||
|
@ -78,17 +86,93 @@ data class TrackFragmentLayoutHolder(
|
|||
private val negativeElevationView: MaterialTextView
|
||||
private val elevationDataViews: Group
|
||||
private val useImperialUnits: Boolean
|
||||
private val handler: Handler = Handler(Looper.getMainLooper())
|
||||
private var special_points_overlay: ItemizedIconOverlay<OverlayItem>? = null
|
||||
private var track_overlay: SimpleFastPointOverlay? = null
|
||||
val RERENDER_DELAY: Long = 1000
|
||||
|
||||
init
|
||||
{
|
||||
// find views
|
||||
rootView = inflater.inflate(R.layout.fragment_track, container, false)
|
||||
mapView = rootView.findViewById(R.id.map)
|
||||
save_track_button = rootView.findViewById(R.id.save_button)
|
||||
deleteButton = rootView.findViewById(R.id.delete_button)
|
||||
trackNameView = rootView.findViewById(R.id.statistics_track_name_headline)
|
||||
|
||||
// basic map setup
|
||||
track.load_trkpts()
|
||||
val actual_start_time: Date = if (track.trkpts.isEmpty()) track.start_time else Date(track.trkpts.first().time)
|
||||
val actual_end_time: Date = if (track.trkpts.isEmpty()) track.end_time else Date(track.trkpts.last().time)
|
||||
|
||||
track_query_start_date = rootView.findViewById(R.id.track_query_start_date)
|
||||
val start_cal = GregorianCalendar()
|
||||
start_cal.time = actual_start_time
|
||||
track_query_start_date.init(start_cal.get(Calendar.YEAR), start_cal.get(Calendar.MONTH), start_cal.get(Calendar.DAY_OF_MONTH), object: DatePicker.OnDateChangedListener {
|
||||
override fun onDateChanged(p0: DatePicker?, p1: Int, p2: Int, p3: Int)
|
||||
{
|
||||
handler.removeCallbacks(requery_and_render)
|
||||
handler.postDelayed(requery_and_render, RERENDER_DELAY)
|
||||
}
|
||||
})
|
||||
|
||||
track_query_start_time = rootView.findViewById(R.id.track_query_start_time)
|
||||
track_query_start_time.setIs24HourView(true)
|
||||
track_query_start_time.hour = actual_start_time.hours
|
||||
track_query_start_time.minute = actual_start_time.minutes
|
||||
track_query_start_time_previous = (actual_start_time.hours * 60) + actual_start_time.minutes
|
||||
track_query_start_time.setOnTimeChangedListener(object : TimePicker.OnTimeChangedListener{
|
||||
override fun onTimeChanged(p0: TimePicker?, p1: Int, p2: Int)
|
||||
{
|
||||
handler.removeCallbacks(requery_and_render)
|
||||
val newminute = (p1 * 60) + p2
|
||||
Log.i("VOUSSOIR", "End time changed $newminute")
|
||||
if (newminute < track_query_start_time_previous && (track_query_start_time_previous - newminute > 60))
|
||||
{
|
||||
increment_datepicker(track_query_start_date)
|
||||
}
|
||||
else if (newminute > track_query_start_time_previous && (newminute - track_query_start_time_previous > 60))
|
||||
{
|
||||
decrement_datepicker(track_query_start_date)
|
||||
}
|
||||
track_query_start_time_previous = newminute
|
||||
handler.postDelayed(requery_and_render, RERENDER_DELAY)
|
||||
}
|
||||
})
|
||||
|
||||
track_query_end_date = rootView.findViewById(R.id.track_query_end_date)
|
||||
val end_cal = GregorianCalendar()
|
||||
end_cal.time = actual_end_time
|
||||
track_query_end_date.init(end_cal.get(Calendar.YEAR), end_cal.get(Calendar.MONTH), end_cal.get(Calendar.DAY_OF_MONTH), object: DatePicker.OnDateChangedListener {
|
||||
override fun onDateChanged(p0: DatePicker?, p1: Int, p2: Int, p3: Int)
|
||||
{
|
||||
handler.removeCallbacks(requery_and_render)
|
||||
handler.postDelayed(requery_and_render, RERENDER_DELAY)
|
||||
}
|
||||
})
|
||||
|
||||
track_query_end_time = rootView.findViewById(R.id.track_query_end_time)
|
||||
track_query_end_time.setIs24HourView(true)
|
||||
track_query_end_time.hour = actual_end_time.hours
|
||||
track_query_end_time.minute = actual_end_time.minutes
|
||||
track_query_end_time_previous = (actual_end_time.hours * 60) + actual_end_time.minutes
|
||||
track_query_end_time.setOnTimeChangedListener(object : TimePicker.OnTimeChangedListener{
|
||||
override fun onTimeChanged(p0: TimePicker?, p1: Int, p2: Int)
|
||||
{
|
||||
handler.removeCallbacks(requery_and_render)
|
||||
val newminute = (p1 * 60) + p2
|
||||
Log.i("VOUSSOIR", "End time changed $newminute")
|
||||
if (newminute < track_query_end_time_previous && (track_query_end_time_previous - newminute > 60))
|
||||
{
|
||||
increment_datepicker(track_query_end_date)
|
||||
}
|
||||
else if (newminute > track_query_end_time_previous && (newminute - track_query_end_time_previous > 60))
|
||||
{
|
||||
decrement_datepicker(track_query_end_date)
|
||||
}
|
||||
track_query_end_time_previous = newminute
|
||||
handler.postDelayed(requery_and_render, RERENDER_DELAY)
|
||||
}
|
||||
})
|
||||
|
||||
controller = mapView.controller
|
||||
mapView.addMapListener(this)
|
||||
mapView.isTilesScaledToDpi = true
|
||||
|
@ -99,7 +183,6 @@ data class TrackFragmentLayoutHolder(
|
|||
controller.setCenter(GeoPoint(track.view_latitude, track.view_longitude))
|
||||
controller.setZoom(Keys.DEFAULT_ZOOM_LEVEL)
|
||||
|
||||
// get views for statistics sheet
|
||||
statisticsSheet = rootView.findViewById(R.id.statistics_sheet)
|
||||
statisticsView = rootView.findViewById(R.id.statistics_view)
|
||||
distanceView = rootView.findViewById(R.id.statistics_data_distance)
|
||||
|
@ -116,36 +199,59 @@ data class TrackFragmentLayoutHolder(
|
|||
negativeElevationView = rootView.findViewById(R.id.statistics_data_negative_elevation)
|
||||
elevationDataViews = rootView.findViewById(R.id.elevation_data)
|
||||
|
||||
// get measurement unit system
|
||||
useImperialUnits = PreferencesHelper.loadUseImperialUnits()
|
||||
|
||||
// set dark map tiles, if necessary
|
||||
if (AppThemeHelper.isDarkModeOn(context as Activity)) {
|
||||
mapView.overlayManager.tilesOverlay.setColorFilter(TilesOverlay.INVERT_COLORS)
|
||||
}
|
||||
|
||||
// add compass to map
|
||||
val compassOverlay = CompassOverlay(context, InternalCompassOrientationProvider(context), mapView)
|
||||
compassOverlay.enableCompass()
|
||||
compassOverlay.setCompassCenter(36f, 36f)
|
||||
// compassOverlay.setCompassCenter(36f, 36f + (statusBarHeight / UiHelper.getDensityScalingFactor(context))) TODO REMOVE
|
||||
mapView.overlays.add(compassOverlay)
|
||||
|
||||
if (track.trkpts.isNotEmpty()) {
|
||||
createSpecialMakersTrackOverlay(context, mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED, displayStartEndMarker = true)
|
||||
createTrackOverlay(context, mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED)
|
||||
}
|
||||
|
||||
// set up and show statistics sheet
|
||||
statisticsSheetBehavior = BottomSheetBehavior.from<View>(statisticsSheet)
|
||||
statisticsSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
|
||||
render_track()
|
||||
}
|
||||
|
||||
fun render_track()
|
||||
{
|
||||
if (special_points_overlay != null)
|
||||
{
|
||||
mapView.overlays.remove(special_points_overlay)
|
||||
mapView.overlays.remove(track_overlay)
|
||||
}
|
||||
if (track.trkpts.isNotEmpty())
|
||||
{
|
||||
special_points_overlay = createSpecialMakersTrackOverlay(context, mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED, displayStartEndMarker = true)
|
||||
track_overlay = createTrackOverlay(context, mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED)
|
||||
}
|
||||
setupStatisticsViews()
|
||||
}
|
||||
|
||||
/* Sets up the statistics sheet */
|
||||
fun get_datetime(datepicker: DatePicker, timepicker: TimePicker, seconds: Int): Date
|
||||
{
|
||||
val cal = GregorianCalendar.getInstance()
|
||||
cal.set(datepicker.year, datepicker.month, datepicker.dayOfMonth, timepicker.hour, timepicker.minute, seconds)
|
||||
Log.i("VOUSSOIR", cal.time.toString())
|
||||
return cal.time
|
||||
}
|
||||
|
||||
fun decrement_datepicker(picker: DatePicker)
|
||||
{
|
||||
val cal = GregorianCalendar.getInstance()
|
||||
cal.set(picker.year, picker.month, picker.dayOfMonth)
|
||||
cal.add(Calendar.DATE, -1)
|
||||
picker.updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH))
|
||||
}
|
||||
|
||||
fun increment_datepicker(picker: DatePicker)
|
||||
{
|
||||
val cal = GregorianCalendar.getInstance()
|
||||
cal.set(picker.year, picker.month, picker.dayOfMonth)
|
||||
cal.add(Calendar.DATE, 1)
|
||||
picker.updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH))
|
||||
}
|
||||
|
||||
private fun setupStatisticsViews()
|
||||
{
|
||||
// populate views
|
||||
val stats: TrackStatistics = track.statistics()
|
||||
trackNameView.text = track.name
|
||||
distanceView.text = LengthUnitHelper.convertDistanceToString(stats.distance, useImperialUnits)
|
||||
|
@ -153,7 +259,7 @@ data class TrackFragmentLayoutHolder(
|
|||
durationView.text = DateTimeHelper.convertToReadableTime(context, stats.duration)
|
||||
velocityView.text = LengthUnitHelper.convertToVelocityString(stats.velocity, useImperialUnits)
|
||||
recordingStartView.text = DateTimeHelper.convertToReadableDateAndTime(track.start_time)
|
||||
recordingStopView.text = DateTimeHelper.convertToReadableDateAndTime(track.stop_time)
|
||||
recordingStopView.text = DateTimeHelper.convertToReadableDateAndTime(track.end_time)
|
||||
maxAltitudeView.text = LengthUnitHelper.convertDistanceToString(stats.max_altitude, useImperialUnits)
|
||||
minAltitudeView.text = LengthUnitHelper.convertDistanceToString(stats.min_altitude, useImperialUnits)
|
||||
positiveElevationView.text = LengthUnitHelper.convertDistanceToString(stats.total_ascent, useImperialUnits)
|
||||
|
@ -192,5 +298,17 @@ data class TrackFragmentLayoutHolder(
|
|||
return (event != null)
|
||||
}
|
||||
|
||||
private val requery_and_render: Runnable = object : Runnable {
|
||||
override fun run()
|
||||
{
|
||||
Log.i("VOUSSOIR", "requery_and_render")
|
||||
track.start_time = get_datetime(track_query_start_date, track_query_start_time, seconds=0)
|
||||
track.end_time = get_datetime(track_query_end_date, track_query_end_time, seconds=59)
|
||||
track.load_trkpts()
|
||||
Log.i("VOUSSOIR", "Reloaded ${track.trkpts.size} trkpts.")
|
||||
render_track()
|
||||
mapView.invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,19 +7,82 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<!-- OSM MAP -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
>
|
||||
|
||||
<DatePicker
|
||||
android:id="@+id/track_query_start_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="130dp"
|
||||
android:translationX="-45dp"
|
||||
android:translationY="-30dp"
|
||||
android:calendarViewShown="false"
|
||||
android:datePickerMode="spinner"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:scaleX="0.5"
|
||||
android:scaleY="0.5"
|
||||
/>
|
||||
|
||||
<TimePicker
|
||||
android:id="@+id/track_query_start_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="130dp"
|
||||
android:translationX="-150dp"
|
||||
android:translationY="-30dp"
|
||||
android:timePickerMode="spinner"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/track_query_start_date"
|
||||
android:scaleX="0.5"
|
||||
android:scaleY="0.5"
|
||||
/>
|
||||
|
||||
<DatePicker
|
||||
android:id="@+id/track_query_end_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="130dp"
|
||||
android:translationX="-45dp"
|
||||
android:translationY="-100dp"
|
||||
android:datePickerMode="spinner"
|
||||
android:calendarViewShown="false"
|
||||
app:layout_constraintTop_toBottomOf="@+id/track_query_start_date"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:scaleX="0.5"
|
||||
android:scaleY="0.5"
|
||||
/>
|
||||
|
||||
<TimePicker
|
||||
android:id="@+id/track_query_end_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="130dp"
|
||||
android:translationX="-150dp"
|
||||
android:translationY="-100dp"
|
||||
android:timePickerMode="spinner"
|
||||
app:layout_constraintTop_toBottomOf="@+id/track_query_start_time"
|
||||
app:layout_constraintStart_toEndOf="@+id/track_query_start_date"
|
||||
android:scaleX="0.5"
|
||||
android:scaleY="0.5"
|
||||
/>
|
||||
|
||||
<org.osmdroid.views.MapView
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/track_query_end_time"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:contentDescription="@string/descr_map_last_track"
|
||||
app:layout_anchor="@+id/map"
|
||||
app:layout_anchorGravity="center">
|
||||
>
|
||||
|
||||
</org.osmdroid.views.MapView>
|
||||
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- BOTTOM SHEET -->
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/statistics_sheet"
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
app:layout_constraintVertical_bias="0" />
|
||||
|
||||
<!-- ONBOARDING -->
|
||||
|
||||
<include
|
||||
layout="@layout/track_onboarding"
|
||||
android:layout_width="0dp"
|
||||
|
|
Loading…
Reference in a new issue