├── .gitignore
├── .idea
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── quaap
│ │ └── primary
│ │ ├── AboutActivity.java
│ │ ├── Levels.java
│ │ ├── MainActivity.java
│ │ ├── NounCleanActivity.java
│ │ ├── Primary.java
│ │ ├── ScoresActivity.java
│ │ ├── SettingsActivity.java
│ │ ├── base
│ │ ├── CommonBaseActivity.java
│ │ ├── Level.java
│ │ ├── StdGameActivity.java
│ │ ├── StdLevel.java
│ │ ├── SubjectBaseActivity.java
│ │ ├── SubjectMenuActivity.java
│ │ ├── component
│ │ │ ├── ActivityWriter.java
│ │ │ ├── HorzItemList.java
│ │ │ ├── InputMode.java
│ │ │ ├── Keyboard.java
│ │ │ ├── SoundEffects.java
│ │ │ └── TextToVoice.java
│ │ └── data
│ │ │ ├── AppData.java
│ │ │ ├── SubjectGroup.java
│ │ │ ├── Subjects.java
│ │ │ └── UserData.java
│ │ ├── math
│ │ ├── BasicMathActivity.java
│ │ ├── BasicMathLevel.java
│ │ ├── MathOp.java
│ │ ├── Negatives.java
│ │ ├── SortingActivity.java
│ │ └── SortingLevel.java
│ │ ├── partsofspeech
│ │ └── plurals
│ │ │ ├── PluralActivity.java
│ │ │ └── PluralLevel.java
│ │ ├── spelling
│ │ ├── SpellingActivity.java
│ │ └── SpellingLevel.java
│ │ └── timemoney
│ │ ├── TimeActivity.java
│ │ └── TimeLevel.java
│ ├── primary_launcher-web.png
│ └── res
│ ├── layout
│ ├── activity_about.xml
│ ├── activity_login.xml
│ ├── activity_noun_clean.xml
│ ├── activity_scores.xml
│ ├── activity_subject_menu.xml
│ ├── horz_list_view.xml
│ ├── level_complete.xml
│ ├── scores1.xml
│ ├── scores2.xml
│ ├── spinner_item.xml
│ ├── std_game_layout.xml
│ ├── std_math_prob.xml
│ ├── std_plural_prob.xml
│ ├── std_sorting_prob.xml
│ ├── std_spelling_prob.xml
│ ├── std_time_prob.xml
│ ├── subject_view.xml
│ ├── typed_input.xml
│ └── user_avatar.xml
│ ├── menu
│ └── main_menu.xml
│ ├── mipmap-hdpi
│ └── primary_launcher.png
│ ├── mipmap-mdpi
│ └── primary_launcher.png
│ ├── mipmap-xhdpi
│ └── primary_launcher.png
│ ├── mipmap-xxhdpi
│ └── primary_launcher.png
│ ├── mipmap-xxxhdpi
│ └── primary_launcher.png
│ ├── raw
│ ├── baba.ogg
│ ├── badbing.ogg
│ ├── badbong.ogg
│ ├── drumrollhit.ogg
│ ├── goodbing.ogg
│ ├── highclick.ogg
│ ├── hit.ogg
│ ├── lowclick.ogg
│ ├── next_level.png
│ └── repeat_level.png
│ ├── values-w820dp
│ └── dimens.xml
│ ├── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── keyboards.xml
│ ├── nouns.xml
│ ├── plurals.xml
│ ├── preferences.xml
│ ├── spelling.xml
│ ├── strings.xml
│ ├── styles.xml
│ └── subjects.xml
│ └── xml
│ ├── preference_headers.xml
│ └── preferences.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
15 |
20 |
25 |
6 | * Copyright (C) 2016 Tom Kliethermes 7 | *
8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 3 of the License, or 11 | * (at your option) any later version. 12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | */
18 | import android.content.pm.PackageInfo;
19 | import android.content.pm.PackageManager;
20 | import android.os.Build;
21 | import android.os.Bundle;
22 | import android.text.Html;
23 | import android.text.method.LinkMovementMethod;
24 | import android.widget.TextView;
25 |
26 | import com.quaap.primary.base.CommonBaseActivity;
27 |
28 | public class AboutActivity extends CommonBaseActivity {
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_about);
34 |
35 |
36 | try {
37 | PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
38 | String version = pInfo.versionName;
39 |
40 | TextView txtappname = findViewById(R.id.txtappname);
41 | txtappname.setText(getString(R.string.app_name) + " " + version);
42 |
43 | } catch (PackageManager.NameNotFoundException e) {
44 | e.printStackTrace();
45 | }
46 |
47 | TextView txtAbout = findViewById(R.id.txtAbout);
48 | txtAbout.setMovementMethod(LinkMovementMethod.getInstance());
49 | if (Build.VERSION.SDK_INT >= 24) {
50 | txtAbout.setText(Html.fromHtml(getString(R.string.about_primary), 0));
51 | } else {
52 | txtAbout.setText(Html.fromHtml(getString(R.string.about_primary)));
53 |
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/NounCleanActivity.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import android.widget.TextView;
8 |
9 | import com.quaap.primary.base.component.ActivityWriter;
10 |
11 | import java.io.File;
12 | import java.io.FileWriter;
13 | import java.io.IOException;
14 |
15 | public class NounCleanActivity extends AppCompatActivity {
16 |
17 | private String [] plurals;
18 | private File outdir;
19 | private FileWriter badpluralsfile;
20 | private FileWriter goodpluralsfile;
21 |
22 | private int onval = 0;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_noun_clean);
28 |
29 | Button good = findViewById(R.id.noun_clean_good);
30 | Button bad = findViewById(R.id.noun_clean_bad);
31 |
32 |
33 |
34 |
35 |
36 |
37 | good.setOnClickListener(new View.OnClickListener() {
38 | @Override
39 | public void onClick(View view) {
40 |
41 | try {
42 | goodpluralsfile.write("
12 | * Copyright (C) 2016 tom 13 | *
14 | * This program is free software; you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation; either version 3 of the License, or 17 | * (at your option) any later version. 18 | *
19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU General Public License for more details. 23 | */ 24 | public class Primary extends Application { 25 | 26 | private TextToVoice mTtv; 27 | 28 | 29 | private SoundEffects mSoundEffects; 30 | 31 | @Override 32 | public void onCreate() { 33 | super.onCreate(); 34 | mSoundEffects = new SoundEffects(this); 35 | } 36 | 37 | 38 | public SoundEffects getSoundEffects() { 39 | return mSoundEffects; 40 | } 41 | 42 | public TextToVoice getTextToVoice() { 43 | if (mTtv == null) { 44 | mTtv = new TextToVoice(this); 45 | } 46 | return mTtv; 47 | } 48 | 49 | @Override 50 | public void onTerminate() { 51 | if (mTtv != null) { 52 | mTtv.shutDown(); 53 | mTtv = null; 54 | } 55 | mSoundEffects.release(); 56 | super.onTerminate(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/quaap/primary/ScoresActivity.java: -------------------------------------------------------------------------------- 1 | package com.quaap.primary; 2 | 3 | /** 4 | * Created by tom on 12/15/16. 5 | *
6 | * Copyright (C) 2016 Tom Kliethermes 7 | *
8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 3 of the License, or 11 | * (at your option) any later version. 12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | */
18 | import android.os.Bundle;
19 | import android.view.ViewGroup;
20 | import android.widget.GridLayout;
21 | import android.widget.LinearLayout;
22 | import android.widget.TextView;
23 |
24 | import com.quaap.primary.base.CommonBaseActivity;
25 | import com.quaap.primary.base.data.AppData;
26 | import com.quaap.primary.base.data.Subjects;
27 | import com.quaap.primary.base.data.UserData;
28 |
29 | import java.util.Map;
30 |
31 | public class ScoresActivity extends CommonBaseActivity {
32 |
33 | private AppData mAppdata;
34 |
35 | private Subjects subjects;
36 |
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | setContentView(R.layout.activity_scores);
41 |
42 | //ViewGroup scroll = (ViewGroup) findViewById(R.id.scores_scroll);
43 |
44 | LinearLayout list = findViewById(R.id.scores_list);
45 |
46 | subjects = Subjects.getInstance(this);
47 |
48 | mAppdata = AppData.getAppData(this);
49 |
50 | for (String username : mAppdata.listUsers()) {
51 | showUserData(list, username);
52 | }
53 |
54 | }
55 |
56 | private void showUserData(ViewGroup list, String username) {
57 | UserData user = mAppdata.getUser(username);
58 |
59 | TextView uname = new TextView(this);
60 | String avname = user.getAvatar() + " " + user.getUsername() + ": " + user.getTotalPoints();
61 | uname.setPadding(0, 23, 0, 2);
62 | uname.setText(avname);
63 | uname.setTextSize(24);
64 | list.addView(uname);
65 |
66 | GridLayout userlayout = new GridLayout(this);
67 | //userlayout.setOrientation(GridLayout.VERTICAL);
68 | userlayout.setColumnCount(2);
69 | userlayout.setPadding(24, 8, 4, 16);
70 | list.addView(userlayout);
71 |
72 | for (String sub : user.getSubjectsStarted()) {
73 |
74 | UserData.Subject subject = user.getSubjectForUser(sub);
75 |
76 | addTextView(userlayout, sub + " (" + subjects.get(sub).getName() + "): ", 20, 0);
77 | addTextView(userlayout, subject.getTotalPoints() + "");
78 |
79 | Map
13 | * Copyright (C) 2016 tom
14 | *
15 | * This program is free software; you can redistribute it and/or modify
16 | * it under the terms of the GNU General Public License as published by
17 | * the Free Software Foundation; either version 3 of the License, or
18 | * (at your option) any later version.
19 | *
20 | * This program is distributed in the hope that it will be useful,
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 | * GNU General Public License for more details.
24 | */
25 | public class SettingsActivity extends PreferenceActivity {
26 |
27 |
28 | @Override
29 | protected boolean isValidFragment(String fragmentName) {
30 | if (fragmentName.equals("com.quaap.primary.SettingsActivity$SettingsFragment")) {
31 | return true;
32 | }
33 | return super.isValidFragment(fragmentName);
34 | }
35 |
36 | @Override
37 | public Intent getIntent() {
38 |
39 | final Intent modIntent = new Intent(super.getIntent());
40 | modIntent.putExtra(EXTRA_SHOW_FRAGMENT, SettingsFragment.class.getName());
41 | modIntent.putExtra(EXTRA_NO_HEADERS, true);
42 | return modIntent;
43 | }
44 |
45 | @Override
46 | public void onBuildHeaders(List
23 | * Copyright (C) 2016 tom
24 | *
25 | * This program is free software; you can redistribute it and/or modify
26 | * it under the terms of the GNU General Public License as published by
27 | * the Free Software Foundation; either version 3 of the License, or
28 | * (at your option) any later version.
29 | *
30 | * This program is distributed in the hope that it will be useful,
31 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 | * GNU General Public License for more details.
34 | */
35 | @SuppressLint("Registered")
36 | public class CommonBaseActivity extends AppCompatActivity {
37 |
38 | // Things here are common to ALL activities.
39 |
40 | private static final int REQUEST_WRITE_EXTERNAL_STORAGE = 121;
41 |
42 | @Override
43 | public boolean onCreateOptionsMenu(Menu menu) {
44 | super.onCreateOptionsMenu(menu);
45 | // Inflate the menu; this adds items to the action bar if it is present.
46 | getMenuInflater().inflate(R.menu.main_menu, menu);
47 |
48 | return true;
49 | }
50 |
51 | @Override
52 | public boolean onOptionsItemSelected(MenuItem item) {
53 | int id = item.getItemId();
54 |
55 | Intent intent = null;
56 | switch (id) {
57 | case R.id.menu_about:
58 | intent = new Intent(this, AboutActivity.class);
59 | break;
60 | case R.id.menu_scores:
61 | intent = new Intent(this, ScoresActivity.class);
62 | break;
63 | case R.id.menu_settings:
64 | intent = new Intent(this, SettingsActivity.class);
65 | break;
66 | }
67 | if (intent != null) {
68 |
69 | intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
70 | intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
71 | intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
72 | startActivity(intent);
73 | }
74 | return super.onOptionsItemSelected(item);
75 | }
76 |
77 |
78 | boolean hasStorageAccess() {
79 | return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
80 | }
81 |
82 |
83 | protected void checkStorageAccess() {
84 | boolean beendenied = getSharedPreferences(this.getClass().getName(), MODE_PRIVATE).getBoolean("denied", false);
85 | if (!beendenied && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
86 | ActivityCompat.requestPermissions(this,
87 | new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
88 | REQUEST_WRITE_EXTERNAL_STORAGE);
89 | }
90 | }
91 |
92 | @Override
93 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
94 | switch (requestCode) {
95 | case REQUEST_WRITE_EXTERNAL_STORAGE: {
96 | // If request is cancelled, the result arrays are empty.
97 | if (grantResults.length > 0
98 | && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
99 |
100 | Toast.makeText(this, R.string.write_perms_granted, Toast.LENGTH_SHORT).show();
101 | } else {
102 | Toast.makeText(this, R.string.write_perms_denied, Toast.LENGTH_LONG).show();
103 | getSharedPreferences(this.getClass().getName(), MODE_PRIVATE).edit().putBoolean("denied", true).apply();
104 | }
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/base/Level.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.base;
2 |
3 | import android.content.Context;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | /**
9 | * Created by tom on 12/15/16.
10 | *
11 | * Copyright (C) 2016 Tom Kliethermes
12 | *
13 | * This program is free software; you can redistribute it and/or modify
14 | * it under the terms of the GNU General Public License as published by
15 | * the Free Software Foundation; either version 3 of the License, or
16 | * (at your option) any later version.
17 | *
18 | * This program is distributed in the hope that it will be useful,
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | * GNU General Public License for more details.
22 | */
23 | public abstract class Level {
24 |
25 | private final static Map
26 | * Copyright (C) 2016 tom
27 | *
28 | * This program is free software; you can redistribute it and/or modify
29 | * it under the terms of the GNU General Public License as published by
30 | * the Free Software Foundation; either version 3 of the License, or
31 | * (at your option) any later version.
32 | *
33 | * This program is distributed in the hope that it will be useful,
34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 | * GNU General Public License for more details.
37 | */
38 | public abstract class StdGameActivity extends SubjectBaseActivity {
39 |
40 | // Things here are common to game activities which want ot use the standard layout.
41 |
42 | private final int mProblemView;
43 |
44 | private volatile Timer timer;
45 | private volatile TimerTask hinttask;
46 |
47 | private volatile boolean showHint = false;
48 | private volatile int hintTick;
49 |
50 | private static final int BASE_HINT_TIME = 20000;
51 | private static final int BASE_HINT_REPEAT_TIME = 3000;
52 |
53 | public StdGameActivity(int problemView) {
54 | super(R.layout.std_game_layout);
55 | mProblemView = problemView;
56 | }
57 |
58 | @Override
59 | protected void onCreate(Bundle savedInstanceState) {
60 | super.onCreate(savedInstanceState);
61 | ViewGroup probarea = findViewById(R.id.problem_area);
62 |
63 | LayoutInflater.from(this).inflate(mProblemView, probarea);
64 |
65 | }
66 |
67 | @Override
68 | protected void onPause() {
69 |
70 |
71 | cancelHint();
72 |
73 | if (timer != null) {
74 | timer.cancel();
75 | timer.purge();
76 | timer = null;
77 | }
78 |
79 | super.onPause();
80 | }
81 |
82 | @Override
83 | protected void onResume() {
84 | super.onResume();
85 | timer = new Timer();
86 |
87 |
88 |
89 | }
90 |
91 | @Override
92 | public void onConfigurationChanged(Configuration newConfig) {
93 | super.onConfigurationChanged(newConfig);
94 |
95 | GridLayout answerarea = findViewById(R.id.answer_area);
96 | LinearLayout centercol = findViewById(R.id.centercol);
97 | ActionBar actionBar = getSupportActionBar();
98 | if (isLandscape()) {
99 |
100 | //answerarea.setOrientation(GridLayout.VERTICAL);
101 | setColumnCount(answerarea,2);
102 |
103 | centercol.setOrientation(LinearLayout.HORIZONTAL);
104 |
105 | if (actionBar != null) {
106 | actionBar.hide();
107 | }
108 | } else {
109 | //answerarea.setOrientation(GridLayout.VERTICAL);
110 |
111 |
112 | setColumnCount(answerarea,1);
113 |
114 | centercol.setOrientation(LinearLayout.VERTICAL);
115 |
116 | if (actionBar != null) {
117 | actionBar.show();
118 | }
119 |
120 | }
121 |
122 | }
123 |
124 | private void setColumnCount(GridLayout answerarea, int count) {
125 | List
11 | * Copyright (C) 2016 tom
12 | *
13 | * This program is free software; you can redistribute it and/or modify
14 | * it under the terms of the GNU General Public License as published by
15 | * the Free Software Foundation; either version 3 of the License, or
16 | * (at your option) any later version.
17 | *
18 | * This program is distributed in the hope that it will be useful,
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | * GNU General Public License for more details.
22 | */
23 | public abstract class StdLevel extends Level {
24 | private final InputMode mInputMode;
25 |
26 | protected StdLevel(int subjectkey, int rounds, InputMode mInputMode) {
27 | super(subjectkey, rounds);
28 | this.mInputMode = mInputMode;
29 | }
30 |
31 |
32 | public InputMode getInputMode() {
33 | return mInputMode;
34 | }
35 |
36 | protected String getInputModeString(Context context) {
37 | return getInputMode() == InputMode.Buttons ? context.getString(R.string.disp_buttons) : context.getString(R.string.disp_input);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/base/SubjectMenuActivity.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.base;
2 |
3 | import android.content.DialogInterface;
4 | import android.content.Intent;
5 | import android.content.SharedPreferences;
6 | import android.os.Bundle;
7 | import android.support.v7.app.ActionBar;
8 | import android.support.v7.app.AlertDialog;
9 | import android.view.Gravity;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.Button;
13 | import android.widget.LinearLayout;
14 | import android.widget.TextView;
15 |
16 | import com.quaap.primary.MainActivity;
17 | import com.quaap.primary.R;
18 | import com.quaap.primary.base.data.AppData;
19 | import com.quaap.primary.base.data.Subjects;
20 | import com.quaap.primary.base.data.UserData;
21 |
22 | /**
23 | * Created by tom on 12/15/16.
24 | *
25 | * Copyright (C) 2016 Tom Kliethermes
26 | *
27 | * This program is free software; you can redistribute it and/or modify
28 | * it under the terms of the GNU General Public License as published by
29 | * the Free Software Foundation; either version 3 of the License, or
30 | * (at your option) any later version.
31 | *
32 | * This program is distributed in the hope that it will be useful,
33 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 | * GNU General Public License for more details.
36 | */
37 |
38 | /*
39 | Future Subjects:
40 | Math 1, but typed answers.
41 | Spelling.
42 | Reading/vocabulary.
43 | New big words.
44 | Goofy math word problems.
45 |
46 |
47 | */
48 |
49 | public class SubjectMenuActivity extends CommonBaseActivity implements Button.OnClickListener {
50 |
51 |
52 | private UserData mUserData;
53 | private UserData.Subject mSubjectData;
54 |
55 | private Subjects.Desc mSubject;
56 | private String mSubjectCode;
57 |
58 | private String username;
59 |
60 |
61 | @Override
62 | protected void onCreate(Bundle savedInstanceState) {
63 | super.onCreate(savedInstanceState);
64 |
65 | //Log.d("onCreate", "onCreate savedInstanceState=" + (savedInstanceState==null?"null":"notnull"));
66 | if (savedInstanceState == null) {
67 |
68 | Intent intent = getIntent();
69 | mSubjectCode = intent.getStringExtra(MainActivity.SUBJECTCODE);
70 | username = intent.getStringExtra(MainActivity.USERNAME);
71 |
72 | } else {
73 | mSubjectCode = savedInstanceState.getString("mSubjectCode", mSubjectCode);
74 | username = savedInstanceState.getString("username", username);
75 | }
76 | //Log.d("onCreate", "onCreate username=" + username);
77 |
78 | if (mSubjectCode == null || username == null) {
79 | SharedPreferences state = getSharedPreferences(this.getClass().getName(), MODE_PRIVATE);
80 | mSubjectCode = state.getString("mSubjectCode", mSubjectCode);
81 | username = state.getString("username", username);
82 | }
83 | //Log.d("onCreate", "onCreate username=" + username);
84 | Subjects subjects = Subjects.getInstance(this);
85 | mSubject = subjects.get(mSubjectCode);
86 |
87 | ActionBar actionBar = getSupportActionBar();
88 | if (actionBar != null) {
89 | actionBar.setTitle(getString(R.string.app_name) + ": " + mSubject.getName() + " (" + username + ")");
90 | }
91 |
92 | mUserData = AppData.getAppData(this).getUser(username);
93 | mSubjectData = mUserData.getSubjectForUser(mSubjectCode);
94 | setContentView(R.layout.activity_subject_menu);
95 |
96 |
97 | Button resume_button = findViewById(R.id.resume_button);
98 | resume_button.setTag(-1);
99 | resume_button.setOnClickListener(this);
100 |
101 | Button clear_button = findViewById(R.id.clear_button);
102 | clear_button.setOnClickListener(new View.OnClickListener() {
103 | @Override
104 | public void onClick(View view) {
105 | new AlertDialog.Builder(SubjectMenuActivity.this)
106 | .setIcon(android.R.drawable.ic_dialog_alert)
107 | .setTitle(getString(R.string.clear_progress))
108 | .setMessage(R.string.sure_clear_progress)
109 | .setPositiveButton(R.string.clear, new DialogInterface.OnClickListener() {
110 | @Override
111 | public void onClick(DialogInterface dialog, int which) {
112 | clearProgress();
113 | }
114 |
115 | })
116 | .setNegativeButton(getString(R.string.cancel), null)
117 | .show();
118 |
119 |
120 | }
121 | });
122 | }
123 |
124 | @Override
125 | protected void onSaveInstanceState(Bundle outState) {
126 | //Log.d("subjectmenu", "onSaveInstanceState called! username=" + username);
127 | outState.putString("mSubjectCode", mSubjectCode);
128 | outState.putString("username", username);
129 | super.onSaveInstanceState(outState);
130 |
131 | }
132 |
133 | @Override
134 | protected void onResume() {
135 | super.onResume();
136 | //Log.d("subjectmenu", "onResume called! username=" + username);
137 |
138 | show_hide_gip();
139 | showLevelButtons();
140 |
141 | }
142 |
143 |
144 | @Override
145 | protected void onPause() {
146 | SharedPreferences state = getSharedPreferences(this.getClass().getName(), MODE_PRIVATE);
147 |
148 | state.edit()
149 | .putString("mSubjectCode", mSubjectCode)
150 | .putString("username", username)
151 | .apply();
152 |
153 | super.onPause();
154 | //Log.d("subjectmenu", "onPause called! username=" + username);
155 |
156 | }
157 |
158 |
159 | @Override
160 | public void onBackPressed() {
161 |
162 | super.onBackPressed();
163 | finish();
164 | }
165 |
166 |
167 | private void showLevelButtons() {
168 | int highest = mUserData.getSubjectForUser(mSubjectCode).getHighestLevelNum();
169 |
170 | LinearLayout button_layout = findViewById(R.id.button_layout);
171 |
172 | button_layout.removeAllViews();
173 |
174 | LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
175 | lp.gravity = Gravity.CENTER_VERTICAL;
176 |
177 | for (Level level : mSubject.getLevels()) {
178 |
179 | LinearLayout levelrow = new LinearLayout(this);
180 | levelrow.setOrientation(LinearLayout.HORIZONTAL);
181 | button_layout.addView(levelrow);
182 |
183 | Button levelbutt = new Button(this);
184 | levelbutt.setLayoutParams(lp);
185 | levelbutt.setText(getString(R.string.level, level.getLevelNum()));
186 | levelbutt.setTag(level.getLevelNum() - 1);
187 | levelbutt.setOnClickListener(this);
188 | levelrow.addView(levelbutt);
189 |
190 | TextView desc = new TextView(this);
191 | desc.setText(level.getDescription(this));
192 | desc.setLayoutParams(lp);
193 | desc.setTextSize(16);
194 | levelrow.addView(desc);
195 |
196 | boolean beenthere = level.getLevelNum() - 1 <= highest;
197 | levelbutt.setEnabled(beenthere);
198 | desc.setEnabled(beenthere);
199 | }
200 | }
201 |
202 | private void clearProgress() {
203 | mSubjectData.clearProgress();
204 |
205 | show_hide_gip();
206 | showLevelButtons();
207 | }
208 |
209 | private void show_hide_gip() {
210 | LinearLayout gip_layout = findViewById(R.id.gip_layout);
211 | TextView score_overview = findViewById(R.id.score_overview);
212 | if (mSubjectData.getLevelNum() == -1) {
213 | gip_layout.setVisibility(View.GONE);
214 | score_overview.setText(" ");
215 | } else {
216 | gip_layout.setVisibility(View.VISIBLE);
217 | int correct = mSubjectData.getTotalCorrect();
218 | int incorrect = mSubjectData.getTotalIncorrect();
219 |
220 | int highest = mSubjectData.getHighestLevelNum() + 1;
221 | int levs = mSubject.getLevels().length;
222 | if (highest>levs) {
223 | highest = levs; // in case an upgrade reduces the number of levels in a subject
224 | }
225 |
226 | int tscore = mSubjectData.getTotalPoints();
227 | if (correct + incorrect > 0) {
228 | String score = getString(R.string.score_overview, highest, correct, (correct + incorrect), tscore);
229 | score_overview.setText(score);
230 | }
231 | }
232 | }
233 |
234 |
235 | @Override
236 | public void onClick(View view) {
237 | Intent intent = new Intent(this, mSubject.getActivityclass());
238 | if ((int) view.getTag() != -1) {
239 | intent.putExtra(SubjectBaseActivity.START_AT_ZERO, true);
240 | intent.putExtra(SubjectBaseActivity.LEVELNUM, (int) view.getTag());
241 | }
242 | intent.putExtra(MainActivity.USERNAME, username);
243 | intent.putExtra(MainActivity.SUBJECTCODE, mSubjectCode);
244 | startActivity(intent);
245 | }
246 |
247 |
248 |
249 | }
250 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/base/component/ActivityWriter.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.base.component;
2 |
3 | import android.content.Context;
4 | import android.os.Environment;
5 | import android.util.Log;
6 |
7 | import com.quaap.primary.R;
8 |
9 | import java.io.File;
10 | import java.io.FileWriter;
11 | import java.io.IOException;
12 | import java.text.SimpleDateFormat;
13 | import java.util.Date;
14 | import java.util.Locale;
15 |
16 | /**
17 | * Created by tom on 12/15/16.
18 | *
19 | * Copyright (C) 2016 Tom Kliethermes
20 | *
21 | * This program is free software; you can redistribute it and/or modify
22 | * it under the terms of the GNU General Public License as published by
23 | * the Free Software Foundation; either version 3 of the License, or
24 | * (at your option) any later version.
25 | *
26 | * This program is distributed in the hope that it will be useful,
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 | * GNU General Public License for more details.
30 | */
31 | public class ActivityWriter {
32 |
33 | private final SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
34 |
35 | private final FileWriter mFw;
36 |
37 |
38 | public ActivityWriter(Context context, String username, String subject) throws IOException {
39 |
40 | username = username.replaceAll("\\W", "_");
41 |
42 |
43 | SimpleDateFormat fileFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
44 | String fname = username + " " + subject + " " + fileFormat.format(new Date());
45 | fname = fname.replaceAll("[/\\\\.(){}$*|?<>\\[\\]]", " ");
46 | File f = new File(getAppDocumentsDir(context), fname + ".csv");
47 | boolean newfile = !f.exists();
48 | mFw = new FileWriter(f, true);
49 | if (newfile) {
50 | writeRow(context.getString(R.string.csv_time), context.getString(R.string.csv_level),
51 | context.getString(R.string.csv_problem), context.getString(R.string.csv_answer),
52 | context.getString(R.string.csv_useranswer), context.getString(R.string.csv_correct),
53 | context.getString(R.string.csv_tspent), context.getString(R.string.csv_run_percent),
54 | context.getString(R.string.csv_points));
55 | }
56 | }
57 |
58 | private static String csvEscape(String value) {
59 |
60 | if (value == null) {
61 | return "";
62 | }
63 | if (value.length() == 0) {
64 | return "\"\"";
65 | }
66 | if (value.matches("^-?(\\d+(\\.\\d+)?|\\.\\d+)$")) {
67 | return value;
68 | }
69 | return "\"" + value.replaceAll("\"", "\"\"") + "\"";
70 |
71 | }
72 |
73 | public synchronized void close() throws IOException {
74 | mFw.close();
75 | }
76 |
77 | public boolean isExternalStorageWritable() {
78 | String state = Environment.getExternalStorageState();
79 | return Environment.MEDIA_MOUNTED.equals(state);
80 | }
81 |
82 | public static File getAppDocumentsDir(Context context) {
83 | File file = new File(Environment.getExternalStoragePublicDirectory(
84 | Environment.DIRECTORY_DOCUMENTS), context.getString(R.string.app_name));
85 | if (!file.exists() && !file.mkdirs()) {
86 | Log.e("Primary", "Directory could not be created");
87 | }
88 | return file;
89 | }
90 |
91 | public synchronized void log(int level, String problem, String answer, String useranswer, boolean correct, long millis, float runningpercent, int points) {
92 | writeRow(mDateFormat.format(new Date()), level, problem, answer, useranswer, correct,
93 | millis, String.format(Locale.getDefault(), "%4.1f", runningpercent), points);
94 | }
95 |
96 |
97 | private synchronized void writeRow(Object... items) {
98 | try {
99 | for (int i = 0; i < items.length; i++) {
100 | mFw.write(csvEscape(items[i].toString()));
101 | if (i < items.length - 1) {
102 | mFw.write(",");
103 | }
104 | }
105 | mFw.write("\n");
106 | mFw.flush();
107 | } catch (IOException e) {
108 | Log.e("Primary", "Could not write row.", e);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/base/component/HorzItemList.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.base.component;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Color;
5 | import android.os.Build;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.HorizontalScrollView;
10 | import android.widget.ImageView;
11 | import android.widget.LinearLayout;
12 | import android.widget.TextView;
13 |
14 | import com.quaap.primary.R;
15 |
16 | import java.util.Collection;
17 | import java.util.Collections;
18 | import java.util.HashMap;
19 | import java.util.Map;
20 |
21 | /**
22 | * Created by tom on 12/20/16.
23 | *
24 | * Copyright (C) 2016 tom
25 | *
26 | * This program is free software; you can redistribute it and/or modify
27 | * it under the terms of the GNU General Public License as published by
28 | * the Free Software Foundation; either version 3 of the License, or
29 | * (at your option) any later version.
30 | *
31 | * This program is distributed in the hope that it will be useful,
32 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 | * GNU General Public License for more details.
35 | */
36 | public abstract class HorzItemList {
37 | //This could be a custom view
38 |
39 |
40 | private final int normalColor = Color.argb(64, 200, 200, 200);
41 | private final Activity mParent;
42 | private final int mItemLayoutId;
43 | private final View mHorzList;
44 | private final LinearLayout mItemsListView;
45 | private final Map
6 | * Copyright (C) 2016 Tom Kliethermes
7 | *
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation; either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | */
18 |
19 | public enum InputMode {
20 | None, Buttons, Input
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/base/component/Keyboard.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.base.component;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.graphics.Point;
6 | import android.graphics.Typeface;
7 | import android.os.Build;
8 | import android.util.TypedValue;
9 | import android.view.Display;
10 | import android.view.Gravity;
11 | import android.view.KeyEvent;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.view.WindowManager;
15 | import android.widget.EditText;
16 | import android.widget.LinearLayout;
17 | import android.widget.TextView;
18 |
19 | import com.quaap.primary.R;
20 |
21 | import java.lang.reflect.Method;
22 | import java.util.HashMap;
23 | import java.util.Map;
24 |
25 | /**
26 | * Created by tom on 12/29/16.
27 | *
28 | * Copyright (C) 2016 tom
29 | *
30 | * This program is free software; you can redistribute it and/or modify
31 | * it under the terms of the GNU General Public License as published by
32 | * the Free Software Foundation; either version 3 of the License, or
33 | * (at your option) any later version.
34 | *
35 | * This program is distributed in the hope that it will be useful,
36 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 | * GNU General Public License for more details.
39 | */
40 | public class Keyboard {
41 |
42 |
43 | private static final String KEY_BACKSP = "\u0008";
44 | private static final String KEY_DONE = "\n";
45 | private final Context mContext;
46 |
47 | private final Map
21 | * Copyright (C) 2017 tom
22 | *
23 | * This program is free software; you can redistribute it and/or modify
24 | * it under the terms of the GNU General Public License as published by
25 | * the Free Software Foundation; either version 3 of the License, or
26 | * (at your option) any later version.
27 | *
28 | * This program is distributed in the hope that it will be useful,
29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 | * GNU General Public License for more details.
32 | */
33 | public class SoundEffects {
34 |
35 | private final SoundPool mSounds;
36 |
37 | private final Map
18 | * This program is free software; you can redistribute it and/or modify
19 | * it under the terms of the GNU General Public License as published by
20 | * the Free Software Foundation; either version 3 of the License, or
21 | * (at your option) any later version.
22 | *
23 | * This program is distributed in the hope that it will be useful,
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 | * GNU General Public License for more details.
27 | */
28 | public class TextToVoice implements TextToSpeech.OnInitListener {
29 | private TextToSpeech mTts = null;
30 | private final Context mContext;
31 | private boolean isInit = false;
32 |
33 | private float mPitch = .8f;
34 | private float mSpeed = .6f;
35 | private int utterid = 0;
36 | private VoiceReadyListener mFil;
37 | private boolean fullyInited;
38 |
39 | public TextToVoice(Context context) {
40 | mContext = context;
41 | try {
42 | Log.d("TextToVoice", "started " + System.currentTimeMillis());
43 | mTts = new TextToSpeech(mContext, this);
44 |
45 | setPitch(mPitch);
46 | setSpeed(mSpeed);
47 | mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
48 | @Override
49 | public void onStart(String s) {
50 |
51 | }
52 |
53 | @Override
54 | public void onDone(String s) {
55 | //Log.d("TextToSpeech", "Done!" + System.currentTimeMillis());
56 | if (!fullyInited) {
57 | fullyInited = true;
58 | if (mFil != null) mFil.onVoiceReady(TextToVoice.this);
59 | } else {
60 | if (mFil != null) mFil.onSpeakComplete(TextToVoice.this);
61 | }
62 | }
63 |
64 | @Override
65 | public void onError(String s) {
66 | Log.e("TextToSpeech", "Error with " + s);
67 | if (mFil != null) mFil.onError(TextToVoice.this);
68 | }
69 | });
70 |
71 |
72 | } catch (Exception e) {
73 | e.printStackTrace();
74 | }
75 | }
76 |
77 | @Override
78 | public void onInit(int status) {
79 | if (status == TextToSpeech.SUCCESS) {
80 | int result = mTts.setLanguage(Locale.getDefault());
81 | isInit = true;
82 |
83 | if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
84 |
85 | Log.e("error", "This Language is not supported");
86 | }
87 | Log.d("TextToSpeech", "Initialization Suceeded! " + System.currentTimeMillis());
88 |
89 | speak(mContext.getString(R.string.voice_ready) + ",");
90 | } else {
91 | Log.e("error", "Initialization Failed! " + status);
92 | }
93 | }
94 |
95 | public void shutDown() {
96 | isInit = false;
97 | fullyInited = false;
98 | if (mTts != null) {
99 | mTts.shutdown();
100 | mTts = null;
101 | }
102 | }
103 |
104 | public void speak(String text) {
105 | // Log.d("TextToSpeech", text + " " + System.currentTimeMillis());
106 | if (isInit) {
107 | if (Build.VERSION.SDK_INT >= 21) {
108 | mTts.speak(text, TextToSpeech.QUEUE_ADD, null, "utt" + utterid);
109 | } else {
110 | mTts.speak(text, TextToSpeech.QUEUE_ADD, null);
111 | }
112 | utterid++;
113 | } else {
114 | Log.e("error", "TTS Not Initialized");
115 | }
116 | }
117 |
118 | public void stop() {
119 | if (fullyInited) {
120 | mTts.stop();
121 | }
122 | }
123 |
124 | public float getPitch() {
125 | return mPitch;
126 | }
127 |
128 | private void setPitch(float pitch) {
129 | mPitch = pitch;
130 | mTts.setPitch(pitch);
131 | }
132 |
133 | public float getSpeed() {
134 | return mSpeed;
135 | }
136 |
137 | private void setSpeed(float speed) {
138 | mSpeed = speed;
139 | mTts.setSpeechRate(speed);
140 | }
141 |
142 | public boolean isReady() {
143 | return fullyInited;
144 | }
145 |
146 | public void setVoiceReadyListener(VoiceReadyListener fil) {
147 | mFil = fil;
148 | }
149 |
150 |
151 | public interface VoiceReadyListener {
152 | void onVoiceReady(TextToVoice ttv);
153 |
154 | void onSpeakComplete(TextToVoice ttv);
155 |
156 | void onError(TextToVoice ttv);
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/base/data/AppData.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.base.data;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | import java.util.ArrayList;
7 | import java.util.Collection;
8 | import java.util.Collections;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.Set;
13 | import java.util.TreeSet;
14 |
15 | import static android.content.Context.MODE_PRIVATE;
16 |
17 | /**
18 | * Created by tom on 12/20/16.
19 | *
20 | * Copyright (C) 2016 tom
21 | *
22 | * This program is free software; you can redistribute it and/or modify
23 | * it under the terms of the GNU General Public License as published by
24 | * the Free Software Foundation; either version 3 of the License, or
25 | * (at your option) any later version.
26 | *
27 | * This program is distributed in the hope that it will be useful,
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 | * GNU General Public License for more details.
31 | */
32 | public class AppData {
33 |
34 | private static final String USERS_KEY = "users";
35 | private final SharedPreferences mPrefs;
36 |
37 | private final Context mContext;
38 | private final Map
11 | * Copyright (C) 2017 tom
12 | *
13 | * This program is free software; you can redistribute it and/or modify
14 | * it under the terms of the GNU General Public License as published by
15 | * the Free Software Foundation; either version 3 of the License, or
16 | * (at your option) any later version.
17 | *
18 | * This program is distributed in the hope that it will be useful,
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | * GNU General Public License for more details.
22 | */
23 | public enum SubjectGroup {
24 | Math("M", R.string.group_m, R.color.group_color_m),
25 | LanguageArts("LA", R.string.group_la, R.color.group_color_la),
26 | TimeMoney("TM", R.string.group_tm, R.color.group_color_tm),
27 | Science("Sc", R.string.group_sc, R.color.group_color_sc),
28 | Music("Mu", R.string.group_mu, R.color.group_color_mu),
29 | Art("Ar", R.string.group_ar, R.color.group_color_ar);
30 |
31 |
32 | private final String mCode;
33 | private final int mResId;
34 | private final int mColorResId;
35 |
36 | SubjectGroup(String code, int resId, int colorResId) {
37 | mCode = code;
38 | mResId = resId;
39 | mColorResId = colorResId;
40 | }
41 |
42 | public String getCode() {
43 | return mCode;
44 | }
45 |
46 | public int getColor(Context context) {
47 | if (Build.VERSION.SDK_INT >= 23) {
48 | return context.getColor(mColorResId);
49 | } else {
50 | return context.getResources().getColor(mColorResId);
51 | }
52 | }
53 |
54 | public String getText(Context context) {
55 | return context.getString(mResId);
56 | }
57 |
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/base/data/Subjects.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.base.data;
2 |
3 | import android.content.Context;
4 |
5 | import com.quaap.primary.Levels;
6 | import com.quaap.primary.base.Level;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | /**
14 | * Created by tom on 12/25/16.
15 | *
16 | * Copyright (C) 2016 tom
17 | *
18 | * This program is free software; you can redistribute it and/or modify
19 | * it under the terms of the GNU General Public License as published by
20 | * the Free Software Foundation; either version 3 of the License, or
21 | * (at your option) any later version.
22 | *
23 | * This program is distributed in the hope that it will be useful,
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 | * GNU General Public License for more details.
27 | */
28 |
29 | public class Subjects {
30 |
31 | private static Subjects inst;
32 | private final Desc[] subjects;
33 | private final Map
7 | * Copyright (C) 2016 Tom Kliethermes
8 | *
9 | * This program is free software; you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation; either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * This program is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | */
19 |
20 | import android.annotation.SuppressLint;
21 | import android.os.Bundle;
22 | import android.view.Gravity;
23 | import android.widget.GridLayout;
24 | import android.widget.TextView;
25 |
26 | import com.quaap.primary.R;
27 | import com.quaap.primary.base.StdGameActivity;
28 | import com.quaap.primary.base.SubjectBaseActivity;
29 | import com.quaap.primary.base.component.InputMode;
30 |
31 | import java.util.ArrayList;
32 | import java.util.Collections;
33 | import java.util.List;
34 | import java.util.Locale;
35 |
36 | public class BasicMathActivity extends StdGameActivity implements SubjectBaseActivity.AnswerGivenListener
6 | * Copyright (C) 2016 Tom Kliethermes
7 | *
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation; either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | */
18 | import android.content.Context;
19 |
20 | import com.quaap.primary.R;
21 | import com.quaap.primary.base.StdLevel;
22 | import com.quaap.primary.base.component.InputMode;
23 |
24 | public class BasicMathLevel extends StdLevel {
25 |
26 | private final MathOp mMaxMathOp;
27 | private final MathOp mMinMathOp;
28 | private final int mMaxNum;
29 | private final Negatives mNegatives;
30 | private final boolean mDoubles;
31 |
32 | public BasicMathLevel(int subjectkey, MathOp maxMathOp, int maxNum, int rounds, InputMode inputMode) {
33 | this(subjectkey, maxMathOp, maxMathOp, maxNum, rounds, inputMode);
34 | }
35 |
36 | public BasicMathLevel(int subjectkey, MathOp maxMathOp, MathOp minMathOp, int maxNum, int rounds, InputMode inputMode) {
37 | this(subjectkey, maxMathOp, minMathOp, maxNum, Negatives.None, rounds, inputMode);
38 | }
39 |
40 | public BasicMathLevel(int subjectkey, MathOp maxMathOp, int maxNum, Negatives negatives, int rounds, InputMode inputMode) {
41 | this(subjectkey, maxMathOp, maxMathOp, maxNum, negatives, rounds, inputMode);
42 | }
43 | public BasicMathLevel(int subjectkey, MathOp maxMathOp, MathOp minMathOp, int maxNum, Negatives negatives, int rounds, InputMode inputMode) {
44 | this(subjectkey, maxMathOp, minMathOp, maxNum, negatives, rounds, false, inputMode);
45 | }
46 | public BasicMathLevel(int subjectkey, MathOp maxMathOp, MathOp minMathOp, int maxNum, Negatives negatives, int rounds, boolean doubles, InputMode inputMode) {
47 | super(subjectkey, rounds, inputMode);
48 |
49 | mMaxMathOp = maxMathOp;
50 | mMinMathOp = minMathOp;
51 | mMaxNum = maxNum;
52 | mNegatives = negatives;
53 | mDoubles = doubles;
54 |
55 | }
56 |
57 | @Override
58 | public String getDescription(Context context) {
59 | String ops = getOpsStr(context);
60 | String max = (mNegatives != Negatives.None ? "\u00B1" : "") + mMaxNum;
61 | return ops + " / " +(getDoubles()?context.getString(R.string.doubles):"")+ context.getString(R.string.max, max) + ". " + getInputModeString(context);
62 |
63 | }
64 |
65 | @Override
66 | public String getShortDescription(Context context) {
67 | String ops = getOpsSymStr();
68 | if (mMaxMathOp == mMinMathOp) {
69 | ops = mMaxMathOp.name();
70 | }
71 | String max = (mNegatives != Negatives.None ? "\u00B1" : "") + mMaxNum;
72 | return context.getString(R.string.max, max) + ". " + ops;
73 | }
74 |
75 | private String getOpsStr(Context context) {
76 | String ops = "";
77 | for (MathOp m : MathOp.values()) {
78 | if (m.ordinal() >= mMinMathOp.ordinal() && m.ordinal() <= mMaxMathOp.ordinal()) {
79 | ops += context.getString(m.getResId());
80 | if (m.ordinal() < mMaxMathOp.ordinal()) {
81 | ops += ", ";
82 | }
83 | }
84 | }
85 | return ops;
86 | }
87 |
88 | private String getOpsSymStr() {
89 | String ops = "";
90 | for (MathOp m : MathOp.values()) {
91 | if (m.ordinal() >= mMinMathOp.ordinal() && m.ordinal() <= mMaxMathOp.ordinal()) {
92 | ops += m.toString();
93 | if (m.ordinal() < mMaxMathOp.ordinal()) {
94 | ops += ", ";
95 | }
96 | }
97 | }
98 | return ops;
99 | }
100 |
101 | public MathOp getMaxMathOp() {
102 | return mMaxMathOp;
103 | }
104 |
105 | public MathOp getMinMathOp() {
106 | return mMinMathOp;
107 | }
108 |
109 | public int getMaxNum() {
110 | return mMaxNum;
111 | }
112 |
113 | public Negatives getNegatives() {
114 | return mNegatives;
115 | }
116 |
117 | public boolean getDoubles() {
118 | return mDoubles;
119 | }
120 |
121 |
122 | // public int getMaxNum(int prevCorrect) {
123 | // return (int)(mMaxNum * ((double)Math.max(prevCorrect, mRounds/5.0)/mRounds));
124 | // }
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/math/MathOp.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.math;
2 |
3 | import com.quaap.primary.R;
4 |
5 | import java.security.SecureRandom;
6 |
7 | /**
8 | * Created by tom on 12/14/16.
9 | *
10 | * Copyright (C) 2016 Tom Kliethermes
11 | *
12 | * This program is free software; you can redistribute it and/or modify
13 | * it under the terms of the GNU General Public License as published by
14 | * the Free Software Foundation; either version 3 of the License, or
15 | * (at your option) any later version.
16 | *
17 | * This program is distributed in the hope that it will be useful,
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU General Public License for more details.
21 | */
22 | public enum MathOp {
23 | Plus("+", R.string.plus),
24 | Minus("-", R.string.minus),
25 | Times("\u00D7", R.string.times),
26 | Divide("\u00F7", R.string.divide);
27 |
28 | private static final SecureRandom random = new SecureRandom();
29 | private final String mDisplay;
30 | private final int mResid;
31 |
32 | MathOp(String display, int resid) {
33 | mDisplay = display;
34 | mResid = resid;
35 | }
36 |
37 | public static MathOp random(MathOp upto) {
38 | return randomEnum(MathOp.class, MathOp.Plus, upto);
39 | }
40 |
41 | public static MathOp random(MathOp start, MathOp upto) {
42 | return randomEnum(MathOp.class, start, upto);
43 | }
44 |
45 | private static
6 | * Copyright (C) 2016 Tom Kliethermes
7 | *
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation; either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | */
18 | public enum Negatives {
19 | None, Allowed, Required
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/math/SortingLevel.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.math;
2 |
3 | import android.content.Context;
4 |
5 | import com.quaap.primary.R;
6 | import com.quaap.primary.base.StdLevel;
7 | import com.quaap.primary.base.component.InputMode;
8 |
9 | /**
10 | * Created by tom on 1/1/17.
11 | *
12 | * Copyright (C) 2017 tom
13 | *
14 | * This program is free software; you can redistribute it and/or modify
15 | * it under the terms of the GNU General Public License as published by
16 | * the Free Software Foundation; either version 3 of the License, or
17 | * (at your option) any later version.
18 | *
19 | * This program is distributed in the hope that it will be useful,
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 | * GNU General Public License for more details.
23 | */
24 | public class SortingLevel extends StdLevel {
25 | private final int mNumItems;
26 | private final int mMaxNum;
27 |
28 | public SortingLevel(int subjectkey, int numItems, int maxNum, int rounds) {
29 | super(subjectkey, rounds, InputMode.None);
30 | mNumItems = numItems;
31 | mMaxNum = maxNum;
32 |
33 | }
34 |
35 | public int getNumItems() {
36 | return mNumItems;
37 | }
38 |
39 | public int getMaxNum() {
40 | return mMaxNum;
41 | }
42 |
43 | @Override
44 | public String getDescription(Context context) {
45 | return context.getString(R.string.sort_desc, mNumItems, mMaxNum);
46 | }
47 |
48 | @Override
49 | public String getShortDescription(Context context) {
50 | return context.getString(R.string.sort_sdesc, mNumItems, mMaxNum);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/partsofspeech/plurals/PluralActivity.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.partsofspeech.plurals;
2 |
3 | /**
4 | * Created by tom on 12/15/16.
5 | *
6 | * Copyright (C) 2016 Tom Kliethermes
7 | *
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation; either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | */
18 | import android.os.Bundle;
19 | import android.util.Log;
20 | import android.widget.LinearLayout;
21 | import android.widget.TextView;
22 |
23 | import com.quaap.primary.R;
24 | import com.quaap.primary.base.StdGameActivity;
25 | import com.quaap.primary.base.StdLevel;
26 | import com.quaap.primary.base.SubjectBaseActivity;
27 | import com.quaap.primary.base.component.InputMode;
28 |
29 | import java.util.ArrayList;
30 | import java.util.Arrays;
31 | import java.util.Collections;
32 | import java.util.List;
33 | import java.util.Map;
34 | import java.util.TreeMap;
35 |
36 | public class PluralActivity extends StdGameActivity
37 | implements SubjectBaseActivity.AnswerGivenListener
12 | * Copyright (C) 2016 tom
13 | *
14 | * This program is free software; you can redistribute it and/or modify
15 | * it under the terms of the GNU General Public License as published by
16 | * the Free Software Foundation; either version 3 of the License, or
17 | * (at your option) any later version.
18 | *
19 | * This program is distributed in the hope that it will be useful,
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 | * GNU General Public License for more details.
23 | */
24 | public class PluralLevel extends StdLevel {
25 |
26 | private static final int wDiff = 3;
27 | private final int mMaxwordlength;
28 | private final int mMinwordlength;
29 |
30 | public PluralLevel(int subjectkey, int maxwordlength, int rounds, InputMode inputMode) {
31 | this(subjectkey, maxwordlength > wDiff ? maxwordlength - wDiff : 1, maxwordlength, rounds, inputMode);
32 | }
33 |
34 | private PluralLevel(int subjectkey, int minwordlength, int maxwordlength, int rounds, InputMode inputMode) {
35 | super(subjectkey, rounds, inputMode);
36 |
37 | mMinwordlength = minwordlength;
38 | mMaxwordlength = maxwordlength;
39 |
40 | }
41 |
42 | @Override
43 | public String getDescription(Context context) {
44 | return context.getString(R.string.length, mMaxwordlength) + " " + getInputModeString(context);
45 | }
46 |
47 | @Override
48 | public String getShortDescription(Context context) {
49 | return "Wl: " + mMaxwordlength;
50 | }
51 |
52 | public int getMaxWordLength() {
53 | return mMaxwordlength;
54 | }
55 |
56 | public int getMinWordLength() {
57 | return mMinwordlength;
58 | }
59 |
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/spelling/SpellingActivity.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.spelling;
2 |
3 | /**
4 | * Created by tom on 12/15/16.
5 | *
6 | * Copyright (C) 2016 Tom Kliethermes
7 | *
8 | * This program is free software; you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation; either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | */
18 | import android.os.Bundle;
19 | import android.os.Handler;
20 | import android.util.Log;
21 | import android.view.View;
22 | import android.widget.Button;
23 | import android.widget.LinearLayout;
24 | import android.widget.TextView;
25 |
26 | import com.quaap.primary.Primary;
27 | import com.quaap.primary.R;
28 | import com.quaap.primary.base.StdGameActivity;
29 | import com.quaap.primary.base.SubjectBaseActivity;
30 | import com.quaap.primary.base.component.InputMode;
31 | import com.quaap.primary.base.component.TextToVoice;
32 |
33 | import java.util.ArrayList;
34 | import java.util.Arrays;
35 | import java.util.Collections;
36 | import java.util.List;
37 |
38 | public class SpellingActivity extends StdGameActivity
39 | implements TextToVoice.VoiceReadyListener,
40 | SubjectBaseActivity.AnswerGivenListener
12 | * Copyright (C) 2016 tom
13 | *
14 | * This program is free software; you can redistribute it and/or modify
15 | * it under the terms of the GNU General Public License as published by
16 | * the Free Software Foundation; either version 3 of the License, or
17 | * (at your option) any later version.
18 | *
19 | * This program is distributed in the hope that it will be useful,
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 | * GNU General Public License for more details.
23 | */
24 | public class SpellingLevel extends StdLevel {
25 |
26 | private final int mWordlistId;
27 | private final int mMaxwordlength;
28 |
29 |
30 | public SpellingLevel(int subjectkey, int wordlistid, int maxwordlength, int rounds, InputMode inputMode) {
31 | super(subjectkey, rounds, inputMode);
32 | mWordlistId = wordlistid;
33 | mMaxwordlength = maxwordlength;
34 |
35 | }
36 |
37 |
38 | @Override
39 | public String getDescription(Context context) {
40 | return context.getString(R.string.length, mMaxwordlength) + " " + getInputModeString(context);
41 | }
42 |
43 | @Override
44 | public String getShortDescription(Context context) {
45 | return "Wl: " + mMaxwordlength;
46 | }
47 |
48 | public int getmWordlistId() {
49 | return mWordlistId;
50 | }
51 |
52 | public int getMaxwordlength() {
53 | return mMaxwordlength;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/com/quaap/primary/timemoney/TimeLevel.java:
--------------------------------------------------------------------------------
1 | package com.quaap.primary.timemoney;
2 |
3 | import android.content.Context;
4 |
5 | import com.quaap.primary.R;
6 | import com.quaap.primary.base.StdLevel;
7 | import com.quaap.primary.base.component.InputMode;
8 |
9 | /**
10 | * Created by tom on 1/4/17.
11 | *
12 | * Copyright (C) 2017 tom
13 | *
14 | * This program is free software; you can redistribute it and/or modify
15 | * it under the terms of the GNU General Public License as published by
16 | * the Free Software Foundation; either version 3 of the License, or
17 | * (at your option) any later version.
18 | *
19 | * This program is distributed in the hope that it will be useful,
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 | * GNU General Public License for more details.
23 | */
24 | public class TimeLevel extends StdLevel {
25 |
26 | public enum MinuteGranularity {
27 | Hour(R.string.min_gran_hour),
28 | Half(R.string.min_gran_half),
29 | Quarter(R.string.min_gran_quarter),
30 | Five(R.string.min_gran_five),
31 | One(R.string.min_gran_one);
32 |
33 | private final int mResId;
34 | MinuteGranularity(int resId) {
35 | mResId = resId;
36 | }
37 |
38 | String getString(Context context) {
39 | return context.getString(mResId);
40 | }
41 | }
42 | //public enum SecondGranularity {Minute, Half, Quarter, Five, One}
43 |
44 | private final MinuteGranularity mMinuteGranularity;
45 |
46 | private final boolean mFuzzy;
47 | public TimeLevel(int subjectkey, MinuteGranularity minGran, int rounds, InputMode inputMode) {
48 | this(subjectkey, minGran, rounds, inputMode, false);
49 | }
50 | public TimeLevel(int subjectkey, MinuteGranularity minGran, int rounds, InputMode inputMode, boolean useFuzzy) {
51 | super(subjectkey, rounds, inputMode);
52 | mMinuteGranularity = minGran;
53 | mFuzzy = useFuzzy;
54 | }
55 |
56 | public boolean useFuzzy() {
57 | return mFuzzy;
58 | }
59 |
60 | public MinuteGranularity getMinuteGranularity() {
61 | return mMinuteGranularity;
62 | }
63 |
64 | @Override
65 | public String getDescription(Context context) {
66 | return mMinuteGranularity.getString(context) + ". " + getInputModeString(context);
67 | }
68 |
69 | @Override
70 | public String getShortDescription(Context context) {
71 | return mMinuteGranularity.toString();
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/primary_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quaap/Primary/95bdb1d12df5599d7b833db36365e5f21be24336/app/src/main/primary_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_about.xml:
--------------------------------------------------------------------------------
1 |
2 | Report any issues, feedback, or suggestions here. This program was written by Tom Kliethermes