package com.eveningoutpost.dexdrip.Models; import android.provider.BaseColumns; import com.activeandroid.Model; import com.activeandroid.annotation.Column; import com.activeandroid.annotation.Table; import com.activeandroid.query.Delete; import com.activeandroid.query.Select; import com.activeandroid.util.SQLiteUtils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Expose; import java.util.ArrayList; import java.util.List; /** * Created by jamorham on 01/11/2016. */ @Table(name = "HeartRate", id = BaseColumns._ID) public class HeartRate extends Model { private final static String TAG = "HeartRate"; private static boolean patched = false; @Expose @Column(name = "timestamp", unique = true, onUniqueConflicts = Column.ConflictAction.IGNORE) public long timestamp; @Expose @Column(name = "bpm") public int bpm; @Expose @Column(name = "accuracy") public int accuracy; public static HeartRate last() { try { return new Select() .from(HeartRate.class) .orderBy("timestamp desc") .executeSingle(); } catch (android.database.sqlite.SQLiteException e) { fixUpTable(); return null; } } public static void create(long timestamp, int bpm, int accuracy) { final HeartRate hr = new HeartRate(); hr.timestamp = timestamp; hr.bpm = bpm; hr.accuracy = accuracy; hr.saveit(); } public static List latestForGraph(int number, double startTime) { return latestForGraph(number, (long) startTime, Long.MAX_VALUE); } public static List latestForGraph(int number, long startTime) { return latestForGraph(number, startTime, Long.MAX_VALUE); } // TODO efficient record creation? public static List latestForGraph(int number, long startTime, long endTime) { try { return new Select() .from(HeartRate.class) .where("timestamp >= " + Math.max(startTime, 0)) .where("timestamp <= " + endTime) .orderBy("timestamp asc") // warn asc! .limit(number) .execute(); } catch (android.database.sqlite.SQLiteException e) { fixUpTable(); return new ArrayList<>(); } } public static List cleanup(int retention_days) { return new Delete() .from(HeartRate.class) .where("timestamp < ?", JoH.tsl() - (retention_days * 86400000L)) .execute(); } // create the table ourselves without worrying about model versioning and downgrading private static void fixUpTable() { if (patched) return; String[] patchup = { "CREATE TABLE HeartRate (_id INTEGER PRIMARY KEY AUTOINCREMENT);", "ALTER TABLE HeartRate ADD COLUMN timestamp INTEGER;", "ALTER TABLE HeartRate ADD COLUMN bpm INTEGER;", "ALTER TABLE HeartRate ADD COLUMN accuracy INTEGER;", "CREATE UNIQUE INDEX index_HeartRate_timestamp on HeartRate(timestamp);"}; for (String patch : patchup) { try { SQLiteUtils.execSql(patch); // UserError.Log.e(TAG, "Processed patch should not have succeeded!!: " + patch); } catch (Exception e) { // UserError.Log.d(TAG, "Patch: " + patch + " generated exception as it should: " + e.toString()); } } patched = true; } // patches and saves public Long saveit() { fixUpTable(); return save(); } // TODO cache gson statically public String toS() { final Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .create(); return gson.toJson(this); } }