package pl.llp.aircasting.storage.db;
import pl.llp.aircasting.helper.CalibrationHelper;
import pl.llp.aircasting.storage.ProgressListener;
import pl.llp.aircasting.sensor.builtin.SimpleAudioReader;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import com.google.inject.Inject;
import org.intellij.lang.annotations.Language;
import static pl.llp.aircasting.storage.db.DBConstants.*;
public class UncalibratedMeasurementCalibrator
{
@Language("SQL")
public static final String FETCH_CALIBRATION = "SELECT "
+ SESSION_ID + ", "
+ SESSION_OFFSET_60_DB + ", "
+ SESSION_CALIBRATION
+ " FROM " + SESSION_TABLE_NAME;
@Language("SQL")
public static final String UPDATE_MEASUREMENT = "UPDATE " +
MEASUREMENT_TABLE_NAME + " SET " +
MEASUREMENT_VALUE + " = ? WHERE " +
MEASUREMENT_ID + " = ?";
@Inject AirCastingDB airCastingDB;
@Inject CalibrationHelper calibrations;
public void calibrate(final ProgressListener listener)
{
int workSize = sessionsToCalibrate();
listener.onSizeCalculated(workSize);
airCastingDB.executeWritableTask(new WritableDatabaseTask<Object>()
{
@Override
public Object execute(SQLiteDatabase writableDatabase)
{
int step = 0;
Cursor calibrations = writableDatabase.rawQuery(FETCH_CALIBRATION, null);
calibrations.moveToFirst();
while(!calibrations.isAfterLast())
{
long sessionId = calibrations.getLong(0);
int offset60DB = calibrations.getInt(1);
int calibration = calibrations.getInt(2);
calibrateMeasurementsInSession(writableDatabase, sessionId, offset60DB, calibration);
markSessionAsCalibrated(writableDatabase, sessionId);
calibrations.moveToNext();
listener.onProgress(step++);
}
calibrations.close();
return null;
}
});
}
private void markSessionAsCalibrated(SQLiteDatabase db, Long sessionId)
{
@Language("SQL")
String query = "UPDATE " + SESSION_TABLE_NAME + " SET " + SESSION_CALIBRATED + " = true " +
" WHERE " + SESSION_ID + " = " + sessionId;
db.execSQL(query);
}
private void calibrateMeasurementsInSession(SQLiteDatabase db, long sessionId, int offset60DB, int calibration)
{
@Language("SQL")
String q = "" +
"SELECT " + STREAM_ID + " " +
"FROM " + STREAM_TABLE_NAME + " " +
"WHERE " + STREAM_SENSOR_NAME + " = '" + SimpleAudioReader.SENSOR_NAME + "' " +
"AND " + STREAM_SESSION_ID + " = " + sessionId;
Cursor c = db.rawQuery(q, null);
if(c.getCount() < 1)
{
c.close();
return;
}
c.moveToFirst();
long streamId = c.getLong(0);
c.close();
Cursor measurement = db.query(MEASUREMENT_TABLE_NAME,
new String[]{MEASUREMENT_ID, MEASUREMENT_VALUE},
MEASUREMENT_STREAM_ID + " = " + streamId,
null, null, null, null);
SQLiteStatement st = db.compileStatement(UPDATE_MEASUREMENT);
measurement.moveToFirst();
try
{
db.beginTransaction();
while (!measurement.isAfterLast())
{
long id = measurement.getLong(0);
double value = measurement.getDouble(1);
double calibrated = calibrations.calibrate(value, calibration, offset60DB);
st.bindDouble(1, calibrated);
st.bindLong(2, id);
st.execute();
measurement.moveToNext();
}
measurement.close();
st.close();
db.setTransactionSuccessful();
}
finally
{
db.endTransaction();
}
}
public int sessionsToCalibrate()
{
return airCastingDB.executeReadOnlyTask(new ReadOnlyDatabaseTask<Integer>()
{
@Override
public Integer execute(SQLiteDatabase readOnlyDatabase)
{
Cursor c = readOnlyDatabase.rawQuery("SELECT COUNT(*) FROM " + SESSION_TABLE_NAME + " WHERE "
+ SESSION_CALIBRATED + " = 0", null);
if(c.getCount() < 1)
{
c.close();
return 0;
}
c.moveToFirst();
int anInt = c.getInt(0);
c.close();
return anInt;
}
});
}
}