123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- package uprrp.tania.fragments;
-
- import android.app.Activity;
- import android.app.ProgressDialog;
- import android.content.Intent;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.Button;
- import android.widget.TextView;
- import android.widget.Toast;
- import androidx.annotation.Nullable;
- import androidx.appcompat.widget.AppCompatButton;
- import androidx.fragment.app.Fragment;
-
- import com.google.android.gms.tasks.OnSuccessListener;
- import com.google.firebase.iid.FirebaseInstanceId;
- import com.google.firebase.iid.InstanceIdResult;
-
- import org.json.JSONException;
- import org.json.JSONObject;
- import org.researchstack.backbone.StorageAccess;
- import org.researchstack.backbone.answerformat.AnswerFormat;
- import org.researchstack.backbone.answerformat.ChoiceAnswerFormat;
- import org.researchstack.backbone.answerformat.TextAnswerFormat;
- import org.researchstack.backbone.model.Choice;
- import org.researchstack.backbone.result.StepResult;
- import org.researchstack.backbone.result.TaskResult;
- import org.researchstack.backbone.step.InstructionStep;
- import org.researchstack.backbone.step.QuestionStep;
- import org.researchstack.backbone.step.Step;
- import org.researchstack.backbone.task.OrderedTask;
- import org.researchstack.backbone.ui.ViewTaskActivity;
-
- import java.util.ArrayList;
- import java.util.List;
-
- import uprrp.tania.networking.FetchAssessment;
- import uprrp.tania.networking.FetchUserStatus;
- import uprrp.tania.models.AssessmentModel;
- import uprrp.tania.models.QuestionModel;
- import uprrp.tania.R;
- import uprrp.tania.SendAnswersToServer;
- import uprrp.tania.URLEventListener;
- import uprrp.tania.models.UserStatusModel;
-
- public class AssessmentsFragment extends Fragment {
-
- // These variables came from the sample app provided to explain the use of Research Stack
- private static final int REQUEST_SURVEY = 1;
- private static final String INSTRUCTION = "identifier";
- private static final String SAMPLE_SURVEY = "sample_assessment";
-
- // Our variables
- private final String TAG = "ASSESSMENTS FRAGMENT";
- private String device_token;
- private String id_subquestionnair;
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
-
- // Get reference for this fragment and other components
- final View thisFragment = inflater.inflate(R.layout.fragment_assessments, container, false);
- final AppCompatButton surveyButton = thisFragment.findViewById(R.id.surveyButton);
- final Button refreshButton = thisFragment.findViewById(R.id.refreshButton); // TODO: check Button vs. AppCompatButton
-
- // Change all caps text to normal capitalization
- // TODO: this is a workaround I found, any other acceptable solution is welcome
- surveyButton.setTransformationMethod(null);
- refreshButton.setTransformationMethod(null);
-
- // Request to Firebase...
- FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
- @Override
- public void onSuccess(InstanceIdResult instanceIdResult) {
-
- // Get device's token
- // IMPORTANT: must come first before setting any
- device_token = instanceIdResult.getToken();
-
- // Add onClick listener to "Answer Survey" button
- surveyButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- fetchAssessment();
- }
- });
-
- // Add onClick listener to "Refresh Status" button
- refreshButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- fetchUserStatus(thisFragment);
- }
- });
-
- // Fetch user status and assessment, if any
- fetchUserStatus(thisFragment);
- // fetchAssessment();
-
- }
- });
-
- return thisFragment;
-
- }
-
- private void fetchUserStatus(View thisFragment) {
-
- // Get text fields and initialize other stuff
- final TextView statusTextView = thisFragment.findViewById(R.id.statusTextView);
- final TextView nextSurveyTextView = thisFragment.findViewById(R.id.nextSurveyTextView);
- final Button surveyButton = thisFragment.findViewById(R.id.surveyButton);
- final Button refreshButton = thisFragment.findViewById(R.id.refreshButton);
-
- // Change UI to indicate loading is happening
- statusTextView.setText(R.string.userStatusLoadingText);
- nextSurveyTextView.setVisibility(View.GONE);
-
- // Define task
- FetchUserStatus userStatusTask = (FetchUserStatus) new FetchUserStatus(new URLEventListener() {
-
- @Override
- public void onSuccess(UserStatusModel userStatus) {
- if(userStatus.isEnrolled()) {
-
- // Change next survey date text (as well as status text)
- statusTextView.setText(userStatus.toString());
- nextSurveyTextView.setText(userStatus.getTimeToNext());
- nextSurveyTextView.setVisibility(View.VISIBLE);
-
- // Hide refresh button (it only refreshes user status, anyways so...)
- refreshButton.setVisibility(View.GONE);
-
- // Toggle "Answer" button visibility depending on survey availability
- // TODO: Decide whether to show the button regardless of anything,
- // since this may be optional functionally, but important for UX
- if(userStatus.surveyAvailable()) {
- surveyButton.setVisibility(View.VISIBLE);
- } else {
- surveyButton.setVisibility(View.GONE);
- }
-
- } else {
- // Prompt user to refresh status if user doesn't have an experience
- // statusTextView.setText("You are not enrolled in any experience.\nIf you think this is a mistake, contact your supervisors."); // for debugging/testing
- statusTextView.setText(userStatus.toString());
- nextSurveyTextView.setVisibility(View.GONE);
- surveyButton.setVisibility(View.GONE);
- refreshButton.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onFailure(Exception e) {
- statusTextView.setText(R.string.userStatusErrorText);
- Toast.makeText(getContext(), "Can't verify identity!", Toast.LENGTH_LONG).show();
- Log.e("ERROR WHILE FETCHING USER STATUS", e.toString());
- }
-
- });
-
- // Start task
- userStatusTask.execute(this.device_token);
-
- }
-
- private void fetchAssessment() {
-
- // Initiate progress dialog
- // TODO: find substitute for this deprecated dialog box
- final ProgressDialog progressDialog = ProgressDialog.show(getContext(),
- "Looking for Survey",
- "This shouldn't take long");
-
- // Fetch the assessment to be taken (if there is at least one available),
- // and launch the assessment (if the button is pressed)
- FetchAssessment assessmentTask = (FetchAssessment) new FetchAssessment(new URLEventListener() {
-
- @Override
- public void onSuccess(AssessmentModel assessment) {
-
- // Stop progress dialog
- progressDialog.dismiss();
-
- // Launch survey or notify there are none available, accordingly
- if(assessment.isEmpty()) {
- Toast.makeText(getContext(), "There are no surveys at the moment!", Toast.LENGTH_LONG).show();
- } else {
- launchSurvey(assessment);
- }
-
- }
-
- @Override
- public void onFailure(Exception e) {
- progressDialog.dismiss();
- Toast.makeText(getContext(), "Can't reach surveys at the moment!", Toast.LENGTH_LONG).show();
- Log.e("ERROR WHILE FETCHING ASSESSMENT", e.toString());
- }
-
- });
-
- // Start task
- assessmentTask.execute(this.device_token);
-
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if(requestCode == REQUEST_SURVEY && resultCode == Activity.RESULT_OK) {
- this.processSurveyResult((TaskResult) data.getSerializableExtra(ViewTaskActivity.EXTRA_TASK_RESULT));
- }
- }
-
- private void launchSurvey(AssessmentModel assessment) {
- this.id_subquestionnair = assessment.getID();
- List<Step> allSteps = this.prepareSurveySteps(assessment);
- OrderedTask task = new OrderedTask(SAMPLE_SURVEY, allSteps);
- Intent intent = ViewTaskActivity.newIntent(getContext(), task);
- startActivityForResult(intent, REQUEST_SURVEY);
- }
-
- private void processSurveyResult(TaskResult result) {
- StorageAccess.getInstance().getAppDatabase().saveTaskResult(result);
-
- // Initiate progress dialog
- // TODO: find substitute for this deprecated dialog box
- final ProgressDialog progressDialog = ProgressDialog.show(getContext(),
- "Sending Answers",
- "This shouldn't take long");
-
- try {
- sendSurveyInfo();
- progressDialog.dismiss();
- } catch(Exception e) {
- // TODO: prompt user to retry sending results
- progressDialog.dismiss();
- Toast.makeText(getContext(), "Couldn't send answers!", Toast.LENGTH_LONG).show();
- Log.e("ERROR WHILE SENDING ANSWERS", e.toString());
- e.printStackTrace();
- }
- }
-
- private void sendSurveyInfo() {
-
- // Load survey results
- TaskResult taskResult = StorageAccess.getInstance()
- .getAppDatabase()
- .loadLatestTaskResult(SAMPLE_SURVEY);
-
- // Serialize results into JSON
- String resultsJSON = this.serializeSurveyResults(taskResult);
-
- // Send JSON
- Log.d(TAG, "preparedJSON:" + resultsJSON);
- new SendAnswersToServer().execute(resultsJSON);
-
- }
-
- private String serializeSurveyResults(TaskResult taskResult) {
-
- JSONObject surveyResults = new JSONObject();
-
- try {
-
- surveyResults.put("os", "Android");
-
- JSONObject data = new JSONObject();
- data.put("id_subquestionnair", this.id_subquestionnair);
- data.put("token", this.device_token);
-
- // TODO: Try Gson.toJSON() to simplify this process
- for (String id : taskResult.getResults().keySet()) {
- JSONObject questions = new JSONObject();
- StepResult stepResult = taskResult.getStepResult(id);
-
- questions.accumulate("id_question", id);
- questions.accumulate("start_datetime", taskResult.getStartDate().toString());
- questions.accumulate("question_answer", stepResult.getResult().toString());
- questions.accumulate("end_datetime", taskResult.getEndDate().toString());
- data.accumulate("preguntas", questions.toString());
- }
-
- surveyResults.put("data", data.toString());
-
- } catch (JSONException e) {
- e.printStackTrace();
- }
-
- return surveyResults.toString();
-
- }
-
- private List<Step> prepareSurveySteps(AssessmentModel assessment) {
-
- // Initialize survey steps
- // List<QuestionStep> taniaQuestions = new ArrayList<>();
- List<Step> allSteps = new ArrayList<>();
-
- // Create instruction screen (add it to total steps)
- InstructionStep instructionStep = new InstructionStep(INSTRUCTION,
- getString(R.string.app_name),
- assessment.getDescription());
- instructionStep.setStepTitle(R.string.survey);
- allSteps.add(0, instructionStep);
-
- // Prepare survey question by question
- List<QuestionModel> questions = assessment.getQuestions();
- Log.d(TAG, "AssessmentCount: " + assessment.getQuestionCount() + " QuestionCount: " + questions.size()); // just to be sure
- for(int i = 0; i < assessment.getQuestionCount(); i++) {
-
- QuestionModel question = questions.get(i);
- Log.d("id_type", question.getType());
-
- if(question.getType().equals("SCALED")) {
-
- // Create question choices
- Choice[] choices = new Choice[question.getMaxValue()];
- for(int m = 0; m < question.getMaxValue(); m++) {
- if (m == 0) {
- choices[m] = new Choice<>((m + 1) + " " + question.getMinText(), m + 1);
- } else if (m == question.getMaxValue() - 1) {
- choices[m] = new Choice<>((m + 1) + " " + question.getMaxText(), m + 1);
- } else {
- choices[m] = new Choice<>(Integer.toString(m + 1), m + 1);
- }
- }
-
- // Create question step along with its choices
- QuestionStep newQuestionStep = new QuestionStep(question.getID());
- AnswerFormat multiFormat = new ChoiceAnswerFormat(AnswerFormat.ChoiceAnswerStyle.SingleChoice, choices);
-
- // Set question step details
- newQuestionStep.setStepTitle(R.string.survey);
- newQuestionStep.setTitle(question.getPremise());
- newQuestionStep.setAnswerFormat(multiFormat);
- newQuestionStep.setOptional(false);
-
- // Add step to arrays
- // taniaQuestions.add(i, newQuestionStep);
- allSteps.add(newQuestionStep);
-
- } else if(question.getType().equals("OPEN")) {
-
- // Create question step along with its choices
- QuestionStep newQuestionStep = new QuestionStep(question.getID());
- TextAnswerFormat format = new TextAnswerFormat();
-
- // Set question step details
- newQuestionStep.setStepTitle(R.string.survey);
- newQuestionStep.setTitle(question.getPremise());
- newQuestionStep.setAnswerFormat(format);
- newQuestionStep.setOptional(false);
-
- // Add step to arrays
- // taniaQuestions.add(i, newQuestionStep);
- allSteps.add(newQuestionStep);
-
- }
- }
-
- return allSteps;
- }
-
- }
|