Merge pull request 'Add trivia file source support' (#13) from dev into master
Reviewed-on: https://git.luca0N.com/luca0N/Pluck/pulls/13
This commit is contained in:
commit
fe468ecfd2
|
@ -23,68 +23,177 @@ Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
|
|
||||||
package com.luca0n.joguitos.pluck.activities;
|
package com.luca0n.joguitos.pluck.activities;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
import com.luca0n.joguitos.pluck.R;
|
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.TriviaCategory;
|
||||||
import com.luca0n.joguitos.pluck.trivia.TriviaDifficulty;
|
import com.luca0n.joguitos.pluck.trivia.TriviaDifficulty;
|
||||||
import com.luca0n.joguitos.pluck.trivia.TriviaQuery;
|
import com.luca0n.joguitos.pluck.trivia.TriviaQuery;
|
||||||
|
import com.luca0n.joguitos.pluck.trivia.TriviaFilters;
|
||||||
|
|
||||||
public class MainActivity extends BaseActivity {
|
public class MainActivity extends BaseActivity {
|
||||||
|
|
||||||
@BindView(R.id.button_play)
|
@BindView(R.id.button_play)
|
||||||
Button buttonPlay;
|
Button buttonPlay;
|
||||||
@BindView(R.id.spinner_number)
|
@BindView(R.id.spinner_source)
|
||||||
Spinner spinnerNumber;
|
Spinner spinnerSource;
|
||||||
@BindView(R.id.spinner_category)
|
@BindView(R.id.spinner_number)
|
||||||
Spinner spinnerCategory;
|
Spinner spinnerNumber;
|
||||||
@BindView(R.id.spinner_difficulty)
|
@BindView(R.id.spinner_category)
|
||||||
Spinner spinnerDifficulty;
|
Spinner spinnerCategory;
|
||||||
|
@BindView(R.id.spinner_difficulty)
|
||||||
|
Spinner spinnerDifficulty;
|
||||||
|
|
||||||
@Override
|
private static final int REQUEST_OPEN_DOCUMENT = 0;
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_main);
|
|
||||||
ButterKnife.bind(this);
|
|
||||||
|
|
||||||
buttonPlay.setOnClickListener(v -> {
|
@Override
|
||||||
int amount = (int) spinnerNumber.getSelectedItem();
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
TriviaCategory category = (TriviaCategory) spinnerCategory.getSelectedItem();
|
super.onCreate(savedInstanceState);
|
||||||
TriviaDifficulty difficulty = (TriviaDifficulty) spinnerDifficulty.getSelectedItem();
|
setContentView(R.layout.activity_main);
|
||||||
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
TriviaQuery query = new TriviaQuery.Builder(amount)
|
buttonPlay.setOnClickListener(v -> {
|
||||||
.category(category)
|
int sourcePos = spinnerSource.getSelectedItemPosition();
|
||||||
.difficulty(difficulty)
|
if (TriviaSource.values()[sourcePos] == TriviaSource.FILE){
|
||||||
.build();
|
// 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);
|
if (amount.equals(getString(R.string.ui_all))){
|
||||||
intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_QUERY, query);
|
// The "All" option is only used for trivia files.
|
||||||
startActivity(intent);
|
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];
|
// Check if the custom server URL preference was empty. If it was, change it to the default URL.
|
||||||
for (int i = 0; i < 50; ) {
|
if (base.equals("?")){
|
||||||
numbers[i] = ++i;
|
base = defaultServer + "?";
|
||||||
}
|
sp.edit().putString(serverKey, defaultServer).commit();
|
||||||
spinnerNumber.setAdapter(
|
}
|
||||||
new ArrayAdapter<>(
|
|
||||||
this, android.R.layout.simple_list_item_1, numbers)
|
|
||||||
);
|
|
||||||
spinnerNumber.setSelection(9);
|
|
||||||
|
|
||||||
spinnerCategory.setAdapter(
|
TriviaQuery query = new TriviaQuery.Builder(Integer.valueOf(amount))
|
||||||
new ArrayAdapter<>(
|
.category(category)
|
||||||
this, android.R.layout.simple_list_item_1, TriviaCategory.values()));
|
.difficulty(difficulty)
|
||||||
|
.base(base)
|
||||||
|
.build();
|
||||||
|
|
||||||
spinnerDifficulty.setAdapter(
|
// Launch the trivia game activity.
|
||||||
new ArrayAdapter<>(
|
Intent intent = new Intent(getApplicationContext(), TriviaGameActivity.class);
|
||||||
this, android.R.layout.simple_list_item_1, TriviaDifficulty.values()));
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
|
|
||||||
package com.luca0n.joguitos.pluck.activities;
|
package com.luca0n.joguitos.pluck.activities;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
|
@ -32,6 +31,7 @@ import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.net.Uri;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
@ -40,30 +40,43 @@ import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.ActionBar;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import com.luca0n.joguitos.pluck.R;
|
import com.luca0n.joguitos.pluck.R;
|
||||||
import com.luca0n.joguitos.pluck.exceptions.NoTriviaResultsException;
|
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.TriviaGameErrorFragment;
|
||||||
import com.luca0n.joguitos.pluck.fragments.TriviaQuestionFragment;
|
import com.luca0n.joguitos.pluck.fragments.TriviaQuestionFragment;
|
||||||
import com.luca0n.joguitos.pluck.interfaces.IDownloadTriviaQuestionReceiver;
|
import com.luca0n.joguitos.pluck.interfaces.IDownloadTriviaQuestionReceiver;
|
||||||
import com.luca0n.joguitos.pluck.trivia.TriviaGame;
|
import com.luca0n.joguitos.pluck.trivia.TriviaGame;
|
||||||
import com.luca0n.joguitos.pluck.trivia.TriviaQuery;
|
import com.luca0n.joguitos.pluck.trivia.TriviaQuery;
|
||||||
import com.luca0n.joguitos.pluck.trivia.TriviaQuestion;
|
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.ApiUtil;
|
||||||
import com.luca0n.joguitos.pluck.util.SoundUtil;
|
import com.luca0n.joguitos.pluck.util.SoundUtil;
|
||||||
|
|
||||||
public class TriviaGameActivity extends BaseActivity
|
public class TriviaGameActivity extends BaseActivity
|
||||||
implements IDownloadTriviaQuestionReceiver {
|
implements IDownloadTriviaQuestionReceiver {
|
||||||
static final String EXTRA_TRIVIA_QUERY = "extra_trivia_query";
|
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 final String STATE_TRIVIA_GAME = "state_trivia_game";
|
||||||
|
|
||||||
private TriviaGame game;
|
private TriviaGame game;
|
||||||
|
private TriviaSource source;
|
||||||
|
private TriviaFilters filters;
|
||||||
|
|
||||||
@BindView(R.id.progress_bar)
|
@BindView(R.id.progress_bar)
|
||||||
ProgressBar progressBar;
|
ProgressBar progressBar;
|
||||||
|
@ -92,12 +105,40 @@ public class TriviaGameActivity extends BaseActivity
|
||||||
Bundle bundle = getIntent().getExtras();
|
Bundle bundle = getIntent().getExtras();
|
||||||
assert bundle != null;
|
assert bundle != null;
|
||||||
TriviaQuery query = (TriviaQuery) bundle.get(EXTRA_TRIVIA_QUERY);
|
TriviaQuery query = (TriviaQuery) bundle.get(EXTRA_TRIVIA_QUERY);
|
||||||
|
|
||||||
|
filters = (TriviaFilters) bundle.get(EXTRA_TRIVIA_FILTERS);
|
||||||
|
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
DownloadTriviaQuestionsTask task = new DownloadTriviaQuestionsTask();
|
// Gather information about the trivia location.
|
||||||
task.setReceiver(this);
|
String sourceData;
|
||||||
task.execute(query);
|
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;
|
return;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
this.game = new TriviaGame(ApiUtil.jsonToQuestionArray(json));
|
this.game = new TriviaGame(ApiUtil.jsonToQuestionArray(json, filters));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//onNoTriviaResults();
|
|
||||||
onException(e);
|
onException(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -200,12 +240,23 @@ public class TriviaGameActivity extends BaseActivity
|
||||||
// Hide the progress bar.
|
// Hide the progress bar.
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
String msg;
|
String msg;
|
||||||
|
int id;
|
||||||
if (e instanceof NoTriviaResultsException)
|
if (e instanceof NoTriviaResultsException)
|
||||||
msg = getResources().getString(R.string.error_no_trivia_results);
|
id = R.string.error_no_trivia_results;
|
||||||
else if (e instanceof InvalidServerResponseException)
|
else if (e instanceof InvalidTriviaFormatException)
|
||||||
msg = getResources().getString(R.string.error_server_response_invalid);
|
// Check the trivia source type.
|
||||||
else
|
if (source == TriviaSource.SERVER)
|
||||||
msg = getResources().getString(R.string.error_unknown);
|
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);
|
Fragment errorFragment = TriviaGameErrorFragment.newInstance(msg);
|
||||||
|
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
This game is a fork of LibreTrivia, and its source code is available at
|
||||||
|
<https://github.com/tryton-vanmeer/LibreTrivia>.
|
||||||
|
|
||||||
|
Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.luca0n.joguitos.pluck.exceptions;
|
||||||
|
|
||||||
|
import java.lang.Throwable;
|
||||||
|
|
||||||
|
public class InvalidTriviaFormatException extends Exception {
|
||||||
|
public InvalidTriviaFormatException(){
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
public InvalidTriviaFormatException(Throwable cause){
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
|
@ -110,7 +110,7 @@ public enum TriviaCategory {
|
||||||
return this.ID;
|
return this.ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getName() {
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
This game is a fork of LibreTrivia, and its source code is available at
|
||||||
|
<https://github.com/tryton-vanmeer/LibreTrivia>.
|
||||||
|
|
||||||
|
Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,15 +23,8 @@ Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
|
|
||||||
package com.luca0n.joguitos.pluck.trivia;
|
package com.luca0n.joguitos.pluck.trivia;
|
||||||
|
|
||||||
import com.luca0n.joguitos.pluck.PluckApplication;
|
|
||||||
import com.luca0n.joguitos.pluck.R;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
|
|
||||||
public class TriviaQuery implements Serializable {
|
public class TriviaQuery implements Serializable {
|
||||||
private static final int DEFAULT_AMOUNT = 10;
|
private static final int DEFAULT_AMOUNT = 10;
|
||||||
|
|
||||||
|
@ -39,12 +32,14 @@ public class TriviaQuery implements Serializable {
|
||||||
private final TriviaCategory category;
|
private final TriviaCategory category;
|
||||||
private final TriviaDifficulty difficulty;
|
private final TriviaDifficulty difficulty;
|
||||||
private final TriviaType type;
|
private final TriviaType type;
|
||||||
|
private final String base;
|
||||||
|
|
||||||
private TriviaQuery(Builder builder) {
|
private TriviaQuery(Builder builder) {
|
||||||
this.amount = builder.amount;
|
this.amount = builder.amount;
|
||||||
this.category = builder.category;
|
this.category = builder.category;
|
||||||
this.difficulty = builder.difficulty;
|
this.difficulty = builder.difficulty;
|
||||||
this.type = builder.type;
|
this.type = builder.type;
|
||||||
|
this.base = builder.base;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
@ -52,6 +47,7 @@ public class TriviaQuery implements Serializable {
|
||||||
private TriviaCategory category;
|
private TriviaCategory category;
|
||||||
private TriviaDifficulty difficulty;
|
private TriviaDifficulty difficulty;
|
||||||
private TriviaType type;
|
private TriviaType type;
|
||||||
|
private String base;
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
this.amount = DEFAULT_AMOUNT;
|
this.amount = DEFAULT_AMOUNT;
|
||||||
|
@ -80,6 +76,11 @@ public class TriviaQuery implements Serializable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder base(String base){
|
||||||
|
this.base = base;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TriviaQuery build() {
|
public TriviaQuery build() {
|
||||||
return new TriviaQuery(this);
|
return new TriviaQuery(this);
|
||||||
}
|
}
|
||||||
|
@ -89,20 +90,6 @@ public class TriviaQuery implements Serializable {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder url = new StringBuilder();
|
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(base);
|
||||||
url.append("amount=").append(this.amount);
|
url.append("amount=").append(this.amount);
|
||||||
|
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
This game is a fork of LibreTrivia, and its source code is available at
|
||||||
|
<https://github.com/tryton-vanmeer/LibreTrivia>.
|
||||||
|
|
||||||
|
Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<String, TriviaSource> 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,16 +43,20 @@ import java.net.Proxy;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import com.luca0n.joguitos.pluck.R;
|
import com.luca0n.joguitos.pluck.R;
|
||||||
import com.luca0n.joguitos.pluck.PluckApplication;
|
import com.luca0n.joguitos.pluck.PluckApplication;
|
||||||
import com.luca0n.joguitos.pluck.exceptions.NoTriviaResultsException;
|
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.TriviaQuery;
|
||||||
import com.luca0n.joguitos.pluck.trivia.TriviaQuestion;
|
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.TriviaQuestionBoolean;
|
||||||
import com.luca0n.joguitos.pluck.trivia.TriviaQuestionMultiple;
|
import com.luca0n.joguitos.pluck.trivia.TriviaQuestionMultiple;
|
||||||
import com.luca0n.joguitos.pluck.trivia.TriviaType;
|
import com.luca0n.joguitos.pluck.trivia.TriviaType;
|
||||||
|
import com.luca0n.joguitos.pluck.trivia.TriviaFilters;
|
||||||
|
|
||||||
public class ApiUtil {
|
public class ApiUtil {
|
||||||
|
|
||||||
|
@ -100,18 +104,20 @@ public class ApiUtil {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String GET(TriviaQuery query) throws IOException {
|
public static String GET(TriviaQuery query)
|
||||||
|
throws IOException {
|
||||||
return GET(query.toString());
|
return GET(query.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<TriviaQuestion> jsonToQuestionArray(String json)
|
public static ArrayList<TriviaQuestion> jsonToQuestionArray(String json,
|
||||||
throws NoTriviaResultsException, InvalidServerResponseException {
|
TriviaFilters filters) throws NoTriviaResultsException,
|
||||||
|
InvalidTriviaFormatException {
|
||||||
JsonObject jsonObject;
|
JsonObject jsonObject;
|
||||||
try{
|
try{
|
||||||
jsonObject = new JsonParser().parse(json).getAsJsonObject();
|
jsonObject = new JsonParser().parse(json).getAsJsonObject();
|
||||||
} catch (JsonSyntaxException e){
|
} catch (JsonSyntaxException e){
|
||||||
// Unknown server response.
|
// Unknown server response.
|
||||||
throw new InvalidServerResponseException();
|
throw new InvalidTriviaFormatException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonObject.get("response_code").getAsInt() == 1) {
|
if (jsonObject.get("response_code").getAsInt() == 1) {
|
||||||
|
@ -122,10 +128,25 @@ public class ApiUtil {
|
||||||
|
|
||||||
ArrayList<TriviaQuestion> questions = new ArrayList<>();
|
ArrayList<TriviaQuestion> questions = new ArrayList<>();
|
||||||
|
|
||||||
|
int elements = 0;
|
||||||
|
|
||||||
for (JsonElement element : jsonArray) {
|
for (JsonElement element : jsonArray) {
|
||||||
|
int amount = filters.getAmount();
|
||||||
|
if (amount > 0 && elements++ == amount)
|
||||||
|
break;
|
||||||
JsonObject object = element.getAsJsonObject();
|
JsonObject object = element.getAsJsonObject();
|
||||||
TriviaType type = TriviaType.get(object.get("type").getAsString());
|
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) {
|
if (type == TriviaType.MULTIPLE) {
|
||||||
questions.add(TriviaQuestionMultiple.fromJson(object));
|
questions.add(TriviaQuestionMultiple.fromJson(object));
|
||||||
} else {
|
} 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;
|
return questions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,16 @@ Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<!-- Trivia Source -->
|
||||||
|
<TextView
|
||||||
|
style="@style/TextLabel"
|
||||||
|
android:labelFor="@id/spinner_source"
|
||||||
|
android:text="@string/ui_source" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinner_source"
|
||||||
|
style="@style/Spinner" />
|
||||||
|
|
||||||
<!-- Select Amount -->
|
<!-- Select Amount -->
|
||||||
<TextView
|
<TextView
|
||||||
style="@style/TextLabel"
|
style="@style/TextLabel"
|
||||||
|
|
|
@ -61,12 +61,17 @@ Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
<string name="question_type_multiple">Multiple Choice</string>
|
<string name="question_type_multiple">Multiple Choice</string>
|
||||||
<string name="question_type_boolean">True / False</string>
|
<string name="question_type_boolean">True / False</string>
|
||||||
|
|
||||||
|
<!-- Source Names -->
|
||||||
|
<string name="source_server">Server</string>
|
||||||
|
<string name="source_file">File</string>
|
||||||
|
|
||||||
<!-- UI -->
|
<!-- UI -->
|
||||||
<string name="ui_settings">Settings</string>
|
<string name="ui_settings">Settings</string>
|
||||||
<string name="ui_about">About</string>
|
<string name="ui_about">About</string>
|
||||||
<string name="ui_play">Play</string>
|
<string name="ui_play">Play</string>
|
||||||
<string name="ui_start_game">Start Game</string>
|
<string name="ui_start_game">Start Game</string>
|
||||||
<string name="ui_any">Any</string>
|
<string name="ui_any">Any</string>
|
||||||
|
<string name="ui_all">All</string>
|
||||||
<string name="ui_true">True</string>
|
<string name="ui_true">True</string>
|
||||||
<string name="ui_false">False</string>
|
<string name="ui_false">False</string>
|
||||||
<string name="ui_correct">Correct</string>
|
<string name="ui_correct">Correct</string>
|
||||||
|
@ -80,13 +85,20 @@ Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
<string name="ui_results_correct">Correct Answers</string>
|
<string name="ui_results_correct">Correct Answers</string>
|
||||||
<string name="ui_results_wrong">Wrong Answers</string>
|
<string name="ui_results_wrong">Wrong Answers</string>
|
||||||
<string name="ui_results_total">Total Questions</string>
|
<string name="ui_results_total">Total Questions</string>
|
||||||
<string name="ui_return_to_menu">Return To Menu</string>
|
<string name="ui_return_to_menu">Return To Menu</string>
|
||||||
|
<string name="ui_source">Source</string>
|
||||||
|
<string name="ui_source_about">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.</string>
|
||||||
|
|
||||||
<!-- Error Strings -->
|
<!-- Error Strings -->
|
||||||
|
<string name="error">Error</string>
|
||||||
<string name="error_network"><b>Network error!</b>\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.</string>
|
<string name="error_network"><b>Network error!</b>\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.</string>
|
||||||
<string name="error_no_trivia_results"><b>No trivia results!</b>\n\nWas not able to find trivia questions that satisfied all options.</string>
|
<string name="error_no_trivia_results"><b>No trivia results!</b>\n\nWas not able to find trivia questions that satisfied all options.</string>
|
||||||
<string name="error_server_response_invalid"><b>Server response error!</b>\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.</string>
|
<string name="error_server_response_invalid"><b>Server response error!</b>\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.</string>
|
||||||
<string name="error_unknown"><b>An unknown error occurred!</b></string>
|
<string name="error_unknown"><b>An unknown error occurred!</b></string>
|
||||||
|
<string name="error_source_file_android_version_unsupported">Trivia files are not supported in this version of Android.</string>
|
||||||
|
<string name="error_trivia_file_invalid"><b>Invalid trivia file!</b>\n\nTrivia files should be in a plain text JSON format.</string>
|
||||||
|
<string name="error_trivia_file_fetch_unknown">An unknown error occurred while attempting to read the opened file.</string>
|
||||||
|
<string name="error_option_all_unavailable">The selected question amount is only available for the "File" trivia game source.</string>
|
||||||
|
|
||||||
<string name="title_activity_settings">Settings</string>
|
<string name="title_activity_settings">Settings</string>
|
||||||
|
|
||||||
|
@ -98,6 +110,6 @@ Contact us at <joguitos+pluck@luca0n.com>.
|
||||||
<string name="pref_category_network_title">Network</string>
|
<string name="pref_category_network_title">Network</string>
|
||||||
<string name="pref_network_tor_title">Connect Using Tor</string>
|
<string name="pref_network_tor_title">Connect Using Tor</string>
|
||||||
<string name="pref_network_tor_summary">Retrieves trivia data via the Tor network. Requires Orbot (recommended) or a Tor daemon with a SOCKS5 proxy listening on port 9050.</string>
|
<string name="pref_network_tor_summary">Retrieves trivia data via the Tor network. Requires Orbot (recommended) or a Tor daemon with a SOCKS5 proxy listening on port 9050.</string>
|
||||||
<string name="pref_network_server_title">Server address</string>
|
<string name="pref_network_server_title">Server Address</string>
|
||||||
<string name="pref_network_server_summary">Specifies the server location used by the game to fetch questions. Leave empty to use the default server.</string>
|
<string name="pref_network_server_summary">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.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue