Added original source files

Added original source files from LibreTrivia
This commit is contained in:
luca0N! 2021-03-02 22:11:40 -03:00
parent 38620145b5
commit bf2ab65870
Signed by: luca0N
GPG key ID: 2E7B4655CF16D7D6
66 changed files with 2439 additions and 0 deletions

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.trytonvanmeer.libretrivia">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".LibreTriviaApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activities.TriviaGameActivity"
android:screenOrientation="fullUser"
android:configChanges="orientation|screenSize"/>
<activity android:name=".activities.TriviaGameResultsActivity"
android:screenOrientation="fullUser"
android:configChanges="orientation|screenSize"/>
<activity android:name=".settings.SettingsActivity"
android:screenOrientation="fullUser"
android:configChanges="orientation|screenSize"/>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,21 @@
package io.github.trytonvanmeer.libretrivia;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
public class LibreTriviaApplication extends Application {
@SuppressLint("StaticFieldLeak")
private static Context context;
@Override
public void onCreate() {
super.onCreate();
LibreTriviaApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return LibreTriviaApplication.context;
}
}

View file

@ -0,0 +1,59 @@
package io.github.trytonvanmeer.libretrivia.activities;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.mikepenz.aboutlibraries.Libs;
import com.mikepenz.aboutlibraries.LibsBuilder;
import androidx.appcompat.app.AppCompatActivity;
import io.github.trytonvanmeer.libretrivia.R;
import io.github.trytonvanmeer.libretrivia.settings.SettingsActivity;
@SuppressLint("Registered")
public class BaseActivity extends AppCompatActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.app_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
onSettings();
return true;
case R.id.about:
onAbout();
return true;
case android.R.id.home:
onBackPressed();
default:
return super.onOptionsItemSelected(item);
}
}
private void onSettings() {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
private void onAbout() {
String appName = getResources().getString(R.string.app_name);
String appDescription = getResources().getString(R.string.app_description);
new LibsBuilder()
.withActivityStyle(Libs.ActivityStyle.LIGHT_DARK_TOOLBAR)
.withAboutIconShown(true)
.withAboutAppName(appName)
.withAboutVersionShownName(true)
.withAboutDescription(appDescription)
.start(this);
}
}

View file

@ -0,0 +1,67 @@
package io.github.trytonvanmeer.libretrivia.activities;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.github.trytonvanmeer.libretrivia.R;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaCategory;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaDifficulty;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuery;
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;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
buttonPlay.setOnClickListener(v -> {
int amount = (int) spinnerNumber.getSelectedItem();
TriviaCategory category = (TriviaCategory) spinnerCategory.getSelectedItem();
TriviaDifficulty difficulty = (TriviaDifficulty) spinnerDifficulty.getSelectedItem();
TriviaQuery query = new TriviaQuery.Builder(amount)
.category(category)
.difficulty(difficulty)
.build();
Intent intent = new Intent(getApplicationContext(), TriviaGameActivity.class);
intent.putExtra(TriviaGameActivity.EXTRA_TRIVIA_QUERY, query);
startActivity(intent);
});
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);
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()));
}
}

View file

@ -0,0 +1,227 @@
package io.github.trytonvanmeer.libretrivia.activities;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.io.IOException;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.github.trytonvanmeer.libretrivia.R;
import io.github.trytonvanmeer.libretrivia.exceptions.NoTriviaResultsException;
import io.github.trytonvanmeer.libretrivia.fragments.TriviaGameErrorFragment;
import io.github.trytonvanmeer.libretrivia.fragments.TriviaQuestionFragment;
import io.github.trytonvanmeer.libretrivia.interfaces.IDownloadTriviaQuestionReceiver;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaGame;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuery;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuestion;
import io.github.trytonvanmeer.libretrivia.util.ApiUtil;
import io.github.trytonvanmeer.libretrivia.util.SoundUtil;
public class TriviaGameActivity extends BaseActivity
implements IDownloadTriviaQuestionReceiver {
static final String EXTRA_TRIVIA_QUERY = "extra_trivia_query";
private final String STATE_TRIVIA_GAME = "state_trivia_game";
private TriviaGame game;
@BindView(R.id.progress_bar)
ProgressBar progressBar;
@BindView(R.id.trivia_status_bar)
LinearLayout triviaStatusBar;
@BindView(R.id.text_question_category)
TextView textViewQuestionCategory;
@BindView(R.id.text_question_difficulty)
TextView textViewQuestionDifficulty;
@BindView(R.id.text_question_progress)
TextView textViewQuestionProgress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_trivia_game);
ButterKnife.bind(this);
if (savedInstanceState != null) {
this.game = (TriviaGame) savedInstanceState.getSerializable(STATE_TRIVIA_GAME);
} else {
Bundle bundle = getIntent().getExtras();
assert bundle != null;
TriviaQuery query = (TriviaQuery) bundle.get(EXTRA_TRIVIA_QUERY);
progressBar.setVisibility(View.VISIBLE);
DownloadTriviaQuestionsTask task = new DownloadTriviaQuestionsTask();
task.setReceiver(this);
task.execute(query);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(STATE_TRIVIA_GAME, this.game);
}
@Override
public void onBackPressed() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.frame_trivia_game);
if (fragment instanceof TriviaGameErrorFragment) {
super.onBackPressed();
} else {
new AlertDialog.Builder(this)
.setTitle(R.string.ui_quit_game)
.setMessage(R.string.ui_quit_game_msg)
.setPositiveButton(android.R.string.yes, (dialog, which) ->
TriviaGameActivity.super.onBackPressed())
.setNegativeButton(android.R.string.no, (dialog, which) -> {
})
.show();
}
}
public void onTriviaQuestionsDownloaded(String json) {
if (json == null) {
onNetworkError();
return;
} else {
try {
this.game = new TriviaGame(ApiUtil.jsonToQuestionArray(json));
} catch (NoTriviaResultsException e) {
onNoTriviaResults();
return;
}
}
// Setup game layout
progressBar.setVisibility(View.GONE);
triviaStatusBar.setVisibility(View.VISIBLE);
updateStatusBar();
updateTriviaQuestion();
}
private void updateStatusBar() {
String progress = getResources().getString(R.string.ui_question_progress,
game.getQuestionProgress(), game.getQuestionsCount());
String category = (game.getCurrentQuestion().getCategory() != null)
? game.getCurrentQuestion().getCategory().toString() : "";
String difficulty = game.getCurrentQuestion().getDifficulty().toString();
textViewQuestionProgress.setText(progress);
textViewQuestionCategory.setText(category);
textViewQuestionDifficulty.setText(difficulty);
}
private void updateTriviaQuestion() {
Fragment fragment = TriviaQuestionFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_trivia_game, fragment)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit();
}
private void onNetworkError() {
String msg = getResources().getString(R.string.error_network);
Fragment errorFragment = TriviaGameErrorFragment.newInstance(msg);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.frame_trivia_game, errorFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
private void onNoTriviaResults() {
String msg = getResources().getString(R.string.error_no_trivia_results);
Fragment errorFragment = TriviaGameErrorFragment.newInstance(msg);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.frame_trivia_game, errorFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
public TriviaQuestion getCurrentQuestion() {
return this.game.getCurrentQuestion();
}
public void onAnswerClick(Button answer, Button correctAnswer) {
boolean guess = game.nextQuestion(answer.getText().toString());
final int green = getResources().getColor(R.color.colorAccentGreen);
int color = guess ? green
: getResources().getColor(R.color.colorAccentRed);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ColorStateList stateList = ColorStateList.valueOf(color);
answer.setBackgroundTintList(stateList);
if (!guess) {
final ColorStateList greenStateList = ColorStateList.valueOf(green);
correctAnswer.setBackgroundTintList(greenStateList);
}
} else {
answer.getBackground().getCurrent().setColorFilter(
new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
if (!guess)
correctAnswer.getBackground().getCurrent().setColorFilter(
new PorterDuffColorFilter(green, PorterDuff.Mode.MULTIPLY));
}
SoundUtil.playSound(this, guess ?
SoundUtil.SOUND_ANSWER_CORRECT : SoundUtil.SOUND_ANSWER_WRONG);
new Handler().postDelayed(() -> {
if (game.isDone()) {
Intent intent = new Intent(getApplicationContext(), TriviaGameResultsActivity.class);
intent.putExtra(TriviaGameResultsActivity.EXTRA_TRIVIA_GAME, game);
startActivity(intent);
finish();
} else {
updateStatusBar();
updateTriviaQuestion();
}
}, 500);
}
private static class DownloadTriviaQuestionsTask extends AsyncTask<TriviaQuery, Integer, String> {
private IDownloadTriviaQuestionReceiver receiver;
@Override
protected String doInBackground(TriviaQuery... query) {
String json;
try {
json = ApiUtil.GET(query[0]);
} catch (IOException e) {
return null;
}
return json;
}
@Override
protected void onPostExecute(String json) {
receiver.onTriviaQuestionsDownloaded(json);
}
private void setReceiver(IDownloadTriviaQuestionReceiver receiver) {
this.receiver = receiver;
}
}
}

View file

@ -0,0 +1,47 @@
package io.github.trytonvanmeer.libretrivia.activities;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.github.trytonvanmeer.libretrivia.R;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaGame;
public class TriviaGameResultsActivity extends BaseActivity {
static final String EXTRA_TRIVIA_GAME = "extra_trivia_game";
@BindView(R.id.text_results_correct)
TextView textResultsCorrect;
@BindView(R.id.text_results_wrong)
TextView textResultsWrong;
@BindView(R.id.text_results_total)
TextView textResultsTotal;
@BindView(R.id.button_return_to_menu)
Button buttonReturnToMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_trivia_game_results);
ButterKnife.bind(this);
Bundle bundle = getIntent().getExtras();
TriviaGame game = (TriviaGame) bundle.get(EXTRA_TRIVIA_GAME);
int correctTotal = 0;
for (boolean result : game.getResults()) {
if (result) {
correctTotal++;
}
}
textResultsCorrect.setText(String.valueOf(correctTotal));
textResultsWrong.setText(String.valueOf(game.getQuestionsCount() - correctTotal));
textResultsTotal.setText(String.valueOf(game.getQuestionsCount()));
buttonReturnToMenu.setOnClickListener(v -> finish());
}
}

View file

@ -0,0 +1,4 @@
package io.github.trytonvanmeer.libretrivia.exceptions;
public class NoTriviaResultsException extends Exception {
}

View file

@ -0,0 +1,46 @@
package io.github.trytonvanmeer.libretrivia.fragments;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.github.trytonvanmeer.libretrivia.R;
public class TriviaGameErrorFragment extends Fragment {
private final static String ARG_ERROR_MSG = "arg_error_msg";
@BindView(R.id.text_error_msg)
TextView textView;
public TriviaGameErrorFragment() {
}
public static TriviaGameErrorFragment newInstance(String msg) {
Bundle args = new Bundle();
args.putString(ARG_ERROR_MSG, msg);
TriviaGameErrorFragment fragment = new TriviaGameErrorFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_trivia_game_error, container, false);
ButterKnife.bind(this, view);
Bundle args;
if ((args = getArguments()) != null) {
textView.setText(args.getString(ARG_ERROR_MSG));
}
return view;
}
}

View file

@ -0,0 +1,117 @@
package io.github.trytonvanmeer.libretrivia.fragments;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import butterknife.BindViews;
import butterknife.ButterKnife;
import io.github.trytonvanmeer.libretrivia.R;
import io.github.trytonvanmeer.libretrivia.activities.TriviaGameActivity;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuestion;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuestionMultiple;
public class TriviaQuestionFragment extends Fragment {
private static final int buttonAnswerOneID = R.id.button_answer_one;
private static final int buttonAnswerTwoID = R.id.button_answer_two;
private static final int buttonAnswerThreeID = R.id.button_answer_three;
private static final int buttonAnswerFourID = R.id.button_answer_four;
@BindViews({
buttonAnswerOneID,
buttonAnswerTwoID,
buttonAnswerThreeID,
buttonAnswerFourID
})
Button[] buttonAnswers;
Button buttonAnswerCorrect;
Button buttonAnswerTrue;
Button buttonAnswerFalse;
public TriviaQuestionFragment() {
}
public static TriviaQuestionFragment newInstance() {
return new TriviaQuestionFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TriviaQuestion question = ((TriviaGameActivity) getActivity()).getCurrentQuestion();
View view;
if (question instanceof TriviaQuestionMultiple) {
view = inflater.inflate(R.layout.fragment_trivia_question_multiple, container, false);
ButterKnife.bind(this, view);
} else {
view = inflater.inflate(R.layout.fragment_trivia_question_boolean, container, false);
this.buttonAnswerTrue = view.findViewById(R.id.button_answer_true);
this.buttonAnswerFalse = view.findViewById(R.id.button_answer_false);
}
TextView textViewQuestion = view.findViewById(R.id.text_trivia_question);
textViewQuestion.setText(question.getQuestion());
setupButtons();
return view;
}
private void setupButtons() {
AnswerButtonListener listener = new AnswerButtonListener();
TriviaQuestion question = ((TriviaGameActivity) getActivity()).getCurrentQuestion();
if (question instanceof TriviaQuestionMultiple) {
List<String> answers = Arrays.asList((
(TriviaQuestionMultiple) question).getAnswerList());
Collections.shuffle(answers);
for (int i = 0; i < buttonAnswers.length; i++) {
buttonAnswers[i].setText(answers.get(i));
buttonAnswers[i].setOnClickListener(listener);
if (question.checkAnswer(answers.get(i))) {
buttonAnswerCorrect = buttonAnswers[i];
}
}
} else {
buttonAnswerTrue.setOnClickListener(listener);
buttonAnswerFalse.setOnClickListener(listener);
}
}
private void disableButtons() {
TriviaQuestion question = ((TriviaGameActivity) getActivity()).getCurrentQuestion();
if (question instanceof TriviaQuestionMultiple) {
buttonAnswers[0].setEnabled(false);
buttonAnswers[1].setEnabled(false);
buttonAnswers[2].setEnabled(false);
buttonAnswers[3].setEnabled(false);
} else {
buttonAnswerTrue.setEnabled(false);
buttonAnswerFalse.setEnabled(false);
}
}
private class AnswerButtonListener implements View.OnClickListener {
@Override
public void onClick(View v) {
disableButtons();
((TriviaGameActivity) getActivity()).onAnswerClick((Button) v, buttonAnswerCorrect);
}
}
}

View file

@ -0,0 +1,5 @@
package io.github.trytonvanmeer.libretrivia.interfaces;
public interface IDownloadTriviaQuestionReceiver {
void onTriviaQuestionsDownloaded(String json);
}

View file

@ -0,0 +1,37 @@
package io.github.trytonvanmeer.libretrivia.settings;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
public class SettingsActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(null);
}
getFragmentManager()
.beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View file

@ -0,0 +1,15 @@
package io.github.trytonvanmeer.libretrivia.settings;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import androidx.annotation.Nullable;
import io.github.trytonvanmeer.libretrivia.R;
public class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}

View file

@ -0,0 +1,102 @@
package io.github.trytonvanmeer.libretrivia.trivia;
import java.util.HashMap;
import java.util.Map;
import io.github.trytonvanmeer.libretrivia.LibreTriviaApplication;
import io.github.trytonvanmeer.libretrivia.R;
/*
Categories that a Trivia Question can fall into
*/
public enum TriviaCategory {
ANY(-1, "Any", R.string.ui_any),
GENERAL_KNOWLEDGE(9, "General Knowledge",
R.string.category_general_knowledge),
ENTERTAINMENT_BOOKS(10, "Entertainment: Books",
R.string.category_entertainment_books),
ENTERTAINMENT_FILM(11, "Entertainment: Film",
R.string.category_entertainment_film),
ENTERTAINMENT_MUSIC(12, "Entertainment: Music",
R.string.category_entertainment_music),
ENTERTAINMENT_MUSICALS_THEATRES(13, "Entertainment: Musicals & Theatres",
R.string.category_entertainment_musicals_theatres),
ENTERTAINMENT_TELEVISION(14, "Entertainment: Television",
R.string.category_entertainment_television),
ENTERTAINMENT_VIDEO_GAMES(15, "Entertainment: Video Games",
R.string.category_entertainment_video_games),
ENTERTAINMENT_BOARD_GAMES(16, "Entertainment: Board Games",
R.string.category_entertainment_board_games),
ENTERTAINMENT_JAPANESE_ANIME_MANGA(31, "Entertainment: Japanese Anime & Manga",
R.string.category_entertainment_japanese_anime_manga),
ENTERTAINMENT_CARTOON_ANIMATIONS(32, "Entertainment: Cartoons & Animation",
R.string.category_entertainment_cartoon_animations),
ENTERTAINMENT_COMICS(29, "Entertainment: Comics",
R.string.category_entertainment_comics),
SCIENCE_NATURE(17, "Science & Nature",
R.string.category_science_nature),
SCIENCE_COMPUTERS(18, "Science: Computers",
R.string.category_science_computers),
SCIENCE_MATHEMATICS(19, "Science: Mathematics",
R.string.category_science_mathematics),
SCIENCE_GADGETS(30, "Science: Gadgets",
R.string.category_science_gadgets),
MYTHOLOGY(20, "Mythology",
R.string.category_mythology),
SPORTS(21, "Sports",
R.string.category_sports),
GEOGRAPHY(22, "Geography",
R.string.category_geography),
HISTORY(23, "History",
R.string.category_history),
POLITICS(24, "Politics",
R.string.category_politics),
ART(25, "Art",
R.string.category_art),
CELEBRITIES(26, "Celebrities",
R.string.category_celebrities),
ANIMALS(27, "Animals",
R.string.category_animals),
VEHICLES(28, "Vehicles",
R.string.category_vehicles);
// The id of the category in the opentdb api
// see <https://opentdb.com/api_category.php>
private final int ID;
// The name of the category in the JSON response
private final String name;
// The display name of the category
private final int displayName;
private static final Map<String, TriviaCategory> lookup = new HashMap<>();
static {
for (TriviaCategory category : TriviaCategory.values()) {
lookup.put(category.getName(), category);
}
}
TriviaCategory(int ID, String name, int displayName) {
this.ID = ID;
this.name = name;
this.displayName = displayName;
}
public int getID() {
return this.ID;
}
private String getName() {
return this.name;
}
public static TriviaCategory get(String name) {
return lookup.get(name);
}
@Override
public String toString() {
return LibreTriviaApplication.getAppContext().getResources().getString(this.displayName);
}
}

View file

@ -0,0 +1,46 @@
package io.github.trytonvanmeer.libretrivia.trivia;
import java.util.HashMap;
import java.util.Map;
import io.github.trytonvanmeer.libretrivia.LibreTriviaApplication;
import io.github.trytonvanmeer.libretrivia.R;
public enum TriviaDifficulty {
ANY("any", R.string.ui_any),
EASY("easy", R.string.difficulty_easy),
MEDIUM("medium", R.string.difficulty_medium),
HARD("hard", R.string.difficulty_hard);
// Name of difficulty used in queries
private final String name;
// Display name of the difficulty
private final int displayName;
private static final Map<String, TriviaDifficulty> lookup = new HashMap<>();
static {
for (TriviaDifficulty difficulty : TriviaDifficulty.values()) {
lookup.put(difficulty.getName(), difficulty);
}
}
TriviaDifficulty(String name, int displayName) {
this.name = name;
this.displayName = displayName;
}
public String getName() {
return this.name;
}
public static TriviaDifficulty get(String name) {
return lookup.get(name);
}
@Override
public String toString() {
return LibreTriviaApplication.getAppContext().getResources().getString(this.displayName);
}
}

View file

@ -0,0 +1,46 @@
package io.github.trytonvanmeer.libretrivia.trivia;
import java.io.Serializable;
import java.util.List;
public class TriviaGame implements Serializable {
private int currentQuestion;
private final boolean[] results;
private final List<TriviaQuestion> questions;
public TriviaGame(List<TriviaQuestion> questions) {
this.currentQuestion = 0;
this.questions = questions;
this.results = new boolean[questions.size()];
}
public TriviaQuestion getCurrentQuestion() {
return this.questions.get(currentQuestion);
}
public int getQuestionProgress() {
return this.currentQuestion + 1;
}
public int getQuestionsCount() {
return this.questions.size();
}
public boolean[] getResults() {
return this.results;
}
public boolean nextQuestion(String guess) {
TriviaQuestion question = getCurrentQuestion();
boolean answer = question.checkAnswer(guess);
results[currentQuestion] = answer;
currentQuestion++;
return answer;
}
public boolean isDone() {
return (this.currentQuestion == questions.size());
}
}

View file

@ -0,0 +1,78 @@
package io.github.trytonvanmeer.libretrivia.trivia;
import java.io.Serializable;
public class TriviaQuery implements Serializable {
private static final String BASE = "https://opentdb.com/api.php?";
private static final int DEFAULT_AMOUNT = 10;
private final int amount;
private final TriviaCategory category;
private final TriviaDifficulty difficulty;
private final TriviaType type;
private TriviaQuery(Builder builder) {
this.amount = builder.amount;
this.category = builder.category;
this.difficulty = builder.difficulty;
this.type = builder.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 TriviaQuery build() {
return new TriviaQuery(this);
}
}
@Override
public String toString() {
StringBuilder url = new StringBuilder();
url.append(BASE);
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();
}
}

View file

@ -0,0 +1,31 @@
package io.github.trytonvanmeer.libretrivia.trivia;
import java.io.Serializable;
public abstract class TriviaQuestion implements Serializable {
private final TriviaCategory category;
private final TriviaDifficulty difficulty;
private final String question;
TriviaQuestion(TriviaCategory category, TriviaDifficulty difficulty, String question) {
this.category = category;
this.difficulty = difficulty;
this.question = question;
}
public TriviaCategory getCategory() {
return this.category;
}
public TriviaDifficulty getDifficulty() {
return this.difficulty;
}
public String getQuestion() {
return this.question;
}
public abstract boolean checkAnswer(String guess);
}

View file

@ -0,0 +1,34 @@
package io.github.trytonvanmeer.libretrivia.trivia;
import android.text.Html;
import com.google.gson.JsonObject;
public class TriviaQuestionBoolean extends TriviaQuestion {
private final Boolean correctAnswer;
public TriviaQuestionBoolean(TriviaCategory category, TriviaDifficulty difficulty,
String question, boolean correctAnswer) {
super(category, difficulty, question);
this.correctAnswer = correctAnswer;
}
@Override
public boolean checkAnswer(String guess) {
return this.correctAnswer.equals(Boolean.valueOf(guess));
}
public boolean checkAnswer(Boolean guess) {
return checkAnswer(guess.toString());
}
public static TriviaQuestionBoolean fromJson(JsonObject json) {
TriviaCategory category = TriviaCategory.get(json.get("category").getAsString());
TriviaDifficulty difficulty = TriviaDifficulty.get(json.get("difficulty").getAsString());
String question = Html.fromHtml(json.get("question").getAsString()).toString();
Boolean correctAnswer = json.get("correct_answer").getAsBoolean();
return new TriviaQuestionBoolean(category, difficulty, question, correctAnswer);
}
}

View file

@ -0,0 +1,48 @@
package io.github.trytonvanmeer.libretrivia.trivia;
import android.text.Html;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
public class TriviaQuestionMultiple extends TriviaQuestion {
private final String correctAnswer;
private final String[] incorrectAnswers;
public TriviaQuestionMultiple(TriviaCategory category, TriviaDifficulty difficulty,
String question, String correctAnswer, String[] incorrectAnswers) {
super(category, difficulty, question);
this.correctAnswer = correctAnswer;
this.incorrectAnswers = incorrectAnswers;
}
public String[] getAnswerList() {
return new String[]{correctAnswer,
incorrectAnswers[0],
incorrectAnswers[1],
incorrectAnswers[2]};
}
@Override
public boolean checkAnswer(String guess) {
return this.correctAnswer.equals(guess);
}
public static TriviaQuestionMultiple fromJson(JsonObject json) {
TriviaCategory category = TriviaCategory.get(json.get("category").getAsString());
TriviaDifficulty difficulty = TriviaDifficulty.get(json.get("difficulty").getAsString());
String question = Html.fromHtml(json.get("question").getAsString()).toString();
String correctAnswer = Html.fromHtml(json.get("correct_answer").getAsString()).toString();
JsonArray incorrectAnswersJson = json.get("incorrect_answers").getAsJsonArray();
String[] incorrectAnswers = new String[]{
Html.fromHtml(incorrectAnswersJson.get(0).getAsString()).toString(),
Html.fromHtml(incorrectAnswersJson.get(1).getAsString()).toString(),
Html.fromHtml(incorrectAnswersJson.get(2).getAsString()).toString()
};
return new TriviaQuestionMultiple(
category, difficulty, question, correctAnswer, incorrectAnswers);
}
}

View file

@ -0,0 +1,45 @@
package io.github.trytonvanmeer.libretrivia.trivia;
import java.util.HashMap;
import java.util.Map;
import io.github.trytonvanmeer.libretrivia.LibreTriviaApplication;
import io.github.trytonvanmeer.libretrivia.R;
public enum TriviaType {
ANY("any", R.string.ui_any),
MULTIPLE("multiple", R.string.question_type_multiple),
BOOLEAN("boolean", R.string.question_type_boolean);
// Name of type used in queries
private final String name;
// Display name of the type
private final int displayName;
private static final Map<String, TriviaType> lookup = new HashMap<>();
static {
for (TriviaType type : TriviaType.values()) {
lookup.put(type.getName(), type);
}
}
TriviaType(String name, int displayName) {
this.name = name;
this.displayName = displayName;
}
public String getName() {
return this.name;
}
public static TriviaType get(String name) {
return lookup.get(name);
}
@Override
public String toString() {
return LibreTriviaApplication.getAppContext().getResources().getString(this.displayName);
}
}

View file

@ -0,0 +1,82 @@
package io.github.trytonvanmeer.libretrivia.util;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import io.github.trytonvanmeer.libretrivia.exceptions.NoTriviaResultsException;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuery;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuestion;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuestionBoolean;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaQuestionMultiple;
import io.github.trytonvanmeer.libretrivia.trivia.TriviaType;
public class ApiUtil {
private static String readStream(InputStream in) throws IOException {
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(in), 1000);
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
builder.append(line);
}
in.close();
return builder.toString();
}
private static String GET(String query) throws IOException {
String response;
URL url = new URL(query);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(connection.getInputStream());
response = readStream(in);
} finally {
connection.disconnect();
}
return response;
}
public static String GET(TriviaQuery query) throws IOException {
return GET(query.toString());
}
public static ArrayList<TriviaQuestion> jsonToQuestionArray(String json) throws NoTriviaResultsException {
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
if (jsonObject.get("response_code").getAsInt() == 1) {
throw new NoTriviaResultsException();
}
JsonArray jsonArray = jsonObject.getAsJsonArray("results");
ArrayList<TriviaQuestion> questions = new ArrayList<>();
for (JsonElement element : jsonArray) {
JsonObject object = element.getAsJsonObject();
TriviaType type = TriviaType.get(object.get("type").getAsString());
if (type == TriviaType.MULTIPLE) {
questions.add(TriviaQuestionMultiple.fromJson(object));
} else {
questions.add(TriviaQuestionBoolean.fromJson(object));
}
}
return questions;
}
}

View file

@ -0,0 +1,25 @@
package io.github.trytonvanmeer.libretrivia.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.preference.PreferenceManager;
import io.github.trytonvanmeer.libretrivia.R;
public class SoundUtil {
public static final int SOUND_ANSWER_CORRECT = R.raw.sound_answer_correct;
public static final int SOUND_ANSWER_WRONG = R.raw.sound_answer_wrong;
public static void playSound(Context context, int sound) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String key_sound = context.getResources().getString(R.string.pref_sound_answer);
boolean pref_sound = preferences.getBoolean(key_sound, true);
if (pref_sound) {
final MediaPlayer player = MediaPlayer.create(context, sound);
player.setVolume(0.25f, 0.25f);
player.start();
}
}
}

View file

@ -0,0 +1,32 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="97.2"
android:viewportHeight="97.2">
<path
android:fillType="evenOdd"
android:pathData="m49.05,22.5 l-6.37,5.01 -6.36,5.01 6.36,5.01 6.37,-5.01 3.73,2.94v8.3l-10.09,7.94v14.17h9L51.69,54.64l10.09,-7.95L61.78,32.52L55.41,27.51ZM42.69,69.41v7.09h9v-7.09z"
android:strokeWidth="1"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:endX=".5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#ffffff"
android:pathData="m48.6,21.6 l-6.37,5.01 -6.36,5.01 6.36,5.01 6.37,-5.01 3.73,2.94v8.3l-10.09,7.94v14.17h9V53.74l10.09,-7.95V31.62L54.96,26.61ZM42.24,68.51V75.6h9v-7.09z"
android:strokeWidth="1" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#000000"
android:pathData="M17,9H7V7H17M17,13H7V11H17M14,17H7V15H14M12,3A1,1 0,0 1,13 4A1,1 0,0 1,12 5A1,1 0,0 1,11 4A1,1 0,0 1,12 3M19,3H14.82C14.4,1.84 13.3,1 12,1C10.7,1 9.6,1.84 9.18,3H5A2,2 0,0 0,3 5V19A2,2 0,0 0,5 21H19A2,2 0,0 0,21 19V5A2,2 0,0 0,19 3Z" />
</vector>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M15.5,8C16.3,8 17,8.7 17,9.5C17,10.3 16.3,11 15.5,11C14.7,11 14,10.3 14,9.5C14,8.7 14.7,8 15.5,8M10,9.5C10,10.3 9.3,11 8.5,11C7.7,11 7,10.3 7,9.5C7,8.7 7.7,8 8.5,8C9.3,8 10,8.7 10,9.5M12,14C13.75,14 15.29,14.72 16.19,15.81L14.77,17.23C14.32,16.5 13.25,16 12,16C10.75,16 9.68,16.5 9.23,17.23L7.81,15.81C8.71,14.72 10.25,14 12,14Z" />
</vector>

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="io.github.trytonvanmeer.libretrivia.activities.MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!-- Select Amount -->
<TextView
style="@style/TextLabel"
android:labelFor="@id/spinner_number"
android:text="@string/ui_amount" />
<Spinner
android:id="@+id/spinner_number"
style="@style/Spinner" />
<!-- Select Category Spinner -->
<TextView
style="@style/TextLabel"
android:labelFor="@id/spinner_category"
android:text="@string/ui_category" />
<Spinner
android:id="@+id/spinner_category"
style="@style/Spinner" />
<!-- Select Difficulty Spinner -->
<TextView
style="@style/TextLabel"
android:labelFor="@id/spinner_difficulty"
android:text="@string/ui_difficulty" />
<Spinner
android:id="@+id/spinner_difficulty"
style="@style/Spinner" />
<!-- Play Button -->
<Button
android:id="@+id/button_play"
style="@style/Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/ui_start_game"
android:textSize="24sp" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/trivia_status_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="@+id/scrollView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/text_question_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
tools:text="Category" />
<TextView
android:id="@+id/text_question_difficulty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
tools:text="Difficulty" />
</LinearLayout>
<TextView
android:id="@+id/text_question_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="16dp"
android:textSize="32sp"
android:textStyle="bold"
tools:text="110" />
</LinearLayout>
<ScrollView
android:id="@+id/scrollView2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/trivia_status_bar">
<FrameLayout
android:id="@+id/frame_trivia_game"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="100dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context="io.github.trytonvanmeer.libretrivia.activities.TriviaGameResultsActivity">
<ImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_gravity="center"
android:layout_marginBottom="16dp"
android:scaleType="fitXY"
android:src="@drawable/ic_clipboard_text"
android:tint="@color/colorTextSecondary" />
<!-- Total Answers -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">
<TextView
style="@style/ResultText"
android:text="@string/ui_results_total"
android:textColor="@color/colorAccent" />
<TextView
android:id="@+id/text_results_total"
style="@style/ResultText"
tools:text="10" />
</LinearLayout>
<!-- Correct Answers -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">
<TextView
style="@style/ResultText"
android:text="@string/ui_results_correct"
android:textColor="@color/colorAccentGreen" />
<TextView
android:id="@+id/text_results_correct"
style="@style/ResultText"
tools:text="6" />
</LinearLayout>
<!-- Wrong Answers-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp">
<TextView
style="@style/ResultText"
android:text="@string/ui_results_wrong"
android:textColor="@color/colorAccentRed" />
<TextView
android:id="@+id/text_results_wrong"
style="@style/ResultText"
tools:text="4" />
</LinearLayout>
<!-- Buttons -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<Button
android:id="@+id/button_return_to_menu"
style="@style/Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/ui_return_to_menu" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View file

@ -0,0 +1,34 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="io.github.trytonvanmeer.libretrivia.fragments.TriviaGameErrorFragment">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:scaleType="fitXY"
android:src="@drawable/ic_emoticon_sad"
android:tint="@color/colorTextSecondary" />
<TextView
android:id="@+id/text_error_msg"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="50dp"
android:text="@string/error_no_trivia_results"
android:textAlignment="center" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/text_trivia_question"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold"
tools:text="Is such-and-such true or false?" />
<Button
android:id="@+id/button_answer_true"
style="@style/AnswerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ui_true" />
<Button
android:id="@+id/button_answer_false"
style="@style/AnswerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ui_false" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/text_trivia_question"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold"
tools:text="What is the answer to this question?" />
<Button
android:id="@+id/button_answer_one"
style="@style/AnswerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Question 1" />
<Button
android:id="@+id/button_answer_two"
style="@style/AnswerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Question 2" />
<Button
android:id="@+id/button_answer_three"
style="@style/AnswerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Question 3" />
<Button
android:id="@+id/button_answer_four"
style="@style/AnswerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Question 4" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/settings"
android:title="@string/ui_settings"
app:showAsAction="never" />
<item
android:id="@+id/about"
android:title="@string/ui_about"
app:showAsAction="never" />
</menu>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/colorPrimary" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/colorPrimary" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,005 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,69 @@
<resources>
<string name="app_description">Ein Open-Source-Trivia-Spiel</string>
<!-- Category Names -->
<string name="category_general_knowledge">Allgemeinwissen</string>
<string name="category_entertainment_books">Unterhaltung: Bücher</string>
<string name="category_entertainment_film">Unterhaltung: Filme</string>
<string name="category_entertainment_music">Unterhaltung: Musik</string>
<string name="category_entertainment_musicals_theatres">Unterhaltung: Musicals und Theater</string>
<string name="category_entertainment_television">Unterhaltung: Fernsehen</string>
<string name="category_entertainment_video_games">Unterhaltung: Video Spiele</string>
<string name="category_entertainment_board_games">Unterhaltung: Brettspiele</string>
<string name="category_entertainment_japanese_anime_manga">Unterhaltung: Japanische Animes &amp; Mangas</string>
<string name="category_entertainment_cartoon_animations">Unterhaltung: Cartoons &amp; Animation</string>
<string name="category_entertainment_comics">Unterhaltung: Comics</string>
<string name="category_science_nature">Wissenschaft und Natur</string>
<string name="category_science_computers">Wissenschaft: Computer</string>
<string name="category_science_mathematics">Wissenschaft: Mathematik</string>
<string name="category_science_gadgets">Wissenschaft: Gadgets</string>
<string name="category_mythology">Mythologie</string>
<string name="category_sports">Sport</string>
<string name="category_geography">Geographie</string>
<string name="category_history">Geschichte</string>
<string name="category_politics">Politik</string>
<string name="category_art">Kunst</string>
<string name="category_celebrities">Prominente</string>
<string name="category_animals">Tiere</string>
<string name="category_vehicles">Fahrzeuge</string>
<!-- Difficulty Names -->
<string name="difficulty_easy">Einfach</string>
<string name="difficulty_medium">Mittel</string>
<string name="difficulty_hard">Schwer</string>
<!-- Question Type Names -->
<string name="question_type_multiple">Multiple-Choice</string>
<string name="question_type_boolean">Richtig / Falsch</string>
<!-- UI -->
<string name="ui_settings">Einstellungen</string>
<string name="ui_about">Über</string>
<string name="ui_play">Spielen</string>
<string name="ui_start_game">Spiel starten</string>
<string name="ui_any">Alle</string>
<string name="ui_true">Richtig</string>
<string name="ui_false">Falsch</string>
<string name="ui_correct">Richtig</string>
<string name="ui_wrong">Falsch</string>
<string name="ui_amount">Fragen</string>
<string name="ui_category">Kategorie</string>
<string name="ui_difficulty">Schwierigkeit</string>
<string name="ui_question_progress">%1$d%2$d</string>
<string name="ui_quit_game">Spiel verlassen</string>
<string name="ui_quit_game_msg">Bist du dir sicher, dass du dieses Spiel verlassen möchtest?</string>
<string name="ui_results_correct">Richtige Antworten</string>
<string name="ui_results_wrong">Flasche Antworten</string>
<string name="ui_results_total">Insgesamte Fragen</string>
<string name="ui_return_to_menu">Zurück ins Menü</string>
<!-- Error Strings -->
<string name="error_network"><b>Netzwerk Fehler!</b>\n
Verbinden mit einem Netzwerk nicht möglich</string>
<string name="error_no_trivia_results"><b>Keine Trivia Ergebnisse!</b>\n
Es wurden keine Trivia Fragen gefunden, die alle Bedingungen erfüllt haben.</string>
<string name="title_activity_settings">Einstellungen</string>
<!-- Setting Strings-->
<string name="pref_category_sound_title">Ton</string>
</resources>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#F44336</color>
<color name="colorPrimaryDark">#D32F2F</color>
<color name="colorAccent">#536DFE</color>
<color name="colorTextPrimary">#212121</color>
<color name="colorTextSecondary">#757575</color>
<color name="colorText">#FFFFFF</color>
<color name="colorAccentRed">#D50000</color>
<color name="colorAccentGreen">#00C853</color>
</resources>

View file

@ -0,0 +1,4 @@
<resources>
<string name="pref_category_sound">pref_key_category_sound</string>
<string name="pref_sound_answer">pref_sound_answer</string>
</resources>

View file

@ -0,0 +1,69 @@
<resources>
<string name="app_name" translatable="false">LibreTrivia</string>
<string name="app_description">An open source trivia game.</string>
<!-- Category Names -->
<string name="category_general_knowledge">General Knowledge</string>
<string name="category_entertainment_books">Entertainment: Books</string>
<string name="category_entertainment_film">Entertainment: Film</string>
<string name="category_entertainment_music">Entertainment: Music</string>
<string name="category_entertainment_musicals_theatres">Entertainment: Musicals &amp; Theatres</string>
<string name="category_entertainment_television">Entertainment: Television</string>
<string name="category_entertainment_video_games">Entertainment: Video Games</string>
<string name="category_entertainment_board_games">Entertainment: Board Games</string>
<string name="category_entertainment_japanese_anime_manga">Entertainment: Japanese Anime &amp; Manga</string>
<string name="category_entertainment_cartoon_animations">Entertainment: Cartoons &amp; Animation</string>
<string name="category_entertainment_comics">Entertainment: Comics</string>
<string name="category_science_nature">Science &amp; Nature</string>
<string name="category_science_computers">Science: Computers</string>
<string name="category_science_mathematics">Science: Mathematics</string>
<string name="category_science_gadgets">Science: Gadgets</string>
<string name="category_mythology">Mythology</string>
<string name="category_sports">Sports</string>
<string name="category_geography">Geography</string>
<string name="category_history">History</string>
<string name="category_politics">Politics</string>
<string name="category_art">Art</string>
<string name="category_celebrities">Celebrities</string>
<string name="category_animals">Animals</string>
<string name="category_vehicles">Vehicles</string>
<!-- Difficulty Names -->
<string name="difficulty_easy">Easy</string>
<string name="difficulty_medium">Medium</string>
<string name="difficulty_hard">Hard</string>
<!-- Question Type Names -->
<string name="question_type_multiple">Multiple Choice</string>
<string name="question_type_boolean">True / False</string>
<!-- UI -->
<string name="ui_settings">Settings</string>
<string name="ui_about">About</string>
<string name="ui_play">Play</string>
<string name="ui_start_game">Start Game</string>
<string name="ui_any">Any</string>
<string name="ui_true">True</string>
<string name="ui_false">False</string>
<string name="ui_correct">Correct</string>
<string name="ui_wrong">Wrong</string>
<string name="ui_amount">Questions</string>
<string name="ui_category">Category</string>
<string name="ui_difficulty">Difficulty</string>
<string name="ui_question_progress">%1$d%2$d</string>
<string name="ui_quit_game">Quit Game</string>
<string name="ui_quit_game_msg">Are you sure you want to quit this game?</string>
<string name="ui_results_correct">Correct Answers</string>
<string name="ui_results_wrong">Wrong Answers</string>
<string name="ui_results_total">Total Questions</string>
<string name="ui_return_to_menu">Return To Menu</string>
<!-- Error Strings -->
<string name="error_network"><b>Network error!</b>\n Could not connect to a network.</string>
<string name="error_no_trivia_results"><b>No trivia results!</b>\n Was not able to find trivia questions that satisfied all options.</string>
<string name="title_activity_settings">Settings</string>
<!-- Setting Strings-->
<string name="pref_category_sound_title">Sound</string>
<string name="pref_sound_answer_title">Answer Sound Effect</string>
</resources>

View file

@ -0,0 +1,42 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="TextLabel">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">18sp</item>
</style>
<style name="Spinner">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginBottom">16dp</item>
</style>
<style name="Button" parent="Base.Widget.AppCompat.Button">
<item name="backgroundTint">@color/colorAccent</item>
<item name="android:textColor">@color/colorText</item>
<item name="android:textAlignment">center</item>
</style>
<style name="AnswerButton" parent="Button">
<item name="android:width">300dp</item>
<item name="android:layout_marginBottom">16dp</item>
</style>
<style name="ResultText">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:textAlignment">center</item>
<item name="android:textStyle">bold</item>
</style>
</resources>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="@string/pref_category_sound"
android:title="@string/pref_category_sound_title">
<CheckBoxPreference
android:defaultValue="true"
android:key="@string/pref_sound_answer"
android:title="@string/pref_sound_answer_title" />
</PreferenceCategory>
</PreferenceScreen>