From 82432f571eaacac770d620a7019e8123ffa34f15 Mon Sep 17 00:00:00 2001 From: Aral1q Date: Thu, 9 Jun 2022 18:30:22 -0700 Subject: [PATCH] Added audio hints, fixed bugs --- .idea/misc.xml | 1 + .idea/vcs.xml | 6 + .../com/example/firstapp/FirstFragment.java | 187 ++++++++++++++---- .../example/firstapp/MainMenuFragment.java | 45 +++++ .../java/com/example/firstapp/Question.java | 11 +- .../com/example/firstapp/SecondFragment.java | 56 ------ app/src/main/res/layout/fragment_first.xml | 11 ++ .../main/res/layout/fragment_main_menu.xml | 20 ++ app/src/main/res/layout/fragment_second.xml | 48 ----- app/src/main/res/navigation/nav_graph.xml | 14 +- app/src/main/res/raw/hint1.mp3 | Bin 0 -> 18429 bytes app/src/main/res/raw/hint2.mp3 | Bin 0 -> 65185 bytes app/src/main/res/raw/hint3.mp3 | Bin 0 -> 16586 bytes app/src/main/res/raw/hint4.mp3 | Bin 0 -> 31572 bytes app/src/main/res/raw/hint5.mp3 | Bin 0 -> 22959 bytes app/src/main/res/values-zh-rCN/strings.xml | 13 +- app/src/main/res/values-zh-rTW/strings.xml | 13 +- app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 12 +- 19 files changed, 266 insertions(+), 172 deletions(-) create mode 100644 .idea/vcs.xml create mode 100644 app/src/main/java/com/example/firstapp/MainMenuFragment.java delete mode 100644 app/src/main/java/com/example/firstapp/SecondFragment.java create mode 100644 app/src/main/res/layout/fragment_main_menu.xml delete mode 100644 app/src/main/res/layout/fragment_second.xml create mode 100644 app/src/main/res/raw/hint1.mp3 create mode 100644 app/src/main/res/raw/hint2.mp3 create mode 100644 app/src/main/res/raw/hint3.mp3 create mode 100644 app/src/main/res/raw/hint4.mp3 create mode 100644 app/src/main/res/raw/hint5.mp3 diff --git a/.idea/misc.xml b/.idea/misc.xml index 603070a..eb9d41c 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,6 +8,7 @@ + diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/firstapp/FirstFragment.java b/app/src/main/java/com/example/firstapp/FirstFragment.java index 50f285b..1d61b5d 100644 --- a/app/src/main/java/com/example/firstapp/FirstFragment.java +++ b/app/src/main/java/com/example/firstapp/FirstFragment.java @@ -1,20 +1,24 @@ package com.example.firstapp; +import android.media.MediaPlayer; import android.os.Bundle; +import android.speech.tts.TextToSpeech; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import androidx.navigation.fragment.NavHostFragment; import com.example.firstapp.databinding.FragmentFirstBinding; import java.util.ArrayList; +import java.util.Locale; import java.util.Random; public class FirstFragment extends Fragment { @@ -23,31 +27,56 @@ public class FirstFragment extends Fragment { private TextView questionTV, questionNumberTV; private ImageView questionImage; - private Button firstBtn, secondBtn, thirdBtn, fourthBtn; + private Button firstBtn, secondBtn, thirdBtn, fourthBtn, menuBtn; private ArrayList quizModalArrayList; - int tempArrayPointer = 0; // For testing purposes, forbid repetitions - Random random; - int score = 0, questionBlockPosition = 0, questionPosition = 0; - boolean firstIncorrect = false; + private TextToSpeech mTTS; + private Random random; + private int score = 0, questionBlockPosition = 0, questionPosition = 0; + private boolean firstIncorrect = false, TTSOn = false; + private MediaPlayer player; // Takes a lot of resources, create only where necessary @Override public View onCreateView( - LayoutInflater inflater, ViewGroup container, + @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { - // Inflate the layout for this fragment + // Inflate the Layout for this Fragment View fragmentFirstLayout = inflater.inflate(R.layout.fragment_first, container, false); - // Get the count text view + // Initialise TextToSpeech + mTTS = new TextToSpeech(getActivity(), new TextToSpeech.OnInitListener() { + @Override + public void onInit(int status) { + if (status == TextToSpeech.SUCCESS) { + int result = mTTS.setLanguage(Locale.UK); + if (result == TextToSpeech.LANG_MISSING_DATA // Check for supported languages + || result == TextToSpeech.LANG_NOT_SUPPORTED) { + Log.e("TTS", "Language not supported"); + } else { + TTSOn = true; + TTSQuestion(); + } + } else { + Log.e("TTS", "Initialisation failed"); + } + } + }); + + // Get the Count and Question TextView questionTV = fragmentFirstLayout.findViewById(R.id.question); questionNumberTV = fragmentFirstLayout.findViewById(R.id.questionNumber); + // Get the Option Buttons firstBtn = fragmentFirstLayout.findViewById(R.id.first_choice); secondBtn = fragmentFirstLayout.findViewById(R.id.second_choice); thirdBtn = fragmentFirstLayout.findViewById(R.id.third_choice); fourthBtn = fragmentFirstLayout.findViewById(R.id.fourth_choice); + menuBtn = fragmentFirstLayout.findViewById(R.id.back_to_menu); + // Get the Image questionImage = fragmentFirstLayout.findViewById(R.id.imageView); + + // Get the Questions quizModalArrayList = new ArrayList<>(); random = new Random(); - getQuizQuestion(quizModalArrayList); + getQuizQuestion(quizModalArrayList); // Populate ArrayList with questions questionBlockPosition = random.nextInt(quizModalArrayList.size()); setDataToViews(); firstBtn.setOnClickListener(v -> { @@ -62,10 +91,17 @@ public View onCreateView( fourthBtn.setOnClickListener(v -> { optionAction(quizModalArrayList, fourthBtn, v); }); + menuBtn.setOnClickListener(v -> { + NavHostFragment.findNavController(FirstFragment.this) + .navigate(R.id.action_FirstFragment_to_MainMenuFragment); + }); return fragmentFirstLayout; } + // Description: Updates Image, Options, QuestionTV after new Question is chosen. + // Precondition: - + // Postcondition: TextViews and Image are updated. private void setDataToViews() { firstBtn.setEnabled(true); secondBtn.setEnabled(true); @@ -76,76 +112,149 @@ private void setDataToViews() { if (questionPosition == 5) { quizModalArrayList.remove(questionBlockPosition); if (quizModalArrayList.size() == 0) { - firstBtn.setEnabled(false); - secondBtn.setEnabled(false); - thirdBtn.setEnabled(false); - fourthBtn.setEnabled(false); + firstBtn.setVisibility(View.GONE); + secondBtn.setVisibility(View.GONE); + thirdBtn.setVisibility(View.GONE); + fourthBtn.setVisibility(View.GONE); questionTV.setText(getString(R.string.answered_all_questions)); + TTSQuestion(); + menuBtn.setVisibility(View.VISIBLE); return; } questionBlockPosition = random.nextInt(quizModalArrayList.size()); questionPosition = 0; } questionImage.setImageResource(quizModalArrayList.get(questionBlockPosition).getImage()); - questionTV.setText(quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getQuestion()); firstBtn.setText(quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getFirst()); secondBtn.setText(quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getSecond()); thirdBtn.setText(quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getThird()); fourthBtn.setText(quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getFourth()); + questionTV.setText(quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getQuestion()); + TTSQuestion(); } - private void optionAction(ArrayList quizModalArrayList, Button button, View v) { + // Description: Increases Score, reduces number of Options, provides Hint, + // sets next Question. + // Precondition: - + // Postcondition: Fam I don't even know what to write here atm + private void optionAction(@NonNull ArrayList quizModalArrayList, @NonNull Button button, View v) { + stopPlayer(player); + mTTS.stop(); if(quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getAnswer().trim().equalsIgnoreCase(button.getText().toString().trim())) { ++score; ++questionPosition; setDataToViews(); - } else if (firstIncorrect == false) { + } else if (!firstIncorrect) { firstIncorrect = true; button.setEnabled(false); - displayToastHint(v, quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getHint()); - // TOAST HINT - // Temporary method of delivering hints - // Could edit style of toast and make it more dementia friendly instead of using textviews - // Toast.makeText(getActivity(), quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getHint(), Toast.LENGTH_SHORT).show(); + TTSQuestion(); } else { ++questionPosition; setDataToViews(); } } - private void displayToastHint(View v, String hint) { - Toast.makeText(getActivity(), hint, Toast.LENGTH_SHORT).show(); + // Description: TTS of Question and Options on first iteration, + // Hint and remaining Options after incorrect answer. + // Precondition: TTS option is ON in settings + // Postcondition: TTS appropriate text strings + private void TTSQuestion() { + stopPlayer(player); + System.out.println("The value of TTSOn = " + TTSOn); + if (!TTSOn) { + return; + } + mTTS.setPitch((float)1); + mTTS.setSpeechRate((float)1); + if (!firstIncorrect) + mTTS.speak(questionTV.getText().toString(), TextToSpeech.QUEUE_ADD, null); + if (firstIncorrect) { + mTTS.speak("Hint: ", TextToSpeech.QUEUE_ADD, null); + player = MediaPlayer.create(getActivity(), quizModalArrayList.get(questionBlockPosition).getQuestionArray(questionPosition).getHint()); + player.start(); + player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + stopPlayer(mediaPlayer); + TTSQuestionButton(firstBtn, 1); + TTSQuestionButton(secondBtn, 2); + TTSQuestionButton(thirdBtn, 3); + TTSQuestionButton(fourthBtn, 4); + } + }); + } + else { + TTSQuestionButton(firstBtn, 1); + TTSQuestionButton(secondBtn, 2); + TTSQuestionButton(thirdBtn, 3); + TTSQuestionButton(fourthBtn, 4); + } + } + + // Description: TTS Options, indicates Options of text string. + // Precondition: button is enabled + // Postcondition: TTS appropriate text strings, highlighting Option + // of text string + // Exceptions: Throws TTSSleepInterruptedException if sleep() got interrupted. + private void TTSQuestionButton(@NonNull Button button, int i) { + // BUG: Colour changes despite button being disabled + // IMPLEMENT: Highlight button while speak() is in progress + System.out.println(i + "is active: " + button.isEnabled()); + if (button.isEnabled() && button.getVisibility() == View.VISIBLE) { + //button.setTextColor(getResources().getColor(R.color.highlight_button)); + mTTS.speak("Option" + i + ":" + button.getText().toString(), TextToSpeech.QUEUE_ADD, null); + //button.setTextColor(getResources().getColor(R.color.white)); + } } + // Description: Populates quizModalArrayList with questions. + // Precondition: - + // Postcondition: quizModalArray populated with questions private void getQuizQuestion(ArrayList quizModalArrayList) { - Question questionOne = new Question("Who is it?", "Mum", "Mate", "Me", "Cornershop bossman", "Me", "It's you"); - Question questionTwo = new Question("How old is he?", "16", "2", "9", "74", "74", "You're pretty old"); - Question questionThree = new Question("What's his ethnicity?", "Asian", "Caucasian", "Mongol", "Kyrgyz", "Asian", "You're from China"); - Question questionFour = new Question("His favourite UK rapper?", "Skepta", "Wiley", "Stormzy", "Himself", "Himself", "You were drilling on regs"); - Question questionFive = new Question("It's Unknown T", "Homerton B", "Gyalie on me", "Op block", "Bali on me", "Homerton B", "Homerton B"); + Question questionOne = new Question("Who is it?", "Mum", "Mate", "Me", "Cornershop bossman", "Me", R.raw.hint1); + Question questionTwo = new Question("How old is he?", "16", "2", "9", "74", "74", R.raw.hint2); + Question questionThree = new Question("What's his ethnicity?", "Asian", "Caucasian", "Mongol", "Kyrgyz", "Asian", R.raw.hint3); + Question questionFour = new Question("His favourite UK rapper?", "Skepta", "Wiley", "Stormzy", "Himself", "Himself", R.raw.hint4); + Question questionFive = new Question("It's Unknown T", "Homerton B", "Gyalie on me", "Op block", "Bali on me", "Homerton B", R.raw.hint5); quizModalArrayList.add(new QuestionBlock(questionOne, questionTwo, questionThree, questionFour, questionFive, R.drawable.daboy)); - questionOne = new Question("Dat boy is who?", "Future doc", "My G", "Taiwanren", "Burnaby S boy", "Taiwanren", "He is from Taiwan"); - questionTwo = new Question("City of birth?", "Tainan", "Taipei", "Taichung", "Taoyuan", "Tainan", "He's from the South"); - questionThree = new Question("Calculus 12 grade?", "A", "A+", "A++", "A+++", "A+++", "He's really smart"); - questionFour = new Question("Most complex 漢字 in Unicode?", "\uD869\uDEA5", "\uD869\uDEA3", "\uD869\uDEA4", "\uD869\uDEA2", "\uD869\uDEA5", "Ye you can't really see them innit"); - questionFive = new Question("Anthem of Taiwan?", "San Min Zhuyi", "Yiyongjun Jinxingqu", "Gong Jin'ou", "Wuzu gonghe ge", "San Min Zhuyi", "three"); + questionOne = new Question("Dat boy is who?", "Future doc", "My G", "Taiwanren", "Burnaby S boy", "Taiwanren", R.raw.hint1); + questionTwo = new Question("City of birth?", "Tainan", "Taipei", "Taichung", "Taoyuan", "Tainan", R.raw.hint2); + questionThree = new Question("Calculus 12 grade?", "A", "A+", "A++", "A+++", "A+++", R.raw.hint3); + questionFour = new Question("Most complex 漢字 in Unicode?", "\uD869\uDEA5", "\uD869\uDEA3", "\uD869\uDEA4", "\uD869\uDEA2", "\uD869\uDEA5", R.raw.hint4); + questionFive = new Question("Anthem of Taiwan?", "San Min Zhuyi", "Yiyongjun Jinxingqu", "Gong Jin'ou", "Wuzu gonghe ge", "San Min Zhuyi", R.raw.hint5); quizModalArrayList.add(new QuestionBlock(questionOne, questionTwo, questionThree, questionFour, questionFive, R.drawable.taiwanren)); - questionOne = new Question("Who dat?", "My mate on teli", "Trump", "MP of UK", "Alien", "My mate on teli", "He's on teli"); - questionTwo = new Question("What is he famous for?", "Tallest man", "Nothing", "best nba player", "Everything", "Nothing", "Nobody knows him"); - questionThree = new Question("It's 3 am I wanna go sleep", "The last", "Questions", "Won't make", "Any sense", "Any sense", "Yes"); - questionFour = new Question("?", "=(", "=)", "=/", "=|", "=)", "Happy la"); - questionFive = new Question("Best anime?", "Boku no piku", "Initial D", "Oreimo", "Pokemon", "Initial D", "Anime about cars"); + questionOne = new Question("Who dat?", "My mate on teli", "Trump", "MP of UK", "Alien", "My mate on teli", R.raw.hint1); + questionTwo = new Question("What is he famous for?", "Tallest man", "Nothing", "best nba player", "Everything", "Nothing", R.raw.hint2); + questionThree = new Question("It's 3 am I wanna go sleep", "The last", "Questions", "Won't make", "Any sense", "Any sense", R.raw.hint3); + questionFour = new Question("?", "=(", "=)", "=/", "=|", "=)", R.raw.hint4); + questionFive = new Question("Best anime?", "Boku no piku", "Initial D", "Oreimo", "Pokemon", "Initial D", R.raw.hint5); quizModalArrayList.add(new QuestionBlock(questionOne, questionTwo, questionThree, questionFour, questionFive, R.drawable.teliman)); + } public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); } + // Description: Deallocates resources allocated for mediaPlayer + // Precondition: mediaPlayer exists + // Postcondition: Resources are released + private void stopPlayer(MediaPlayer mediaPlayer) { + if (mediaPlayer != null) + mediaPlayer.release(); + } + + // Description: Disconnects from TTS engine + // Precondition: mTTS exists + // Postcondition: App disconnected from TTS engine @Override public void onDestroyView() { + if (mTTS != null) { + mTTS.stop(); + mTTS.shutdown(); + } super.onDestroyView(); binding = null; } diff --git a/app/src/main/java/com/example/firstapp/MainMenuFragment.java b/app/src/main/java/com/example/firstapp/MainMenuFragment.java new file mode 100644 index 0000000..43c71dc --- /dev/null +++ b/app/src/main/java/com/example/firstapp/MainMenuFragment.java @@ -0,0 +1,45 @@ +package com.example.firstapp; + +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 androidx.navigation.fragment.NavHostFragment; + +import com.example.firstapp.databinding.FragmentMainMenuBinding; + +import java.util.Random; + +public class MainMenuFragment extends Fragment { + +private FragmentMainMenuBinding binding; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + binding = FragmentMainMenuBinding.inflate(inflater, container, false); + return binding.getRoot(); + } + + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + view.findViewById(R.id.quiz_button).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + NavHostFragment.findNavController(MainMenuFragment.this) + .navigate(R.id.action_MainMenuFragment_to_FirstFragment); + } + }); + } + +@Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/firstapp/Question.java b/app/src/main/java/com/example/firstapp/Question.java index 66aefe4..2bf5c9b 100644 --- a/app/src/main/java/com/example/firstapp/Question.java +++ b/app/src/main/java/com/example/firstapp/Question.java @@ -1,10 +1,13 @@ package com.example.firstapp; +import java.io.File; + public class Question { - private String question, first, second, third, fourth, answer, hint; + private String question, first, second, third, fourth, answer; + private int hint; // Constructor - public Question(String question, String first, String second, String third, String fourth, String answer, String hint) { + public Question(String question, String first, String second, String third, String fourth, String answer, int hint) { this.question = question; this.first = first; this.second = second; @@ -63,11 +66,11 @@ public void setAnswer(String answer) { this.answer = answer; } - public String getHint() { + public int getHint() { return hint; } - public void setHint(String hint) { + public void setHint(int hint) { this.hint = hint; } } diff --git a/app/src/main/java/com/example/firstapp/SecondFragment.java b/app/src/main/java/com/example/firstapp/SecondFragment.java deleted file mode 100644 index 8f229c8..0000000 --- a/app/src/main/java/com/example/firstapp/SecondFragment.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.example.firstapp; - -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 androidx.navigation.fragment.NavHostFragment; -import com.example.firstapp.databinding.FragmentSecondBinding; - -import java.util.Random; - -public class SecondFragment extends Fragment { - -private FragmentSecondBinding binding; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - binding = FragmentSecondBinding.inflate(inflater, container, false); - return binding.getRoot(); - } - - public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - Integer count = SecondFragmentArgs.fromBundle(getArguments()).getMyArg(); - String countText = getString(R.string.random_heading, count); - TextView headerView = view.getRootView().findViewById(R.id.textview_header); - headerView.setText(countText); - Random random = new java.util.Random(); - Integer randomNumber = 0; - if (count > 0) { - randomNumber = random.nextInt(count+1); - } - TextView randomView = view.getRootView().findViewById(R.id.textview_random); - randomView.setText(randomNumber.toString()); - - binding.buttonSecond.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - NavHostFragment.findNavController(SecondFragment.this) - .navigate(R.id.action_SecondFragment_to_FirstFragment); - } - }); - } - -@Override - public void onDestroyView() { - super.onDestroyView(); - binding = null; - } - -} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_first.xml b/app/src/main/res/layout/fragment_first.xml index eae93db..3d28167 100644 --- a/app/src/main/res/layout/fragment_first.xml +++ b/app/src/main/res/layout/fragment_first.xml @@ -91,4 +91,15 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> +