├── .gitignore
├── .idea
├── codeStyles
│ └── Project.xml
├── gradle.xml
├── jarRepositories.xml
├── misc.xml
├── render.experimental.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── remcv
│ │ └── com
│ │ └── github
│ │ └── examprep
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── java
│ │ └── remcv
│ │ │ └── com
│ │ │ └── github
│ │ │ └── examprep
│ │ │ ├── AddExamItemActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── TestSubjectsActivity.java
│ │ │ ├── UpdateDeleteItemActivity.java
│ │ │ ├── controller
│ │ │ ├── DatabaseCrud.java
│ │ │ └── DatabaseHandler.java
│ │ │ ├── model
│ │ │ └── ExamItem.java
│ │ │ ├── utils
│ │ │ ├── TableConstants.java
│ │ │ └── Utils.java
│ │ │ └── view
│ │ │ ├── DialogNumberOfQuestions.java
│ │ │ ├── ExamItemAdapter.java
│ │ │ └── MyDialogDatePicker.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── check_icon.png
│ │ ├── circle.xml
│ │ ├── circle2.xml
│ │ ├── circle_subject_solved.xml
│ │ ├── classroom.jpg
│ │ ├── ic_baseline_add_24.xml
│ │ ├── ic_baseline_notes_24.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── mountains.jpg
│ │ └── pencil.jpg
│ │ ├── layout
│ │ ├── activity_add_exam_item.xml
│ │ ├── activity_main.xml
│ │ ├── activity_test_subjects.xml
│ │ ├── activity_update_delete_item.xml
│ │ ├── dialog_number_of_questions.xml
│ │ ├── exam_item.xml
│ │ └── exam_item_test.xml
│ │ ├── menu
│ │ └── settings_menu.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── remcv
│ └── com
│ └── github
│ └── examprep
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots
└── Screenshot_03.jpg
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | xmlns:android
32 |
33 | ^$
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | xmlns:.*
43 |
44 | ^$
45 |
46 |
47 | BY_NAME
48 |
49 |
50 |
51 |
52 |
53 |
54 | .*:id
55 |
56 | http://schemas.android.com/apk/res/android
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | .*:name
66 |
67 | http://schemas.android.com/apk/res/android
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | name
77 |
78 | ^$
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | style
88 |
89 | ^$
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | .*
99 |
100 | ^$
101 |
102 |
103 | BY_NAME
104 |
105 |
106 |
107 |
108 |
109 |
110 | .*
111 |
112 | http://schemas.android.com/apk/res/android
113 |
114 |
115 | ANDROID_ATTRIBUTE_ORDER
116 |
117 |
118 |
119 |
120 |
121 |
122 | .*
123 |
124 | .*
125 |
126 |
127 | BY_NAME
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/render.experimental.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ExamPrep
2 |
3 | Simple Android application to help you prepare for your exams.
4 |
5 | ### How it works
6 | Randomly select a predefined number of questions from a list of questions.
7 |
8 | ### Features
9 | - add, update, delete exam items
10 | - countdown of the number of days until your exam (can be modified by the user)
11 | - the user can check and exclude the problems already solved
12 | - upload your own list of questions in .tsv format (number\tsubject\tisSolved) from your Android phone
13 | - test yourself with a user-determined number of random questions
14 |
15 | ### Screenshot
16 |
17 | 
18 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.3"
6 |
7 | defaultConfig {
8 | applicationId "remcv.com.github.examprep"
9 | minSdkVersion 28
10 | targetSdkVersion 29
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | }
16 |
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | compileOptions {
24 | sourceCompatibility JavaVersion.VERSION_1_8
25 | targetCompatibility JavaVersion.VERSION_1_8
26 | }
27 | }
28 |
29 | dependencies {
30 | implementation fileTree(dir: "libs", include: ["*.jar"])
31 | implementation 'androidx.appcompat:appcompat:1.1.0'
32 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
33 | implementation 'com.google.android.material:material:1.1.0'
34 | testImplementation 'junit:junit:4.12'
35 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
37 | implementation 'com.google.code.gson:gson:2.8.6'
38 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/androidTest/java/remcv/com/github/examprep/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest
20 | {
21 | @Test
22 | public void useAppContext()
23 | {
24 | // Context of the app under test.
25 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
26 | assertEquals("remcv.com.github.examprep", appContext.getPackageName());
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
15 |
18 |
19 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/AddExamItemActivity.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.util.Log;
8 | import android.widget.Button;
9 | import android.widget.CheckBox;
10 |
11 | import com.google.android.material.textfield.TextInputLayout;
12 |
13 | import remcv.com.github.examprep.utils.TableConstants;
14 | import remcv.com.github.examprep.utils.Utils;
15 |
16 | public class AddExamItemActivity extends AppCompatActivity
17 | {
18 | // fields - data
19 | public static final String TAG = "ExamPrep";
20 |
21 | // fields - layout
22 | private TextInputLayout categoryNumber_TIL;
23 | private TextInputLayout problem_TIL;
24 | private Button addItem_Button;
25 | private CheckBox subjectIsSolved_CB;
26 |
27 | // methods - lifecycle
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState)
30 | {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_add_exam_item);
33 |
34 | // initialize data
35 |
36 | // initialize layout
37 | initializeLayout();
38 |
39 | // handle button events
40 | addItem_Button.setOnClickListener((v) -> onAddItemButtonClicked());
41 | }
42 |
43 | // methods - handle button clicks
44 | public void onAddItemButtonClicked()
45 | {
46 | // check input data validity
47 | if (Utils.isNumberValid(categoryNumber_TIL) & Utils.isStringInputValid(problem_TIL))
48 | {
49 | int categoryNumber = Integer.parseInt(categoryNumber_TIL.getEditText().getText().toString());
50 | String problem = problem_TIL.getEditText().getText().toString();
51 | boolean isDone = subjectIsSolved_CB.isChecked();
52 |
53 | Log.d(TAG, "onAddItemButtonClicked: isDone before - " + isDone);
54 |
55 | Intent intent = new Intent(AddExamItemActivity.this, MainActivity.class);
56 | intent.putExtra(TableConstants.CATEGORY_NUMBER, categoryNumber);
57 | intent.putExtra(TableConstants.PROBLEM, problem);
58 | intent.putExtra(TableConstants.IS_DONE, isDone);
59 |
60 | // set result to pass to MainActivity
61 | setResult(RESULT_OK, intent);
62 |
63 | // finish current activity without starting a new MainActivity
64 | finish();
65 | }
66 | }
67 |
68 | // methods - data
69 | public void initializeData()
70 | {
71 | // TODO
72 | }
73 |
74 | // methods layout
75 | public void initializeLayout()
76 | {
77 | categoryNumber_TIL = findViewById(R.id.categoryNumberTextInputLayout_AAEI);
78 | problem_TIL = findViewById(R.id.problemTextInputLayout_AAEI);
79 | addItem_Button = findViewById(R.id.addItemButton_AAEI);
80 | subjectIsSolved_CB = findViewById(R.id.subjectSolvedCheckBox_AAEI);
81 | }
82 | }
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/MainActivity.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import androidx.appcompat.app.AppCompatActivity;
6 |
7 | import android.app.DatePickerDialog;
8 | import android.content.Intent;
9 | import android.content.SharedPreferences;
10 | import android.net.Uri;
11 | import android.os.Bundle;
12 | import android.util.Log;
13 | import android.view.Menu;
14 | import android.view.MenuInflater;
15 | import android.view.MenuItem;
16 | import android.widget.DatePicker;
17 | import android.widget.ListView;
18 | import android.widget.TextView;
19 | import android.widget.Toast;
20 |
21 | import com.google.gson.Gson;
22 |
23 | import java.io.BufferedReader;
24 | import java.io.File;
25 | import java.io.IOException;
26 | import java.io.InputStream;
27 | import java.io.InputStreamReader;
28 | import java.time.LocalDate;
29 | import java.time.Month;
30 | import java.util.Collections;
31 | import java.util.List;
32 | import java.util.stream.Collectors;
33 |
34 | import remcv.com.github.examprep.controller.DatabaseCrud;
35 | import remcv.com.github.examprep.controller.DatabaseHandler;
36 | import remcv.com.github.examprep.model.ExamItem;
37 | import remcv.com.github.examprep.utils.TableConstants;
38 | import remcv.com.github.examprep.utils.Utils;
39 | import remcv.com.github.examprep.view.DialogNumberOfQuestions;
40 | import remcv.com.github.examprep.view.ExamItemAdapter;
41 | import remcv.com.github.examprep.view.MyDialogDatePicker;
42 |
43 | public class MainActivity extends AppCompatActivity implements TableConstants, DialogNumberOfQuestions.DialogNumberOfQuestionsListener, DatePickerDialog.OnDateSetListener
44 | {
45 | // fields - data
46 | private File sourceFile;
47 | private DatabaseCrud databaseHandler;
48 | private ExamItemAdapter adapter;
49 | private int numberOfSubjectsToTest;
50 | private int solvedNumberOfSubjects;
51 | private LocalDate examDate;
52 |
53 | // fields - static final
54 | private static final String TAG = "ExamPrep";
55 | private static final int ADD_ITEM_REQUEST_CODE = 1;
56 | private static final int UPDATE_DELETE_ITEM_REQUEST_CODE = 2;
57 | private static final int UPLOAD_TSV_REQUEST_CODE = 3;
58 | public static final String SHARED_PREFS = "mySharedPrefs";
59 | public static final String NUMBER_OF_SUBJECTS = "numberOfSubjects";
60 | public static final String EXAM_YEAR = "examYear";
61 | public static final String EXAM_MONTH = "examMonth";
62 | public static final String EXAM_DAY = "examDay";
63 |
64 | // fields - layout
65 | private TextView countdown_TV;
66 | private TextView numberOfSubjects_TV;
67 | private TextView totalNumberOfSubjects_TV;
68 | private ListView problems_LV;
69 |
70 | // methods - lifecycle
71 | @Override
72 | protected void onCreate(Bundle savedInstanceState)
73 | {
74 | super.onCreate(savedInstanceState);
75 | setContentView(R.layout.activity_main);
76 |
77 | // initialize data
78 | initializeData();
79 |
80 | // initiate layout
81 | initializeLayout();
82 |
83 | // ListView adapter
84 | adapter = new ExamItemAdapter(databaseHandler.getList(), MainActivity.this);
85 | problems_LV.setAdapter(adapter);
86 |
87 | // handle events
88 | problems_LV.setOnItemClickListener((parent, view, position, id) -> onListViewItemClicked(position));
89 | }
90 |
91 | @Override
92 | protected void onStop()
93 | {
94 | super.onStop();
95 |
96 | // save database
97 | databaseHandler.saveDb(sourceFile);
98 | }
99 |
100 | @Override
101 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
102 | {
103 | super.onActivityResult(requestCode, resultCode, data);
104 |
105 | /*
106 | 1 - add item
107 | 2 - update OR delete
108 | 3 - import database from tsv file
109 | */
110 |
111 | if (resultCode == RESULT_OK)
112 | {
113 | switch (requestCode)
114 | {
115 | case ADD_ITEM_REQUEST_CODE:
116 | onAddItemReturn(data);
117 | break;
118 | case UPDATE_DELETE_ITEM_REQUEST_CODE:
119 | onUpdateDeleteReturn(data);
120 | break;
121 | case UPLOAD_TSV_REQUEST_CODE:
122 | onUploadReturn(data);
123 | break;
124 | }
125 | }
126 |
127 | Collections.sort(databaseHandler.getList());
128 | adapter.notifyDataSetChanged();
129 |
130 | updateData();
131 | updateUI();
132 | }
133 |
134 | // methods - handle events
135 | public void onListViewItemClicked(int position)
136 | {
137 | ExamItem examItem = databaseHandler.getList().get(position);
138 |
139 | Intent intent = new Intent(MainActivity.this, UpdateDeleteItemActivity.class);
140 | intent.putExtra(TableConstants.CATEGORY_NUMBER, examItem.getCategoryNumber());
141 | intent.putExtra(TableConstants.PROBLEM, examItem.getProblem());
142 | intent.putExtra(TableConstants.IS_DONE, examItem.getIsDone());
143 | intent.putExtra(TableConstants.INDEX, position);
144 |
145 | int requestCode = 2;
146 | startActivityForResult(intent, requestCode);
147 | }
148 |
149 | @Override
150 | public boolean onOptionsItemSelected(@NonNull MenuItem item)
151 | {
152 | switch (item.getItemId())
153 | {
154 | case R.id.settingsMenu_itemAdd:
155 | onAddButtonClicked();
156 | break;
157 | case R.id.settingsMenu_itemGenerateRandomList:
158 | onGenerateRandomListOfSubjectsClicked();
159 | break;
160 | case R.id.settingsMenu_itemChangeExamDate:
161 | onChangeExamDateMenuItemClicked();
162 | break;
163 | case R.id.settingsMenu_itemSetNoSubjectsInTest:
164 | createAlertDialogNumberOfQuestions();
165 | break;
166 | case R.id.settingsMenu_itemImport:
167 | onImportButtonClicked();
168 | break;
169 | }
170 |
171 | return true;
172 | }
173 |
174 | public void onAddButtonClicked()
175 | {
176 | Intent addIntent = new Intent(MainActivity.this, AddExamItemActivity.class);
177 | startActivityForResult(addIntent, ADD_ITEM_REQUEST_CODE);
178 | }
179 |
180 | public void onGenerateRandomListOfSubjectsClicked()
181 | {
182 | List list = databaseHandler.getList().stream()
183 | .filter(examItem -> !examItem.getIsDone())
184 | .collect(Collectors.toList());
185 |
186 | list = Utils.generateRandomSubjectList(numberOfSubjectsToTest, list);
187 |
188 | if (list == null)
189 | {
190 | Toast.makeText(this, "Not enough subjects or categories in your list", Toast.LENGTH_SHORT).show();
191 | }
192 | else
193 | {
194 | // send the list to TestSubjectsActivity
195 | Gson gson = new Gson();
196 | String listJson = gson.toJson(list);
197 |
198 | Intent toTestSubjectsActivityIntent = new Intent(MainActivity.this, TestSubjectsActivity.class);
199 | toTestSubjectsActivityIntent.putExtra(TableConstants.RANDOM_LIST, listJson);
200 |
201 | startActivity(toTestSubjectsActivityIntent);
202 | }
203 | }
204 |
205 | public void onImportButtonClicked()
206 | {
207 | // create Intent to open an external csv file
208 | Intent getCsvIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
209 | getCsvIntent.addCategory(Intent.CATEGORY_OPENABLE);
210 | getCsvIntent.setType("text/tab-separated-values");
211 |
212 | startActivityForResult(getCsvIntent, UPLOAD_TSV_REQUEST_CODE);
213 | }
214 |
215 | // methods - data
216 | public void initializeData()
217 | {
218 | // instantiate a DatabaseCrud implementation
219 | databaseHandler = new DatabaseHandler(MainActivity.this);
220 |
221 | // instantiate the database File object by accessing the Android device app storage
222 | sourceFile = new File(getApplicationContext().getFilesDir(), databaseHandler.getDatabasePath());
223 |
224 | // create the .csv file if it doesn't exist (for first time users)
225 | try
226 | {
227 | sourceFile.createNewFile();
228 | }
229 | catch (IOException e)
230 | {
231 | Log.e(TAG, "initializeData() " + e.getMessage());
232 | }
233 |
234 | // load the database from storage
235 | databaseHandler.loadDb(sourceFile);
236 | Collections.sort(databaseHandler.getList());
237 |
238 | // calculate solvedNumberOfSubjects
239 | solvedNumberOfSubjects = (int) databaseHandler.getList().stream()
240 | .filter(ExamItem::getIsDone)
241 | .count();
242 |
243 | // load the number of subjects (default value is 5)
244 | numberOfSubjectsToTest = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE).getInt(NUMBER_OF_SUBJECTS, 5);
245 |
246 | // load exam date
247 | int year = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE).getInt(EXAM_YEAR, 0);
248 | int month = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE).getInt(EXAM_MONTH, 0);
249 | int dayOfMonth = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE).getInt(EXAM_DAY, 0);
250 |
251 | if (year == 0)
252 | {
253 | // default value of exam date is 30 days from the current day
254 | examDate = LocalDate.now().plusDays(30);
255 | }
256 | else
257 | {
258 | examDate = LocalDate.of(year, month, dayOfMonth);
259 | }
260 | }
261 |
262 | public void updateData()
263 | {
264 | solvedNumberOfSubjects = (int) databaseHandler.getList().stream()
265 | .filter(ExamItem::getIsDone)
266 | .count();
267 | }
268 |
269 | public void onAddItemReturn(Intent data)
270 | {
271 | int categoryNumber = data.getIntExtra(TableConstants.CATEGORY_NUMBER, 0);
272 | String problem = data.getStringExtra(TableConstants.PROBLEM);
273 | boolean isDone = data.getBooleanExtra(TableConstants.IS_DONE, false);
274 |
275 | ExamItem newExamItem = new ExamItem(categoryNumber, problem, isDone);
276 | databaseHandler.getList().add(newExamItem);
277 |
278 | Toast.makeText(this, "Exam item added", Toast.LENGTH_SHORT).show();
279 | }
280 |
281 | public void onUpdateDeleteReturn(Intent data)
282 | {
283 | // get metadata
284 | String buttonName = data.getStringExtra(TableConstants.BUTTON_NAME);
285 | int index = data.getIntExtra(TableConstants.INDEX, 0);
286 |
287 | if (buttonName.equals("deleteButton"))
288 | {
289 | onDeleteReturn(index);
290 | }
291 | else // buttonName.equals("updateButton")
292 | {
293 | onUpdateReturn(index, data);
294 | }
295 | }
296 |
297 | public void onDeleteReturn(int index)
298 | {
299 | databaseHandler.getList().remove(index);
300 | Toast.makeText(MainActivity.this, "Item deleted", Toast.LENGTH_SHORT).show();
301 | }
302 |
303 | public void onUpdateReturn(int index, Intent data)
304 | {
305 | // gather data
306 | int categoryNumber = data.getIntExtra(TableConstants.CATEGORY_NUMBER, -1);
307 | String problem = data.getStringExtra(TableConstants.PROBLEM);
308 | boolean isDone = data.getBooleanExtra(TableConstants.IS_DONE, false);
309 |
310 | // create ExamItem and update it in list
311 | databaseHandler.getList().set(index, new ExamItem(categoryNumber, problem, isDone));
312 | }
313 |
314 | public void onDeleteItem(int index)
315 | {
316 | databaseHandler.getList().remove(index);
317 | Toast.makeText(this, "Exam item deleted", Toast.LENGTH_SHORT).show();
318 | }
319 |
320 | public void onUploadReturn(Intent data)
321 | {
322 | Uri csvUri = data.getData();
323 | InputStream inputStream = null;
324 |
325 | try
326 | {
327 | inputStream = getContentResolver().openInputStream(csvUri);
328 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
329 |
330 | // if no exception was thrown until here, then clear the old list
331 | databaseHandler.getList().clear();
332 |
333 | String line;
334 | String[] lineArray;
335 |
336 | while ((line = reader.readLine()) != null)
337 | {
338 | lineArray = line.split("\t", 3);
339 | int categoryNumber = Integer.parseInt(lineArray[0]);
340 | String problem = lineArray[1];
341 | boolean isDone = Boolean.parseBoolean(lineArray[2]);
342 |
343 | ExamItem item = new ExamItem(categoryNumber, problem, isDone);
344 | databaseHandler.getList().add(item);
345 | }
346 |
347 | reader.close();
348 | inputStream.close();
349 |
350 | // update data and UI
351 | solvedNumberOfSubjects = (int) databaseHandler.getList().stream()
352 | .filter(ExamItem::getIsDone)
353 | .count();
354 | totalNumberOfSubjects_TV.setText(String.format("Subjects (%d)", databaseHandler.getList().size()));
355 | }
356 | catch (Exception e)
357 | {
358 | Log.d(TAG, "onUploadReturn: exception " + e.getMessage());
359 | Toast.makeText(this, "File loading failed", Toast.LENGTH_SHORT).show();
360 | }
361 | }
362 |
363 | // methods layout
364 | public void initializeLayout()
365 | {
366 | countdown_TV = findViewById(R.id.countdownTextView_AM);
367 | numberOfSubjects_TV = findViewById(R.id.numberOfSubjects_AM);
368 | problems_LV = findViewById(R.id.problemsListView_AM);
369 | totalNumberOfSubjects_TV = findViewById(R.id.totalNumberOfSubjects_AM);
370 |
371 | // put data in layout
372 | updateUI();
373 | }
374 |
375 | @Override
376 | public boolean onCreateOptionsMenu(Menu menu)
377 | {
378 | MenuInflater inflater = getMenuInflater();
379 | inflater.inflate(R.menu.settings_menu, menu);
380 | return true;
381 | }
382 |
383 | public void updateUI()
384 | {
385 | numberOfSubjects_TV.setText(String.valueOf(numberOfSubjectsToTest));
386 | totalNumberOfSubjects_TV.setText(String.format("Subjects (%d solved / %d)", solvedNumberOfSubjects, databaseHandler.getList().size()));
387 | countdown_TV.setText(Utils.calculateDaysLeft(examDate));
388 | }
389 |
390 | // methods - alert dialog
391 | public void createAlertDialogNumberOfQuestions()
392 | {
393 | DialogNumberOfQuestions dialog = new DialogNumberOfQuestions();
394 | dialog.show(getSupportFragmentManager(), "DialogNumberOfQuestions");
395 | }
396 |
397 | public void onChangeExamDateMenuItemClicked()
398 | {
399 | MyDialogDatePicker dp = new MyDialogDatePicker();
400 | dp.show(getSupportFragmentManager(), "MyDialogDatePicker");
401 | }
402 |
403 | @Override
404 | public void getNumber(int number)
405 | {
406 | numberOfSubjectsToTest = number;
407 |
408 | // save the new value to SharedPreferences
409 | SharedPreferences sp = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
410 | SharedPreferences.Editor editor = sp.edit();
411 | editor.putInt(NUMBER_OF_SUBJECTS, numberOfSubjectsToTest);
412 | editor.apply();
413 |
414 | // update UI
415 | numberOfSubjects_TV.setText(String.valueOf(numberOfSubjectsToTest));
416 | }
417 |
418 | @Override
419 | public void onDateSet(DatePicker view, int year, int month, int dayOfMonth)
420 | {
421 | examDate = LocalDate.of(year, month + 1, dayOfMonth);
422 |
423 | // save new values to shared preferences
424 | SharedPreferences sp = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
425 | SharedPreferences.Editor editor = sp.edit();
426 | editor.putInt(EXAM_YEAR, year);
427 | editor.putInt(EXAM_MONTH, month + 1);
428 | editor.putInt(EXAM_DAY, dayOfMonth);
429 | editor.apply();
430 |
431 | // update UI
432 | updateUI();
433 | }
434 | }
435 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/TestSubjectsActivity.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.widget.ListView;
8 | import android.widget.TextView;
9 |
10 | import com.google.gson.Gson;
11 | import com.google.gson.reflect.TypeToken;
12 |
13 | import java.lang.reflect.Type;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | import remcv.com.github.examprep.model.ExamItem;
18 | import remcv.com.github.examprep.utils.TableConstants;
19 | import remcv.com.github.examprep.utils.Utils;
20 | import remcv.com.github.examprep.view.ExamItemAdapter;
21 |
22 | public class TestSubjectsActivity extends AppCompatActivity implements TableConstants
23 | {
24 | // fields - layout
25 | private TextView minutes_TV;
26 | private ListView subjects_LV;
27 |
28 | // fields - data
29 | private List examItems;
30 | private ExamItemAdapter adapter;
31 |
32 | // methods - life cycle
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState)
35 | {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.activity_test_subjects);
38 |
39 | // initialize layout
40 | initializeLayout();
41 |
42 | // initialize data
43 | initialDataSetup();
44 |
45 | // update layout
46 | updateLayout();
47 | }
48 |
49 | // methods - data
50 | public void initialDataSetup()
51 | {
52 | // get list of Exam items
53 | Intent getListIntent = getIntent();
54 | String listStringJson = getListIntent.getStringExtra(TableConstants.RANDOM_LIST);
55 |
56 | Gson gson = new Gson();
57 | Type type = new TypeToken>() {}.getType();
58 |
59 | examItems = gson.fromJson(listStringJson, type);
60 |
61 | // set adapter
62 | adapter = new ExamItemAdapter(examItems, TestSubjectsActivity.this);
63 | }
64 |
65 | // methods - layout
66 | public void initializeLayout()
67 | {
68 | minutes_TV = findViewById(R.id.minutesTextView_ATS);
69 | subjects_LV = findViewById(R.id.problemsListView_ATS);
70 | }
71 |
72 | public void updateLayout()
73 | {
74 | // minutes
75 | String minutes = Utils.calculateMinutes(examItems.size());
76 | minutes_TV.setText(minutes);
77 |
78 | // put items in listView
79 | subjects_LV.setAdapter(adapter);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/UpdateDeleteItemActivity.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.widget.Button;
8 | import android.widget.CheckBox;
9 |
10 | import com.google.android.material.textfield.TextInputLayout;
11 |
12 | import remcv.com.github.examprep.utils.TableConstants;
13 | import remcv.com.github.examprep.utils.Utils;
14 |
15 | public class UpdateDeleteItemActivity extends AppCompatActivity implements TableConstants
16 | {
17 | // fields - data
18 | private int indexOfItemInList;
19 |
20 | // fields - layout
21 | private TextInputLayout categoryNumber_til;
22 | private TextInputLayout problem_til;
23 | private Button updateButton;
24 | private Button deleteButton;
25 | private CheckBox subjectIsSolved_CB;
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState)
29 | {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_update_delete_item);
32 |
33 | // initialize layout
34 | initializeLayout();
35 |
36 | // initialize data
37 | initializeData();
38 |
39 | // handle events
40 | deleteButton.setOnClickListener(v -> onDeleteButtonClicked());
41 | updateButton.setOnClickListener(v -> onUpdateButtonClicked());
42 | }
43 |
44 | // methods - handle events
45 | public void onDeleteButtonClicked()
46 | {
47 | // create intent
48 | Intent intent = new Intent(UpdateDeleteItemActivity.this, MainActivity.class);
49 | intent.putExtra(TableConstants.INDEX, indexOfItemInList);
50 | intent.putExtra(TableConstants.BUTTON_NAME, "deleteButton");
51 |
52 | // set the result code
53 | setResult(RESULT_OK, intent);
54 |
55 | // close activity
56 | finish();
57 | }
58 |
59 | public void onUpdateButtonClicked()
60 | {
61 | // validate user input
62 | if (Utils.isNumberValid(categoryNumber_til) & Utils.isStringInputValid(problem_til))
63 | {
64 | // gather data
65 | int categoryNumber = Integer.parseInt(categoryNumber_til.getEditText().getText().toString());
66 | String problem = problem_til.getEditText().getText().toString();
67 | boolean isDone = subjectIsSolved_CB.isChecked();
68 |
69 | // make Intent and put the data in extras
70 | Intent intent = new Intent(UpdateDeleteItemActivity.this, MainActivity.class);
71 | intent.putExtra(TableConstants.CATEGORY_NUMBER, categoryNumber);
72 | intent.putExtra(TableConstants.PROBLEM, problem);
73 | intent.putExtra(TableConstants.IS_DONE, isDone);
74 | intent.putExtra(TableConstants.INDEX, indexOfItemInList);
75 | intent.putExtra(TableConstants.BUTTON_NAME, "updateButton");
76 |
77 | // set result to pass to MainActivity
78 | setResult(RESULT_OK, intent);
79 |
80 | // finish current activity without starting a new MainActivity
81 | finish();
82 | }
83 | }
84 |
85 | // methods - data
86 | public void initializeData()
87 | {
88 | Intent intent = getIntent();
89 |
90 | int categoryNumber = intent.getIntExtra(TableConstants.CATEGORY_NUMBER, 0);
91 | String problem = intent.getStringExtra(TableConstants.PROBLEM);
92 | boolean isDone = intent.getBooleanExtra(TableConstants.IS_DONE, false);
93 | indexOfItemInList = intent.getIntExtra(TableConstants.INDEX, 0);
94 |
95 | categoryNumber_til.getEditText().setText(String.valueOf(categoryNumber));
96 | problem_til.getEditText().setText(problem);
97 | subjectIsSolved_CB.setChecked(isDone);
98 | }
99 |
100 | // methods - layout
101 | public void initializeLayout()
102 | {
103 | categoryNumber_til = findViewById(R.id.categoryNumberTextInputLayout_AUDI);
104 | problem_til = findViewById(R.id.problemTextInputLayout_AUDI);
105 | updateButton = findViewById(R.id.updateItemButton_AUDI);
106 | deleteButton = findViewById(R.id.deleteItemButton_AUDI);
107 | subjectIsSolved_CB = findViewById(R.id.subjectSolvedCheckBox_AUDI);
108 | }
109 | }
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/controller/DatabaseCrud.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep.controller;
2 |
3 | import java.io.File;
4 | import java.util.List;
5 |
6 | public interface DatabaseCrud
7 | {
8 | public abstract boolean add(T item);
9 | public abstract T read(int id);
10 | public abstract boolean update(T item);
11 | public abstract boolean delete(int id);
12 | public abstract void loadDb(File databaseFile);
13 | public abstract void saveDb(File databaseFile);
14 | public abstract String getDatabasePath();
15 | public abstract List getList();
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/controller/DatabaseHandler.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep.controller;
2 |
3 | import android.app.Activity;
4 | import android.util.Log;
5 | import android.widget.Toast;
6 |
7 | import androidx.appcompat.app.AppCompatActivity;
8 |
9 | import java.io.BufferedReader;
10 | import java.io.BufferedWriter;
11 | import java.io.File;
12 | import java.io.FileReader;
13 | import java.io.FileWriter;
14 | import java.io.IOException;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | import remcv.com.github.examprep.model.ExamItem;
19 |
20 | public class DatabaseHandler implements DatabaseCrud
21 | {
22 | // fields
23 | private static final String FILE_PATH = "database.csv";
24 | private static final String TAG = "ExamPrep";
25 | private List examItemsList;
26 | private Activity mActivity;
27 |
28 | // constructor
29 | public DatabaseHandler(Activity activity)
30 | {
31 | mActivity = activity;
32 | examItemsList = new ArrayList();
33 | }
34 |
35 | // methods from interface
36 | @Override
37 | public boolean add(ExamItem item)
38 | {
39 | return examItemsList.add(item);
40 | }
41 |
42 | @Override
43 | public ExamItem read(int id)
44 | {
45 | // TODO
46 | return null;
47 | }
48 |
49 | @Override
50 | public boolean update(ExamItem item)
51 | {
52 | // TODO
53 | return false;
54 | }
55 |
56 | @Override
57 | public boolean delete(int id)
58 | {
59 | // TODO
60 | return false;
61 | }
62 |
63 | @Override
64 | public void loadDb(File databaseFile)
65 | {
66 | try (BufferedReader br = new BufferedReader(new FileReader(databaseFile)))
67 | {
68 | int categoryNumber;
69 | String problem;
70 | boolean isDone;
71 |
72 | String s;
73 | String[] oneRow;
74 |
75 | while((s = br.readLine()) != null)
76 | {
77 | oneRow = s.split(",", 3);
78 | categoryNumber = Integer.parseInt(oneRow[0]);
79 | problem = oneRow[1];
80 | isDone = Boolean.parseBoolean(oneRow[2]);
81 |
82 | ExamItem item = new ExamItem(categoryNumber, problem, isDone);
83 | examItemsList.add(item);
84 | }
85 | }
86 | catch (IOException e)
87 | {
88 | Log.e(TAG, "loadDb() exception thrown " + e.toString());
89 | Toast.makeText(mActivity.getApplicationContext(), "Load failed ...", Toast.LENGTH_SHORT).show();
90 | }
91 | }
92 |
93 | @Override
94 | public void saveDb(File databaseFile)
95 | {
96 | try (BufferedWriter bw = new BufferedWriter(new FileWriter(databaseFile)))
97 | {
98 | StringBuilder oneItem = new StringBuilder();
99 |
100 | for (ExamItem item : examItemsList)
101 | {
102 | oneItem.append(item.getCategoryNumber());
103 | oneItem.append(",");
104 | oneItem.append(item.getProblem());
105 | oneItem.append(",");
106 | oneItem.append(item.getIsDone());
107 |
108 | bw.write(oneItem.toString());
109 | Log.d(TAG, "saveDb() item " + item.toString());
110 | bw.newLine();
111 | bw.flush();
112 |
113 | oneItem.delete(0, oneItem.length());
114 | }
115 | }
116 | catch (IOException e)
117 | {
118 | Log.e(TAG, "saveDb() exception thrown " + e.toString());
119 | }
120 | }
121 |
122 | // methods - getters
123 | @Override
124 | public List getList()
125 | {
126 | return examItemsList;
127 | }
128 |
129 | @Override
130 | public String getDatabasePath()
131 | {
132 | return FILE_PATH;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/model/ExamItem.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep.model;
2 |
3 | public class ExamItem implements Comparable
4 | {
5 | // fields
6 | private int categoryNumber;
7 | private String problem;
8 | private boolean isDone;
9 |
10 | // constructor
11 | public ExamItem(int categoryNumber, String problem, boolean isDone)
12 | {
13 | this.categoryNumber = categoryNumber;
14 | this.problem = problem;
15 | this.isDone = isDone;
16 | }
17 |
18 | // methods - getters
19 | public int getCategoryNumber()
20 | {
21 | return categoryNumber;
22 | }
23 |
24 | public String getProblem()
25 | {
26 | return problem;
27 | }
28 |
29 | public boolean getIsDone()
30 | {
31 | return isDone;
32 | }
33 |
34 | // methods - interface
35 | @Override
36 | public int compareTo(ExamItem other)
37 | {
38 | // by category number, than alphabetical
39 | if (this.categoryNumber == other.getCategoryNumber())
40 | {
41 | return this.problem.compareTo(other.getProblem());
42 | }
43 | else
44 | {
45 | return this.categoryNumber - other.getCategoryNumber();
46 | }
47 | }
48 |
49 | // methods - toString
50 | @Override
51 | public String toString()
52 | {
53 | return "ExamItem{" +
54 | "categoryNumber=" + categoryNumber +
55 | ", problem='" + problem + '\'' +
56 | ", isDone=" + isDone +
57 | '}';
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/utils/TableConstants.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep.utils;
2 |
3 | public interface TableConstants
4 | {
5 | public static final String CATEGORY_NUMBER = "categoryNumber";
6 | public static final String PROBLEM = "problem";
7 | public static final String INDEX = "index";
8 | public static final String BUTTON_NAME = "buttonName";
9 | public static final String IS_DONE = "isDone";
10 | public static final String RANDOM_LIST = "randomList";
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep.utils;
2 |
3 | import android.util.Log;
4 |
5 | import com.google.android.material.textfield.TextInputLayout;
6 |
7 | import java.time.LocalDate;
8 | import java.time.Period;
9 | import java.time.chrono.ChronoPeriod;
10 | import java.time.temporal.ChronoUnit;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import java.util.Random;
14 |
15 | import remcv.com.github.examprep.model.ExamItem;
16 |
17 | public class Utils
18 | {
19 | // fields
20 | public static final int MINUTES_PER_SUBJECT = 18;
21 |
22 | // methods
23 | public static String calculateDaysLeft(LocalDate examDate)
24 | {
25 | long daysLeft = ChronoUnit.DAYS.between(LocalDate.now(), examDate);
26 | return String.valueOf(daysLeft);
27 | }
28 |
29 | public static String calculateMinutes(int numberOfSubjects)
30 | {
31 | return String.valueOf(numberOfSubjects * MINUTES_PER_SUBJECT);
32 | }
33 |
34 | public static List generateRandomSubjectList(int numberOfSubjects, List list)
35 | {
36 | // setup
37 | int listSize = list.size();
38 | long numberOfCateg = list.stream()
39 | .map(examItem -> Integer.valueOf(examItem.getCategoryNumber()))
40 | .distinct()
41 | .count();
42 |
43 | ArrayList indexesOfTakenSubjects = new ArrayList<>();
44 | ArrayList categoriesPicked = new ArrayList<>();
45 |
46 | // check if numberOfSubjects is greater than the subjects from the list
47 | if (numberOfSubjects > listSize)
48 | {
49 | return null;
50 | }
51 | else if (numberOfSubjects > (int) numberOfCateg)
52 | {
53 | return null;
54 | }
55 | else
56 | {
57 | Random random = new Random();
58 | int tempNumber;
59 |
60 | while (indexesOfTakenSubjects.size() < numberOfSubjects)
61 | {
62 | tempNumber = random.nextInt(listSize);
63 |
64 | if (indexesOfTakenSubjects.contains(tempNumber))
65 | {
66 | continue;
67 | }
68 | else
69 | {
70 | if (categoriesPicked.contains(list.get(tempNumber).getCategoryNumber()))
71 | {
72 | continue;
73 | }
74 | else
75 | {
76 | indexesOfTakenSubjects.add(tempNumber);
77 | categoriesPicked.add(list.get(tempNumber).getCategoryNumber());
78 | }
79 | }
80 | }
81 | }
82 |
83 | ArrayList listToReturn = new ArrayList<>();
84 |
85 | for (Integer i : indexesOfTakenSubjects)
86 | {
87 | listToReturn.add(list.get(i));
88 | }
89 |
90 | return listToReturn;
91 | }
92 |
93 | // input validation methods
94 | public static boolean isNumberValid(TextInputLayout til)
95 | {
96 | String idString = til.getEditText().getText().toString();
97 |
98 | // check if field is empty
99 | if (idString.trim().isEmpty())
100 | {
101 | til.setError("Empty fields are not allowed");
102 | return false;
103 | }
104 | else
105 | {
106 | try
107 | {
108 | Integer.parseInt(idString);
109 | til.setError(null);
110 | return true;
111 | }
112 | catch (NumberFormatException e)
113 | {
114 | til.setError("Invalid number");
115 | return false;
116 | }
117 | }
118 | }
119 |
120 | public static boolean isStringInputValid(TextInputLayout til)
121 | {
122 | String problem = til.getEditText().getText().toString();
123 |
124 | if (problem.trim().isEmpty())
125 | {
126 | til.setError("Empty fields are not allowed");
127 | return false;
128 | }
129 | else
130 | {
131 | til.setError(null);
132 | return true;
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/view/DialogNumberOfQuestions.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep.view;
2 |
3 | import android.app.AlertDialog;
4 | import android.app.Dialog;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 | import android.os.Bundle;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.widget.EditText;
11 |
12 | import androidx.annotation.NonNull;
13 | import androidx.annotation.Nullable;
14 | import androidx.appcompat.app.AppCompatDialogFragment;
15 |
16 | import remcv.com.github.examprep.R;
17 |
18 | public class DialogNumberOfQuestions extends AppCompatDialogFragment
19 | {
20 | // fields
21 | private DialogNumberOfQuestionsListener dnoq;
22 |
23 | // nested interface
24 | public interface DialogNumberOfQuestionsListener
25 | {
26 | void getNumber(int number);
27 | }
28 |
29 | // constructor
30 | @NonNull
31 | @Override
32 | public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
33 | {
34 | //
35 |
36 |
37 | //
38 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
39 |
40 | LayoutInflater inflater = getActivity().getLayoutInflater();
41 | View view = inflater.inflate(R.layout.dialog_number_of_questions, null);
42 | EditText numberOfQuestions_ET = view.findViewById(R.id.numberOfQuestions_ET_DNQ);
43 |
44 | builder.setView(view)
45 | .setTitle("Number of questions for test")
46 | .setNegativeButton("cancel", new DialogInterface.OnClickListener()
47 | {
48 | @Override
49 | public void onClick(DialogInterface dialog, int which)
50 | {
51 | dismiss();
52 | }
53 | })
54 | .setPositiveButton("save", new DialogInterface.OnClickListener()
55 | {
56 | @Override
57 | public void onClick(DialogInterface dialog, int which)
58 | {
59 | int numberOfQuestions = Integer.parseInt(numberOfQuestions_ET.getText().toString());
60 | dnoq.getNumber(numberOfQuestions);
61 | }
62 | });
63 |
64 |
65 |
66 | return builder.create();
67 | }
68 |
69 | // methods
70 | @Override
71 | public void onAttach(@NonNull Context context)
72 | {
73 | super.onAttach(context);
74 |
75 | try
76 | {
77 | dnoq = (DialogNumberOfQuestionsListener) context;
78 | }
79 | catch (ClassCastException e)
80 | {
81 | throw new ClassCastException(context.toString() + " must implement DialogNumberOfQuestionsListener");
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/view/ExamItemAdapter.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep.view;
2 |
3 | import android.app.Activity;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.ImageView;
9 | import android.widget.TextView;
10 |
11 | import java.util.List;
12 |
13 | import remcv.com.github.examprep.R;
14 | import remcv.com.github.examprep.model.ExamItem;
15 |
16 | public class ExamItemAdapter extends BaseAdapter
17 | {
18 | // fields
19 | private List list;
20 | private Activity activity;
21 |
22 | // constructor
23 | public ExamItemAdapter(List list, Activity activity)
24 | {
25 | this.list = list;
26 | this.activity = activity;
27 | }
28 |
29 | // methods from parent class
30 | @Override
31 | public int getCount()
32 | {
33 | return list.size();
34 | }
35 |
36 | @Override
37 | public ExamItem getItem(int position)
38 | {
39 | return list.get(position);
40 | }
41 |
42 | @Override
43 | public long getItemId(int position)
44 | {
45 | return 0;
46 | }
47 |
48 | @Override
49 | public View getView(int position, View convertView, ViewGroup parent)
50 | {
51 | View oneExamItemView;
52 | LayoutInflater inflater = LayoutInflater.from(activity);
53 | oneExamItemView = inflater.inflate(R.layout.exam_item, parent, false);
54 |
55 | // initialize layout
56 | TextView categoryNumber_TV = oneExamItemView.findViewById(R.id.categoryNumberTextView_EI);
57 | TextView problem_TV = oneExamItemView.findViewById(R.id.problemTextView_EI);
58 |
59 | // put data in view
60 | ExamItem examItem = list.get(position);
61 | categoryNumber_TV.setText(String.valueOf(examItem.getCategoryNumber()));
62 | problem_TV.setText(examItem.getProblem());
63 |
64 | if (examItem.getIsDone())
65 | {
66 | categoryNumber_TV.setBackgroundResource(R.drawable.circle_subject_solved);
67 | }
68 |
69 | return oneExamItemView;
70 | }
71 |
72 | // methods - setters
73 | public void setList(List list)
74 | {
75 | this.list = list;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/remcv/com/github/examprep/view/MyDialogDatePicker.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep.view;
2 |
3 | import android.app.DatePickerDialog;
4 | import android.app.Dialog;
5 | import android.os.Bundle;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.annotation.Nullable;
9 | import androidx.fragment.app.DialogFragment;
10 |
11 | import java.util.Calendar;
12 |
13 | public class MyDialogDatePicker extends DialogFragment
14 | {
15 | @NonNull
16 | @Override
17 | public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
18 | {
19 | // use the current date as the default date in the picker
20 | final Calendar c = Calendar.getInstance();
21 | int year = c.get(Calendar.YEAR);
22 | int month = c.get(Calendar.MONTH);
23 | int day = c.get(Calendar.DAY_OF_MONTH);
24 |
25 | // create an instance of DatePickerDialog and return it
26 | return new DatePickerDialog(getActivity(), (DatePickerDialog.OnDateSetListener) getActivity(), year, month, day);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/check_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/drawable/check_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/circle_subject_solved.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/classroom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/drawable/classroom.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_add_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_notes_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/mountains.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/drawable/mountains.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pencil.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/drawable/pencil.jpg
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_add_exam_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
18 |
19 |
28 |
29 |
36 |
37 |
42 |
43 |
44 |
51 |
52 |
57 |
58 |
59 |
67 |
68 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
15 |
16 |
25 |
26 |
37 |
38 |
47 |
48 |
55 |
56 |
57 |
58 |
69 |
70 |
79 |
80 |
87 |
88 |
89 |
90 |
91 |
92 |
101 |
102 |
110 |
111 |
120 |
121 |
122 |
123 |
124 |
125 |
132 |
133 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_test_subjects.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
15 |
16 |
25 |
26 |
37 |
38 |
47 |
48 |
55 |
56 |
57 |
58 |
59 |
60 |
69 |
70 |
78 |
79 |
87 |
88 |
89 |
90 |
91 |
98 |
99 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_update_delete_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
18 |
19 |
28 |
29 |
36 |
37 |
42 |
43 |
44 |
51 |
52 |
57 |
58 |
59 |
66 |
67 |
74 |
75 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_number_of_questions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/exam_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
26 |
27 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/exam_item_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/settings_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2E7D32
4 | #2E7D32
5 | #3949AB
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ExamPrep
3 | solved
4 | subject is solved
5 | Import
6 | Add
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/test/java/remcv/com/github/examprep/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package remcv.com.github.examprep;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest
13 | {
14 | @Test
15 | public void addition_isCorrect()
16 | {
17 | assertEquals(4, 2 + 2);
18 | }
19 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:4.0.1"
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | jcenter()
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Aug 03 07:11:37 EEST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/screenshots/Screenshot_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remcv/ExamPrep-Android/da0fbe255c73bb2d2a1a5605c2152b8ddbd4a0f5/screenshots/Screenshot_03.jpg
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | rootProject.name = "ExamPrep"
--------------------------------------------------------------------------------