Commit 8e97c163 by Joosep L

Initial

First commit of Android to TUT git
parents
Showing with 11288 additions and 0 deletions
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>
\ No newline at end of file
<component name="CopyrightManager">
<settings default="" />
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/thesis.iml" filepath="$PROJECT_DIR$/thesis.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "ee.ttu.thesis"
minSdkVersion 21
targetSdkVersion 22
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
android {
compileOptions.incremental = false
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
// android
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
//UI
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
compile 'com.google.android.gms:play-services:10.2.0'
compile 'jp.wasabeef:recyclerview-animators:2.2.6'
//rx java
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.9'
compile 'com.jakewharton.rxrelay2:rxrelay:2.0.0'
compile 'uk.co.chrisjenx:calligraphy:2.2.0'
// dependency injection
compile "com.google.dagger:dagger:2.8"
annotationProcessor "com.google.dagger:dagger-compiler:2.8"
provided 'javax.annotation:jsr250-api:1.0'
compile 'javax.inject:javax.inject:1'
compile 'com.jakewharton:butterknife:8.5.1'
// network
compile "com.amitshekhar.android:rx2-android-networking:1.0.0"
//helper
compile 'com.orhanobut:logger:1.15'
compile 'com.github.deano2390:MaterialShowcaseView:1.1.0'
compile ('com.github.worker8:tourguide:1.0.17-SNAPSHOT@aar'){
transitive=true
}
}
apply plugin: 'com.google.gms.google-services'
{
"project_info": {
"project_number": "61076858488",
"project_id": "firebase-thesis"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:61076858488:android:fabc7ea6905e8dc5",
"android_client_info": {
"package_name": "ee.ttu.thesis"
}
},
"oauth_client": [
{
"client_id": "61076858488-u2cg2n8lv0c8280hk7i8krkhu7s4v361.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "61076858488-ksjb18fbta0j2a7e1ac3cg26b93j2mko.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "ee.ttu.thesis",
"certificate_hash": "05de74f702a795d2258f058e26b0ba0c63a49c12"
}
}
],
"api_key": [
{
"current_key": "AIzaSyCCRw2qGiq3JMmE9TL8DtXsmTA9tLRwcZI"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 1
}
}
}
],
"configuration_version": "1"
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/hajola/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 *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package ee.ttu.thesis;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumentation test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("ee.ttu.thesis", appContext.getPackageName());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ee.ttu.thesis">
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<application
android:name=".ThesisApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:hardwareAccelerated="true"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ui.login.LoginActivity"
android:screenOrientation="portrait"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.list.ListActivity"
android:screenOrientation="portrait">
</activity>
<activity
android:name=".ui.start.StartActivity"
android:screenOrientation="portrait">
</activity>
<activity
android:name=".ui.game.GameActivity"
android:screenOrientation="portrait">
</activity>
<activity
android:name=".ui.future.FutureGameActivity"
android:screenOrientation="portrait">
</activity>
<activity
android:name=".ui.past.HistoryActivity"
android:screenOrientation="portrait">
</activity>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCVOu0A8kPjB3jfA09CzqoEwrZ-VAbJuyQ"/>
</application>
</manifest>
\ No newline at end of file
package ee.ttu.thesis;
import android.app.Application;
import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.interceptors.HttpLoggingInterceptor;
import javax.inject.Inject;
import ee.ttu.thesis.data.DataManager;
import ee.ttu.thesis.di.component.ApplicationComponent;
import ee.ttu.thesis.di.component.DaggerApplicationComponent;
import ee.ttu.thesis.di.module.ApplicationModule;
import uk.co.chrisjenx.calligraphy.CalligraphyConfig;
/**
* Created by hajola on 9.05.17.
*/
public class ThesisApp extends Application {
@Inject
DataManager mDataManager;
private ApplicationComponent mApplicationComponent;
@Override
public void onCreate() {
super.onCreate();
mApplicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this)).build();
mApplicationComponent.inject(this);
AndroidNetworking.initialize(getApplicationContext());
if (BuildConfig.DEBUG) {
AndroidNetworking.enableLogging(HttpLoggingInterceptor.Level.BODY);
}
}
public ApplicationComponent getComponent() {
return mApplicationComponent;
}
public void setComponent(ApplicationComponent applicationComponent) {
mApplicationComponent = applicationComponent;
}
}
package ee.ttu.thesis.data;
import android.content.Context;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.CheckIn;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.Message;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.data.model.UserGame;
import ee.ttu.thesis.data.network.ApiHelper;
import ee.ttu.thesis.data.prefs.PreferencesHelper;
import ee.ttu.thesis.di.ApplicationContext;
import io.reactivex.Observable;
/**
* Created by hajola on 9.05.17.
*/
@Singleton
public class AppDataManager implements DataManager {
private final Context mContext;
private final ApiHelper mApiHelper;
private final PreferencesHelper mPreferencesHelper;
@Inject
public AppDataManager(@ApplicationContext Context context,
PreferencesHelper preferencesHelper,
ApiHelper apiHelper) {
mContext = context;
mApiHelper = apiHelper;
mPreferencesHelper = preferencesHelper;
}
@Override
public Observable<List<UserGame>> getUserGames(GamesRequest.UserGamesRequest request) {
return mApiHelper.getUserGames(request);
}
@Override
public Observable<UserGame> addUserToAGame(GamesRequest.AddGameRequest request) {
return mApiHelper.addUserToAGame(request);
}
@Override
public Observable<List<Point>> getPoints(GamesRequest.PointsRequest request) {
return mApiHelper.getPoints(request);
}
@Override
public Observable<CheckInResponse> postCheckIn(CheckIn checkIn) {
return mApiHelper.postCheckIn(checkIn);
}
@Override
public Observable<String> startGame(String userGameId) {
return mApiHelper.startGame(userGameId);
}
@Override
public Observable<List<Game>> getGame(String gameCode) {
return mApiHelper.getGame(gameCode);
}
@Override
public Observable<User> makeUser(String userName, String deviceId) {
return mApiHelper.makeUser(userName, deviceId);
}
@Override
public Observable<String> postMessage(Message request) {
return mApiHelper.postMessage(request);
}
@Override
public Observable<String> postAnswer(Answer answer) {
return mApiHelper.postAnswer(answer);
}
@Override
public int getCurrentUserId() {
return mPreferencesHelper.getCurrentUserId();
}
@Override
public void setCurrentUserId(int userId) {
mPreferencesHelper.setCurrentUserId(userId);
}
}
package ee.ttu.thesis.data;
import ee.ttu.thesis.data.network.ApiHelper;
import ee.ttu.thesis.data.prefs.PreferencesHelper;
/**
* Created by hajola on 9.05.17.
*/
public interface DataManager extends ApiHelper, PreferencesHelper {
}
package ee.ttu.thesis.data.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by hajola on 18.05.17.
*/
public class Answer {
@Expose
@SerializedName("id")
private int id;
@Expose
@SerializedName("user_game")
private int user_game_id;
@Expose
@SerializedName("point")
private int point_id;
@Expose
@SerializedName("problem_type")
private ProblemType problem_type;
@Expose
@SerializedName("given_answer")
private String answer;
@Expose
@SerializedName("is_correct")
private boolean is_correct;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUser_game_id() {
return user_game_id;
}
public void setUser_game_id(int user_game_id) {
this.user_game_id = user_game_id;
}
public int getPoint_id() {
return point_id;
}
public void setPoint_id(int point_id) {
this.point_id = point_id;
}
public ProblemType getProblem_type() {
return problem_type;
}
public void setProblem_type(ProblemType problem_type) {
this.problem_type = problem_type;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public boolean is_correct() {
return is_correct;
}
public void setIs_correct(boolean is_correct) {
this.is_correct = is_correct;
}
public Answer(int user_game_id, int point_id, ProblemType problem_type, String answer, boolean is_correct) {
this.user_game_id = user_game_id;
this.point_id = point_id;
this.problem_type = problem_type;
this.answer = answer;
this.is_correct = is_correct;
}
public Answer(String answer) {
this.answer = answer;
}
public Answer(int point_id, ProblemType problem_type, String answer, boolean is_correct) {
this.point_id = point_id;
this.problem_type = problem_type;
this.answer = answer;
this.is_correct = is_correct;
}
public Answer(int point_id, String answer, boolean is_correct) {
this.point_id = point_id;
this.answer = answer;
this.is_correct = is_correct;
}
public static boolean isAnswerCorrect(Point point, String answer){
for (Solution s : point.getSolutions()) {
if (s.getSolution().equals(answer)) {
return true;
}
}
return false;
}
@Override
public String toString() {
return "vastus: " + answer;
}
}
package ee.ttu.thesis.data.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
import java.util.List;
/**
* Created by hajola on 19.05.17.
*/
public class Bound {
@Expose
@SerializedName("id")
private int id;
@Expose
@SerializedName("notification_text")
private String text;
@Expose
@SerializedName("violated_on")
private Date violated_on;
public Date getViolated_on() {
return violated_on;
}
public void setViolated_on(Date violated_on) {
this.violated_on = violated_on;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
package ee.ttu.thesis.data.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by hajola on 17.05.17.
*/
public class CheckIn {
public CheckIn(int user_game_id, double lat, double lon, int current_point_id, int latest_answer_id) {
this.user_game_id = user_game_id;
this.lat = lat;
this.lon = lon;
this.current_point_id = current_point_id;
this.latest_answer_id = latest_answer_id;
}
public CheckIn(int user_game_id, double lat, double lon, int current_point_id) {
this.user_game_id = user_game_id;
this.lat = lat;
this.lon = lon;
this.current_point_id = current_point_id;
}
@Expose
@SerializedName("user_game_id")
private int user_game_id;
@Expose
@SerializedName("lat")
private double lat;
@Expose
@SerializedName("lon")
private double lon;
@Expose
@SerializedName("current_point_id")
private int current_point_id;
@Expose
@SerializedName("latest_answer_id")
private int latest_answer_id;
public int getUser_game_id() {
return user_game_id;
}
public void setUser_game_id(int user_game_id) {
this.user_game_id = user_game_id;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
public int getCurrent_point_id() {
return current_point_id;
}
public void setCurrent_point_id(int current_point_id) {
this.current_point_id = current_point_id;
}
public int getLatest_answer_id() {
return latest_answer_id;
}
public void setLatest_answer_id(int latest_answer_id) {
this.latest_answer_id = latest_answer_id;
}
}
package ee.ttu.thesis.data.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
import io.reactivex.Observable;
/**
* Created by hajola on 17.05.17.
*/
public class CheckInResponse {
@Expose
@SerializedName("bounds")
private List<Bound> bounds;
@Expose
@SerializedName("messages")
private List<Message> messages;
@Expose
@SerializedName("answer")
private Answer answer;
public List<Bound> getBounds() {
return bounds;
}
public void setBounds(List<Bound> bounds) {
this.bounds = bounds;
}
public List<Message> getMessages() {
return messages;
}
public void setMessages(List<Message> messages) {
this.messages = messages;
}
public Answer getAnswer() {
return answer;
}
public void setAnswer(Answer answer) {
this.answer = answer;
}
}
package ee.ttu.thesis.data.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Created by hajola on 19.05.17.
*/
public class Conversation {
@Expose
@SerializedName("id")
private int id;
@Expose
@SerializedName("user_game")
private int user_game_id;
@Expose
@SerializedName("created_by")
private int user_id;
@Expose
@SerializedName("created_at")
private Date created_at;
@Expose
@SerializedName("messages")
private List<Message> messages;
public Conversation(int id, int user_game_id, int user_id) {
this.id = id;
this.user_game_id = user_game_id;
this.user_id = user_id;
}
public int getId() {
return id;
}
public void addMessage(Message message){
if(messages == null){
messages = new ArrayList<>();
messages.add(message);
}
}
public void setId(int id) {
this.id = id;
}
public int getUser_game_id() {
return user_game_id;
}
public void setUser_game_id(int user_game_id) {
this.user_game_id = user_game_id;
}
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
public Date getCreated_at() {
return created_at;
}
public void setCreated_at(Date created_at) {
this.created_at = created_at;
}
public List<Message> getMessages() {
return messages;
}
public void setMessages(List<Message> messages) {
this.messages = messages;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Conversation that = (Conversation) o;
if (id == that.id) return true;
return false;
}
@Override
public int hashCode() {
int result = id;
return result;
}
}
package ee.ttu.thesis.data.model;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
/**
* Created by hajola on 23.03.17.
*/
public class Game implements Parcelable {
private int userGameId;
public int getUserGameId() {
return userGameId;
}
public void setUserGameId(int userGameId) {
this.userGameId = userGameId;
}
@Expose
@SerializedName("id")
private int id;
@Expose
@SerializedName("title")
private String title;
@SerializedName("game_code")
private String gameCode;
@Expose
@SerializedName("description")
private String description;
@Expose
@SerializedName("location_name")
private String locationName;
@Expose
@SerializedName("max_duration")
private int maxDuration;
@Expose
@SerializedName("start_time")
private Date startTime;
@Expose
@SerializedName("end_time")
private Date endTime;
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getGameCode() {
return gameCode;
}
public void setGameCode(String gameCode) {
this.gameCode = gameCode;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public int getMaxDuration() {
return maxDuration;
}
public void setMaxDuration(int maxDuration) {
this.maxDuration = maxDuration;
}
@Override
public String toString() {
String s = "";
s += "Desciription: " + description;
s += "\ntitle: " + title;
s += "\ngameCode: " + gameCode;
s += "\nstartTime: " + startTime.toString();
return s;
}
public Game() {
}
public boolean isUpcoming(){
Date now = new Date();
Date start = getStartTime();
Date end = getEndTime();
if (start.before(now) && end.after(now)) {
return true;
} else if (start.after(now)) {
return false;
} else {
return false;
}
}
public boolean isCurrent(){
Date now = new Date();
Date start = getStartTime();
Date end = getEndTime();
if (start.before(now) && end.after(now)) {
return true;
} else if (start.after(now)) {
return false;
} else {
return false;
}
}
public boolean isPast(){
Date now = new Date();
Date start = getStartTime();
Date end = getEndTime();
if (start.before(now) && end.after(now)) {
return false;
} else if (start.after(now)) {
return false;
} else {
return true;
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.userGameId);
dest.writeInt(this.id);
dest.writeString(this.title);
dest.writeString(this.gameCode);
dest.writeString(this.description);
dest.writeString(this.locationName);
dest.writeInt(this.maxDuration);
dest.writeLong(this.startTime != null ? this.startTime.getTime() : -1);
dest.writeLong(this.endTime != null ? this.endTime.getTime() : -1);
}
protected Game(Parcel in) {
this.userGameId = in.readInt();
this.id = in.readInt();
this.title = in.readString();
this.gameCode = in.readString();
this.description = in.readString();
this.locationName = in.readString();
this.maxDuration = in.readInt();
long tmpStartTime = in.readLong();
this.startTime = tmpStartTime == -1 ? null : new Date(tmpStartTime);
long tmpEndTime = in.readLong();
this.endTime = tmpEndTime == -1 ? null : new Date(tmpEndTime);
}
public static final Creator<Game> CREATOR = new Creator<Game>() {
@Override
public Game createFromParcel(Parcel source) {
return new Game(source);
}
@Override
public Game[] newArray(int size) {
return new Game[size];
}
};
}
package ee.ttu.thesis.data.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by hajola on 9.05.17.
*/
public class GamesRequest {
private GamesRequest(){
}
public static class UserGamesRequest {
@Expose
@SerializedName("user")
private int user_id;
public UserGamesRequest(int user_id) {
this.user_id = user_id;
}
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
}
public static class PointsRequest {
@Expose
@SerializedName("game")
private int game_id;
public PointsRequest(int game_id) {
this.game_id = game_id;
}
public int getGame_id() {
return game_id;
}
public void setGame_id(int game_id) {
this.game_id = game_id;
}
}
public static class AddGameRequest {
@Expose
@SerializedName("user")
private int user_id;
@Expose
@SerializedName("game_code")
private String game_code;
public AddGameRequest(int user_id, String game_code) {
this.user_id = user_id;
this.game_code = game_code;
}
public String getGame_code() {
return game_code;
}
public void setGame_code(String game_code) {
this.game_code = game_code;
}
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
}
}
package ee.ttu.thesis.data.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
/**
* Created by hajola on 19.05.17.
*/
public class Message {
@Expose
@SerializedName("id")
private int id;
@Expose
@SerializedName("user")
private int user_id;
@Expose
@SerializedName("content")
private String content;
@Expose
@SerializedName("user_game")
private int user_game_id;
public Message(int user_id, String content, int user_game_id) {
this.user_id = user_id;
this.content = content;
this.user_game_id = user_game_id;
}
public int getUser_game_id() {
return user_game_id;
}
public void setUser_game_id(int user_game_id) {
this.user_game_id = user_game_id;
}
public int getUser_id() {
return user_id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
package ee.ttu.thesis.data.model;
import java.util.ArrayList;
import java.util.Date;
import ee.ttu.thesis.ui.game.messages.NotificationAdapter;
/**
* Created by hajola on 19.04.17.
*/
public class Notification {
private int type;
private String text;
private Date time;
public Notification(int type, String text, Date time) {
this.type = type;
this.text = text;
this.time = time;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
// public static ArrayList<Notification> getNotifications() {
// ArrayList<Notification> notifications = new ArrayList<>();
//// notification = new Notification(NotificationAdapter.GAME_UPDATE, "Second point completed!");
//// notifications.add(notification);
// Notification notification = new Notification(NotificationAdapter.HEADER, "You messaged the coordinator");
// notifications.add(notification);
// notification = new Notification(NotificationAdapter.SENT_MESSAGE, "Could we get another hint?");
// notifications.add(notification);
// notification = new Notification(NotificationAdapter.RECEIVED_MESSAGE, "Sure! The same thing that go to the beach to enjoy makes it tick.");
// notifications.add(notification);
// notification = new Notification(NotificationAdapter.SENT_MESSAGE, "Thanks!");
// notifications.add(notification);
// notification = new Notification(NotificationAdapter.REPLY, "");
// notifications.add(notification);
// notification = new Notification(NotificationAdapter.BOUNDS, "You are leaving the game area. There are no points here.");
// notifications.add(notification);
// notification = new Notification(NotificationAdapter.GAME_UPDATE, "Game start");
// notifications.add(notification);
//
//
// return notifications;
// }
}
package ee.ttu.thesis.data.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
import ee.ttu.thesis.utils.Constants;
/**
* Created by hajola on 23.03.17.
*/
public class Point implements Parcelable {
@Expose
@SerializedName("id")
private int id;
@Expose
@SerializedName("game")
private int game_id;
@Expose
@SerializedName("lat")
private double lat;
@Expose
@SerializedName("point_type")
private List<PointType> pointTypes;
@Expose
@SerializedName("lon")
private double lon;
@Expose
@SerializedName("title")
private String title;
@Expose
@SerializedName("question")
private String question;
@Expose
@SerializedName("time_penalty")
private int timePenalty;
@Expose
@SerializedName("hint")
private String hint;
@Expose
@SerializedName("problem_description")
private String problemDescription;
@Expose
@SerializedName("solutions")
private List<Solution> solutions;
@Expose
@SerializedName("description")
private String description;
@Expose
@SerializedName("problem_type")
private ProblemType problemType;
@Expose
@SerializedName("order")
private int order;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getGame_id() {
return game_id;
}
public void setGame_id(int game_id) {
this.game_id = game_id;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getHint() {
return hint;
}
public void setHint(String hint) {
this.hint = hint;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public List<PointType> getPointTypes() {
return pointTypes;
}
public void setPointTypes(List<PointType> pointTypes) {
this.pointTypes = pointTypes;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public int getTimePenalty() {
return timePenalty;
}
public void setTimePenalty(int timePenalty) {
this.timePenalty = timePenalty;
}
public String getProblemDescription() {
return problemDescription;
}
public void setProblemDescription(String problemDescription) {
this.problemDescription = problemDescription;
}
public List<Solution> getSolutions() {
return solutions;
}
public void setSolutions(List<Solution> solutions) {
this.solutions = solutions;
}
public ProblemType getProblemType() {
return problemType;
}
public void setProblemType(ProblemType problemType) {
this.problemType = problemType;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeInt(this.game_id);
dest.writeDouble(this.lat);
dest.writeList(this.pointTypes);
dest.writeDouble(this.lon);
dest.writeString(this.title);
dest.writeString(this.question);
dest.writeInt(this.timePenalty);
dest.writeString(this.hint);
dest.writeString(this.problemDescription);
dest.writeList(this.solutions);
dest.writeString(this.description);
dest.writeParcelable(this.problemType, flags);
dest.writeInt(this.order);
}
public Point() {
}
protected Point(Parcel in) {
this.id = in.readInt();
this.game_id = in.readInt();
this.lat = in.readDouble();
this.pointTypes = new ArrayList<PointType>();
in.readList(this.pointTypes, PointType.class.getClassLoader());
this.lon = in.readDouble();
this.title = in.readString();
this.question = in.readString();
this.timePenalty = in.readInt();
this.hint = in.readString();
this.problemDescription = in.readString();
this.solutions = new ArrayList<Solution>();
in.readList(this.solutions, Solution.class.getClassLoader());
this.description = in.readString();
this.problemType = in.readParcelable(ProblemType.class.getClassLoader());
this.order = in.readInt();
}
public static final Parcelable.Creator<Point> CREATOR = new Parcelable.Creator<Point>() {
@Override
public Point createFromParcel(Parcel source) {
return new Point(source);
}
@Override
public Point[] newArray(int size) {
return new Point[size];
}
};
@Override
public String toString() {
return super.toString();
}
}
package ee.ttu.thesis.data.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.orhanobut.logger.Logger;
import java.io.Console;
/**
* Created by hajola on 17.05.17.
*/
public class PointType implements Parcelable {
public static final String MAP = "MAP";
public static final String DISTANCE = "DST";
public static final String HINT = "HNT";
public static final String COMPASS = "CMP";
@Expose
@SerializedName("title")
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.title);
}
public PointType() {
}
public PointType(String title) {
this.title = title;
}
@Override
public boolean equals(Object obj) {
return obj.equals(title);
}
protected PointType(Parcel in) {
this.title = in.readString();
}
public static final Parcelable.Creator<PointType> CREATOR = new Parcelable.Creator<PointType>() {
@Override
public PointType createFromParcel(Parcel source) {
return new PointType(source);
}
@Override
public PointType[] newArray(int size) {
return new PointType[size];
}
};
}
package ee.ttu.thesis.data.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by hajola on 17.05.17.
*/
public class ProblemType implements Parcelable {
public static final String NFC = "NFC";
public static final String QUIZ = "QUZ";
public static final String QR = "QRC";
public static final String CAMERA = "CAM";
public static final String LOCATION = "LOC";
@Expose
@SerializedName("id")
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Expose
@SerializedName("title")
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public ProblemType() {
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.title);
}
protected ProblemType(Parcel in) {
this.id = in.readInt();
this.title = in.readString();
}
public static final Creator<ProblemType> CREATOR = new Creator<ProblemType>() {
@Override
public ProblemType createFromParcel(Parcel source) {
return new ProblemType(source);
}
@Override
public ProblemType[] newArray(int size) {
return new ProblemType[size];
}
};
}
package ee.ttu.thesis.data.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by hajola on 17.05.17.
*/
public class Solution implements Parcelable {
@Expose
@SerializedName("id")
private int id;
@Expose
@SerializedName("solution")
private String solution;
@Expose
@SerializedName("is_correct_answer")
private boolean isCorrectAnswer;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSolution() {
return solution;
}
public void setSolution(String solution) {
this.solution = solution;
}
public boolean isCorrectAnswer() {
return isCorrectAnswer;
}
public void setCorrectAnswer(boolean correctAnswer) {
isCorrectAnswer = correctAnswer;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.solution);
dest.writeByte(this.isCorrectAnswer ? (byte) 1 : (byte) 0);
}
public Solution() {
}
protected Solution(Parcel in) {
this.id = in.readInt();
this.solution = in.readString();
this.isCorrectAnswer = in.readByte() != 0;
}
public static final Parcelable.Creator<Solution> CREATOR = new Parcelable.Creator<Solution>() {
@Override
public Solution createFromParcel(Parcel source) {
return new Solution(source);
}
@Override
public Solution[] newArray(int size) {
return new Solution[size];
}
};
}
package ee.ttu.thesis.data.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by hajola on 18.05.17.
*/
public class User implements Parcelable {
@Expose
@SerializedName("user_id")
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
}
public User() {
}
protected User(Parcel in) {
this.id = in.readInt();
}
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
@Override
public User createFromParcel(Parcel source) {
return new User(source);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
package ee.ttu.thesis.data.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by hajola on 9.05.17.
*/
public class UserGame {
@Expose
@SerializedName("user_game_id")
private int UserGameId;
@Expose
@SerializedName("game")
private Game game;
public int getUserGameId() {
return UserGameId;
}
public void setUserGameId(int userGameId) {
UserGameId = userGameId;
}
public Game getGame() {
return game;
}
public void setGame(Game game) {
this.game = game;
}
@Override
public String toString() {
return "id: " + UserGameId + " game: " + game.toString();
}
}
package ee.ttu.thesis.data.network;
/**
* Created by hajola on 9.05.17.
*/
public final class ApiEndPoint {
public static final String BASE_URL = "http://128.199.63.125/api";
public static final String ENDPOINT_GET_GAMES = BASE_URL
+ "/user/games";
public static final String ENDPOINT_ADD_USER_GAME = BASE_URL
+ "/game/adduser";
public static final String ENDPOINT_GET_POINTS = BASE_URL
+ "/game/points";
public static final String ENDPOINT_POST_CHECK_IN = BASE_URL
+ "/game/checkin";
public static final String ENDPOINT_START_GAME = BASE_URL
+ "/game/start";
public static final String ENDPOINT_GET_GAME = BASE_URL
+ "/games";
public static final String ENDPOINT_MAKE_USER = BASE_URL
+ "/user/add";
public static final String ENDPOINT_POST_MESSAGE = BASE_URL
+ "/game/message";
public static final String ENDPOINT_POST_ANSWER = BASE_URL
+ "/game/addanswer";
private ApiEndPoint() {
// This class is not publicly instantiable
}
}
package ee.ttu.thesis.data.network;
import java.util.List;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.CheckIn;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.Message;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.data.model.UserGame;
import io.reactivex.Observable;
import javax.inject.Singleton;
/**
* Created by hajola on 9.05.17.
*/
@Singleton
public interface ApiHelper {
Observable<List<UserGame>> getUserGames(GamesRequest.UserGamesRequest request);
Observable<UserGame> addUserToAGame(GamesRequest.AddGameRequest request);
Observable<List<Point>> getPoints(GamesRequest.PointsRequest request);
Observable<CheckInResponse> postCheckIn(CheckIn checkIn);
Observable<String> startGame(String userGameId);
Observable<List<Game>> getGame(String gameCode);
Observable<User> makeUser(String userName, String deviceId);
Observable<String> postMessage(Message request);
Observable<String> postAnswer(Answer answer);
}
package ee.ttu.thesis.data.network;
import com.rx2androidnetworking.Rx2AndroidNetworking;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.CheckIn;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.Message;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.data.model.UserGame;
import io.reactivex.Observable;
/**
* Created by hajola on 9.05.17.
*/
@Singleton
public class AppApiHelper implements ApiHelper {
@Inject
public AppApiHelper() {
}
@Override
public Observable<List<UserGame>> getUserGames(GamesRequest.UserGamesRequest request) {
return Rx2AndroidNetworking.get(ApiEndPoint.ENDPOINT_GET_GAMES)
.addQueryParameter("user", Integer.toString(request.getUser_id()))
.build()
.getObjectListObservable(UserGame.class);
}
@Override
public Observable<UserGame> addUserToAGame(GamesRequest.AddGameRequest request) {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_ADD_USER_GAME)
.addBodyParameter("game_code", request.getGame_code())
.addBodyParameter("user_id", Integer.toString(request.getUser_id()))
.build()
.getObjectObservable(UserGame.class);
}
@Override
public Observable<List<Point>> getPoints(GamesRequest.PointsRequest request) {
return Rx2AndroidNetworking.get(ApiEndPoint.ENDPOINT_GET_POINTS)
.addQueryParameter("game_id", Integer.toString(request.getGame_id()))
.build()
.getObjectListObservable(Point.class);
}
@Override
public Observable<CheckInResponse> postCheckIn(CheckIn request) {
if(request.getLatest_answer_id() != 0 ) {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_POST_CHECK_IN)
.addBodyParameter("user_game_id", Integer.toString(request.getUser_game_id()))
.addBodyParameter("lat", Double.toString(request.getLat()))
.addBodyParameter("lon", Double.toString(request.getLon()))
.addBodyParameter("current_point_id", Integer.toString(request.getCurrent_point_id()))
.addBodyParameter("latest_answer_id", Integer.toString(request.getLatest_answer_id()))
.build()
.getObjectObservable(CheckInResponse.class);
} else{
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_POST_CHECK_IN)
.addBodyParameter("user_game_id", Integer.toString(request.getUser_game_id()))
.addBodyParameter("lat", Double.toString(request.getLat()))
.addBodyParameter("lon", Double.toString(request.getLon()))
.addBodyParameter("current_point_id", Integer.toString(request.getCurrent_point_id()))
.build()
.getObjectObservable(CheckInResponse.class);
}
}
@Override
public Observable<String> startGame(String userGameId) {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_START_GAME)
.addBodyParameter("user_game_id", userGameId)
.build()
.getObjectObservable(String.class);
}
@Override
public Observable<List<Game>> getGame(String gameCode) {
return Rx2AndroidNetworking.get(ApiEndPoint.ENDPOINT_GET_GAME)
.addQueryParameter("game_code", gameCode)
.build()
.getObjectListObservable(Game.class);
}
@Override
public Observable<User> makeUser(String userName, String deviceId) {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_MAKE_USER)
.addBodyParameter("username", userName)
.addBodyParameter("device_id", deviceId)
.build()
.getObjectObservable(User.class);
}
@Override
public Observable<String> postMessage(Message request) {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_POST_MESSAGE)
.addBodyParameter("user_game_id", Integer.toString(request.getUser_game_id()))
.addBodyParameter("user_id", Integer.toString(request.getUser_id()))
.addBodyParameter("content", request.getContent())
.build()
.getObjectObservable(String.class);
}
@Override
public Observable<String> postAnswer(Answer answer) {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_POST_ANSWER)
.addBodyParameter("user_game_id", Integer.toString(answer.getUser_game_id()))
.addBodyParameter("point_id", Integer.toString(answer.getPoint_id()))
.addBodyParameter("problem_type_id", Integer.toString(answer.getProblem_type().getId()))
.addBodyParameter("given_answer", answer.getAnswer())
.addBodyParameter("is_correct", answer.is_correct() ? "1" : "0")
.build()
.getObjectObservable(String.class);
}
}
package ee.ttu.thesis.data.prefs;
import android.content.Context;
import android.content.SharedPreferences;
import javax.inject.Inject;
import javax.inject.Singleton;
import ee.ttu.thesis.di.ApplicationContext;
import ee.ttu.thesis.di.PreferenceInfo;
/**
* Created by hajola on 18.05.17.
*/
@Singleton
public class AppPreferencesHelper implements PreferencesHelper {
private static final String PREF_KEY_CURRENT_USER_ID = "PREFS_KEY_CURRENT_USER_ID";
private final SharedPreferences mPrefs;
@Inject
public AppPreferencesHelper(@ApplicationContext Context context,
@PreferenceInfo String prefFileName) {
mPrefs = context.getSharedPreferences(prefFileName, Context.MODE_PRIVATE);
}
@Override
public int getCurrentUserId() {
int userId = mPrefs.getInt(PREF_KEY_CURRENT_USER_ID, 0);
if(userId == 0)
return 1;
return userId;
}
@Override
public void setCurrentUserId(int userId) {
int id = userId;
mPrefs.edit().putInt(PREF_KEY_CURRENT_USER_ID, id).apply();
}
}
package ee.ttu.thesis.data.prefs;
/**
* Created by hajola on 18.05.17.
*/
public interface PreferencesHelper {
int getCurrentUserId();
void setCurrentUserId(int userId);
}
package ee.ttu.thesis.di;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Qualifier;
/**
* Created by hajola on 9.05.17.
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityContext {
}
package ee.ttu.thesis.di;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Qualifier;
/**
* Created by hajola on 9.05.17.
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ApplicationContext {
}
package ee.ttu.thesis.di;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Scope;
/**
* Created by hajola on 9.05.17.
*/
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {
}
package ee.ttu.thesis.di;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Qualifier;
/**
* Created by hajola on 18.05.17.
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PreferenceInfo {
}
package ee.ttu.thesis.di.component;
import dagger.Component;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.ui.list.ListActivity;
import ee.ttu.thesis.ui.login.LoginActivity;
import ee.ttu.thesis.ui.start.StartActivity;
import ee.ttu.thesis.di.PerActivity;
import ee.ttu.thesis.di.module.ActivityModule;
/**
* Created by hajola on 9.05.17.
*/
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
void inject(ListActivity activity);
void inject(GameActivity activity);
void inject(StartActivity activity);
void inject(LoginActivity activity);
}
package ee.ttu.thesis.di.component;
import android.app.Application;
import android.content.Context;
import javax.inject.Singleton;
import dagger.Component;
import ee.ttu.thesis.ThesisApp;
import ee.ttu.thesis.data.DataManager;
import ee.ttu.thesis.di.ApplicationContext;
import ee.ttu.thesis.di.module.ApplicationModule;
/**
* Created by hajola on 9.05.17.
*/
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(ThesisApp app);
@ApplicationContext
Context context();
Application application();
DataManager getDataManager();
}
\ No newline at end of file
package ee.ttu.thesis.di.module;
import android.app.Activity;
import android.content.Context;
import dagger.Module;
import dagger.Provides;
import ee.ttu.thesis.di.ActivityContext;
import ee.ttu.thesis.di.PerActivity;
import ee.ttu.thesis.ui.game.GamePresenter;
import ee.ttu.thesis.ui.game.GameTreasureHuntPresenter;
import ee.ttu.thesis.ui.list.ListPresenter;
import ee.ttu.thesis.ui.list.ListTreasureHuntPresenter;
import ee.ttu.thesis.ui.login.LoginPresenter;
import ee.ttu.thesis.ui.login.LoginTreasureHuntPresenter;
import ee.ttu.thesis.ui.start.StartPresenter;
import ee.ttu.thesis.ui.start.StartTreasureHuntPresenter;
import ee.ttu.thesis.utils.AppSchedulerProvider;
import ee.ttu.thesis.utils.SchedulerProvider;
import ee.ttu.thesis.ui.game.GameView;
import ee.ttu.thesis.ui.list.ListView;
import ee.ttu.thesis.ui.login.LoginView;
import ee.ttu.thesis.ui.start.StartView;
import io.reactivex.disposables.CompositeDisposable;
/**
* Created by hajola on 9.05.17.
*/
@Module
public class ActivityModule {
private Activity mActivity;
public ActivityModule(Activity activity) {
this.mActivity = activity;
}
@Provides
@ActivityContext
Context provideContext() {
return mActivity;
}
@Provides
Activity provideActivity() {
return mActivity;
}
@Provides
CompositeDisposable provideCompositeDisposable() {
return new CompositeDisposable();
}
@Provides
SchedulerProvider provideSchedulerProvider() {
return new AppSchedulerProvider();
}
@Provides
@PerActivity
ListTreasureHuntPresenter<ListView> provideMainPresenter(ListPresenter<ListView>
presenter) {
return presenter;
}
@Provides
@PerActivity
GameTreasureHuntPresenter<GameView> provideGamePresenter(GamePresenter<GameView>
presenter) {
return presenter;
}
@Provides
@PerActivity
StartTreasureHuntPresenter<StartView> providesStartPresenter(StartPresenter<StartView>
presenter) {
return presenter;
}
@Provides
@PerActivity
LoginTreasureHuntPresenter<LoginView> providesLoginPresenter(LoginPresenter<LoginView>
presenter) {
return presenter;
}
}
package ee.ttu.thesis.di.module;
import android.app.Application;
import android.content.Context;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import ee.ttu.thesis.data.AppDataManager;
import ee.ttu.thesis.data.DataManager;
import ee.ttu.thesis.data.network.ApiHelper;
import ee.ttu.thesis.data.network.AppApiHelper;
import ee.ttu.thesis.data.prefs.AppPreferencesHelper;
import ee.ttu.thesis.data.prefs.PreferencesHelper;
import ee.ttu.thesis.di.ApplicationContext;
import ee.ttu.thesis.di.PreferenceInfo;
/**
* Created by hajola on 9.05.17.
*/
@Module
public class ApplicationModule {
private final Application mApplication;
public ApplicationModule(Application application) {
mApplication = application;
}
@Provides
@ApplicationContext
Context provideContext() {
return mApplication;
}
@Provides
Application provideApplication() {
return mApplication;
}
@Provides
@Singleton
DataManager provideDataManager(AppDataManager appDataManager) {
return appDataManager;
}
@Provides
@Singleton
ApiHelper provideApiHelper(AppApiHelper appApiHelper) {
return appApiHelper;
}
@Provides
@Singleton
PreferencesHelper providePreferencesHelper(AppPreferencesHelper appPreferencesHelper) {
return appPreferencesHelper;
}
@Provides
@PreferenceInfo
String providePreferenceName() {
return "thesis";
}
}
package ee.ttu.thesis.ui.base;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import com.orhanobut.logger.Logger;
import ee.ttu.thesis.R;
import ee.ttu.thesis.ThesisApp;
import ee.ttu.thesis.di.component.ActivityComponent;
import ee.ttu.thesis.di.component.DaggerActivityComponent;
import ee.ttu.thesis.di.module.ActivityModule;
import ee.ttu.thesis.utils.CommonUtils;
import uk.co.chrisjenx.calligraphy.CalligraphyConfig;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
/**
* Created by hajola on 23.04.17.
*/
public abstract class BaseActivity extends AppCompatActivity implements TreasureHuntView {
private ProgressDialog mProgressDialog;
private ActivityComponent mActivityComponent;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivityComponent = DaggerActivityComponent.builder()
.activityModule(new ActivityModule(this))
.applicationComponent(((ThesisApp) getApplication()).getComponent())
.build();
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/lato_regular.ttf")
.setFontAttrId(R.attr.fontPath)
.build()
);
Logger.init();
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
public ActivityComponent getActivityComponent() {
return mActivityComponent;
}
@Override
public void showLoading() {
hideLoading();
mProgressDialog = CommonUtils.showLoadingDialog(this);
}
@Override
public void hideLoading() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.cancel();
}
}
public void hideKeyboard() {
View view = this.getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
\ No newline at end of file
package ee.ttu.thesis.ui.base;
/**
* Created by hajola on 10.05.17.
*/
import com.androidnetworking.common.ANConstants;
import com.androidnetworking.error.ANError;
import javax.inject.Inject;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.DataManager;
import ee.ttu.thesis.utils.Constants;
import ee.ttu.thesis.utils.SchedulerProvider;
import io.reactivex.disposables.CompositeDisposable;
/**
* Base class that implements the Presenter interface and provides a base implementation for
* onAttach() and onDetach(). It also handles keeping a reference to the mvpView that
* can be accessed from the children classes by calling getMvpView().
*/
public class BasePresenter<V extends TreasureHuntView> implements TreauseHuntPresenter<V> {
private final DataManager mDataManager;
private final SchedulerProvider mSchedulerProvider;
private final CompositeDisposable mCompositeDisposable;
private V mThesisView;
@Inject
public BasePresenter(DataManager dataManager,
SchedulerProvider schedulerProvider,
CompositeDisposable compositeDisposable) {
this.mDataManager = dataManager;
this.mSchedulerProvider = schedulerProvider;
this.mCompositeDisposable = compositeDisposable;
}
@Override
public void onAttach(V mvpView) {
mThesisView = mvpView;
}
@Override
public void onDetach() {
mCompositeDisposable.dispose();
mThesisView = null;
}
public boolean isViewAttached() {
return mThesisView != null;
}
public V getmThesisView() {
return mThesisView;
}
public void checkViewAttached() {
if (!isViewAttached()) throw new MvpViewNotAttachedException();
}
public DataManager getDataManager() {
return mDataManager;
}
public SchedulerProvider getSchedulerProvider() {
return mSchedulerProvider;
}
public CompositeDisposable getCompositeDisposable() {
return mCompositeDisposable;
}
@Override
public void handleApiError(ANError error) {
if (error == null || error.getErrorBody() == null) {
getmThesisView().onError(R.string.api_default_error);
return;
}
if (error.getErrorCode() == Constants.API_STATUS_CODE_LOCAL_ERROR
&& error.getErrorDetail().equals(ANConstants.CONNECTION_ERROR)) {
getmThesisView().onError(R.string.connection_error);
return;
}
if (error.getErrorCode() == Constants.API_STATUS_CODE_LOCAL_ERROR
&& error.getErrorDetail().equals(ANConstants.REQUEST_CANCELLED_ERROR)) {
getmThesisView().onError(R.string.api_retry_error);
return;
}
// final GsonBuilder builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
// final Gson gson = builder.create();
//
// try {
// ApiError apiError = gson.fromJson(error.getErrorBody(), ApiError.class);
//
// if (apiError == null || apiError.getMessage() == null) {
// getMvpView().onError(R.string.api_default_error);
// return;
// }
//
// switch (error.getErrorCode()) {
// case HttpsURLConnection.HTTP_UNAUTHORIZED:
// case HttpsURLConnection.HTTP_FORBIDDEN:
// setUserAsLoggedOut();
// getMvpView().openActivityOnTokenExpire();
// case HttpsURLConnection.HTTP_INTERNAL_ERROR:
// case HttpsURLConnection.HTTP_NOT_FOUND:
// default:
// getMvpView().onError(apiError.getMessage());
// }
// } catch (JsonSyntaxException | NullPointerException e) {
// Logger.e("handleApiError", e);
// getMvpView().onError(R.string.api_default_error);
// }
}
public static class MvpViewNotAttachedException extends RuntimeException {
public MvpViewNotAttachedException() {
super("Please call Presenter.onAttach(MvpView) before" +
" requesting data to the Presenter");
}
}
}
package ee.ttu.thesis.ui.base;
/**
* Created by hajola on 9.05.17.
*/
import android.support.annotation.StringRes;
/**
* Base interface that any class that wants to act as a View in the MVP (Model View Presenter)
* pattern must implement. Generally this interface will be extended by a more specific interface
* that then usually will be implemented by an Activity or Fragment.
*/
public interface TreasureHuntView {
void showLoading();
void hideLoading();
void openActivityOnTokenExpire();
void onError(@StringRes int resId);
void onError(String message);
boolean isNetworkConnected();
void hideKeyboard();
}
\ No newline at end of file
package ee.ttu.thesis.ui.base;
/**
* Created by hajola on 10.05.17.
*/
import com.androidnetworking.error.ANError;
import ee.ttu.thesis.ui.base.TreasureHuntView;
/**
* Every presenter in the app must either implement this interface or extend BasePresenter
* indicating the MvpView type that wants to be attached with.
*/
public interface TreauseHuntPresenter<V extends TreasureHuntView> {
void onAttach(V mvpView);
void onDetach();
void handleApiError(ANError error);
}
package ee.ttu.thesis.ui.future;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.view.View;
import android.widget.TextView;
import java.util.Calendar;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.ui.base.BaseActivity;
import ee.ttu.thesis.data.model.Game;
import static ee.ttu.thesis.ui.game.GameActivity.GAME_KEY;
/**
* Created by hajola on 28.04.17.
*/
public class FutureGameActivity extends BaseActivity {
@BindView(R.id.layout_time_to_game_days_TextView)
TextView mDays;
@BindView(R.id.layout_time_to_game_hours_TextView)
TextView mHours;
@BindView(R.id.layout_time_to_game_minutes_TextView)
TextView mMinutes;
@BindView(R.id.layout_time_to_game_seconds_TextView)
TextView mSeconds;
@BindView(R.id.activity_future_game_title)
TextView mTitle;
@BindView(R.id.activity_future_game_description)
TextView mDescription;
Game mGame;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_future_game);
ButterKnife.bind(this);
mGame = getIntent().getParcelableExtra(GAME_KEY);
mTitle.setText(mGame.getTitle());
mDescription.setText(mGame.getDescription());
Calendar cal = Calendar.getInstance(); // creates calendar
cal.setTime(mGame.getStartTime()); // sets calendar time/date
cal.getTime(); // returns new date object, one hour in the future
long difference = cal.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
new CountDownTimer(difference, 1000) {
public void onTick(long millisUntilFinished) {
int seconds = (int) (millisUntilFinished / 1000);
int minutes = seconds / 60;
int hours = minutes / 60;
int days = hours / 24;
mDays.setText(String.format("%02d", days));
hours -= (days*24);
mHours.setText(String.format("%02d", hours));
minutes -= (days*24*60+hours*60);
mMinutes.setText(String.format("%02d", minutes));
seconds -= (days*24*60*60+hours*60*60 + minutes*60);
mSeconds.setText(String.format("%02d", seconds));
}
public void onFinish() {
// mTextField.setText("done!");
}
}.start();
}
@OnClick(R.id.activity_future_game_go_back_textView)
public void onBackClicked(View v){
finish();
}
@Override
public void showLoading() {
}
@Override
public void hideLoading() {
}
@Override
public void openActivityOnTokenExpire() {
}
@Override
public void onError(@StringRes int resId) {
}
@Override
public void onError(String message) {
}
@Override
public boolean isNetworkConnected() {
return false;
}
@Override
public void hideKeyboard() {
}
}
package ee.ttu.thesis.ui.game;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.graphics.PorterDuff;
import android.location.Location;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.orhanobut.logger.Logger;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.Message;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.ui.base.BaseActivity;
import ee.ttu.thesis.data.model.CheckIn;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.ui.game.map.MapFragment;
import ee.ttu.thesis.ui.game.messages.NotificationFragment;
import ee.ttu.thesis.ui.game.point.GameFragment;
import ee.ttu.thesis.ui.list.ListActivity;
import ee.ttu.thesis.utils.RxBus;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
/**
* Created by hajola on 27.03.17.
*/
public class GameActivity extends BaseActivity
implements NfcAdapter.ReaderCallback,
GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks,
LocationListener,
GameView{
@Inject
GameTreasureHuntPresenter<GameView> mPresenter;
public static final String GAME_KEY = "game";
// Keys for storing activity state in the Bundle.
protected final static String KEY_REQUESTING_LOCATION_UPDATES = "requesting-location-updates";
protected final static String KEY_LOCATION = "location";
protected final static String KEY_LAST_UPDATED_TIME_STRING = "last-updated-time-string";
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
public static final String POINT_KEY = "point";
public static final String USER_KEY = "user";
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
protected LocationSettingsRequest mLocationSettingsRequest;
protected Location mCurrentLocation;
protected Boolean mRequestingLocationUpdates = true;
protected Boolean mPausedRequestingLocationUpdates = false;
protected String mLastUpdateTime = "";
@BindView(R.id.activity_game_pager)
ViewPager mViewPager;
@BindView(R.id.activity_game_tablayout)
TabLayout mTabLayout;
Game mGame;
User mUser;
Answer mLatestAnswer = null;
ArrayList<Point> mPoints;
int mCurrentPoint = 0;
NfcAdapter mNfcAdapter;
RxBus _rxBus = null;
CompositeDisposable mDisposables;
ScreenSlidePagerAdapter mPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
getActivityComponent().inject(this);
ButterKnife.bind(this);
mPresenter.onAttach(this);
mGame = getIntent().getParcelableExtra(GAME_KEY);
mUser = getIntent().getParcelableExtra(USER_KEY);
mPresenter.onViewInitialized(new GamesRequest.PointsRequest(mGame.getId()));
updateValuesFromBundle(savedInstanceState);
buildGoogleApiClient();
createLocationRequest();
buildLocationSettingsRequest();
}
public RxBus getRxBusSingleton() {
if (_rxBus == null) {
_rxBus = new RxBus();
}
return _rxBus;
}
/**
* Updates fields based on data stored in the bundle.
*
* @param savedInstanceState The activity state saved in the Bundle.
*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Update the value of mRequestingLocationUpdates from the Bundle, and make sure that
// the Start Updates and Stop Updates buttons are correctly enabled or disabled.
if (savedInstanceState.keySet().contains(KEY_REQUESTING_LOCATION_UPDATES)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
KEY_REQUESTING_LOCATION_UPDATES);
Logger.d("updates: " + mRequestingLocationUpdates);
}
// Update the value of mCurrentLocation from the Bundle and update the UI to show the
// correct latitude and longitude.
if (savedInstanceState.keySet().contains(KEY_LOCATION)) {
// Since KEY_LOCATION was found in the Bundle, we can be sure that mCurrentLocation
// is not null.
mCurrentLocation = savedInstanceState.getParcelable(KEY_LOCATION);
}
// Update the value of mLastUpdateTime from the Bundle and update the UI.
if (savedInstanceState.keySet().contains(KEY_LAST_UPDATED_TIME_STRING)) {
mLastUpdateTime = savedInstanceState.getString(KEY_LAST_UPDATED_TIME_STRING);
}
updateLocationUI();
}
}
private void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.build();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Uses a {@link com.google.android.gms.location.LocationSettingsRequest.Builder} to build
* a {@link com.google.android.gms.location.LocationSettingsRequest} that is used for checking
* if a device has the needed location settings.
*/
protected void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
//Icons
private void setUpTabLayout() {
mTabLayout.getTabAt(0).setIcon(R.drawable.ic_location_on_black_24dp);
mTabLayout.getTabAt(1).setIcon(R.drawable.ic_map_black_24dp);
mTabLayout.getTabAt(2).setIcon(R.drawable.ic_message_black_24dp);
final int unSelectedTabIconColor = ContextCompat.getColor(this, R.color.colorTabUnSelected);
final int SelectedTabIconColor = ContextCompat.getColor(this, R.color.colorTabSelected);
mTabLayout.getTabAt(0).getIcon().setColorFilter(SelectedTabIconColor, PorterDuff.Mode.SRC_IN);
mTabLayout.getTabAt(1).getIcon().setColorFilter(unSelectedTabIconColor, PorterDuff.Mode.SRC_IN);
mTabLayout.getTabAt(2).getIcon().setColorFilter(unSelectedTabIconColor, PorterDuff.Mode.SRC_IN);
mTabLayout.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager) {
@Override
public void onTabSelected(TabLayout.Tab tab) {
super.onTabSelected(tab);
if (tab.getIcon() != null)
tab.getIcon().setColorFilter(SelectedTabIconColor, PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
super.onTabUnselected(tab);
if (tab.getIcon() != null)
tab.getIcon().setColorFilter(unSelectedTabIconColor, PorterDuff.Mode.SRC_IN);
}
});
}
public Location getmCurrentLocation() {
return mCurrentLocation;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
Logger.i("User agreed to make required location settings changes.");
mPausedRequestingLocationUpdates = true;
// Nothing to do. startLocationupdates() gets called in onResume again.
break;
case Activity.RESULT_CANCELED:
Logger.i("User chose not to make required location settings changes.");
Logger.d("false");
Toast.makeText(this, "Please agree to location settings", Toast.LENGTH_LONG).show();
Intent intent = new Intent(GameActivity.this, ListActivity.class);
startActivity(intent);
finish();
mRequestingLocationUpdates = false;
break;
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
Logger.d("true");
mRequestingLocationUpdates = true;
LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
mLocationSettingsRequest
).setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Logger.i("All location settings are satisfied.");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, GameActivity.this);
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Logger.i("Location settings are not satisfied. Attempting to upgrade " +
"location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
status.startResolutionForResult(GameActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Logger.i("PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
String errorMessage = "Location settings are inadequate, and cannot be " +
"fixed here. Fix in Settings.";
Logger.e(errorMessage);
Toast.makeText(GameActivity.this, errorMessage, Toast.LENGTH_LONG).show();
Logger.d("false");
mRequestingLocationUpdates = false;
}
}
});
}
private void updateLocationUI() {
if (mCurrentLocation == null)
return;
if (_rxBus.hasObservers())
_rxBus.send(mCurrentLocation);
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient,
this
).setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
mPausedRequestingLocationUpdates = true;
}
});
}
@Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
_rxBus = getRxBusSingleton();
mDisposables = new CompositeDisposable();
mDisposables.add(_rxBus.asFlowable()
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@Override
public void accept(@io.reactivex.annotations.NonNull Object o) throws Exception {
if (o instanceof Answer) {
((Answer) o).setUser_game_id(mGame.getUserGameId());
if(((Answer) o).is_correct())
mCurrentPoint++;
mLatestAnswer = (Answer) o;
mPresenter.postAnswer((Answer) o);
} else if(o instanceof Message){
mPresenter.postMessage((Message) o);
}
}
}));
}
@Override
protected void onNewIntent(Intent intent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
Logger.d("hello");
String uri = intent.getDataString();
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
for (int i = 0; i < rawMsgs.length; i++) {
Logger.wtf("ndef: " + rawMsgs[i].describeContents());
}
}
}
super.onNewIntent(intent);
}
@Override
protected void onResume() {
super.onResume();
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
mNfcAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS, null);
// Within {@code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates && mPausedRequestingLocationUpdates) {
startLocationUpdates();
mPausedRequestingLocationUpdates = false;
}
}
@Override
protected void onPause() {
super.onPause();
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
mNfcAdapter.disableReaderMode(this);
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
@Override
public void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
mDisposables.clear();
}
@Override
public void onTagDiscovered(Tag tag) {
if (tag != null) {
if (_rxBus.hasObservers())
_rxBus.send(tag);
}
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
@Override
public void onConnected(Bundle connectionHint) {
// If the initial location was never previously requested, we use
// FusedLocationApi.getLastLocation() to get it. If it was previously requested, we store
// its value in the Bundle and check for it in onCreate(). We
// do not request it again unless the user specifically requests location updates by pressing
// the Start Updates button.
//
// Because we cache the value of the initial location in the Bundle, it means that if the
// user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
if (mCurrentLocation == null) {
Logger.d("null");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
Logger.d("return");
return;
}
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
if (mRequestingLocationUpdates) {
Logger.i("in onConnected(), starting location updates");
startLocationUpdates();
}
}
/**
* Callback that fires when the location changes.
*/
@Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
if(mLatestAnswer != null && mLatestAnswer.getId() > 0 && mPoints != null && mPoints.get(mCurrentPoint) != null)
mPresenter.postCheckIn(new CheckIn(mGame.getUserGameId(), location.getLatitude(), location.getLongitude(), mPoints.get(mCurrentPoint).getId(),mLatestAnswer.getId()));
else
mPresenter.postCheckIn(new CheckIn(mGame.getUserGameId(), location.getLatitude(), location.getLongitude(), mPoints.get(mCurrentPoint).getId()));
updateLocationUI();
}
/**
* Stores activity data in the Bundle.
*/
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(KEY_REQUESTING_LOCATION_UPDATES, mRequestingLocationUpdates);
savedInstanceState.putParcelable(KEY_LOCATION, mCurrentLocation);
savedInstanceState.putString(KEY_LAST_UPDATED_TIME_STRING, mLastUpdateTime);
super.onSaveInstanceState(savedInstanceState);
}
@Override
public void onConnectionSuspended(int i) {
Logger.d("Play services connection suspended");
}
/**
* Handles failure to connect to the Google Play services client.
*/
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Logger.d("Play services connection failed: ConnectionResult.getErrorCode() = "
+ connectionResult.getErrorCode());
}
@Override
public void openActivityOnTokenExpire() {
}
@Override
public void onError(@StringRes int resId) {
}
@Override
public void onError(String message) {
}
@Override
public boolean isNetworkConnected() {
return false;
}
@Override
public void hideKeyboard() {
}
@Override
public void loadPoints(List<Point> response) {
mPoints = (ArrayList<Point>) response;
Collections.sort(mPoints, new Comparator<Point>() {
@Override
public int compare(Point p1, Point p2) {
return p1.getOrder()-p2.getOrder();
}
});
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager(), this);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setOffscreenPageLimit(2);
mTabLayout.setupWithViewPager(mViewPager);
setUpTabLayout();
hideLoading();
}
@Override
public void checkInResponse(CheckInResponse checkInResponse) {
if(_rxBus.hasObservers())
_rxBus.send(checkInResponse);
}
@Override
public void messagePosted() {
}
@Override
public void answerPosted(String id) {
mLatestAnswer.setId(Integer.parseInt(id));
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[]{"Point", "Map", "Messages"};
private Context mContext;
public ScreenSlidePagerAdapter(FragmentManager fm, Context context) {
super(fm);
mContext = context;
}
@Override
public Fragment getItem(int position) {
Fragment fragment;
if (position == 0) {
fragment = GameFragment.newInstance(mGame, mPoints);
} else if (position == 1) {
fragment = MapFragment.newInstance(mGame, mPoints);
} else{
fragment = NotificationFragment.newInstance(mGame, mPoints, mUser);
}
return fragment;
}
@Override
public int getCount() {
return PAGE_COUNT;
}
@Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
}
}
\ No newline at end of file
package ee.ttu.thesis.ui.game;
import java.util.List;
import javax.inject.Inject;
import ee.ttu.thesis.data.DataManager;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.CheckIn;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.Message;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.ui.base.BasePresenter;
import ee.ttu.thesis.utils.SchedulerProvider;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
/**
* Created by hajola on 17.05.17.
*/
public class GamePresenter<V extends GameView> extends BasePresenter<V> implements GameTreasureHuntPresenter<V> {
@Inject
public GamePresenter(DataManager dataManager, SchedulerProvider schedulerProvider, CompositeDisposable compositeDisposable) {
super(dataManager, schedulerProvider, compositeDisposable);
}
@Override
public void onViewInitialized(GamesRequest.PointsRequest request) {
getmThesisView().showLoading();
getCompositeDisposable().add(getDataManager()
.getPoints(request)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<List<Point>>() {
@Override
public void accept(@NonNull List<Point> points) throws Exception {;
if (!isViewAttached()) {
getmThesisView().hideLoading();
return;
}
if (points != null) {
getmThesisView().loadPoints(points);
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().hideLoading();
getmThesisView().onError(throwable.getMessage());
}
}));
}
@Override
public void postCheckIn(CheckIn checkIn) {
getCompositeDisposable().add(getDataManager()
.postCheckIn(checkIn)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<CheckInResponse>() {
@Override
public void accept(@NonNull CheckInResponse checkInResponse) throws Exception {
if (!isViewAttached()) {
return;
}
getmThesisView().checkInResponse(checkInResponse);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().onError(throwable.getMessage());
}
}));
}
@Override
public void postMessage(Message request) {
getmThesisView().showLoading();
getCompositeDisposable().add(getDataManager()
.postMessage(request)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
getmThesisView().hideLoading();
if (!isViewAttached()) {
return;
}
getmThesisView().messagePosted();
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().onError(throwable.getMessage());
}
}));
}
@Override
public void postAnswer(Answer answer) {
getmThesisView().showLoading();
getCompositeDisposable().add(getDataManager()
.postAnswer(answer)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
getmThesisView().hideLoading();
if (!isViewAttached()) {
return;
}
getmThesisView().answerPosted(s);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().onError(throwable.getMessage());
}
}));
}
}
package ee.ttu.thesis.ui.game;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.CheckIn;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.Message;
import ee.ttu.thesis.ui.base.TreauseHuntPresenter;
/**
* Created by hajola on 17.05.17.
*/
public interface GameTreasureHuntPresenter<V extends GameView> extends TreauseHuntPresenter<V> {
void onViewInitialized(GamesRequest.PointsRequest request);
void postCheckIn(CheckIn checkIn);
void postMessage(Message request);
void postAnswer(Answer answer);
}
package ee.ttu.thesis.ui.game;
import java.util.List;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.ui.base.TreasureHuntView;
/**
* Created by hajola on 17.05.17.
*/
public interface GameView extends TreasureHuntView {
void loadPoints(List<Point> response);
void checkInResponse(CheckInResponse checkInResponse);
void messagePosted();
void answerPosted(String id);
}
package ee.ttu.thesis.ui.game.map;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MapStyleOptions;
import com.google.android.gms.maps.model.MarkerOptions;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
import java.util.List;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.PointType;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.ui.game.onMapUpdateListener;
import ee.ttu.thesis.utils.RxBus;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import static ee.ttu.thesis.ui.game.GameActivity.GAME_KEY;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
/**
* Created by hajola on 18.04.17.
*/
public class MapFragment extends Fragment implements OnMapReadyCallback {
private CameraPosition mCameraPosition;
private GoogleMap mMap;
private final LatLng mDefaultLocation = new LatLng(59.397212, 24.666660);
private static final int DEFAULT_ZOOM = 12;
private Location mLastKnownLocation;
private boolean isCameraAboveUser = false;
private static final String KEY_CAMERA_POSITION = "camera_position";
private static final String KEY_LOCATION = "location";
Game mGame;
int mCurrentPoint = 0;
RxBus _rxBus;
CompositeDisposable mDisposables;
List<Point> mPoints;
public static MapFragment newInstance(Game game, ArrayList<Point> points) {
Bundle args = new Bundle();
args.putParcelable(GAME_KEY, game);
args.putParcelableArrayList(POINT_KEY, points);
MapFragment fragment = new MapFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onStop() {
super.onStop();
mDisposables.clear();
}
@Override
public void onStart() {
super.onStart();
_rxBus = ((GameActivity) getActivity()).getRxBusSingleton();
mDisposables = new CompositeDisposable();
mDisposables.add(_rxBus.asFlowable()
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
if (o instanceof Location) {
updateLocationUI((Location) o);
} else if(o instanceof Answer){
if(((Answer) o).is_correct()){
mCurrentPoint++;
newPoint();
}
}
}
}));
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_map, container, false);
ButterKnife.bind(this, v);
mGame = getArguments().getParcelable(GAME_KEY);
mPoints = getArguments().getParcelableArrayList(POINT_KEY);
return v;
}
@Override
public void onSaveInstanceState(Bundle outState) {
if (mMap != null) {
outState.putParcelable(KEY_CAMERA_POSITION, mMap.getCameraPosition());
outState.putParcelable(KEY_LOCATION, mLastKnownLocation);
super.onSaveInstanceState(outState);
}
}
private void newPoint() {
Point point = mPoints.get(mCurrentPoint);
if(point.getPointTypes().contains(new PointType("MAP"))){
mMap.clear();
Drawable circleDrawable = getResources().getDrawable(R.drawable.ic_location_on_black_24dp);
BitmapDescriptor markerIcon = getMarkerIconFromDrawable(circleDrawable);
MarkerOptions marker = new MarkerOptions()
.position(new LatLng(point.getLat(), point.getLon()))
.title(point.getTitle())
.snippet(point.getDescription())
.icon(markerIcon);
mMap.addMarker(marker);
getDeviceLocation();
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
try {
MapStyleOptions style = MapStyleOptions.loadRawResourceStyle(getActivity(), R.raw.mapstyle);
mMap.setMapStyle(style);
} catch (Exception e) {
Logger.wtf("Exception " + e.getMessage());
}
newPoint();
}
private BitmapDescriptor getMarkerIconFromDrawable(Drawable drawable) {
Canvas canvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.setColorFilter(getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_IN);
drawable.draw(canvas);
return BitmapDescriptorFactory.fromBitmap(bitmap);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
mLastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION);
mCameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION);
}
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mLastKnownLocation = ((GameActivity) getActivity()).getmCurrentLocation();
if(mLastKnownLocation!= null)
updateLocationUI(mLastKnownLocation);
}
private void getDeviceLocation() {
if (mCameraPosition != null) {
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(mCameraPosition));
} else if (mLastKnownLocation != null) {
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
isCameraAboveUser = true;
} else {
Logger.d("Current location is null. Using defaults.");
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
}
public void updateLocationUI(Location newLocation) {
this.mLastKnownLocation = newLocation;
if(!isCameraAboveUser && mMap != null)
getDeviceLocation();
}
}
package ee.ttu.thesis.ui.game.map;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.google.android.gms.maps.SupportMapFragment;
/**
* Created by hajola on 29.04.17.
*/
public class WorkAroundMapFragment extends SupportMapFragment {
private OnTouchListener mListener;
@Override
public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle savedInstance) {
View layout = super.onCreateView(layoutInflater, viewGroup, savedInstance);
TouchableWrapper frameLayout = new TouchableWrapper(getActivity());
frameLayout.setBackgroundColor(getResources().getColor(android.R.color.transparent));
((ViewGroup) layout).addView(frameLayout,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return layout;
}
public void setListener(OnTouchListener listener) {
mListener = listener;
}
public interface OnTouchListener {
public abstract void onTouch();
}
public class TouchableWrapper extends FrameLayout {
public TouchableWrapper(Context context) {
super(context);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mListener.onTouch();
break;
case MotionEvent.ACTION_UP:
mListener.onTouch();
break;
}
return super.dispatchTouchEvent(event);
}
}
}
\ No newline at end of file
package ee.ttu.thesis.ui.game.messages;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.orhanobut.logger.Logger;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Bound;
import ee.ttu.thesis.data.model.Conversation;
import ee.ttu.thesis.data.model.Message;
import ee.ttu.thesis.data.model.Notification;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.ui.base.BaseActivity;
/**
* Created by hajola on 18.04.17.
*/
public class NotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Object> mObjects;
private BaseActivity mContext;
private User user;
public final static int
BOUNDS = 1,
GAME_UPDATE = 4,
RECEIVED_MESSAGE = 6,
SENT_MESSAGE = 7;
private NotificationFragment mFragment;
public NotificationAdapter(List<Object> mObjects, BaseActivity mContext, NotificationFragment fragment, User user) {
this.mObjects = mObjects;
this.mContext = mContext;
this.mFragment = fragment;
this.user = user;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
RecyclerView.ViewHolder viewHolder;
switch (viewType) {
case SENT_MESSAGE:
View sent_view = inflater.inflate(R.layout.item_game_notification_message_sent, parent, false);
viewHolder = new ViewHolderNotificationMessageSent(sent_view);
break;
case RECEIVED_MESSAGE:
View received_view = inflater.inflate(R.layout.item_game_notification_message_received, parent, false);
viewHolder = new ViewHolderNotificationMessageReceived(received_view);
break;
case BOUNDS:
View bound_view = inflater.inflate(R.layout.item_game_notification, parent, false);
viewHolder = new ViewHolderGameNotification(bound_view);
break;
default:
View notification_view = inflater.inflate(R.layout.item_game_notification, parent, false);
viewHolder = new ViewHolderGameNotification(notification_view);
break;
}
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case SENT_MESSAGE:
ViewHolderNotificationMessageSent viewHolderNotificationMessageSent = (ViewHolderNotificationMessageSent) holder;
configureSentViewHolder(viewHolderNotificationMessageSent, position);
break;
case RECEIVED_MESSAGE:
ViewHolderNotificationMessageReceived viewHolderNotificationMessageReceived = (ViewHolderNotificationMessageReceived) holder;
configureReceivedViewHolder(viewHolderNotificationMessageReceived, position);
break;
case BOUNDS:
ViewHolderGameNotification viewHolderGameNotificationBounds = (ViewHolderGameNotification) holder;
configureBoundsViewHolder(viewHolderGameNotificationBounds, position);
break;
default:
ViewHolderGameNotification viewHolderGameNotification = (ViewHolderGameNotification) holder;
configureNotificationViewHolder(viewHolderGameNotification, position);
break;
}
}
private void configureBoundsViewHolder(final ViewHolderGameNotification viewHolderGameNotification, int position) {
final Bound bound = (Bound) mObjects.get(position);
viewHolderGameNotification.getmMessage().setText(bound.getText());
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
mContext.runOnUiThread(new Runnable() {
@Override
public void run() {
viewHolderGameNotification.getmTime().setText(getTimeDiff(new Date(), bound.getViolated_on()));
}
});
}
}, 0, 60000);
}
private void configureNotificationViewHolder(final ViewHolderGameNotification viewHolderGameNotification, int position) {
final Notification notification = (Notification) mObjects.get(position);
viewHolderGameNotification.getmMessage().setText(notification.getText());
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
mContext.runOnUiThread(new Runnable() {
@Override
public void run() {
viewHolderGameNotification.getmTime().setText(getTimeDiff(new Date(), notification.getTime()));
}
});
}
}, 0, 60000);
}
private void configureReceivedViewHolder(ViewHolderNotificationMessageReceived viewHolderNotificationMessageReceived, int position) {
Message object = (Message) mObjects.get(position);
viewHolderNotificationMessageReceived.getmMessageText().setText(object.getContent());
}
private void configureSentViewHolder(ViewHolderNotificationMessageSent viewHolderNotificationMessageSent, int position) {
Message object = (Message) mObjects.get(position);
viewHolderNotificationMessageSent.getmMessageText().setText(object.getContent());
}
public String getTimeDiff(Date dateOne, Date dateTwo) {
String diff = "";
long timeDiff = Math.abs(dateOne.getTime() - dateTwo.getTime());
diff = String.format("%d minutes ago", TimeUnit.MILLISECONDS.toMinutes(timeDiff) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeDiff)));
return diff;
}
@Override
public int getItemViewType(int position) {
if (mObjects.get(position) instanceof Message && ((Message) mObjects.get(position)).getUser_id() == user.getId())
return SENT_MESSAGE;
else if (mObjects.get(position) instanceof Message)
return RECEIVED_MESSAGE;
else if (mObjects.get(position) instanceof Notification && ((Notification) mObjects.get(position)).getType() == GAME_UPDATE)
return GAME_UPDATE;
else if (mObjects.get(position) instanceof Bound)
return BOUNDS;
else
Logger.d(mObjects.get(position));
throw new IllegalArgumentException("This viewtype does not exist");
}
public void remove(int position) {
mObjects.remove(position);
notifyItemRemoved(position);
}
@Override
public int getItemCount() {
return mObjects.size();
}
}
package ee.ttu.thesis.ui.game.messages;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.Bound;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.Message;
import ee.ttu.thesis.data.model.Notification;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.ui.base.BaseActivity;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.utils.BottomOffsetDecoration;
import ee.ttu.thesis.utils.DeviceDimensionsHelper;
import ee.ttu.thesis.utils.RxBus;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import jp.wasabeef.recyclerview.animators.FadeInRightAnimator;
import static ee.ttu.thesis.ui.game.GameActivity.GAME_KEY;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
import static ee.ttu.thesis.ui.game.GameActivity.USER_KEY;
/**
* Created by hajola on 21.04.17.
*/
public class NotificationFragment extends Fragment {
@BindView(R.id.activity_game_recyclerview)
RecyclerView mRecyclerView;
@BindView(R.id.fragment_notification_editText)
EditText mEditText;
@BindView(R.id.fragment_notification_send)
ImageView mSend;
ArrayList<Object> mShownObjects = new ArrayList<>();
NotificationAdapter mAdapter;
BottomOffsetDecoration mOffsetDecoration;
Game mGame;
User mUser;
int mCurrentPoint = 0;
RxBus _rxBus;
CompositeDisposable mDisposables;
List<Point> mPoints;
public static NotificationFragment newInstance(Game game, ArrayList<Point> points, User user) {
Bundle args = new Bundle();
args.putParcelable(GAME_KEY, game);
args.putParcelable(USER_KEY, user);
args.putParcelableArrayList(POINT_KEY, points);
NotificationFragment fragment = new NotificationFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_notifications, container, false);
ButterKnife.bind(this, v);
mGame = getArguments().getParcelable(GAME_KEY);
mPoints = getArguments().getParcelableArrayList(POINT_KEY);
mUser = getArguments().getParcelable(USER_KEY);
return v;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mShownObjects.add(new Notification(NotificationAdapter.GAME_UPDATE, "Game Start", new Date()));
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
mAdapter = new NotificationAdapter(mShownObjects, (BaseActivity) getActivity(), this, mUser);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(layoutManager);
mOffsetDecoration = new BottomOffsetDecoration(DeviceDimensionsHelper.convertDpToPixel(24, getActivity()), mShownObjects.size());
mRecyclerView.addItemDecoration(mOffsetDecoration);
mRecyclerView.setItemAnimator(new FadeInRightAnimator());
}
@OnClick(R.id.fragment_notification_send)
public void onSendClicked(View view) {
String text = mEditText.getText().toString();
mEditText.setText("");
Message message = new Message(mUser.getId(), text, mGame.getUserGameId());
addMessage(message);
if (_rxBus.hasObservers())
_rxBus.send(message);
}
private void addMessage(Message message) {
mShownObjects.add(message);
mAdapter.notifyItemInserted(mShownObjects.size() - 1);
}
@Override
public void onStop() {
super.onStop();
mDisposables.clear();
}
@Override
public void onStart() {
super.onStart();
_rxBus = ((GameActivity) getActivity()).getRxBusSingleton();
mDisposables = new CompositeDisposable();
mDisposables.add(_rxBus.asFlowable()
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
if (o instanceof Answer) {
mCurrentPoint++;
} else if (o instanceof CheckInResponse) {
// bounds
addBounds(((CheckInResponse) o).getBounds());
// messages
addMessages(((CheckInResponse) o).getMessages());
}
}
}));
}
private void addMessages(List<Message> messages) {
for (Message message : messages) {
mShownObjects.add(message);
mAdapter.notifyItemInserted(mShownObjects.size() - 1);
}
}
private void addBounds(List<Bound> bounds) {
for (Object object : mShownObjects) {
if (object instanceof Bound) {
ListIterator<Bound> iterator = bounds.listIterator();
while (iterator.hasNext()) {
Bound bound = iterator.next();
bound.setViolated_on(new Date());
if (bound.getId() == ((Bound) object).getId()) {
iterator.remove();
}
}
}
}
for (int i = 0; i < bounds.size(); i++) {
bounds.get(i).setViolated_on(new Date());
mShownObjects.add(bounds.get(i));
mAdapter.notifyItemInserted(mShownObjects.size() - 1);
}
}
}
package ee.ttu.thesis.ui.game.messages;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
/**
* Created by hajola on 18.04.17.
*/
public class ViewHolderGameNotification extends RecyclerView.ViewHolder {
@BindView(R.id.item_game_notification_message)
TextView mMessage;
@BindView(R.id.item_game_notification_timeTV)
TextView mTime;
public TextView getmTime() {
return mTime;
}
public void setmTime(TextView mTime) {
this.mTime = mTime;
}
public ViewHolderGameNotification(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public TextView getmMessage() {
return mMessage;
}
public void setmMessage(TextView mMessage) {
this.mMessage = mMessage;
}
}
package ee.ttu.thesis.ui.game.messages;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
/**
* Created by hajola on 23.04.17.
*/
public class ViewHolderNotificationMessageReceived extends RecyclerView.ViewHolder {
@BindView(R.id.item_game_notification_message_received_text)
TextView mMessageText;
@BindView(R.id.item_game_notification_message_received_root)
LinearLayout mContainer;
public ViewHolderNotificationMessageReceived(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public LinearLayout getmContainer() {
return mContainer;
}
public void setmContainer(LinearLayout mContainer) {
this.mContainer = mContainer;
}
public TextView getmMessageText() {
return mMessageText;
}
public void setmMessageText(TextView mMessageText) {
this.mMessageText = mMessageText;
}
}
package ee.ttu.thesis.ui.game.messages;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
/**
* Created by hajola on 23.04.17.
*/
public class ViewHolderNotificationMessageSent extends RecyclerView.ViewHolder {
@BindView(R.id.item_game_notification_message_sent_text)
TextView mMessageText;
@BindView(R.id.item_game_notification_message_sent_root)
LinearLayout mContainer;
public ViewHolderNotificationMessageSent(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public TextView getmMessageText() {
return mMessageText;
}
public void setmMessageText(TextView mMessageText) {
this.mMessageText = mMessageText;
}
public LinearLayout getmContainer() {
return mContainer;
}
public void setmContainer(LinearLayout mContainer) {
this.mContainer = mContainer;
}
}
package ee.ttu.thesis.ui.game;
import android.location.Location;
/**
* Created by hajola on 24.04.17.
*/
public interface onMapUpdateListener {
void onLocationChanged(Location newLocation);
}
package ee.ttu.thesis.ui.game.point;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import com.orhanobut.logger.Logger;
import ee.ttu.thesis.R;
import ee.ttu.thesis.utils.DeviceDimensionsHelper;
public class CompassView extends View {
// setup initial color
private final int paintColor = Color.GREEN;
private int circleColor;
private int centerColor;
private int lineColor;
private int searchColor;
private int textColor;
// defines paint and canvas
private Paint drawPaint;
private Paint textPaint;
private Paint linePaint;
int size; // Size of the customview, a square
int width, height;
int distance = 1000;
int defaultDistance = 500;//size that is described on the compass
int degrees = Integer.MAX_VALUE;
Path line = new Path();
public CompassView(Context context) {
super(context);
}
public CompassView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
circleColor = context.getResources().getColor(R.color.colorCompassCircle);
centerColor = context.getResources().getColor(R.color.colorCompassCenter);
lineColor = context.getResources().getColor(R.color.colorCompassLine);
searchColor = context.getResources().getColor(R.color.colorCompassFinDot);
textColor = context.getResources().getColor(R.color.colorCompassText);
setupPaint();
}
// Setup paint with color and stroke styles
private void setupPaint() {
drawPaint = new Paint();
drawPaint.setColor(circleColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(5);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
textPaint = new Paint();
textPaint.setColor(textColor);
textPaint.setAntiAlias(true);
textPaint.setTextSize(40);
linePaint = new Paint();
linePaint.setFlags(Paint.ANTI_ALIAS_FLAG);
linePaint.setAntiAlias(true);
linePaint.setFilterBitmap(true);
linePaint.setColor(lineColor);
linePaint.setStrokeWidth(1);
linePaint.setStyle(Paint.Style.STROKE);
linePaint.setPathEffect(new DashPathEffect(new float[] {10,5}, 0));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int cx = width/2;
int cy = size/2 + getPaddingTop();
int radius = (size/2);
// circle
drawPaint.setColor(circleColor);
drawPaint.setStrokeWidth(5);
canvas.drawCircle(cx, cy, radius, drawPaint);
// centerdot
drawPaint.setStrokeWidth(20);
drawPaint.setColor(centerColor);
canvas.drawPoint(cx, cy, drawPaint);
// search dot
if(degrees != Integer.MAX_VALUE) {
double newRadius = radius;
if(distance/defaultDistance < 1){
double dividor = ((double) distance)/((double)defaultDistance);
newRadius *= dividor;
}
int y = (int) (-newRadius * Math.cos(Math.toRadians(degrees)));
int x = (int) (newRadius * Math.sin(Math.toRadians(degrees)));
x += cx;
y += cy;
drawPaint.setStrokeWidth(35);
drawPaint.setColor(searchColor);
canvas.drawPoint(x, y, drawPaint);
}
// line
line.moveTo(cx, cy);
line.lineTo(cx+radius, cy);
canvas.drawPath(line, linePaint);
// text
int text_width = (int) textPaint.measureText(defaultDistance + " meters");
canvas.drawText(defaultDistance + " meters", cx + (radius/2 - text_width/2), cy, textPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
size = 0;
width = getMeasuredWidth();
height = getMeasuredHeight();
int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom();
// set the dimensions
if (widthWithoutPadding > heigthWithoutPadding) {
size = heigthWithoutPadding;
} else {
size = widthWithoutPadding;
}
setMeasuredDimension(size + getPaddingLeft() + getPaddingRight(), size + getPaddingTop() + getPaddingBottom());
}
public void updateUI(int degrees, int distance){
this.degrees = degrees;
this.distance = distance;
invalidate();
}
}
package ee.ttu.thesis.ui.game.point;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.Solution;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.utils.RxBus;
import io.reactivex.disposables.CompositeDisposable;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
/**
* Created by hajola on 27.04.17.
*/
public class DialogFragmentSolveQuestion extends DialogFragment {
@BindView(R.id.dialog_question_radiogroup)
RadioGroup mRadioGroup;
@BindView(R.id.dialog_question_title)
TextView mTitle;
Point mPoint;
int correctId;
String correctSolution;
RxBus _rxBus = null;
CompositeDisposable mDisposables;
public static DialogFragmentSolveQuestion newInstance(Point point) {
Bundle args = new Bundle();
args.putParcelable(POINT_KEY, point);
DialogFragmentSolveQuestion fragment = new DialogFragmentSolveQuestion();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.dialog_question, container, false);
ButterKnife.bind(this, v);
mPoint = getArguments().getParcelable(POINT_KEY);
mTitle.setText(mPoint.getQuestion());
for (Solution s : mPoint.getSolutions()) {
RadioButton button = (RadioButton) inflater.inflate(R.layout.item_dialog_question_radiobutton, container, false);
button.setText(s.getSolution());
button.setId(View.generateViewId());
if (s.isCorrectAnswer()) {
correctId = button.getId();
correctSolution = (String) button.getText();
}
mRadioGroup.addView(button);
}
return v;
}
@OnClick(R.id.dialog_question_cancel_button)
public void onCancelClicked(View v) {
dismiss();
}
@OnClick(R.id.dialog_question_submit_button)
public void onSubmitClicked(View v) {
Answer answer = new Answer(mPoint.getId(), mPoint.getProblemType(), correctSolution, correctId == mRadioGroup.getCheckedRadioButtonId());
if ( _rxBus.hasObservers() )
_rxBus.send(answer);
dismiss();
}
@Override
public void onStop() {
super.onStop();
mDisposables.clear();
}
@Override
public void onStart() {
super.onStart();
_rxBus = ((GameActivity) getActivity()).getRxBusSingleton();
mDisposables = new CompositeDisposable();
// mDisposables.add(_rxBus.asFlowable()
// .subscribeOn(AndroidSchedulers.mainThread())
// .subscribe(new Consumer<Object>() {
// @Override
// public void accept(@NonNull Object o) throws Exception {
//
// }
// }));
}
}
package ee.ttu.thesis.ui.game.point;
import android.content.Context;
import android.location.Location;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Vibrator;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.maps.model.LatLng;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.PointType;
import ee.ttu.thesis.data.model.ProblemType;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.utils.RxBus;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import static ee.ttu.thesis.ui.game.GameActivity.GAME_KEY;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
import static java.lang.Math.atan2;
import static java.lang.Math.cos;
import static java.lang.Math.sin;
/**
* Created by hajola on 21.04.17.
* https://github.com/googlesamples/android-play-location/blob/master/LocationUpdates/app/src/main/java/com/google/android/gms/location/sample/locationupdates/MainActivity.java
*/
public class GameFragment extends Fragment {
@BindView(R.id.fragment_solve_point_title)
TextView mTitle;
@BindView(R.id.fragment_solve_point_order)
TextView mOrder;
@BindView(R.id.fragment_solve_point_description)
TextView mDescription;
TextView mDistance;
CompassView mCompassView;
@BindView(R.id.fragment_compass_hint_root)
LinearLayout mHintRoot;
@BindView(R.id.fragment_compass_compass_root)
LinearLayout mCompassRoot;
@BindView(R.id.fragment_compass_distance_root)
LinearLayout mDistanceRoot;
TextView mHintView;
@BindView(R.id.fragment_howtosolvecontent)
FrameLayout mSolveContent;
Game mGame;
Location mLastKnownLocation = null;
int mCurrentPoint = 0;
RxBus _rxBus;
CompositeDisposable mDisposables;
List<Point> mPoints;
public static GameFragment newInstance(Game game, ArrayList<Point> points) {
Bundle args = new Bundle();
args.putParcelable(GAME_KEY, game);
args.putParcelableArrayList(POINT_KEY, points);
GameFragment fragment = new GameFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_game, container, false);
ButterKnife.bind(this, v);
mGame = getArguments().getParcelable(GAME_KEY);
mPoints = getArguments().getParcelableArrayList(POINT_KEY);
return v;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
displayNewPoint();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mLastKnownLocation = ((GameActivity) getActivity()).getmCurrentLocation();
insertHowToSolveFragment();
if (mLastKnownLocation != null)
updateLocationUI(mLastKnownLocation);
}
private void insertHowToSolveFragment() {
Fragment fragment = null;
switch (mPoints.get(mCurrentPoint).getProblemType().getTitle()) {
case ProblemType.NFC:
fragment = GameNFCFragment.newInstance(mPoints.get(mCurrentPoint));
break;
case ProblemType.LOCATION:
fragment = GameLocationFragment.newInstance(mPoints.get(mCurrentPoint));
break;
case ProblemType.QUIZ:
fragment = GameLocationFragment.newInstance(mPoints.get(mCurrentPoint));
break;
case ProblemType.CAMERA:
fragment = GamePhotoFragment.newInstance(mPoints.get(mCurrentPoint));
break;
case ProblemType.QR:
fragment = GameQRFragment.newInstance(mPoints.get(mCurrentPoint));
break;
}
FragmentTransaction ft = getChildFragmentManager().beginTransaction();
ft.replace(R.id.fragment_howtosolvecontent, fragment);
ft.commit();
}
@Override
public void onStop() {
super.onStop();
mDisposables.clear();
}
@Override
public void onStart() {
super.onStart();
_rxBus = ((GameActivity) getActivity()).getRxBusSingleton();
mDisposables = new CompositeDisposable();
mDisposables.add(_rxBus.asFlowable()
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
if (o instanceof Location) {
updateLocationUI((Location) o);
} else if (o instanceof Answer) {
if (((Answer) o).is_correct()) {
onPointCompleted();
} else {
onWrongAnswer();
}
} else if (o instanceof CheckInResponse) {
}
}
}));
}
private void updateLocationUI(Location mCurrentLocation) {
mLastKnownLocation = mCurrentLocation;
if (mLastKnownLocation != null && mPoints.get(mCurrentPoint) != null) {
LatLng point2 = new LatLng(mLastKnownLocation.getLatitude(), mLastKnownLocation.getLongitude());
LatLng point = new LatLng(mPoints.get(mCurrentPoint).getLat(), mPoints.get(mCurrentPoint).getLon());
double lat1 = point.latitude;
double lon1 = point.longitude;
double lat2 = point2.latitude;
double lon2 = point2.longitude;
double y = Math.sin(lon2 - lon1) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1);
Location loc1 = new Location("");
loc1.setLatitude(lat1);
loc1.setLongitude(lon1);
Location loc2 = new Location("");
loc2.setLatitude(lat2);
loc2.setLongitude(lon2);
int distanceInMeters = (int) loc1.distanceTo(loc2);
int degrees = (int) Math.toDegrees(atan2(y, x));
if (degrees < 0) {
degrees += 360;
}
if (mDistance != null)
mDistance.setText("" + distanceInMeters + " meters away from the point ");
if (mCompassView != null)
mCompassView.updateUI(degrees, distanceInMeters);
}
}
private void displayNewPoint() {
Point point = mPoints.get(mCurrentPoint);
if (!point.getPointTypes().contains(new PointType(PointType.HINT))) {
mHintRoot.removeAllViews();
mHintView = null;
} else {
if ( mHintView == null) {
mHintView = (TextView) getActivity().getLayoutInflater().inflate(R.layout.layout_hint, null);
mHintRoot.addView(mHintView);
}
mHintView.setText(mPoints.get(mCurrentPoint).getHint());
}
if (!point.getPointTypes().contains((new PointType(PointType.COMPASS)))) {
mCompassRoot.removeAllViews();
mCompassView = null;
} else {
if ( mCompassView == null) {
mCompassView = (CompassView) getActivity().getLayoutInflater().inflate(R.layout.layout_compass, null);
mCompassRoot.addView(mCompassView);
}
}
if (!point.getPointTypes().contains((new PointType(PointType.DISTANCE)))) {
mDistanceRoot.removeAllViews();
mDistance = null;
} else {
if ( mDistance == null) {
mDistance = (TextView) getActivity().getLayoutInflater().inflate(R.layout.layout_distance, null);
mDistanceRoot.addView(mDistance);
}
}
mTitle.setText(mPoints.get(mCurrentPoint).getTitle());
mOrder.setText(mPoints.get(mCurrentPoint).getOrder() + " / " + mPoints.size());
mDescription.setText(mPoints.get(mCurrentPoint).getDescription());
insertHowToSolveFragment();
}
public void onPointCompleted() {
try {
final MediaPlayer mp = MediaPlayer.create(getActivity(), R.raw.success);
mp.start();
} catch (Exception e) {
e.printStackTrace();
}
if (mPoints.size() - 1 <= mCurrentPoint) {
// TODO WON GAME
Toast.makeText(getActivity(), "Game won!", Toast.LENGTH_SHORT).show();
} else {
mCurrentPoint++;
displayNewPoint();
}
}
public void onWrongAnswer() {
}
}
package ee.ttu.thesis.ui.game.point;
import android.graphics.PorterDuff;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.view.View;
import com.orhanobut.logger.Logger;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.ProblemType;
import ee.ttu.thesis.utils.DeviceDimensionsHelper;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
/**
* Created by hajola on 27.04.17.
*/
public class GameLocationFragment extends SolveFragment {
public static GameLocationFragment newInstance(Point point) {
Bundle args = new Bundle();
args.putParcelable(POINT_KEY, point);
GameLocationFragment fragment = new GameLocationFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onIconClicked(v);
}
});
}
@Override
public void onStart() {
super.onStart();
mDisposables.add(_rxBus.asFlowable()
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
if (o instanceof Location) {
}
}
}));
}
@Override
public void onStop() {
super.onStop();
mDisposables.clear();
}
@OnClick(R.id.fragment_solve_icon)
public void onIconClicked(View v) {
Logger.d("LocationClicked");
if (mPoint.getProblemType().getTitle().equals(ProblemType.QUIZ)) {
onAskAQuestion();
} else {
Answer answer = new Answer(mPoint.getId(), mPoint.getProblemType(), "automaatne", true);
if (_rxBus.hasObservers())
_rxBus.send(answer);
}
}
private void onAskAQuestion() {
mIcon.setImageDrawable(getResources().getDrawable(R.drawable.ic_create_black_24dp));
mIcon.setBackground(getActivity().getResources().getDrawable(R.drawable.circle_login_icons));
mInstructions.setText(mPoint.getProblemDescription());
mIcon.setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.DST_OUT);
mIcon.setElevation(DeviceDimensionsHelper.convertDpToPixel(4, getActivity()));
mIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
displayQuestionnaire();
}
});
mInstructions.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
displayQuestionnaire();
}
});
}
private void displayQuestionnaire() {
FragmentManager fm = getChildFragmentManager();
DialogFragmentSolveQuestion dialogFragmentSolveQuestion = DialogFragmentSolveQuestion.newInstance(mPoint);
dialogFragmentSolveQuestion.show(fm, "fragment_location_questionnaire");
}
}
\ No newline at end of file
package ee.ttu.thesis.ui.game.point;
import android.nfc.NdefMessage;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.widget.Toast;
import com.orhanobut.logger.Logger;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.utils.RxBus;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
/**
* Created by hajola on 25.04.17.
*/
public class GameNFCFragment extends SolveFragment {
public static GameNFCFragment newInstance(Point point) {
Bundle args = new Bundle();
args.putParcelable(POINT_KEY, point);
GameNFCFragment fragment = new GameNFCFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onStart() {
super.onStart();
mDisposables.add(_rxBus.asFlowable()
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
if (o instanceof Tag) {
onNewNFCTag((Tag) o);
}
}
}));
}
@Override
public void onStop() {
super.onStop();
mDisposables.clear();
}
public void onNewNFCTag(Tag tag) {
Logger.d("TAG: " + tag.toString());
Answer answer = new Answer(mPoint.getId(), mPoint.getProblemType(), tag.toString(), Answer.isAnswerCorrect(mPoint, tag.toString()));
if(_rxBus.hasObservers())
_rxBus.send(answer);
}
}
package ee.ttu.thesis.ui.game.point;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Toast;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Point;
import static android.app.Activity.RESULT_OK;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
/**
* Created by hajola on 27.04.17.
*/
public class GamePhotoFragment extends SolveFragment {
static final int REQUEST_IMAGE_CAPTURE = 1;
public static GamePhotoFragment newInstance(Point point) {
Bundle args = new Bundle();
args.putParcelable(POINT_KEY, point);
GamePhotoFragment fragment = new GamePhotoFragment();
fragment.setArguments(args);
return fragment;
}
@OnClick(R.id.fragment_solve_icon)
public void onIconClicked(View v) {
dispatchTakePictureIntent();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Toast.makeText(getActivity(), "Mängujuht hindaks pilti (oota 4s)", Toast.LENGTH_LONG).show();
onPhotoTaken();
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// mOnPointCompletedListener.onPointCompleted();
}
}, 4000);
}
}
public void onPhotoTaken() {
// mOnPointCompletedListener.onWrongAnswer();
mInstructions.setText("Please wait");
mIcon.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mInstructions.setText("Please wait");
mIcon.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
}
}, 6000);
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
package ee.ttu.thesis.ui.game.point;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.view.View;
import com.orhanobut.logger.Logger;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Point;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
public class GameQRFragment extends SolveFragment {
public static GameQRFragment newInstance(Point point) {
Bundle args = new Bundle();
args.putParcelable(POINT_KEY, point);
GameQRFragment fragment = new GameQRFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onStart() {
super.onStart();
}
@OnClick(R.id.fragment_solve_icon)
public void onIconClicked(View v) {
FragmentManager fm = getChildFragmentManager();
QRScannerDialogFragment qrScannerDialogFragment = QRScannerDialogFragment.newInstance(mPoint);
qrScannerDialogFragment.show(fm, "fragment_qr_scanner");
}
}
\ No newline at end of file
package ee.ttu.thesis.ui.game.point;
import android.Manifest;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.orhanobut.logger.Logger;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.utils.QRDataListener;
import ee.ttu.thesis.utils.QRReader;
import ee.ttu.thesis.utils.RxBus;
import io.reactivex.disposables.CompositeDisposable;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
/**
* Created by hajola on 26.04.17.
*/
public class QRScannerDialogFragment extends DialogFragment {
@BindView(R.id.dialog_qr_scanner_camera_view)
SurfaceView mCameraView;
@BindView(R.id.dialog_qr_scanner_cancel_button)
Button mCancelButton;
QRReader mQrReader;
Point mPoint;
RxBus _rxBus = null;
boolean answerSent = false;
CompositeDisposable mDisposables;
public static QRScannerDialogFragment newInstance(Point point) {
Bundle args = new Bundle();
args.putParcelable(POINT_KEY, point);
QRScannerDialogFragment fragment = new QRScannerDialogFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.dialog_qr_scanner, container, false);
ButterKnife.bind(this, v);
mPoint = getArguments().getParcelable(POINT_KEY);
return v;
}
@Override
public void onStop() {
super.onStop();
mDisposables.clear();
}
@Override
public void onStart() {
super.onStart();
_rxBus = ((GameActivity) getActivity()).getRxBusSingleton();
mDisposables = new CompositeDisposable();
// mDisposables.add(_rxBus.asFlowable()
// .subscribeOn(AndroidSchedulers.mainThread())
// .subscribe(new Consumer<Object>() {
// @Override
// public void accept(@NonNull Object o) throws Exception {
//
// }
// }));
}
@OnClick(R.id.dialog_qr_scanner_cancel_button)
public void onCancelClicked(View v) {
dismiss();
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Logger.d( "view created: ");
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.CAMERA},
1);
mQrReader = new QRReader.Builder(getActivity(), mCameraView, new QRDataListener() {
@Override
public void onDetected(final String data) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if(!answerSent) {
answerSent = true;
Answer answer = new Answer(mPoint.getId(), mPoint.getProblemType(), data, Answer.isAnswerCorrect(mPoint, data));
if (_rxBus.hasObservers())
_rxBus.send(answer);
}
dismiss();
}
});
}
}).facing(QRReader.BACK_CAM)
.enableAutofocus(true)
.height(mCameraView.getHeight())
.width(mCameraView.getWidth())
.build();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onResume() {
super.onResume();
mQrReader.initAndStart(mCameraView);
}
@Override
public void onPause() {
super.onPause();
mQrReader.releaseAndCleanup();
}
}
package ee.ttu.thesis.ui.game.point;
import android.content.Context;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Answer;
import ee.ttu.thesis.data.model.CheckInResponse;
import ee.ttu.thesis.data.model.Point;
import ee.ttu.thesis.data.model.ProblemType;
import ee.ttu.thesis.data.model.Solution;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.utils.DeviceDimensionsHelper;
import ee.ttu.thesis.utils.RxBus;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import static ee.ttu.thesis.ui.game.GameActivity.POINT_KEY;
/**
* Created by hajola on 28.04.17.
*/
public class SolveFragment extends Fragment implements onAnswerGivenListener {
@BindView(R.id.fragment_solve_instructions_textView)
TextView mInstructions;
@BindView(R.id.fragment_solve_icon)
ImageView mIcon;
@BindView(R.id.progressBar_wrong_answer)
ProgressBar mProgressBar;
Point mPoint;
RxBus _rxBus = null;
CompositeDisposable mDisposables;
boolean isUserWaitingForAnswer = false;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_solve, container, false);
ButterKnife.bind(this, v);
_rxBus = ((GameActivity) getActivity()).getRxBusSingleton();
mPoint = getArguments().getParcelable(POINT_KEY);
switch (mPoint.getProblemType().getTitle()) {
case (ProblemType.NFC):
mIcon.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.ic_nfc));
mIcon.setBackground(getActivity().getResources().getDrawable(R.drawable.circle_solve_not_button));
mInstructions.setText(getResources().getString(R.string.solve_nfc));
break;
case (ProblemType.QR):
mIcon.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.ic_qrcode_scan));
mIcon.setBackground(getActivity().getResources().getDrawable(R.drawable.circle_login_icons));
mIcon.setElevation(DeviceDimensionsHelper.convertDpToPixel(6, getActivity()));
mIcon.setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.SRC_IN);
mInstructions.setText(getResources().getString(R.string.solve_qr));
break;
case (ProblemType.QUIZ): // Kuni joutakse lahedale, on search ikoon
mIcon.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.ic_search_black_24dp));
mIcon.setBackground(getActivity().getResources().getDrawable(R.drawable.circle_solve_not_button));
mInstructions.setText(getResources().getString(R.string.solve_location));
break;
case (ProblemType.LOCATION):
mIcon.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.ic_search_black_24dp));
mIcon.setBackground(getActivity().getResources().getDrawable(R.drawable.circle_solve_not_button));
mInstructions.setText(getResources().getString(R.string.solve_location));
break;
case (ProblemType.CAMERA):
mIcon.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.ic_photo_camera_black_24dp));
mIcon.setBackground(getActivity().getResources().getDrawable(R.drawable.circle_login_icons));
mIcon.setColorFilter(getResources().getColor(R.color.white), PorterDuff.Mode.DST_OUT);
mIcon.setElevation(DeviceDimensionsHelper.convertDpToPixel(6, getActivity()));
mInstructions.setText(getResources().getString(R.string.solve_photo));
break;
}
return v;
}
@Override
public void onStop() {
super.onStop();
mDisposables.clear();
}
@Override
public void onStart() {
super.onStart();
_rxBus = ((GameActivity) getActivity()).getRxBusSingleton();
mDisposables = new CompositeDisposable();
mDisposables.add(_rxBus.asFlowable()
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
@Override
public void accept(@NonNull Object o) throws Exception {
if (o instanceof CheckInResponse) {
if (isUserWaitingForAnswer && ((CheckInResponse) o).getAnswer().getProblem_type().getTitle().equals(ProblemType.CAMERA))
onWrongAnswer(((CheckInResponse) o).getAnswer());
}
}
}));
}
@Override
public void onAnswered(Answer answer) {
if (answer.getProblem_type().getTitle().equals(ProblemType.CAMERA))
isUserWaitingForAnswer = true;
if (_rxBus.hasObservers())
_rxBus.send(answer);
for (Solution s : mPoint.getSolutions()) {
if (s.getSolution().equals(answer.getAnswer())) {
if (s.isCorrectAnswer()) {
return;
}
}
}
onWrongAnswer(answer);
}
private void onWrongAnswer(Answer answer) {
isUserWaitingForAnswer = false;
mInstructions.setText(getActivity().getResources().getString(R.string.solve_wrong_answer, mPoint.getTimePenalty()));
Vibrator v = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(500);
mIcon.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mInstructions.setText(getActivity().getResources().getString(R.string.solve_try_again));
mIcon.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
}
}, mPoint.getTimePenalty());
}
}
package ee.ttu.thesis.ui.game.point;
import ee.ttu.thesis.data.model.Answer;
/**
* Created by hajola on 27.04.17.
*/
public interface onAnswerGivenListener {
void onAnswered(Answer answer);
}
package ee.ttu.thesis.ui.list;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import ee.ttu.thesis.R;
/**
* Created by hajola on 18.04.17.
*/
public class AddGameDialogFragment extends DialogFragment implements TextView.OnEditorActionListener {
@BindView(R.id.dialog_enter_new_game_editText)
EditText mEditText;
@BindView(R.id.dialog_add_new_game_cancel_button)
Button mCancel;
@BindView(R.id.dialog_add_new_game_ok_button)
Button mOk;
public interface OnGameAddListener {
void onFinishEditDialog(String gameName);
}
public AddGameDialogFragment() {
}
public static AddGameDialogFragment newInstance() {
Bundle args = new Bundle();
AddGameDialogFragment fragment = new AddGameDialogFragment();
fragment.setArguments(args);
return fragment;
}
@OnClick(R.id.dialog_add_new_game_cancel_button)
public void onCancelClicked(View v){
dismiss();
}
@OnClick(R.id.dialog_add_new_game_ok_button)
public void onOkClicked(View v){
OnGameAddListener listener = (OnGameAddListener) getActivity();
listener.onFinishEditDialog(mEditText.getText().toString());
dismiss();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.dialog_enter_new_game, container);
ButterKnife.bind(this, v);
return v;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mEditText.setOnEditorActionListener(this);
mEditText.requestFocus();
getDialog().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (EditorInfo.IME_ACTION_DONE == actionId) {
// Return input text back to activity through the implemented listener
OnGameAddListener listener = (OnGameAddListener) getActivity();
listener.onFinishEditDialog(mEditText.getText().toString());
// Close the dialog and return back to the parent activity
dismiss();
return true;
}
return false;
}
}
package ee.ttu.thesis.ui.list;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.text.SimpleDateFormat;
import java.util.List;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.ui.list.ViewHolderGamesCategory;
import ee.ttu.thesis.ui.list.ViewHolderGamesGame;
/**
* Created by hajola on 23.03.17.
*/
public class GamesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Object> mObjects;
private Context mContext;
public final static int CATEGORY_TITLE = 0, GAME = 1;
public GamesAdapter(List<Object> mObjects, Context mContext) {
this.mObjects = mObjects;
this.mContext = mContext;
}
public Context getContext() {
return mContext;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
RecyclerView.ViewHolder viewHolder;
switch (viewType) {
case CATEGORY_TITLE:
View category_view = inflater.inflate(R.layout.item_game_category, parent, false);
viewHolder = new ViewHolderGamesCategory(category_view);
break;
case GAME:
View game_view = inflater.inflate(R.layout.item_game, parent, false);
viewHolder = new ViewHolderGamesGame(game_view);
break;
default:
View default_view = inflater.inflate(R.layout.item_game_category, parent, false);
viewHolder = new ViewHolderGamesCategory(default_view);
break;
}
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()){
case CATEGORY_TITLE:
ViewHolderGamesCategory viewHolderGamesCategory = (ViewHolderGamesCategory) holder;
configureCategoryViewHolder(viewHolderGamesCategory, position);
break;
case GAME:
ViewHolderGamesGame viewHolderGamesGame = (ViewHolderGamesGame) holder;
configureGameViewHolder(viewHolderGamesGame , position);
break;
}
}
private void configureGameViewHolder(ViewHolderGamesGame viewHolderGamesGame, int position) {
Game game = (Game)mObjects.get(position);
viewHolderGamesGame.getGameNameTV().setText(game.getTitle());
viewHolderGamesGame.getGameLocationTV().setText("@"+game.getLocationName());
if(position == 1){
viewHolderGamesGame.getGameTimeTV().setText("• Now");
viewHolderGamesGame.getGameTimeTV().setTextColor(getContext().getResources().getColor(R.color.colorAccent));
}else{
SimpleDateFormat dateFormatter = new SimpleDateFormat("E, d-M-y");
viewHolderGamesGame.getGameTimeTV().setText(dateFormatter.format(game.getStartTime()));
}
}
private void configureCategoryViewHolder(ViewHolderGamesCategory viewHolderGamesCategory, int position) {
if(position == 0)
viewHolderGamesCategory.getCategoryTextView().setText(mObjects.get(position).toString());
else
viewHolderGamesCategory.getCategoryTextView().setText(mObjects.get(position).toString());
}
@Override
public int getItemViewType(int position) {
if(mObjects.get(position) instanceof String)
return CATEGORY_TITLE;
else
return GAME;
}
@Override
public int getItemCount() {
return mObjects.size();
}
}
package ee.ttu.thesis.ui.list;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.FragmentManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.ui.base.BaseActivity;
import ee.ttu.thesis.ui.future.FutureGameActivity;
import ee.ttu.thesis.ui.past.HistoryActivity;
import ee.ttu.thesis.ui.start.StartActivity;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.UserGame;
import ee.ttu.thesis.utils.DividerDecoration;
import ee.ttu.thesis.utils.ItemClickSupport;
import static ee.ttu.thesis.ui.game.GameActivity.GAME_KEY;
import static ee.ttu.thesis.ui.game.GameActivity.USER_KEY;
/**
* Created by hajola on 22.03.17.
*/
public class ListActivity extends BaseActivity implements AddGameDialogFragment.OnGameAddListener, ListView {
@Inject
ListTreasureHuntPresenter<ListView> mPresenter;
@BindView(R.id.activity_main_recyclerview)
RecyclerView mRecyclerView;
ArrayList<Object> mObjects = new ArrayList<>();
GamesAdapter mAdapter;
List<UserGame> mUserGames = new ArrayList<>();
User mUser;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActivityComponent().inject(this);
ButterKnife.bind(this);
mPresenter.onAttach(this);
mPresenter.onViewInitialized(new GamesRequest.UserGamesRequest(1));
mUser = getIntent().getParcelableExtra(USER_KEY);
mAdapter = new GamesAdapter(mObjects, this);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
RecyclerView.ItemDecoration itemDecoration = new
DividerDecoration(this, getResources().getColor(R.color.colorPrimaryLight), 1f);
mRecyclerView.addItemDecoration(itemDecoration);
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(
new ItemClickSupport.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
if (mObjects.get(position) instanceof Game) {
Game game = (Game) mObjects.get(position);
Date now = new Date();
Date start = game.getStartTime();
Date end = game.getEndTime();
if (start.before(now) && end.after(now)) {
Intent intent = new Intent(ListActivity.this, StartActivity.class);
intent.putExtra(GAME_KEY, ((Game) mObjects.get(position)));
intent.putExtra(USER_KEY, mUser);
startActivity(intent);
finish();
} else if (start.after(now)) {
Intent intent = new Intent(ListActivity.this, FutureGameActivity.class);
intent.putExtra(GAME_KEY, ((Game) mObjects.get(position)));
startActivity(intent);
} else {
Intent intent = new Intent(ListActivity.this, HistoryActivity.class);
intent.putExtra(GAME_KEY, ((Game) mObjects.get(position)));
intent.putExtra(USER_KEY, mUser);
startActivity(intent);
}
}
}
}
);
}
@OnClick(R.id.floatingActionButton)
public void onFabClick(View v) {
FragmentManager fm = getSupportFragmentManager();
AddGameDialogFragment addGameDialogFragment = AddGameDialogFragment.newInstance();
addGameDialogFragment.show(fm, "fragment_add_game");
}
@Override
public void onFinishEditDialog(String gameName) {
Toast.makeText(this, gameName, Toast.LENGTH_SHORT).show();
mPresenter.onAddGame(new GamesRequest.AddGameRequest(1, gameName));
}
@Override
public void openActivityOnTokenExpire() {
}
@Override
public void onError(@StringRes int resId) {
}
@Override
public void onError(String message) {
Toast.makeText(this, "ERROR: " + message, Toast.LENGTH_LONG).show();
}
@Override
public boolean isNetworkConnected() {
return false;
}
@Override
public void hideKeyboard() {
}
@Override
public void loadGames(List<UserGame> response) {
Logger.d("response length: " + response.size());
mUserGames = response;
Date now = new Date();
int upcoming = 0;
int past = 0;
boolean _bcurrent = false;
boolean _bupcoming = false;
boolean _bpast = false;
for (UserGame u : response) {
Game g = u.getGame();
g.setUserGameId(u.getUserGameId());
Date start = g.getStartTime();
Date end = g.getEndTime();
if (start.before(now) && end.after(now)) {
mObjects.add(0, g);
upcoming++;
past++;
_bcurrent = true;
} else if (start.after(now)) {
past++;
_bupcoming = true;
mObjects.add(upcoming, g);
} else {
_bpast = true;
mObjects.add(past, g);
}
}
if(_bpast)
mObjects.add(past, "Past");
if(_bupcoming)
mObjects.add(upcoming, "Upcoming");
if(_bcurrent)
mObjects.add(0, "Current");
mAdapter.notifyDataSetChanged();
}
@Override
public void addGame(UserGame response) {
Date now = new Date();
Game game = response.getGame();
game.setUserGameId(response.getUserGameId());
Date start = game.getStartTime();
Date end = game.getEndTime();
if (start.before(now) && end.after(now)) {
mObjects.add(0, game);
mObjects.add(0, "Current");
} else if (start.after(now)) {
// upcoming
for (Object o : mObjects) {
if (o instanceof String) {
if (o.equals("Upcoming")) {
mObjects.add(mObjects.indexOf(o), game);
mAdapter.notifyDataSetChanged();
return;
}
if (o.equals("Past")) {
mObjects.add(mObjects.indexOf(o), game);
mObjects.add(mObjects.indexOf(o), "Upcoming");
mAdapter.notifyDataSetChanged();
return;
}
}
}
mObjects.add(mObjects.size(), "Upcoming");
mObjects.add(mObjects.size(), game);
} else {
// past
for (Object o : mObjects) {
if (o instanceof String) {
if (o.equals("Past")) {
mObjects.add(mObjects.indexOf(o), game);
mAdapter.notifyDataSetChanged();
return;
}
}
mObjects.add(mObjects.size(), "Past");
mObjects.add(mObjects.size(), game);
}
}
mAdapter.notifyDataSetChanged();
}
}
package ee.ttu.thesis.ui.list;
import java.util.List;
import javax.inject.Inject;
import ee.ttu.thesis.data.DataManager;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.UserGame;
import ee.ttu.thesis.ui.base.BasePresenter;
import ee.ttu.thesis.utils.SchedulerProvider;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
/**
* Created by hajola on 10.05.17.
*/
public class ListPresenter<V extends ListView> extends BasePresenter<V> implements ListTreasureHuntPresenter<V> {
@Inject
public ListPresenter(DataManager dataManager, SchedulerProvider schedulerProvider, CompositeDisposable compositeDisposable) {
super(dataManager, schedulerProvider, compositeDisposable);
}
@Override
public void onViewInitialized(GamesRequest.UserGamesRequest request) {
getmThesisView().showLoading();
getCompositeDisposable().add(getDataManager()
.getUserGames(request)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<List<UserGame>>() {
@Override
public void accept(@NonNull List<UserGame> userGames) throws Exception {
getmThesisView().hideLoading();
if (!isViewAttached()) {
return;
}
if (userGames != null) {
getmThesisView().loadGames(userGames);
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().hideLoading();
getmThesisView().onError(throwable.getMessage());
}
}));
}
@Override
public void onAddGame(GamesRequest.AddGameRequest request) {
getmThesisView().showLoading();
getCompositeDisposable().add(getDataManager()
.addUserToAGame(request)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<UserGame>() {
@Override
public void accept(@NonNull UserGame userGame) throws Exception {
getmThesisView().hideLoading();
if (!isViewAttached()) {
return;
}
if (userGame != null) {
getmThesisView().addGame(userGame);
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().hideLoading();
getmThesisView().onError(throwable.getMessage());
}
}));
}
}
package ee.ttu.thesis.ui.list;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.di.PerActivity;
import ee.ttu.thesis.ui.base.TreauseHuntPresenter;
/**
* Created by hajola on 10.05.17.
*/
@PerActivity
public interface ListTreasureHuntPresenter<V extends ListView> extends TreauseHuntPresenter<V> {
void onViewInitialized(GamesRequest.UserGamesRequest userGamesRequest);
void onAddGame(GamesRequest.AddGameRequest userGamesRequest);
}
package ee.ttu.thesis.ui.list;
import java.util.List;
import ee.ttu.thesis.data.model.UserGame;
import ee.ttu.thesis.ui.base.TreasureHuntView;
/**
* Created by hajola on 9.05.17.
*/
public interface ListView extends TreasureHuntView {
void loadGames(List<UserGame> response);
void addGame(UserGame response);
}
package ee.ttu.thesis.ui.list;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
/**
* Created by hajola on 16.04.17.
*/
public class ViewHolderGamesCategory extends RecyclerView.ViewHolder {
@BindView(R.id.item_game_category_textView)
TextView categoryTextView;
public ViewHolderGamesCategory(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public TextView getCategoryTextView() {
return categoryTextView;
}
public void setCategoryTextView(TextView categoryTextView) {
this.categoryTextView = categoryTextView;
}
}
\ No newline at end of file
package ee.ttu.thesis.ui.list;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
/**
* Created by hajola on 16.04.17.
*/
public class ViewHolderGamesGame extends RecyclerView.ViewHolder {
@BindView(R.id.item_game_linearlayout)
View rootView;
@BindView(R.id.item_game_gamename_textview)
TextView gameNameTV;
@BindView(R.id.item_game_time_textView)
TextView gameTimeTV;
@BindView(R.id.item_game_location_textview)
TextView gameLocationTV;
public ViewHolderGamesGame(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public View getRootView() {
return rootView;
}
public void setRootView(View rootView) {
this.rootView = rootView;
}
public TextView getGameNameTV() {
return gameNameTV;
}
public void setGameNameTV(TextView gameNameTV) {
this.gameNameTV = gameNameTV;
}
public TextView getGameTimeTV() {
return gameTimeTV;
}
public void setGameTimeTV(TextView gameTimeTV) {
this.gameTimeTV = gameTimeTV;
}
public TextView getGameLocationTV() {
return gameLocationTV;
}
public void setGameLocationTV(TextView gameLocationTV) {
this.gameLocationTV = gameLocationTV;
}
}
package ee.ttu.thesis.ui.login;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.OptionalPendingResult;
import com.google.android.gms.common.api.ResultCallback;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.ui.base.BaseActivity;
import ee.ttu.thesis.ui.list.ListActivity;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.UserGame;
import ee.ttu.thesis.ui.start.StartActivity;
import ee.ttu.thesis.utils.CommonUtils;
import ee.ttu.thesis.utils.DeviceDimensionsHelper;
import static ee.ttu.thesis.ui.game.GameActivity.GAME_KEY;
import static ee.ttu.thesis.ui.game.GameActivity.USER_KEY;
public class LoginActivity extends BaseActivity implements GoogleApiClient.OnConnectionFailedListener, LoginView {
private GoogleApiClient mGoogleApiClient;
private static final int RC_SIGN_IN = 9001;
@Inject
LoginTreasureHuntPresenter<LoginView> mPresenter;
String gameCode = "";
String userName = "";
Game mGame;
User mUser;
boolean isGameReady = false;
@BindView(R.id.signInButton_activity_login_google)
View mGoogleSignInButton;
@BindView(R.id.activity_login_game_code_editText)
EditText mGameCodeET;
@BindView(R.id.activity_login_user_name_editText)
EditText mUserNameET;
@BindView(R.id.activity_login_enter_button)
Button mEnterButton;
@BindView(R.id.activity_login_game_title_header)
TextView mHeader;
@BindView(R.id.activity_login_progressbar)
ProgressBar mProgressBar;
@BindView(R.id.activity_login_jointheadventure)
TextView mJoinTheAdventure;
@BindView(R.id.activity_login_game_title)
TextView mGameTitle;
@BindView(R.id.activity_login_gameInfo)
TextView mInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
getActivityComponent().inject(this);
ButterKnife.bind(this);
mPresenter.onAttach(this);
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestId()
.requestIdToken(getString(R.string.server_client_id))
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
mGameCodeET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
gameCode = s.toString();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
gameCode = s.toString();
if (gameCode.length() == 0) {
loadGame(null);
} else {
mPresenter.getGame(gameCode);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
mUserNameET.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
userName = s.toString();
if(userName.length() > 0 && mGame != null && mGame.isCurrent())
elevateEnter(true);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
userName = s.toString();
if(userName.length() == 0)
elevateEnter(false);
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@OnClick(R.id.activity_login_enter_button)
public void onEnterClicked(View v){
if(isGameReady){
mPresenter.makeUser(userName, CommonUtils.getDeviceId(this));
} else {
}
}
@Override
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d("LoginActivity", "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
// showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
@Override
public void onResult(GoogleSignInResult googleSignInResult) {
// hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
// TODO something
}
@OnClick(R.id.signInButton_activity_login_google)
public void onGoogleSignInClicked(View signInButton) {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
private void handleSignInResult(GoogleSignInResult result) {
Log.d("LoginActivity", "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
String idToken = acct.getIdToken();
// TODO(user): send token to server and validate server-side
goToGame(true);
} else {
// Signed out, show unauthenticated UI.
// goToGame(false, null;
}
}
private void goToGame(boolean isRegisterdUser){
if(isRegisterdUser){
mUser = new User();
mUser.setId(1);
Intent intent = new Intent(this, ListActivity.class);
intent.putExtra(USER_KEY, mUser);
startActivity(intent);
finish();
} else {
Intent intent = new Intent(this, StartActivity.class);
intent.putExtra(GAME_KEY, mGame);
intent.putExtra(USER_KEY, mUser);
startActivity(intent);
finish();
}
}
@Override
public void showLoading() {
mProgressBar.setVisibility(View.VISIBLE);
mJoinTheAdventure.setVisibility(View.INVISIBLE);
mHeader.setVisibility(View.INVISIBLE);
mGameTitle.setVisibility(View.INVISIBLE);
}
private void elevateEnter(boolean elevate) {
isGameReady = elevate;
if (elevate) {
mEnterButton.setBackground(getResources().getDrawable(R.drawable.login_rounded_rectangle_filled));
mEnterButton.setTextColor(getResources().getColor(R.color.white));
mEnterButton.setElevation(DeviceDimensionsHelper.convertDpToPixel(6, LoginActivity.this));
} else {
mEnterButton.setBackground(getResources().getDrawable(R.drawable.rounded_rectangle));
mEnterButton.setTextColor(getResources().getColor(R.color.colorPrimaryLight));
mEnterButton.setElevation(DeviceDimensionsHelper.convertDpToPixel(0, LoginActivity.this));
}
}
@Override
public void hideLoading() {
mProgressBar.setVisibility(View.INVISIBLE);
}
@Override
public void openActivityOnTokenExpire() {
}
@Override
public void onError(@StringRes int resId) {
}
@Override
public void onError(String message) {
mJoinTheAdventure.setVisibility(View.VISIBLE);
mHeader.setVisibility(View.INVISIBLE);
mGameTitle.setVisibility(View.INVISIBLE);
mInfo.setVisibility(View.INVISIBLE);
}
@Override
public boolean isNetworkConnected() {
return false;
}
@Override
public void hideKeyboard() {
}
@Override
public void loadGame(List<Game> games) {
if (games == null || games.size() < 1) {
mJoinTheAdventure.setVisibility(View.VISIBLE);
mHeader.setVisibility(View.INVISIBLE);
mGameTitle.setVisibility(View.INVISIBLE);
mInfo.setVisibility(View.INVISIBLE);
elevateEnter(false);
return;
}
Date now = new Date();
Game game = games.get(0);
mGame = game;
Date start = game.getStartTime();
Date end = game.getEndTime();
if (start.before(now) && end.after(now)) {
mInfo.setVisibility(View.INVISIBLE);
if(userName.length() > 0)
elevateEnter(true);
} else if (start.after(now)) {
mInfo.setText("The game has not yet started.");
mInfo.setVisibility(View.VISIBLE);
elevateEnter(false);
} else {
mInfo.setText("Sadly, the game has already ended.\nOur apologies :(");
mInfo.setVisibility(View.VISIBLE);
elevateEnter(false);
}
mJoinTheAdventure.setVisibility(View.INVISIBLE);
mHeader.setVisibility(View.VISIBLE);
mGameTitle.setVisibility(View.VISIBLE);
mGameTitle.setText(games.get(0).getTitle());
}
@Override
public void userAdded(User user) {
mUser = user;
mPresenter.saveUser(user);
mPresenter.addUserToAGame(new GamesRequest.AddGameRequest(user.getId(), gameCode));
}
@Override
public void showLargeLoading() {
super.hideKeyboard();
super.showLoading();
}
@Override
public void hideLargeLoading() {
super.hideLoading();
}
@Override
public void gameAdded(UserGame userGame) {
mGame = userGame.getGame();
mGame.setUserGameId(userGame.getUserGameId());
goToGame(false);
}
}
package ee.ttu.thesis.ui.login;
import java.util.List;
import javax.inject.Inject;
import ee.ttu.thesis.data.DataManager;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.data.model.UserGame;
import ee.ttu.thesis.ui.base.BasePresenter;
import ee.ttu.thesis.utils.SchedulerProvider;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
/**
* Created by hajola on 18.05.17.
*/
public class LoginPresenter<V extends LoginView> extends BasePresenter<V> implements LoginTreasureHuntPresenter<V> {
@Inject
public LoginPresenter(DataManager dataManager, SchedulerProvider schedulerProvider, CompositeDisposable compositeDisposable) {
super(dataManager, schedulerProvider, compositeDisposable);
}
@Override
public void getGame(String gameCode) {
getmThesisView().showLoading();
getCompositeDisposable().add(getDataManager()
.getGame(gameCode)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<List<Game>>() {
@Override
public void accept(@NonNull List<Game> games) throws Exception {
getmThesisView().hideLoading();
if (!isViewAttached()) {
return;
}
getmThesisView().loadGame(games);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().hideLoading();
getmThesisView().onError(throwable.getMessage());
}
}));
}
@Override
public void makeUser(String userName, String deviceId) {
getmThesisView().showLargeLoading();
getCompositeDisposable().add(getDataManager()
.makeUser(userName, deviceId)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<User>() {
@Override
public void accept(@NonNull User user) throws Exception {
if (!isViewAttached()) {
getmThesisView().hideLargeLoading();
return;
}
getmThesisView().userAdded(user);
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().hideLargeLoading();
getmThesisView().onError(throwable.getMessage());
}
}));
}
@Override
public void addUserToAGame(GamesRequest.AddGameRequest request) {
getmThesisView().showLargeLoading();
getCompositeDisposable().add(getDataManager()
.addUserToAGame(request)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<UserGame>() {
@Override
public void accept(@NonNull UserGame userGame) throws Exception {
getmThesisView().hideLargeLoading();
if (!isViewAttached()) {
return;
}
if (userGame != null) {
getmThesisView().gameAdded(userGame);
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().hideLargeLoading();
getmThesisView().onError(throwable.getMessage());
}
}));
}
@Override
public void saveUser(User user) {
getDataManager().setCurrentUserId(user.getId());
}
}
package ee.ttu.thesis.ui.login;
import ee.ttu.thesis.data.model.GamesRequest;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.ui.base.TreauseHuntPresenter;
/**
* Created by hajola on 18.05.17.
*/
public interface LoginTreasureHuntPresenter<V extends LoginView> extends TreauseHuntPresenter<V> {
void getGame(String gameCode);
void makeUser(String userName, String deviceId);
void addUserToAGame(GamesRequest.AddGameRequest request);
void saveUser(User user);
}
package ee.ttu.thesis.ui.login;
import java.util.List;
import ee.ttu.thesis.data.model.Game;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.data.model.UserGame;
import ee.ttu.thesis.ui.base.TreasureHuntView;
/**
* Created by hajola on 18.05.17.
*/
public interface LoginView extends TreasureHuntView {
void loadGame(List<Game> game);
void userAdded(User user);
void showLargeLoading();
void hideLargeLoading();
void gameAdded(UserGame userGame);
}
package ee.ttu.thesis.ui.past;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.widget.ScrollView;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.JointType;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MapStyleOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.google.android.gms.maps.model.RoundCap;
import com.orhanobut.logger.Logger;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
import ee.ttu.thesis.ui.base.BaseActivity;
import ee.ttu.thesis.ui.game.map.WorkAroundMapFragment;
/**
* Created by hajola on 29.04.17.
*/
public class HistoryActivity extends BaseActivity
implements OnMapReadyCallback,
GoogleMap.OnPolylineClickListener {
GoogleMap mMap;
@BindView(R.id.activity_history_scrollview)
ScrollView mScrollView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
ButterKnife.bind(this);
WorkAroundMapFragment mapFragment = (WorkAroundMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.getUiSettings().setZoomControlsEnabled(true);
try {
MapStyleOptions style = MapStyleOptions.loadRawResourceStyle(this, R.raw.mapstyle);
mMap.setMapStyle(style);
} catch (Exception e) {
Logger.wtf("Exception " + e.getMessage());
}
((WorkAroundMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.setListener(new WorkAroundMapFragment.OnTouchListener() {
@Override
public void onTouch() {
mScrollView.requestDisallowInterceptTouchEvent(true);
}
});
// a single polyline. Read the rest of the tutorial to learn more.
Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
.add(
new LatLng(-35.016, 143.321),
new LatLng(-34.747, 145.592),
new LatLng(-34.364, 147.891),
new LatLng(-33.501, 150.217),
new LatLng(-32.306, 149.248),
new LatLng(-32.491, 147.309)));
// Position the map's camera near Alice Springs in the center of Australia,
// and set the zoom factor so most of Australia shows on the screen.
polyline1.setEndCap(new RoundCap());
polyline1.setColor(getResources().getColor(R.color.colorAccent));
polyline1.setJointType(JointType.ROUND);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-23.684, 133.903), 4));
// Set listeners for click events.
googleMap.setOnPolylineClickListener(this);
}
@Override
public void onPolylineClick(Polyline polyline) {
}
@Override
public void showLoading() {
}
@Override
public void hideLoading() {
}
@Override
public void openActivityOnTokenExpire() {
}
@Override
public void onError(@StringRes int resId) {
}
@Override
public void onError(String message) {
}
@Override
public boolean isNetworkConnected() {
return false;
}
@Override
public void hideKeyboard() {
}
}
package ee.ttu.thesis.ui.start;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.Toast;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.User;
import ee.ttu.thesis.ui.base.BaseActivity;
import ee.ttu.thesis.ui.game.GameActivity;
import ee.ttu.thesis.data.model.Game;
import static ee.ttu.thesis.ui.game.GameActivity.GAME_KEY;
import static ee.ttu.thesis.ui.game.GameActivity.USER_KEY;
/**
* Created by hajola on 23.04.17.
*/
public class StartActivity extends BaseActivity implements StartView {
@Inject
StartTreasureHuntPresenter<StartView> mPresenter;
Game mGame;
User mUser;
@BindView(R.id.activity_start_viewpager)
ViewPager mPager;
@BindView(R.id.activity_start_tablayout)
TabLayout mTabLayout;
ScreenSlidePagerAdapter mPagerAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
getActivityComponent().inject(this);
ButterKnife.bind(this);
mPresenter.onAttach(this);
mGame = getIntent().getParcelableExtra(GAME_KEY);
mUser = getIntent().getParcelableExtra(USER_KEY);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager(), this);
mPager.setAdapter(mPagerAdapter);
mTabLayout.setupWithViewPager(mPager, true);
}
@OnClick(R.id.activity_start_button)
public void onStartClicked(View v){
mPresenter.startGame(Integer.toString(mGame.getUserGameId()));
}
@Override
public void openActivityOnTokenExpire() {
}
@Override
public void onError(@StringRes int resId) {
}
@Override
public void onError(String message) {
Toast.makeText(this, "Something went wrong: " + message, Toast.LENGTH_LONG).show();
}
@Override
public boolean isNetworkConnected() {
return false;
}
@Override
public void hideKeyboard() {
}
@Override
public void gameStarted() {
Intent intent = new Intent(StartActivity.this, GameActivity.class);
intent.putExtra(GAME_KEY, mGame);
intent.putExtra(USER_KEY, mUser);
startActivity(intent);
finish();
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 5;
private Context mContext;
public ScreenSlidePagerAdapter(FragmentManager fm, Context context) {
super(fm);
mContext = context;
}
@Override
public Fragment getItem(int position) {
Fragment fragment;
if (position == 0) {
fragment = TutorialIntroFragment.newInstance(mGame);
} else if (position == 1) {
fragment = TutorialIntroFragment.newInstance(mGame);
} else{
fragment = TutorialIntroFragment.newInstance(mGame);
}
return fragment;
}
@Override
public int getCount() {
return PAGE_COUNT;
}
@Override
public CharSequence getPageTitle(int position) {
return "";
}
}
}
package ee.ttu.thesis.ui.start;
import javax.inject.Inject;
import ee.ttu.thesis.data.DataManager;
import ee.ttu.thesis.ui.base.BasePresenter;
import ee.ttu.thesis.utils.SchedulerProvider;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
/**
* Created by hajola on 18.05.17.
*/
public class StartPresenter<V extends StartView> extends BasePresenter<V> implements StartTreasureHuntPresenter<V> {
@Inject
public StartPresenter(DataManager dataManager, SchedulerProvider schedulerProvider, CompositeDisposable compositeDisposable) {
super(dataManager, schedulerProvider, compositeDisposable);
}
@Override
public void startGame(String userGameId) {
getmThesisView().showLoading();
getCompositeDisposable().add(getDataManager()
.startGame(userGameId)
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
getmThesisView().gameStarted();
}
}, new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
getmThesisView().hideLoading();
getmThesisView().onError(throwable.getMessage());
}
}));
}
}
package ee.ttu.thesis.ui.start;
import ee.ttu.thesis.ui.base.TreauseHuntPresenter;
/**
* Created by hajola on 18.05.17.
*/
public interface StartTreasureHuntPresenter<V extends StartView> extends TreauseHuntPresenter<V> {
void startGame(String userGameId);
}
\ No newline at end of file
package ee.ttu.thesis.ui.start;
import ee.ttu.thesis.ui.base.TreasureHuntView;
/**
* Created by hajola on 18.05.17.
*/
public interface StartView extends TreasureHuntView {
void gameStarted();
}
package ee.ttu.thesis.ui.start;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import ee.ttu.thesis.R;
import ee.ttu.thesis.data.model.Game;
import static ee.ttu.thesis.ui.game.GameActivity.GAME_KEY;
/**
* Created by hajola on 14.05.17.
*/
public class TutorialIntroFragment extends Fragment {
Game mGame;
@BindView(R.id.fragment_tutorial_intro_title)
TextView mTitle;
@BindView(R.id.fragment_tutorial_intro_description)
TextView mDescription;
@BindView(R.id.fragment_tutorial_intro_numbofpoints)
TextView mPointsNumber;
@BindView(R.id.fragment_tutorial_intro_limitedTime)
TextView mWarning;
public static TutorialIntroFragment newInstance(Game game) {
Bundle args = new Bundle();
args.putParcelable(GAME_KEY, game);
TutorialIntroFragment fragment = new TutorialIntroFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_tutorial_intro, container, false);
ButterKnife.bind(this, v);
mGame = getArguments().getParcelable(GAME_KEY);
return v;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mTitle.setText(mGame.getTitle());
mDescription.setText(mGame.getDescription());
// mPointsNumber.setText(mGame.getTitle());
if(mGame.getMaxDuration() == 0){
mWarning.setText("");
} else {
mWarning.setText("Once you press the Start button, you have "+mGame.getMaxDuration()+" minutes to find all the points.");
}
}
}
package ee.ttu.thesis.utils;
import io.reactivex.Scheduler;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created by hajola on 9.05.17.
*/
public class AppSchedulerProvider implements SchedulerProvider {
@Override
public Scheduler ui() {
return AndroidSchedulers.mainThread();
}
@Override
public Scheduler computation() {
return Schedulers.computation();
}
@Override
public Scheduler io() {
return Schedulers.io();
}
}
\ No newline at end of file
package ee.ttu.thesis.utils;
import android.content.Context;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
/**
* Created by hajola on 26.04.17.
*/
class BarcodeDetectorHolder {
private static BarcodeDetector detector;
/**
* Gets barcode detector.
*
* @param context
* the context
* @return the barcode detector
*/
static BarcodeDetector getBarcodeDetector(Context context) {
if (detector == null) {
detector = new BarcodeDetector.Builder(context.getApplicationContext()).setBarcodeFormats(
Barcode.QR_CODE).build();
}
return detector;
}
}
\ No newline at end of file
package ee.ttu.thesis.utils;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Created by hajola on 18.04.17.
*/
public class BottomOffsetDecoration extends RecyclerView.ItemDecoration {
private int mOffset;
private int mDataSize;
public BottomOffsetDecoration(float bottomOffsetInPixels, int mDataSize) {
mOffset = (int) bottomOffsetInPixels;
this.mDataSize = mDataSize;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// mDataSize = state.getItemCount();
int position = parent.getChildPosition(view);
if (mDataSize > 0 && position == 0) {
outRect.set(0, mOffset, 0, 0);
} else if(mDataSize > 0 && position == mDataSize-1){
outRect.set(0, 0, 0, mOffset);
} else {
outRect.set(0, 0, 0, 0);
}
}
public void updateDataSize(int newSize){
mDataSize = newSize;
}
}
package ee.ttu.thesis.utils;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.provider.Settings;
import ee.ttu.thesis.R;
/**
* Created by hajola on 10.05.17.
*/
public final class CommonUtils {
private static final String TAG = "CommonUtils";
private CommonUtils() {
// This utility class is not publicly instantiable
}
public static ProgressDialog showLoadingDialog(Context context) {
ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.show();
if (progressDialog.getWindow() != null) {
progressDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
progressDialog.setContentView(R.layout.progress_dialog);
progressDialog.setIndeterminate(true);
progressDialog.setCancelable(true);
progressDialog.setCanceledOnTouchOutside(false);
return progressDialog;
}
@SuppressLint("all")
public static String getDeviceId(Context context) {
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
}
package ee.ttu.thesis.utils;
/**
* Created by hajola on 26.04.17.
*/
public class Constants {
public static final int SOLVE_NFC = 0;
public static final int SOLVE_LOCATION = 1;
public static final int SOLVE_QUESTION = 2;
public static final int SOLVE_PHOTO = 3;
public static final int SOLVE_QR = 4;
public static final int FIND_COMPASS = 0;
public static final int FIND_HINT = 1;
public static final int FIND_HINT_COMPASS = 2;
public static final String STATUS_CODE_SUCCESS = "success";
public static final String STATUS_CODE_FAILED = "failed";
public static final int API_STATUS_CODE_LOCAL_ERROR = 0;
}
package ee.ttu.thesis.utils;
import android.content.Context;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.TypedValue;
public class DeviceDimensionsHelper {
// DeviceDimensionsHelper.getDisplayWidth(context) => (display width in pixels)
public static int getDisplayWidth(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
return displayMetrics.widthPixels;
}
// DeviceDimensionsHelper.getDisplayHeight(context) => (display height in pixels)
public static int getDisplayHeight(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
return displayMetrics.heightPixels;
}
// DeviceDimensionsHelper.convertDpToPixel(25f, context) => (25dp converted to pixels)
public static float convertDpToPixel(float dp, Context context){
Resources r = context.getResources();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
}
// DeviceDimensionsHelper.convertPixelsToDp(25f, context) => (25px converted to dp)
public static float convertPixelsToDp(float px, Context context){
Resources r = context.getResources();
DisplayMetrics metrics = r.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
}
\ No newline at end of file
package ee.ttu.thesis.utils;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.View;
import ee.ttu.thesis.ui.list.GamesAdapter;
/**
* Created by hajola on 17.04.17.
*/
public class DividerDecoration extends RecyclerView.ItemDecoration {
private final Paint mPaint;
private int mHeightDp;
public DividerDecoration(Context context) {
this(context, Color.argb((int) (255 * 0.2), 0, 0, 0), 1f);
}
public DividerDecoration(Context context, int color, float heightDp) {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(color);
mHeightDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, heightDp, context.getResources().getDisplayMetrics());
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
int viewType = parent.getAdapter().getItemViewType(position);
int viewTypeAfter = -1;
try {
viewTypeAfter = parent.getAdapter().getItemViewType(position + 1);
} catch (IndexOutOfBoundsException e) {
}
if (viewType == GamesAdapter.GAME && viewTypeAfter == GamesAdapter.GAME) {
outRect.set(0, 0, 0, mHeightDp);
} else {
outRect.setEmpty();
}
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
int viewType = parent.getAdapter().getItemViewType(position);
int viewTypeAfter = -1;
try {
viewTypeAfter = parent.getAdapter().getItemViewType(position + 1);
} catch (IndexOutOfBoundsException e) {
}
if (viewType == GamesAdapter.GAME && viewTypeAfter == GamesAdapter.GAME) {
c.drawRect(view.getLeft(), view.getBottom(), view.getRight(), view.getBottom() + mHeightDp, mPaint);
} else {
}
}
}
}
\ No newline at end of file
package ee.ttu.thesis.utils;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import ee.ttu.thesis.R;
/**
* Created by hajola on 26.03.17.
*/
public class ItemClickSupport {
private final RecyclerView mRecyclerView;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
}
};
private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mOnItemLongClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
return false;
}
};
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
= new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(View view) {
if (mOnItemClickListener != null) {
view.setOnClickListener(mOnClickListener);
}
if (mOnItemLongClickListener != null) {
view.setOnLongClickListener(mOnLongClickListener);
}
}
@Override
public void onChildViewDetachedFromWindow(View view) {
}
};
private ItemClickSupport(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
mRecyclerView.setTag(R.id.item_click_support, this);
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
}
public static ItemClickSupport addTo(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support == null) {
support = new ItemClickSupport(view);
}
return support;
}
public static ItemClickSupport removeFrom(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support != null) {
support.detach(view);
}
return support;
}
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
return this;
}
public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
mOnItemLongClickListener = listener;
return this;
}
private void detach(RecyclerView view) {
view.removeOnChildAttachStateChangeListener(mAttachListener);
view.setTag(R.id.item_click_support, null);
}
public interface OnItemClickListener {
void onItemClicked(RecyclerView recyclerView, int position, View v);
}
public interface OnItemLongClickListener {
boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
}
}
\ No newline at end of file
package ee.ttu.thesis.utils;
/**
* Created by hajola on 26.04.17.
*/
/**
* The interface Qr data listener.
*/
public interface QRDataListener {
/**
* On detected.
*
* @param data
* the data
*/
// Called from not main thread. Be careful
void onDetected(final String data);
}
package ee.ttu.thesis.utils;
import android.Manifest;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewTreeObserver;
import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
import com.orhanobut.logger.Logger;
import java.io.IOException;
/**
* Created by hajola on 26.04.17.
*/
public class QRReader {
private final String LOGTAG = getClass().getSimpleName();
private CameraSource cameraSource = null;
private BarcodeDetector barcodeDetector = null;
/**
* The constant FRONT_CAM.
*/
public static final int FRONT_CAM = CameraSource.CAMERA_FACING_FRONT;
/**
* The constant BACK_CAM.
*/
public static final int BACK_CAM = CameraSource.CAMERA_FACING_BACK;
private final int width;
private final int height;
private final int facing;
private final QRDataListener qrDataListener;
private final Context context;
private final SurfaceView surfaceView;
private boolean autoFocusEnabled;
private boolean cameraRunning = false;
private boolean surfaceCreated = false;
public void initAndStart(final SurfaceView surfaceView) {
surfaceView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
init();
start();
removeOnGlobalLayoutListener(surfaceView, this);
}
});
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private static void removeOnGlobalLayoutListener(View v,
ViewTreeObserver.OnGlobalLayoutListener listener) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
}
else {
v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
}
private final SurfaceHolder.Callback surfaceHolderCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
//we can start barcode after after creating
surfaceCreated = true;
startCameraView(context, cameraSource, surfaceView);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
surfaceCreated = false;
stop();
surfaceHolder.removeCallback(this);
}
};
/**
* Instantiates a new QREader.
*
* @param builder
* the builder
*/
/*
* Instantiates a new QREader
*
* @param builder the builder
*/
private QRReader(final Builder builder) {
this.autoFocusEnabled = builder.autofocusEnabled;
this.width = builder.width;
this.height = builder.height;
this.facing = builder.facing;
this.qrDataListener = builder.qrDataListener;
this.context = builder.context;
this.surfaceView = builder.surfaceView;
//for better performance we should use one detector for all Reader, if builder not specify it
if (builder.barcodeDetector == null) {
this.barcodeDetector = BarcodeDetectorHolder.getBarcodeDetector(context);
}
else {
this.barcodeDetector = builder.barcodeDetector;
}
}
/**
* Is camera running boolean.
*
* @return the boolean
*/
public boolean isCameraRunning() {
return cameraRunning;
}
/**
* Init.
*/
private void init() {
if (!hasAutofocus(context)) {
Log.e(LOGTAG, "Do not have autofocus feature, disabling autofocus feature in the library!");
autoFocusEnabled = false;
}
if (!hasCameraHardware(context)) {
Log.e(LOGTAG, "Does not have camera hardware!");
return;
}
if (!checkCameraPermission(context)) {
Log.e(LOGTAG, "Do not have camera permission!");
return;
}
if (barcodeDetector.isOperational()) {
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
@Override
public void release() {
// Handled via public method
}
@Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barcodes = detections.getDetectedItems();
if (barcodes.size() != 0 && qrDataListener != null) {
qrDataListener.onDetected(barcodes.valueAt(0).displayValue);
}
}
});
cameraSource =
new CameraSource.Builder(context, barcodeDetector).setAutoFocusEnabled(autoFocusEnabled)
.setFacing(facing)
.setRequestedPreviewSize(width, height)
.build();
}
else {
Log.e(LOGTAG, "Barcode recognition libs are not downloaded and are not operational");
}
}
/**
* Start scanning qr codes.
*/
public void start() {
if (surfaceView != null && surfaceHolderCallback != null) {
//if surface already created, we can start camera
if (surfaceCreated) {
startCameraView(context, cameraSource, surfaceView);
}
else {
//startCameraView will be invoke in void surfaceCreated
surfaceView.getHolder().addCallback(surfaceHolderCallback);
}
}
}
private void startCameraView(Context context, CameraSource cameraSource,
SurfaceView surfaceView) {
if (cameraRunning) {
// throw new IllegalStateException("Camera already started!");
}
try {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
Log.e(LOGTAG, "Permission not granted!");
}
else if (!cameraRunning && cameraSource != null && surfaceView != null) {
cameraSource.start(surfaceView.getHolder());
cameraRunning = true;
}
} catch (IOException ie) {
Log.e(LOGTAG, ie.getMessage());
ie.printStackTrace();
}
}
/**
* Stop camera
*/
public void stop() {
try {
if (cameraRunning && cameraSource != null) {
cameraSource.stop();
cameraRunning = false;
}
} catch (Exception ie) {
Log.e(LOGTAG, ie.getMessage());
ie.printStackTrace();
}
}
/**
* Release and cleanup QREader.
*/
public void releaseAndCleanup() {
stop();
if (cameraSource != null) {
//release camera and barcode detector(will invoke inside) resources
cameraSource.release();
cameraSource = null;
}
}
private boolean checkCameraPermission(Context context) {
String permission = Manifest.permission.CAMERA;
int res = context.checkCallingOrSelfPermission(permission);
return res == PackageManager.PERMISSION_GRANTED;
}
private boolean hasCameraHardware(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
private boolean hasAutofocus(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_AUTOFOCUS);
}
/**
* The type Builder.
*/
public static class Builder {
private boolean autofocusEnabled;
private int width;
private int height;
private int facing;
private final QRDataListener qrDataListener;
private final Context context;
private final SurfaceView surfaceView;
private BarcodeDetector barcodeDetector;
/**
* Instantiates a new Builder.
*
* @param context
* the context
* @param surfaceView
* the surface view
* @param qrDataListener
* the qr data listener
*/
public Builder(Context context, SurfaceView surfaceView, QRDataListener qrDataListener) {
this.autofocusEnabled = true;
this.width = 800;
this.height = 800;
this.facing = BACK_CAM;
this.qrDataListener = qrDataListener;
this.context = context;
this.surfaceView = surfaceView;
}
/**
* Enable autofocus builder.
*
* @param autofocusEnabled
* the autofocus enabled
* @return the builder
*/
public Builder enableAutofocus(boolean autofocusEnabled) {
this.autofocusEnabled = autofocusEnabled;
return this;
}
/**
* Width builder.
*
* @param width
* the width
* @return the builder
*/
public Builder width(int width) {
if (width != 0) {
this.width = width;
}
return this;
}
/**
* Height builder.
*
* @param height
* the height
* @return the builder
*/
public Builder height(int height) {
if (height != 0) {
this.height = height;
}
return this;
}
/**
* Facing builder.
*
* @param facing
* the facing
* @return the builder
*/
public Builder facing(int facing) {
this.facing = facing;
return this;
}
/**
* Build QREader
*
* @return the QREader
*/
public QRReader build() {
return new QRReader(this);
}
/**
* Barcode detector.
*
* @param barcodeDetector
* the barcode detector
*/
public void barcodeDetector(BarcodeDetector barcodeDetector) {
this.barcodeDetector = barcodeDetector;
}
}
}
\ No newline at end of file
package ee.ttu.thesis.utils;
import com.jakewharton.rxrelay2.PublishRelay;
import com.jakewharton.rxrelay2.Relay;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
/**
* Created by hajola on 25.04.17.
*/
public class RxBus {
private final Relay<Object> _bus = PublishRelay.create().toSerialized();
public void send(Object o) {
_bus.accept(o);
}
public Flowable<Object> asFlowable() {
return _bus.toFlowable(BackpressureStrategy.LATEST);
}
public boolean hasObservers() {
return _bus.hasObservers();
}
}
package ee.ttu.thesis.utils;
import io.reactivex.Scheduler;
/**
* Created by hajola on 9.05.17.
*/
public interface SchedulerProvider {
Scheduler ui();
Scheduler computation();
Scheduler io();
}
\ No newline at end of file
package ee.ttu.thesis.utils;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by hajola on 17.04.17.
*/
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,
dyUnconsumed);
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
child.hide();
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
child.show();
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="@color/colorNotificationChatBackground" />
<corners
android:bottomLeftRadius="6dp"
android:bottomRightRadius="6dp"
android:radius="1dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="@color/colorNotificationChatBackground" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="@color/colorNotificationChatBackground" />
<corners
android:bottomLeftRadius="6dp"
android:bottomRightRadius="6dp"
android:radius="1dp"
android:topLeftRadius="6dp"
android:topRightRadius="6dp" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="@color/colorNotificationChatBackground" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:radius="1dp"
android:topLeftRadius="6dp"
android:topRightRadius="6dp" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="@color/white" />
<corners android:radius="6dp" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="@color/colorPrimary" />
<corners android:radius="6dp" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape android:shape="oval">
<solid android:color="@color/colorPrimaryDark"/>
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="@color/colorPrimary"/>
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/colorPrimary"/>
<stroke
android:width="2dp"
android:color="@color/colorAccent"/>
<size
android:width="120dp"
android:height="120dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="2dp"
android:color="@color/colorNotificationLine"/>
<size
android:width="48dp"
android:height="48dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="2dp"
android:color="@color/colorAccent"/>
<size
android:width="48dp"
android:height="48dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="6dp"
android:useLevel="false">
<solid android:color="@color/colorPrimaryLight"/>
</shape>
</item>
</layer-list>
\ No newline at end of file
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="@color/colorPrimary"
android:endColor="@android:color/transparent"
android:angle="90"
android:type="linear"
android:useLevel="true" />
</shape>
\ No newline at end of file
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="@color/colorPrimaryLight"
android:endColor="@android:color/transparent"
android:angle="90"
android:type="linear"
android:useLevel="true" />
</shape>
\ No newline at end of file
<vector android:height="48dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M7,10l5,5 5,-5z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M7,14l5,-5 5,5z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M14,20A2,2 0,0 1,12 22A2,2 0,0 1,10 20H14M12,2A1,1 0,0 1,13 3V4.08C15.84,4.56 18,7.03 18,10V16L21,19H3L6,16V10C6,7.03 8.16,4.56 11,4.08V3A1,1 0,0 1,12 2Z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM6,9h12v2L6,11L6,9zM14,14L6,14v-2h8v2zM18,8L6,8L6,6h12v2z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M10.09,15.59L11.5,17l5,-5 -5,-5 -1.41,1.41L12.67,11H3v2h9.67l-2.58,2.59zM19,3H5c-1.11,0 -2,0.9 -2,2v4h2V5h14v14H5v-4H3v4c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,8l-6,6 1.41,1.41L12,10.83l4.59,4.58L18,14z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M16.59,8.59L12,13.17 7.41,8.59 6,10l6,6 6,-6z"/>
</vector>
<vector android:height="48dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17,2V2H17V6H15C14.31,6 14,6.81 14,7.5V10H14L17,10V14H14V22H10V14H7V10H10V6A4,4 0,0 1,14 2H17Z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M9,10L6,5H18L15,10H9M18,4H6V2H18V4M9,22V11H15V22H9M12,13A1,1 0,0 0,11 14A1,1 0,0 0,12 15A1,1 0,0 0,13 14A1,1 0,0 0,12 13Z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M2,5.27L3.28,4L20,20.72L18.73,22L15,18.27V22H9V12.27L2,5.27M18,5L15,10H11.82L6.82,5H18M18,4H6V2H18V4M15,11V13.18L12.82,11H15Z"/>
</vector>
<vector android:height="48dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M23,11H21V9H19V11H17V13H19V15H21V13H23M8,11V13.4H12C11.8,14.4 10.8,16.4 8,16.4C5.6,16.4 3.7,14.4 3.7,12C3.7,9.6 5.6,7.6 8,7.6C9.4,7.6 10.3,8.2 10.8,8.7L12.7,6.9C11.5,5.7 9.9,5 8,5C4.1,5 1,8.1 1,12C1,15.9 4.1,19 8,19C12,19 14.7,16.2 14.7,12.2C14.7,11.7 14.7,11.4 14.6,11H8Z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94V1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11H1v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94V23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94H23v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20.5,3l-0.16,0.03L15,5.1 9,3 3.36,4.9c-0.21,0.07 -0.36,0.25 -0.36,0.48V20.5c0,0.28 0.22,0.5 0.5,0.5l0.16,-0.03L9,18.9l6,2.1 5.64,-1.9c0.21,-0.07 0.36,-0.25 0.36,-0.48V3.5c0,-0.28 -0.22,-0.5 -0.5,-0.5zM15,19l-6,-2.11V5l6,2.11V19z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M10.59,7.66C10.59,7.66 11.19,7.39 11.57,7.82C11.95,8.26 12.92,9.94 12.92,11.62C12.92,13.3 12.5,15.09 12.05,15.68C11.62,16.28 11.19,16.28 10.86,16.06C10.54,15.85 5.5,12 5.23,11.89C4.95,11.78 4.85,12.05 5.12,13.5C5.39,15 4.95,15.41 4.57,15.47C4.2,15.5 3.06,15.2 3,12.16C2.95,9.13 3.76,8.64 4.14,8.64C4.85,8.64 10.27,13.5 10.64,13.46C10.97,13.41 11.13,11.35 10.5,9.72C9.78,7.96 10.59,7.66 10.59,7.66M19.3,4.63C21.12,8.24 21,11.66 21,12C21,12.34 21.12,15.76 19.3,19.37C19.3,19.37 18.83,19.92 18.12,19.59C17.42,19.26 17.66,18.4 17.66,18.4C17.66,18.4 19.14,15.55 19.1,12.05V12C19.14,8.5 17.66,5.6 17.66,5.6C17.66,5.6 17.42,4.74 18.12,4.41C18.83,4.08 19.3,4.63 19.3,4.63M15.77,6.25C17.26,8.96 17.16,11.66 17.14,12C17.16,12.34 17.26,14.92 15.77,17.85C15.77,17.85 15.3,18.4 14.59,18.07C13.89,17.74 14.13,16.88 14.13,16.88C14.13,16.88 15.09,15.5 15.24,12.05V12C15.14,8.53 14.13,7.23 14.13,7.23C14.13,7.23 13.89,6.36 14.59,6.04C15.3,5.71 15.77,6.25 15.77,6.25Z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path
android:fillColor="#FF000000"
android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M4,4H10V10H4V4M20,4V10H14V4H20M14,15H16V13H14V11H16V13H18V11H20V13H18V15H20V18H18V20H16V18H13V20H11V16H14V15M16,15V18H18V15H16M4,20V14H10V20H4M6,6V8H8V6H6M16,6V8H18V6H16M6,16V18H8V16H6M4,11H6V13H4V11M9,11H13V15H11V13H9V11M11,6H13V10H11V6M2,2V6H0V2A2,2 0,0 1,2 0H6V2H2M22,0A2,2 0,0 1,24 2V6H22V2H18V0H22M2,18V22H6V24H2A2,2 0,0 1,0 22V18H2M22,22V18H24V22A2,2 0,0 1,22 24H18V22H22Z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M5,4H19A3,3 0,0 1,22 7V11H15V10H9V11H2V7A3,3 0,0 1,5 4M11,11H13V13H11V11M2,12H9V13L11,15H13L15,13V12H22V20H2V12Z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M21,10.12h-6.78l2.74,-2.82c-2.73,-2.7 -7.15,-2.8 -9.88,-0.1 -2.73,2.71 -2.73,7.08 0,9.79 2.73,2.71 7.15,2.71 9.88,0C18.32,15.65 19,14.08 19,12.1h2c0,1.98 -0.88,4.55 -2.64,6.29 -3.51,3.48 -9.21,3.48 -12.72,0 -3.5,-3.47 -3.53,-9.11 -0.02,-12.58 3.51,-3.47 9.14,-3.47 12.65,0L21,3v7.12zM12.5,8v4.25l3.5,2.08 -0.72,1.21L11,13V8h1.5z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorPrimary" />
<stroke
android:width="2dp"
android:color="@color/colorAccent" />
<corners android:radius="30dp" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="2dp"
android:color="@color/colorPrimaryLight" />
<corners android:radius="30dp" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="6dp"
android:useLevel="false">
<solid android:color="@color/colorAccent"/>
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/selected_dot"
android:state_selected="true"/>
<item android:drawable="@drawable/default_dot"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<stroke
android:width="1dip"
android:color="@color/white"
/>
<padding
android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip"
/>
</shape>
</item>
<item android:bottom="1dp" android:top="1dp" android:left="1dp" >
<shape android:shape="rectangle">
<solid android:color="@color/white" />
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<stroke
android:width="1dip"
android:color="@color/white"
/>
<padding
android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip"
/>
</shape>
</item>
<item android:bottom="1dp" android:top="1dp" >
<shape android:shape="rectangle">
<solid android:color="@color/colorPrimaryDark" />
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<stroke
android:width="1dip"
android:color="@color/white"
/>
<padding
android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip"
/>
</shape>
</item>
<item android:bottom="1dp" android:top="1dp" android:right="1dp" >
<shape android:shape="rectangle">
<solid android:color="@color/colorPrimaryDark" />
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingTop="32dp"
android:id="@+id/linearLayout3">
<TextView
android:id="@+id/activity_future_game_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="TUT Summer hunt"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/activity_future_game_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="You are challenged to obtain the highest number of points in 60 minutes by completing a series of puzzles. Winning team gets the grand prize!"
android:textColor="@color/colorSecondaryMain" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/activity_future_game_go_back_textView"
android:layout_below="@+id/linearLayout3">
<TextView
android:id="@+id/textView16"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/include"
android:layout_centerHorizontal="true"
android:text="Game starts in"
android:textColor="@color/colorSecondaryLight" />
<include
android:id="@+id/include"
layout="@layout/layout_time_to_game" />
</RelativeLayout>
<TextView
android:id="@+id/activity_future_game_go_back_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_marginBottom="32dp"
android:layout_marginEnd="32dp"
android:layout_marginLeft="32dp"
android:layout_marginRight="32dp"
android:layout_marginStart="32dp"
android:layout_marginTop="80dp"
android:background="@drawable/login_rounded_rectangle_filled"
android:elevation="8dp"
android:paddingBottom="64dp"
android:paddingTop="64dp"
android:text="BACK"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="36sp" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="@+id/activity_game_tablayout"
style="@style/MyCustomTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:elevation="4dp"
android:fillViewport="false" />
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/activity_game_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" />
</android.support.design.widget.CoordinatorLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_history_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="ee.ttu.thesis.ui.game.map.WorkAroundMapFragment"
android:layout_width="match_parent"
android:layout_height="350dp"
map:uiCompass="true"
tools:context=".ui.past.HistoryActivity" />
<View
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_alignBottom="@id/map"
android:background="@drawable/gradient_rectangle_map_overlay" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="32dp">
<TextView
android:id="@+id/textView15"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:text="Rank:"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView
android:id="@+id/textView17"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="2nd"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="8dp">
<TextView
android:id="@+id/activity_history_distance_traveled_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:text="Distance traveled:"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView
android:id="@+id/activity_history_distance_traveled"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="12.4 km"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="8dp">
<TextView
android:id="@+id/textView155"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:text="Time taken:"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView
android:id="@+id/textView175"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="147 minutes"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="8dp">
<TextView
android:id="@+id/activity_history_number_of_points_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:text="Points visited:"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView
android:id="@+id/activity_history_number_of_points"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="12"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="8dp">
<TextView
android:id="@+id/activityV_history_average_speed_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:text="Average speed:"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView
android:id="@+id/activityV_history_average_speed"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="6.27 km/h"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="32dp">
<TextView
android:id="@+id/activity_history_average_point_speed_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:text="Average speed:"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView
android:id="@+id/activity_history_average_point_speed"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="12 min/point"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="8dp">
<TextView
android:id="@+id/activity_history_start_time_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:text="Start:"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView
android:id="@+id/activity_history_start_time"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="DD/MM hh:mm"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="32dp">
<TextView
android:id="@+id/activity_history_end_time_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:text="End:"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView
android:id="@+id/activity_history_end_time"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="DD/MM hh:mm"
android:textAlignment="textStart"
android:textColor="@color/white"
android:textSize="24sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
\ No newline at end of file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:gravity="top|center_horizontal"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="60dp"
android:paddingRight="60dp"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="ee.ttu.thesis.ui.login.LoginActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/activity_login_game_title_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/textView5"
android:layout_centerHorizontal="true"
android:paddingBottom="8dp"
android:paddingTop="48dp"
android:text="Game title"
android:textColor="@color/colorPrimaryLight"
android:textSize="18sp"
android:visibility="invisible" />
<ProgressBar
android:id="@+id/activity_login_progressbar"
style="?android:attr/progressBarStyle"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="invisible" />
<TextView
android:id="@+id/activity_login_jointheadventure"
fontPath="fonts/amatic.ttf"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="64dp"
android:layout_marginTop="64dp"
android:text="Join the game!"
android:textAlignment="center"
android:textColor="@color/colorAccent"
android:textSize="48sp"
android:textStyle="italic"
android:typeface="sans"
android:visibility="visible"
tools:ignore="MissingPrefix" />
<TextView
android:id="@+id/activity_login_game_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="PEALKIRI"
android:textAlignment="center"
android:textColor="@color/colorAccent"
android:textSize="30sp"
android:textStyle="bold"
android:visibility="invisible" />
<TextView
android:id="@+id/activity_login_gameInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/activity_login_progressbar"
android:layout_centerHorizontal="true"
android:layout_marginTop="48dp"
android:text="TextView"
android:textColor="@color/colorSecondaryMain"
android:textSize="18sp"
android:visibility="invisible" />
</RelativeLayout>
<EditText
android:id="@+id/activity_login_game_code_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:ems="10"
android:hint="Game code"
android:inputType="text|textPersonName"
android:textColor="@android:color/white"
android:textColorHint="@color/colorPrimaryLight"
android:theme="@style/LoginEditTextTheme" />
<EditText
android:id="@+id/activity_login_user_name_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:ems="10"
android:hint="Enter your name"
android:inputType="text|textPersonName"
android:textColor="@android:color/white"
android:textColorHint="@color/colorPrimaryLight"
android:theme="@style/LoginEditTextTheme" />
<Button
android:id="@+id/activity_login_enter_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="48dp"
android:background="@drawable/rounded_rectangle"
android:text="enter"
android:textAllCaps="false"
android:textColor="@color/colorPrimaryLight" />
<!--<LinearLayout-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_gravity="center_horizontal"-->
<!--android:padding="16dp"-->
<!--android:orientation="horizontal">-->
<!--<View-->
<!--android:layout_width="0px"-->
<!--android:layout_height="1dp"-->
<!--android:layout_gravity="center"-->
<!--android:layout_weight="4"-->
<!--android:background="@color/colorPrimaryLight" />-->
<!--<TextView-->
<!--android:layout_width="0px"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_gravity="center"-->
<!--android:layout_weight="1"-->
<!--android:fontFamily="sans-serif"-->
<!--android:gravity="center"-->
<!--android:text="or"-->
<!--android:textColor="@color/colorPrimaryLight"-->
<!--android:textSize="14sp"-->
<!--android:textStyle="normal" />-->
<!--<View-->
<!--android:layout_width="0px"-->
<!--android:layout_height="1dp"-->
<!--android:layout_gravity="center"-->
<!--android:layout_weight="4"-->
<!--android:background="@color/colorPrimaryLight" />-->
<!--</LinearLayout>-->
<TextView
android:id="@+id/textView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="or login using"
android:textAlignment="center"
android:textColor="@color/colorAccent"
android:textSize="14sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/signInButton_activity_login_google"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:layout_marginBottom="16dp"
android:layout_marginRight="32dp"
android:background="@drawable/circle_login_icons"
android:elevation="6dp"
android:padding="24dp"
android:src="@drawable/ic_google_plus"
android:tint="@color/loginScreenWhiteText" />
<ImageView
android:id="@+id/signInButton_activity_login_facebook"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_gravity="center"
android:layout_marginBottom="16dp"
android:background="@drawable/circle_login_icons"
android:elevation="6dp"
android:padding="24dp"
android:src="@drawable/ic_facebook"
android:tint="@color/loginScreenWhiteText" />
</RelativeLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:background="@color/colorPrimaryDark"
android:layout_height="match_parent">
<!--<TextView-->
<!--android:id="@+id/activity_main_textview"-->
<!--android:text="text"-->
<!--android:layout_margin="20dp"-->
<!--android:textSize="24sp"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content" />-->
<!--<Button-->
<!--android:id="@+id/button2"-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:text="LogOut" />-->
<android.support.v7.widget.RecyclerView
android:id="@+id/activity_main_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v7.widget.RecyclerView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"
android:clickable="true"
android:tint="@android:color/white"
app:fabSize="normal"
app:layout_behavior="ee.ttu.thesis.utils.ScrollAwareFABBehavior"
app:layout_anchor="@id/activity_main_recyclerview"
app:layout_anchorGravity="bottom|right|end"
app:srcCompat="@drawable/ic_add_black_48dp" />
</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/colorPrimaryDark"
android:layout_above="@+id/activity_start_button">
<android.support.v4.view.ViewPager
android:id="@+id/activity_start_viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.design.widget.TabLayout
android:id="@+id/activity_start_tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
android:layout_alignParentBottom="true" />
</RelativeLayout>
<TextView
android:id="@+id/activity_start_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_marginBottom="32dp"
android:layout_marginEnd="32dp"
android:layout_marginLeft="32dp"
android:layout_marginRight="32dp"
android:layout_marginStart="32dp"
android:layout_marginTop="80dp"
android:background="@drawable/login_rounded_rectangle_filled"
android:elevation="8dp"
android:paddingBottom="64dp"
android:paddingTop="64dp"
android:text="START"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="36sp" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<EditText
android:id="@+id/dialog_enter_new_game_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp"
android:ems="10"
android:hint="Game code"
android:inputType="textPersonName"
android:textColor="@color/white"
android:textColorHint="@color/colorPrimaryLight"
android:theme="@style/LoginEditTextTheme" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingRight="4dp"
android:paddingTop="8dp">
<Button
android:id="@+id/dialog_add_new_game_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toStartOf="@+id/dialog_add_new_game_ok_button"
android:background="@android:color/transparent"
android:text="CANCEL"
android:textColor="@color/colorAccent" />
<Button
android:id="@+id/dialog_add_new_game_ok_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="4dp"
android:background="@android:color/transparent"
android:text="OK"
android:textColor="@color/colorAccent" />
</RelativeLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<SurfaceView
android:id="@+id/dialog_qr_scanner_camera_view"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:layout_gravity="center_horizontal" />
<TextView
android:id="@+id/textView14"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="8dp"
android:text="Point the camera to a QR code"
android:textAlignment="center"
android:textColor="@color/colorPrimaryLight" />
<Button
android:id="@+id/dialog_qr_scanner_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@android:color/transparent"
android:text="CANCEL"
android:textColor="@color/colorAccent" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<TextView
android:id="@+id/dialog_question_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="Nam suscipit augue ligula ?"
android:textColor="@color/colorAccent"
android:textSize="18sp"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/dialog_question_radiogroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp">
</RadioGroup>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingRight="4dp"
android:paddingTop="8dp">
<Button
android:id="@+id/dialog_question_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:text="CANCEL"
android:textColor="@color/colorAccent"
android:layout_alignParentTop="true"
android:layout_toStartOf="@+id/dialog_question_submit_button" />
<Button
android:id="@+id/dialog_question_submit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="4dp"
android:background="@android:color/transparent"
android:text="SUBMIT"
android:textColor="@color/colorAccent" />
</RelativeLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<EditText
android:id="@+id/dialog_write_to_coordinators_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="16dp"
android:ems="10"
android:hint="Message"
android:inputType="textPersonName"
android:textColor="@color/white"
android:textColorHint="@color/colorPrimaryLight"
android:theme="@style/LoginEditTextTheme" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingRight="4dp"
android:paddingTop="8dp">
<Button
android:id="@+id/dialog_write_to_coordinators_cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toStartOf="@+id/dialog_write_to_coordinators_ok_button"
android:background="@android:color/transparent"
android:text="CANCEL"
android:textColor="@color/colorAccent" />
<Button
android:id="@+id/dialog_write_to_coordinators_ok_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="4dp"
android:background="@android:color/transparent"
android:text="SEND"
android:textColor="@color/colorAccent" />
</RelativeLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/fragment_compass_upper_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="32dp">
<TextView
android:id="@+id/fragment_solve_point_title"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Kadriorg's time"
android:textColor="@color/white"
android:textSize="24sp" />
<TextView
android:id="@+id/fragment_solve_point_order"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="2 / 5"
android:textAlignment="viewEnd"
android:textColor="@color/colorSecondaryMain"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/fragment_solve_point_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:paddingBottom="32dp"
android:paddingTop="16dp"
android:text="The object in question has been there since 1937. It was designed by A. Lomann and built by E. Uukivi."
android:textColor="@color/colorSecondaryMain"
android:textSize="14sp" />
<LinearLayout
android:id="@+id/fragment_compass_hint_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/layout_hint" />
</LinearLayout>
<LinearLayout
android:id="@+id/fragment_compass_compass_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/layout_compass" />
</LinearLayout>
<LinearLayout
android:id="@+id/fragment_compass_distance_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/layout_distance" />
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/fragment_howtosolvecontent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</ScrollView>
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/fragment_compass_upper_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="32dp">
<TextView
android:id="@+id/fragment_solve_point_title"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="5"
android:text="Kadriorg's time"
android:textColor="@color/white"
android:textSize="24sp" />
<TextView
android:id="@+id/fragment_solve_point_order"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="2 / 5"
android:textAlignment="viewEnd"
android:textColor="@color/colorSecondaryMain"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/fragment_solve_point_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:paddingBottom="32dp"
android:paddingTop="16dp"
android:text="The object in question has been there since 1937. It was designed by A. Lomann and built by E. Uukivi."
android:textColor="@color/colorSecondaryMain"
android:textSize="14sp" />
<LinearLayout
android:id="@+id/fragment_compass_hint_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:id="@+id/fragment_compass_compass_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:id="@+id/fragment_compass_distance_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/fragment_howtosolvecontent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</ScrollView>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/linearLayout"
android:background="@color/colorPrimaryLight"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp">
<TextView
android:id="@+id/fragment_go_to_location_instructions_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:text="Find the location"
android:textAlignment="center" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_gravity="center_horizontal"
android:padding="4dp"
android:layout_marginTop="8dp">
<ImageView
android:id="@+id/fragment_go_to_location_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:background="@drawable/circle_notification_icon_background"
android:padding="8dp"
android:layout_marginBottom="8dp"
android:src="@drawable/ic_search_black_24dp"
android:tint="@color/colorAccent" />
<include android:visibility="invisible" layout="@layout/progressbar_wrong_answer" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<TextView
android:id="@+id/fragment_go_to_location_point_title"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Title"
android:textSize="18sp" />
<TextView
android:id="@+id/textView8"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="5/9"
android:textAlignment="viewEnd"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/textView6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum sit amet" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorSolveFragmentBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:elevation="2dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="32dp">
<TextView
android:id="@+id/fragment_solve_point_title"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Title"
android:textColor="@color/white"
android:textSize="24sp" />
<TextView
android:id="@+id/fragment_solve_point_order"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="2 / 5"
android:textAlignment="viewEnd"
android:textColor="@color/colorSecondaryMain"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/fragment_solve_point_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:paddingBottom="32dp"
android:paddingTop="16dp"
android:text="Point description."
android:textColor="@color/colorSecondaryMain"
android:textSize="18sp" />
<TextView
android:id="@+id/textView12"
fontPath="fonts/lato_italic.ttf"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="64dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et turpis viverra erat sagittis fringilla placerat sed tellus. "
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="italic"
tools:ignore="MissingPrefix" />
<FrameLayout
android:id="@+id/fragment_howtosolvecontent"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_game_map_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryLight"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:uiCompass="true"
tools:context=".ui.game.GameActivity" />
</RelativeLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/activity_game_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimaryDark"
android:layout_above="@+id/item_notification_reply_root"
android:layout_alignParentTop="true" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_notification_reply_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:orientation="horizontal"
android:padding="8dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true">
<EditText
android:id="@+id/fragment_notification_editText"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="2.45"
android:ems="10"
android:inputType="text"
android:textColor="@android:color/white"
android:textColorHint="@color/loginScreenWhiteText"
android:theme="@style/LoginEditTextTheme" />
<ImageView
android:id="@+id/fragment_notification_send"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:background="@drawable/login_rounded_rectangle_filled"
android:gravity="center"
android:src="@drawable/ic_send_black_24dp"
android:tint="@color/white" />
</LinearLayout>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/linearLayout"
android:background="@color/colorPrimaryLight"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp">
<TextView
android:id="@+id/textView7"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Take a picture of the location"
android:textAlignment="center" />
<ImageButton
android:id="@+id/fragment_photo_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:background="@drawable/circle_button_howtosolve"
android:padding="8dp"
android:src="@drawable/ic_photo_camera_black_24dp"
android:tint="@color/colorAccent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<TextView
android:id="@+id/fragment_game_map_point_title"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Title"
android:textSize="18sp" />
<TextView
android:id="@+id/textView8"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="5/9"
android:textAlignment="viewEnd"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/textView6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum sit amet" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/linearLayout"
android:background="@color/colorPrimaryLight"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp">
<TextView
android:id="@+id/textView7"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Scan the QR code"
android:textAlignment="center" />
<ImageButton
android:id="@+id/fragment_qr_code_scanButton"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:elevation="4dp"
android:background="@drawable/circle_button_howtosolve"
android:padding="8dp"
android:src="@drawable/ic_qrcode_scan"
android:tint="@color/colorAccent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<TextView
android:id="@+id/fragment_game_map_point_title"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Title"
android:textSize="18sp" />
<TextView
android:id="@+id/textView8"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="5/9"
android:textAlignment="viewEnd"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/textView6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum sit amet" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/linearLayout"
android:background="@color/colorSolveFragmentBackground"
android:orientation="vertical"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="8dp">
<TextView
android:id="@+id/fragment_solve_instructions_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:text="In order to complete the point, you must find the location."
android:textAlignment="center"
android:textColor="@color/colorSecondaryMain"
android:textSize="18sp" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:gravity="center"
android:padding="8dp">
<ImageView
android:id="@+id/fragment_solve_icon"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="16dp"
android:background="@drawable/circle_solve_not_button"
android:gravity="center_horizontal"
android:padding="16dp"
android:src="@drawable/ic_google_plus"
android:tint="@color/colorAccent" />
<include
layout="@layout/progressbar_wrong_answer"
android:visibility="invisible"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorPrimaryDark"
android:orientation="vertical"
android:paddingTop="32dp">
<TextView
android:id="@+id/fragment_tutorial_intro_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="TUT Summer hunt"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/fragment_tutorial_intro_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="You are challenged to obtain the highest number of points in 60 minutes by completing a series of puzzles. Winning team gets the grand prize!"
android:textColor="@color/colorSecondaryMain" />
<TextView
android:id="@+id/fragment_tutorial_intro_numbofpoints"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="The game has a total of 3 points."
android:textColor="@color/colorSecondaryMain" />
<TextView
android:id="@+id/fragment_tutorial_intro_limitedTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="Once you press the Start button, you have 60 minutes to find all the points."
android:textColor="@color/colorAccent" />
<TextView
android:id="@+id/textView21"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:gravity="bottom"
android:paddingBottom="64dp"
android:paddingTop="32dp"
android:text="Swipe right for a tutorial"
android:textAlignment="center"
android:textColor="@color/white" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/radioButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:padding="16dp"
android:text="RadioButton"
android:buttonTint="@color/colorPrimaryLight"
android:textColor="@color/white"
android:textSize="16sp" />
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_game_linearlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:background="@drawable/login_rounded_rectangle_filled"
android:elevation="8dp"
android:orientation="vertical"
android:paddingBottom="32dp"
android:paddingEnd="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingStart="16dp"
android:paddingTop="32dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="8dp">
<TextView
android:id="@+id/item_game_gamename_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left"
android:text="Nimi"
android:textColor="@color/white"
android:textSize="@dimen/text_size_normal" />
<TextView
android:id="@+id/item_game_time_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_weight="1"
android:gravity="right"
android:text="02/03/2017"
android:textColor="@color/colorSecondaryLight"
android:textSize="@dimen/text_size_normal" />
</RelativeLayout>
<TextView
android:id="@+id/item_game_location_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="\@Tallinn"
android:textAlignment="textStart"
android:textColor="@color/colorSecondaryMain" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/item_game_category_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingTop="24dp"
android:text="TextView"
android:textAlignment="center"
android:textColor="@color/colorPrimaryLight"
android:textSize="24sp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/item_game_notification_message"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingEnd="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:paddingTop="8dp"
android:text="TextView"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/item_game_notification_timeTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingBottom="16dp"
android:paddingEnd="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:text="18 minutes ago"
android:textAlignment="center"
android:textColor="@color/colorSecondaryMain" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/item_game_notification_message_header_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="16dp"
android:tag="expanded"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="@+id/item_game_notification_message_header_view_top"
android:layout_width="2dp"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:background="@color/colorNotificationLine" />
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/circle_notification_icon_background"
android:padding="8dp"
android:src="@drawable/ic_email_black_24dp"
android:tint="@color/colorNotificationIcons" />
<View
android:layout_width="2dp"
android:layout_height="30dp"
android:layout_gravity="center_horizontal"
android:background="@color/colorNotificationLine" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<TextView
android:id="@+id/item_game_notification_message_header_textView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:padding="8dp"
android:text="Message from the coordinator"
android:textColor="@color/white"
android:textSize="18sp" />
<ImageView
android:id="@+id/item_game_notification_message_expand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|left"
android:gravity="center_vertical|left"
android:src="@drawable/ic_expand_more_black_24dp"
android:tint="@android:color/white" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_game_notification_message_received_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/notifications_layout_left_margin"
android:layout_marginRight="@dimen/notifications_layout_right_margin"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingBottom="4dp"
android:paddingLeft="2dp"
android:paddingRight="2dp"
android:paddingTop="2dp">
<TextView
android:id="@+id/item_game_notification_message_received_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dp"
android:layout_marginRight="48dp"
android:background="@drawable/chat_body_external"
android:elevation="6dp"
android:padding="12dp"
android:text="TextView"
android:textColor="@color/colorPrimaryDark"
android:textSize="14sp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_game_notification_message_sent_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginLeft="@dimen/notifications_layout_left_margin"
android:layout_marginRight="@dimen/notifications_layout_right_margin"
android:gravity="right"
android:orientation="vertical"
android:paddingBottom="4dp"
android:paddingLeft="48dp"
android:paddingRight="2dp"
android:paddingTop="2dp">
<TextView
android:id="@+id/item_game_notification_message_sent_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="4dp"
android:elevation="4dp"
android:background="@drawable/chat_body_internal"
android:gravity="right"
android:padding="12dp"
android:text="TextView"
android:textColor="@android:color/white"
android:textSize="14sp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">
<TextView
android:id="@+id/item_game_feed_header_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:text="Pealkiri"
android:textColor="@color/white"
android:textSize="24sp" />
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="84dp"
android:background="@color/white" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_notification_reply_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/notifications_layout_left_margin"
android:layout_marginRight="@dimen/notifications_layout_right_margin"
android:background="@color/colorPrimaryLight"
android:orientation="horizontal"
android:paddingTop="16dp">
<EditText
android:id="@+id/item_notification_reply_editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2.45"
android:ems="10"
android:inputType="text"
android:textColor="@android:color/white"
android:textColorHint="@color/loginScreenWhiteText"
android:theme="@style/LoginEditTextTheme" />
<ImageView
android:id="@+id/item_notification_reply_imageView"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:paddingRight="8dp"
android:src="@drawable/ic_send_black_24dp"
android:tint="@color/colorPrimaryDark" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ee.ttu.thesis.ui.game.point.CompassView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/compassView"
android:layout_width="match_parent"
android:layout_height="400dp"
android:padding="16dp" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_compass_distance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="32dp"
android:paddingLeft="32dp"
android:paddingRight="32dp"
android:paddingTop="24dp"
android:textAlignment="center"
android:textColor="@color/colorSecondaryMain"
android:textSize="24sp" />
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_hint_textview"
fontPath="fonts/lato_italic.ttf"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:text="Only useful when the closest star to us is visible in the sky."
android:textColor="@color/white"
android:textSize="24sp"
tools:ignore="MissingPrefix" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:layout_gravity="center">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginBottom="16dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="02"
android:id="@+id/layout_time_to_game_days_TextView"
android:textSize="32dp"
android:layout_gravity="center"
android:background="@drawable/time_to_air_border_left"
android:paddingLeft="16dp"
android:paddingTop="8dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
android:textColor="@color/colorPrimaryDark" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Days"
android:id="@+id/textView8"
android:layout_gravity="center_horizontal"
android:layout_marginTop="4dp"
android:textAllCaps="false"
android:textColor="@color/colorSecondaryLight" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="03"
android:id="@+id/layout_time_to_game_hours_TextView"
android:textSize="32dp"
android:layout_gravity="center"
android:paddingLeft="16dp"
android:paddingTop="8dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
android:background="@drawable/time_to_air_border_middle"
android:textColor="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Hours"
android:layout_gravity="center_horizontal"
android:layout_marginTop="4dp"
android:textColor="@color/colorSecondaryLight" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="04"
android:id="@+id/layout_time_to_game_minutes_TextView"
android:textSize="32dp"
android:layout_gravity="center"
android:paddingLeft="16dp"
android:paddingTop="8dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
android:background="@drawable/time_to_air_border_middle"
android:textColor="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Minutes"
android:layout_gravity="center_horizontal"
android:layout_marginTop="4dp"
android:textColor="@color/colorSecondaryLight" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="05"
android:id="@+id/layout_time_to_game_seconds_TextView"
android:textSize="32dp"
android:layout_gravity="center"
android:paddingLeft="16dp"
android:paddingTop="8dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
android:background="@drawable/time_to_air_border_right"
android:textColor="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Seconds"
android:layout_gravity="center_horizontal"
android:layout_marginTop="4dp"
android:textColor="@color/colorSecondaryLight" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@android:color/transparent">
<ProgressBar
android:id="@+id/pb_loading"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:progressDrawable="@color/colorAccent" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progressBar_wrong_answer"
style="?android:attr/progressBarStyle"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_gravity="center"
android:gravity="center" />
[
{
"featureType": "road",
"elementType": "geometry",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "poi",
"elementType": "geometry",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "landscape",
"elementType": "geometry",
"stylers": [
{
"color": "#FFFAF0"
}
]
},
{
"featureType": "water",
"stylers": [
{
"color": "#d9edf7"
}
]
},
{
"featureType": "road",
"elementType": "labels",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "transit",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "administrative",
"elementType": "geometry",
"stylers": [
{
"lightness": 40
}
]
},
{
"featureType": "poi.park",
"elementType": "geometry",
"stylers": [
{
"visibility": "on",
"color": "#c5dac6"
}
]
},
{
"featureType": "landscape.natural.terrain",
"elementType": "geometry.fill",
"stylers": [
{
"visibility": "on"
},
{
"color": "#CCAA88"
},
{
"lightness": 40
}
]
},
{
"featureType": "landscape.man_made",
"elementType": "geometry.fill",
"stylers": [
{
"visibility": "on"
},
{
"color": "#EEEEEE"
}
]
},
{
"featureType": "road",
"stylers": [
{
"visibility": "simplified"
},
{
"color": "#FF0000"
},
{
"gamma": 9
}
]
},
{
"featureType": "road.highway",
"stylers": [
{
"visibility": "on"
},
{
"color": "#FF0000"
},
{
"gamma": 8
}
]
},
{
"featureType": "road.highway.controlled_access",
"stylers": [
{
"visibility": "on"
},
{
"color": "#FF0000"
},
{
"gamma": 4
}
]
},
{
"featureType": "road",
"elementType": "labels",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "poi.government",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
},
{
"color": "#DDDDDD"
}
]
},
{
"featureType": "transit.station",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
},
{
"color": "#CCCCCC"
}
]
},
{
"featureType": "transit.line",
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
},
{
"color": "#AAAAAA"
},
{
"gamma": 4
}
]
}
]
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--Stuff that can't be pressed is primaryLight-->
<color name="colorPrimary">#4B4C55</color>
<color name="colorPrimaryDark">#2d303c</color>
<color name="colorPrimaryLight">#abaac1</color>
<color name="colorAccent">#EA585F</color>
<color name="colorSecondaryMain">#5977a6</color>
<color name="colorSecondaryLight">#8e9ab9</color>
<color name="white">#f7f6f5</color>
<color name="colorDarkTextMain">#212121</color>
<color name="colorLightTextMain">#616161</color>
<color name="colorNotificationLine">@color/colorPrimary</color>
<color name="colorNotificationIcons">@color/colorSecondaryMain</color>
<color name="colorNotificationChatBackground">@color/colorNotificationLine</color>
<color name="colorSolveFragmentBackground">@color/colorPrimaryDark</color>
<!--COMPASSVIEW COLORS-->
<color name="colorCompassCircle">@color/colorSecondaryMain</color>
<color name="colorCompassCenter">@color/colorSecondaryMain</color>
<color name="colorCompassText">@color/colorSecondaryMain</color>
<color name="colorCompassLine">@color/colorSecondaryMain</color>
<color name="colorCompassFinDot">@color/colorAccent</color>
<!--TAB COLORS-->
<color name="colorTabSelected">@color/colorAccent</color>
<color name="colorTabUnSelected">@color/colorPrimaryLight</color>
<color name="loginScreenWhiteText">#F7F6F5</color>
<color name="loginScreenButtonBackground">#96ffffff</color>
<color name="OrderSelectedTabTextColor">@color/colorAccent</color>
<color name="OrderUnSelectedTabTextColor">@color/colorPrimary</color>
</resources>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="text_size_normal">18sp</dimen>
<!--Notifications-->
<dimen name="notifications_layout_left_margin">8dp</dimen>
<dimen name="notifications_layout_right_margin">8dp</dimen>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="item_click_support" type="id" />
<item name="esimene" type="id" />
<item name="teine" type="id" />
<item name="kolmas" type="id" />
<item name="neljas" type="id" />
</resources>
\ No newline at end of file
<resources>
<string name="app_name">Thesis</string>
<!-- Strings related to login -->
<string name="error_field_required">This field is required</string>
<string name="permission_rationale">"Contacts permissions are needed for providing email
completions."
</string>
<!--Solve instructins-->
<string name="solve_photo">Take a photo of the location</string>
<string name="solve_qr">In order to complete the point, you must find a QR code near the location.</string>
<string name="solve_location">Find the location</string>
<string name="solve_nfc">Find the NFC tag</string>
<string name="solve_question">Please answer the question correctly to complete this point</string>
<string name="solve_wrong_answer">Wrong answer! Please wait %1$d seconds for another chance.</string>
<string name="solve_try_again">Please try again.</string>
<string name="server_client_id">61076858488-u2cg2n8lv0c8280hk7i8krkhu7s4v361.apps.googleusercontent.com</string>
<string name="api_default_error">Something went wrong</string>
<string name="connection_error">Internet connection lost</string>
<string name="api_retry_error">Try again</string>
</resources>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="LoginEditTextTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorControlNormal">@color/colorAccent</item>
<item name="colorControlActivated">@color/colorAccent</item>
<item name="colorControlHighlight">@color/colorAccent</item>
</style>
<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
<!--<item name="tabIndicatorColor">@color/textSecondary</item>-->
<item name="tabTextAppearance">@style/MyCustomTextAppearance</item>
<item name="tabIndicatorHeight">0px</item>
<item name="tabSelectedTextColor">@color/colorTabSelected</item>
<item name="textAllCaps">false</item>
<item name="android:textAllCaps">false</item>
</style>
<style name="MyCustomTextAppearance" parent="TextAppearance.Design.Tab">
<item name="textAllCaps">true</item>
<item name="android:textColor">@color/colorTabUnSelected</item>
</style>
</resources>
package ee.ttu.thesis;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'com.google.gms:google-services:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
maven(){
url "https://oss.sonatype.org/content/repositories/snapshots"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
# 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.
org.gradle.jvmargs=-Xmx1536m
# 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
#Wed Mar 22 19:06:35 EET 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
#!/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
# 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\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
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"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# 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 "$@"
@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
include ':app'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment