package dlr.stressrecognition.classifier;
import java.util.Random;
import dlr.stressrecognition.elicitation.MentalStress;
import dlr.stressrecognition.elicitation.PhysicalStress;
import dlr.stressrecognition.logger.Logger;
import dlr.stressrecognition.sensor.BioSensor;
import dlr.stressrecognition.sensor.MotionSensor;
import dlr.stressrecognition.utils.AppSharedPrefs;
import dlr.stressrecognition.utils.BluetoothConnection;
import dlr.stressrecognition.utils.DBAdapter;
import dlr.stressrecognition.utils.PlaySound;
import dlr.stressrecognition.HighScoreActivity;
import dlr.stressrecognition.MainActivity;
import dlr.stressrecognition.R;
import dlr.stressrecognition.system.*;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
/**
* Implementation of a combined stress test with stress logging.
*
* @author Michael Gross
*
*/
public class SRSEvaluationActivity extends StressElicitationActivity {
private Logger eventLogger;
private BluetoothConnection btConnection;
private BioSensor bioSensor;
private MotionSensor sensor;
private Classifier classifier = null;
private StressClassifier srs;
private DataReader dr;
private PhysicalStress pExercise;
private MentalStress mExercise;
private int difficulty = -1;
private int score = 0;
private CountDownTimer timer;
private Toast notification;
private boolean stopped = true;
private boolean btStarted = false;
private boolean activityStarted = false;
private DBAdapter dbHelper;
// GUI related attributes
private TextView statusText;
private TextView answerTypeText;
private TextView timerText;
private TextView question;
private TextView answer1;
private TextView answer2;
private TextView answer3;
private TextView answer4;
private ProgressBar progressBar;
private ProgressDialog progressDialog;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create GUI and Layout
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.combined_test);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.window_title);
statusText = (TextView) findViewById(R.id.textViewStatus);
question = (TextView) findViewById(R.id.question);
answer1 = (TextView) findViewById(R.id.answer1);
answer2 = (TextView) findViewById(R.id.answer2);
answer3 = (TextView) findViewById(R.id.answer3);
answer4 = (TextView) findViewById(R.id.answer4);
answerTypeText = (TextView) findViewById(R.id.AnswerType);
timerText = (TextView) findViewById(R.id.Timer);
progressBar=(ProgressBar)findViewById(R.id.progressBar);
notification = Toast.makeText(this, "", Toast.LENGTH_SHORT);
difficulty = AppSharedPrefs.getDifficulty(this);
dbHelper = new DBAdapter(this);
dbHelper.open();
btConnection = new BluetoothConnection(getApplicationContext(), mHandler);
btConnection.prepareBluetooth();
// Attach Start Button Handler
findViewById(R.id.btnStart).setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
String[] log = new String[1];
log[0] = "Calibrating";
eventLogger.write(log);
progressDialog = ProgressDialog.show(SRSEvaluationActivity.this,
"", "Initializing ARS. Please wait...", true);
initSensorSystem();
}
});
// Attach Stop Button Handler
findViewById(R.id.btnStop).setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
statusText.setText("Stopped");
stopSensorSystem();
}
});
OnClickListener answerListener = new TextView.OnClickListener() {
@Override
public void onClick(View v) {
TextView t = (TextView) v;
String result;
if(timer != null)
timer.cancel();
if(mExercise.checkAnswer(t.getText().toString())) {
eventLogger.write("Exercise -> Answer: right");
result = "Right!";
score++;
} else {
eventLogger.write("Exercise -> Answer: wrong");
result = "Wrong!";
score--;
}
notification.setText(result);
notification.show();
mExercise.ask();
}
};
findViewById(R.id.answer1).setOnClickListener(answerListener);
findViewById(R.id.answer2).setOnClickListener(answerListener);
findViewById(R.id.answer3).setOnClickListener(answerListener);
findViewById(R.id.answer4).setOnClickListener(answerListener);
}
/** Called when the activity started. */
@Override
public void onStart() {
super.onStart();
findViewById(R.id.stroop_test).setVisibility(View.INVISIBLE);
// Set Event Logger
LOGFILE = "-" + System.currentTimeMillis();
eventLogger = new Logger("Event");
String[] events = { "Event" };
eventLogger.writeHeader(events);
// Create bio sensor object
bioSensor = new BioSensor(mHandler, mHandler);
// Create Physical Stress Exercise Object
pExercise = new PhysicalStress(this, mHandler);
classifier = new Classifier(mHandler);
double[] baseline = {68.058212058212060, 13.110602910602905, 33.903742203742300, 36.445979165902780};
srs = new SRS_DLR(classifier, baseline);
dr = new DataReader(srs.getSignals(), srs);
}
/** Called when the activity destroyed. */
@Override
public void onDestroy() {
super.onDestroy();
if (!stopped)
stopSensorSystem();
}
/**
* Initializes the sensor system
*/
private void initSensorSystem() {
// Start BT Sensor
if (!btStarted) {
btConnection.connectBTSensor(bioSensor);
}
// Start Activity Recognition
if (!activityStarted)
initActivityRecognition();
// Sensor system is running
stopped = false;
}
/**
* Sets a random difficulty
*/
private void randomDifficulty() {
Random generator = new Random();
difficulty = generator.nextInt(5);
if(difficulty < 2) {
progressBar.setVisibility(View.INVISIBLE);
timerText.setVisibility(View.INVISIBLE);
} else {
progressBar.setVisibility(View.VISIBLE);
timerText.setVisibility(View.VISIBLE);
}
}
/**
* Initializes the activity recognition system
*/
private void initActivityRecognition() {
ThreadGroup tg = new ThreadGroup("activity");
tg.setMaxPriority(Thread.MAX_PRIORITY);
Thread t = new Thread(tg, new Runnable() {
@Override
public void run() {
Process.setThreadPriority(-10);
sensor = new MotionSensor(mHandler);
}
}, "MotionSensor", 2000000) {
};
t.start();
activityStarted = true;
}
/**
* Shows the highscore to the user and finishes the CslActivity
*/
private void showHighScore() {
// Show close dialog
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Gameover!\n" +
"Congratulations! You made "+score+" points.");
builder.setCancelable(false);
builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
SRSEvaluationActivity.this.finish();
Intent serverIntent = new Intent(getApplicationContext(), HighScoreActivity.class);
startActivity(serverIntent);
}
});
AlertDialog alert = builder.create();
alert.show();
}
/**
* Stops the sensor system
*/
private void stopSensorSystem() {
String[] log = { "Stopped" };
eventLogger.write(log);
// Close connections
if (btStarted)
btConnection.disconnectBTSensor();
if (activityStarted)
sensor.stop();
// Reset variables
stopped = true;
activityStarted = false;
btStarted = false;
}
/**
* Handler for managing the communication with the different classes used for the combined stress test.
* E.g. MotionSensor, BioSensor ...
*/
public final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String[] log = new String[1];
switch (msg.what) {
case MESSAGE_CALIB:
break;
case MESSAGE_CALIB_FIN:
log[0] = "Calibrating Finished";
eventLogger.write(log);
sensor.calibrate();
new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
statusText.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
statusText.setText("START!");
PlaySound.play(getBaseContext());
pExercise.startExercise();
sensor.start();
}
}.start();
statusText.setText("");
progressDialog.dismiss();
break;
case MESSAGE_UPDATE:
Bundle activityMsg = msg.getData();
String activity = activityMsg.getString("activity");
double[] probabilities = activityMsg.getDoubleArray("dBN");
if(activity != null) {
dr.updateActivity(activity, probabilities);
}
//log[0] = "New Message";
//eventLogger.write(log);
//statusText.setText(msg.getData().getString("sdBN"));
break;
case MESSAGE_STOP:
log[0] = "Stop";
eventLogger.write(log);
break;
case EXERCISE_CHANGED:
log[0] = "Exercise changed->"+msg.getData().getString("Activity");
eventLogger.write(log);
if(!msg.getData().getString("Activity").equals("Running")) {
findViewById(R.id.stroop_test).setVisibility(View.VISIBLE);
if(mExercise != null) {
mExercise.abort();
mExercise = null;
if(timer != null)
timer.cancel();
}
// Create New Mental Stress Exercise Object
randomDifficulty();
mExercise = new MentalStress(SRSEvaluationActivity.this, mHandler, difficulty, false);
mExercise.ask();
} else {
findViewById(R.id.stroop_test).setVisibility(View.INVISIBLE);
if(mExercise != null) {
mExercise.abort();
mExercise = null;
if(timer != null)
timer.cancel();
}
}
statusText.setText(msg.getData().getString("Activity"));
break;
case EXERCISE_FINISHED:
log[0] = "Exercise changed->STOP";
eventLogger.write(log);
statusText.setText("STOP");
dbHelper.createHighscore(MainActivity.NAME, score);
stopSensorSystem();
showHighScore();
break;
case EXERCISE_STROOP_ASK:
Bundle data = msg.getData();
String questionText = data.getString("Question");
int questionColor = data.getInt("QuestionColor");
String[] answers = data.getStringArray("Answers");
int[] answerColors = data.getIntArray("AnswersColors");
int time = data.getInt("Timer");
boolean answerType = data.getBoolean("AnswerType");
if(answerType) {
answerTypeText.setText("Name the Color!");
eventLogger.write("Exercise -> Question: Name the Color");
} else {
answerTypeText.setText("Name the Word!");
eventLogger.write("Exercise -> Question: Name the Word!");
}
if(time > 0) {
progressBar.setMax(time);
timer = new CountDownTimer(time*1000, 1000) {
int tick = 0;
public void onTick(long millisUntilFinished) {
tick++;
progressBar.setProgress(tick);
timerText.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
if(!stopped) {
eventLogger.write("Exercise -> Question: Time out");
notification.setText("Time out");
notification.show();
mExercise.ask();
}
}
};
timer.start();
}
question.setText(questionText);
question.setTextColor(questionColor);
answer1.setText(answers[0]);
answer1.setTextColor(answerColors[0]);
answer2.setText(answers[1]);
answer2.setTextColor(answerColors[1]);
answer3.setText(answers[2]);
answer3.setTextColor(answerColors[2]);
answer4.setText(answers[3]);
answer4.setTextColor(answerColors[3]);
break;
case EXERCISE_STARTED:
//TODO: What happens after Stroop start;
break;
case EXERCISE_STROOP_NEXT_LVL:
//TODO: What happens after Stroop level change;
break;
case EXERCISE_STROOP_CANCELED:
//TODO: What happens after Stroop canceled;
break;
case EXERCISE_STROOP_FIN:
//TODO: What happens after Stroop test finished;
break;
case HEART_RATE:
Bundle b = msg.getData();
double hr = b.getDouble("HeartRate");
double br = b.getDouble("RespirationRate");
double temp = b.getDouble("SkinTemperature");
if(dr != null) {
dr.updateGP(hr, br, temp);
}
break;
case RR:
Bundle bRR = msg.getData();
int rr = bRR.getInt("RtoR");
if(dr != null) {
dr.updateRR(rr);
}
break;
case BT_CONNECTED:
btStarted = true;
notification.setText(msg.getData().getString("device") + "connected");
notification.show();
break;
case BT_NOTCONNECTED:
notification.setText("Unable to connect");
notification.show();
break;
case BT_NOTAVAILABLE:
Toast.makeText(getApplicationContext(), "Bluetooth is not available", Toast.LENGTH_LONG).show();
finish();
return;
}
}
};
}