├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ ├── AndroidManifest.xml │ └── java │ │ └── de │ │ └── fhdw │ │ └── ergoholics │ │ └── brainphaser │ │ ├── ApplicationTest.java │ │ ├── DaggerActivityTestRule.java │ │ ├── MockTestRunner.java │ │ ├── TestAppModule.java │ │ ├── TestBrainPhaserApplication.java │ │ ├── TestUtils.java │ │ ├── database │ │ └── MockDatabaseModule.java │ │ ├── logic │ │ └── MockTestUserLogicFactory.java │ │ └── selectcategorytest │ │ └── CategorySelectionTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── challenges │ │ └── test.bpc │ ├── java │ │ └── de │ │ │ └── fhdw │ │ │ └── ergoholics │ │ │ └── brainphaser │ │ │ ├── AppModule.java │ │ │ ├── BrainPhaserApplication.java │ │ │ ├── BrainPhaserComponent.java │ │ │ ├── activities │ │ │ ├── BrainPhaserActivity.java │ │ │ ├── BrainPhaserFragment.java │ │ │ ├── aboutscreen │ │ │ │ └── AboutActivity.java │ │ │ ├── createuser │ │ │ │ ├── AvatarImageAdapter.java │ │ │ │ ├── AvatarPickerDialogFragment.java │ │ │ │ ├── Avatars.java │ │ │ │ └── CreateUserActivity.java │ │ │ ├── fileimport │ │ │ │ └── ImportChallengeActivity.java │ │ │ ├── main │ │ │ │ ├── MainActivity.java │ │ │ │ └── ProxyActivity.java │ │ │ ├── playchallenge │ │ │ │ ├── AnswerAdapter.java │ │ │ │ ├── AnswerFragment.java │ │ │ │ ├── AnswerFragmentFactory.java │ │ │ │ ├── ChallengeActivity.java │ │ │ │ ├── multiplechoice │ │ │ │ │ ├── ButtonViewState.java │ │ │ │ │ ├── ButtonsAdapter.java │ │ │ │ │ └── MultipleChoiceFragment.java │ │ │ │ ├── selfcheck │ │ │ │ │ └── SelfTestFragment.java │ │ │ │ └── text │ │ │ │ │ └── TextFragment.java │ │ │ ├── selectcategory │ │ │ │ ├── CategoryAdapter.java │ │ │ │ ├── CategoryViewHolder.java │ │ │ │ └── SelectCategoryPage.java │ │ │ ├── selectuser │ │ │ │ ├── UserAdapter.java │ │ │ │ └── UserSelectionActivity.java │ │ │ ├── statistics │ │ │ │ ├── ChartValueSelectedListener.java │ │ │ │ ├── StatisticViewHolder.java │ │ │ │ ├── StatisticsActivity.java │ │ │ │ ├── StatisticsAdapter.java │ │ │ │ └── StatisticsSpanSizeLookup.java │ │ │ └── usersettings │ │ │ │ ├── CollapsingLinearLayout.java │ │ │ │ ├── SettingsActivity.java │ │ │ │ ├── SettingsAdapter.java │ │ │ │ ├── SettingsViewHolder.java │ │ │ │ └── slidertimeperiod │ │ │ │ ├── DateComponent.java │ │ │ │ └── TimePeriodSlider.java │ │ │ ├── database │ │ │ ├── AnswerDataSource.java │ │ │ ├── CategoryDataSource.java │ │ │ ├── ChallengeDataSource.java │ │ │ ├── ChallengeStage.java │ │ │ ├── ChallengeType.java │ │ │ ├── CompletionDataSource.java │ │ │ ├── DatabaseModule.java │ │ │ ├── SettingsDataSource.java │ │ │ ├── StatisticsDataSource.java │ │ │ └── UserDataSource.java │ │ │ ├── logic │ │ │ ├── CompletionLogic.java │ │ │ ├── DueChallengeLogic.java │ │ │ ├── SettingsLogic.java │ │ │ ├── UserLogicFactory.java │ │ │ ├── UserManager.java │ │ │ ├── fileimport │ │ │ │ ├── FileImport.java │ │ │ │ ├── bpc │ │ │ │ │ ├── BPCObjects.java │ │ │ │ │ ├── BPCRead.java │ │ │ │ │ └── BPCWrite.java │ │ │ │ └── exceptions │ │ │ │ │ ├── ElementAmountException.java │ │ │ │ │ ├── FileFormatException.java │ │ │ │ │ ├── InvalidAttributeException.java │ │ │ │ │ └── UnexpectedElementException.java │ │ │ └── statistics │ │ │ │ ├── ChartDataLogic.java │ │ │ │ ├── ChartSettings.java │ │ │ │ ├── CustomizedFormatter.java │ │ │ │ ├── StatisticType.java │ │ │ │ └── StatisticsLogic.java │ │ │ ├── model │ │ │ ├── Answer.java │ │ │ ├── AnswerDao.java │ │ │ ├── Category.java │ │ │ ├── CategoryDao.java │ │ │ ├── Challenge.java │ │ │ ├── ChallengeDao.java │ │ │ ├── Completion.java │ │ │ ├── CompletionDao.java │ │ │ ├── DaoMaster.java │ │ │ ├── DaoSession.java │ │ │ ├── Settings.java │ │ │ ├── SettingsDao.java │ │ │ ├── Statistics.java │ │ │ ├── StatisticsDao.java │ │ │ ├── User.java │ │ │ └── UserDao.java │ │ │ └── utility │ │ │ ├── DividerItemDecoration.java │ │ │ ├── FileUtils.java │ │ │ └── ImageProxy.java │ └── res │ │ ├── color │ │ └── multiplechoice_button.xml │ │ ├── drawable-hdpi │ │ ├── ic_check.png │ │ ├── ic_check_white_24dp.png │ │ ├── ic_cross.png │ │ ├── ic_expand_less_white_24dp.png │ │ ├── ic_expand_more_white_24dp.png │ │ ├── ic_happyphaser.png │ │ ├── ic_navigate_next_white_24dp.png │ │ ├── ic_person_white_24dp.png │ │ ├── ic_person_white_48dp.png │ │ ├── ic_settings_white_24dp.png │ │ └── ic_settings_white_48dp.png │ │ ├── drawable-mdpi │ │ ├── ic_check.png │ │ ├── ic_check_white_24dp.png │ │ ├── ic_cross.png │ │ ├── ic_expand_less_white_24dp.png │ │ ├── ic_expand_more_white_24dp.png │ │ ├── ic_happyphaser.png │ │ ├── ic_navigate_next_white_24dp.png │ │ ├── ic_person_white_24dp.png │ │ ├── ic_person_white_48dp.png │ │ ├── ic_settings_white_24dp.png │ │ └── ic_settings_white_48dp.png │ │ ├── drawable-xhdpi │ │ ├── ic_check.png │ │ ├── ic_check_white_24dp.png │ │ ├── ic_cross.png │ │ ├── ic_expand_less_white_24dp.png │ │ ├── ic_expand_more_white_24dp.png │ │ ├── ic_happyphaser.png │ │ ├── ic_navigate_next_white_24dp.png │ │ ├── ic_person_white_24dp.png │ │ ├── ic_person_white_48dp.png │ │ ├── ic_settings_white_24dp.png │ │ └── ic_settings_white_48dp.png │ │ ├── drawable-xxhdpi │ │ ├── ic_check.png │ │ ├── ic_check_white_24dp.png │ │ ├── ic_cross.png │ │ ├── ic_expand_less_white_24dp.png │ │ ├── ic_expand_more_white_24dp.png │ │ ├── ic_happyphaser.png │ │ ├── ic_navigate_next_white_24dp.png │ │ ├── ic_person_white_24dp.png │ │ ├── ic_person_white_48dp.png │ │ ├── ic_settings_white_24dp.png │ │ └── ic_settings_white_48dp.png │ │ ├── drawable-xxxhdpi │ │ ├── ic_check.png │ │ ├── ic_check_white_24dp.png │ │ ├── ic_cross.png │ │ ├── ic_expand_less_white_24dp.png │ │ ├── ic_expand_more_white_24dp.png │ │ ├── ic_happyphaser.png │ │ ├── ic_navigate_next_white_24dp.png │ │ ├── ic_person_white_24dp.png │ │ ├── ic_person_white_48dp.png │ │ ├── ic_settings_white_24dp.png │ │ └── ic_settings_white_48dp.png │ │ ├── drawable │ │ ├── all.jpg │ │ ├── anonymous.png │ │ ├── anonymous2.png │ │ ├── anonymous2_girl.png │ │ ├── architektur.jpg │ │ ├── astronaut.png │ │ ├── background_splash.xml │ │ ├── basketball_man.png │ │ ├── bomberman.png │ │ ├── bomberman2.png │ │ ├── boxer_hispanic.png │ │ ├── bride_hispanic_material.png │ │ ├── budist.png │ │ ├── call_center_operator_man.png │ │ ├── cashier_woman.png │ │ ├── computer.jpg │ │ ├── cook2_man.png │ │ ├── englisch.jpg │ │ ├── european_commission.jpg │ │ ├── international_trade.jpg │ │ ├── multichoice_bg_checked.xml │ │ ├── multichoice_bg_unchecked.xml │ │ ├── multiple_choice_toggle.xml │ │ ├── physik_elektrizitaet.jpg │ │ ├── progress.xml │ │ ├── team.jpg │ │ └── text_meta_data.xml │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_challenge.xml │ │ ├── activity_create_user.xml │ │ ├── activity_import_challenges.xml │ │ ├── activity_proxy.xml │ │ ├── activity_select_category.xml │ │ ├── activity_settings.xml │ │ ├── activity_statistics.xml │ │ ├── activity_user_selection.xml │ │ ├── appbar_layout.xml │ │ ├── avatar_picker.xml │ │ ├── challenge_meta_data.xml │ │ ├── control_time_period_slider.xml │ │ ├── fragment_challenge_multiple_choice.xml │ │ ├── fragment_challenge_self_test.xml │ │ ├── fragment_challenge_self_test_null.xml │ │ ├── fragment_challenge_text.xml │ │ ├── fragment_finish_challenge.xml │ │ ├── list_item_category.xml │ │ ├── list_item_setting.xml │ │ ├── list_item_statistic_most_played.xml │ │ ├── list_item_statistic_pie_chart.xml │ │ ├── list_item_user.xml │ │ ├── mainactivity.xml │ │ ├── multiplechoice_button.xml │ │ └── self_test_dialog.xml │ │ ├── menu │ │ └── menu.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── raw │ │ ├── challenges.bpc │ │ └── credits.txt │ │ ├── values-de │ │ └── strings.xml │ │ ├── values-es │ │ └── strings.xml │ │ ├── values-v21 │ │ ├── strings.xml │ │ └── styles.xml │ │ ├── values-w820dp │ │ ├── dimens.xml │ │ └── strings.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── de │ └── fhdw │ └── ergoholics │ └── brainphaser │ └── ExampleUnitTest.java ├── brainphaserdaogenerator ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── de │ └── fhdw │ └── ergoholics │ └── brainphasergenerator │ └── BrainphaserDaoGenerator.java ├── build.gradle ├── documentation ├── config.properties └── pdfdoclet-2.50.1-SNAPSHOT-all.jar ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .DS_Store 3 | .gradle 4 | .idea 5 | /.idea/libraries 6 | /.idea/workspace.xml 7 | /build 8 | /captures 9 | /local.properties 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | # Emulator Management: Create, Start and Wait 3 | before_script: 4 | - echo no | android create avd --force -n test -t android-19 --abi armeabi-v7a 5 | - emulator -avd test -no-audio -no-window & 6 | - android-wait-for-emulator 7 | - adb shell input keyevent 82 & 8 | android: 9 | components: 10 | # use the latest revision of Android SDK Tools 11 | - platform-tools 12 | - tools 13 | 14 | # The BuildTools version used by your project 15 | - build-tools-24.0.0 16 | 17 | # The SDK version used to compile your project 18 | - android-23 19 | 20 | # Additional components 21 | - extra-android-support 22 | - extra-google-m2repository 23 | - extra-android-m2repository 24 | 25 | # Specify at least one system image, 26 | # if you need to run emulator(s) during your tests 27 | - sys-img-armeabi-v7a-android-19 28 | - sys-img-x86-android-17 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BrainPhaser 2 | 3 | [![Build Status](https://travis-ci.org/Kamshak/BrainPhaser.svg?branch=master)](https://travis-ci.org/Kamshak/BrainPhaser) 4 | 5 | Android Quiz App in Material Design made with Java. Designed for tablets in landscape or smartphones in portrait. 6 | 7 |

8 | Launcher Icon 9 |

10 | 11 | ## Features 12 | 13 | - Different Categories 14 | - 3 Different Types of Questions ("Challenges"): Multiple Choice, Self-Check, Text Entry 15 | - Material Design 16 | - Import of Challenges/Categories via XML 17 | - Multiple Users 18 | - Statistics 19 | - Settings 20 | - Supported Langauages: English, German and Spanish 21 | 22 | ## Screenshots 23 | 24 | ![User Selection](https://s3-eu-west-1.amazonaws.com/pointshop2/2016-05-18+08.02.11.jpg) 25 | ![Category Selection](https://s3-eu-west-1.amazonaws.com/pointshop2/2016-05-18+08.02.06.jpg) 26 | ![Challengemc](https://s3-eu-west-1.amazonaws.com/pointshop2/2016-05-18+08.06.01.jpg) 27 | ![Selfcheck](https://s3-eu-west-1.amazonaws.com/pointshop2/2016-05-18+08.06.09.jpg) 28 | ![SC2](https://s3-eu-west-1.amazonaws.com/pointshop2/2016-05-18+08.06.13.jpg) 29 | ![FreeEntry](https://s3-eu-west-1.amazonaws.com/pointshop2/2016-05-18+08.06.27.jpg) 30 | ![Statistics](https://s3-eu-west-1.amazonaws.com/pointshop2/2016-05-18+08.02.40.jpg) 31 | ![Settings](https://s3-eu-west-1.amazonaws.com/pointshop2/2016-05-18+08.02.24.jpg) 32 | 33 | ## License 34 | 35 | Brain Phase Android Quiz App 36 | Copyright (C) 2016 Daniel Hoogen, Lars Kahra, Christian Kost, Thomas Stückel, Valentin Funk 37 | 38 | This program is free software: you can redistribute it and/or modify 39 | it under the terms of the GNU General Public License as published by 40 | the Free Software Foundation, either version 3 of the License, or 41 | (at your option) any later version. 42 | 43 | This program is distributed in the hope that it will be useful, 44 | but WITHOUT ANY WARRANTY; without even the implied warranty of 45 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 46 | GNU General Public License for more details. 47 | 48 | You should have received a copy of the GNU General Public License 49 | along with this program. If not, see . 50 | 51 | EN & ES translations by [ordago](https://github.com/ordago) 52 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\funkv\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/androidTest/java/de/fhdw/ergoholics/brainphaser/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/de/fhdw/ergoholics/brainphaser/DaggerActivityTestRule.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | /* 4 | * Copyright (C) 2015 Tomasz Rozbicki 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.app.Activity; 20 | import android.app.Application; 21 | import android.support.annotation.NonNull; 22 | import android.support.test.InstrumentationRegistry; 23 | import android.support.test.rule.ActivityTestRule; 24 | 25 | /** 26 | * {@link ActivityTestRule} which provides hook for 27 | * {@link ActivityTestRule#beforeActivityLaunched()} method. Can be used for test dependency 28 | * injection especially in Espresso based tests. 29 | * 30 | * @author Tomasz Rozbicki 31 | */ 32 | public class DaggerActivityTestRule extends ActivityTestRule { 33 | 34 | private final OnBeforeActivityLaunchedListener mListener; 35 | 36 | public DaggerActivityTestRule(Class activityClass, 37 | @NonNull OnBeforeActivityLaunchedListener listener) { 38 | this(activityClass, false, listener); 39 | } 40 | 41 | public DaggerActivityTestRule(Class activityClass, boolean initialTouchMode, 42 | @NonNull OnBeforeActivityLaunchedListener listener) { 43 | this(activityClass, initialTouchMode, true, listener); 44 | } 45 | 46 | public DaggerActivityTestRule(Class activityClass, boolean initialTouchMode, 47 | boolean launchActivity, 48 | @NonNull OnBeforeActivityLaunchedListener listener) { 49 | super(activityClass, initialTouchMode, launchActivity); 50 | mListener = listener; 51 | } 52 | 53 | @Override 54 | protected void beforeActivityLaunched() { 55 | super.beforeActivityLaunched(); 56 | mListener.beforeActivityLaunched((Application) InstrumentationRegistry.getInstrumentation() 57 | .getTargetContext().getApplicationContext(), getActivity()); 58 | } 59 | 60 | public interface OnBeforeActivityLaunchedListener { 61 | 62 | void beforeActivityLaunched(@NonNull Application application, @NonNull T activity); 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/de/fhdw/ergoholics/brainphaser/MockTestRunner.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.support.test.runner.AndroidJUnitRunner; 6 | 7 | /** 8 | * Created by funkv on 07.03.2016. 9 | */ 10 | public class MockTestRunner extends AndroidJUnitRunner { 11 | @Override 12 | public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { 13 | return super.newApplication(cl, TestBrainPhaserApplication.class.getName(), context); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/androidTest/java/de/fhdw/ergoholics/brainphaser/TestAppModule.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import org.mockito.Mockito; 7 | 8 | import javax.inject.Singleton; 9 | 10 | import dagger.Module; 11 | import dagger.Provides; 12 | 13 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.AnswerFragmentFactory; 14 | import de.fhdw.ergoholics.brainphaser.database.CompletionDataSource; 15 | import de.fhdw.ergoholics.brainphaser.database.UserDataSource; 16 | import de.fhdw.ergoholics.brainphaser.logic.CompletionLogic; 17 | import de.fhdw.ergoholics.brainphaser.logic.SettingsLogic; 18 | import de.fhdw.ergoholics.brainphaser.logic.UserLogicFactory; 19 | import de.fhdw.ergoholics.brainphaser.logic.UserManager; 20 | 21 | /** 22 | * Created by funkv on 07.03.2016. 23 | */ 24 | @Module 25 | public class TestAppModule { 26 | BrainPhaserApplication mApplication; 27 | 28 | public TestAppModule(BrainPhaserApplication application) { 29 | mApplication = application; 30 | } 31 | 32 | @Provides 33 | @Singleton 34 | Application providesApplication() { 35 | return mApplication; 36 | } 37 | 38 | @Provides 39 | @Singleton 40 | BrainPhaserApplication providesBpApp() { 41 | return mApplication; 42 | } 43 | 44 | @Provides 45 | @Singleton 46 | UserManager providesUserManager(Application application, UserDataSource userDataSource) { 47 | return new UserManager(application, userDataSource); 48 | } 49 | 50 | @Provides 51 | @Singleton 52 | Context providesContext() { 53 | return mApplication.getApplicationContext(); 54 | } 55 | 56 | @Provides 57 | @Singleton 58 | UserLogicFactory providesUserLogic(BrainPhaserApplication app) { 59 | return Mockito.mock(UserLogicFactory.class); 60 | } 61 | 62 | @Provides 63 | @Singleton 64 | SettingsLogic providesSettingsLogic() { 65 | return new SettingsLogic(); 66 | } 67 | 68 | @Provides 69 | @Singleton 70 | AnswerFragmentFactory providesFragmentFactory() { return new AnswerFragmentFactory(); } 71 | 72 | @Provides 73 | @Singleton 74 | CompletionLogic providesCompletionLogic(CompletionDataSource ds) { 75 | return new CompletionLogic(ds); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/androidTest/java/de/fhdw/ergoholics/brainphaser/TestBrainPhaserApplication.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | /** 4 | * Created by funkv on 07.03.2016. 5 | */ 6 | public class TestBrainPhaserApplication extends BrainPhaserApplication { 7 | BrainPhaserComponent mTestComponent; 8 | public void setTestComponent(BrainPhaserComponent component) { 9 | mTestComponent = component; 10 | } 11 | 12 | @Override 13 | public BrainPhaserComponent getComponent() { 14 | return mTestComponent; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/androidTest/java/de/fhdw/ergoholics/brainphaser/TestUtils.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.test.espresso.matcher.BoundedMatcher; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | 8 | import org.hamcrest.Description; 9 | import org.hamcrest.Matcher; 10 | 11 | import static com.google.common.base.Preconditions.checkNotNull; 12 | /** 13 | * Created by funkv on 05.03.2016. 14 | */ 15 | public class TestUtils { 16 | // http://stackoverflow.com/questions/31394569/how-to-assert-inside-a-recyclerview-in-espresso 17 | public static Matcher atPosition(final int position, @NonNull final Matcher itemMatcher) { 18 | checkNotNull(itemMatcher); 19 | return new BoundedMatcher(RecyclerView.class) { 20 | @Override 21 | public void describeTo(Description description) { 22 | description.appendText("has item at position " + position + ": "); 23 | itemMatcher.describeTo(description); 24 | } 25 | 26 | @Override 27 | protected boolean matchesSafely(final RecyclerView view) { 28 | RecyclerView.ViewHolder viewHolder = view.findViewHolderForAdapterPosition(position); 29 | return viewHolder != null && itemMatcher.matches(viewHolder.itemView); 30 | } 31 | }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/androidTest/java/de/fhdw/ergoholics/brainphaser/database/MockDatabaseModule.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | 6 | import org.mockito.Mockito; 7 | 8 | import javax.inject.Singleton; 9 | 10 | import dagger.Module; 11 | import dagger.Provides; 12 | import de.fhdw.ergoholics.brainphaser.model.DaoMaster; 13 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 14 | 15 | /** 16 | * Created by funkv on 07.03.2016. 17 | */ 18 | @Module 19 | public class MockDatabaseModule { 20 | DaoMaster.DevOpenHelper mDevOpenHelper; 21 | SQLiteDatabase mDatabase; 22 | 23 | public MockDatabaseModule(Context context, String databaseName) { 24 | mDevOpenHelper = new DaoMaster.DevOpenHelper(context, databaseName, null); 25 | mDatabase = mDevOpenHelper.getWritableDatabase(); 26 | } 27 | 28 | @Provides 29 | @Singleton 30 | DaoSession provideSession() { 31 | DaoMaster daoMaster = new DaoMaster(mDatabase); 32 | return daoMaster.newSession(); 33 | } 34 | 35 | @Provides 36 | @Singleton 37 | SQLiteDatabase provideDatabase() { 38 | return mDevOpenHelper.getWritableDatabase(); 39 | } 40 | 41 | @Provides 42 | @Singleton 43 | AnswerDataSource provideAnswerDataSource(DaoSession session) { 44 | return new AnswerDataSource(session); 45 | } 46 | 47 | @Provides 48 | @Singleton 49 | ChallengeDataSource provideChallengeDataSource(DaoSession session) { 50 | return new ChallengeDataSource(session); 51 | } 52 | 53 | @Provides 54 | @Singleton 55 | CompletionDataSource provideCompletionDataSource(DaoSession session) { 56 | return new CompletionDataSource(session); 57 | } 58 | 59 | @Provides 60 | @Singleton 61 | SettingsDataSource provideSettingsDataSource(DaoSession session) { 62 | return new SettingsDataSource(session); 63 | } 64 | 65 | @Provides 66 | @Singleton 67 | UserDataSource provideUserDataSource(DaoSession session, SettingsDataSource settingsDataSource) { 68 | return new UserDataSource(session, settingsDataSource); 69 | } 70 | 71 | @Provides 72 | @Singleton 73 | CategoryDataSource provideCategoryDataSource(DaoSession session) { 74 | return Mockito.mock(CategoryDataSource.class); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/androidTest/java/de/fhdw/ergoholics/brainphaser/logic/MockTestUserLogicFactory.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic; 2 | 3 | import org.mockito.Mockito; 4 | 5 | import de.fhdw.ergoholics.brainphaser.model.User; 6 | 7 | /** 8 | * Created by funkv on 07.03.2016. 9 | */ 10 | public class MockTestUserLogicFactory extends UserLogicFactory { 11 | @Override 12 | public DueChallengeLogic createDueChallengeLogic(User user) { 13 | return Mockito.mock(DueChallengeLogic.class); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/challenges/test.bpc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/AppModule.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import javax.inject.Singleton; 7 | 8 | import dagger.Module; 9 | import dagger.Provides; 10 | 11 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.AnswerFragmentFactory; 12 | import de.fhdw.ergoholics.brainphaser.database.CompletionDataSource; 13 | import de.fhdw.ergoholics.brainphaser.database.UserDataSource; 14 | import de.fhdw.ergoholics.brainphaser.logic.CompletionLogic; 15 | import de.fhdw.ergoholics.brainphaser.logic.SettingsLogic; 16 | import de.fhdw.ergoholics.brainphaser.logic.UserLogicFactory; 17 | import de.fhdw.ergoholics.brainphaser.logic.UserManager; 18 | import de.fhdw.ergoholics.brainphaser.logic.statistics.ChartSettings; 19 | 20 | /** 21 | * Created by funkv on 06.03.2016. 22 | * 23 | * Defines how instances are created for the App 24 | */ 25 | @Module 26 | public class AppModule { 27 | BrainPhaserApplication mApplication; 28 | 29 | public AppModule(BrainPhaserApplication application) { 30 | mApplication = application; 31 | } 32 | 33 | @Provides 34 | @Singleton 35 | Application providesApplication() { 36 | return mApplication; 37 | } 38 | 39 | @Provides 40 | @Singleton 41 | BrainPhaserApplication providesBpApp() { 42 | return mApplication; 43 | } 44 | 45 | @Provides 46 | @Singleton 47 | UserManager providesUserManager(Application application, UserDataSource userDataSource) { 48 | return new UserManager(application, userDataSource); 49 | } 50 | 51 | @Provides 52 | @Singleton 53 | Context providesContext() { 54 | return mApplication.getApplicationContext(); 55 | } 56 | 57 | @Provides 58 | @Singleton 59 | UserLogicFactory providesUserLogic(BrainPhaserApplication app) { 60 | UserLogicFactory factory = new UserLogicFactory(); 61 | app.getComponent().inject(factory); 62 | return factory; 63 | } 64 | 65 | @Provides 66 | @Singleton 67 | ChartSettings providesChartSettings(BrainPhaserApplication app) { 68 | return new ChartSettings(app); 69 | } 70 | 71 | @Provides 72 | @Singleton 73 | SettingsLogic providesSettingsLogic() { 74 | return new SettingsLogic(); 75 | } 76 | 77 | @Provides 78 | @Singleton 79 | AnswerFragmentFactory providesFragmentFactory() { return new AnswerFragmentFactory(); } 80 | 81 | @Provides 82 | @Singleton 83 | CompletionLogic providesCompletionLogic(CompletionDataSource ds) { 84 | return new CompletionLogic(ds); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/BrainPhaserApplication.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | import android.app.Application; 4 | import android.content.res.Resources; 5 | import android.util.DisplayMetrics; 6 | 7 | import net.danlew.android.joda.JodaTimeAndroid; 8 | 9 | import javax.inject.Singleton; 10 | 11 | import dagger.Component; 12 | import de.fhdw.ergoholics.brainphaser.database.DatabaseModule; 13 | 14 | /** 15 | * Created by funkv on 17.02.2016. 16 | * 17 | * Custom Application class for hooking into App creation 18 | */ 19 | public class BrainPhaserApplication extends Application { 20 | public static String PACKAGE_NAME; 21 | public static BrainPhaserComponent component; 22 | 23 | /** 24 | * Creates the Production app Component 25 | */ 26 | protected BrainPhaserComponent createComponent( ) { 27 | return DaggerBrainPhaserApplication_ApplicationComponent.builder() 28 | .appModule(new AppModule(this)) 29 | .databaseModule(new DatabaseModule(getApplicationContext(), "prodDb")) 30 | .build(); 31 | } 32 | 33 | /** 34 | * Returns the Component for use with Dependency Injection for this 35 | * Application. 36 | * @return compoenent to use for DI 37 | */ 38 | public BrainPhaserComponent getComponent( ) { 39 | return component; 40 | } 41 | 42 | /** 43 | * initializes the DaoManager with a writeable database 44 | */ 45 | @Override 46 | public void onCreate() { 47 | super.onCreate(); 48 | JodaTimeAndroid.init(this); 49 | component = createComponent(); 50 | PACKAGE_NAME = getApplicationContext().getPackageName(); 51 | } 52 | 53 | /** 54 | * Defines the Component to use in the Production Application. 55 | * The component is a bridge between Modules and Injects. 56 | * It creates instances of all the types defined. 57 | */ 58 | @Singleton 59 | @Component(modules = {AppModule.class, DatabaseModule.class}) 60 | public interface ApplicationComponent extends BrainPhaserComponent { 61 | } 62 | 63 | /** 64 | * Licensed under CC BY-SA (c) 2012 Muhammad Nabeel Arif 65 | * http://stackoverflow.com/questions/4605527/converting-pixels-to-dp 66 | * 67 | * This method converts device specific pixels to density independent pixels. 68 | * 69 | * @param px A value in px (pixels) unit. Which we need to convert into dp 70 | * @return A float value to represent dp equivalent to px value 71 | */ 72 | public float convertPixelsToDp(float px){ 73 | Resources resources = getResources(); 74 | DisplayMetrics metrics = resources.getDisplayMetrics(); 75 | float dp = px / ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); 76 | return dp; 77 | } 78 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/BrainPhaserComponent.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser; 2 | 3 | import de.fhdw.ergoholics.brainphaser.activities.aboutscreen.AboutActivity; 4 | import de.fhdw.ergoholics.brainphaser.activities.createuser.CreateUserActivity; 5 | import de.fhdw.ergoholics.brainphaser.activities.main.MainActivity; 6 | import de.fhdw.ergoholics.brainphaser.activities.main.ProxyActivity; 7 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.AnswerFragment; 8 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.ChallengeActivity; 9 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.multiplechoice.ButtonViewState; 10 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.multiplechoice.MultipleChoiceFragment; 11 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.selfcheck.SelfTestFragment; 12 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.text.TextFragment; 13 | import de.fhdw.ergoholics.brainphaser.activities.selectcategory.SelectCategoryPage; 14 | import de.fhdw.ergoholics.brainphaser.activities.selectuser.UserAdapter; 15 | import de.fhdw.ergoholics.brainphaser.activities.selectuser.UserSelectionActivity; 16 | import de.fhdw.ergoholics.brainphaser.activities.statistics.StatisticsActivity; 17 | import de.fhdw.ergoholics.brainphaser.activities.usersettings.SettingsActivity; 18 | import de.fhdw.ergoholics.brainphaser.logic.UserLogicFactory; 19 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.bpc.BPCWrite; 20 | 21 | /** 22 | * Created by funkv on 06.03.2016. 23 | * 24 | * App Component that defines injection targets for DI. 25 | */ 26 | public interface BrainPhaserComponent { 27 | void inject(MainActivity mainActivity); 28 | void inject(ProxyActivity activity); 29 | void inject(ChallengeActivity challengeActivity); 30 | void inject(MultipleChoiceFragment questionFragment); 31 | void inject(TextFragment textFragment); 32 | void inject(SelfTestFragment selfTestFragment); 33 | void inject(CreateUserActivity createUserActivity); 34 | void inject(UserAdapter userAdapter); 35 | void inject(UserSelectionActivity activity); 36 | void inject(StatisticsActivity activity); 37 | void inject(SettingsActivity activity); 38 | 39 | void inject(AboutActivity activity); 40 | 41 | void inject(SelectCategoryPage selectCategoryPage); 42 | void inject(AnswerFragment answerFragment); 43 | 44 | void inject(BPCWrite bpcWrite); 45 | void inject(ButtonViewState state); 46 | 47 | void inject(UserLogicFactory f); 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/BrainPhaserActivity.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | 6 | import de.fhdw.ergoholics.brainphaser.BrainPhaserApplication; 7 | import de.fhdw.ergoholics.brainphaser.BrainPhaserComponent; 8 | 9 | /** 10 | * Created by funkv on 06.03.2016. 11 | *

12 | * Base Activity class to be used by all activitites in the project. 13 | * Subclasses need to implement injectComponent to use the Depency Injector. 14 | * See: https://blog.gouline.net/2015/05/04/dagger-2-even-sharper-less-square/ 15 | */ 16 | public abstract class BrainPhaserActivity extends AppCompatActivity { 17 | /** 18 | * OnCreate injects components 19 | * 20 | * @param savedInstanceState Ignored 21 | */ 22 | @Override 23 | public void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | injectComponent(((BrainPhaserApplication) getApplication()).getComponent()); 26 | } 27 | 28 | /** 29 | * Called to inject dependencies. Calls component.inject(this) as 30 | * uniform implementation in all Activities. 31 | * 32 | * @param component the component supplied by the Application to resolve dependencies 33 | */ 34 | protected abstract void injectComponent(BrainPhaserComponent component); 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/BrainPhaserFragment.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.Fragment; 5 | 6 | import de.fhdw.ergoholics.brainphaser.BrainPhaserApplication; 7 | import de.fhdw.ergoholics.brainphaser.BrainPhaserComponent; 8 | 9 | /** 10 | * Created by funkv on 06.03.2016. 11 | *

12 | * Base Activity class to be used by all Fragments in the project. 13 | * Subclasses need to implement injectComponent to use the Depency Injector. 14 | * See: https://blog.gouline.net/2015/05/04/dagger-2-even-sharper-less-square/ 15 | */ 16 | public abstract class BrainPhaserFragment extends Fragment { 17 | /** 18 | * OnCreate injects components 19 | * 20 | * @param savedInstanceState Ignored 21 | */ 22 | @Override 23 | public void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | 26 | injectComponent(((BrainPhaserApplication) getActivity().getApplication()).getComponent()); 27 | } 28 | 29 | /** 30 | * Called to inject dependencies. Should call component.inject(this) as 31 | * uniform implementation in all Activities. 32 | * 33 | * @param component 34 | */ 35 | protected abstract void injectComponent(BrainPhaserComponent component); 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/aboutscreen/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.aboutscreen; 2 | 3 | import android.content.res.Resources; 4 | import android.os.Bundle; 5 | import android.support.v7.app.ActionBar; 6 | import android.support.v7.widget.Toolbar; 7 | import android.widget.TextView; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | 12 | import de.fhdw.ergoholics.brainphaser.BrainPhaserComponent; 13 | import de.fhdw.ergoholics.brainphaser.R; 14 | import de.fhdw.ergoholics.brainphaser.activities.BrainPhaserActivity; 15 | import de.fhdw.ergoholics.brainphaser.utility.FileUtils; 16 | 17 | /** 18 | * Created by thomasstuckel on 07/03/2016. 19 | * 20 | * opens and reads the license from a .txt file and shows on the about screen 21 | */ 22 | public class AboutActivity extends BrainPhaserActivity { 23 | private TextView mAboutText; 24 | 25 | /** 26 | * {@inheritDoc} 27 | */ 28 | @Override 29 | protected void injectComponent(BrainPhaserComponent component) { 30 | component.inject(this); 31 | } 32 | 33 | /** 34 | * This method is called when the activity is created 35 | * 36 | * @param savedInstanceState handed over to super constructor 37 | */ 38 | @Override 39 | public void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | 42 | setContentView(R.layout.activity_about); 43 | 44 | mAboutText = (TextView) findViewById(R.id.action_about); 45 | 46 | try { 47 | String contents = getStringFromRawFile(); 48 | mAboutText.setText(contents); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | } 52 | //load the toolbar from layout into the toolbar varible 53 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 54 | 55 | // Set as Actionbar 56 | setSupportActionBar(toolbar); 57 | 58 | // Get a support ActionBar corresponding to this toolbar 59 | ActionBar ab = getSupportActionBar(); 60 | 61 | // Enable the Up button 62 | ab.setDisplayHomeAsUpEnabled(true); 63 | } 64 | 65 | /** 66 | * Resource: Pro Android by Syes Y. Hashimi and Satya Komatineni (2009) p.59 67 | * opens the textfile from credits.txt and reads and converts with convertStreamToString() into a String 68 | * @return string from .txt file 69 | * @throws IOException 70 | */ 71 | String getStringFromRawFile() throws IOException { 72 | Resources r = getResources(); 73 | InputStream is = r.openRawResource(R.raw.credits); 74 | String myText = FileUtils.convertStreamToString(is); 75 | is.close(); 76 | return myText; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/createuser/AvatarImageAdapter.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.createuser; 2 | 3 | import android.content.Context; 4 | import android.util.TypedValue; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | import android.widget.GridView; 9 | 10 | import com.makeramen.roundedimageview.RoundedImageView; 11 | 12 | /** 13 | * Created by funkv on 13.02.2016, adapted from http://developer.android.com/guide/topics/ui/layout/gridview.html 14 | *

15 | * Creates RoundedImages for each Avatar from the AvatarPickerDialogFragment. 16 | */ 17 | public class AvatarImageAdapter extends BaseAdapter { 18 | private Context mContext; 19 | // references to our images 20 | private Integer[] mThumbIds = Avatars.getAvatarResources(); 21 | // references to ImageViews 22 | private RoundedImageView[] mImages = new RoundedImageView[mThumbIds.length]; 23 | 24 | /** 25 | * Constructor defines the context 26 | * 27 | * @param c Context 28 | */ 29 | public AvatarImageAdapter(Context c) { 30 | mContext = c; 31 | } 32 | 33 | /** 34 | * Get the length of the adapter 35 | * 36 | * @return Thumb-Id length 37 | */ 38 | public int getCount() { 39 | return mThumbIds.length; 40 | } 41 | 42 | /** 43 | * Get an object at the position 44 | * 45 | * @param position Position of the item 46 | * @return Object at the position 47 | */ 48 | public Object getItem(int position) { 49 | return mImages[position]; 50 | } 51 | 52 | /** 53 | * Get the id of an item 54 | * 55 | * @param position Position of the item 56 | * @return 0 57 | */ 58 | public long getItemId(int position) { 59 | return 0; 60 | } 61 | 62 | /** 63 | * Create a new ImageView for each item referenced by the Adapter 64 | */ 65 | public View getView(int position, View convertView, ViewGroup parent) { 66 | RoundedImageView imageView; 67 | if (convertView == null) { 68 | // if it's not recycled, initialize some attributes 69 | imageView = new RoundedImageView(mContext); 70 | 71 | int sizeDip = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 72 | 85.f, 73 | mContext.getResources().getDisplayMetrics()); 74 | 75 | imageView.setLayoutParams(new GridView.LayoutParams(sizeDip, sizeDip)); 76 | 77 | //imageView.setScaleType(ImageView.ScaleType.); 78 | imageView.setOval(true); 79 | imageView.setPadding(8, 8, 8, 8); 80 | } else { 81 | imageView = (RoundedImageView) convertView; 82 | } 83 | 84 | mImages[position] = imageView; 85 | imageView.setImageResource(mThumbIds[position]); 86 | return imageView; 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/createuser/Avatars.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.createuser; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | import de.fhdw.ergoholics.brainphaser.R; 7 | 8 | /** 9 | * Created by funkv on 15.02.2016. 10 | *

11 | * Class for bundling shared avatar functionality. 12 | */ 13 | public class Avatars { 14 | // List of all available avatars 15 | private static final Integer[] AVATARS = { 16 | R.drawable.anonymous, R.drawable.anonymous2_girl, 17 | R.drawable.astronaut, R.drawable.basketball_man, 18 | R.drawable.bomberman, R.drawable.bomberman2, 19 | R.drawable.boxer_hispanic, R.drawable.bride_hispanic_material, 20 | R.drawable.budist, R.drawable.call_center_operator_man, 21 | R.drawable.cashier_woman, R.drawable.cook2_man 22 | }; 23 | 24 | /** 25 | * Get a list of all avatar resource ids. 26 | * 27 | * @return Array containing all avatar resource ids. 28 | */ 29 | public static Integer[] getAvatarResources() { 30 | return AVATARS; 31 | } 32 | 33 | /** 34 | * Get the resource name for a given avatar resource id. 35 | * 36 | * @param context 37 | * @param avatarResourceId resource id of the avatar 38 | * @return resource name of the avatar to be used for persistent storage. 39 | */ 40 | public static String getAvatarResourceName(Context context, Integer avatarResourceId) { 41 | Resources resources = context.getResources(); 42 | return resources.getResourceEntryName(avatarResourceId); 43 | } 44 | 45 | /** 46 | * Get the resource id for a given avatar name 47 | * 48 | * @param context 49 | * @param avatarResourceName name of the avatar 50 | * @return resource id 51 | */ 52 | public static Integer getAvatarResourceId(Context context, String avatarResourceName) { 53 | Resources resources = context.getResources(); 54 | return resources.getIdentifier(avatarResourceName, "drawable", context.getPackageName()); 55 | } 56 | 57 | /** 58 | * @return resource name of the default avatar 59 | */ 60 | public static String getDefaultAvatarResourceName() { 61 | return "anonymous"; 62 | } 63 | 64 | /** 65 | * @return resource id of the default avatar 66 | */ 67 | public static Integer getDefaultAvatarResourceId() { 68 | return R.drawable.anonymous; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/main/ProxyActivity.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.main; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | 7 | import java.io.InputStream; 8 | 9 | import javax.inject.Inject; 10 | 11 | import de.fhdw.ergoholics.brainphaser.BrainPhaserApplication; 12 | import de.fhdw.ergoholics.brainphaser.BrainPhaserComponent; 13 | import de.fhdw.ergoholics.brainphaser.R; 14 | import de.fhdw.ergoholics.brainphaser.activities.BrainPhaserActivity; 15 | import de.fhdw.ergoholics.brainphaser.activities.createuser.CreateUserActivity; 16 | import de.fhdw.ergoholics.brainphaser.database.ChallengeDataSource; 17 | import de.fhdw.ergoholics.brainphaser.logic.UserManager; 18 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.FileImport; 19 | 20 | /** 21 | * Created by funkv on 29.02.2016. 22 | * 23 | * The activity redirects to user creation on first launch. On later launches it loads last selected 24 | * user and redirects to the main activity. 25 | */ 26 | public class ProxyActivity extends BrainPhaserActivity { 27 | @Inject 28 | UserManager mUserManager; 29 | @Inject 30 | ChallengeDataSource mChallengeDataSource; 31 | 32 | /** 33 | * {@inheritDoc} 34 | */ 35 | @Override 36 | protected void injectComponent(BrainPhaserComponent component) { 37 | component.inject(this); 38 | } 39 | 40 | /** 41 | * This method is called when the activity is created 42 | * 43 | * @param savedInstanceState handed over to super constructor 44 | */ 45 | @Override 46 | public void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | 49 | setContentView(R.layout.activity_proxy); 50 | 51 | BrainPhaserApplication application = (BrainPhaserApplication)getApplication(); 52 | if (mUserManager.logInLastUser()) { 53 | Intent intent = new Intent(getApplicationContext(), MainActivity.class); 54 | intent.putExtra(MainActivity.EXTRA_SHOW_LOGGEDIN_SNACKBAR, true); 55 | 56 | startActivity(intent); 57 | finish(); 58 | } else { 59 | // Import challenges if the database does not include any 60 | if (mChallengeDataSource.getAll().size() == 0) { 61 | InputStream is = getResources().openRawResource(R.raw.challenges); 62 | try { 63 | FileImport.importBPC(is, application); 64 | } catch (Exception e) { 65 | throw new RuntimeException("An unexpected error has occured when trying to add " + 66 | "example challenges!"); 67 | } 68 | } 69 | 70 | startActivity(new Intent(Intent.ACTION_INSERT, Uri.EMPTY, getApplicationContext(), CreateUserActivity.class)); 71 | finish(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/playchallenge/AnswerAdapter.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.playchallenge; 2 | 3 | import android.support.v4.content.ContextCompat; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.Gravity; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import java.util.List; 12 | 13 | import de.fhdw.ergoholics.brainphaser.R; 14 | import de.fhdw.ergoholics.brainphaser.model.Answer; 15 | 16 | /** 17 | * Created by Christian Kost 18 | *

19 | * Adapter to load the given answers into a simple list 20 | */ 21 | public class AnswerAdapter extends RecyclerView.Adapter { 22 | private List mAnswers; 23 | private String mGivenAnswer; 24 | 25 | /** 26 | * Constructor for the answer adapter which loads the different answers of a challenge 27 | * 28 | * @param answers List of answers of the challenge 29 | * @param givenAnswer The given answer by the user 30 | */ 31 | public AnswerAdapter(List answers, String givenAnswer) { 32 | mAnswers = answers; 33 | mGivenAnswer = givenAnswer; 34 | } 35 | 36 | /** 37 | * Inflate the view 38 | * 39 | * @param parent Ignored 40 | * @param viewType Ignored 41 | * @return The ViewHolder with the inflated view 42 | */ 43 | @Override 44 | public AnswerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 45 | LayoutInflater myInflater = LayoutInflater.from(parent.getContext()); 46 | //Load the list template 47 | View customView = myInflater.inflate(android.R.layout.simple_list_item_1, parent, false); 48 | TextView textView = (TextView) customView.findViewById(android.R.id.text1); 49 | textView.setGravity(Gravity.CENTER); 50 | return new AnswerViewHolder(customView); 51 | } 52 | 53 | /** 54 | * Create a list item 55 | * 56 | * @param holder ViewHolder which binds the answer text 57 | * @param position The position of the answer item 58 | */ 59 | @Override 60 | public void onBindViewHolder(AnswerViewHolder holder, int position) { 61 | //bind the answer 62 | Answer answer = mAnswers.get(position); 63 | holder.bindAnswer(answer.getText()); 64 | } 65 | 66 | /** 67 | * Get the size of the view 68 | * 69 | * @return size of the answer list 70 | */ 71 | @Override 72 | public int getItemCount() { 73 | return mAnswers.size(); 74 | } 75 | 76 | /** 77 | * Answer View Holder holds the items in the AnswerList 78 | */ 79 | public class AnswerViewHolder extends RecyclerView.ViewHolder { 80 | private TextView mAnswerText; 81 | private int colorRight; 82 | 83 | /** 84 | * Constructor fo the ViewHolder. Sets up the answer text and the highlight color 85 | * 86 | * @param itemView View to find the TextView for the answer text 87 | */ 88 | public AnswerViewHolder(View itemView) { 89 | super(itemView); 90 | mAnswerText = (TextView) itemView.findViewById(android.R.id.text1); 91 | colorRight = ContextCompat.getColor(itemView.getContext(), R.color.colorRight); 92 | } 93 | 94 | /** 95 | * Set the answer text in the View Holder and highlight the given answer 96 | * 97 | * @param answer Answer text 98 | */ 99 | public void bindAnswer(String answer) { 100 | mAnswerText.setText(answer); 101 | // Ff the answer equals to the given answer, mark the text 102 | if (mGivenAnswer != null && mGivenAnswer.equals(answer)) { 103 | mAnswerText.setTextColor(colorRight); 104 | } 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/playchallenge/AnswerFragmentFactory.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.playchallenge; 2 | 3 | import java.util.HashMap; 4 | 5 | import de.fhdw.ergoholics.brainphaser.BuildConfig; 6 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.multiplechoice.MultipleChoiceFragment; 7 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.selfcheck.SelfTestFragment; 8 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.text.TextFragment; 9 | import de.fhdw.ergoholics.brainphaser.database.ChallengeType; 10 | 11 | /** 12 | * Created by Christian Kost 13 | *

14 | * Abstracts and bundles the creation of Fragments for Challenge Types. 15 | */ 16 | public class AnswerFragmentFactory { 17 | private static HashMap challengeTypeFactories; 18 | 19 | static { 20 | challengeTypeFactories = new HashMap<>(); 21 | challengeTypeFactories.put(ChallengeType.MULTIPLE_CHOICE, new AnswerFragmentCreator() { 22 | @Override 23 | public AnswerFragment createFragment() { 24 | return new MultipleChoiceFragment(); 25 | } 26 | }); 27 | challengeTypeFactories.put(ChallengeType.TEXT, new AnswerFragmentCreator() { 28 | @Override 29 | public AnswerFragment createFragment() { 30 | return new TextFragment(); 31 | } 32 | }); 33 | challengeTypeFactories.put(ChallengeType.SELF_TEST, new AnswerFragmentCreator() { 34 | @Override 35 | public AnswerFragment createFragment() { 36 | return new SelfTestFragment(); 37 | } 38 | }); 39 | } 40 | 41 | /** 42 | * Creates a fragment for the specified challengeType. 43 | * 44 | * @param challengeType one of ChallengeType.* 45 | * @return newly created fragment. 46 | */ 47 | public AnswerFragment createFragmentForType(int challengeType) { 48 | AnswerFragmentCreator creator = challengeTypeFactories.get(challengeType); 49 | if (BuildConfig.DEBUG && creator == null) { 50 | throw new RuntimeException("Invalid Challenge Type " + challengeType); 51 | } 52 | 53 | return creator.createFragment(); 54 | } 55 | 56 | /** 57 | * Interface to create an AnswerFragment 58 | */ 59 | private interface AnswerFragmentCreator { 60 | AnswerFragment createFragment(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/playchallenge/multiplechoice/ButtonViewState.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.playchallenge.multiplechoice; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import javax.inject.Inject; 7 | 8 | import de.fhdw.ergoholics.brainphaser.BrainPhaserApplication; 9 | import de.fhdw.ergoholics.brainphaser.database.AnswerDataSource; 10 | import de.fhdw.ergoholics.brainphaser.model.Answer; 11 | 12 | /** 13 | * Created by Christian Kost 14 | *

15 | * Represents an answer button's state including answer and toggle state. 16 | * Implement Parcelable to allow saving/restoring using bundles 17 | */ 18 | public class ButtonViewState implements Parcelable { 19 | public static final Parcelable.Creator CREATOR 20 | = new Parcelable.Creator() { 21 | public ButtonViewState createFromParcel(Parcel in) { 22 | return new ButtonViewState(in); 23 | } 24 | 25 | public ButtonViewState[] newArray(int size) { 26 | return new ButtonViewState[size]; 27 | } 28 | }; 29 | @Inject 30 | AnswerDataSource mAnswerDataSource; 31 | private boolean mToggleState = false; 32 | private Answer mAnswer; 33 | 34 | /** 35 | * Constructor instantiates the answer 36 | * 37 | * @param answer Answer text 38 | */ 39 | public ButtonViewState(Answer answer) { 40 | mAnswer = answer; 41 | } 42 | 43 | /** 44 | * @param in Parcel 45 | */ 46 | private ButtonViewState(Parcel in) { 47 | BrainPhaserApplication.component.inject(this); 48 | mAnswer = mAnswerDataSource.getById(in.readLong()); 49 | mToggleState = in.readInt() == 1; 50 | } 51 | 52 | /** 53 | * Returns the current ToggleState 54 | * 55 | * @return ToggleState 56 | */ 57 | public boolean getToggleState() { 58 | return mToggleState; 59 | } 60 | 61 | /** 62 | * Sets the ToggleState 63 | * 64 | * @param toggleState ToggleState 65 | */ 66 | public void setToggleState(boolean toggleState) { 67 | mToggleState = toggleState; 68 | } 69 | 70 | /** 71 | * Return the current Answer 72 | * 73 | * @return Answer 74 | */ 75 | public Answer getAnswer() { 76 | return mAnswer; 77 | } 78 | 79 | /** 80 | * Set the Answer 81 | * 82 | * @param answer Answer 83 | */ 84 | public void setAnswer(Answer answer) { 85 | mAnswer = answer; 86 | } 87 | 88 | /** 89 | * DescribeContents return 0 90 | * 91 | * @return 0 92 | */ 93 | @Override 94 | public int describeContents() { 95 | return 0; 96 | } 97 | 98 | /** 99 | * Writes the answer id and the toggle state to the given parcel 100 | * 101 | * @param dest the parel to write to 102 | * @param flags ignored 103 | */ 104 | @Override 105 | public void writeToParcel(Parcel dest, int flags) { 106 | dest.writeLong(mAnswer.getId()); 107 | dest.writeInt(mToggleState ? 1 : 0); 108 | } 109 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/playchallenge/selfcheck/SelfTestFragment.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.playchallenge.selfcheck; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | 10 | import de.fhdw.ergoholics.brainphaser.BrainPhaserComponent; 11 | import de.fhdw.ergoholics.brainphaser.R; 12 | import de.fhdw.ergoholics.brainphaser.activities.playchallenge.AnswerFragment; 13 | 14 | /** 15 | * Created by Christian Kost 16 | *

17 | * Fragment for a self-check challenge. 18 | */ 19 | public class SelfTestFragment extends AnswerFragment { 20 | private final static String KEY_CHECKING_ANSWER = "CHECKING_ANSWER"; 21 | 22 | private boolean mCheckingAnswer = false; 23 | 24 | /** 25 | * Sets up the view depending on the state 26 | * 27 | * @param inflater Inflates the fragment 28 | * @param container Container to inflate the fragment 29 | * @param savedInstanceState Reloads the old state of the fragment 30 | * @return Return the inflated view 31 | */ 32 | @Nullable 33 | @Override 34 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 35 | if (savedInstanceState != null) { 36 | mCheckingAnswer = savedInstanceState.getBoolean(KEY_CHECKING_ANSWER, false); 37 | } 38 | 39 | // Inflate the view depending on the state the fragment is currently in. 40 | if (mCheckingAnswer) { 41 | // shows all valid answers and asks user to confirm whether or not the selected answer is correct. 42 | View view = inflater.inflate(R.layout.fragment_challenge_self_test, container, false); 43 | 44 | Button btnRight = (Button) view.findViewById(R.id.answerRight); 45 | Button btnWrong = (Button) view.findViewById(R.id.answerWrong); 46 | //set on click listener to the button 47 | btnRight.setOnClickListener(new View.OnClickListener() { 48 | @Override 49 | public void onClick(View view) { 50 | //execute AnswerListener and loads the next screen 51 | mListener.onAnswerChecked(true, true); 52 | } 53 | }); 54 | btnWrong.setOnClickListener(new View.OnClickListener() { 55 | @Override 56 | public void onClick(View view) { 57 | //execute AnswerListener and loads the next screen 58 | mListener.onAnswerChecked(false, true); 59 | } 60 | }); 61 | 62 | return view; 63 | } else { 64 | // Shows only the hint to think of an answer and click on the FAB to continue. 65 | return inflater.inflate(R.layout.fragment_challenge_self_test_null, container, false); 66 | } 67 | } 68 | 69 | /** 70 | * Loads the list of answers 71 | */ 72 | @Override 73 | public void onStart() { 74 | super.onStart(); 75 | 76 | if (mCheckingAnswer) { 77 | //Loads the possible answers into a list 78 | populateRecyclerViewWithCorrectAnswers(R.id.answerListSelfCheck, null); 79 | } 80 | } 81 | 82 | /** 83 | * Saves the current state of the fragment 84 | * 85 | * @param outState Bundle that contains the Challenge-Id and 86 | */ 87 | @Override 88 | public void onSaveInstanceState(Bundle outState) { 89 | super.onSaveInstanceState(outState); 90 | outState.putBoolean(KEY_CHECKING_ANSWER, mCheckingAnswer); 91 | } 92 | 93 | /** 94 | * Reloads the fragment in checkAnswer mode. 95 | */ 96 | @Override 97 | public AnswerFragment.ContinueMode goToNextState() { 98 | this.mCheckingAnswer = true; 99 | if (!this.isDetached()) { 100 | // Reload this fragment 101 | getFragmentManager().beginTransaction() 102 | .detach(this) 103 | .attach(this) 104 | .commit(); 105 | } 106 | return ContinueMode.CONTINUE_HIDE_FAB; 107 | } 108 | 109 | /** 110 | * Inject components 111 | * 112 | * @param component BrainPhaserComponent 113 | */ 114 | @Override 115 | protected void injectComponent(BrainPhaserComponent component) { 116 | component.inject(this); 117 | } 118 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/selectcategory/CategoryAdapter.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.selectcategory; 2 | 3 | import android.support.v4.util.LongSparseArray; 4 | import android.support.v7.widget.LinearLayoutCompat; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import java.util.List; 11 | 12 | import de.fhdw.ergoholics.brainphaser.R; 13 | import de.fhdw.ergoholics.brainphaser.database.CategoryDataSource; 14 | import de.fhdw.ergoholics.brainphaser.model.Category; 15 | 16 | /** 17 | * Created by funkv on 17.02.2016. 18 | */ 19 | public class CategoryAdapter extends RecyclerView.Adapter { 20 | private List mCategories; 21 | private SelectionListener mListener; 22 | private LongSparseArray mDueChallengeCounts = new LongSparseArray<>(); 23 | 24 | /** 25 | * Adapter for Listing Categories in a recycler view 26 | * @param categories list of categories to show 27 | * @param dueChallengeCounts an SparseArray that maps category ids to their due challenge count. 28 | * @param listener listener that is notified when a category is clicked. 29 | */ 30 | public CategoryAdapter(List categories, LongSparseArray dueChallengeCounts, SelectionListener listener) { 31 | mListener = listener; 32 | mCategories = categories; 33 | mDueChallengeCounts = dueChallengeCounts; 34 | 35 | setHasStableIds(true); 36 | } 37 | 38 | /** 39 | * Notify the adapter that new due challenge counts are to be displayed 40 | * @param dueChallengeCounts due challenge counts to apply 41 | */ 42 | public void notifyDueChallengeCountsChanged(LongSparseArray dueChallengeCounts) { 43 | mDueChallengeCounts = dueChallengeCounts; 44 | notifyDataSetChanged(); 45 | } 46 | 47 | /** 48 | * Called to create the ViewHolder at the given position. 49 | * 50 | * @param parent parent to assign the newly created view to 51 | * @param viewType ignored 52 | */ 53 | @Override 54 | public CategoryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 55 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_category, parent, false); 56 | v.setLayoutParams(new LinearLayoutCompat.LayoutParams(LinearLayoutCompat.LayoutParams.MATCH_PARENT, LinearLayoutCompat.LayoutParams.WRAP_CONTENT)); 57 | 58 | return new CategoryViewHolder(v, mListener); 59 | } 60 | 61 | /** 62 | * Called to bind the ViewHolder at the given position. 63 | * 64 | * @param holder the ViewHolder object to be bound 65 | * @param position the position of the ViewHolder 66 | */ 67 | @Override 68 | public void onBindViewHolder(CategoryViewHolder holder, int position) { 69 | // Categories 70 | int amountDue = 0; 71 | if (position == 0) { 72 | for (Category category : mCategories) { 73 | amountDue += mDueChallengeCounts.get(category.getId()); 74 | } 75 | holder.bindAllCategoriesCard(amountDue); 76 | } else { 77 | final Category category = mCategories.get(position - 1); 78 | holder.bindCard(category, mDueChallengeCounts.get(category.getId())); 79 | } 80 | } 81 | 82 | /** 83 | * Returns the count of ViewHolders in the adapter 84 | * 85 | * @return the count of ViewHolders 86 | */ 87 | @Override 88 | public int getItemCount() { 89 | return mCategories.size() + 1; 90 | } 91 | 92 | /** 93 | * Returns the stable ID for the item at position. 94 | * 95 | * @param position Adapter position to query 96 | * @return the stable ID of the item at position 97 | */ 98 | @Override 99 | public long getItemId(int position) { 100 | if (position == 0) { 101 | return CategoryDataSource.CATEGORY_ID_ALL; 102 | } 103 | 104 | Category category = mCategories.get(position - 1); 105 | return category.getId(); 106 | } 107 | 108 | /** 109 | * Interface to pass selection events. 110 | */ 111 | public interface SelectionListener { 112 | void onCategorySelected(Category category); 113 | void onAllCategoriesSelected(); 114 | 115 | void onCategoryStatisticsSelected(Category category); 116 | 117 | void onAllCategoriesStatisticsSelected(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/statistics/ChartValueSelectedListener.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.statistics; 2 | 3 | import com.github.mikephil.charting.data.Entry; 4 | import com.github.mikephil.charting.highlight.Highlight; 5 | import com.github.mikephil.charting.listener.OnChartValueSelectedListener; 6 | 7 | /** 8 | * Created by Daniel Hoogen on 13/03/2016. 9 | *

10 | * This class implements a listener for selecting and deselecting values in a chart 11 | */ 12 | public class ChartValueSelectedListener implements OnChartValueSelectedListener { 13 | //Attributes 14 | private StatisticViewHolder mHolder; 15 | 16 | /** 17 | * This constructor saves the given parameters as member attributes 18 | * 19 | * @param holder the view holder to be saved as a member attribute 20 | */ 21 | public ChartValueSelectedListener(StatisticViewHolder holder) { 22 | mHolder = holder; 23 | } 24 | 25 | /** 26 | * This method is called when a value in the chart, this listener is assigned to, is selected. 27 | * It runs the corresponding method with the ViewHolder object containing the chart. 28 | * 29 | * @param e the selected entry 30 | * @param dataSetIndex ignored 31 | * @param h ignored 32 | */ 33 | @Override 34 | public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { 35 | mHolder.onValueSelected(e); 36 | } 37 | 38 | /** 39 | * This method is called when a value in the chart is unselected. It runs the corresponding 40 | * method with the ViewHolder object containing the chart. 41 | */ 42 | @Override 43 | public void onNothingSelected() { 44 | mHolder.onNothingSelected(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/statistics/StatisticsSpanSizeLookup.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.statistics; 2 | 3 | import android.support.v7.widget.GridLayoutManager; 4 | 5 | import java.util.List; 6 | 7 | import de.fhdw.ergoholics.brainphaser.logic.statistics.StatisticType; 8 | 9 | /** 10 | * Created by Daniel Hoogen on 17/03/2016. 11 | *

12 | * This class calculates the span sizes for the ViewHolders in the recycler view used in the 13 | * statistics activity 14 | *

15 | */ 16 | public class StatisticsSpanSizeLookup extends GridLayoutManager.SpanSizeLookup { 17 | //Attributes 18 | private final List mTypes; 19 | 20 | /** 21 | * This constructor saves the given parameters as member attributes. 22 | * 23 | * @param types the types to be saved as a member attribute 24 | */ 25 | public StatisticsSpanSizeLookup(List types) { 26 | mTypes = types; 27 | } 28 | 29 | /** 30 | * Returns the span size of a ViewHolder depending on the device orientation and the ViewHolder 31 | * position 32 | * 33 | * @param position the position of the ViewHolder 34 | */ 35 | @Override 36 | public int getSpanSize(int position) { 37 | switch (StatisticsAdapter.VIEW_TYPE_MAP.get(mTypes.get(position))) { 38 | case StatisticViewHolder.TYPE_LARGE: 39 | return 2; 40 | case StatisticViewHolder.TYPE_SMALL: 41 | return 1; 42 | } 43 | return 0; 44 | } 45 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/activities/usersettings/slidertimeperiod/DateComponent.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.activities.usersettings.slidertimeperiod; 2 | 3 | import de.fhdw.ergoholics.brainphaser.R; 4 | 5 | /** 6 | * Created by funkv on 15.03.2016. 7 | * 8 | * Exposes information about the time units(components) for the TimePeriodSlider, such as name and valid ranges. 9 | */ 10 | public class DateComponent { 11 | public static int WEEKS = 1; 12 | public static int DAYS = 2; 13 | public static int HOURS = 3; 14 | public static int MINUTES = 4; 15 | 16 | private static ComponentInfo[] info = new ComponentInfo[]{ 17 | null, // Skip, WEEKS is index 1 18 | new ComponentInfo(R.string.weeks, 51), 19 | new ComponentInfo(R.string.days, 6), 20 | new ComponentInfo(R.string.hours, 23), 21 | new ComponentInfo(R.string.minutes, 59) 22 | }; 23 | 24 | public static ComponentInfo getInfo(int component) { 25 | return info[component]; 26 | } 27 | 28 | /** 29 | * Container class wrapping the values for easy access. 30 | * Bundles information about a single unit picker (e.g. Hours, Minutes, Days). 31 | */ 32 | static class ComponentInfo { 33 | private int mResourceId; 34 | private int mRangeMax; 35 | 36 | /** 37 | * Create a new instance 38 | * @param resourceId resource id of the string that represents this time component (i.e. Months, Days, Hours) 39 | * @param rangeMax maximum valid amount until the next unit would be reached (e.g. 12 for hours, day would be the next unit) 40 | */ 41 | public ComponentInfo(int resourceId, int rangeMax) { 42 | this.mResourceId = resourceId; 43 | this.mRangeMax = rangeMax; 44 | } 45 | 46 | /** 47 | * Returns the max range of the component info 48 | * 49 | * @return the max range attribute 50 | */ 51 | public int getRangeMax() { 52 | return mRangeMax; 53 | } 54 | 55 | /** 56 | * Returns the ressource id of the component info 57 | * 58 | * @return the ressource id attribute 59 | */ 60 | public int getResourceId() { 61 | return mResourceId; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/AnswerDataSource.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import java.util.List; 4 | 5 | import javax.inject.Inject; 6 | 7 | import de.fhdw.ergoholics.brainphaser.model.Answer; 8 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 9 | 10 | /** 11 | * Created by Daniel Hoogen on 25/02/2016. 12 | *

13 | * Data Source class for custom access to answer table entries in the database 14 | */ 15 | public class AnswerDataSource { 16 | //Attributes 17 | private DaoSession mDaoSession; 18 | 19 | /** 20 | * Constructor which saves all given parameters to local member attributes. 21 | * 22 | * @param session the session to be saved as a member attribute 23 | */ 24 | @Inject 25 | AnswerDataSource(DaoSession session) { 26 | mDaoSession = session; 27 | } 28 | 29 | /** 30 | * Return all Answer objects in the answer table 31 | * 32 | * @return List object containing all Answer objects 33 | */ 34 | public List getAll() { 35 | return mDaoSession.getAnswerDao().loadAll(); 36 | } 37 | 38 | /** 39 | * Returns the Answer object with the given id 40 | * 41 | * @param id answer id in the database 42 | * @return Answer object with the given id 43 | */ 44 | public Answer getById(long id) { 45 | return mDaoSession.getAnswerDao().load(id); 46 | } 47 | 48 | /** 49 | * Adds an Answer object to the database 50 | * 51 | * @param answer answer to be created in the answer table 52 | * @return id of the created object 53 | */ 54 | public long create(Answer answer) { 55 | return mDaoSession.getAnswerDao().insert(answer); 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/CategoryDataSource.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import java.util.List; 4 | 5 | import javax.inject.Inject; 6 | import javax.inject.Singleton; 7 | 8 | import de.fhdw.ergoholics.brainphaser.model.Category; 9 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 10 | 11 | /** 12 | * Created by funkv on 20.02.2016. 13 | */ 14 | @Singleton 15 | public class CategoryDataSource { 16 | //Constants 17 | public static final long CATEGORY_ID_ALL = -1L; 18 | 19 | //Attributes 20 | private DaoSession mDaoSession; 21 | 22 | 23 | /** 24 | * Constructor defines the daosession 25 | * 26 | * @param session the DaoSession 27 | */ 28 | @Inject 29 | public CategoryDataSource(DaoSession session) { 30 | mDaoSession = session; 31 | } 32 | 33 | /** 34 | * Gets all categories from the database 35 | * 36 | * @return List of all categories 37 | */ 38 | public List getAll() { 39 | return mDaoSession.getCategoryDao().loadAll(); 40 | } 41 | 42 | /** 43 | * Creates a new category 44 | * 45 | * @param category category to create 46 | * @return id of the created category 47 | */ 48 | public long create(Category category) { 49 | return mDaoSession.getCategoryDao().insert(category); 50 | } 51 | 52 | /** 53 | * Gets a category by its id 54 | * 55 | * @param id Id of the category 56 | * @return Category 57 | */ 58 | public Category getById(long id) { 59 | return mDaoSession.getCategoryDao().load(id); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/ChallengeDataSource.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import java.util.List; 4 | 5 | import javax.inject.Inject; 6 | 7 | import de.fhdw.ergoholics.brainphaser.model.Challenge; 8 | import de.fhdw.ergoholics.brainphaser.model.ChallengeDao; 9 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 10 | 11 | /** 12 | * Created by Daniel Hoogen on 25/02/2016. 13 | *

14 | * Data Source class for custom access to challenge table entries in the database 15 | */ 16 | public class ChallengeDataSource { 17 | //Attributes 18 | private DaoSession mDaoSession; 19 | 20 | /** 21 | * Constructor which saves all given parameters to local member attributes. 22 | * 23 | * @param session the session to be saved as a member attribute 24 | */ 25 | @Inject 26 | ChallengeDataSource(DaoSession session) { 27 | mDaoSession = session; 28 | } 29 | 30 | /** 31 | * Returns a list with all challenges 32 | * 33 | * @return list with all challenges 34 | */ 35 | public List getAll() { 36 | return mDaoSession.getChallengeDao().loadAll(); 37 | } 38 | 39 | /** 40 | * Returns the Challenge object with the given id 41 | * 42 | * @param id challenge id in the challenge table 43 | * @return Challenge object with the given id 44 | */ 45 | public Challenge getById(long id) { 46 | return mDaoSession.getChallengeDao().load(id); 47 | } 48 | 49 | /** 50 | * Adds a Challenge object to the database 51 | * 52 | * @param challenge challenge to be created in the challenge table 53 | * @return id of the created object 54 | */ 55 | public long create(Challenge challenge) { 56 | return mDaoSession.getChallengeDao().insert(challenge); 57 | } 58 | 59 | /** 60 | * Returns all challenges with the given category id 61 | * 62 | * @param categoryId the category id of the category whose challenges are returned 63 | * @return list of challenges with the given category id 64 | */ 65 | public List getByCategoryId(long categoryId) { 66 | if (categoryId == CategoryDataSource.CATEGORY_ID_ALL) { 67 | return getAll(); 68 | } else { 69 | return mDaoSession.getChallengeDao().queryBuilder() 70 | .where(ChallengeDao.Properties.CategoryId.eq(categoryId)).list(); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/ChallengeStage.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import de.fhdw.ergoholics.brainphaser.R; 4 | 5 | /** 6 | * Created by Christian Kost 7 | * 8 | * Defines common functions for stages 9 | */ 10 | public class ChallengeStage { 11 | private static int[] stageColorResources = new int[] { 12 | -1, 13 | R.color.colorStage1, 14 | R.color.colorStage2, 15 | R.color.colorStage3, 16 | R.color.colorStage4, 17 | R.color.colorStage5, 18 | R.color.colorStage6 19 | }; 20 | 21 | /** 22 | * Returns the resource id of the color for this stage 23 | * @param stage challenge type to get the color for 24 | * @return resource id corresponding to the stage's associated color 25 | */ 26 | public static int getColorResource(int stage) { 27 | return stageColorResources[stage]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/ChallengeType.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import de.fhdw.ergoholics.brainphaser.R; 4 | 5 | /** 6 | * Created by Christian Kost on 03.03.2016. 7 | *

8 | * Defines valid challenge types. 9 | */ 10 | public class ChallengeType { 11 | public final static int MULTIPLE_CHOICE = 1; 12 | public final static int TEXT = 2; 13 | public final static int SELF_TEST = 3; 14 | 15 | private static int[] challengeNameResources = new int[]{ 16 | -1, 17 | R.string.multiple_choice, 18 | R.string.text, 19 | R.string.self_check 20 | }; 21 | 22 | private static int[] challengeColorResources = new int[]{ 23 | -1, 24 | R.color.colorMultipleChoice, 25 | R.color.colorText, 26 | R.color.colorSelfCheck 27 | }; 28 | 29 | /** 30 | * Returns the resource id of the name string for this challenge type 31 | * @param challengeType challenge type to get the name for 32 | * @return resource id corresponding to the challenge type name 33 | */ 34 | public static int getNameResource(int challengeType) { 35 | return challengeNameResources[challengeType]; 36 | } 37 | 38 | /** 39 | * Returns the resource id of the color for this challenge type 40 | * @param challengeType challenge type to get the color for 41 | * @return resource id corresponding to the challenge type's associated color 42 | */ 43 | public static int getColorResource(int challengeType) { 44 | return challengeColorResources[challengeType]; 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/CompletionDataSource.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.inject.Inject; 7 | 8 | import de.fhdw.ergoholics.brainphaser.model.Completion; 9 | import de.fhdw.ergoholics.brainphaser.model.CompletionDao; 10 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 11 | import de.fhdw.ergoholics.brainphaser.model.User; 12 | import de.greenrobot.dao.query.QueryBuilder; 13 | 14 | /** 15 | * Created by Christian Kost 16 | *

17 | * Data Source class for custom access to completion table entries in the database 18 | */ 19 | public class CompletionDataSource { 20 | private DaoSession mDaoSession; 21 | 22 | /** 23 | * Constructor defines the daosession 24 | * @param session the DaoSession 25 | */ 26 | @Inject 27 | CompletionDataSource(DaoSession session) { 28 | mDaoSession = session; 29 | } 30 | 31 | /** 32 | * Find a completion object of a challenge and a user (combined "primary" key) 33 | * @param challengeId the challenge 34 | * @param userId the user 35 | * @return The completion object 36 | */ 37 | public Completion findByChallengeAndUser(long challengeId, long userId) { 38 | return mDaoSession.getCompletionDao().queryBuilder().where(CompletionDao.Properties.ChallengeId.eq(challengeId), CompletionDao.Properties.UserId.eq(userId)).unique(); 39 | } 40 | 41 | /** 42 | * Updates a completion object in the database 43 | * @param completed Completion 44 | */ 45 | public void update(Completion completed) { 46 | mDaoSession.update(completed); 47 | } 48 | 49 | /** 50 | * Inserts a completion object in the database 51 | * @param completed Completion object 52 | * @return row number 53 | */ 54 | public long create(Completion completed) { 55 | return mDaoSession.getCompletionDao().insert(completed); 56 | } 57 | 58 | /** 59 | * Get all completion objects depending on the user and the stage 60 | * @param user the user 61 | * @param stage the stage 62 | * @return List of completion objects 63 | */ 64 | public List findByUserAndStage(User user, int stage) { 65 | QueryBuilder completed = mDaoSession.getCompletionDao().queryBuilder() 66 | .where(CompletionDao.Properties.UserId.eq(user.getId()), 67 | CompletionDao.Properties.Stage.eq(stage)); 68 | return completed.list(); 69 | } 70 | 71 | /** 72 | * Get all completion objects depending on the user, the stage and the category 73 | * @param user the user 74 | * @param stage the stage 75 | * @param categoryId the category 76 | * @return List of completion objects 77 | */ 78 | public List findByUserAndStageAndCategory(User user, int stage, long categoryId) { 79 | List userStageCompletions = findByUserAndStage(user, stage); 80 | if (categoryId == CategoryDataSource.CATEGORY_ID_ALL) 81 | return userStageCompletions; 82 | else { 83 | List completions = new ArrayList<>(); 84 | for (Completion completion : userStageCompletions) { 85 | if (completion.getChallenge().getCategoryId()==categoryId) { 86 | completions.add(completion); 87 | } 88 | } 89 | return completions; 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/DatabaseModule.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | 6 | import javax.inject.Singleton; 7 | 8 | import dagger.Module; 9 | import dagger.Provides; 10 | import de.fhdw.ergoholics.brainphaser.model.DaoMaster; 11 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 12 | 13 | /** 14 | * Created by funkv on 06.03.2016. 15 | *

16 | * Modules that provides DataSource objects 17 | */ 18 | @Module 19 | public class DatabaseModule { 20 | DaoMaster.DevOpenHelper mDevOpenHelper; 21 | SQLiteDatabase mDatabase; 22 | 23 | /** 24 | * Constructs a DatabaseModule and instantiates its context and database name 25 | * 26 | * @param context Context 27 | * @param databaseName Database name 28 | */ 29 | public DatabaseModule(Context context, String databaseName) { 30 | mDevOpenHelper = new DaoMaster.DevOpenHelper(context, databaseName, null); 31 | mDatabase = mDevOpenHelper.getWritableDatabase(); 32 | } 33 | 34 | /** 35 | * Provides the DaoSession 36 | * 37 | * @return DaoSession 38 | */ 39 | @Provides 40 | @Singleton 41 | DaoSession provideSession() { 42 | DaoMaster daoMaster = new DaoMaster(mDatabase); 43 | return daoMaster.newSession(); 44 | } 45 | 46 | /** 47 | * Provides the writeable database 48 | * 49 | * @return SQLiteDatabase 50 | */ 51 | @Provides 52 | @Singleton 53 | SQLiteDatabase provideDatabase() { 54 | return mDevOpenHelper.getWritableDatabase(); 55 | } 56 | 57 | /** 58 | * Provides the AnswerDataSource 59 | * 60 | * @param session Current DaoSession 61 | * @return AnswerDataSource 62 | */ 63 | @Provides 64 | @Singleton 65 | AnswerDataSource provideAnswerDataSource(DaoSession session) { 66 | return new AnswerDataSource(session); 67 | } 68 | 69 | /** 70 | * Provides the CategoryDataSource 71 | * 72 | * @param session Current DaoSession 73 | * @return CategoryDataSource 74 | */ 75 | @Provides 76 | @Singleton 77 | CategoryDataSource provideCategoryDataSource(DaoSession session) { 78 | return new CategoryDataSource(session); 79 | } 80 | 81 | /** 82 | * Provides the ChallengeDataSource 83 | * 84 | * @param session Current DaoSession 85 | * @return ChallengeDataSource 86 | */ 87 | @Provides 88 | @Singleton 89 | ChallengeDataSource provideChallengeDataSource(DaoSession session) { 90 | return new ChallengeDataSource(session); 91 | } 92 | 93 | /** 94 | * Provides the CompletionDataSource 95 | * 96 | * @param session Current DaoSession 97 | * @return CompletionDataSource 98 | */ 99 | @Provides 100 | @Singleton 101 | CompletionDataSource provideCompletionDataSource(DaoSession session) { 102 | return new CompletionDataSource(session); 103 | } 104 | 105 | /** 106 | * Provides the SettingsDataSource 107 | * 108 | * @param session Current DaoSession 109 | * @return SettingsDataSource 110 | */ 111 | @Provides 112 | @Singleton 113 | SettingsDataSource provideSettingsDataSource(DaoSession session) { 114 | return new SettingsDataSource(session); 115 | } 116 | 117 | /** 118 | * Provides the StatisticsDataSource 119 | * 120 | * @param session Current DaoSession 121 | * @return StatisticsDataSource 122 | */ 123 | @Provides 124 | @Singleton 125 | StatisticsDataSource provideStatisticsDataSource(DaoSession session) { 126 | return new StatisticsDataSource(session); 127 | } 128 | 129 | /** 130 | * Provides the UserDataSource 131 | * 132 | * @param session Current DaoSession 133 | * @return UserDataSource 134 | */ 135 | @Provides 136 | @Singleton 137 | UserDataSource provideUserDataSource(DaoSession session, SettingsDataSource settingsDataSource) { 138 | return new UserDataSource(session, settingsDataSource); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/StatisticsDataSource.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.inject.Inject; 7 | 8 | import de.fhdw.ergoholics.brainphaser.model.Challenge; 9 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 10 | import de.fhdw.ergoholics.brainphaser.model.Statistics; 11 | import de.fhdw.ergoholics.brainphaser.model.StatisticsDao; 12 | import de.fhdw.ergoholics.brainphaser.model.User; 13 | 14 | /** 15 | * Created by Daniel Hoogen on 11/03/2016. 16 | *

17 | * Data Source class for custom access to statistics table entries in the database 18 | */ 19 | public class StatisticsDataSource { 20 | //Attributes 21 | private DaoSession mDaoSession; 22 | 23 | /** 24 | * Constructor which saves all given parameters to local member attributes. 25 | * 26 | * @param session the session to be saved as a member attribute 27 | */ 28 | @Inject 29 | StatisticsDataSource(DaoSession session) { 30 | mDaoSession = session; 31 | } 32 | 33 | /** 34 | * Updates a Statistics object in the database 35 | * 36 | * @param statistics representation of the object to be updated 37 | */ 38 | public void update(Statistics statistics) { 39 | mDaoSession.update(statistics); 40 | } 41 | 42 | /** 43 | * Adds a Statistics object to the database 44 | * 45 | * @param statistics statistics entry to be created in the statistics table 46 | * @return id of the created object 47 | */ 48 | public long create(Statistics statistics) { 49 | return mDaoSession.getStatisticsDao().insert(statistics); 50 | } 51 | 52 | /** 53 | * Returns all Statistics objects of the given user 54 | * 55 | * @param userId the user whose statistics entries will be returned 56 | * @return list of Statistics objects of the given user 57 | */ 58 | public List findByUser(long userId) { 59 | return mDaoSession.getStatisticsDao().queryBuilder() 60 | .where(StatisticsDao.Properties.UserId.eq(userId)).list(); 61 | } 62 | 63 | /** 64 | * Returns all Statistics objects of the given user and category 65 | * 66 | * @param categoryId the id of the category whose statistics entries will be returned 67 | * @param user the user whose statistics entries will be returned 68 | * @return list of Statistics objects with the given category id and user 69 | */ 70 | public List findByCategoryAndUser(long categoryId, User user) { 71 | List userStatistics = findByUser(user.getId()); 72 | 73 | if (categoryId == CategoryDataSource.CATEGORY_ID_ALL) 74 | return userStatistics; 75 | else { 76 | List statistics = new ArrayList<>(); 77 | for (Statistics statistic : userStatistics) { 78 | Challenge challenge; 79 | challenge = mDaoSession.getChallengeDao().load(statistic.getChallengeId()); 80 | 81 | if (challenge.getCategoryId() == categoryId) { 82 | statistics.add(statistic); 83 | } 84 | } 85 | return statistics; 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/database/UserDataSource.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.database; 2 | 3 | import java.util.List; 4 | 5 | import javax.inject.Inject; 6 | 7 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 8 | import de.fhdw.ergoholics.brainphaser.model.User; 9 | import de.fhdw.ergoholics.brainphaser.model.UserDao; 10 | 11 | /** 12 | * Created by funkv on 20.02.2016.

13 | * Data Source class for custom access to user table entries in the database 14 | */ 15 | public class UserDataSource { 16 | public final static int MAX_USERNAME_LENGTH = 30; 17 | 18 | private SettingsDataSource mSettingsDataSource; 19 | private DaoSession mDaoSession; 20 | 21 | /** 22 | * Constructor defines the daosession 23 | * 24 | * @param session the DaoSession 25 | * @param settingsDataSource the SettingsDataSource 26 | */ 27 | @Inject 28 | UserDataSource(DaoSession session, SettingsDataSource settingsDataSource) { 29 | mDaoSession = session; 30 | mSettingsDataSource = settingsDataSource; 31 | } 32 | 33 | /** 34 | * Gets all users from the database 35 | * 36 | * @return List of all users 37 | */ 38 | public List getAll() { 39 | return mDaoSession.getUserDao().loadAll(); 40 | } 41 | 42 | /** 43 | * Creates a new user and assigns default settings 44 | * 45 | * @param user user to create 46 | * @return id of the created user 47 | */ 48 | public long create(User user) { 49 | if (user.getSettingsId() == 0) { 50 | user.setSettings(mSettingsDataSource.createNewDefaultSettings()); 51 | } 52 | 53 | return mDaoSession.getUserDao().insert(user); 54 | } 55 | 56 | /** 57 | * Gets a user by its name 58 | * 59 | * @param name Name of the user 60 | * @return User 61 | */ 62 | public User findOneByName(String name) { 63 | return mDaoSession.getUserDao().queryBuilder().where(UserDao.Properties.Name.eq(name)).unique(); 64 | } 65 | 66 | /** 67 | * Gets a user by its id 68 | * 69 | * @param id Id of the user 70 | * @return User 71 | */ 72 | public User getById(long id) { 73 | return mDaoSession.getUserDao().load(id); 74 | } 75 | 76 | /** 77 | * Updates a user in the database 78 | * 79 | * @param user To updated user 80 | */ 81 | public void update(User user) { 82 | mDaoSession.update(user); 83 | } 84 | 85 | /** 86 | * Deletes a user from the database 87 | * 88 | * @param user To deleted user 89 | */ 90 | public void delete(User user) { 91 | mDaoSession.delete(user); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/CompletionLogic.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic; 2 | 3 | import java.util.Date; 4 | 5 | import de.fhdw.ergoholics.brainphaser.database.CompletionDataSource; 6 | import de.fhdw.ergoholics.brainphaser.model.Completion; 7 | 8 | /** 9 | * Created by Christian Kost 10 | *

11 | * Provides functions for completion logic checking 12 | */ 13 | public class CompletionLogic { 14 | 15 | public static int ANSWER_RIGHT = 1; 16 | public static int ANSWER_WRONG = -1; 17 | 18 | private CompletionDataSource mCompletionDataSource; 19 | 20 | /** 21 | * Constructor which saves the given parameters as member attributes. 22 | * 23 | * @param completionDataSource the completion data source to be saved as a member attribute 24 | */ 25 | public CompletionLogic(CompletionDataSource completionDataSource) { 26 | mCompletionDataSource = completionDataSource; 27 | } 28 | 29 | /** 30 | * Updates or inserts a completion object depending on the answer 31 | * @param challengeId The Challenge ID 32 | * @param userId The currently loggen in user 33 | * @param stageUp 1 for StageUp -1 for StageDown (answer right, answer wrong) 34 | */ 35 | public void updateAfterAnswer(long challengeId, long userId, int stageUp) { 36 | if (stageUp != ANSWER_WRONG && stageUp != ANSWER_RIGHT) { 37 | return; 38 | } 39 | Completion completed = mCompletionDataSource.findByChallengeAndUser(challengeId, userId); 40 | if (completed == null) { 41 | completed = new Completion(null, 2, new Date(), userId, challengeId); 42 | if (stageUp == ANSWER_WRONG) { 43 | completed.setStage(1); 44 | } 45 | mCompletionDataSource.create(completed); 46 | } else { 47 | completed.setStage(completed.getStage() + stageUp); 48 | if (completed.getStage() < 1) { 49 | completed.setStage(1); 50 | } else if (completed.getStage() > 6) { 51 | completed.setStage(6); 52 | } 53 | completed.setLastCompleted(new Date()); 54 | mCompletionDataSource.update(completed); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/SettingsLogic.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic; 2 | 3 | import java.util.Date; 4 | 5 | import de.fhdw.ergoholics.brainphaser.BuildConfig; 6 | import de.fhdw.ergoholics.brainphaser.R; 7 | import de.fhdw.ergoholics.brainphaser.database.SettingsDataSource; 8 | import de.fhdw.ergoholics.brainphaser.model.Settings; 9 | 10 | /** 11 | * Created by Lars Kahra on 16.03.2016. 12 | *

13 | * Provides functions for Settings logic checking 14 | */ 15 | public class SettingsLogic { 16 | /** 17 | * Check whether the given duration is valid for a given stage 18 | * 19 | * @param stage stage to check 20 | * @param durationMsec duration for this stage 21 | * @return null if this is a valid value, error string id if it is invalid 22 | */ 23 | public Integer isTimeValidForStage(Settings settings, int stage, long durationMsec) { 24 | // Assertion 25 | if (BuildConfig.DEBUG && (stage < 1 || stage > SettingsDataSource.STAGE_COUNT)) { 26 | throw new RuntimeException("Invalid stage " + stage); 27 | } 28 | 29 | int prevStage = stage - 1; 30 | int nextStage = stage + 1; 31 | 32 | // Cannot be smaller than previous 33 | if (prevStage >= 1) { 34 | Date time = SettingsDataSource.getTimeboxByStage(settings, prevStage); 35 | if (durationMsec <= time.getTime()) { 36 | return R.string.error_less_than_previous; 37 | } 38 | } 39 | 40 | // Or bigger than next 41 | if (nextStage <= SettingsDataSource.STAGE_COUNT) { 42 | Date time = SettingsDataSource.getTimeboxByStage(settings, nextStage); 43 | if (durationMsec >= time.getTime()) { 44 | return R.string.error_more_than_next; 45 | } 46 | } 47 | 48 | // Or 0 49 | if (durationMsec == 0) { 50 | return R.string.error_zero_value; 51 | } 52 | 53 | return null; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/UserLogicFactory.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic; 2 | 3 | import javax.inject.Inject; 4 | 5 | import de.fhdw.ergoholics.brainphaser.BrainPhaserApplication; 6 | import de.fhdw.ergoholics.brainphaser.database.ChallengeDataSource; 7 | import de.fhdw.ergoholics.brainphaser.database.CompletionDataSource; 8 | import de.fhdw.ergoholics.brainphaser.database.StatisticsDataSource; 9 | import de.fhdw.ergoholics.brainphaser.logic.statistics.ChartDataLogic; 10 | import de.fhdw.ergoholics.brainphaser.logic.statistics.ChartSettings; 11 | import de.fhdw.ergoholics.brainphaser.logic.statistics.StatisticsLogic; 12 | import de.fhdw.ergoholics.brainphaser.model.User; 13 | 14 | /** 15 | * Created by funkv on 06.03.2016. 16 | *

17 | * Factory that is used to create logic objects which require a user. 18 | * Dependencies are injected automatically. 19 | */ 20 | public class UserLogicFactory { 21 | @Inject 22 | BrainPhaserApplication mApplication; 23 | @Inject 24 | CompletionDataSource mCompletionDataSource; 25 | @Inject 26 | ChallengeDataSource mChallengeDataSource; 27 | @Inject 28 | StatisticsDataSource mStatisticsDataSource; 29 | @Inject 30 | ChartSettings mSettings; 31 | 32 | /** 33 | * Create a DueChallengeLogic for the specified user. 34 | * 35 | * @param user user whose challenges are inspected 36 | * @return the DueChallengeLogic object 37 | */ 38 | public DueChallengeLogic createDueChallengeLogic(User user) { 39 | return new DueChallengeLogic(user, mCompletionDataSource, mChallengeDataSource); 40 | } 41 | 42 | /** 43 | * Creates ChartDataLogic 44 | * 45 | * @param user 46 | * @param categoryId category to inspect 47 | * @return ChartDataLogic 48 | */ 49 | public ChartDataLogic createChartDataLogic(User user, long categoryId) { 50 | return new ChartDataLogic(user, 51 | categoryId, 52 | mApplication, 53 | mChallengeDataSource, 54 | mCompletionDataSource, 55 | mStatisticsDataSource, 56 | this); 57 | } 58 | 59 | /** 60 | * Create a DueChallengeLogic for the specified user. 61 | * 62 | * @param user user whose challenges are inspected 63 | * @param categoryId category to inspect 64 | * @return the DueChallengeLogic object 65 | */ 66 | public StatisticsLogic createStatisticsLogic(User user, long categoryId) { 67 | return new StatisticsLogic(mApplication, mSettings, createChartDataLogic(user, categoryId)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/UserManager.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic; 2 | 3 | import android.app.Application; 4 | import android.content.SharedPreferences; 5 | 6 | import javax.inject.Inject; 7 | import javax.inject.Singleton; 8 | 9 | import de.fhdw.ergoholics.brainphaser.database.UserDataSource; 10 | import de.fhdw.ergoholics.brainphaser.model.User; 11 | 12 | @Singleton 13 | /** 14 | * Created by funkv on 06.03.2016. 15 | * 16 | * Controls the saving of the last logged in user and provides functions 17 | * for switching and persisting the current user. 18 | */ 19 | public class UserManager { 20 | private static final String PREFS_NAME = "BrainPhaserPrefsFile"; 21 | private static final String KEY_PERSISTENT_USER_ID = "loggedInUser"; 22 | private User mCurrentUser; 23 | 24 | private Application mApplication; 25 | private UserDataSource mUserDataSource; 26 | 27 | /** 28 | * Constructor of the user manager requires the application and a user data source 29 | * 30 | * @param application Apllication 31 | * @param userDataSource UserDataSource 32 | */ 33 | @Inject 34 | public UserManager(Application application, UserDataSource userDataSource) { 35 | mApplication = application; 36 | mUserDataSource = userDataSource; 37 | } 38 | 39 | /** 40 | * Logs in the last logged in user. 41 | * 42 | * @return true, if user was logged in, false if no user has been persisted 43 | */ 44 | public boolean logInLastUser() { 45 | SharedPreferences settings = mApplication.getSharedPreferences(PREFS_NAME, 0); 46 | long lastLoggedInUserId = settings.getLong(KEY_PERSISTENT_USER_ID, -1); 47 | if (lastLoggedInUserId != -1) { 48 | User user = mUserDataSource.getById(lastLoggedInUserId); 49 | if (user == null) { 50 | return false; 51 | } 52 | 53 | mCurrentUser = user; 54 | return true; 55 | } 56 | 57 | return false; 58 | } 59 | 60 | /** 61 | * Get the currently logged in user 62 | * 63 | * @return Currently logged in user 64 | */ 65 | public User getCurrentUser() { 66 | return mCurrentUser; 67 | } 68 | 69 | /** 70 | * Switches the current user. 71 | * 72 | * @param user the user to log in 73 | */ 74 | public void switchUser(User user) { 75 | mCurrentUser = user; 76 | persistCurrentUser(); 77 | } 78 | 79 | /** 80 | * Save the selected user to persistent storage 81 | */ 82 | public void persistCurrentUser() { 83 | SharedPreferences settings = mApplication.getSharedPreferences(PREFS_NAME, 0); 84 | SharedPreferences.Editor editor = settings.edit(); 85 | editor.putLong(KEY_PERSISTENT_USER_ID, mCurrentUser.getId()); 86 | editor.apply(); 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/fileimport/FileImport.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.fileimport; 2 | 3 | import org.w3c.dom.Node; 4 | 5 | import java.io.InputStream; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import de.fhdw.ergoholics.brainphaser.BrainPhaserApplication; 10 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.bpc.BPCObjects; 11 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.bpc.BPCRead; 12 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.bpc.BPCWrite; 13 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions.ElementAmountException; 14 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions.FileFormatException; 15 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions.InvalidAttributeException; 16 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions.UnexpectedElementException; 17 | import de.fhdw.ergoholics.brainphaser.model.Answer; 18 | import de.fhdw.ergoholics.brainphaser.model.Category; 19 | import de.fhdw.ergoholics.brainphaser.model.Challenge; 20 | 21 | /** 22 | * Created by Daniel Hoogen on 19/02/2016. 23 | *

24 | * Contains the logic for importing files 25 | */ 26 | public class FileImport { 27 | /** 28 | * Imports a .bpc file containing categories with challenges and their answers into the database 29 | * 30 | * @param is the input stream of the file to be imported 31 | * @param application the BrainPhaserApplication instance 32 | * @throws FileFormatException if file is no xml file 33 | * @throws UnexpectedElementException if an unexpected element was fond in the file 34 | * @throws ElementAmountException if an element occurs more or less often than expected 35 | * @throws InvalidAttributeException if an attribute has an invalid value 36 | */ 37 | public static void importBPC(InputStream is, BrainPhaserApplication application) 38 | throws FileFormatException, UnexpectedElementException, ElementAmountException, 39 | InvalidAttributeException { 40 | 41 | //Get root element 42 | Node categoriesNode = BPCRead.getCategoriesNode(is); 43 | 44 | //Get the root's child nodes 45 | Node childCategories = categoriesNode.getFirstChild(); 46 | 47 | //Create lists for saving the categories, challenges and answers 48 | List categoryList = new ArrayList<>(); 49 | List challengeList = new ArrayList<>(); 50 | List answerList = new ArrayList<>(); 51 | 52 | //All categories, challenges and answers are read first 53 | //So if there is any syntax error in the file, nothing will be imported 54 | long i = 0; 55 | long nextChallengeId = 0; 56 | while (childCategories != null) { 57 | if (childCategories.getNodeType() == Node.ELEMENT_NODE) { 58 | nextChallengeId = BPCObjects.readCategory(childCategories, i, nextChallengeId, 59 | categoryList, challengeList, answerList); 60 | i++; 61 | } 62 | 63 | childCategories = childCategories.getNextSibling(); 64 | } 65 | if (i == 0) throw new ElementAmountException("", ">0", "0"); 66 | 67 | //No syntax errors were found, so the read information is being written 68 | BPCWrite writer = new BPCWrite(application); 69 | writer.writeAll(categoryList, challengeList, answerList); 70 | } 71 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/fileimport/bpc/BPCRead.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.fileimport.bpc; 2 | 3 | import android.util.Log; 4 | 5 | import org.w3c.dom.Document; 6 | import org.w3c.dom.Node; 7 | import org.xml.sax.SAXException; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | 12 | import javax.xml.parsers.DocumentBuilderFactory; 13 | import javax.xml.parsers.ParserConfigurationException; 14 | 15 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions.FileFormatException; 16 | import de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions.UnexpectedElementException; 17 | 18 | /** 19 | * Created by Daniel Hoogen on 25/02/2016. 20 | *

21 | * Contains the logic for reading the root element of an .bpc file 22 | */ 23 | public class BPCRead { 24 | /** 25 | * Reads the categories node from an input stream of a .bpc file and returns it 26 | * 27 | * @param is the input stream of the .bpc file 28 | * @return the categories node of the .bpc file 29 | * @throws FileFormatException if file is no xml file 30 | * @throws UnexpectedElementException if an unexpected element was fond in the file 31 | */ 32 | public static Node getCategoriesNode(InputStream is) 33 | throws FileFormatException, UnexpectedElementException { 34 | //Read document 35 | Document document; 36 | 37 | try { 38 | document = DocumentBuilderFactory.newInstance().newDocumentBuilder() 39 | .parse(is); 40 | } catch (ParserConfigurationException | SAXException | IOException e) { 41 | Log.d("FileImport Exception", e.getMessage()); 42 | throw new FileFormatException("BPC"); 43 | } 44 | 45 | document.getDocumentElement().normalize(); 46 | 47 | //Get Nodes from document 48 | Node childRoot = document.getFirstChild(); 49 | 50 | /** 51 | * By the definition of the file format it is expected that the root element is a 52 | * element. If this requirement is not met, an exception is caused. Otherwise 53 | * the method returns the correct root element. 54 | */ 55 | if (!childRoot.getNodeName().equals("categories")) 56 | throw new UnexpectedElementException("BPC"); 57 | else { 58 | return childRoot; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/fileimport/bpc/BPCWrite.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.fileimport.bpc; 2 | 3 | import java.util.List; 4 | 5 | import javax.inject.Inject; 6 | 7 | import de.fhdw.ergoholics.brainphaser.BrainPhaserApplication; 8 | import de.fhdw.ergoholics.brainphaser.database.AnswerDataSource; 9 | import de.fhdw.ergoholics.brainphaser.database.CategoryDataSource; 10 | import de.fhdw.ergoholics.brainphaser.database.ChallengeDataSource; 11 | import de.fhdw.ergoholics.brainphaser.model.Answer; 12 | import de.fhdw.ergoholics.brainphaser.model.Category; 13 | import de.fhdw.ergoholics.brainphaser.model.Challenge; 14 | 15 | /** 16 | * Created by Daniel Hoogen on 25/02/2016. 17 | */ 18 | public class BPCWrite { 19 | //Attributes 20 | @Inject 21 | CategoryDataSource mCategoryDataSource; 22 | @Inject 23 | ChallengeDataSource mChallengeDataSource; 24 | @Inject 25 | AnswerDataSource mAnswerDataSource; 26 | 27 | /** 28 | * Constructor which saves the given parameters as member attributes. 29 | * 30 | * @param application the BrainPhaserApplication to be saved as a member attribute 31 | */ 32 | public BPCWrite(BrainPhaserApplication application) { 33 | application.getComponent().inject(this); 34 | } 35 | 36 | /** 37 | * Writes all categories with their challenges and their answers to the database 38 | * 39 | * @param categoryList the list of categories to be written to the database 40 | * @param challengeList the list of challenges to be written to the database 41 | * @param answerList the list of answers to be written to the database 42 | */ 43 | public void writeAll(List categoryList, List challengeList, List answerList) { 44 | for (Category category : categoryList) { 45 | writeCategory(category, challengeList, answerList); 46 | } 47 | } 48 | 49 | /** 50 | * Writes a category with their challenges and their answers to the database 51 | * 52 | * @param category the category to be written to the database 53 | * @param challengeList the list of challenges to be written to the database 54 | * @param answerList the list of answers to be written to the database 55 | */ 56 | private void writeCategory(Category category, List challengeList, List answerList) { 57 | long oldCategoryId = category.getId(); 58 | category.setId(null); 59 | long categoryId = mCategoryDataSource.create(category); 60 | 61 | for (int i = 0; i < challengeList.size(); i++) { 62 | Challenge challenge = challengeList.get(i); 63 | if (challenge != null && challenge.getCategoryId() == oldCategoryId) { 64 | challenge.setCategoryId(categoryId); 65 | writeChallenge(challenge, answerList); 66 | challengeList.set(i, null); 67 | } 68 | } 69 | } 70 | 71 | /** 72 | * Writes a challenge with their answers to the database 73 | * 74 | * @param challenge the challenge to be written to the database 75 | * @param answerList the list of answers to be written to the database 76 | */ 77 | private void writeChallenge(Challenge challenge, List answerList) { 78 | long oldChallengeId = challenge.getId(); 79 | challenge.setId(null); 80 | long challengeId = mChallengeDataSource.create(challenge); 81 | 82 | for (Answer answer : answerList) { 83 | if (answer.getChallengeId() == oldChallengeId) { 84 | answer.setChallengeId(challengeId); 85 | writeAnswer(answer); 86 | answer.setChallengeId(-1); 87 | } 88 | } 89 | } 90 | 91 | /** 92 | * Writes an answer to the database 93 | * 94 | * @param answer the answer to be written to the database 95 | */ 96 | private void writeAnswer(Answer answer) { 97 | answer.setId(null); 98 | mAnswerDataSource.create(answer); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/fileimport/exceptions/ElementAmountException.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions; 2 | 3 | /** 4 | * Created by Daniel Hoogen on 19/02/2016. 5 | *

6 | * This exception is thrown when an element does not occur as often as it is expected in a given context 7 | */ 8 | public class ElementAmountException extends Exception { 9 | private String mElement; 10 | private String mExpectedAmount; 11 | private String mAmount; 12 | 13 | /** 14 | * Constructor which creates an error string from the given string parameters and saves them as 15 | * member attributes. 16 | * 17 | * @param element the element that did not occur as often as expected 18 | * @param amountExpected the expected amount of occurences of the element 19 | * @param amount the amount of occurences of the element 20 | */ 21 | public ElementAmountException(String element, String amountExpected, String amount) { 22 | super("The element " + element + " is expected " + amountExpected + " times but was found " + amount + " times!"); 23 | 24 | mElement = element; 25 | mExpectedAmount = amountExpected; 26 | mAmount = amount; 27 | } 28 | 29 | /** 30 | * Returns the name of the element that was given when the exception was created 31 | * 32 | * @return the name of the element 33 | */ 34 | public String getElement() { 35 | return mElement; 36 | } 37 | 38 | /** 39 | * Returns the expected amount of the element that was given when the exception was created 40 | * 41 | * @return the expected amount of the alement 42 | */ 43 | public String getExpectedAmount() { 44 | return mExpectedAmount; 45 | } 46 | 47 | /** 48 | * Returns the amount of the element that was given when the exception was created 49 | * 50 | * @return the amount of the alement 51 | */ 52 | public String getAmount() { 53 | return mAmount; 54 | } 55 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/fileimport/exceptions/FileFormatException.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions; 2 | 3 | /** 4 | * Created by Daniel Hoogen on 19/02/2016. 5 | *

6 | * This exception is thrown when a file does not have the expected format 7 | */ 8 | public class FileFormatException extends Exception { 9 | /** 10 | * Constructor which creates an error string from the given string parameters 11 | * 12 | * @param expectedType the expected file type 13 | */ 14 | public FileFormatException(String expectedType) { 15 | super("The given file does not match the expected " + expectedType + " file structure!"); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/fileimport/exceptions/InvalidAttributeException.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions; 2 | 3 | /** 4 | * Created by Daniel Hoogen on 15/03/2016. 5 | *

6 | * This exception is thrown when an invalid attribute value was found in a file 7 | */ 8 | public class InvalidAttributeException extends Exception { 9 | //Attributes 10 | private String mAttribute; 11 | private String mValue; 12 | 13 | /** 14 | * Constructor which creates an error string from the given string parameters and saves them as 15 | * member attributes. 16 | * 17 | * @param attributeName the name of the attribute 18 | * @param attributeValue the value of the attribute 19 | */ 20 | public InvalidAttributeException(String attributeName, String attributeValue) { 21 | super("The attribute " + attributeName + " has an invalid value: " + attributeValue + "!"); 22 | 23 | mAttribute = attributeName; 24 | mValue = attributeValue; 25 | } 26 | 27 | /** 28 | * Returns the name of the attribute that was given when the exception was created 29 | * 30 | * @return the name of the attribute 31 | */ 32 | public String getAttribute() { 33 | return mAttribute; 34 | } 35 | 36 | /** 37 | * Returns the value of the attribute that was given when the exception was created 38 | * 39 | * @return the value of the attribute 40 | */ 41 | public String getValue() { 42 | return mValue; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/fileimport/exceptions/UnexpectedElementException.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.fileimport.exceptions; 2 | 3 | /** 4 | * Created by Daniel Hoogen on 19/02/2016. 5 | *

6 | * This exception is thrown when an unexpected element is found in a xml based file 7 | */ 8 | public class UnexpectedElementException extends Exception { 9 | /** 10 | * Constructor which creates an error string from the given string parameters 11 | * 12 | * @param elementName the name of the unexpected element 13 | */ 14 | public UnexpectedElementException(String elementName) { 15 | super("Unexpected element: " + elementName + "!"); 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/statistics/CustomizedFormatter.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.statistics; 2 | 3 | import com.github.mikephil.charting.data.Entry; 4 | import com.github.mikephil.charting.formatter.ValueFormatter; 5 | import com.github.mikephil.charting.utils.ViewPortHandler; 6 | 7 | import java.text.DecimalFormat; 8 | import java.text.NumberFormat; 9 | import java.util.Locale; 10 | 11 | /** 12 | * Created by Daniel Hoogen on 06/03/2016. 13 | *

14 | * This class implements a ValueFormatter for formatting values for pie charts used in the app 15 | */ 16 | public class CustomizedFormatter implements ValueFormatter { 17 | //Constants 18 | private static final String VALUE_FORMAT = "#,###,##0.######"; 19 | 20 | //Attributes 21 | DecimalFormat mFormat; 22 | 23 | /** 24 | * Standard constructor which created the decimal format 25 | */ 26 | public CustomizedFormatter() { 27 | //Create a decimal format 28 | mFormat = (DecimalFormat) NumberFormat.getNumberInstance(Locale.GERMANY); 29 | mFormat.applyPattern(VALUE_FORMAT); 30 | } 31 | 32 | /** 33 | * Formats a value to be shown in a pie chart. Values with decimal places will be hidden, 34 | * because they are unexpected. This also affects dummy values, which are shown as small slices. 35 | * 36 | * @param value the value to be formatted 37 | * @return String containing the formatted value 38 | */ 39 | @Override 40 | public String getFormattedValue(float value, Entry entry, int dataSetIndex, 41 | ViewPortHandler viewPortHandler) { 42 | String valueText = mFormat.format(value); 43 | String[] valueParts = valueText.split(","); 44 | //If the value is 0 the value will be hidden for avoiding visual bugs 45 | if (valueParts.length != 1) { 46 | return ""; 47 | //Otherwise the result will be returned 48 | } else { 49 | return valueParts[0]; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/statistics/StatisticType.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.statistics; 2 | 3 | /** 4 | * Created by Daniel Hoogen on 12/03/2016. 5 | *

6 | * Enumeration for the different statistic types 7 | */ 8 | public enum StatisticType { 9 | TYPE_DUE, 10 | TYPE_STAGE, 11 | TYPE_MOST_PLAYED, 12 | TYPE_MOST_FAILED, 13 | TYPE_MOST_SUCCEEDED 14 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/logic/statistics/StatisticsLogic.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.logic.statistics; 2 | 3 | import com.github.mikephil.charting.charts.PieChart; 4 | import com.github.mikephil.charting.data.PieData; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import javax.inject.Inject; 10 | 11 | import de.fhdw.ergoholics.brainphaser.BrainPhaserApplication; 12 | import de.fhdw.ergoholics.brainphaser.R; 13 | 14 | /** 15 | * Created by Daniel Hoogen on 05/03/2016. 16 | *

17 | * This class contains the logic for creating statistics about due challenges and challenge stages 18 | */ 19 | public class StatisticsLogic { 20 | //Attributes 21 | private BrainPhaserApplication mApplication; 22 | private ChartSettings mSettings; 23 | private ChartDataLogic mDataLogic; 24 | 25 | /** 26 | * Constructor which saves the given parameters as member attributes. 27 | * 28 | * @param application the BrainPhaserApplication to be saved as a member attribute 29 | * @param chartSettings the chart settings to be saved as a member attribute 30 | * @param chartDataLogic the chart data logic to be saved as a member attribute 31 | */ 32 | @Inject 33 | public StatisticsLogic(BrainPhaserApplication application, ChartSettings chartSettings, ChartDataLogic chartDataLogic) { 34 | mApplication = application; 35 | 36 | mSettings = chartSettings; 37 | mDataLogic = chartDataLogic; 38 | } 39 | 40 | /** 41 | * Creates a PieData object containing entries with the numbers of due and not due challenges. 42 | * 43 | * @param chart the PieChart object the calculated data will be applied to 44 | * @param type the type of the statistic to be created 45 | * @return a list of the ids of the shown challenges, if a most played / failed / succeeded 46 | * challenges chart is created. Otherwise null will be returned. 47 | */ 48 | public List fillChart(PieChart chart, StatisticType type) { 49 | if (chart == null) return null; 50 | 51 | //Clear the chart for reloading 52 | chart.clear(); 53 | 54 | //Create chart data 55 | List shownChallenges = new ArrayList<>(); 56 | PieData data; 57 | 58 | //Find chart data and apply type specific settings 59 | switch (type) { 60 | case TYPE_DUE: 61 | data = mDataLogic.findDueData(); 62 | chart.setCenterText(mApplication.getString(R.string.due_chart_center_text)); 63 | break; 64 | case TYPE_STAGE: 65 | data = mDataLogic.findStageData(); 66 | chart.setCenterText(mApplication.getString(R.string.stage_chart_center_text)); 67 | break; 68 | default: 69 | data = mDataLogic.findMostPlayedData(type, shownChallenges); 70 | chart.setCenterText(""); 71 | chart.getLegend().setEnabled(false); 72 | } 73 | 74 | if (data != null) { 75 | //Add data to chart 76 | chart.setData(data); 77 | 78 | //Apply default chart settings to the chart 79 | mSettings.applyChartSettings(chart); 80 | } else { 81 | //Format the no data text of the chart 82 | mSettings.applyNoDataSettings(chart); 83 | } 84 | 85 | //If there are shown challenges in the List object return the List object, else return null 86 | return (shownChallenges.size() > 0) ? shownChallenges : null; 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/model/Answer.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.model; 2 | 3 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit. 4 | /** 5 | * Entity mapped to table "ANSWER". 6 | */ 7 | public class Answer { 8 | 9 | private Long id; 10 | /** Not-null value. */ 11 | private String text; 12 | private Boolean answerCorrect; 13 | private long challengeId; 14 | 15 | public Answer() { 16 | } 17 | 18 | public Answer(Long id) { 19 | this.id = id; 20 | } 21 | 22 | public Answer(Long id, String text, Boolean answerCorrect, long challengeId) { 23 | this.id = id; 24 | this.text = text; 25 | this.answerCorrect = answerCorrect; 26 | this.challengeId = challengeId; 27 | } 28 | 29 | public Long getId() { 30 | return id; 31 | } 32 | 33 | public void setId(Long id) { 34 | this.id = id; 35 | } 36 | 37 | /** Not-null value. */ 38 | public String getText() { 39 | return text; 40 | } 41 | 42 | /** Not-null value; ensure this value is available before it is saved to the database. */ 43 | public void setText(String text) { 44 | this.text = text; 45 | } 46 | 47 | public Boolean getAnswerCorrect() { 48 | return answerCorrect; 49 | } 50 | 51 | public void setAnswerCorrect(Boolean answerCorrect) { 52 | this.answerCorrect = answerCorrect; 53 | } 54 | 55 | public long getChallengeId() { 56 | return challengeId; 57 | } 58 | 59 | public void setChallengeId(long challengeId) { 60 | this.challengeId = challengeId; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/model/Challenge.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.model; 2 | 3 | import java.util.List; 4 | import de.fhdw.ergoholics.brainphaser.model.DaoSession; 5 | import de.greenrobot.dao.DaoException; 6 | 7 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit. 8 | /** 9 | * Entity mapped to table "CHALLENGE". 10 | */ 11 | public class Challenge { 12 | 13 | private Long id; 14 | private int challengeType; 15 | /** Not-null value. */ 16 | private String question; 17 | private long categoryId; 18 | 19 | /** Used to resolve relations */ 20 | private transient DaoSession daoSession; 21 | 22 | /** Used for active entity operations. */ 23 | private transient ChallengeDao myDao; 24 | 25 | private List answers; 26 | 27 | public Challenge() { 28 | } 29 | 30 | public Challenge(Long id) { 31 | this.id = id; 32 | } 33 | 34 | public Challenge(Long id, int challengeType, String question, long categoryId) { 35 | this.id = id; 36 | this.challengeType = challengeType; 37 | this.question = question; 38 | this.categoryId = categoryId; 39 | } 40 | 41 | /** called by internal mechanisms, do not call yourself. */ 42 | public void __setDaoSession(DaoSession daoSession) { 43 | this.daoSession = daoSession; 44 | myDao = daoSession != null ? daoSession.getChallengeDao() : null; 45 | } 46 | 47 | public Long getId() { 48 | return id; 49 | } 50 | 51 | public void setId(Long id) { 52 | this.id = id; 53 | } 54 | 55 | public int getChallengeType() { 56 | return challengeType; 57 | } 58 | 59 | public void setChallengeType(int challengeType) { 60 | this.challengeType = challengeType; 61 | } 62 | 63 | /** Not-null value. */ 64 | public String getQuestion() { 65 | return question; 66 | } 67 | 68 | /** Not-null value; ensure this value is available before it is saved to the database. */ 69 | public void setQuestion(String question) { 70 | this.question = question; 71 | } 72 | 73 | public long getCategoryId() { 74 | return categoryId; 75 | } 76 | 77 | public void setCategoryId(long categoryId) { 78 | this.categoryId = categoryId; 79 | } 80 | 81 | /** To-many relationship, resolved on first access (and after reset). Changes to to-many relations are not persisted, make changes to the target entity. */ 82 | public List getAnswers() { 83 | if (answers == null) { 84 | if (daoSession == null) { 85 | throw new DaoException("Entity is detached from DAO context"); 86 | } 87 | AnswerDao targetDao = daoSession.getAnswerDao(); 88 | List answersNew = targetDao._queryChallenge_Answers(id); 89 | synchronized (this) { 90 | if(answers == null) { 91 | answers = answersNew; 92 | } 93 | } 94 | } 95 | return answers; 96 | } 97 | 98 | /** Resets a to-many relationship, making the next get call to query for a fresh result. */ 99 | public synchronized void resetAnswers() { 100 | answers = null; 101 | } 102 | 103 | /** Convenient call for {@link AbstractDao#delete(Object)}. Entity must attached to an entity context. */ 104 | public void delete() { 105 | if (myDao == null) { 106 | throw new DaoException("Entity is detached from DAO context"); 107 | } 108 | myDao.delete(this); 109 | } 110 | 111 | /** Convenient call for {@link AbstractDao#update(Object)}. Entity must attached to an entity context. */ 112 | public void update() { 113 | if (myDao == null) { 114 | throw new DaoException("Entity is detached from DAO context"); 115 | } 116 | myDao.update(this); 117 | } 118 | 119 | /** Convenient call for {@link AbstractDao#refresh(Object)}. Entity must attached to an entity context. */ 120 | public void refresh() { 121 | if (myDao == null) { 122 | throw new DaoException("Entity is detached from DAO context"); 123 | } 124 | myDao.refresh(this); 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/model/DaoMaster.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.model; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteDatabase.CursorFactory; 6 | import android.database.sqlite.SQLiteOpenHelper; 7 | import android.util.Log; 8 | import de.greenrobot.dao.AbstractDaoMaster; 9 | import de.greenrobot.dao.identityscope.IdentityScopeType; 10 | 11 | import de.fhdw.ergoholics.brainphaser.model.UserDao; 12 | import de.fhdw.ergoholics.brainphaser.model.CategoryDao; 13 | import de.fhdw.ergoholics.brainphaser.model.ChallengeDao; 14 | import de.fhdw.ergoholics.brainphaser.model.AnswerDao; 15 | import de.fhdw.ergoholics.brainphaser.model.CompletionDao; 16 | import de.fhdw.ergoholics.brainphaser.model.SettingsDao; 17 | import de.fhdw.ergoholics.brainphaser.model.StatisticsDao; 18 | 19 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. 20 | /** 21 | * Master of DAO (schema version 1): knows all DAOs. 22 | */ 23 | public class DaoMaster extends AbstractDaoMaster { 24 | public static final int SCHEMA_VERSION = 1; 25 | 26 | /** Creates underlying database table using DAOs. */ 27 | public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) { 28 | UserDao.createTable(db, ifNotExists); 29 | CategoryDao.createTable(db, ifNotExists); 30 | ChallengeDao.createTable(db, ifNotExists); 31 | AnswerDao.createTable(db, ifNotExists); 32 | CompletionDao.createTable(db, ifNotExists); 33 | SettingsDao.createTable(db, ifNotExists); 34 | StatisticsDao.createTable(db, ifNotExists); 35 | } 36 | 37 | /** Drops underlying database table using DAOs. */ 38 | public static void dropAllTables(SQLiteDatabase db, boolean ifExists) { 39 | UserDao.dropTable(db, ifExists); 40 | CategoryDao.dropTable(db, ifExists); 41 | ChallengeDao.dropTable(db, ifExists); 42 | AnswerDao.dropTable(db, ifExists); 43 | CompletionDao.dropTable(db, ifExists); 44 | SettingsDao.dropTable(db, ifExists); 45 | StatisticsDao.dropTable(db, ifExists); 46 | } 47 | 48 | public static abstract class OpenHelper extends SQLiteOpenHelper { 49 | 50 | public OpenHelper(Context context, String name, CursorFactory factory) { 51 | super(context, name, factory, SCHEMA_VERSION); 52 | } 53 | 54 | @Override 55 | public void onCreate(SQLiteDatabase db) { 56 | Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION); 57 | createAllTables(db, false); 58 | } 59 | } 60 | 61 | /** WARNING: Drops all table on Upgrade! Use only during development. */ 62 | public static class DevOpenHelper extends OpenHelper { 63 | public DevOpenHelper(Context context, String name, CursorFactory factory) { 64 | super(context, name, factory); 65 | } 66 | 67 | @Override 68 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 69 | Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables"); 70 | dropAllTables(db, true); 71 | onCreate(db); 72 | } 73 | } 74 | 75 | public DaoMaster(SQLiteDatabase db) { 76 | super(db, SCHEMA_VERSION); 77 | registerDaoClass(UserDao.class); 78 | registerDaoClass(CategoryDao.class); 79 | registerDaoClass(ChallengeDao.class); 80 | registerDaoClass(AnswerDao.class); 81 | registerDaoClass(CompletionDao.class); 82 | registerDaoClass(SettingsDao.class); 83 | registerDaoClass(StatisticsDao.class); 84 | } 85 | 86 | public DaoSession newSession() { 87 | return new DaoSession(db, IdentityScopeType.Session, daoConfigMap); 88 | } 89 | 90 | public DaoSession newSession(IdentityScopeType type) { 91 | return new DaoSession(db, type, daoConfigMap); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/model/Settings.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.model; 2 | 3 | // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit. 4 | /** 5 | * Entity mapped to table "SETTINGS". 6 | */ 7 | public class Settings { 8 | 9 | private Long id; 10 | private java.util.Date timeBoxStage1; 11 | private java.util.Date timeBoxStage2; 12 | private java.util.Date timeBoxStage3; 13 | private java.util.Date timeBoxStage4; 14 | private java.util.Date timeBoxStage5; 15 | private java.util.Date timeBoxStage6; 16 | 17 | public Settings() { 18 | } 19 | 20 | public Settings(Long id) { 21 | this.id = id; 22 | } 23 | 24 | public Settings(Long id, java.util.Date timeBoxStage1, java.util.Date timeBoxStage2, java.util.Date timeBoxStage3, java.util.Date timeBoxStage4, java.util.Date timeBoxStage5, java.util.Date timeBoxStage6) { 25 | this.id = id; 26 | this.timeBoxStage1 = timeBoxStage1; 27 | this.timeBoxStage2 = timeBoxStage2; 28 | this.timeBoxStage3 = timeBoxStage3; 29 | this.timeBoxStage4 = timeBoxStage4; 30 | this.timeBoxStage5 = timeBoxStage5; 31 | this.timeBoxStage6 = timeBoxStage6; 32 | } 33 | 34 | public Long getId() { 35 | return id; 36 | } 37 | 38 | public void setId(Long id) { 39 | this.id = id; 40 | } 41 | 42 | public java.util.Date getTimeBoxStage1() { 43 | return timeBoxStage1; 44 | } 45 | 46 | public void setTimeBoxStage1(java.util.Date timeBoxStage1) { 47 | this.timeBoxStage1 = timeBoxStage1; 48 | } 49 | 50 | public java.util.Date getTimeBoxStage2() { 51 | return timeBoxStage2; 52 | } 53 | 54 | public void setTimeBoxStage2(java.util.Date timeBoxStage2) { 55 | this.timeBoxStage2 = timeBoxStage2; 56 | } 57 | 58 | public java.util.Date getTimeBoxStage3() { 59 | return timeBoxStage3; 60 | } 61 | 62 | public void setTimeBoxStage3(java.util.Date timeBoxStage3) { 63 | this.timeBoxStage3 = timeBoxStage3; 64 | } 65 | 66 | public java.util.Date getTimeBoxStage4() { 67 | return timeBoxStage4; 68 | } 69 | 70 | public void setTimeBoxStage4(java.util.Date timeBoxStage4) { 71 | this.timeBoxStage4 = timeBoxStage4; 72 | } 73 | 74 | public java.util.Date getTimeBoxStage5() { 75 | return timeBoxStage5; 76 | } 77 | 78 | public void setTimeBoxStage5(java.util.Date timeBoxStage5) { 79 | this.timeBoxStage5 = timeBoxStage5; 80 | } 81 | 82 | public java.util.Date getTimeBoxStage6() { 83 | return timeBoxStage6; 84 | } 85 | 86 | public void setTimeBoxStage6(java.util.Date timeBoxStage6) { 87 | this.timeBoxStage6 = timeBoxStage6; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/utility/FileUtils.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.utility; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | /** 8 | * Created by thomasstuckel on 10/03/2016. 9 | * 10 | * This class contains all file utilitiy methods. 11 | */ 12 | public class FileUtils { 13 | /** 14 | * Resource: Pro Android by Syes Y. Hashimi and Satya Komatineni (2009) p.59 15 | * this funnctions reads all bytes from a stream and converts into a String 16 | * @param is input stream 17 | * @return a string 18 | * @throws IOException 19 | */ 20 | public static String convertStreamToString(InputStream is) throws IOException { 21 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 22 | int i = is.read(); 23 | while (i != -1) { 24 | baos.write(i); 25 | i = is.read(); 26 | } 27 | return baos.toString(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/de/fhdw/ergoholics/brainphaser/utility/ImageProxy.java: -------------------------------------------------------------------------------- 1 | package de.fhdw.ergoholics.brainphaser.utility; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.util.SparseArray; 6 | 7 | import com.squareup.picasso.Picasso; 8 | import com.squareup.picasso.RequestCreator; 9 | 10 | import java.io.File; 11 | 12 | /** 13 | * Created by funkv on 17.02.2016. 14 | * 15 | * Gives a combined interface for loading both filesystem images and resource drawables 16 | * via picasso. Filepaths that are drawable should be prefixed with @drawable/, the filepath is 17 | * then the resource name. 18 | */ 19 | public class ImageProxy { 20 | private static SparseArray requestCache = new SparseArray<>(); 21 | 22 | /** 23 | * Returns whether the path represents a drawable resource. 24 | * @param imagePath the path to analyze 25 | * @return true if the path represents a drawable resource 26 | */ 27 | public static boolean isDrawableImage(String imagePath) { 28 | return imagePath.startsWith("@drawable/"); 29 | } 30 | 31 | /** 32 | * Gets the resource id of an abstract path. 33 | * @param imagePath imagePath the path to analyze 34 | * @param context context to use 35 | * @return resource id of the corresponding drawable 36 | */ 37 | public static int getResourceId(String imagePath, Context context) { 38 | if (!isDrawableImage(imagePath)) { 39 | throw new IllegalArgumentException("Drawable is not a resource drawable."); 40 | } 41 | 42 | Resources resources = context.getResources(); 43 | String resourceName = imagePath.substring("@drawable/".length()); 44 | return resources.getIdentifier(resourceName, "drawable", context.getPackageName()); 45 | } 46 | 47 | /** 48 | * Loads an image using Picasso while caching it. 49 | * @param imagePath path as described above 50 | * @param context context to use 51 | * @return cached or newly created RequestCreator 52 | */ 53 | public static RequestCreator loadImage(String imagePath, Context context) { 54 | if (!isDrawableImage(imagePath)) { 55 | return Picasso.with(context).load(new File(imagePath)); 56 | } else { 57 | int resourceId = getResourceId(imagePath, context); 58 | RequestCreator requestCreator = requestCache.get(resourceId); 59 | if (requestCreator == null) { 60 | requestCreator = Picasso.with(context).load(resourceId); 61 | requestCache.put(resourceId, requestCreator); 62 | } 63 | 64 | return requestCreator; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/res/color/multiplechoice_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_check_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_check_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_cross.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_expand_less_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_expand_less_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_expand_more_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_expand_more_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_happyphaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_happyphaser.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_navigate_next_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_navigate_next_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_person_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_person_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_person_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_person_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_settings_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-hdpi/ic_settings_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_check_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_check_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_cross.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_expand_less_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_expand_less_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_expand_more_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_expand_more_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_happyphaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_happyphaser.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_navigate_next_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_navigate_next_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_person_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_person_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_person_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_person_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_settings_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-mdpi/ic_settings_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_check_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_check_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_cross.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_expand_less_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_expand_less_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_expand_more_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_expand_more_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_happyphaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_happyphaser.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_navigate_next_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_navigate_next_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_person_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_person_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_person_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_person_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xhdpi/ic_settings_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_check_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_cross.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_expand_less_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_expand_less_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_expand_more_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_expand_more_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_happyphaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_happyphaser.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_navigate_next_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_navigate_next_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_person_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_person_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_person_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_person_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_settings_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxhdpi/ic_settings_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_check_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_cross.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_expand_less_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_expand_less_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_expand_more_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_expand_more_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_happyphaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_happyphaser.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_navigate_next_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_navigate_next_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_person_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_person_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_person_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_person_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_settings_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable-xxxhdpi/ic_settings_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/all.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/all.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/anonymous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/anonymous.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/anonymous2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/anonymous2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/anonymous2_girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/anonymous2_girl.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/architektur.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/architektur.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/astronaut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/astronaut.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/basketball_man.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/basketball_man.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bomberman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/bomberman.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bomberman2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/bomberman2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/boxer_hispanic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/boxer_hispanic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bride_hispanic_material.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/bride_hispanic_material.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/budist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/budist.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/call_center_operator_man.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/call_center_operator_man.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/cashier_woman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/cashier_woman.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/computer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/computer.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/cook2_man.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/cook2_man.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/englisch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/englisch.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/european_commission.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/european_commission.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/international_trade.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/international_trade.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/multichoice_bg_checked.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/multichoice_bg_unchecked.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/multiple_choice_toggle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/physik_elektrizitaet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/physik_elektrizitaet.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/team.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ValentinFunk/BrainPhaser/7af7538656edd7d4176fa4d9cb2c92745ca354a9/app/src/main/res/drawable/team.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/text_meta_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 17 | 18 | 23 | 24 | 32 | 33 | 43 | 44 | 53 | 54 | 60 | 61 | 71 | 72 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_challenge.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 20 | 26 | 33 | 34 | 40 | 41 | 47 | 48 | 59 | 60 | 70 | 71 | 72 | 73 | 74 | 75 | 87 | 88 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_import_challenges.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 17 | 18 | 26 | 27 | 32 | 33 | 37 | 38 |