package fr.tvbarthel.apps.adaptilo.engine;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;

/**
 * shake listener used to detected shake events
 */
public abstract class ShakeListener implements SensorEventListener {

    /**
     * noise boundary for shake detection
     */
    private static final float SHAKE_BOUNDARY = 18.0f;

    /**
     * time in milli between two shake to considered that user is shaking
     */
    private static final int SHAKE_SPEED_BOUNDARY = 2000;

    /**
     * smoothing ratio for Low-Pass filter algorithm
     */
    private static final double LOW_PASS_FILTER_SMOOTHING = 3.0d;

    /**
     * last shake
     */
    private double mLastCheck = 0.0d;

    /**
     * last shake speed
     */
    private double mLastSpeed = 0.0d;

    /**
     * called when shake is detected
     */
    public abstract void onShakeDetected();

    /**
     * called when device is being shaken
     *
     * @param speed
     */
    public abstract void onShaking(double speed);


    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            final float x = event.values[0];
            final float y = event.values[1];
            final float z = event.values[2];

            final float shakeAcceleration = (float) Math.sqrt((double) (x * x + y * y + z * z));

            if (shakeAcceleration > SHAKE_BOUNDARY) {
                final double currentShake = System.currentTimeMillis();
                final double delay = currentShake - mLastCheck;
                if (delay <= SHAKE_SPEED_BOUNDARY) {
                    //user is shaking
                    final double newSpeed = 2.0f / delay * 1000;
                    mLastSpeed = mLastSpeed + (newSpeed - mLastSpeed) / LOW_PASS_FILTER_SMOOTHING;
                    onShaking(mLastSpeed);
                } else {
                    //first shake
                    onShakeDetected();
                }
                mLastCheck = currentShake;
            }


        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

}

@@ -698,24 +698,64 @@
 * last shake
+ timestamp used to evaluated shake speed
 %0A     */%0A   
@@ -775,21 +775,25 @@
 le mLast
-Check
+ShakeTime
  = 0.0d;
@@ -816,29 +816,204 @@
  last shake 
-speed
+values used to evaluated distance between two shake%0A     */%0A    private float%5B%5D mLastShakeValues = new float%5B3%5D;%0A%0A    /**%0A     * last shake speed used for low pass filter algorithm
 %0A     */%0A   
@@ -1040,32 +1040,33 @@
 tSpeed = 0.0d;%0A%0A
+%0A
     /**%0A     * c
@@ -1835,21 +1835,25 @@
  - mLast
-Check
+ShakeTime
 ;%0A      
@@ -1933,24 +1933,176 @@
  is shaking%0A
+                    final double shakeDist = Math.abs(x - mLastShakeValues%5B0%5D) + Math.abs(y - mLastShakeValues%5B1%5D) + Math.abs(z - mLastShakeValues%5B2%5D);%0A
             
@@ -2137,12 +2137,17 @@
 d = 
-2.0f
+shakeDist
  / d
@@ -2442,13 +2442,17 @@
 Last
-Check
+ShakeTime
  = c
@@ -2464,16 +2464,139 @@
 tShake;%0A
+                mLastShakeValues%5B0%5D = x;%0A                mLastShakeValues%5B1%5D = y;%0A                mLastShakeValues%5B2%5D = z;%0A
         

Use pseudo distance in velocity evaluation