Comments are very welcome
** changes are marked by double quotes **
public class QuizActivity extends AppCompatActivity {
private static final String KEY_INDEX = "index";
private static final String KEY_SCORE = "score";
private static final String KEY_ANSWERED = "answered";
**private static final String KEY_CHEATED = "cheater";**
private static final int REQUEST_CODE_CHEAT = 0;
private static final int QUESTION_GRADE = 1;
private Button mTrueButton;
private Button mFalseButton;
private Button mCheatButton;
private Button mNextButton;
private Button mPrevButton;
private TextView mQuestionTextView;
private Question[] mQuestionBank = new Question[]{
new Question(R.string.question_australia, true),
new Question(R.string.question_oceans, true),
new Question(R.string.question_middleeast, false),
new Question(R.string.question_africa, false),
new Question(R.string.question_americas, true),
new Question(R.string.question_asia, true),
};
private int mCurrentIndex = 0;
private boolean[] mQuestionStatus = new boolean[mQuestionBank.length];
**private boolean[] mCheated = new boolean[mQuestionBank.length];**
private int[] mScore = new int[mQuestionBank.length];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
if (savedInstanceState != null) {
if (savedInstanceState.containsKey(KEY_INDEX)) {
mCurrentIndex = savedInstanceState.getInt(KEY_INDEX);
}
if (savedInstanceState.containsKey(KEY_ANSWERED)) {
mQuestionStatus = savedInstanceState.getBooleanArray(KEY_ANSWERED);
}
if (savedInstanceState.containsKey(KEY_SCORE)) {
mScore = savedInstanceState.getIntArray(KEY_SCORE);
}
if (savedInstanceState.containsKey(KEY_CHEATED)){
**mCheated = savedInstanceState.getBooleanArray(KEY_CHEATED);**
}
}
// question text view
mQuestionTextView = (TextView) findViewById(R.id.question_text_view);
// True button
mTrueButton = (Button) findViewById(R.id.true_button);
mTrueButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkAnswer(true);
}
});
// False button
mFalseButton = (Button) findViewById(R.id.false_button);
mFalseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkAnswer(false);
}
});
// Cheat button
mCheatButton = (Button) findViewById(R.id.cheat_button) ;
mCheatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue();
Intent intent =
CheatActivity.newIntent(QuizActivity.this, answerIsTrue);
startActivityForResult(intent, REQUEST_CODE_CHEAT);
}
});
// Next button
mNextButton = (Button) findViewById(R.id.next_button);
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
nextQuestion();
}
});
// Previous button
mPrevButton = (Button) findViewById(R.id.previous_button);
mPrevButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
previousQuestion();
}
});
// At app run, display the first question
updateQuestion();
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log.d(TAG, "onSaveInstanceState() called");
savedInstanceState.putInt(KEY_INDEX, mCurrentIndex);
savedInstanceState.putBooleanArray(KEY_ANSWERED, mQuestionStatus);
savedInstanceState.putIntArray(KEY_SCORE, mScore);
**savedInstanceState.putBooleanArray(KEY_CHEATED, mCheated);**
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
return;
}
if (requestCode == REQUEST_CODE_CHEAT) {
if (data == null) {
return;
}
**mCheated[mCurrentIndex] = CheatActivity.wasAnswerShown(data);**
}
}
/*
* Updates the text view with the question statement
* corresponding to current index
*/
private void updateQuestion() {
int question = mQuestionBank[mCurrentIndex].getTextResId();
mQuestionTextView.setText(question);
// if question has not been answered already, activate answer buttons
if (!mQuestionStatus[mCurrentIndex]) {
activateAnswerButton();
} else {
deactivateAnswerButton();
}
}
/*
* Display a toast message indicating correctness of user answer
* @param userPressedTrue A falg indicating whether the user answered True
*/
private void checkAnswer(boolean userPressedTrue) {
// Mark question as answered
mQuestionStatus[mCurrentIndex] = true;
deactivateAnswerButton();
int toastResId;
**if (mCheated[mCurrentIndex]) {**
**toastResId = R.string.judgment_toast;**
**mScore[mCurrentIndex] = 0;**
} else {
boolean isCorrectAnswer = userPressedTrue == mQuestionBank[mCurrentIndex].isAnswerTrue();
if (isCorrectAnswer) {
mScore[mCurrentIndex] = QUESTION_GRADE;
toastResId = R.string.correct_toast;
} else {
// when user answered again, report his inccorect answeres(depend on business logic)
mScore[mCurrentIndex] = 0;
toastResId = R.string.incorrect_toast;
}
}
Toast toast = Toast.makeText(QuizActivity.this, toastResId,
Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
if (allAnswered()) {
DisplayScore();
reset();
}
}
/*
* Checks whether the user has answered all the questions
* @return true if the user has answered all questions
*/
private boolean allAnswered() {
for (boolean status : mQuestionStatus) {
if (!status) {
return false;
}
}
return true;
}
/*
* Reset score and answered questions
*/
private void reset() {
// set all questions unanswered
for (int i = 0; i < mQuestionStatus.length ; i++) {
mQuestionStatus[i] = false;
}
**// reset cheating record**
**for (int i = 0; i < mCheated.length ; i++) {**
**mCheated[i] = false;**
**}**
// set all scores to zero
for (int i = 0; i < mScore.length ; i++) {
mScore[i] = 0;
}
}
/*
* Displays the score
*/
private void DisplayScore() {
Toast.makeText(this,
"Score: " + getScore() + "%",
Toast.LENGTH_LONG).show();
}
/*
* Gets the score as a percentage
* @return The score as a double
*/
private double getScore() {
double score = 0;
for (int i = 0; i < mScore.length ; i++) {
score += mScore[i];
}
return (score / mQuestionBank.length) * 100;
}
/*
* Proceeds to next question
*/
private void nextQuestion() {
// keep looping forward in the questions
mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
updateQuestion();
}
/*
* Returns to previous question
*/
private void previousQuestion() {
// keep looping backward in the questions
if(mCurrentIndex == 0) {
mCurrentIndex = mQuestionBank.length - 1;
} else {
mCurrentIndex = mCurrentIndex - 1;
}
updateQuestion();
}
/*
* Deactivates True and False buttons
*/
private void deactivateAnswerButton() {
mTrueButton.setEnabled(false);
mFalseButton.setEnabled(false);
}
/*
* Activates True and False buttons
*/
private void activateAnswerButton() {
mTrueButton.setEnabled(true);
mFalseButton.setEnabled(true);
}
}
public class CheatActivity extends AppCompatActivity {
private static final String EXTRA_ANSWER_IS_TRUE =
"com.bignerdranch.android.geoquiz.answer_is_true";
private static final String EXTRA_ANSWER_SHOWN =
"com.bignerdranch.android.geoquiz.answer_shown";
private static final String KEY_ANSWER_SHOWN = "answer is shown";
private boolean mAnswerIsTrue;
**private boolean mAnswerIsShown;**
private TextView mAnswerTextView;
private Button mShowAnswerButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cheat);
mAnswerIsTrue = getIntent().getBooleanExtra(EXTRA_ANSWER_IS_TRUE, false);
**if (savedInstanceState != null) {**
**if (savedInstanceState.containsKey(KEY_ANSWER_SHOWN)) {**
**mAnswerIsShown = savedInstanceState.getBoolean(KEY_ANSWER_SHOWN);**
**}**
**}**
// Answer TextView
mAnswerTextView = (TextView) findViewById(R.id.answer_text_view);
// Show answer Button
mShowAnswerButton = (Button) findViewById(R.id.show_answer_button);
mShowAnswerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showAnswer();
**mAnswerIsShown = true;**
setAnswerShownResult(mAnswerIsShown);
**mShowAnswerButton.setEnabled(false);**
}
});
**if(mAnswerIsShown) {**
**showAnswer();**
**mShowAnswerButton.setEnabled(false);**
**setAnswerShownResult(mAnswerIsShown);**
**}**
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
**savedInstanceState.putBoolean(KEY_ANSWER_SHOWN, mAnswerIsShown);**
}
/*
* Display the answer
*/
private void showAnswer() {
if(mAnswerIsTrue) {
mAnswerTextView.setText(R.string.true_button);
} else {
mAnswerTextView.setText(R.string.false_button);
}
}
/*
* Creates new intent to create a new CheatActivity object and pass information to it
* @param packageContext The package of CheatActivity clss
* @param answerIsTrue A flag that indicates if the current question statement is true
* @return The intent
*/
public static Intent newIntent(Context packageContext, boolean answerIsTrue) {
Intent intent = new Intent(packageContext, CheatActivity.class);
intent.putExtra(EXTRA_ANSWER_IS_TRUE, answerIsTrue);
return intent;
}
/*
* Determines whether the answer was shawn
* @param result The intent resulting when CheatActivity return to its launcher
* @return A flag indicating whether the answer was shown
*/
public static boolean wasAnswerShown(Intent result) {
return result.getBooleanExtra(EXTRA_ANSWER_SHOWN, false);
}
/*
* Infrom parent Activity whether the user has seen the answer
* @param isAnswerShown A flag to indicate whether the user has seen the answer
*/
private void setAnswerShownResult(boolean isAnswerShown) {
Intent data = new Intent();
data.putExtra(EXTRA_ANSWER_SHOWN, isAnswerShown);
setResult(RESULT_OK, data);
}
}