diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/activities/MainActivity.java b/app/src/main/java/com/luca0n/joguitos/pluck/activities/MainActivity.java index a29015a..3cb9f2e 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/activities/MainActivity.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/activities/MainActivity.java @@ -23,68 +23,177 @@ Contact us at . package com.luca0n.joguitos.pluck.activities; +import android.app.Activity; import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Build; import android.os.Bundle; +import android.preference.PreferenceManager; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; +import androidx.appcompat.app.AlertDialog; import butterknife.BindView; import butterknife.ButterKnife; + import com.luca0n.joguitos.pluck.R; +import com.luca0n.joguitos.pluck.trivia.TriviaSource; import com.luca0n.joguitos.pluck.trivia.TriviaCategory; import com.luca0n.joguitos.pluck.trivia.TriviaDifficulty; import com.luca0n.joguitos.pluck.trivia.TriviaQuery; +import com.luca0n.joguitos.pluck.trivia.TriviaFilters; public class MainActivity extends BaseActivity { - @BindView(R.id.button_play) - Button buttonPlay; - @BindView(R.id.spinner_number) - Spinner spinnerNumber; - @BindView(R.id.spinner_category) - Spinner spinnerCategory; - @BindView(R.id.spinner_difficulty) - Spinner spinnerDifficulty; + @BindView(R.id.button_play) + Button buttonPlay; + @BindView(R.id.spinner_source) + Spinner spinnerSource; + @BindView(R.id.spinner_number) + Spinner spinnerNumber; + @BindView(R.id.spinner_category) + Spinner spinnerCategory; + @BindView(R.id.spinner_difficulty) + Spinner spinnerDifficulty; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - ButterKnife.bind(this); + private static final int REQUEST_OPEN_DOCUMENT = 0; - buttonPlay.setOnClickListener(v -> { - int amount = (int) spinnerNumber.getSelectedItem(); - TriviaCategory category = (TriviaCategory) spinnerCategory.getSelectedItem(); - TriviaDifficulty difficulty = (TriviaDifficulty) spinnerDifficulty.getSelectedItem(); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + ButterKnife.bind(this); - TriviaQuery query = new TriviaQuery.Builder(amount) - .category(category) - .difficulty(difficulty) - .build(); + buttonPlay.setOnClickListener(v -> { + int sourcePos = spinnerSource.getSelectedItemPosition(); + if (TriviaSource.values()[sourcePos] == TriviaSource.FILE){ + // Check the Android version. + if (Build.VERSION.SDK_INT >= 19){ + // TODO: Show the open document dialog and read the trivia file. + Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT); + i.setType("*/*"); + startActivityForResult(i, REQUEST_OPEN_DOCUMENT); + return; + } else { + // Unsupported version. + new AlertDialog.Builder(this) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.error) + .setMessage(R.string.error_source_file_android_version_unsupported) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + return; + } + String amount = (String) spinnerNumber.getSelectedItem(); + TriviaCategory category = (TriviaCategory) spinnerCategory.getSelectedItem(); + TriviaDifficulty difficulty = (TriviaDifficulty) spinnerDifficulty.getSelectedItem(); - Intent intent = new Intent(getApplicationContext(), TriviaGameActivity.class); - intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_QUERY, query); - startActivity(intent); - }); + if (amount.equals(getString(R.string.ui_all))){ + // The "All" option is only used for trivia files. + new AlertDialog.Builder(this) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.error) + .setMessage(R.string.error_option_all_unavailable) + .setPositiveButton(android.R.string.ok, null) + .show(); + return; + } + // Put the server address in the TriviaQuery object. + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + String serverKey = getResources().getString(R.string.pref_network_server); + // Load default server URL in case the player did not specify a custom server URL. + String defaultServer = getResources().getString(R.string.pref_network_server_default); + String base = sp.getString(serverKey, defaultServer) + "?"; // append "?" to the end of the URL so we can specify GET parameters. - Integer[] numbers = new Integer[50]; - for (int i = 0; i < 50; ) { - numbers[i] = ++i; - } - spinnerNumber.setAdapter( - new ArrayAdapter<>( - this, android.R.layout.simple_list_item_1, numbers) - ); - spinnerNumber.setSelection(9); + // Check if the custom server URL preference was empty. If it was, change it to the default URL. + if (base.equals("?")){ + base = defaultServer + "?"; + sp.edit().putString(serverKey, defaultServer).commit(); + } - spinnerCategory.setAdapter( - new ArrayAdapter<>( - this, android.R.layout.simple_list_item_1, TriviaCategory.values())); + TriviaQuery query = new TriviaQuery.Builder(Integer.valueOf(amount)) + .category(category) + .difficulty(difficulty) + .base(base) + .build(); - spinnerDifficulty.setAdapter( - new ArrayAdapter<>( - this, android.R.layout.simple_list_item_1, TriviaDifficulty.values())); - } + // Launch the trivia game activity. + Intent intent = new Intent(getApplicationContext(), TriviaGameActivity.class); + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_SOURCE, TriviaSource.SERVER.getName()); // Specify the trivia source. + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_QUERY, query); + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_FILTERS, + new TriviaFilters.Builder(Integer.valueOf(amount)) + .category(category) + .difficulty(difficulty) + .build()); + startActivity(intent); + }); + + // Create a String array that holds all options for spinnerNumber. + String[] numbers = new String[51]; + for (int i = 0; i < 51; i++) { + // The first entry on the spinner should be the value "All", which is used with the + // file trivia source. + numbers[i] = i == 0 ? getString(R.string.ui_all) : String.valueOf(i); + } + spinnerSource.setAdapter( + new ArrayAdapter<>( + this, android.R.layout.simple_list_item_1, TriviaSource.values()) + ); + spinnerNumber.setAdapter( + new ArrayAdapter<>( + this, android.R.layout.simple_list_item_1, numbers) + ); + spinnerNumber.setSelection(10); + + spinnerCategory.setAdapter( + new ArrayAdapter<>( + this, android.R.layout.simple_list_item_1, TriviaCategory.values())); + + spinnerDifficulty.setAdapter( + new ArrayAdapter<>( + this, android.R.layout.simple_list_item_1, TriviaDifficulty.values())); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent extras){ + switch (requestCode){ + case REQUEST_OPEN_DOCUMENT: + // Was the request executed successfully? + if (resultCode == Activity.RESULT_OK){ + // Check if the user canceled the operation. + if (extras == null) + break; + + String amount = (String) spinnerNumber.getSelectedItem(); + TriviaCategory category = (TriviaCategory) spinnerCategory.getSelectedItem(); + TriviaDifficulty difficulty = (TriviaDifficulty) spinnerDifficulty.getSelectedItem(); + + Intent intent = new Intent(getApplicationContext(), TriviaGameActivity.class); + // Put filters on the extras object. + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_FILTERS, + new TriviaFilters.Builder(amount.equals(getString(R.string.ui_all)) ? -1 : Integer.valueOf(amount)) + .category(category) + .difficulty(difficulty) + .build()); + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_SOURCE, TriviaSource.FILE.getName()); // Specify the trivia source. + intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_SOURCE_DATA, extras.getData()); // Specify the trivia source data. In this case, since the user chose the "File" source option, we should put the file Uri object here. + startActivity(intent); + } else { + new AlertDialog.Builder(this) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.error) + .setMessage(R.string.error_trivia_file_fetch_unknown) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + break; + default: + super.onActivityResult(requestCode, resultCode, extras); + break; + } + } } diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/activities/TriviaGameActivity.java b/app/src/main/java/com/luca0n/joguitos/pluck/activities/TriviaGameActivity.java index cece721..7349b44 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/activities/TriviaGameActivity.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/activities/TriviaGameActivity.java @@ -23,7 +23,6 @@ Contact us at . package com.luca0n.joguitos.pluck.activities; -import android.app.AlertDialog; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.PorterDuff; @@ -32,6 +31,7 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.net.Uri; import android.view.View; import android.view.MenuItem; import android.widget.Button; @@ -40,30 +40,43 @@ import android.widget.ProgressBar; import android.widget.TextView; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.io.Reader; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.io.BufferedReader; import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; import butterknife.BindView; import butterknife.ButterKnife; import com.luca0n.joguitos.pluck.R; import com.luca0n.joguitos.pluck.exceptions.NoTriviaResultsException; -import com.luca0n.joguitos.pluck.exceptions.InvalidServerResponseException; +import com.luca0n.joguitos.pluck.exceptions.InvalidTriviaFormatException; import com.luca0n.joguitos.pluck.fragments.TriviaGameErrorFragment; import com.luca0n.joguitos.pluck.fragments.TriviaQuestionFragment; import com.luca0n.joguitos.pluck.interfaces.IDownloadTriviaQuestionReceiver; import com.luca0n.joguitos.pluck.trivia.TriviaGame; import com.luca0n.joguitos.pluck.trivia.TriviaQuery; import com.luca0n.joguitos.pluck.trivia.TriviaQuestion; +import com.luca0n.joguitos.pluck.trivia.TriviaSource; +import com.luca0n.joguitos.pluck.trivia.TriviaFilters; import com.luca0n.joguitos.pluck.util.ApiUtil; import com.luca0n.joguitos.pluck.util.SoundUtil; public class TriviaGameActivity extends BaseActivity implements IDownloadTriviaQuestionReceiver { static final String EXTRA_TRIVIA_QUERY = "extra_trivia_query"; + static final String EXTRA_TRIVIA_SOURCE = "extra_trivia_source"; + static final String EXTRA_TRIVIA_SOURCE_DATA = "extra_trivia_source_data"; + static final String EXTRA_TRIVIA_FILTERS = "extra_trivia_filters"; private final String STATE_TRIVIA_GAME = "state_trivia_game"; private TriviaGame game; + private TriviaSource source; + private TriviaFilters filters; @BindView(R.id.progress_bar) ProgressBar progressBar; @@ -92,12 +105,40 @@ public class TriviaGameActivity extends BaseActivity Bundle bundle = getIntent().getExtras(); assert bundle != null; TriviaQuery query = (TriviaQuery) bundle.get(EXTRA_TRIVIA_QUERY); + + filters = (TriviaFilters) bundle.get(EXTRA_TRIVIA_FILTERS); progressBar.setVisibility(View.VISIBLE); - DownloadTriviaQuestionsTask task = new DownloadTriviaQuestionsTask(); - task.setReceiver(this); - task.execute(query); + // Gather information about the trivia location. + String sourceData; + source = TriviaSource.get(bundle.getString(EXTRA_TRIVIA_SOURCE)); + switch (source){ + case SERVER: + DownloadTriviaQuestionsTask task = new DownloadTriviaQuestionsTask(); + task.setReceiver(this); + task.execute(query); + break; + case FILE: + // Attempt to open the trivia file specified by the player. + // Read the file as a plain text JSON trivia file. + StringBuilder sb = new StringBuilder(); + try { + InputStream is = getContentResolver().openInputStream((Uri) bundle.get(EXTRA_TRIVIA_SOURCE_DATA)); + Reader in = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + for (int c; (c = in.read()) >= 0;) + sb.append((char) c); + } catch (IOException e){ + onException(e); + return; + } + onTriviaQuestionsDownloaded(sb.toString()); + break; + default: + // Unknown trivia source. + // TODO: Show error message to the user about this internal error. + break; + } } } @@ -142,9 +183,8 @@ public class TriviaGameActivity extends BaseActivity return; } else { try { - this.game = new TriviaGame(ApiUtil.jsonToQuestionArray(json)); + this.game = new TriviaGame(ApiUtil.jsonToQuestionArray(json, filters)); } catch (Exception e) { - //onNoTriviaResults(); onException(e); return; } @@ -200,12 +240,23 @@ public class TriviaGameActivity extends BaseActivity // Hide the progress bar. progressBar.setVisibility(View.GONE); String msg; + int id; if (e instanceof NoTriviaResultsException) - msg = getResources().getString(R.string.error_no_trivia_results); - else if (e instanceof InvalidServerResponseException) - msg = getResources().getString(R.string.error_server_response_invalid); - else - msg = getResources().getString(R.string.error_unknown); + id = R.string.error_no_trivia_results; + else if (e instanceof InvalidTriviaFormatException) + // Check the trivia source type. + if (source == TriviaSource.SERVER) + id = R.string.error_server_response_invalid; + else + id = R.string.error_trivia_file_invalid; + else + id = R.string.error_unknown; + + new AlertDialog.Builder(this) + .setMessage(e.toString()) + .show(); + + msg = getResources().getString(id); Fragment errorFragment = TriviaGameErrorFragment.newInstance(msg); diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/exceptions/InvalidTriviaFormatException.java b/app/src/main/java/com/luca0n/joguitos/pluck/exceptions/InvalidTriviaFormatException.java new file mode 100644 index 0000000..3832b49 --- /dev/null +++ b/app/src/main/java/com/luca0n/joguitos/pluck/exceptions/InvalidTriviaFormatException.java @@ -0,0 +1,35 @@ +/* +Pluck: an open source trivia game for Android + +Copyright (C) 2021 Joguitos do luca0N! + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . + +This game is a fork of LibreTrivia, and its source code is available at +. + +Contact us at . +*/ + +package com.luca0n.joguitos.pluck.exceptions; + +import java.lang.Throwable; + +public class InvalidTriviaFormatException extends Exception { + public InvalidTriviaFormatException(){ + super(); + } + public InvalidTriviaFormatException(Throwable cause){ + super(cause); + } +} diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaCategory.java b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaCategory.java index c1b2ce3..6e55097 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaCategory.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaCategory.java @@ -110,7 +110,7 @@ public enum TriviaCategory { return this.ID; } - private String getName() { + public String getName() { return this.name; } diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaFilters.java b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaFilters.java new file mode 100644 index 0000000..9e817df --- /dev/null +++ b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaFilters.java @@ -0,0 +1,128 @@ +/* +Pluck: an open source trivia game for Android + +Copyright (C) 2021 Joguitos do luca0N! + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . + +This game is a fork of LibreTrivia, and its source code is available at +. + +Contact us at . +*/ + +package com.luca0n.joguitos.pluck.trivia; + +import java.io.Serializable; + +public class TriviaFilters implements Serializable { + private static final int DEFAULT_AMOUNT = 10; + + private final int amount; + private final TriviaCategory category; + private final TriviaDifficulty difficulty; + private final TriviaType type; + + private TriviaFilters(Builder builder) { + this.amount = builder.amount; + this.category = builder.category; + this.difficulty = builder.difficulty; + this.type = builder.type; + } + + /** + * @return The desired amount of questions selected by the player. + * @since 2021-03-16 + */ + public int getAmount(){ + return amount; + } + /** + * @return The category selected by the player. + * @since 2021-03-16 + */ + public TriviaCategory getCategory(){ + return category; + } + /** + * @return The difficulty selected by the player. + * @since 2021-03-16 + */ + public TriviaDifficulty getDifficulty(){ + return difficulty; + } + /** + * @return The type selected by the player. + * @since 2021-03-16 + */ + public TriviaType getType(){ + return type; + } + + public static class Builder { + private final int amount; + private TriviaCategory category; + private TriviaDifficulty difficulty; + private TriviaType type; + + public Builder() { + this.amount = DEFAULT_AMOUNT; + } + + public Builder(int amount) { + if (amount > 50) { + this.amount = 50; + } else { + this.amount = amount; + } + } + + public Builder category(TriviaCategory category) { + this.category = category; + return this; + } + + public Builder difficulty(TriviaDifficulty difficulty) { + this.difficulty = difficulty; + return this; + } + + public Builder type(TriviaType type) { + this.type = type; + return this; + } + + public TriviaFilters build() { + return new TriviaFilters(this); + } + } + + @Override + public String toString() { + StringBuilder url = new StringBuilder(); + + url.append("amount=").append(this.amount); + + if (this.category != null & this.category != TriviaCategory.ANY) { + url.append("&category=").append(this.category.getID()); + } + if (this.difficulty != null & this.difficulty != TriviaDifficulty.ANY) { + url.append("&difficulty=").append(this.difficulty.getName()); + } + if (this.type != null & this.type != TriviaType.ANY) { + url.append("&type=").append(this.type.getName()); + } + + return url.toString(); + } +} diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaQuery.java b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaQuery.java index f9a0767..8e16fb9 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaQuery.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaQuery.java @@ -23,15 +23,8 @@ Contact us at . package com.luca0n.joguitos.pluck.trivia; -import com.luca0n.joguitos.pluck.PluckApplication; -import com.luca0n.joguitos.pluck.R; - import java.io.Serializable; -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - public class TriviaQuery implements Serializable { private static final int DEFAULT_AMOUNT = 10; @@ -39,12 +32,14 @@ public class TriviaQuery implements Serializable { private final TriviaCategory category; private final TriviaDifficulty difficulty; private final TriviaType type; + private final String base; private TriviaQuery(Builder builder) { this.amount = builder.amount; this.category = builder.category; this.difficulty = builder.difficulty; this.type = builder.type; + this.base = builder.base; } public static class Builder { @@ -52,6 +47,7 @@ public class TriviaQuery implements Serializable { private TriviaCategory category; private TriviaDifficulty difficulty; private TriviaType type; + private String base; public Builder() { this.amount = DEFAULT_AMOUNT; @@ -80,6 +76,11 @@ public class TriviaQuery implements Serializable { return this; } + public Builder base(String base){ + this.base = base; + return this; + } + public TriviaQuery build() { return new TriviaQuery(this); } @@ -89,20 +90,6 @@ public class TriviaQuery implements Serializable { public String toString() { StringBuilder url = new StringBuilder(); - // Load custom server URL. - Context c = PluckApplication.getAppContext(); - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(c); - String serverKey = c.getResources().getString(R.string.pref_network_server); - // Load default server URL in case the player did not specify a custom server URL. - String defaultServer = c.getResources().getString(R.string.pref_network_server_default); - String base = sp.getString(serverKey, defaultServer) + "?"; // append "?" to the end of the URL so we can specify GET parameters. - - // Check if the custom server URL preference was empty. If it was, change it to the default URL. - if (base.equals("?")){ - base = defaultServer + "?"; - sp.edit().putString(serverKey, defaultServer).commit(); - } - url.append(base); url.append("amount=").append(this.amount); diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaSource.java b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaSource.java new file mode 100644 index 0000000..7a09cbb --- /dev/null +++ b/app/src/main/java/com/luca0n/joguitos/pluck/trivia/TriviaSource.java @@ -0,0 +1,66 @@ +/* +Pluck: an open source trivia game for Android + +Copyright (C) 2021 Joguitos do luca0N! + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . + +This game is a fork of LibreTrivia, and its source code is available at +. + +Contact us at . +*/ + +package com.luca0n.joguitos.pluck.trivia; + +import java.util.HashMap; +import java.util.Map; + +import com.luca0n.joguitos.pluck.PluckApplication; +import com.luca0n.joguitos.pluck.R; + +public enum TriviaSource { + SERVER("server", R.string.source_server), + FILE("file", R.string.source_file); + + // Name of source + private final String name; + // Display name of the source + private final int displayName; + + private static final Map lookup = new HashMap<>(); + + static { + for (TriviaSource source : TriviaSource.values()) { + lookup.put(source.getName(), source); + } + } + + TriviaSource(String name, int displayName) { + this.name = name; + this.displayName = displayName; + } + + public String getName() { + return this.name; + } + + public static TriviaSource get(String name) { + return lookup.get(name); + } + + @Override + public String toString() { + return PluckApplication.getAppContext().getResources().getString(this.displayName); + } +} diff --git a/app/src/main/java/com/luca0n/joguitos/pluck/util/ApiUtil.java b/app/src/main/java/com/luca0n/joguitos/pluck/util/ApiUtil.java index 5a77fb5..997865f 100644 --- a/app/src/main/java/com/luca0n/joguitos/pluck/util/ApiUtil.java +++ b/app/src/main/java/com/luca0n/joguitos/pluck/util/ApiUtil.java @@ -43,16 +43,20 @@ import java.net.Proxy; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; +import java.util.Collections; import com.luca0n.joguitos.pluck.R; import com.luca0n.joguitos.pluck.PluckApplication; import com.luca0n.joguitos.pluck.exceptions.NoTriviaResultsException; -import com.luca0n.joguitos.pluck.exceptions.InvalidServerResponseException; +import com.luca0n.joguitos.pluck.exceptions.InvalidTriviaFormatException; import com.luca0n.joguitos.pluck.trivia.TriviaQuery; import com.luca0n.joguitos.pluck.trivia.TriviaQuestion; +import com.luca0n.joguitos.pluck.trivia.TriviaCategory; +import com.luca0n.joguitos.pluck.trivia.TriviaDifficulty; import com.luca0n.joguitos.pluck.trivia.TriviaQuestionBoolean; import com.luca0n.joguitos.pluck.trivia.TriviaQuestionMultiple; import com.luca0n.joguitos.pluck.trivia.TriviaType; +import com.luca0n.joguitos.pluck.trivia.TriviaFilters; public class ApiUtil { @@ -100,18 +104,20 @@ public class ApiUtil { return response; } - public static String GET(TriviaQuery query) throws IOException { + public static String GET(TriviaQuery query) + throws IOException { return GET(query.toString()); } - public static ArrayList jsonToQuestionArray(String json) - throws NoTriviaResultsException, InvalidServerResponseException { + public static ArrayList jsonToQuestionArray(String json, + TriviaFilters filters) throws NoTriviaResultsException, + InvalidTriviaFormatException { JsonObject jsonObject; try{ jsonObject = new JsonParser().parse(json).getAsJsonObject(); } catch (JsonSyntaxException e){ // Unknown server response. - throw new InvalidServerResponseException(); + throw new InvalidTriviaFormatException(e); } if (jsonObject.get("response_code").getAsInt() == 1) { @@ -122,10 +128,25 @@ public class ApiUtil { ArrayList questions = new ArrayList<>(); + int elements = 0; + for (JsonElement element : jsonArray) { + int amount = filters.getAmount(); + if (amount > 0 && elements++ == amount) + break; JsonObject object = element.getAsJsonObject(); TriviaType type = TriviaType.get(object.get("type").getAsString()); + TriviaCategory fc = filters.getCategory(); + + // Check if this question matches the user specified criteria. + if (fc != null && + fc != TriviaCategory.ANY && !object.get("category").getAsString().equals(fc.getName())) + continue; + + if (filters.getDifficulty() != TriviaDifficulty.ANY && !object.get("difficulty").getAsString().equals(filters.getDifficulty().getName())) + continue; + if (type == TriviaType.MULTIPLE) { questions.add(TriviaQuestionMultiple.fromJson(object)); } else { @@ -133,6 +154,13 @@ public class ApiUtil { } } + // Check if there are no questions that match the specified user criteria. + if (questions.size() == 0) + throw new NoTriviaResultsException(); + + // Shuffle the question array. + Collections.shuffle(questions); + return questions; } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9870330..a4d4044 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -44,6 +44,16 @@ Contact us at . app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent"> + + + + + . Multiple Choice True / False + + Server + File + Settings About Play Start Game - Any + Any + All True False Correct @@ -80,13 +85,20 @@ Contact us at . Correct Answers Wrong Answers Total Questions - Return To Menu + Return To Menu + Source + This value specifies where the game should retrieve trivia data. By default, the game gathers trivia data from a server, but you can load trivia files with the "File" source option. - + + Error Network error!\n\nCould not connect to a network. Check if your custom server address is correct. If Tor is enabled in the game settings, check if Orbot is running and then try again. No trivia results!\n\nWas not able to find trivia questions that satisfied all options. Server response error!\n\nCould not parse the server response. The server response may be in a unsupported version. If you are using a custom server, make sure the server address points to a valid address and then try again. An unknown error occurred! + Trivia files are not supported in this version of Android. + Invalid trivia file!\n\nTrivia files should be in a plain text JSON format. + An unknown error occurred while attempting to read the opened file. + The selected question amount is only available for the "File" trivia game source. Settings @@ -98,6 +110,6 @@ Contact us at . Network Connect Using Tor Retrieves trivia data via the Tor network. Requires Orbot (recommended) or a Tor daemon with a SOCKS5 proxy listening on port 9050. - Server address - Specifies the server location used by the game to fetch questions. Leave empty to use the default server. + Server Address + Specifies the server location used by the game to fetch questions when using a server as the trivia source. Leave this setting empty to use the default server.