/* * Copyright (C) 2013 jonas.oreland@gmail.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.runnerup.db.entities; import android.annotation.TargetApi; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.location.Location; import android.os.Build; import org.runnerup.common.util.Constants; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Content values wrapper for the {@code location} table. */ @TargetApi(Build.VERSION_CODES.FROYO) public class LocationEntity extends AbstractEntity { private Double mDistance; private Long mElapsed; public LocationEntity() { super(); } private LocationEntity(Cursor c, LocationEntity lastLocation) { super(); toContentValues(c); // Compute distance and elapsed Double distance = 0.0; Long elapsed = 0L; if (lastLocation != null) { //First point is zero int type = this.getType(); distance = lastLocation.getDistance(); elapsed = lastLocation.getElapsed(); switch (type) { case Constants.DB.LOCATION.TYPE_START: case Constants.DB.LOCATION.TYPE_END: case Constants.DB.LOCATION.TYPE_RESUME: break; case Constants.DB.LOCATION.TYPE_PAUSE: case Constants.DB.LOCATION.TYPE_GPS: float res[] = { 0 }; Location.distanceBetween(lastLocation.getLatitude(), lastLocation.getLongitude(), this.getLatitude(), this.getLongitude(), res); distance += res[0]; elapsed += this.getTime() - lastLocation.getTime(); break; } } mDistance = distance; mElapsed = elapsed; } public static class LocationList<E> implements Iterable<E> { LocationIterator iter; final long mID; final SQLiteDatabase mDB; public LocationList(SQLiteDatabase mDB, long mID) { this.mID = mID; this.mDB = mDB; } @Override @SuppressWarnings("unchecked") public Iterator<E> iterator() { iter = new LocationIterator(this.mID, this.mDB); return iter; } public int getCount() { return iter == null ? 0 : iter.getCount(); } public void close() { if (iter != null) {iter.close();} } private class LocationIterator implements Iterator<E> { private LocationIterator(long mID, SQLiteDatabase mDB) { c = mDB.query(Constants.DB.LOCATION.TABLE, from, "activity_id == " + mID, null, null, null, "_id", null); if (!c.moveToFirst()) { c.close(); } } final String[] from = new String[]{ Constants.DB.LOCATION.LATITUDE, Constants.DB.LOCATION.LONGITUDE, Constants.DB.LOCATION.ALTITUDE, Constants.DB.LOCATION.TYPE, Constants.DB.LOCATION.TIME, Constants.DB.LOCATION.LAP, Constants.DB.LOCATION.HR }; Cursor c = null; E prev = null; public int getCount() { return c.getCount(); } public void close() { if (!c.isClosed()) { c.close(); } } @Override public boolean hasNext() { return !c.isClosed() && !c.isLast(); } @Override @SuppressWarnings("unchecked") public E next() { c.moveToNext(); prev = (E)new LocationEntity(c, (LocationEntity)prev); if (c.isLast()) { c.close(); } return prev; } @Override public void remove() { next(); } } } /** * Id of the activity the location point belongs to */ public void setActivityId(Long value) { values().put(Constants.DB.LOCATION.ACTIVITY, value); } public Long getActivityId() { if (values().containsKey(Constants.DB.LOCATION.ACTIVITY)) { return values().getAsLong(Constants.DB.LOCATION.ACTIVITY); } return null; } /** * Lap number of the activity the location point belongs to */ public void setLap(Integer value) { values().put(Constants.DB.LOCATION.LAP, value); } public Integer getLap() { if (values().containsKey(Constants.DB.LOCATION.LAP)) { return values().getAsInteger(Constants.DB.LOCATION.LAP); } return null; } /** * Type of the location point */ public void setType(Integer value) { values().put(Constants.DB.LOCATION.TYPE, value); } public Integer getType() { if (values().containsKey(Constants.DB.LOCATION.TYPE)) { return values().getAsInteger(Constants.DB.LOCATION.TYPE); } return null; } /** * The moment in time when the location point was recorded */ public void setTime(Long value) { values().put(Constants.DB.LOCATION.TIME, value); } public Long getTime() { if (values().containsKey(Constants.DB.LOCATION.TIME)) { return values().getAsLong(Constants.DB.LOCATION.TIME); } return null; } /** * Longitude of the location */ public void setLongitude(Double value) { values().put(Constants.DB.LOCATION.LONGITUDE, value); } public Double getLongitude() { if (values().containsKey(Constants.DB.LOCATION.LONGITUDE)) { return values().getAsDouble(Constants.DB.LOCATION.LONGITUDE); } return null; } /** * Latitude of the location */ public void setLatitude(Double value) { values().put(Constants.DB.LOCATION.LATITUDE, value); } public Double getLatitude() { if (values().containsKey(Constants.DB.LOCATION.LATITUDE)) { return values().getAsDouble(Constants.DB.LOCATION.LATITUDE); } return null; } /** * Distance of the location */ public Double getDistance() { return mDistance; } /** * Elapsed time in ms, excluding pauses */ public Long getElapsed() { return mElapsed; } /** * Accuracy of the location */ private void setAccuracy(Float value) { values().put(Constants.DB.LOCATION.ACCURANCY, value); } public Float getAccuracy() { if (values().containsKey(Constants.DB.LOCATION.ACCURANCY)) { return values().getAsFloat(Constants.DB.LOCATION.ACCURANCY); } return null; } /** * Satellites for the location */ private void setSatelites(int value) { values().put(Constants.DB.LOCATION.SATELLITES, value); } public int getSatellites() { if (values().containsKey(Constants.DB.LOCATION.SATELLITES)) { return values().getAsInteger(Constants.DB.LOCATION.SATELLITES); } return -1; } /** * Altitude of the location */ public void setAltitude(Double value) { values().put(Constants.DB.LOCATION.ALTITUDE, value); } public Double getAltitude() { if (values().containsKey(Constants.DB.LOCATION.ALTITUDE)) { return values().getAsDouble(Constants.DB.LOCATION.ALTITUDE); } return null; } /** * Altitude of the location, raw GPS format (not baro or geoid adjusted) */ public void setGPSAltitude(Double value) { values().put(Constants.DB.LOCATION.GPS_ALTITUDE, value); } public Double getGPSAltitude() { if (values().containsKey(Constants.DB.LOCATION.GPS_ALTITUDE)) { return values().getAsDouble(Constants.DB.LOCATION.GPS_ALTITUDE); } return null; } /** * Speed of the location */ public void setSpeed(Float value) { values().put(Constants.DB.LOCATION.SPEED, value); } public Float getSpeed() { if (values().containsKey(Constants.DB.LOCATION.SPEED)) { return values().getAsFloat(Constants.DB.LOCATION.SPEED); } return null; } /** * Bearing of the location */ private void setBearing(Float value) { values().put(Constants.DB.LOCATION.BEARING, value); } public Float getBearing() { if (values().containsKey(Constants.DB.LOCATION.BEARING)) { return values().getAsFloat(Constants.DB.LOCATION.BEARING); } return null; } /** * HR at the location */ public void setHr(Integer value) { values().put(Constants.DB.LOCATION.HR, value); } public Integer getHr() { if (values().containsKey(Constants.DB.LOCATION.HR)) { return values().getAsInteger(Constants.DB.LOCATION.HR); } return null; } /** * Cadence at the location */ private void setCadence(Float value) { values().put(Constants.DB.LOCATION.CADENCE, value); } public Float getCadence() { if (values().containsKey(Constants.DB.LOCATION.CADENCE)) { return values().getAsFloat(Constants.DB.LOCATION.CADENCE); } return null; } /** * Temperature at the location */ public void setTemperature(Float value) { values().put(Constants.DB.LOCATION.TEMPERATURE, value); } public Float getTemperature() { if (values().containsKey(Constants.DB.LOCATION.TEMPERATURE)) { return values().getAsFloat(Constants.DB.LOCATION.TEMPERATURE); } return null; } /** * Pressure at the location */ public void setPressure(Float value) { values().put(Constants.DB.LOCATION.PRESSURE, value); } public Float getPressure() { if (values().containsKey(Constants.DB.LOCATION.PRESSURE)) { return values().getAsFloat(Constants.DB.LOCATION.PRESSURE); } return null; } @Override protected List<String> getValidColumns() { List<String> columns = new ArrayList<>(); columns.add(Constants.DB.PRIMARY_KEY); columns.add(Constants.DB.LOCATION.ACTIVITY); columns.add(Constants.DB.LOCATION.LAP); columns.add(Constants.DB.LOCATION.TYPE); columns.add(Constants.DB.LOCATION.TIME); columns.add(Constants.DB.LOCATION.ELAPSED); columns.add(Constants.DB.LOCATION.DISTANCE); columns.add(Constants.DB.LOCATION.LATITUDE); columns.add(Constants.DB.LOCATION.LONGITUDE); columns.add(Constants.DB.LOCATION.ALTITUDE); columns.add(Constants.DB.LOCATION.HR); columns.add(Constants.DB.LOCATION.CADENCE); columns.add(Constants.DB.LOCATION.TEMPERATURE); columns.add(Constants.DB.LOCATION.PRESSURE); columns.add(Constants.DB.LOCATION.GPS_ALTITUDE); columns.add(Constants.DB.LOCATION.ACCURANCY); columns.add(Constants.DB.LOCATION.SPEED); columns.add(Constants.DB.LOCATION.BEARING); return columns; } @Override protected String getTableName() { return Constants.DB.LOCATION.TABLE; } @Override protected String getNullColumnHack() { return null; } }