mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 21:03:54 +01:00
Merge gamification branch with master (#1752)
* Quiz (#1629) * Layout inflated * Layout for mcq added * Inflated Basic Layout * Implemented basic flow * Added the basic implementation pf score * Added the result layout * Added the result layout * Added functionality to set result * Changed the launcher intent to Quiz Activity for testing purpose * Explanations of answers added * Improved the layout of quiz result a bit * Fixed some minor issues * Fixed build issues * Api Added and basic structure for calling implemented * Added intents * Added the title * Fixed image error and improved quality of pr * Made separate class for checking quiz * Added counter * Implemented back and next for quiz result * Added back functionality to quiz * Added progressBar * Fixed bugs * Improved code quality * Imporved code Quality * Updated strings * Added share screenshot function * Added checks and improved UI * Removed unused string * Removed unused string * Adding checks and improving code quality * Changed string * Improved code quality * Update strings.xml * Update MediaWikiApi.java * Fix build
This commit is contained in:
parent
80068f7e9f
commit
386bd0a106
21 changed files with 1067 additions and 8 deletions
|
|
@ -9,6 +9,7 @@ import com.viewpagerindicator.CirclePageIndicator;
|
|||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import fr.free.nrw.commons.quiz.QuizActivity;
|
||||
import fr.free.nrw.commons.theme.BaseActivity;
|
||||
|
||||
public class WelcomeActivity extends BaseActivity {
|
||||
|
|
@ -17,6 +18,7 @@ public class WelcomeActivity extends BaseActivity {
|
|||
@BindView(R.id.welcomePagerIndicator) CirclePageIndicator indicator;
|
||||
|
||||
private WelcomePagerAdapter adapter = new WelcomePagerAdapter();
|
||||
private boolean isQuiz;
|
||||
|
||||
/**
|
||||
* Initialises exiting fields and dependencies
|
||||
|
|
@ -28,6 +30,15 @@ public class WelcomeActivity extends BaseActivity {
|
|||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_welcome);
|
||||
|
||||
if(getIntent() != null) {
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
if (bundle != null) {
|
||||
isQuiz = bundle.getBoolean("isQuiz");
|
||||
}
|
||||
} else{
|
||||
isQuiz = false;
|
||||
}
|
||||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
pager.setAdapter(adapter);
|
||||
|
|
@ -40,6 +51,10 @@ public class WelcomeActivity extends BaseActivity {
|
|||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if(isQuiz){
|
||||
Intent i = new Intent(WelcomeActivity.this, QuizActivity.class);
|
||||
startActivity(i);
|
||||
}
|
||||
adapter.setCallback(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ public class AchievementsActivity extends NavigationBaseActivity {
|
|||
private void setRevertCount(){
|
||||
if(checkAccount()) {
|
||||
compositeDisposable.add(mediaWikiApi
|
||||
.getRevertCount(sessionManager.getCurrentAccount().name)
|
||||
.getRevertRespObjectSingle(sessionManager.getCurrentAccount().name)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package fr.free.nrw.commons.contributions;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
|
@ -34,8 +35,10 @@ import fr.free.nrw.commons.auth.AuthenticatedActivity;
|
|||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import fr.free.nrw.commons.quiz.QuizChecker;
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
import fr.free.nrw.commons.upload.UploadService;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
|
@ -137,10 +140,17 @@ public class ContributionsActivity
|
|||
|
||||
getSupportLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
requestAuthToken();
|
||||
initDrawer();
|
||||
setTitle(getString(R.string.title_activity_contributions));
|
||||
|
||||
|
||||
if(checkAccount()) {
|
||||
new QuizChecker(this,
|
||||
sessionManager.getCurrentAccount().name,
|
||||
mediaWikiApi);
|
||||
}
|
||||
if(!BuildConfig.FLAVOR.equalsIgnoreCase("beta")){
|
||||
setUploadCount();
|
||||
}
|
||||
|
|
@ -338,6 +348,21 @@ public class ContributionsActivity
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* to ensure user is logged in
|
||||
* @return
|
||||
*/
|
||||
private boolean checkAccount() {
|
||||
Account currentAccount = sessionManager.getCurrentAccount();
|
||||
if (currentAccount == null) {
|
||||
Timber.d("Current account is null");
|
||||
ViewUtil.showLongToast(this, getResources().getString(R.string.user_not_logged_in));
|
||||
sessionManager.forceLogin(this);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackStackChanged() {
|
||||
initBackButton();
|
||||
|
|
|
|||
|
|
@ -894,6 +894,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
}
|
||||
|
||||
/**
|
||||
|
||||
* Checks to see if a user is currently blocked from Commons
|
||||
* @return whether or not the user is blocked from Commons
|
||||
*/
|
||||
|
|
@ -964,7 +965,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public Single<JSONObject> getRevertCount(String userName){
|
||||
public Single<JSONObject> getRevertRespObjectSingle(String userName){
|
||||
final String fetchRevertCountUrlTemplate =
|
||||
wikiMediaToolforgeUrl + "urbanecmbot/commonsmisc/feedback.py";
|
||||
return Single.fromCallable(() -> {
|
||||
|
|
|
|||
|
|
@ -97,14 +97,14 @@ public interface MediaWikiApi {
|
|||
@NonNull
|
||||
Single<Integer> getUploadCount(String userName);
|
||||
|
||||
@NonNull
|
||||
Single<JSONObject> getRevertRespObjectSingle(String userName);
|
||||
|
||||
boolean isUserBlockedFromCommons();
|
||||
|
||||
@NonNull
|
||||
Single<JSONObject> getAchievements(String userName);
|
||||
|
||||
@NonNull
|
||||
Single<JSONObject> getRevertCount(String userName);
|
||||
|
||||
interface ProgressListener {
|
||||
void onProgress(long transferred, long total);
|
||||
}
|
||||
|
|
|
|||
165
app/src/main/java/fr/free/nrw/commons/quiz/QuizActivity.java
Normal file
165
app/src/main/java/fr/free/nrw/commons/quiz/QuizActivity.java
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
package fr.free.nrw.commons.quiz;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.graphics.drawable.VectorDrawableCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.drawable.ProgressBarDrawable;
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
||||
|
||||
public class QuizActivity extends AppCompatActivity {
|
||||
|
||||
@BindView(R.id.question_image) SimpleDraweeView imageView;
|
||||
@BindView(R.id.question_text) TextView questionText;
|
||||
@BindView(R.id.question_title) TextView questionTitle;
|
||||
@BindView(R.id.quiz_positive_answer) RadioButton positiveAnswer;
|
||||
@BindView(R.id.quiz_negative_answer) RadioButton negativeAnswer;
|
||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||
|
||||
private QuizController quizController = new QuizController();
|
||||
private ArrayList<QuizQuestion> quiz = new ArrayList<QuizQuestion>();
|
||||
private int questionIndex = 0;
|
||||
private int score;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_quiz);
|
||||
Fresco.initialize(this);
|
||||
|
||||
quizController.initialize(this);
|
||||
ButterKnife.bind(this);
|
||||
setSupportActionBar(toolbar);
|
||||
displayQuestion();
|
||||
}
|
||||
|
||||
/**
|
||||
* to move to next question and check whether answer is selected or not
|
||||
*/
|
||||
@OnClick(R.id.next_button)
|
||||
public void setNextQuestion(){
|
||||
if( questionIndex <= quiz.size() && (positiveAnswer.isChecked() || negativeAnswer.isChecked())) {
|
||||
evaluateScore();
|
||||
} else if ( !positiveAnswer.isChecked() && !negativeAnswer.isChecked()){
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this);
|
||||
alert.setTitle(getResources().getString(R.string.warning));
|
||||
alert.setMessage(getResources().getString(R.string.warning_for_no_answer));
|
||||
alert.setPositiveButton(R.string.continue_message, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = alert.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* to give warning before ending quiz
|
||||
*/
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this);
|
||||
alert.setTitle(getResources().getString(R.string.warning));
|
||||
alert.setMessage(getResources().getString(R.string.quiz_back_button));
|
||||
alert.setPositiveButton(R.string.continue_message, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent i = new Intent(QuizActivity.this, QuizResultActivity.class);
|
||||
dialog.dismiss();
|
||||
i.putExtra("QuizResult",score);
|
||||
startActivity(i);
|
||||
}
|
||||
});
|
||||
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
dialogInterface.dismiss();
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = alert.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* to display the question
|
||||
*/
|
||||
public void displayQuestion() {
|
||||
quiz = quizController.getQuiz();
|
||||
questionText.setText(quiz.get(questionIndex).getQuestion());
|
||||
questionTitle.setText(getResources().getString(R.string.question)+quiz.get(questionIndex).getQuestionNumber());
|
||||
imageView.setHierarchy(GenericDraweeHierarchyBuilder
|
||||
.newInstance(getResources())
|
||||
.setFailureImage(VectorDrawableCompat.create(getResources(),
|
||||
R.drawable.ic_error_outline_black_24dp, getTheme()))
|
||||
.setProgressBarImage(new ProgressBarDrawable())
|
||||
.build());
|
||||
|
||||
imageView.setImageURI(quiz.get(questionIndex).getUrl());
|
||||
new RadioGroupHelper(this, R.id.quiz_positive_answer, R.id.quiz_negative_answer);
|
||||
positiveAnswer.setChecked(false);
|
||||
negativeAnswer.setChecked(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* to evaluate score and check whether answer is correct or wrong
|
||||
*/
|
||||
public void evaluateScore() {
|
||||
if((quiz.get(questionIndex).isAnswer() && positiveAnswer.isChecked()) ||
|
||||
(!quiz.get(questionIndex).isAnswer() && negativeAnswer.isChecked()) ){
|
||||
customAlert(getResources().getString(R.string.correct),quiz.get(questionIndex).getAnswerMessage() );
|
||||
score++;
|
||||
} else{
|
||||
customAlert(getResources().getString(R.string.wrong), quiz.get(questionIndex).getAnswerMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* to display explanation after each answer, update questionIndex and move to next question
|
||||
* @param title
|
||||
* @param Message
|
||||
*/
|
||||
public void customAlert(String title, String Message) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this);
|
||||
alert.setTitle(title);
|
||||
alert.setMessage(Message);
|
||||
alert.setPositiveButton(R.string.continue_message, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
questionIndex++;
|
||||
if(questionIndex == quiz.size()){
|
||||
Intent i = new Intent(QuizActivity.this, QuizResultActivity.class);
|
||||
dialog.dismiss();
|
||||
i.putExtra("QuizResult",score);
|
||||
startActivity(i);
|
||||
}else {
|
||||
displayQuestion();
|
||||
}
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = alert.create();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
160
app/src/main/java/fr/free/nrw/commons/quiz/QuizChecker.java
Normal file
160
app/src/main/java/fr/free/nrw/commons/quiz/QuizChecker.java
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
package fr.free.nrw.commons.quiz;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.v7.app.AlertDialog.Builder;
|
||||
import android.util.Log;
|
||||
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.WelcomeActivity;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* fetches the number of images uploaded and number of images reverted.
|
||||
* Then it calculates the percentage of the images reverted
|
||||
* if the percentage of images reverted after last quiz exceeds 50% and number of images uploaded is
|
||||
* greater than 50, then quiz is popped up
|
||||
*/
|
||||
public class QuizChecker {
|
||||
|
||||
private int revertCount ;
|
||||
private int totalUploadCount ;
|
||||
private boolean isRevertCountFetched;
|
||||
private boolean isUploadCountFetched;
|
||||
private CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
public Context context;
|
||||
private String userName;
|
||||
private MediaWikiApi mediaWikiApi;
|
||||
private SharedPreferences revertPref;
|
||||
private SharedPreferences countPref;
|
||||
|
||||
private final int UPLOAD_COUNT_THRESHOLD = 5;
|
||||
private final String REVERT_PERCENTAGE_FOR_MESSAGE = "50%";
|
||||
private final String REVERT_SHARED_PREFERENCE = "revertCount";
|
||||
private final String UPLOAD_SHARED_PREFERENCE = "uploadCount";
|
||||
|
||||
/**
|
||||
* constructor to set the parameters for quiz
|
||||
* @param context
|
||||
* @param userName
|
||||
* @param mediaWikiApi
|
||||
*/
|
||||
public QuizChecker(Context context, String userName, MediaWikiApi mediaWikiApi) {
|
||||
this.context = context;
|
||||
this.userName = userName;
|
||||
this.mediaWikiApi = mediaWikiApi;
|
||||
revertPref = context.getSharedPreferences(REVERT_SHARED_PREFERENCE, Context.MODE_PRIVATE);
|
||||
countPref = context.getSharedPreferences(UPLOAD_SHARED_PREFERENCE,Context.MODE_PRIVATE);
|
||||
setUploadCount();
|
||||
setRevertCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* to fet the total number of images uploaded
|
||||
*/
|
||||
private void setUploadCount() {
|
||||
compositeDisposable.add(mediaWikiApi
|
||||
.getUploadCount(userName)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
uploadCount -> setTotalUploadCount(uploadCount),
|
||||
t -> Timber.e(t, "Fetching upload count failed")
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* set the sub Title of Contibutions Activity and
|
||||
* call function to check for quiz
|
||||
* @param uploadCount
|
||||
*/
|
||||
private void setTotalUploadCount(int uploadCount) {
|
||||
totalUploadCount = uploadCount - countPref.getInt(UPLOAD_SHARED_PREFERENCE,0);
|
||||
if( totalUploadCount < 0){
|
||||
totalUploadCount = 0;
|
||||
countPref.edit().putInt(UPLOAD_SHARED_PREFERENCE,0).apply();
|
||||
}
|
||||
isUploadCountFetched = true;
|
||||
calculateRevertParameter();
|
||||
}
|
||||
|
||||
/**
|
||||
* To call the API to get reverts count in form of JSONObject
|
||||
*/
|
||||
private void setRevertCount() {
|
||||
compositeDisposable.add(mediaWikiApi
|
||||
.getRevertRespObjectSingle(userName)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
object -> setRevertParameter(object.getInt("deletedUploads"))
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* to calculate the number of images reverted after previous quiz
|
||||
* @param revertCountFetched
|
||||
*/
|
||||
private void setRevertParameter(int revertCountFetched) {
|
||||
revertCount = revertCountFetched - revertPref.getInt(REVERT_SHARED_PREFERENCE,0);
|
||||
if(revertCount < 0){
|
||||
revertCount = 0;
|
||||
revertPref.edit().putInt(REVERT_SHARED_PREFERENCE, 0).apply();
|
||||
}
|
||||
isRevertCountFetched = true;
|
||||
calculateRevertParameter();
|
||||
}
|
||||
|
||||
/**
|
||||
* to check whether the criterion to call quiz is satisfied
|
||||
*/
|
||||
private void calculateRevertParameter() {
|
||||
if( revertCount < 0 || totalUploadCount < 0){
|
||||
revertPref.edit().putInt(REVERT_SHARED_PREFERENCE, 0).apply();
|
||||
countPref.edit().putInt(UPLOAD_SHARED_PREFERENCE,0).apply();
|
||||
return;
|
||||
}
|
||||
if (isRevertCountFetched && isUploadCountFetched &&
|
||||
totalUploadCount >= UPLOAD_COUNT_THRESHOLD &&
|
||||
(revertCount * 100) / totalUploadCount >= 50) {
|
||||
callQuiz();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alert which prompts to quiz
|
||||
*/
|
||||
public void callQuiz() {
|
||||
Builder alert = new Builder(context);
|
||||
alert.setTitle(context.getResources().getString(R.string.quiz));
|
||||
alert.setMessage(context.getResources().getString(R.string.quiz_alert_message,
|
||||
REVERT_PERCENTAGE_FOR_MESSAGE));
|
||||
alert.setPositiveButton("Proceed", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
int newRevetSharedPrefs = revertCount+ revertPref.getInt(REVERT_SHARED_PREFERENCE,0);
|
||||
revertPref.edit().putInt(REVERT_SHARED_PREFERENCE, newRevetSharedPrefs).apply();
|
||||
int newUploadCount = totalUploadCount + countPref.getInt(UPLOAD_SHARED_PREFERENCE,0);
|
||||
countPref.edit().putInt(UPLOAD_SHARED_PREFERENCE,newUploadCount).apply();
|
||||
Intent i = new Intent(context, WelcomeActivity.class);
|
||||
i.putExtra("isQuiz", true);
|
||||
dialog.dismiss();
|
||||
context.startActivity(i);
|
||||
}
|
||||
});
|
||||
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
dialogInterface.cancel();
|
||||
}
|
||||
});
|
||||
android.support.v7.app.AlertDialog dialog = alert.create();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package fr.free.nrw.commons.quiz;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import butterknife.BindView;
|
||||
import fr.free.nrw.commons.R;
|
||||
|
||||
/**
|
||||
* controls the quiz in the Activity
|
||||
*/
|
||||
public class QuizController {
|
||||
|
||||
ArrayList<QuizQuestion> quiz = new ArrayList<QuizQuestion>();
|
||||
|
||||
private final String URL_FOR_SELFIE = "https://i.imgur.com/0fMYcpM.jpg";
|
||||
private final String URL_FOR_TAJ_MAHAL = "https://upload.wikimedia.org/wikipedia/commons/1/15/Taj_Mahal-03.jpg";
|
||||
private final String URL_FOR_BLURRY_IMAGE = "https://i.imgur.com/Kepb5jR.jpg";
|
||||
private final String URL_FOR_SCREENSHOT = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Social_media_app_mockup_screenshot.svg/500px-Social_media_app_mockup_screenshot.svg.png";
|
||||
private final String URL_FOR_EVENT = "https://upload.wikimedia.org/wikipedia/commons/5/51/HouseBuildingInNorthernVietnam.jpg";
|
||||
|
||||
public void initialize(Context context){
|
||||
QuizQuestion q1 = new QuizQuestion(1,
|
||||
context.getResources().getString(R.string.quiz_question_string),
|
||||
URL_FOR_SELFIE,
|
||||
false,
|
||||
context.getResources().getString(R.string.selfie_answer));
|
||||
quiz.add(q1);
|
||||
|
||||
QuizQuestion q2 = new QuizQuestion(2,
|
||||
context.getResources().getString(R.string.quiz_question_string),
|
||||
URL_FOR_TAJ_MAHAL,
|
||||
true,
|
||||
context.getResources().getString(R.string.taj_mahal_answer));
|
||||
quiz.add(q2);
|
||||
|
||||
QuizQuestion q3 = new QuizQuestion(3,
|
||||
context.getResources().getString(R.string.quiz_question_string),
|
||||
URL_FOR_BLURRY_IMAGE,
|
||||
false,
|
||||
context.getResources().getString(R.string.blurry_image_answer));
|
||||
quiz.add(q3);
|
||||
|
||||
QuizQuestion q4 = new QuizQuestion(4,
|
||||
context.getResources().getString(R.string.quiz_question_string),
|
||||
URL_FOR_SCREENSHOT,
|
||||
false,
|
||||
context.getResources().getString(R.string.screenshot_answer));
|
||||
quiz.add(q4);
|
||||
|
||||
QuizQuestion q5 = new QuizQuestion(5,
|
||||
context.getResources().getString(R.string.quiz_question_string),
|
||||
URL_FOR_EVENT,
|
||||
true,
|
||||
context.getResources().getString(R.string.construction_event_answer));
|
||||
quiz.add(q5);
|
||||
|
||||
}
|
||||
|
||||
public ArrayList<QuizQuestion> getQuiz() {
|
||||
return quiz;
|
||||
}
|
||||
}
|
||||
62
app/src/main/java/fr/free/nrw/commons/quiz/QuizQuestion.java
Normal file
62
app/src/main/java/fr/free/nrw/commons/quiz/QuizQuestion.java
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
package fr.free.nrw.commons.quiz;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* class contains information about all the quiz questions
|
||||
*/
|
||||
public class QuizQuestion {
|
||||
private int questionNumber;
|
||||
private String question;
|
||||
private boolean answer;
|
||||
private String url;
|
||||
private String answerMessage;
|
||||
|
||||
QuizQuestion(int questionNumber, String question, String url, boolean answer, String answerMessage){
|
||||
this.questionNumber = questionNumber;
|
||||
this.question = question;
|
||||
this.url = url;
|
||||
this.answer = answer;
|
||||
this.answerMessage = answerMessage;
|
||||
}
|
||||
|
||||
public Uri getUrl() {
|
||||
return Uri.parse(url);
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public boolean isAnswer() {
|
||||
return answer;
|
||||
}
|
||||
|
||||
public int getQuestionNumber() {
|
||||
return questionNumber;
|
||||
}
|
||||
|
||||
public String getQuestion() {
|
||||
return question;
|
||||
}
|
||||
|
||||
public void setAnswer(boolean answer) {
|
||||
this.answer = answer;
|
||||
}
|
||||
|
||||
public void setQuestion(String question) {
|
||||
this.question = question;
|
||||
}
|
||||
|
||||
public void setQuestionNumber(int questionNumber) {
|
||||
this.questionNumber = questionNumber;
|
||||
}
|
||||
|
||||
public String getAnswerMessage() {
|
||||
return answerMessage;
|
||||
}
|
||||
|
||||
public void setAnswerMessage(String answerMessage) {
|
||||
this.answerMessage = answerMessage;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
package fr.free.nrw.commons.quiz;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.dinuscxj.progressbar.CircleProgressBar;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
||||
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
/**
|
||||
* Displays the final score of quiz and congratulates the user
|
||||
*/
|
||||
public class QuizResultActivity extends AppCompatActivity {
|
||||
|
||||
@BindView(R.id.result_progress_bar) CircleProgressBar resultProgressBar;
|
||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||
@BindView(R.id.congratulatory_message) TextView congratulatoryMessageText;
|
||||
|
||||
private final int NUMBER_OF_QUESTIONS = 5;
|
||||
private final int MULTIPLIER_TO_GET_PERCENTAGE = 20;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_quiz_result);
|
||||
|
||||
ButterKnife.bind(this);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
if( getIntent() != null) {
|
||||
Bundle extras = getIntent().getExtras();
|
||||
int score = extras.getInt("QuizResult");
|
||||
setScore(score);
|
||||
}else{
|
||||
startActivityWithFlags(
|
||||
this, ContributionsActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* to calculate and display percentage and score
|
||||
* @param score
|
||||
*/
|
||||
public void setScore(int score) {
|
||||
int per = score * MULTIPLIER_TO_GET_PERCENTAGE;
|
||||
resultProgressBar.setProgress(per);
|
||||
resultProgressBar.setProgressTextFormatPattern(score +" / " + NUMBER_OF_QUESTIONS);
|
||||
String message = getResources().getString(R.string.congratulatory_message_quiz,per + "%");
|
||||
congratulatoryMessageText.setText(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* to go to Contibutions Activity
|
||||
*/
|
||||
@OnClick(R.id.quiz_result_next)
|
||||
public void launchContributionActivity(){
|
||||
startActivityWithFlags(
|
||||
this, ContributionsActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
startActivityWithFlags(
|
||||
this, ContributionsActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
|
||||
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to call intent to an activity
|
||||
* @param context
|
||||
* @param cls
|
||||
* @param flags
|
||||
* @param <T>
|
||||
*/
|
||||
public static <T> void startActivityWithFlags(Context context, Class<T> cls, int... flags) {
|
||||
Intent intent = new Intent(context, cls);
|
||||
for (int flag: flags) {
|
||||
intent.addFlags(flag);
|
||||
}
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* to inflate menu
|
||||
* @param menu
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_about, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* if share option selected then take screenshot and launch alert
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.share_app_icon) {
|
||||
View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
|
||||
Bitmap screenShot = getScreenShot(rootView);
|
||||
showAlert(screenShot);
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* to store the screenshot of image in bitmap variable temporarily
|
||||
* @param view
|
||||
* @return
|
||||
*/
|
||||
public static Bitmap getScreenShot(View view) {
|
||||
View screenView = view.getRootView();
|
||||
screenView.setDrawingCacheEnabled(true);
|
||||
Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
|
||||
screenView.setDrawingCacheEnabled(false);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* share the screenshot through social media
|
||||
* @param bitmap
|
||||
*/
|
||||
void shareScreen(Bitmap bitmap) {
|
||||
try {
|
||||
File file = new File(this.getExternalCacheDir(),"screen.png");
|
||||
FileOutputStream fOut = new FileOutputStream(file);
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
|
||||
fOut.flush();
|
||||
fOut.close();
|
||||
file.setReadable(true, false);
|
||||
final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
|
||||
intent.setType("image/png");
|
||||
startActivity(Intent.createChooser(intent, "Share image via"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It display the alertDialog with Image of screenshot
|
||||
* @param screenshot
|
||||
*/
|
||||
public void showAlert(Bitmap screenshot) {
|
||||
AlertDialog.Builder alertadd = new AlertDialog.Builder(QuizResultActivity.this);
|
||||
LayoutInflater factory = LayoutInflater.from(QuizResultActivity.this);
|
||||
final View view = factory.inflate(R.layout.image_alert_layout, null);
|
||||
ImageView screenShotImage = (ImageView) view.findViewById(R.id.alert_image);
|
||||
screenShotImage.setImageBitmap(screenshot);
|
||||
TextView shareMessage = (TextView) view.findViewById(R.id.alert_text);
|
||||
shareMessage.setText(R.string.quiz_result_share_message);
|
||||
alertadd.setView(view);
|
||||
alertadd.setPositiveButton("Proceed", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
shareScreen(screenshot);
|
||||
}
|
||||
});
|
||||
alertadd.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
alertadd.show();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package fr.free.nrw.commons.quiz;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used to group to or more radio buttons to ensure
|
||||
* that at a particular time only one of them is selected
|
||||
*/
|
||||
public class RadioGroupHelper {
|
||||
|
||||
public List<CompoundButton> radioButtons = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructor to group radio buttons
|
||||
* @param radios
|
||||
*/
|
||||
public RadioGroupHelper(RadioButton... radios) {
|
||||
super();
|
||||
for (RadioButton rb : radios) {
|
||||
add(rb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to group radio buttons
|
||||
* @param activity
|
||||
* @param radiosIDs
|
||||
*/
|
||||
public RadioGroupHelper(Activity activity, int... radiosIDs) {
|
||||
this(activity.findViewById(android.R.id.content),radiosIDs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to group radio buttons
|
||||
* @param rootView
|
||||
* @param radiosIDs
|
||||
*/
|
||||
public RadioGroupHelper(View rootView, int... radiosIDs) {
|
||||
super();
|
||||
for (int radioButtonID : radiosIDs) {
|
||||
add((RadioButton)rootView.findViewById(radioButtonID));
|
||||
}
|
||||
}
|
||||
|
||||
private void add(CompoundButton button){
|
||||
this.radioButtons.add(button);
|
||||
button.setOnClickListener(onClickListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* listener to ensure only one of the radio button is selected
|
||||
*/
|
||||
View.OnClickListener onClickListener = v -> {
|
||||
for (CompoundButton rb : radioButtons) {
|
||||
if(rb != v) rb.setChecked(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue