diff --git a/2016/android/.gitignore b/2016/android/.gitignore
new file mode 100644
index 0000000..485dee6
--- /dev/null
+++ b/2016/android/.gitignore
@@ -0,0 +1 @@
+.idea
diff --git a/2016/android/Geofence/.gitignore b/2016/android/Geofence/.gitignore
new file mode 100644
index 0000000..589505b
--- /dev/null
+++ b/2016/android/Geofence/.gitignore
@@ -0,0 +1,9 @@
+.gradle
+.idea
+*.iml
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/2016/android/Geofence/app/.gitignore b/2016/android/Geofence/app/.gitignore
new file mode 100644
index 0000000..f2cf8c1
--- /dev/null
+++ b/2016/android/Geofence/app/.gitignore
@@ -0,0 +1,2 @@
+/build
+src/main/gen
diff --git a/2016/android/Geofence/app/build.gradle b/2016/android/Geofence/app/build.gradle
new file mode 100644
index 0000000..f6cf7dc
--- /dev/null
+++ b/2016/android/Geofence/app/build.gradle
@@ -0,0 +1,37 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 17
+ buildToolsVersion "22.0.1"
+
+ defaultConfig {
+ applicationId "esrlabs.com.geofence"
+ minSdkVersion 17
+ targetSdkVersion 17
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ testOptions {
+ unitTests.returnDefaultValues = true
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ testCompile('org.robolectric:robolectric:3.0-rc2') {
+ exclude group: 'commons-logging', module: 'commons-logging'
+ exclude group: 'org.apache.httpcomponents', module: 'httpclient'
+ }
+ testCompile 'org.mockito:mockito-core:1.9.5'
+ testCompile 'org.hamcrest:hamcrest-library:1.3'
+ compile project(':headunitinterface')
+}
diff --git a/2016/android/Geofence/app/proguard-rules.pro b/2016/android/Geofence/app/proguard-rules.pro
new file mode 100644
index 0000000..c7339c4
--- /dev/null
+++ b/2016/android/Geofence/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/andreibechet/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/2016/android/Geofence/app/src/main/AndroidManifest.xml b/2016/android/Geofence/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..99e3992
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/AndroidManifest.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/CircleGeofence.java b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/CircleGeofence.java
new file mode 100644
index 0000000..7df55e5
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/CircleGeofence.java
@@ -0,0 +1,19 @@
+package com.esrlabs.geofence;
+
+import android.location.Location;
+
+public class CircleGeofence implements Geofence {
+
+ final Location center;
+ final float radiusInMeters;
+
+ public CircleGeofence(Location center, float radiusInMeters) {
+ this.center = center;
+ this.radiusInMeters = radiusInMeters;
+ }
+
+ @Override
+ public boolean containsLocation(Location location) {
+ return false;
+ }
+}
diff --git a/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/Geofence.java b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/Geofence.java
new file mode 100644
index 0000000..edb778b
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/Geofence.java
@@ -0,0 +1,8 @@
+package com.esrlabs.geofence;
+
+import android.location.Location;
+
+public interface Geofence {
+
+ public boolean containsLocation(Location location);
+}
diff --git a/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/GeofenceApp.java b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/GeofenceApp.java
new file mode 100644
index 0000000..6777ad9
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/GeofenceApp.java
@@ -0,0 +1,87 @@
+package com.esrlabs.geofence;
+
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.esrlabs.headunitinterface.HeadUnit;
+
+import java.util.List;
+
+import static android.location.LocationManager.NETWORK_PROVIDER;
+import static com.esrlabs.geofence.Utils.location;
+
+/**
+ * Steps:
+ * - register to the location provider
+ * - connect to the HeadUnitService
+ * - build geofence object
+ * - implement the exercise logic (when the user is outside of the geofence show popup; hide it otherwise)
+ *
+ * See:
+ * - that tests are green
+ * - that the notification appears in the emulator
+ */
+public class GeofenceApp extends Service implements LocationListener {
+
+ public static final String TAG = "GeofenceApp";
+
+ private LocationManager locationManager;
+ private Geofence geofence;
+
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ Log.d(TAG, "onCreate");
+
+ if (locationManager == null) {
+ locationManager = (LocationManager)
+ this.getSystemService(Context.LOCATION_SERVICE);
+ }
+
+ initLocationListener();
+ initHeadUnitService();
+
+ if (geofence == null) {
+ final int someRadiusInMeters = 25;
+ final Location someCenterForTheGeofence = location(NETWORK_PROVIDER, 48.118920, 11.601057);
+ geofence = new CircleGeofence(someCenterForTheGeofence, someRadiusInMeters);
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onLocationChanged(Location location) {
+
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+
+ }
+}
\ No newline at end of file
diff --git a/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/PolygonGeofence.java b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/PolygonGeofence.java
new file mode 100644
index 0000000..4e14397
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/PolygonGeofence.java
@@ -0,0 +1,34 @@
+package com.esrlabs.geofence;
+
+import android.location.Location;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class PolygonGeofence implements Geofence {
+
+ final List polygonPoints;
+
+ public PolygonGeofence(Location... locations) {
+ polygonPoints = new ArrayList(Arrays.asList(locations));
+ }
+
+ /**
+ * It implements the Ray casting algorithm, with the convention that the line is horizontal and
+ * goes from left to right.
+ * @param location The point to be checked if is inside the defined polygon shaped geofence
+ * @return True if the location is inside the defined polygon.
+ */
+ @Override
+ public boolean containsLocation(Location location) {
+ int numberOfCorners = polygonPoints.size();
+
+ //adding the first corner at the end so that we can count the edge between last and first corners too
+ List corners = new ArrayList(polygonPoints);
+ corners.add(polygonPoints.get(0));
+
+ return false;
+ }
+
+}
diff --git a/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/Utils.java b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/Utils.java
new file mode 100644
index 0000000..76b7515
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/java/com/esrlabs/geofence/Utils.java
@@ -0,0 +1,14 @@
+package com.esrlabs.geofence;
+
+import android.location.Location;
+
+public class Utils {
+
+ public static Location location(String provider, double latitude, double longitude) {
+ Location location = new Location(provider);
+ location.setLatitude(latitude);
+ location.setLongitude(longitude);
+ location.setTime(System.currentTimeMillis());
+ return location;
+ }
+}
diff --git a/2016/android/Geofence/app/src/main/res/mipmap-hdpi/ic_launcher.png b/2016/android/Geofence/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/2016/android/Geofence/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/2016/android/Geofence/app/src/main/res/mipmap-mdpi/ic_launcher.png b/2016/android/Geofence/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/2016/android/Geofence/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/2016/android/Geofence/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/2016/android/Geofence/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/2016/android/Geofence/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/2016/android/Geofence/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/2016/android/Geofence/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/2016/android/Geofence/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/2016/android/Geofence/app/src/main/res/values-w820dp/dimens.xml b/2016/android/Geofence/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/2016/android/Geofence/app/src/main/res/values/dimens.xml b/2016/android/Geofence/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..47c8224
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/2016/android/Geofence/app/src/main/res/values/strings.xml b/2016/android/Geofence/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..cdf8554
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ Geofence
+
diff --git a/2016/android/Geofence/app/src/main/res/values/styles.xml b/2016/android/Geofence/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..b3da264
--- /dev/null
+++ b/2016/android/Geofence/app/src/main/res/values/styles.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/CircleGeofenceTest.java b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/CircleGeofenceTest.java
new file mode 100644
index 0000000..c3d9aa4
--- /dev/null
+++ b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/CircleGeofenceTest.java
@@ -0,0 +1,40 @@
+package com.esrlabs.geofence;
+
+import android.location.Location;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricGradleTestRunner;
+import org.robolectric.annotation.Config;
+
+import esrlabs.com.geofence.BuildConfig;
+
+import static android.location.LocationManager.NETWORK_PROVIDER;
+import static com.esrlabs.geofence.Utils.location;
+
+@RunWith(RobolectricGradleTestRunner.class)
+@Config(constants = BuildConfig.class, emulateSdk = 17)
+public class CircleGeofenceTest extends TestCase {
+ public static final double distanceSmallerThanRadiusInDeg = 0.0001;
+ public static final double distanceLargerThanRadiusInDeg = 0.001;
+
+ private static final float someRadiusInMeters = 100;
+ private static final Location someCenterForTheGeofence = location(NETWORK_PROVIDER, 48.118920, 11.601057);
+ public static final CircleGeofence someCircleGeofence = new CircleGeofence(someCenterForTheGeofence, someRadiusInMeters);
+
+ @Test
+ public void testContainsLocation() throws Exception {
+ assertTrue(someCircleGeofence.containsLocation(someLocationInside()));
+ assertFalse(someCircleGeofence.containsLocation(someLocationOutside()));
+ }
+
+ private Location someLocationInside() {
+ return location(NETWORK_PROVIDER, someCenterForTheGeofence.getLatitude() + distanceSmallerThanRadiusInDeg, someCenterForTheGeofence.getLongitude());
+ }
+
+ private Location someLocationOutside() {
+ return location(NETWORK_PROVIDER, someCenterForTheGeofence.getLatitude() + distanceLargerThanRadiusInDeg, someCenterForTheGeofence.getLongitude());
+ }
+}
\ No newline at end of file
diff --git a/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/GeofenceAppTest.java b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/GeofenceAppTest.java
new file mode 100644
index 0000000..1242bb5
--- /dev/null
+++ b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/GeofenceAppTest.java
@@ -0,0 +1,114 @@
+package com.esrlabs.geofence;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.location.Location;
+import android.location.LocationManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.esrlabs.headunitinterface.HeadUnit;
+
+import junit.framework.TestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricGradleTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLocationManager;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import esrlabs.com.geofence.BuildConfig;
+
+import static android.location.LocationManager.NETWORK_PROVIDER;
+import static com.esrlabs.geofence.CircleGeofenceTest.someCircleGeofence;
+import static com.esrlabs.geofence.Utils.location;
+import static org.robolectric.Shadows.shadowOf;
+
+
+@RunWith(RobolectricGradleTestRunner.class)
+@Config(constants = BuildConfig.class, emulateSdk = 17)
+public class GeofenceAppTest extends TestCase {
+ private final LocationManager locationManager = (LocationManager)
+ RuntimeEnvironment.application.getSystemService(Context.LOCATION_SERVICE);
+ private final ShadowLocationManager shadowLocationManager = shadowOf(locationManager);
+ private final Location someLocation = Utils.location(NETWORK_PROVIDER, 12.0, 20.0);
+ private final AtomicBoolean notificationVisibility = new AtomicBoolean(false);
+
+
+ private GeofenceApp geofenceApp;
+
+ @Before
+ public void setUp() throws Exception {
+ initHeadUnitServiceMock();
+ setupGeofenceApp();
+ }
+
+ private void initHeadUnitServiceMock() {
+ IBinder headUnitStub = newTestHeadUnitServerBinder();
+ shadowOf(RuntimeEnvironment.application).setComponentNameAndServiceForBindService(
+ new ComponentName("com.esrlabs.headunitinterface", "HeadUnit"), headUnitStub);
+ }
+
+ private IBinder newTestHeadUnitServerBinder() {
+ return new HeadUnit.Stub() {
+ @Override
+ public void showNotification(String text) throws RemoteException {
+ notificationVisibility.set(true);
+ }
+
+ @Override
+ public void hideAllNotifications() throws RemoteException {
+ notificationVisibility.set(false);
+ }
+ };
+ }
+
+ private void setupGeofenceApp() {
+ GeofenceApp service = new GeofenceApp(locationManager, someCircleGeofence);
+ service.onCreate();
+ geofenceApp = service;
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ geofenceApp.onDestroy();
+ }
+
+ @Test
+ public void shouldReceiveTheLatestLocation() throws Exception {
+ simulateNewLocation(someLocation);
+ assertTrue(someLocation.equals(geofenceApp.latestLocation()));
+ }
+
+ @Test
+ public void shouldShowPopupWhenTheCurrentLocationIsOutsideTheGeofence() throws Exception {
+ Location locationInside = location(NETWORK_PROVIDER, someCircleGeofence.center.getLatitude() + CircleGeofenceTest.distanceSmallerThanRadiusInDeg,
+ someCircleGeofence.center.getLongitude());
+ simulateNewLocation(locationInside);
+ assertTrue(locationInside.equals(geofenceApp.latestLocation()));
+ assertFalse(notificationVisibility.get());
+
+ Location locationOutside = location(NETWORK_PROVIDER, someCircleGeofence.center.getLatitude() + CircleGeofenceTest.distanceLargerThanRadiusInDeg,
+ someCircleGeofence.center.getLongitude());
+ simulateNewLocation(locationOutside);
+ assertTrue(locationOutside.equals(geofenceApp.latestLocation()));
+ assertTrue(notificationVisibility.get());
+
+ Location nextLocationInside = location(NETWORK_PROVIDER, someCircleGeofence.center.getLatitude() + CircleGeofenceTest.distanceSmallerThanRadiusInDeg,
+ someCircleGeofence.center.getLongitude());
+ simulateNewLocation(nextLocationInside);
+ assertTrue(nextLocationInside.equals(geofenceApp.latestLocation()));
+ assertFalse(notificationVisibility.get());
+ }
+
+ private void simulateNewLocation(Location someLocation) {
+ shadowLocationManager.simulateLocation(someLocation);
+ }
+
+
+}
\ No newline at end of file
diff --git a/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/HeadUnitServiceMock.java b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/HeadUnitServiceMock.java
new file mode 100644
index 0000000..80546d9
--- /dev/null
+++ b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/HeadUnitServiceMock.java
@@ -0,0 +1,22 @@
+package com.esrlabs.geofence;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.util.Log;
+
+public class HeadUnitServiceMock extends Service {
+ public static final String TAG = "HeadUnitServiceMockTest";
+
+ final IBinder headUnitStub;
+
+ public HeadUnitServiceMock(IBinder headUnitStub) {
+ this.headUnitStub = headUnitStub;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.i(TAG, "onBind");
+ return headUnitStub;
+ }
+}
diff --git a/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/PolygonGeofenceTest.java b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/PolygonGeofenceTest.java
new file mode 100644
index 0000000..c76753e
--- /dev/null
+++ b/2016/android/Geofence/app/src/test/java/com/esrlabs/geofence/PolygonGeofenceTest.java
@@ -0,0 +1,44 @@
+package com.esrlabs.geofence;
+
+import android.location.Location;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricGradleTestRunner;
+import org.robolectric.annotation.Config;
+
+import esrlabs.com.geofence.BuildConfig;
+
+import static android.location.LocationManager.NETWORK_PROVIDER;
+import static com.esrlabs.geofence.CircleGeofenceTest.distanceLargerThanRadiusInDeg;
+import static com.esrlabs.geofence.Utils.location;
+
+@RunWith(RobolectricGradleTestRunner.class)
+@Config(constants = BuildConfig.class, emulateSdk = 17)
+public class PolygonGeofenceTest extends TestCase {
+ // Test polygon defined physically like:
+ // 48.119033, 11.601664 48.119051, 11.601766
+ // 48.117726, 11.602404 48.117758, 11.602543
+ public static final Location testPolygonTopRightCorner = location(NETWORK_PROVIDER, 48.119033, 11.601664);
+ public static final Location testPolygonTopLeftCorner = location(NETWORK_PROVIDER, 48.119051, 11.601966);
+ public static final Location testPolygonBottomRightCorner = location(NETWORK_PROVIDER, 48.116726, 11.602404);
+ public static final Location testPolygonBottomLeftCorner = location(NETWORK_PROVIDER, 48.116758, 11.602743);
+ public static final PolygonGeofence testGeofence = new PolygonGeofence(testPolygonTopRightCorner, testPolygonTopLeftCorner,
+ testPolygonBottomRightCorner, testPolygonBottomLeftCorner);
+
+ @Test
+ public void testContainsLocation() throws Exception {
+ assertTrue(testGeofence.containsLocation(someLocationInside()));
+ assertFalse(testGeofence.containsLocation(someLocationOutside()));
+ }
+
+ private Location someLocationInside() {
+ return location(NETWORK_PROVIDER, testPolygonTopRightCorner.getLatitude() - 0.001, testPolygonTopRightCorner.getLongitude() - 0.001);
+ }
+
+ private Location someLocationOutside() {
+ return location(NETWORK_PROVIDER, testPolygonTopRightCorner.getLatitude() + distanceLargerThanRadiusInDeg, testPolygonTopRightCorner.getLongitude());
+ }
+}
\ No newline at end of file
diff --git a/2016/android/Geofence/build.gradle b/2016/android/Geofence/build.gradle
new file mode 100644
index 0000000..894d3ee
--- /dev/null
+++ b/2016/android/Geofence/build.gradle
@@ -0,0 +1,22 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter {
+ jcenter()
+ //url "http://jcenter.bintray.com/"
+ }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.1.2'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
diff --git a/2016/android/Geofence/gradle.properties b/2016/android/Geofence/gradle.properties
new file mode 100644
index 0000000..1d3591c
--- /dev/null
+++ b/2016/android/Geofence/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/2016/android/Geofence/gradle/wrapper/gradle-wrapper.jar b/2016/android/Geofence/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
Binary files /dev/null and b/2016/android/Geofence/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/2016/android/Geofence/gradle/wrapper/gradle-wrapper.properties b/2016/android/Geofence/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..5723a8c
--- /dev/null
+++ b/2016/android/Geofence/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sun Jul 03 23:08:01 CEST 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
diff --git a/2016/android/Geofence/gradlew b/2016/android/Geofence/gradlew
new file mode 100644
index 0000000..91a7e26
--- /dev/null
+++ b/2016/android/Geofence/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/2016/android/Geofence/gradlew.bat b/2016/android/Geofence/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/2016/android/Geofence/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/2016/android/Geofence/headunitinterface/.gitignore b/2016/android/Geofence/headunitinterface/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/2016/android/Geofence/headunitinterface/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/2016/android/Geofence/headunitinterface/build.gradle b/2016/android/Geofence/headunitinterface/build.gradle
new file mode 100644
index 0000000..31a1fb3
--- /dev/null
+++ b/2016/android/Geofence/headunitinterface/build.gradle
@@ -0,0 +1,23 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 17
+ buildToolsVersion "22.0.1"
+
+ defaultConfig {
+ minSdkVersion 17
+ targetSdkVersion 17
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+}
diff --git a/2016/android/Geofence/headunitinterface/proguard-rules.pro b/2016/android/Geofence/headunitinterface/proguard-rules.pro
new file mode 100644
index 0000000..ca379fe
--- /dev/null
+++ b/2016/android/Geofence/headunitinterface/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /home/flo/android-sdks/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/2016/android/Geofence/headunitinterface/src/androidTest/java/com/esrlabs/headunitinterface/ApplicationTest.java b/2016/android/Geofence/headunitinterface/src/androidTest/java/com/esrlabs/headunitinterface/ApplicationTest.java
new file mode 100644
index 0000000..6082182
--- /dev/null
+++ b/2016/android/Geofence/headunitinterface/src/androidTest/java/com/esrlabs/headunitinterface/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.esrlabs.headunitinterface;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/2016/android/Geofence/headunitinterface/src/main/AndroidManifest.xml b/2016/android/Geofence/headunitinterface/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a2aa29e
--- /dev/null
+++ b/2016/android/Geofence/headunitinterface/src/main/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/2016/android/Geofence/headunitinterface/src/main/aidl/com/esrlabs/headunitinterface/HeadUnit.aidl b/2016/android/Geofence/headunitinterface/src/main/aidl/com/esrlabs/headunitinterface/HeadUnit.aidl
new file mode 100644
index 0000000..d881a7b
--- /dev/null
+++ b/2016/android/Geofence/headunitinterface/src/main/aidl/com/esrlabs/headunitinterface/HeadUnit.aidl
@@ -0,0 +1,9 @@
+// HeadUnit.aidl
+package com.esrlabs.headunitinterface;
+
+interface HeadUnit {
+
+ void showNotification(String text);
+
+ void hideAllNotifications();
+}
diff --git a/2016/android/Geofence/headunitinterface/src/main/res/values/strings.xml b/2016/android/Geofence/headunitinterface/src/main/res/values/strings.xml
new file mode 100644
index 0000000..81ed599
--- /dev/null
+++ b/2016/android/Geofence/headunitinterface/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ HeadUnitInterface
+
diff --git a/2016/android/Geofence/headunitservicemock/.gitignore b/2016/android/Geofence/headunitservicemock/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/2016/android/Geofence/headunitservicemock/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/2016/android/Geofence/headunitservicemock/build.gradle b/2016/android/Geofence/headunitservicemock/build.gradle
new file mode 100644
index 0000000..a5d04f4
--- /dev/null
+++ b/2016/android/Geofence/headunitservicemock/build.gradle
@@ -0,0 +1,27 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 22
+ buildToolsVersion "22.0.1"
+ defaultConfig {
+ applicationId 'com.esrlabs.headunitservice'
+ minSdkVersion 17
+ targetSdkVersion 22
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ productFlavors {
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:appcompat-v7:22.2.0'
+ compile project(':headunitinterface')
+}
diff --git a/2016/android/Geofence/headunitservicemock/proguard-rules.pro b/2016/android/Geofence/headunitservicemock/proguard-rules.pro
new file mode 100644
index 0000000..ca379fe
--- /dev/null
+++ b/2016/android/Geofence/headunitservicemock/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /home/flo/android-sdks/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/2016/android/Geofence/headunitservicemock/src/androidTest/java/com/esrlabs/headunitservicemock/ApplicationTest.java b/2016/android/Geofence/headunitservicemock/src/androidTest/java/com/esrlabs/headunitservicemock/ApplicationTest.java
new file mode 100644
index 0000000..61dac17
--- /dev/null
+++ b/2016/android/Geofence/headunitservicemock/src/androidTest/java/com/esrlabs/headunitservicemock/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.esrlabs.headunitservice;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/2016/android/Geofence/headunitservicemock/src/main/AndroidManifest.xml b/2016/android/Geofence/headunitservicemock/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..aec6209
--- /dev/null
+++ b/2016/android/Geofence/headunitservicemock/src/main/AndroidManifest.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/2016/android/Geofence/headunitservicemock/src/main/java/com/esrlabs/headunitservice/HeadUnitService.java b/2016/android/Geofence/headunitservicemock/src/main/java/com/esrlabs/headunitservice/HeadUnitService.java
new file mode 100644
index 0000000..ef051c7
--- /dev/null
+++ b/2016/android/Geofence/headunitservicemock/src/main/java/com/esrlabs/headunitservice/HeadUnitService.java
@@ -0,0 +1,52 @@
+package com.esrlabs.headunitservice;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.esrlabs.headunitinterface.HeadUnit;
+
+/**
+ * A test implementation of the HeadUnit interface
+ *
+ * Provides a way to run against the interface without the presence of a real headunit
+ *
+ * Will use the Android UI instead
+ */
+public class HeadUnitService extends Service {
+
+ public static final String TAG = "HeadUnitServiceMock";
+
+ public HeadUnitService() {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.i(TAG, "onBind");
+ return binder;
+ }
+
+ private final HeadUnit.Stub binder = new HeadUnit.Stub() {
+ @Override
+ public void showNotification(String text) throws RemoteException {
+ Log.i(TAG, "showNotification '" + text + "'");
+ Notification.Builder builder = new Notification.Builder(getBaseContext()).setContentText(text).setSmallIcon(R.drawable.tum_logo);
+ notificationService().notify(0,builder.build());
+ }
+
+ @Override
+ public void hideAllNotifications() throws RemoteException {
+ Log.i(TAG, "hideAllNotifications");
+ notificationService().cancelAll();
+ }
+ };
+
+ private NotificationManager notificationService() {
+ return (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ }
+}
diff --git a/2016/android/Geofence/headunitservicemock/src/main/res/drawable/tum_logo.gif b/2016/android/Geofence/headunitservicemock/src/main/res/drawable/tum_logo.gif
new file mode 100644
index 0000000..6e628f7
Binary files /dev/null and b/2016/android/Geofence/headunitservicemock/src/main/res/drawable/tum_logo.gif differ
diff --git a/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-hdpi/ic_launcher.png b/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-mdpi/ic_launcher.png b/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-xhdpi/ic_launcher.png b/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-xxhdpi/ic_launcher.png b/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/2016/android/Geofence/headunitservicemock/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/2016/android/Geofence/headunitservicemock/src/main/res/values/strings.xml b/2016/android/Geofence/headunitservicemock/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e552f4b
--- /dev/null
+++ b/2016/android/Geofence/headunitservicemock/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ HeadUnitServiceMock
+
diff --git a/2016/android/Geofence/headunitservicemock/src/main/res/values/styles.xml b/2016/android/Geofence/headunitservicemock/src/main/res/values/styles.xml
new file mode 100644
index 0000000..766ab99
--- /dev/null
+++ b/2016/android/Geofence/headunitservicemock/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/2016/android/Geofence/settings.gradle b/2016/android/Geofence/settings.gradle
new file mode 100644
index 0000000..6f50817
--- /dev/null
+++ b/2016/android/Geofence/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':headunitinterface', ':headunitservicemock'
diff --git a/2016/android/README.md b/2016/android/README.md
index 7093815..18aeafb 100644
--- a/2016/android/README.md
+++ b/2016/android/README.md
@@ -6,3 +6,71 @@ To be able to develop for android and run it in the simulator, you will need the
- latest android sdk
You can find both [here](https://developer.android.com/studio/index.html)
+
+# Display a notification on the headunit
+
+In this task you have to create an android application which will use a geofence and the current location data in order to open/close a popup on the headunit.
+
+## Receive the current location
+
+Use the [android location manager](http://developer.android.com/reference/android/location/LocationManager.html) to request location updates. If the location is retrieved correctly, then the following test will pass.
+
+```java
+GeofenceAppTest.shouldReceiveTheLatestLocation()
+```
+
+## Bind to a remote service to be able to display notifications
+
+Use the [AIDL](http://developer.android.com/guide/components/aidl.html) to allow interprocess communication between your app and another service which will allow you to display notifications. The AIDL you will use is *HeadUnit.aidl*. You are on the client side. You will need to bind to the service using an intent and a [ServiceConnection](http://developer.android.com/reference/android/content/ServiceConnection.html) object (see [here](http://developer.android.com/guide/components/aidl.html#Expose)).
+
+```java
+Intent headUnitServiceIntent = new Intent(HeadUnit.class.getName());
+headUnitServiceIntent.setPackage("com.esrlabs.headunitservice");
+bindService(headUnitServiceIntent, serviceConnection_object, BIND_AUTO_CREATE);
+```
+
+## Implement a circle geofence object to tell if the current is inside a designated area or not
+
+The first step is to implement a circle geofence. You cannot use the google API because that is part of the play API, and it is not supported by our android controller. You have included in the test suite a test class for the circle geofence to help you.
+
+The second step is to display a popup if the current location is outside of a given geofence (alternatively to close if the location is inside). If this is correctly implemented than all the tests should be green (**Note** that unless you are going for the bonus you should disable the test in the *PolygonGeofenceTest* class with *@Ignore* in front of the *@Test*).
+
+For the circle geofence you should use this location as the center and radius of :
+
+ (48.262596, 11.668720) and radius of 25 meters
+
+
+## Observations
+
+In order to ease testing dependancy injection has been used. That means to pass the objects our class will use via a constructor. In android, services are not constructed by the user, instead they are built internally. The needed things for the service to run are instantated during the *onCreate()* call. The constructor in the code is there just for testing purposes. For the functioning of the service you should do the following:
+
+```java
+if (locationManager == null) {
+ locationManager = (LocationManager)
+ this.getSystemService(Context.LOCATION_SERVICE);
+}
+```
+and
+```java
+if (geofence == null) {
+ geofence = myGeofence(...);
+}
+```
+
+
+
+## **Bonus** Implement a polygon geofence instead
+
+You can use the [Ray-casting algorithm](https://en.wikipedia.org/wiki/Point_in_polygon).
+
+#### HINT
+
+Use the slope of a straight line in order to tell if the ray starting from the given point and going in a fixed direction, intersects an edge of the polygon. Take care that *Math.atan()* return radians, and you will have to correct a negative angle:
+
+```java
+90 + (90 - Math.abs(angle))
+```
+
+For the polygon geofence you should use the following locations as the polygon's cornerns:
+
+ (48.262739, 11.668393), (48.262674, 11.668956), (48.262100, 11.668419), (48.262324, 11.670174)
diff --git a/2016/ppc/.gitignore b/2016/ppc/.gitignore
new file mode 100644
index 0000000..9870652
--- /dev/null
+++ b/2016/ppc/.gitignore
@@ -0,0 +1,3 @@
+gps/UnitTest
+.bake
+build_UnitTest
diff --git a/2016/ppc/.ruby-gemset b/2016/ppc/.ruby-gemset
new file mode 100644
index 0000000..9ff1cf4
--- /dev/null
+++ b/2016/ppc/.ruby-gemset
@@ -0,0 +1 @@
+inga
diff --git a/2016/ppc/.ruby-version b/2016/ppc/.ruby-version
new file mode 100644
index 0000000..879b416
--- /dev/null
+++ b/2016/ppc/.ruby-version
@@ -0,0 +1 @@
+2.1
diff --git a/2016/ppc/README.mkd b/2016/ppc/README.mkd
index 0f961ec..2ac9d2a 100644
--- a/2016/ppc/README.mkd
+++ b/2016/ppc/README.mkd
@@ -10,3 +10,91 @@ To be able to compile your solutions and execute the tests, you will need the fo
see https://esrlabs.github.io/bake/
+# GPS on CAN
+
+In this task you will need to receive Can-frames on the can-bus that contain the GPS location of the
+vehicle. The raw data has to be converted to arc-milliseconds
+
+ 1°2'5" == (1*3600+ 2*60 + 5)*1000
+
+**Beware that the system you are running your code on will not support floating point operations.
+Use only unsigned and signed integers!**
+Still the precision of your calculations has to be +-100 milli-arc-seconds
+
+Dynamic allocation is not supported on the system.
+
+You will have to complete the *GpsConverter.cpp* (and .h).
+
+
+## Conversion to Arc-Degree
+
+inDegree hex = 180/(2^31-1) * (hex) [°]
+
+#### HINT 1
+
+Try to use constants as much as possible, isntead of computing stuff on the go.
+
+#### HINT 2
+
+In order to aviod losing decimals first multiply with a large factor and then divide to get the result in ms.
+
+## GPS Datalayout in CAN Message
+
+ Byte7 ST_LAT_NAVI
+ Byte6 ST_LAT_NAVI
+ Byte5 ST_LAT_NAVI
+ Byte4 ST_LAT_NAVI
+ Byte3 ST_LONG_NAVI
+ Byte2 ST_LONG_NAVI
+ Byte1 ST_LONG_NAVI
+ Byte0 ST_LONG_NAVI
+
+## Byteorder
+
+Little Endian (Least Significant Byte is at lowest address)
+
+## Status Longitude Navigation
+
+ ST_LONG_NAVI
+
+### Possible Values
+
+ -180° ... +180°
+
+### Signal type
+
+32 Bit Signed Integer (Byte 0 ... Byte 3)
+
+### Invalid Data
+
+Invalid-Value: 80 00 00 00
+
+Signal not available value: 7F FF FF FF and FF FF FF FF
+
+**Do not forget to check for these values**
+
+## Status Latitude Navigation
+
+ ST_LAT_NAVI
+
+### Possible Values
+
+ -180° ... +180°
+
+### Signal type
+
+32 Bit Signed Integer (Byte 4 ... Byte 7)
+
+### Invalid Data
+
+Invalid-Value: 80 00 00 00
+
+Signal not available value: 7F FF FF FF and FF FF FF FF
+
+## Send the data over to the AC
+
+Use the *IGpsACPusher*.
+
+## Running the tests
+
+execute `rake run` from this directory
\ No newline at end of file
diff --git a/2016/ppc/common/include/commonTypes.h b/2016/ppc/common/include/commonTypes.h
new file mode 100644
index 0000000..e20e789
--- /dev/null
+++ b/2016/ppc/common/include/commonTypes.h
@@ -0,0 +1,32 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#ifndef COMMON_TYPES_H
+#define COMMON_TYPES_H
+
+/* standard types file to be used for
+ * all C++ basic software components */
+
+#ifdef UNIT_TEST
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef unsigned long long int uint64;
+
+typedef signed char sint8;
+typedef signed short sint16;
+typedef signed int sint32;
+typedef signed long long int sint64;
+
+#else
+#include "Std_Types.h"
+
+typedef volatile uint32 vuint32;
+typedef volatile uint32 vuint32_t;
+#endif
+
+#endif /* COMMON_TYPES_H */
diff --git a/2016/ppc/common/include/util/CompileTimeConstraints.h b/2016/ppc/common/include/util/CompileTimeConstraints.h
new file mode 100644
index 0000000..cd2a068
--- /dev/null
+++ b/2016/ppc/common/include/util/CompileTimeConstraints.h
@@ -0,0 +1,92 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#ifndef COMPILETIMECONSTRAINTS_H_
+#define COMPILETIMECONSTRAINTS_H_
+
+#include "commonTypes.h"
+
+#define ZGW_JOIN( X, Y ) ZGW_DO_JOIN( X, Y )
+#define ZGW_DO_JOIN( X, Y ) ZGW_DO_JOIN2(X,Y)
+#define ZGW_DO_JOIN2( X, Y ) X##Y
+
+namespace common
+{
+template struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; };
+
+# define ECU_STATIC_ASSERT( B ) \
+ typedef char ZGW_JOIN(zgw_static_assert_typedef_, __LINE__) \
+ [ ::common::STATIC_ASSERTION_FAILURE< (bool)( B ) >::value ]
+
+template
+struct CompileTimeError;
+
+template<>
+struct CompileTimeError {};
+
+/**
+ * STATIC_CHECK will fail when expr evaluates to true
+ */
+#define STATIC_CHECK(msg, expr) \
+ { common::CompileTimeError<(expr)> ERROR_##msg; (void)ERROR_##msg; }
+
+/**
+ * STATIC_ASSERT will fail when expr evaluates to false
+ * simple usage: STATIC_ASSERT(too_bad_static_assert_failed, 2 > 3)
+ */
+#define STATIC_ASSERT(msg, expr) \
+ { common::CompileTimeError ERROR_##msg; (void)ERROR_##msg; }
+
+/**
+ * another example-setup for compile-time-check: a class only has to inherit from this constraint,
+ * so the constructor of this Constraint has to be compiled and the static check is executed
+ * by the compiler.
+ * will only compile if ACTUAL_SIZE <= ALLOWED_SIZE
+ *
+ * the argument passed to the STATIC_CHECK-macro can be any allowed C++-identifier,
+ */
+template
+struct ValidSizeConstraint
+{
+ static void constraint()
+ {
+ STATIC_CHECK(fuck_allowed_size_is_too_small,
+ (ACTUAL_SIZE > ALLOWED_SIZE));
+ }
+ ValidSizeConstraint()
+ {
+ void (*p)() = constraint;
+ (*p)();//call function, only to make compiler warning about unused variable go away, will get optimized away
+ }
+};
+
+/**
+ * static checks
+ * usage:
+ * struct B {}; struct D : B { };
+ * ...Derived_from();
+ */
+template struct Derived_from
+{
+ static void constraints(T* p) { B* pb = p; pb = pb;}
+ Derived_from() { void(*p)(T*) = constraints; p = p;}
+};
+
+template struct Can_copy
+{
+ static void constraints(T1 a, T2 b) { T2 c = a; b = a; c = a; b = a; }
+ Can_copy() { void(*p)(T1,T2) = constraints;}
+};
+
+template struct Can_compare
+{
+ static void constraints(T1 a, T2 b) { a==b; a!=b; a
+inline const T& smin(const T& t1, const T& t2)
+{
+ return (t1 < t2 ? t1 : t2);
+}
+
+/**
+ * returns maximum of two values
+ * \param T type of values
+ * \param t1 first value
+ * \param t2 second value
+ * \return maximum of t1 and t2
+ */
+template
+inline const T& smax(const T& t1, const T& t2)
+{
+ return (t1 > t2 ? t1 : t2);
+}
+
+/**
+ * swaps two values
+ * \param T type of values
+ * \param t1 first value
+ * \param t2 second value
+ */
+template
+inline void sswap(T& t1, T& t2)
+{
+ T t = t1;
+ t1 = t2;
+ t2 = t;
+}
+
+/**
+ * finds a value in a given iterator range
+ * \param InputIterator type of iterators
+ * \param EqualityCompareable type of value to find
+ * \param first begin of range
+ * \param last and of range
+ * \param value value to find in range
+ * \return iterator to first element equal to value in range
+ */
+template<
+ typename InputIterator,
+ typename EqualityCompareable>
+inline InputIterator sfind(
+ InputIterator first,
+ InputIterator last,
+ const EqualityCompareable& value)
+{
+ return sfind(
+ first,
+ last,
+ value,
+ typename SIteratorTraits::iterator_category());
+}
+
+/**
+ * implementation of sfind for input iterators
+ * \see sfind()
+ */
+template<
+ typename InputIterator,
+ typename EqualityCompareable>
+inline InputIterator sfind(
+ InputIterator first,
+ InputIterator last,
+ const EqualityCompareable& value,
+ SInputIteratorTag)
+{
+ while (!(first == last) && !(*first == value))
+ {
+ ++first;
+ }
+ return first;
+}
+
+/**
+ * removes all elements equal to a value from a range and copies it to another
+ * \param InputIterator type of input range iterators
+ * \param OutputIterator type of result range iterator
+ * \param EqualityCompareable type of value to remove from input range
+ * \param first begin of input range
+ * \param last end of input range
+ * \param result begin iterator of result range
+ * \param value value to remove
+ * \return end of result range
+ */
+template<
+ typename InputIterator,
+ typename OutputIterator,
+ typename EqualityCompareable>
+inline OutputIterator sremove_copy(
+ InputIterator first,
+ InputIterator last,
+ OutputIterator result,
+ const EqualityCompareable& value)
+{
+ while (first != last)
+ {
+ if (!(*first == value))
+ {
+ *result = *first;
+ ++result;
+ }
+ ++first;
+ }
+ return result;
+}
+
+/**
+ * removes all elements of a given value from a range
+ * \param ForwardIterator type of range iterator
+ * \param EqualityCompareable type of value to remove
+ * \param first begin of range
+ * \param last end of range
+ * \param value value to remove from range
+ * \return iterator to result range
+ */
+template<
+ typename ForwardIterator,
+ typename EqualityCompareable>
+ForwardIterator sremove(
+ ForwardIterator first,
+ ForwardIterator last,
+ const EqualityCompareable& value)
+{
+ first = sfind(first, last, value);
+ ForwardIterator i = first;
+ return first == last ? first : sremove_copy(++i, last, first, value);
+}
+
+template<
+ typename InputIterator,
+ typename EqualityComparable>
+typename SIteratorTraits::difference_type scount(
+ InputIterator first, InputIterator last,
+ const EqualityComparable& value)
+{
+ typename SIteratorTraits::difference_type result = 0;
+ while (first != last)
+ {
+ if (*first == value)
+ {
+ ++result;
+ }
+ ++first;
+ }
+ return result;
+}
+
+#endif /*SALGORITHM_H_*/
diff --git a/2016/ppc/common/include/util/SBaseTypes.h b/2016/ppc/common/include/util/SBaseTypes.h
new file mode 100644
index 0000000..589a207
--- /dev/null
+++ b/2016/ppc/common/include/util/SBaseTypes.h
@@ -0,0 +1,38 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * Contains basic type traits.
+ * \file SBaseTypes.h
+ * \ingroup sstl
+ */
+#ifndef SBASETYPES_H_
+#define SBASETYPES_H_
+
+/**
+ * type traits
+ * \param T type to get traits from
+ *
+ * This class may be used to save some type work.
+ */
+template
+struct STypeTraits
+{
+ /** unsigned integral type */
+ typedef unsigned int size_type;
+ /** signed integral type */
+ typedef signed int difference_type;
+ /** type of T itsself */
+ typedef T value_type;
+ /** pointer to T */
+ typedef T* pointer;
+ /** reference to T */
+ typedef T& reference;
+ /** const reference to T */
+ typedef const T& const_reference;
+};
+
+#endif /*SBASETYPES_H_*/
diff --git a/2016/ppc/common/include/util/SIteratorBaseTypes.h b/2016/ppc/common/include/util/SIteratorBaseTypes.h
new file mode 100644
index 0000000..d6e2498
--- /dev/null
+++ b/2016/ppc/common/include/util/SIteratorBaseTypes.h
@@ -0,0 +1,141 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * Contains base types for iterators.
+ * \file SIteratorBaseTypes.h
+ * \ingroup sstl
+ */
+#ifndef SITERATORBASETYPES_H_
+#define SITERATORBASETYPES_H_
+
+/**
+ * input iterator
+ *
+ * \section Description
+ * May advance through a iterator range. Reads each
+ * value exactly one time.
+ */
+struct SInputIteratorTag {};
+
+/**
+ * output iterator
+ *
+ * \section Description
+ * May advance through a iterator range and alter values.
+ */
+struct SOutputIteratorTag {};
+
+/**
+ * forward iterator
+ *
+ * \section Description
+ * May advance through a iterator range and read each value
+ * more than on time.
+ */
+struct SForwardIteratorTag : public SInputIteratorTag {};
+
+/**
+ * bidirectional iterator
+ *
+ * \section Description
+ * May go through a iterator range in both directions and
+ * read each value more than one time
+ */
+struct SBidirectionalIteratorTag : public SForwardIteratorTag {};
+
+/**
+ * random access iterator
+ *
+ * \section Description
+ * May go through a iterator range like a pointer through an
+ * array and read each value more than one time.
+ */
+struct SRandomAccessIteratorTag : public SBidirectionalIteratorTag {};
+
+/**
+ * optional base class for iterators
+ * \param Category iterators category
+ * \param T type iterator points to
+ * \param Distance signed integral type
+ * \param Pointer pointer to T
+ * \param Reference reference to T
+ *
+ * Classes may subclass this class to save some typedef work.
+ */
+template<
+ typename Category,
+ typename T,
+ typename Distance = signed int,
+ typename Pointer = T*,
+ typename Reference = T&>
+struct SIterator
+{
+ /** the iterators category */
+ typedef Category iterator_category;
+ /** type of value iterator points to */
+ typedef T value_type;
+ /** signed integral type */
+ typedef Distance difference_type;
+ /** pointer to value type */
+ typedef Pointer pointer;
+ /** reference to value type */
+ typedef Reference reference;
+};
+
+/**
+ * traits for iterators
+ * \param Iterator iterator to generate traits for
+ */
+template
+struct SIteratorTraits
+{
+ /** the iterators category */
+ typedef typename Iterator::iterator_category iterator_category;
+ /** type of value iterator points to */
+ typedef typename Iterator::value_type value_type;
+ /** signed integral type */
+ typedef typename Iterator::difference_type difference_type;
+ /** pointer to value */
+ typedef typename Iterator::pointer pointer;
+ /** reference to value */
+ typedef typename Iterator::reference reference;
+};
+
+/**
+ * special implementation for pointers
+ * \param T type of value for whose pointer traits are generated
+ *
+ * \see SIteratorTraits
+ */
+template
+struct SIteratorTraits
+{
+ typedef SRandomAccessIteratorTag iterator_category;
+ typedef T value_type;
+ typedef signed int difference_type;
+ typedef value_type* pointer;
+ typedef value_type& reference;
+};
+
+/**
+ * special implementation for const pointers
+ * \param T type of value for whose const pointer traits are generated
+ *
+ * \see SIteratorTraits
+ *
+ */
+template
+struct SIteratorTraits
+{
+ typedef SRandomAccessIteratorTag iterator_category;
+ typedef T value_type;
+ typedef signed int difference_type;
+ typedef const value_type* pointer;
+ typedef const value_type& reference;
+};
+
+#endif /*SITERATORBASETYPES_H_*/
diff --git a/2016/ppc/common/include/util/SLinkedListSet.h b/2016/ppc/common/include/util/SLinkedListSet.h
new file mode 100644
index 0000000..1061c63
--- /dev/null
+++ b/2016/ppc/common/include/util/SLinkedListSet.h
@@ -0,0 +1,441 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#ifndef SLINKEDLIST_H_
+#define SLINKEDLIST_H_
+
+#include "util/SBaseTypes.h"
+#include "util/SIteratorBaseTypes.h"
+#include "util/CompileTimeConstraints.h"
+#include
+
+template
+class SLinkedListSetNode
+{
+public:
+
+ typedef T value_type;
+ SLinkedListSetNode() :
+ fpNext(0L),
+ fAddedToList(false)
+ {}
+
+ T* getNext() const
+ {
+ return fpNext;
+ }
+
+ void setNext(T* pNext)
+ {
+ fpNext = pNext;
+ }
+
+ void addToList()
+ {
+ assert(!fAddedToList);
+ fAddedToList = true;
+ }
+
+ void removeFromList()
+ {
+ fAddedToList = false;
+ }
+private:
+ SLinkedListSetNode(const SLinkedListSetNode&);
+ SLinkedListSetNode& operator=(const SLinkedListSetNode&);
+
+ T* fpNext;
+ bool fAddedToList;
+};
+
+template
+class SLinkedListSetIterator;
+
+template
+class SLinkedListSet
+ : common::Derived_from >
+{
+private:
+ /** type of list itsself */
+ typedef SLinkedListSet self_type;
+public:
+ /** type of values stored in vector */
+ typedef typename STypeTraits::value_type value_type;
+ /** pointer to value */
+ typedef typename STypeTraits::pointer pointer;
+ /** reference to value */
+ typedef typename STypeTraits::reference reference;
+ /** const reference to value */
+ typedef typename STypeTraits::const_reference const_reference;
+ /** unsigned integral type */
+ typedef typename STypeTraits::size_type size_type;
+ /** signed integral type */
+ typedef typename STypeTraits::difference_type difference_type;
+ /** iterator type */
+ typedef SLinkedListSetIterator iterator;
+ /** const iterator type */
+ typedef SLinkedListSetIterator const_iterator;
+
+ SLinkedListSet() :
+ fpFirst(0L),
+ fpLast(0L)
+ {
+ clear();
+ }
+
+ /**
+ * @note
+ * O(n)!
+ * @todo
+ * Maybe a field would be better
+ */
+ size_type size() const
+ {
+ size_type size = (fpFirst) ? 1 : 0;
+ for (const T* pNode = fpFirst; pNode != fpLast; pNode = pNode->getNext())
+ {
+ ++size;
+ }
+ return size;
+ }
+
+ bool empty() const
+ {
+ return (fpFirst == 0L);
+ }
+
+ void clear()
+ {
+ while (!empty())
+ {
+ pop_front();
+ }
+ fpFirst = 0L;
+ fpLast = 0L;
+ }
+
+ const_reference front() const
+ {
+ assert(fpFirst);
+ return *fpFirst;
+ }
+
+ reference front()
+ {
+ return const_cast(
+ static_cast(
+ *this).front());
+ }
+
+ const_reference back() const
+ {
+ assert(fpLast);
+ return *fpLast;
+ }
+
+ reference back()
+ {
+ return const_cast(
+ static_cast(
+ *this).back());
+ }
+
+ void push_front(T& node)
+ {
+ if (contains_node(&node))
+ {
+ return;
+ }
+ node.addToList();
+ node.setNext(fpFirst);
+ fpFirst = &node;
+ if (!fpLast)
+ {//inserted first node
+ fpLast = fpFirst;
+ fpFirst->setNext(0L);
+ }
+ }
+
+ void push_back(T& node)
+ {
+ if (empty())
+ {//inserted first node
+ fpFirst = &node;
+ }
+ else
+ {
+ if (contains_node(&node))
+ {
+ return;
+ }
+ fpLast->setNext(&node);
+ }
+ node.addToList();
+ fpLast = &node;
+ fpLast->setNext(0L);
+ }
+
+ void pop_front()
+ {
+ if (!fpFirst)
+ {
+ return;
+ }
+ fpFirst->removeFromList();
+ fpFirst = fpFirst->getNext();
+ if (!fpFirst)
+ {//removed last element
+ fpLast = 0L;
+ }
+ }
+
+ void pop_back();
+
+ iterator begin()
+ {
+ return iterator(fpFirst);
+ }
+
+ const_iterator begin() const
+ {
+ return const_iterator(fpFirst);
+ }
+
+ iterator end()
+ {
+ return iterator(0L);
+ }
+
+ const_iterator end() const
+ {
+ return const_iterator(0L);
+ }
+
+ iterator erase(iterator pos);
+
+ iterator insert(iterator pos, T& value);
+
+ void remove(const T& value);
+
+ bool contains(const T& value) const
+ {
+ return contains_node(&value);
+ }
+private:
+ SLinkedListSet(const SLinkedListSet&);
+ SLinkedListSet& operator=(const SLinkedListSet&);
+
+ T* findPredecessor(const T* pNode) const
+ {
+ T* pResult = fpFirst;
+ while ((pResult != 0L) && (pResult->getNext() != pNode))
+ {
+ pResult = pResult->getNext();
+ }
+ return pResult;
+ }
+
+ bool contains_node(const T* pNodeToFind) const;
+
+ T* fpFirst;
+ T* fpLast;
+};
+
+template
+bool SLinkedListSet::contains_node(const T* pNodeToFind) const
+{
+ T* pNode = fpFirst;
+ while (pNode != 0L)
+ {
+ if (pNodeToFind == pNode)
+ {
+ return true;
+ }
+ pNode = pNode->getNext();
+ }
+ return false;
+}
+
+template
+void SLinkedListSet::pop_back()
+{
+ if (!fpLast)
+ {
+ return;
+ }
+ fpLast->removeFromList();
+ if (fpFirst == fpLast)
+ {
+ clear();
+ }
+ else
+ {
+ fpLast = findPredecessor(fpLast);
+ assert(fpLast);
+ fpLast->setNext(0L);
+ }
+}
+
+template
+typename SLinkedListSet::iterator SLinkedListSet::erase(
+ SLinkedListSet::iterator pos)
+{
+ if (!fpFirst)
+ {
+ return end();
+ }
+ iterator next = pos;
+ ++next;
+ if (pos == begin())
+ {//remove first element
+ pop_front();
+ }
+ else
+ {
+ pos->removeFromList();
+ T* pNode = findPredecessor(pos.operator->());
+ assert(pNode);
+ if (pNode->getNext() == fpLast)
+ {//removing last element
+ fpLast = pNode;
+ }
+ pNode->setNext(pos->getNext());
+ }
+ return next;
+}
+
+template
+typename SLinkedListSet::iterator SLinkedListSet::insert(
+ SLinkedListSet::iterator pos,
+ T& value)
+{
+ if (contains_node(&value))
+ {
+ return pos;
+ }
+ if (empty() || (pos == begin()))
+ {
+ push_front(value);
+ }
+ else if (pos == end())
+ {
+ push_back(value);
+ }
+ else
+ {
+ value.addToList();
+ T* pNode = findPredecessor(pos.operator->());
+ assert(pNode);
+ value.setNext(pNode->getNext());
+ pNode->setNext(&value);
+ }
+ return iterator(&value);
+}
+
+template
+void SLinkedListSet::remove(const T& value)
+{
+ if (&value == fpFirst)
+ {
+ pop_front();
+ }
+ else if (&value == fpLast)
+ {
+ pop_back();
+ }
+ else
+ {
+ const_cast(value).removeFromList();
+ T* pNode = findPredecessor(&value);
+ if (pNode)
+ {
+ pNode->setNext(value.getNext());
+ }
+ }
+}
+
+template
+bool operator==(
+ const SLinkedListSetIterator& x,
+ const SLinkedListSetIterator& y);
+
+template
+bool operator!=(
+ const SLinkedListSetIterator& x,
+ const SLinkedListSetIterator& y);
+
+template
+class SLinkedListSetIterator
+{
+public:
+ /** the iterators category */
+ typedef SForwardIteratorTag iterator_category;
+ /** value type of iterator */
+ typedef typename STypeTraits::value_type value_type;
+ /** reference to value */
+ typedef typename STypeTraits::reference reference;
+ /** pointer to value */
+ typedef typename STypeTraits::pointer pointer;
+ /** signed integral type */
+ typedef typename STypeTraits::difference_type difference_type;
+
+ SLinkedListSetIterator(T* pValue) :
+ fpValue(pValue)
+ {}
+
+ SLinkedListSetIterator(const SLinkedListSetIterator& rhs) :
+ fpValue(rhs.fpValue)
+ {}
+
+ SLinkedListSetIterator& operator=(const SLinkedListSetIterator& rhs)
+ {
+ fpValue = rhs.fpValue;
+ return *this;
+ }
+
+ SLinkedListSetIterator& operator++()
+ {
+ fpValue = fpValue->getNext();
+ return *this;
+ }
+
+ reference operator*()
+ {
+ return *fpValue;
+ }
+
+ pointer operator->()
+ {
+ return fpValue;
+ }
+
+private:
+ friend bool operator==(
+ const SLinkedListSetIterator&,
+ const SLinkedListSetIterator&);
+ friend bool operator!=(
+ const SLinkedListSetIterator&,
+ const SLinkedListSetIterator&);
+ T* fpValue;
+};
+
+template
+inline bool operator==(
+ const SLinkedListSetIterator& x,
+ const SLinkedListSetIterator& y)
+{
+ return (x.fpValue == y.fpValue);
+}
+
+template
+inline bool operator!=(
+ const SLinkedListSetIterator& x,
+ const SLinkedListSetIterator& y)
+{
+ return !(x == y);
+}
+
+#endif /*SLINKEDLIST_H_*/
diff --git a/2016/ppc/common/include/util/Uncopyable.h b/2016/ppc/common/include/util/Uncopyable.h
new file mode 100644
index 0000000..d9d48d0
--- /dev/null
+++ b/2016/ppc/common/include/util/Uncopyable.h
@@ -0,0 +1,57 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * Contains helpers to make C++ classes uncopyable, i.e. declare copy
+ * constructor and assignment operator private.
+ * \file Uncopyable.h
+ */
+#ifndef UNCOPYABLE_H_
+#define UNCOPYABLE_H_
+
+/**
+ * The macro MAKE_UNCOPYABLE expands to a declaration of copy constructor and
+ * assignment operator.
+ * \par Usage example
+ * \code
+ * class MyClass
+ * {
+ * MAKE_UNCOPYABLE(MyClass)
+ * public:
+ * //...
+ * };
+ * \endcode
+ */
+#ifdef MAKE_UNCOPYABLE
+#error "MAKE_UNCOPYABLE was already defined!"
+#endif
+// PRQA S 1030 3
+#define MAKE_UNCOPYABLE(TypeName) \
+ TypeName(const TypeName&); \
+ TypeName& operator=(const TypeName&);
+
+namespace common
+{
+
+/**
+ * Inheriting from Uncopyable makes sure that no copies of any subclass
+ * are instantiated accidently because the C++ compiler will raise an error.
+ *
+ * \author oliver.mueller
+ */
+class Uncopyable
+{
+protected:
+ Uncopyable(){}
+
+private:
+ Uncopyable(const Uncopyable&);
+ Uncopyable& operator=(const Uncopyable&);
+};
+
+}//namespace common
+
+#endif /*UNCOPYABLE_H_*/
diff --git a/2016/ppc/gps/Project.meta b/2016/ppc/gps/Project.meta
new file mode 100644
index 0000000..e468cc6
--- /dev/null
+++ b/2016/ppc/gps/Project.meta
@@ -0,0 +1,24 @@
+Project {
+ ExecutableConfig UnitTest {
+ Files "src/**/*.cpp"
+ ExcludeFiles "src/ac/*.cpp"
+ Files "test/**/*.cpp"
+ IncludeDir "include"
+ IncludeDir "test/include"
+ IncludeDir "common/include"
+ ArtifactName "gpsTests.exe"
+ PostSteps {
+ CommandLine "$(OutputDir)/$(ArtifactName) -r xml --out $(OutputDir)/test_$(ArtifactName).xml", filter: run, default: off
+ }
+ DefaultToolchain GCC {
+ Compiler CPP {
+ Flags "-g -Wall -fpermissive -fmessage-length=0"
+ Define "UNIT_TEST"
+ }
+ Compiler C {
+ Flags "-g -Wall -fpermissive -fmessage-length=0"
+ Define "UNIT_TEST"
+ }
+ }
+ }
+}
diff --git a/2016/ppc/gps/include/ac/GpsACPusher.h b/2016/ppc/gps/include/ac/GpsACPusher.h
new file mode 100644
index 0000000..73dacd6
--- /dev/null
+++ b/2016/ppc/gps/include/ac/GpsACPusher.h
@@ -0,0 +1,36 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+#ifndef AC_PUSHER_H_
+#define AC_PUSHER_H_
+
+#include "gps/IACPusher.h"
+
+namespace android
+{
+class ICaimTransceiver;
+}
+
+namespace gps
+{
+class GpsAcPusher : public IACPusher
+{
+public:
+ virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs);
+private:
+ uint8 fPosition[15];
+ ICaimTransceiver& fCaimTransceiver;
+ static const uint8 LONGITUDE_OFFSET = 0;
+ static const uint8 LATITUDE_OFFSET = 4;
+ static const uint8 HEADING_OFFSET = 8;
+
+ static const uint8 HEIGHT_OFFSET = 9;
+ static const uint8 QUALITY_OFFSET = 11;
+ static const uint8 SPEED_OFFSET = 13;
+};
+} // namespace gps
+
+#endif /* end of include guard */
+
diff --git a/2016/ppc/gps/include/ac/IGpsACPusher.h b/2016/ppc/gps/include/ac/IGpsACPusher.h
new file mode 100644
index 0000000..c3dbf14
--- /dev/null
+++ b/2016/ppc/gps/include/ac/IGpsACPusher.h
@@ -0,0 +1,21 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+#ifndef IAC_PUSHER_H_
+#define IAC_PUSHER_H_
+
+#include "commonTypes.h"
+
+namespace gps
+{
+class IGpsACPusher
+{
+public:
+ virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs) = 0;
+
+};
+} // namespace gps
+#endif /* end of include guard */
+
diff --git a/2016/ppc/gps/include/busId/BusId.h b/2016/ppc/gps/include/busId/BusId.h
new file mode 100644
index 0000000..635fbfb
--- /dev/null
+++ b/2016/ppc/gps/include/busId/BusId.h
@@ -0,0 +1,236 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+#ifndef BUSID_H_
+#define BUSID_H_
+
+#include "commonTypes.h"
+#include "util/Uncopyable.h"
+
+//forward declarations
+class BusIdIterator;
+
+/**
+ * Abstraction for bus ids used throughout the system.
+ * @author matthias.kessler
+ *
+ * BusId contains constants for all busses used and provides an iterator
+ * to access them. Each BusId will have an index that is unique in the system.
+ */
+class BusId
+{
+public:
+ enum { MAX_INDEX = 4 };
+ /** iterator over BusIds */
+ typedef BusIdIterator iterator;
+ /** maximum number of busses, used to allocate static memory */
+ static const uint8 MAX_NUMBER_OF_BUSSES = MAX_INDEX;
+ static const uint8 NUMBER_OF_LIN_BUSSES = 1;
+
+ static const BusId BODYCAN;
+ static const BusId LIN;
+ static const BusId TAS;
+ static const BusId SELFDIAG;
+ static const BusId INVALID; //MUST be last BusId and is not part of MAX_NUMBER_OF_BUSSES
+
+ /**
+ * constructor
+ * @param name string representation of BusId
+ */
+ explicit BusId(const char* name);
+
+ /**
+ * @return the BusIds name
+ */
+ const char* getName() const
+ {
+ return fpName;
+ }
+
+ /**
+ * @return the BusIds unique index
+ */
+ uint8 toIndex() const
+ {
+ return fId;
+ }
+
+ uint8 toCANIndex() const;
+
+ uint8 toLINIndex() const;
+
+ /**
+ * @param index index of BusId to access
+ * @return BusId at given index
+ */
+ static const BusId& get(uint8 index);
+
+ /**
+ * @return iterator to first BusId
+ */
+ static iterator begin();
+
+ /**
+ * @return iterator one past last BusId
+ */
+ static iterator end();
+
+ /**
+ * @return total number of busses (excluding INVALID)
+ */
+ static uint8 numberOfBusses()
+ {
+ return sfIdCount;
+ }
+private:
+ MAKE_UNCOPYABLE(BusId)
+
+ //friends
+ friend bool operator==(const BusId& x, const BusId& y);
+ friend bool operator!=(const BusId& x, const BusId& y);
+ friend class BusIdIterator;
+ //fields
+ uint8 fId;
+ const char* fpName;
+ //static fields
+ static uint8 sfIdCount;
+ static BusId* sfBusId[MAX_NUMBER_OF_BUSSES];
+};
+
+/**
+ * Compares two given BusIds
+ * @param x first BusId to compare
+ * @param y second BusId to compare
+ * @return
+ * - true BusIds are equal
+ * - false BusIds are not equal
+ */
+inline bool operator==(const BusId& x, const BusId& y)
+{
+ return (x.fId == y.fId);
+}
+
+/**
+ * Compares two given BusIds
+ * @param x first BusId to compare
+ * @param y second BusId to compare
+ * @return
+ * - true BusIds are not equal
+ * - false BusIds are equal
+ */
+inline bool operator!=(const BusId& x, const BusId& y)
+{
+ return (x.fId != y.fId);
+}
+
+/**
+ * Iterator for BusIds.
+ * @author matthias.kessler
+ */
+class BusIdIterator
+{
+public:
+ /** pointer to a BusId */
+ typedef BusId* pointer;
+ /** reference to a BusId */
+ typedef BusId& reference;
+
+ /**
+ * constructor
+ * @param pBusId pointer to BusId this iterator points initially to
+ */
+ explicit BusIdIterator(BusId* pBusId) :
+ fpBusId(pBusId)
+ {}
+
+ /**
+ * copy constructor
+ * @param itr iterator to copy from
+ */
+ BusIdIterator(const BusIdIterator& itr) :
+ fpBusId(itr.fpBusId)
+ {}
+
+ /**
+ * assignment operator
+ * @param itr iterator to copy from
+ */
+ BusIdIterator& operator=(const BusIdIterator& itr)
+ {
+ if (&itr != this)
+ {
+ fpBusId = itr.fpBusId;
+ }
+ return *this;
+ }
+
+ /**
+ * @return pointer to BusId iterator currently points to
+ */
+ pointer operator->() const
+ {
+ return fpBusId;
+ }
+
+ /**
+ * @return reference to BusId iterator currently points to
+ */
+ reference operator*() const
+ {
+ return *fpBusId;
+ }
+
+ /**
+ * prefix increment operator
+ * @return next iterator
+ */
+ BusIdIterator& operator++()
+ {
+ if (fpBusId->toIndex() < BusId::sfIdCount-2)//-2 because of INVALID is last BusId
+ {
+ fpBusId = BusId::sfBusId[fpBusId->toIndex() + 1];
+ }
+ else
+ {
+ fpBusId = 0L;
+ }
+ return *this;
+ }
+
+private:
+ //friends
+ friend bool operator==(const BusIdIterator& x, const BusIdIterator& y);
+ friend bool operator!=(const BusIdIterator& x, const BusIdIterator& y);
+ //fields
+ BusId* fpBusId;
+};
+
+/**
+ * compares two BusIdIterators
+ * @param x first BusIdIterators to compare
+ * @param y second BusIdIterators to compare
+ * @return
+ * - true BusIdIterators are equal
+ * - false BusIdIterators are not equal
+ */
+inline bool operator==(const BusIdIterator& x, const BusIdIterator& y)
+{
+ return (x.fpBusId == y.fpBusId);
+}
+
+/**
+ * compares two BusIdIterators
+ * @param x first BusIdIterators to compare
+ * @param y second BusIdIterators to compare
+ * @return
+ * - true BusIdIterators are not equal
+ * - false BusIdIterators are equal
+ */
+inline bool operator!=(const BusIdIterator& x, const BusIdIterator& y)
+{
+ return (x.fpBusId != y.fpBusId);
+}
+
+#endif /*BUSID_H_*/
diff --git a/2016/ppc/gps/include/busId/BusIdMask.h b/2016/ppc/gps/include/busId/BusIdMask.h
new file mode 100644
index 0000000..1224d7b
--- /dev/null
+++ b/2016/ppc/gps/include/busId/BusIdMask.h
@@ -0,0 +1,18 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * @file BusIdMask.h
+ */
+#ifndef BUSIDMASK_H_
+#define BUSIDMASK_H_
+
+#include "util/Mask.h"
+#include "busId/BusId.h"
+
+typedef Mask BusIdMask;
+
+#endif /*BUSIDMASK_H_*/
diff --git a/2016/ppc/gps/include/can/ICANTransceiver.h b/2016/ppc/gps/include/can/ICANTransceiver.h
new file mode 100644
index 0000000..fac8ea0
--- /dev/null
+++ b/2016/ppc/gps/include/can/ICANTransceiver.h
@@ -0,0 +1,44 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#ifndef I_CAN_TRANSCEIVER_H_
+#define I_CAN_TRANSCEIVER_H_
+
+#include "can/canframes/CANFrame.h"
+
+namespace can
+{
+class ICANTransceiver
+{
+public:
+ enum ErrorCode
+ {
+ CAN_ERR_OK,
+ CAN_ERR_TX_FAIL
+ };
+
+ virtual ErrorCode init() = 0;
+
+ virtual void shutdown() = 0;
+
+ virtual ErrorCode open() = 0;
+
+ virtual ErrorCode close() = 0;
+
+ virtual ErrorCode mute() = 0;
+
+ virtual ErrorCode unmute() = 0;
+
+ virtual ErrorCode write(const can::CANFrame& frame) = 0;
+
+ virtual uint32 getBaudrate() const = 0;
+
+ virtual uint16 getHwQueueTimeout() const = 0;
+
+};
+} // namespace can
+#endif /* end of include guard */
+
diff --git a/2016/ppc/gps/include/can/canframes/CANFrame.h b/2016/ppc/gps/include/can/canframes/CANFrame.h
new file mode 100644
index 0000000..51880ff
--- /dev/null
+++ b/2016/ppc/gps/include/can/canframes/CANFrame.h
@@ -0,0 +1,181 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * Contains Cpp2CAN CANFrame.
+ * @file CANFrame.h
+ * @ingroup cpp2can
+ */
+#ifndef CANFRAME_H
+#define CANFRAME_H
+
+#include "commonTypes.h"
+#include
+
+namespace can
+{
+
+/**
+ * Class representing a CANFrame.
+ * @author matthias.kessler
+ *
+ * A object of type CANFrame does not provide any payload-buffer by default.
+ * It has to be provided with buffers by using a certain constructor or the
+ * setPayload() method.
+ *
+ * @note
+ * CANFrame may be used as base class for special frame classes providing
+ * the programmer with explicit methods to access the signals that are
+ * encoded in the CANFrames payload.
+ */
+class CANFrame
+{
+public:
+ /** bitmask to extract sender */
+ static const uint8 SENDER_MASK = 0xFF;
+ /** overhead of a CANFrame (in bit) */
+ static const uint8 CAN_OVERHEAD_BITS = 47;
+ /** maximum payload length of a CANFrame */
+ static const uint8 MAX_FRAME_LENGTH = 8;
+ /** maximum value of a CANFrame id */
+ static const uint16 MAX_FRAME_ID = 0x7FF;
+
+ /**
+ * @post getId() == 0x00
+ * @post getPayload() == NULL
+ * @post getPayloadLength() == 0
+ * @post getTimestamp() == 0
+ */
+ CANFrame();
+
+ /**
+ * Copy constructor
+ * @param frame CANFrame to copy content from
+ */
+ CANFrame(const CANFrame& frame);
+
+ /**
+ * Constructor initializing id, payload and length
+ *
+ * @pre id <= MAX_FRAME_ID
+ * @pre length <= MAX_FRAME_LENGTH
+ * @throws assertion
+ *
+ * The payload will not be copied, it is passed as a
+ * reference and CANFrame will work on this payload!
+ */
+ CANFrame(uint16 id, uint8 payload[], uint8 length);
+
+ uint16 getId() const
+ {
+ return fId;
+ }
+
+ void setId(uint16 id)
+ {
+ this->fId = id;
+ }
+
+ /**
+ * @return pointer to modifiable payload of this CANFrame
+ */
+ uint8* getPayload()
+ {
+ return fpPayload;
+ }
+
+ /**
+ * @return pointer to read only payload of this CANFrame
+ */
+ const uint8* getPayload() const
+ {
+ return fpPayload;
+ }
+
+ /**
+ * Sets the CANFrames payload and length
+ *
+ * @note
+ * This method just sets a pointer to the payload and does not copy it!
+ *
+ * @post getPayload() == payload
+ * @post getPayloadLength() == length
+ * @post getMaxPayloadLength() == length
+ */
+ void setPayload(uint8 payload[], uint8 length)
+ {
+ fpPayload = payload;
+ fPayloadLength = length;
+ fMaxPayloadLength = length;
+ }
+
+ /**
+ * @pre getPayload() != NULL
+ * @pre length <= getMaxPayloadLength()
+ * @throws assertion
+ */
+ void setPayloadLength(uint8 length);
+
+ uint8 getPayloadLength() const
+ {
+ return fPayloadLength;
+ }
+
+ uint8 getMaxPayloadLength() const
+ {
+ return fMaxPayloadLength;
+ }
+
+ /**
+ * Assigns content of a CANFrame to another.
+ * @param canFrame frame to copy from
+ * @return reference to frame with new content
+ * @pre getMaxPayloadLength() >= canFrame.getPayloadLength()
+ * @throws assertion
+ */
+ CANFrame& operator=(const CANFrame& canFrame);
+
+ /**
+ * @return modifiable reference to timestamp
+ */
+ uint64& getTimestamp()
+ {
+ return fTimestamp; // PRQA S 4024
+ }
+
+ /**
+ * @return read only access to timestamp
+ */
+ const uint64& getTimestamp() const
+ {
+ return fTimestamp;
+ }
+
+ bool isExtended() const { return false; } /* TODO: cleanup */
+
+protected:
+ friend bool operator==(const CANFrame& frame1, const CANFrame& frame2);
+
+ uint8* fpPayload;
+ uint16 fId;
+ uint8 fPayloadLength;
+ uint8 fMaxPayloadLength;
+ uint64 fTimestamp;
+};
+
+/**
+ * Compares two CANFrames without considering the timestamp
+ * @param frame1 first frame to compare
+ * @param frame2 second frame to compare
+ * @return
+ * - true if frames are equal
+ * - false if frames are not equal
+ */
+bool operator==(const CANFrame& frame1, const CANFrame& frame2);
+
+} /* namespace can */
+
+#endif /* CANFRAME_H */
diff --git a/2016/ppc/gps/include/can/filter/IFilter.h b/2016/ppc/gps/include/can/filter/IFilter.h
new file mode 100644
index 0000000..701f73f
--- /dev/null
+++ b/2016/ppc/gps/include/can/filter/IFilter.h
@@ -0,0 +1,79 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * Contains IFilter interface.
+ * @file IFilter.h
+ * @ingroup filter
+ */
+#ifndef IFILTER_H_
+#define IFILTER_H_
+
+#include "commonTypes.h"
+#include "util/Uncopyable.h"
+
+namespace can
+{
+//forward declaration
+class IMerger;
+
+/**
+ * common interface for filter classes
+ * @author matthias.kessler
+ */
+class IFilter
+{
+public:
+ IFilter() {};
+
+ /**
+ * adds a single id to the filter
+ * @param id id to add
+ * @post filter.match(id)
+ */
+ virtual void add(uint16 id) = 0;
+
+ /**
+ * adds a range of ids to the filter
+ * @param from begin of range
+ * @param to end of range
+ * @post filter.match(from...to);
+ */
+ virtual void add(uint16 from, uint16 to) = 0;
+
+ /**
+ * checks if a given id matches the filter
+ * @return
+ * - true: id matches filter
+ * - false: id does not match filter
+ */
+ virtual bool match(uint16 id) const = 0;
+
+ /**
+ * clears the filter so that nothing matches
+ */
+ virtual void clear() = 0;
+
+ /**
+ * opens the filters full range
+ */
+ virtual void open() = 0;
+
+ /**
+ * merges filter with a given merger
+ * @param merger IMerger to merge filter to
+ *
+ * This is part of the visitor pattern that is used to
+ * merge different kinds of filters.
+ */
+ virtual void acceptMerger(IMerger& merger) = 0;
+private:
+ MAKE_UNCOPYABLE(IFilter)
+};
+
+} //namespace can
+
+#endif /*IFILTER_H_*/
diff --git a/2016/ppc/gps/include/can/filter/IMerger.h b/2016/ppc/gps/include/can/filter/IMerger.h
new file mode 100644
index 0000000..503db0b
--- /dev/null
+++ b/2016/ppc/gps/include/can/filter/IMerger.h
@@ -0,0 +1,62 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * Contains IMerger interface.
+ * @file IMerger.h
+ * @ingroup filter
+ */
+#ifndef _IMERGER_H_
+#define _IMERGER_H_
+
+#include "util/Uncopyable.h"
+
+namespace can
+{
+
+//forward declarations
+class BitFieldFilter;
+class AbstractStaticBitFieldFilter;
+class IntervalFilter;
+
+/**
+ * interface for class that are able to merge with other filter classes
+ * @class IMerger
+ * @author gerd.schaefer
+ *
+ * @see BitFieldFilter
+ * @see AbstractStaticBitFieldFilter
+ * @see IntervalFilter
+ */
+class IMerger
+{
+public:
+ IMerger() {}
+
+ /**
+ * merges with a BitFieldFilter
+ * @param filter BitFieldFilter to merge with
+ */
+ virtual void mergeWithBitField(BitFieldFilter& filter) = 0;
+
+ /**
+ * merges with a AbstractStaticBitFieldFilter
+ * @param filter AbstractStaticBitFieldFilter to merge with
+ */
+ virtual void mergeWithStaticBitField(AbstractStaticBitFieldFilter& filter) = 0;
+
+ /**
+ * merges with a IntervalFilter
+ * @param filter IntervalFilter to merge with
+ */
+ virtual void mergeWithInterval(IntervalFilter& filter) = 0;
+private:
+ MAKE_UNCOPYABLE(IMerger)
+};
+
+} //namespace can
+
+#endif //_IMERGER_H_
diff --git a/2016/ppc/gps/include/can/filter/IntervalFilter.h b/2016/ppc/gps/include/can/filter/IntervalFilter.h
new file mode 100644
index 0000000..575587e
--- /dev/null
+++ b/2016/ppc/gps/include/can/filter/IntervalFilter.h
@@ -0,0 +1,148 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * Contains IntervalFilter class.
+ * @file IntervalFilter.h
+ * @ingroup filter
+ */
+#ifndef _INTERVALFILTER_H_
+#define _INTERVALFILTER_H_
+
+#include "commonTypes.h"
+#include "can/canframes/CANFrame.h"
+#include "can/filter/IFilter.h"
+#include "can/filter/IMerger.h"
+#include "util/Uncopyable.h"
+
+namespace can
+{
+
+/**
+ * Cpp2CAN IntervalFilter
+ * @author gerd.schaefer, matthias.kessler
+ *
+ * @see IFilter
+ */
+class IntervalFilter :
+ public IFilter
+{
+public:
+ /** maximum id the filter may take */
+ static const uint16 MAX_ID = CANFrame::MAX_FRAME_ID;
+
+ /**
+ * constructor
+ * @post getLowerBound() == MAX_ID
+ * @post getUpperBound() == 0x0
+ *
+ * Nothing wil be accepted by default
+ */
+ IntervalFilter();
+
+ /**
+ * constructor initializing an interval
+ * @param from first id that will be accepted
+ * @param to last id that will be accepted
+ * @pre from <= MAX_ID
+ * @pre to <= MAX_ID
+ * @post getLowerBound() == from
+ * @post getUpperBound() == to
+ *
+ * @note
+ * If from or to exceed MAX_ID, they will be set to MAX_ID.
+ */
+ explicit IntervalFilter(uint16 from, uint16 to);
+
+ /**
+ * @see IFilter::add()
+ * @param id id to add to filter
+ * @pre id <= MAX_ID, otherwise no effect
+ * @post getLowerBound() == min(id, getLowerBound())
+ * @post getUpperBound() == max(id, getUpperBound())
+ *
+ * @note
+ * This call is equal to add(id, id).
+ */
+ virtual void add(uint16 id)
+ {
+ if (id <= MAX_ID)
+ {
+ add(id, id);
+ }
+ }
+
+ /**
+ * @see IFilter::add()
+ * @param from lower bound of interval to add
+ * @param to upper bound of interval to add
+ * @pre from <= MAX_ID
+ * @pre to <= MAX_ID
+ * @post getLowerBound() == min(from, getLowerBound())
+ * @post getUpperBound() == max(to, getUpperBound())
+ *
+ * If from or to exceed MAX_ID, they will be set to MAX_ID.
+ *
+ * This call will not replace the current filter configuration, but
+ * adjust lower and upper bound of the filter according to the parameters.
+ */
+ virtual void add(uint16 from, uint16 to);
+
+ /**
+ * checks if an id matches the filter
+ * @param id id to check
+ * @return
+ * - true: filter matches id
+ * - false: id is not in filters range
+ */
+ virtual bool match(uint16 id) const
+ {
+ return (id >= fFrom) && (id <= fTo);
+ }
+
+ /**
+ * @see IFilter::acceptMerger()
+ */
+ virtual void acceptMerger(IMerger& merger)
+ {
+ merger.mergeWithInterval(*this);
+ }
+
+ /**
+ * @see IFilter::clear();
+ */
+ virtual void clear();
+
+ /**
+ * @see IFilter::open();
+ */
+ virtual void open();
+
+ /**
+ * @return lower bound of filter
+ */
+ uint16 getLowerBound() const
+ {
+ return fFrom;
+ }
+
+ /**
+ * @return upper bound of filter
+ */
+ uint16 getUpperBound() const
+ {
+ return fTo;
+ }
+private:
+ MAKE_UNCOPYABLE(IntervalFilter)
+ //fields
+ uint16 fFrom;
+ uint16 fTo;
+};
+
+} /*namespace can*/
+
+#endif //_INTERVALFILTER_H_
diff --git a/2016/ppc/gps/include/can/framemgmt/ICANFrameListener.h b/2016/ppc/gps/include/can/framemgmt/ICANFrameListener.h
new file mode 100644
index 0000000..d155450
--- /dev/null
+++ b/2016/ppc/gps/include/can/framemgmt/ICANFrameListener.h
@@ -0,0 +1,50 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+/**
+ * Contains interface ICANFrameListener.
+ * @file ICANFrameListener.h
+ * @ingroup framemgmt
+ */
+#ifndef ICANFRAMELISTENER_H
+#define ICANFRAMELISTENER_H
+
+#include "util/SLinkedListSet.h"
+#include "util/Uncopyable.h"
+
+namespace can
+{
+class CANFrame;
+class IFilter;
+
+/**
+ * CANFrameListener interface
+ * @author matthias.kessler
+ *
+ * An ICANFrameListener subclass is a class interested in the reception
+ * of CANFrames. Therefore it needs to register at an AbstractCANTransceiver.
+ */
+class ICANFrameListener :
+ public SLinkedListSetNode
+{
+ MAKE_UNCOPYABLE(ICANFrameListener)
+public:
+ ICANFrameListener() {}
+
+ /**
+ * This method notifies the listener of a CANFrame reception.
+ */
+ virtual void frameReceived(const CANFrame& canFrame) = 0;
+
+ /**
+ * Returns the ICANFrameListeners filter.
+ */
+ virtual IFilter& getFilter() = 0;
+};
+
+} //namespace can
+
+#endif // ICANFRAMELISTENER_H
diff --git a/2016/ppc/gps/include/gps/GpsConverter.h b/2016/ppc/gps/include/gps/GpsConverter.h
new file mode 100644
index 0000000..b353bdc
--- /dev/null
+++ b/2016/ppc/gps/include/gps/GpsConverter.h
@@ -0,0 +1,48 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#ifndef GPSCONVERTER_H_
+#define GPSCONVERTER_H_
+
+#include "commonTypes.h"
+#include "can/framemgmt/ICANFrameListener.h"
+#include "can/filter/IntervalFilter.h"
+
+namespace can
+{
+class CANFrame;
+class ICANTransceiver;
+}
+namespace gps
+{
+class IGpsACPusher;
+
+class GpsConverter :
+ public can::ICANFrameListener
+{
+public:
+ enum { GPS_FRAME_ID = 0x34a }; //NavGps1
+ GpsConverter(can::ICANTransceiver& transceiver, IGpsACPusher& acPusher);
+
+ /* ICANFrameListener */
+ virtual void frameReceived(const can::CANFrame& canFrame);
+ virtual can::IFilter& getFilter()
+ {
+ return fCanFilter;
+ }
+
+private:
+ can::ICANTransceiver& fCanTransceiver;
+ can::IntervalFilter fCanFilter;
+
+ IGpsACPusher& fAcPusher;
+ sint32 fLastLatInMs;
+ sint32 fLastLongInMs;
+};
+
+} // namespace gps
+#endif /* end of include guard */
+
diff --git a/2016/ppc/gps/rakefile.rb b/2016/ppc/gps/rakefile.rb
new file mode 100644
index 0000000..2c570be
--- /dev/null
+++ b/2016/ppc/gps/rakefile.rb
@@ -0,0 +1,7 @@
+
+desc "run unittests"
+task :runTests do
+ sh "bake -b UnitTest -a black --include_filter run"
+end
+task :default => :run
+
diff --git a/2016/ppc/gps/src/ac/GpsACPusher.cpp b/2016/ppc/gps/src/ac/GpsACPusher.cpp
new file mode 100644
index 0000000..cb50a27
--- /dev/null
+++ b/2016/ppc/gps/src/ac/GpsACPusher.cpp
@@ -0,0 +1,33 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#include "gps/AcPusher.h"
+#include "android/caim/base/ICaimTransceiver.h"
+#include "util/endian.h"
+
+namespace gps
+{
+
+void GpsAcPusher::pushGPSCoordinates(sint32 latMs, sint32 longMs)
+{
+ uint8 newPosition[sizeof(fPosition)];
+
+ writeMem32(newPosition + LONGITUDE_OFFSET, longMs);
+ writeMem32(newPosition + LATITUDE_OFFSET, latMs);
+
+ writeMem16(newPosition + HEIGHT_OFFSET, 0);
+ writeMem16(newPosition + SPEED_OFFSET, 0);
+ newPosition[HEADING_OFFSET] = 0;
+ writeMem16(newPosition + QUALITY_OFFSET, 0);
+
+ if (memcmp(newPosition, fPosition, sizeof(fPosition)))
+ {
+ memcpy(fPosition, newPosition, sizeof(fPosition));
+ fCaimTransceiver.push(POSITION_COMMAND, fPosition, sizeof(fPosition));
+ }
+}
+} // namespace gps
+
diff --git a/2016/ppc/gps/src/can/canframes/CANFrame.cpp b/2016/ppc/gps/src/can/canframes/CANFrame.cpp
new file mode 100644
index 0000000..3cdc019
--- /dev/null
+++ b/2016/ppc/gps/src/can/canframes/CANFrame.cpp
@@ -0,0 +1,99 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#include "can/canframes/CANFrame.h"
+
+namespace can
+{
+
+//define const variables for GCC
+#ifdef __GNUC__
+const uint8 CANFrame::SENDER_MASK;
+const uint8 CANFrame::CAN_OVERHEAD_BITS;
+const uint8 CANFrame::MAX_FRAME_LENGTH;
+const uint16 CANFrame::MAX_FRAME_ID;
+#endif
+
+CANFrame::CANFrame() :
+ fpPayload(0L),
+ fId(0),
+ fPayloadLength(0),
+ fMaxPayloadLength(0),
+ fTimestamp(0)
+{}
+
+CANFrame::CANFrame(const CANFrame& frame) :
+ fpPayload(frame.fpPayload),
+ fId(frame.fId),
+ fPayloadLength(frame.fPayloadLength),
+ fMaxPayloadLength(frame.fMaxPayloadLength),
+ fTimestamp(frame.fTimestamp)
+{
+}
+
+CANFrame::CANFrame(uint16 id, uint8 payload[], uint8 length) :
+ fpPayload(payload),
+ fId(id),
+ fPayloadLength(length),
+ fMaxPayloadLength(length)
+{
+ assert(id <= MAX_FRAME_ID);
+ assert(length <= MAX_FRAME_LENGTH);
+}
+
+CANFrame& CANFrame::operator=(const CANFrame& canFrame)
+{
+ if (&canFrame != this)
+ {
+ if (fMaxPayloadLength < canFrame.fPayloadLength)
+ {
+ assert(fMaxPayloadLength >= canFrame.fPayloadLength);
+ }
+ fId = canFrame.fId;
+ for (uint8 i = 0; i < canFrame.fPayloadLength; ++i)
+ {
+ fpPayload[i] = canFrame.fpPayload[i];
+ }
+ fPayloadLength = canFrame.fPayloadLength;
+ fTimestamp = canFrame.fTimestamp;
+ }
+ return *this;
+}
+
+void CANFrame::setPayloadLength(uint8 length)
+{
+ if (!fpPayload)
+ {
+ assert(fpPayload != 0L);
+ }
+ if (length > fMaxPayloadLength)
+ {
+ assert(length <= fMaxPayloadLength);
+ }
+ fPayloadLength = length;
+}
+
+bool operator==(const CANFrame& frame1, const CANFrame& frame2)
+{
+ if (frame1.fId != frame2.fId)
+ {
+ return false;
+ }
+ if (frame1.fPayloadLength != frame2.fPayloadLength)
+ {
+ return false;
+ }
+ for (uint8 i = 0; i < frame1.fPayloadLength; i++)
+ {
+ if (frame1.fpPayload[i] != frame2.fpPayload[i])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+} //namespace can
diff --git a/2016/ppc/gps/src/can/filter/IntervalFilter.cpp b/2016/ppc/gps/src/can/filter/IntervalFilter.cpp
new file mode 100644
index 0000000..77a8289
--- /dev/null
+++ b/2016/ppc/gps/src/can/filter/IntervalFilter.cpp
@@ -0,0 +1,69 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#include "can/filter/IntervalFilter.h"
+#include "util/SAlgorithm.h"
+
+namespace can
+{
+
+#ifdef __GNUC__
+const uint16 IntervalFilter::MAX_ID;
+#endif
+
+IntervalFilter::IntervalFilter()
+{
+ clear();
+}
+
+IntervalFilter::IntervalFilter(uint16 from, uint16 to) :
+ fFrom(from),
+ fTo(to)
+{
+ if (from > MAX_ID)
+ {
+ fFrom = MAX_ID;
+ }
+ if (to > MAX_ID)
+ {
+ fTo = MAX_ID;
+ }
+}
+
+void IntervalFilter::add(uint16 from, uint16 to)
+{
+ if (from > MAX_ID)
+ {
+ from = MAX_ID;
+ }
+ if (to > MAX_ID)
+ {
+ to = MAX_ID;
+ }
+ //assert order
+ if (from > to)
+ {
+ sswap(from, to);
+ }
+ //adjust lower bound
+ fFrom = smin(fFrom, from);
+ //adjust upper bound
+ fTo = smax(fTo, to);
+}
+
+void IntervalFilter::clear()
+{
+ fFrom = MAX_ID;
+ fTo = 0;
+}
+
+void IntervalFilter::open()
+{
+ fFrom = 0x0;
+ fTo = MAX_ID;
+}
+
+} /*namespace can*/
diff --git a/2016/ppc/gps/src/gps/GpsConverter.cpp b/2016/ppc/gps/src/gps/GpsConverter.cpp
new file mode 100644
index 0000000..acf60ab
--- /dev/null
+++ b/2016/ppc/gps/src/gps/GpsConverter.cpp
@@ -0,0 +1,48 @@
+/**
+ * \copyright
+ * (c) 2012 - 2015 E.S.R. Labs GmbH (http://www.esrlabs.com)
+ * All rights reserved.
+ */
+
+#include "gps/GpsConverter.h"
+#include "ac/IGpsACPusher.h"
+#include "can/canframes/CANFrame.h"
+#include "can/ICANTransceiver.h"
+#include
+
+using namespace can;
+
+namespace gps
+{
+
+GpsConverter::GpsConverter(
+ ICANTransceiver& transceiver,
+ IGpsACPusher& acPusher)
+ : fCanTransceiver(transceiver)
+ , fCanFilter(GPS_FRAME_ID, GPS_FRAME_ID)
+ , fAcPusher(acPusher)
+{
+}
+
+void GpsConverter::frameReceived(const CANFrame& canFrame)
+{
+ const uint8* payload = canFrame.getPayload();
+ // TOOD implement conversion to arc-msec and call IGpsACPusher
+
+ sint32 latInMs = 0; // here add your converted lat
+ sint32 longInMs = 0; // here add your converted long
+
+
+ if (latInMs != fLastLatInMs || longInMs != fLastLongInMs)
+ {
+ // value changed
+ fAcPusher.pushGPSCoordinates(latInMs, longInMs);
+ fLastLatInMs = latInMs;
+ fLastLongInMs = longInMs;
+ }
+}
+
+
+} // namespace gps
+
+
diff --git a/2016/ppc/gps/test/CanTransceiverMock.h b/2016/ppc/gps/test/CanTransceiverMock.h
new file mode 100644
index 0000000..199620f
--- /dev/null
+++ b/2016/ppc/gps/test/CanTransceiverMock.h
@@ -0,0 +1,53 @@
+#ifndef CANTRANSCEIVER_MOCK_H_
+#define CANTRANSCEIVER_MOCK_H_
+
+#include "can/ICANTransceiver.h"
+#include "busId/BusId.h"
+
+namespace can
+{
+
+class CanTransceiverMock
+ : public ICANTransceiver
+{
+public:
+ CanTransceiverMock()
+ {}
+ virtual ErrorCode init()
+ {
+ return CAN_ERR_OK;
+ }
+ virtual void shutdown() {}
+ virtual ErrorCode open()
+ {
+ return CAN_ERR_OK;
+ }
+ virtual ErrorCode close()
+ {
+ return CAN_ERR_OK;
+ }
+ virtual ErrorCode mute()
+ {
+ return CAN_ERR_OK;
+ }
+ virtual ErrorCode unmute()
+ {
+ return CAN_ERR_OK;
+ }
+ virtual ErrorCode write(const can::CANFrame& frame)
+ {
+ return CAN_ERR_OK;
+ }
+ virtual uint32 getBaudrate() const
+ {
+ return 500000;
+ }
+ virtual uint16 getHwQueueTimeout() const
+ {
+ return 50;
+ }
+};
+} // namespace can
+#endif /* end of include guard */
+
+
diff --git a/2016/ppc/gps/test/GpsConverterTest.cpp b/2016/ppc/gps/test/GpsConverterTest.cpp
new file mode 100644
index 0000000..ba4ce4b
--- /dev/null
+++ b/2016/ppc/gps/test/GpsConverterTest.cpp
@@ -0,0 +1,110 @@
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
+#include "commonTypes.h"
+#include "can/canframes/CANFrame.h"
+#include "gps/GpsConverter.h"
+#include "ac/IGpsACPusher.h"
+#include "CanTransceiverMock.h"
+#include "busId/BusId.h"
+
+using namespace gps;
+using namespace common;
+using namespace can;
+
+namespace test
+{
+
+class GpsAcPusherMock : public gps::IGpsACPusher
+{
+public:
+ GpsAcPusherMock()
+ : gpsWasSet(false)
+ {}
+ virtual void pushGPSCoordinates(sint32 latMs, sint32 longMs)
+ {
+ printf("pushGPSCoordinates received: %d and %d\n", latMs, longMs);
+ gpsWasSet = true;
+ latitudeMs = latMs;
+ longitudeMs = longMs;
+ }
+ void clear()
+ {
+ gpsWasSet = false;
+ latitudeMs = 0;
+ longitudeMs = 0;
+ }
+ sint32 latitudeMs;
+ sint32 longitudeMs;
+ bool gpsWasSet;
+};
+class GpsConverterTest
+{
+public:
+ GpsConverterTest()
+ : canTransceiverMock()
+ , converter(canTransceiverMock, acPusherMock)
+ {}
+
+ virtual ~GpsConverterTest() {}
+
+ can::CanTransceiverMock canTransceiverMock;
+ GpsAcPusherMock acPusherMock;
+ GpsConverter converter;
+};
+
+static bool withinTolerance(sint32 x1, sint32 x2, sint32 tolerance)
+{
+ return abs(x1-x2) < tolerance;
+}
+
+TEST_CASE_METHOD(GpsConverterTest, "london east calling", "[gps]")
+{
+ uint8 payload[8] = { 0xDF, 0x48, 0xEA, 0xFF, 0x08, 0xC5, 0xA5, 0x24 };
+ CANFrame gpsInfo(0x34a, payload, 8);
+ converter.frameReceived(gpsInfo);
+ CHECK(acPusherMock.gpsWasSet);
+ CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
+ CHECK(withinTolerance(acPusherMock.longitudeMs, -429429, 100));
+}
+
+TEST_CASE_METHOD(GpsConverterTest, "london west calling", "[gps]")
+{
+ uint8 payload[8] = { 0x1F, 0xB7, 0x15, 0x00, 0x08, 0xC5, 0xA5, 0x24 };
+ CANFrame gpsInfo(0x34a, payload, 8);
+ converter.frameReceived(gpsInfo);
+ SECTION("receive once")
+ {
+ CHECK(acPusherMock.gpsWasSet);
+ CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
+ CHECK(withinTolerance(acPusherMock.longitudeMs, 429428, 100));
+ }
+ SECTION("receive twice same value, only propagate once")
+ {
+ CHECK(acPusherMock.gpsWasSet);
+ CHECK(withinTolerance(acPusherMock.latitudeMs, 185528159, 100));
+ CHECK(withinTolerance(acPusherMock.longitudeMs, 429428, 100));
+ acPusherMock.clear();
+ converter.frameReceived(gpsInfo);
+ CHECK(!acPusherMock.gpsWasSet);
+ }
+}
+TEST_CASE_METHOD(GpsConverterTest, "invalid data", "[gps]")
+{
+ uint8 payload[8] = { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80 };
+ CANFrame gpsInfo(0x34a, payload, 8);
+ converter.frameReceived(gpsInfo);
+ CHECK(!acPusherMock.gpsWasSet);
+}
+TEST_CASE_METHOD(GpsConverterTest, "no signal", "[gps]")
+{
+ uint8 payload[8] = { 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F };
+ CANFrame gpsInfo(0x34a, payload, 8);
+ converter.frameReceived(gpsInfo);
+ CHECK(!acPusherMock.gpsWasSet);
+}
+// 48.1172966,11.5913253
+// 48.1173275,11.591452
+
+} // namespace test
+
+
diff --git a/2016/ppc/gps/test/catch.hpp b/2016/ppc/gps/test/catch.hpp
new file mode 100644
index 0000000..2964790
--- /dev/null
+++ b/2016/ppc/gps/test/catch.hpp
@@ -0,0 +1,9427 @@
+/*
+ * CATCH v1.1 build 14 (develop branch)
+ * Generated: 2015-03-04 18:32:24.627737
+ * ----------------------------------------------------------
+ * This file has been merged from multiple headers. Please don't edit it directly
+ * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
+#define TWOBLUECUBES_CATCH_HPP_INCLUDED
+
+// #included from: internal/catch_suppress_warnings.h
+
+#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
+
+#ifdef __clang__
+# ifdef __ICC // icpc defines the __clang__ macro
+# pragma warning(push)
+# pragma warning(disable: 161 1682)
+# else // __ICC
+# pragma clang diagnostic ignored "-Wglobal-constructors"
+# pragma clang diagnostic ignored "-Wvariadic-macros"
+# pragma clang diagnostic ignored "-Wc99-extensions"
+# pragma clang diagnostic ignored "-Wunused-variable"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wpadded"
+# pragma clang diagnostic ignored "-Wc++98-compat"
+# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+# endif
+#elif defined __GNUC__
+# pragma GCC diagnostic ignored "-Wvariadic-macros"
+# pragma GCC diagnostic ignored "-Wunused-variable"
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpadded"
+#endif
+
+#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
+# define CATCH_IMPL
+#endif
+
+#ifdef CATCH_IMPL
+# ifndef CLARA_CONFIG_MAIN
+# define CLARA_CONFIG_MAIN_NOT_DEFINED
+# define CLARA_CONFIG_MAIN
+# endif
+#endif
+
+// #included from: internal/catch_notimplemented_exception.h
+#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
+
+// #included from: catch_common.h
+#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
+
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
+#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
+
+#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
+#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
+
+#include
+#include
+#include
+
+// #included from: catch_compiler_capabilities.h
+#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
+
+// Much of the following code is based on Boost (1.53)
+
+#ifdef __clang__
+
+# if __has_feature(cxx_nullptr)
+# define CATCH_CONFIG_CPP11_NULLPTR
+# endif
+
+# if __has_feature(cxx_noexcept)
+# define CATCH_CONFIG_CPP11_NOEXCEPT
+# endif
+
+#endif // __clang__
+
+////////////////////////////////////////////////////////////////////////////////
+// Borland
+#ifdef __BORLANDC__
+
+#if (__BORLANDC__ > 0x582 )
+//#define CATCH_CONFIG_SFINAE // Not confirmed
+#endif
+
+#endif // __BORLANDC__
+
+////////////////////////////////////////////////////////////////////////////////
+// EDG
+#ifdef __EDG_VERSION__
+
+#if (__EDG_VERSION__ > 238 )
+//#define CATCH_CONFIG_SFINAE // Not confirmed
+#endif
+
+#endif // __EDG_VERSION__
+
+////////////////////////////////////////////////////////////////////////////////
+// Digital Mars
+#ifdef __DMC__
+
+#if (__DMC__ > 0x840 )
+//#define CATCH_CONFIG_SFINAE // Not confirmed
+#endif
+
+#endif // __DMC__
+
+////////////////////////////////////////////////////////////////////////////////
+// GCC
+#ifdef __GNUC__
+
+#if __GNUC__ < 3
+
+#if (__GNUC_MINOR__ >= 96 )
+//#define CATCH_CONFIG_SFINAE
+#endif
+
+#elif __GNUC__ >= 3
+
+// #define CATCH_CONFIG_SFINAE // Taking this out completely for now
+
+#endif // __GNUC__ < 3
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
+
+#define CATCH_CONFIG_CPP11_NULLPTR
+#endif
+
+#endif // __GNUC__
+
+////////////////////////////////////////////////////////////////////////////////
+// Visual C++
+#ifdef _MSC_VER
+
+#if (_MSC_VER >= 1600)
+#define CATCH_CONFIG_CPP11_NULLPTR
+#endif
+
+#if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
+//#define CATCH_CONFIG_SFINAE // Not confirmed
+#endif
+
+#endif // _MSC_VER
+
+// Use variadic macros if the compiler supports them
+#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
+ ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
+ ( defined __GNUC__ && __GNUC__ >= 3 ) || \
+ ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
+
+#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS
+#define CATCH_CONFIG_VARIADIC_MACROS
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// C++ language feature support
+
+// detect language version:
+#if (__cplusplus == 201103L)
+# define CATCH_CPP11
+# define CATCH_CPP11_OR_GREATER
+#elif (__cplusplus >= 201103L)
+# define CATCH_CPP11_OR_GREATER
+#endif
+
+// noexcept support:
+#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
+# define CATCH_NOEXCEPT noexcept
+# define CATCH_NOEXCEPT_IS(x) noexcept(x)
+#else
+# define CATCH_NOEXCEPT throw()
+# define CATCH_NOEXCEPT_IS(x)
+#endif
+
+namespace Catch {
+
+ class NonCopyable {
+#ifdef CATCH_CPP11_OR_GREATER
+ NonCopyable( NonCopyable const& ) = delete;
+ NonCopyable( NonCopyable && ) = delete;
+ NonCopyable& operator = ( NonCopyable const& ) = delete;
+ NonCopyable& operator = ( NonCopyable && ) = delete;
+#else
+ NonCopyable( NonCopyable const& info );
+ NonCopyable& operator = ( NonCopyable const& );
+#endif
+
+ protected:
+ NonCopyable() {}
+ virtual ~NonCopyable();
+ };
+
+ class SafeBool {
+ public:
+ typedef void (SafeBool::*type)() const;
+
+ static type makeSafe( bool value ) {
+ return value ? &SafeBool::trueValue : 0;
+ }
+ private:
+ void trueValue() const {}
+ };
+
+ template
+ inline void deleteAll( ContainerT& container ) {
+ typename ContainerT::const_iterator it = container.begin();
+ typename ContainerT::const_iterator itEnd = container.end();
+ for(; it != itEnd; ++it )
+ delete *it;
+ }
+ template
+ inline void deleteAllValues( AssociativeContainerT& container ) {
+ typename AssociativeContainerT::const_iterator it = container.begin();
+ typename AssociativeContainerT::const_iterator itEnd = container.end();
+ for(; it != itEnd; ++it )
+ delete it->second;
+ }
+
+ bool startsWith( std::string const& s, std::string const& prefix );
+ bool endsWith( std::string const& s, std::string const& suffix );
+ bool contains( std::string const& s, std::string const& infix );
+ void toLowerInPlace( std::string& s );
+ std::string toLower( std::string const& s );
+ std::string trim( std::string const& str );
+ bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
+
+ struct pluralise {
+ pluralise( std::size_t count, std::string const& label );
+
+ friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
+
+ std::size_t m_count;
+ std::string m_label;
+ };
+
+ struct SourceLineInfo {
+
+ SourceLineInfo();
+ SourceLineInfo( char const* _file, std::size_t _line );
+ SourceLineInfo( SourceLineInfo const& other );
+# ifdef CATCH_CPP11_OR_GREATER
+ SourceLineInfo( SourceLineInfo && ) = default;
+ SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
+ SourceLineInfo& operator = ( SourceLineInfo && ) = default;
+# endif
+ bool empty() const;
+ bool operator == ( SourceLineInfo const& other ) const;
+ bool operator < ( SourceLineInfo const& other ) const;
+
+ std::string file;
+ std::size_t line;
+ };
+
+ std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
+
+ // This is just here to avoid compiler warnings with macro constants and boolean literals
+ inline bool isTrue( bool value ){ return value; }
+ inline bool alwaysTrue() { return true; }
+ inline bool alwaysFalse() { return false; }
+
+ void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
+
+ // Use this in variadic streaming macros to allow
+ // >> +StreamEndStop
+ // as well as
+ // >> stuff +StreamEndStop
+ struct StreamEndStop {
+ std::string operator+() {
+ return std::string();
+ }
+ };
+ template
+ T const& operator + ( T const& value, StreamEndStop ) {
+ return value;
+ }
+}
+
+#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) )
+#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
+
+#include
+
+namespace Catch {
+
+ class NotImplementedException : public std::exception
+ {
+ public:
+ NotImplementedException( SourceLineInfo const& lineInfo );
+ NotImplementedException( NotImplementedException const& ) {}
+
+ virtual ~NotImplementedException() CATCH_NOEXCEPT {}
+
+ virtual const char* what() const CATCH_NOEXCEPT;
+
+ private:
+ std::string m_what;
+ SourceLineInfo m_lineInfo;
+ };
+
+} // end namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
+
+// #included from: internal/catch_context.h
+#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
+
+// #included from: catch_interfaces_generators.h
+#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
+
+#include
+
+namespace Catch {
+
+ struct IGeneratorInfo {
+ virtual ~IGeneratorInfo();
+ virtual bool moveNext() = 0;
+ virtual std::size_t getCurrentIndex() const = 0;
+ };
+
+ struct IGeneratorsForTest {
+ virtual ~IGeneratorsForTest();
+
+ virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
+ virtual bool moveNext() = 0;
+ };
+
+ IGeneratorsForTest* createGeneratorsForTest();
+
+} // end namespace Catch
+
+// #included from: catch_ptr.hpp
+#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+ // An intrusive reference counting smart pointer.
+ // T must implement addRef() and release() methods
+ // typically implementing the IShared interface
+ template
+ class Ptr {
+ public:
+ Ptr() : m_p( NULL ){}
+ Ptr( T* p ) : m_p( p ){
+ if( m_p )
+ m_p->addRef();
+ }
+ Ptr( Ptr const& other ) : m_p( other.m_p ){
+ if( m_p )
+ m_p->addRef();
+ }
+ ~Ptr(){
+ if( m_p )
+ m_p->release();
+ }
+ void reset() {
+ if( m_p )
+ m_p->release();
+ m_p = NULL;
+ }
+ Ptr& operator = ( T* p ){
+ Ptr temp( p );
+ swap( temp );
+ return *this;
+ }
+ Ptr& operator = ( Ptr const& other ){
+ Ptr temp( other );
+ swap( temp );
+ return *this;
+ }
+ void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
+ T* get() { return m_p; }
+ const T* get() const{ return m_p; }
+ T& operator*() const { return *m_p; }
+ T* operator->() const { return m_p; }
+ bool operator !() const { return m_p == NULL; }
+ operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
+
+ private:
+ T* m_p;
+ };
+
+ struct IShared : NonCopyable {
+ virtual ~IShared();
+ virtual void addRef() const = 0;
+ virtual void release() const = 0;
+ };
+
+ template
+ struct SharedImpl : T {
+
+ SharedImpl() : m_rc( 0 ){}
+
+ virtual void addRef() const {
+ ++m_rc;
+ }
+ virtual void release() const {
+ if( --m_rc == 0 )
+ delete this;
+ }
+
+ mutable unsigned int m_rc;
+ };
+
+} // end namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#include
+#include
+#include
+
+namespace Catch {
+
+ class TestCase;
+ class Stream;
+ struct IResultCapture;
+ struct IRunner;
+ struct IGeneratorsForTest;
+ struct IConfig;
+
+ struct IContext
+ {
+ virtual ~IContext();
+
+ virtual IResultCapture* getResultCapture() = 0;
+ virtual IRunner* getRunner() = 0;
+ virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
+ virtual bool advanceGeneratorsForCurrentTest() = 0;
+ virtual Ptr getConfig() const = 0;
+ };
+
+ struct IMutableContext : IContext
+ {
+ virtual ~IMutableContext();
+ virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+ virtual void setRunner( IRunner* runner ) = 0;
+ virtual void setConfig( Ptr const& config ) = 0;
+ };
+
+ IContext& getCurrentContext();
+ IMutableContext& getCurrentMutableContext();
+ void cleanUpContext();
+ Stream createStream( std::string const& streamName );
+
+}
+
+// #included from: internal/catch_test_registry.hpp
+#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
+
+// #included from: catch_interfaces_testcase.h
+#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
+
+#include
+
+namespace Catch {
+
+ class TestSpec;
+
+ struct ITestCase : IShared {
+ virtual void invoke () const = 0;
+ protected:
+ virtual ~ITestCase();
+ };
+
+ class TestCase;
+ struct IConfig;
+
+ struct ITestCaseRegistry {
+ virtual ~ITestCaseRegistry();
+ virtual std::vector const& getAllTests() const = 0;
+ virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const = 0;
+
+ };
+}
+
+namespace Catch {
+
+template
+class MethodTestCase : public SharedImpl {
+
+public:
+ MethodTestCase( void (C::*method)() ) : m_method( method ) {}
+
+ virtual void invoke() const {
+ C obj;
+ (obj.*m_method)();
+ }
+
+private:
+ virtual ~MethodTestCase() {}
+
+ void (C::*m_method)();
+};
+
+typedef void(*TestFunction)();
+
+struct NameAndDesc {
+ NameAndDesc( const char* _name = "", const char* _description= "" )
+ : name( _name ), description( _description )
+ {}
+
+ const char* name;
+ const char* description;
+};
+
+struct AutoReg {
+
+ AutoReg( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc );
+
+ template
+ AutoReg( void (C::*method)(),
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo ) {
+ registerTestCase( new MethodTestCase( method ),
+ className,
+ nameAndDesc,
+ lineInfo );
+ }
+
+ void registerTestCase( ITestCase* testCase,
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo );
+
+ ~AutoReg();
+
+private:
+ AutoReg( AutoReg const& );
+ void operator= ( AutoReg const& );
+};
+
+} // end namespace Catch
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TESTCASE( ... ) \
+ static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
+ static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
+ namespace{ \
+ struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
+ void test(); \
+ }; \
+ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
+ } \
+ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
+
+#else
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
+ static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
+ static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
+ namespace{ \
+ struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
+ void test(); \
+ }; \
+ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
+ } \
+ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
+
+#endif
+
+// #included from: internal/catch_capture.hpp
+#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
+
+// #included from: catch_result_builder.h
+#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
+
+// #included from: catch_result_type.h
+#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
+
+namespace Catch {
+
+ // ResultWas::OfType enum
+ struct ResultWas { enum OfType {
+ Unknown = -1,
+ Ok = 0,
+ Info = 1,
+ Warning = 2,
+
+ FailureBit = 0x10,
+
+ ExpressionFailed = FailureBit | 1,
+ ExplicitFailure = FailureBit | 2,
+
+ Exception = 0x100 | FailureBit,
+
+ ThrewException = Exception | 1,
+ DidntThrowException = Exception | 2,
+
+ FatalErrorCondition = 0x200 | FailureBit
+
+ }; };
+
+ inline bool isOk( ResultWas::OfType resultType ) {
+ return ( resultType & ResultWas::FailureBit ) == 0;
+ }
+ inline bool isJustInfo( int flags ) {
+ return flags == ResultWas::Info;
+ }
+
+ // ResultDisposition::Flags enum
+ struct ResultDisposition { enum Flags {
+ Normal = 0x00,
+
+ ContinueOnFailure = 0x01, // Failures fail test, but execution continues
+ FalseTest = 0x02, // Prefix expression with !
+ SuppressFail = 0x04 // Failures are reported but do not fail the test
+ }; };
+
+ inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
+ return static_cast( static_cast( lhs ) | static_cast( rhs ) );
+ }
+
+ inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
+ inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
+ inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
+
+} // end namespace Catch
+
+// #included from: catch_assertionresult.h
+#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
+
+#include
+
+namespace Catch {
+
+ struct AssertionInfo
+ {
+ AssertionInfo() {}
+ AssertionInfo( std::string const& _macroName,
+ SourceLineInfo const& _lineInfo,
+ std::string const& _capturedExpression,
+ ResultDisposition::Flags _resultDisposition );
+
+ std::string macroName;
+ SourceLineInfo lineInfo;
+ std::string capturedExpression;
+ ResultDisposition::Flags resultDisposition;
+ };
+
+ struct AssertionResultData
+ {
+ AssertionResultData() : resultType( ResultWas::Unknown ) {}
+
+ std::string reconstructedExpression;
+ std::string message;
+ ResultWas::OfType resultType;
+ };
+
+ class AssertionResult {
+ public:
+ AssertionResult();
+ AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
+ ~AssertionResult();
+# ifdef CATCH_CPP11_OR_GREATER
+ AssertionResult( AssertionResult const& ) = default;
+ AssertionResult( AssertionResult && ) = default;
+ AssertionResult& operator = ( AssertionResult const& ) = default;
+ AssertionResult& operator = ( AssertionResult && ) = default;
+# endif
+
+ bool isOk() const;
+ bool succeeded() const;
+ ResultWas::OfType getResultType() const;
+ bool hasExpression() const;
+ bool hasMessage() const;
+ std::string getExpression() const;
+ std::string getExpressionInMacro() const;
+ bool hasExpandedExpression() const;
+ std::string getExpandedExpression() const;
+ std::string getMessage() const;
+ SourceLineInfo getSourceInfo() const;
+ std::string getTestMacroName() const;
+
+ protected:
+ AssertionInfo m_info;
+ AssertionResultData m_resultData;
+ };
+
+} // end namespace Catch
+
+namespace Catch {
+
+ struct TestFailureException{};
+
+ template class ExpressionLhs;
+
+ struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
+
+ struct CopyableStream {
+ CopyableStream() {}
+ CopyableStream( CopyableStream const& other ) {
+ oss << other.oss.str();
+ }
+ CopyableStream& operator=( CopyableStream const& other ) {
+ oss.str("");
+ oss << other.oss.str();
+ return *this;
+ }
+ std::ostringstream oss;
+ };
+
+ class ResultBuilder {
+ public:
+ ResultBuilder( char const* macroName,
+ SourceLineInfo const& lineInfo,
+ char const* capturedExpression,
+ ResultDisposition::Flags resultDisposition );
+
+ template
+ ExpressionLhs operator->* ( T const& operand );
+ ExpressionLhs operator->* ( bool value );
+
+ template
+ ResultBuilder& operator << ( T const& value ) {
+ m_stream.oss << value;
+ return *this;
+ }
+
+ template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+ template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
+
+ ResultBuilder& setResultType( ResultWas::OfType result );
+ ResultBuilder& setResultType( bool result );
+ ResultBuilder& setLhs( std::string const& lhs );
+ ResultBuilder& setRhs( std::string const& rhs );
+ ResultBuilder& setOp( std::string const& op );
+
+ void endExpression();
+
+ std::string reconstructExpression() const;
+ AssertionResult build() const;
+
+ void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
+ void captureResult( ResultWas::OfType resultType );
+ void captureExpression();
+ void react();
+ bool shouldDebugBreak() const;
+ bool allowThrows() const;
+
+ private:
+ AssertionInfo m_assertionInfo;
+ AssertionResultData m_data;
+ struct ExprComponents {
+ ExprComponents() : testFalse( false ) {}
+ bool testFalse;
+ std::string lhs, rhs, op;
+ } m_exprComponents;
+ CopyableStream m_stream;
+
+ bool m_shouldDebugBreak;
+ bool m_shouldThrow;
+ };
+
+} // namespace Catch
+
+// Include after due to circular dependency:
+// #included from: catch_expression_lhs.hpp
+#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
+
+// #included from: catch_evaluate.hpp
+#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+#endif
+
+#include
+
+namespace Catch {
+namespace Internal {
+
+ enum Operator {
+ IsEqualTo,
+ IsNotEqualTo,
+ IsLessThan,
+ IsGreaterThan,
+ IsLessThanOrEqualTo,
+ IsGreaterThanOrEqualTo
+ };
+
+ template struct OperatorTraits { static const char* getName(){ return "*error*"; } };
+ template<> struct OperatorTraits { static const char* getName(){ return "=="; } };
+ template<> struct OperatorTraits { static const char* getName(){ return "!="; } };
+ template<> struct OperatorTraits { static const char* getName(){ return "<"; } };
+ template<> struct OperatorTraits { static const char* getName(){ return ">"; } };
+ template<> struct OperatorTraits { static const char* getName(){ return "<="; } };
+ template<> struct OperatorTraits{ static const char* getName(){ return ">="; } };
+
+ template
+ inline T& opCast(T const& t) { return const_cast(t); }
+
+// nullptr_t support based on pull request #154 from Konstantin Baumann
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+ inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
+#endif // CATCH_CONFIG_CPP11_NULLPTR
+
+ // So the compare overloads can be operator agnostic we convey the operator as a template
+ // enum, which is used to specialise an Evaluator for doing the comparison.
+ template
+ class Evaluator{};
+
+ template
+ struct Evaluator {
+ static bool evaluate( T1 const& lhs, T2 const& rhs) {
+ return opCast( lhs ) == opCast( rhs );
+ }
+ };
+ template
+ struct Evaluator {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) != opCast( rhs );
+ }
+ };
+ template
+ struct Evaluator {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) < opCast( rhs );
+ }
+ };
+ template
+ struct Evaluator {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) > opCast( rhs );
+ }
+ };
+ template
+ struct Evaluator {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) >= opCast( rhs );
+ }
+ };
+ template
+ struct Evaluator {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return opCast( lhs ) <= opCast( rhs );
+ }
+ };
+
+ template
+ bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator::evaluate( lhs, rhs );
+ }
+
+ // This level of indirection allows us to specialise for integer types
+ // to avoid signed/ unsigned warnings
+
+ // "base" overload
+ template
+ bool compare( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator::evaluate( lhs, rhs );
+ }
+
+ // unsigned X to int
+ template bool compare( unsigned int lhs, int rhs ) {
+ return applyEvaluator( lhs, static_cast( rhs ) );
+ }
+ template bool compare( unsigned long lhs, int rhs ) {
+ return applyEvaluator( lhs, static_cast( rhs ) );
+ }
+ template bool compare( unsigned char lhs, int rhs ) {
+ return applyEvaluator( lhs, static_cast( rhs ) );
+ }
+
+ // unsigned X to long
+ template bool compare( unsigned int lhs, long rhs ) {
+ return applyEvaluator( lhs, static_cast( rhs ) );
+ }
+ template bool compare( unsigned long lhs, long rhs ) {
+ return applyEvaluator( lhs, static_cast( rhs ) );
+ }
+ template bool compare( unsigned char lhs, long rhs ) {
+ return applyEvaluator( lhs, static_cast( rhs ) );
+ }
+
+ // int to unsigned X
+ template bool compare( int lhs, unsigned int rhs ) {
+ return applyEvaluator( static_cast( lhs ), rhs );
+ }
+ template bool compare( int lhs, unsigned long rhs ) {
+ return applyEvaluator( static_cast( lhs ), rhs );
+ }
+ template bool compare( int lhs, unsigned char rhs ) {
+ return applyEvaluator( static_cast( lhs ), rhs );
+ }
+
+ // long to unsigned X
+ template bool compare( long lhs, unsigned int rhs ) {
+ return applyEvaluator( static_cast( lhs ), rhs );
+ }
+ template bool compare( long lhs, unsigned long rhs ) {
+ return applyEvaluator( static_cast( lhs ), rhs );
+ }
+ template bool compare( long lhs, unsigned char rhs ) {
+ return applyEvaluator( static_cast( lhs ), rhs );
+ }
+
+ // pointer to long (when comparing against NULL)
+ template bool compare( long lhs, T* rhs ) {
+ return Evaluator::evaluate( reinterpret_cast( lhs ), rhs );
+ }
+ template bool compare( T* lhs, long rhs ) {
+ return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) );
+ }
+
+ // pointer to int (when comparing against NULL)
+ template bool compare( int lhs, T* rhs ) {
+ return Evaluator::evaluate( reinterpret_cast( lhs ), rhs );
+ }
+ template bool compare( T* lhs, int rhs ) {
+ return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) );
+ }
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+ // pointer to nullptr_t (when comparing against nullptr)
+ template bool compare( std::nullptr_t, T* rhs ) {
+ return Evaluator::evaluate( NULL, rhs );
+ }
+ template bool compare( T* lhs, std::nullptr_t ) {
+ return Evaluator::evaluate( lhs, NULL );
+ }
+#endif // CATCH_CONFIG_CPP11_NULLPTR
+
+} // end of namespace Internal
+} // end of namespace Catch
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// #included from: catch_tostring.h
+#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
+
+// #included from: catch_sfinae.hpp
+#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
+
+// Try to detect if the current compiler supports SFINAE
+
+namespace Catch {
+
+ struct TrueType {
+ static const bool value = true;
+ typedef void Enable;
+ char sizer[1];
+ };
+ struct FalseType {
+ static const bool value = false;
+ typedef void Disable;
+ char sizer[2];
+ };
+
+#ifdef CATCH_CONFIG_SFINAE
+
+ template struct NotABooleanExpression;
+
+ template struct If : NotABooleanExpression {};
+ template<> struct If : TrueType {};
+ template<> struct If : FalseType {};
+
+ template struct SizedIf;
+ template<> struct SizedIf : TrueType {};
+ template<> struct SizedIf : FalseType {};
+
+#endif // CATCH_CONFIG_SFINAE
+
+} // end namespace Catch
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __OBJC__
+// #included from: catch_objc_arc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
+
+#import
+
+#ifdef __has_feature
+#define CATCH_ARC_ENABLED __has_feature(objc_arc)
+#else
+#define CATCH_ARC_ENABLED 0
+#endif
+
+void arcSafeRelease( NSObject* obj );
+id performOptionalSelector( id obj, SEL sel );
+
+#if !CATCH_ARC_ENABLED
+inline void arcSafeRelease( NSObject* obj ) {
+ [obj release];
+}
+inline id performOptionalSelector( id obj, SEL sel ) {
+ if( [obj respondsToSelector: sel] )
+ return [obj performSelector: sel];
+ return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED
+#define CATCH_ARC_STRONG
+#else
+inline void arcSafeRelease( NSObject* ){}
+inline id performOptionalSelector( id obj, SEL sel ) {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+#endif
+ if( [obj respondsToSelector: sel] )
+ return [obj performSelector: sel];
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
+#define CATCH_ARC_STRONG __strong
+#endif
+
+#endif
+
+#ifdef CATCH_CPP11_OR_GREATER
+#include
+#include
+#endif
+
+namespace Catch {
+
+// Why we're here.
+template
+std::string toString( T const& value );
+
+// Built in overloads
+
+std::string toString( std::string const& value );
+std::string toString( std::wstring const& value );
+std::string toString( const char* const value );
+std::string toString( char* const value );
+std::string toString( const wchar_t* const value );
+std::string toString( wchar_t* const value );
+std::string toString( int value );
+std::string toString( unsigned long value );
+std::string toString( unsigned int value );
+std::string toString( const double value );
+std::string toString( const float value );
+std::string toString( bool value );
+std::string toString( char value );
+std::string toString( signed char value );
+std::string toString( unsigned char value );
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+std::string toString( std::nullptr_t );
+#endif
+
+#ifdef __OBJC__
+ std::string toString( NSString const * const& nsstring );
+ std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
+ std::string toString( NSObject* const& nsObject );
+#endif
+
+namespace Detail {
+
+ extern std::string unprintableString;
+
+// SFINAE is currently disabled by default for all compilers.
+// If the non SFINAE version of IsStreamInsertable is ambiguous for you
+// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
+#ifdef CATCH_CONFIG_SFINAE
+
+ template
+ class IsStreamInsertableHelper {
+ template struct TrueIfSizeable : TrueType {};
+
+ template
+ static TrueIfSizeable dummy(T2*);
+ static FalseType dummy(...);
+
+ public:
+ typedef SizedIf type;
+ };
+
+ template
+ struct IsStreamInsertable : IsStreamInsertableHelper::type {};
+
+#else
+
+ struct BorgType {
+ template BorgType( T const& );
+ };
+
+ TrueType& testStreamable( std::ostream& );
+ FalseType testStreamable( FalseType );
+
+ FalseType operator<<( std::ostream const&, BorgType const& );
+
+ template
+ struct IsStreamInsertable {
+ static std::ostream &s;
+ static T const&t;
+ enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
+ };
+
+#endif
+
+#if defined(CATCH_CPP11_OR_GREATER)
+ template::value
+ >
+ struct EnumStringMaker
+ {
+ static std::string convert( T const& ) { return unprintableString; }
+ };
+
+ template
+ struct EnumStringMaker
+ {
+ static std::string convert( T const& v )
+ {
+ return ::Catch::toString(
+ static_cast::type>(v)
+ );
+ }
+ };
+#endif
+ template
+ struct StringMakerBase {
+#if defined(CATCH_CPP11_OR_GREATER)
+ template
+ static std::string convert( T const& v )
+ {
+ return EnumStringMaker::convert( v );
+ }
+#else
+ template
+ static std::string convert( T const& ) { return unprintableString; }
+#endif
+ };
+
+ template<>
+ struct StringMakerBase {
+ template
+ static std::string convert( T const& _value ) {
+ std::ostringstream oss;
+ oss << _value;
+ return oss.str();
+ }
+ };
+
+ std::string rawMemoryToString( const void *object, std::size_t size );
+
+ template
+ inline std::string rawMemoryToString( const T& object ) {
+ return rawMemoryToString( &object, sizeof(object) );
+ }
+
+} // end namespace Detail
+
+template
+struct StringMaker :
+ Detail::StringMakerBase::value> {};
+
+template
+struct StringMaker {
+ template
+ static std::string convert( U* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+template
+struct StringMaker {
+ static std::string convert( R C::* p ) {
+ if( !p )
+ return INTERNAL_CATCH_STRINGIFY( NULL );
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+namespace Detail {
+ template
+ std::string rangeToString( InputIterator first, InputIterator last );
+}
+
+//template
+//struct StringMaker > {
+// static std::string convert( std::vector const& v ) {
+// return Detail::rangeToString( v.begin(), v.end() );
+// }
+//};
+
+template
+std::string toString( std::vector const& v ) {
+ return Detail::rangeToString( v.begin(), v.end() );
+}
+
+#ifdef CATCH_CPP11_OR_GREATER
+
+// toString for tuples
+namespace TupleDetail {
+ template<
+ typename Tuple,
+ std::size_t N = 0,
+ bool = (N < std::tuple_size::value)
+ >
+ struct ElementPrinter {
+ static void print( const Tuple& tuple, std::ostream& os )
+ {
+ os << ( N ? ", " : " " )
+ << Catch::toString(std::get(tuple));
+ ElementPrinter::print(tuple,os);
+ }
+ };
+
+ template<
+ typename Tuple,
+ std::size_t N
+ >
+ struct ElementPrinter {
+ static void print( const Tuple&, std::ostream& ) {}
+ };
+
+}
+
+template