Ejemplo n.º 1
0
    def list(self, request, *args, **kwargs):
        """
        List all questions in specific survey with choices
        """
        try:
            survey = Survey.objects.get(id=int(request.GET["survey_id"]))
        except:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        questions = cache.get("survey:" + str(survey.id) + ":questions")
        if questions is not None:
            return Response(questions)
        else:
            questions = redis.set_questions_cache(survey)
            return Response(questions)
Ejemplo n.º 2
0
    def create(self, request, *args, **kwargs):
        """
        Create result if result is not exist or updated datetime is past than the comparison target
        Otherwise get ID of existing result
        """
        try:
            category = request.data["category"]
        except:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        try:
            survey = Survey.objects.get(id=int(request.data["survey_id"]))
        except:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        try:
            result = Result.objects.filter(survey=survey, category=category, user=request.user).latest("id")
        except:
            result = None

        # Choose 'unawareness' for unaswered questions
        if request.user not in survey.participants.all():
            all_questions = cache.get("survey:" + str(survey.id) + ":questions")
            if all_questions is None:
                all_questions = redis.set_questions_cache(survey)
            all_questions_id_list = []
            for i in range(0, len(all_questions)):
                all_questions_id_list.append(all_questions[i]["id"])

            answered_questions_id_list = []
            answers = Answer.objects.select_related("choice").filter(user=request.user, choice__question__survey=survey)
            for answer in answers:
                answered_questions_id_list.append(answer.choice.question.id)

            # Extract id list of unanswered question
            unanswered_questions_id_list = list(set(all_questions_id_list) - set(answered_questions_id_list))

            # Choose 'unawareness' for unaswered questions, or choose randomly if failed
            for unanswered_question_id in unanswered_questions_id_list:
                question = Question.objects.prefetch_related("choices").get(id=unanswered_question_id)
                try:
                    Answer(user=request.user, choice=question.choices.filter(factor=7)[0]).save()
                except:
                    Answer(user=request.user, choice=question.choices.all().order_by("?")[0]).save()

            # Add user to participant list of survey
            survey.participants.add(request.user)

        comparison_targets = cache.get("survey:" + str(survey.id) + ":comparison_targets:data")
        if comparison_targets is None:
            comparison_targets = redis.set_survey_data_of_comparison_targets_cache(survey)

        # Data of comparison target
        target_data = comparison_targets["data"]
        comparison_targets_updated_at = comparison_targets["updated_at"]

        user_data = utilities.get_survey_data_of_user(request.user, survey)

        if category == "factor_list":
            # Get ID of result object(=DO NOT CREATE NEW ONE) only if
            #   (1) Result is exist
            #   (2) User's answers are not updated after result object is created
            if result is not None and result.updated_at > user_data["updated_at"]:
                return Response(
                    {"state": True, "id": result.id, "message": "Result already exist."}, status=status.HTTP_200_OK
                )

            factor_list = user_data["factor_list"]
            record = ""

            # Get question count
            questions_count = cache.get("survey:" + str(survey.id) + "questions:count")
            if questions_count is None:
                questions_count = redis.set_questions_count_cache(survey)

            for i in range(0, min(len(factor_list), questions_count)):
                record += str(i + 1) + "=" + str(factor_list[i]) + "&"

            record = record[:-1]

        elif category == "agreement_score":
            # Get ID of result object(=DO NOT CREATE NEW ONE) only if
            #   (1) Result is exist
            #   (2) User's answers are not updated after result object is created
            if result is not None and result.updated_at > user_data["updated_at"]:
                return Response(
                    {"state": True, "id": result.id, "message": "Result already exist."}, status=status.HTTP_200_OK
                )

            user_data["name"] = "나"
            record = utilities.get_agreement_score_result(user_data, *target_data)

        elif category == "city_block_distance":
            # Get ID of result object(=DO NOT CREATE NEW ONE) only if
            #   (1) Result is exist
            #   (2) User's answers are not updated after result object is created
            #   (3) Answers of comparison targets are not updated after result object is created
            if (
                result is not None
                and result.updated_at > user_data["updated_at"]
                and result.updated_at > max(comparison_targets_updated_at)
            ):
                return Response(
                    {"state": True, "id": result.id, "message": "Result already exist."}, status=status.HTTP_200_OK
                )

            questions_category = []
            questions = cache.get("survey:" + str(survey.id) + ":questions")
            for question in questions:
                questions_category.append(question["subtitle"])

            record = utilities.get_city_block_distance_result(
                questions_category, user_data["factor_list"], *target_data
            )

        elif category == "pca":
            rotation_matrix = cache.get("survey:" + str(survey.id) + ":rotation_matrix")
            if rotation_matrix is None:
                try:
                    rotation_matrix = redis.set_rotation_matrix_cache(survey)
                except:
                    return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)

            # Get ID of result object(=DO NOT CREATE NEW ONE) only if
            #   (1) Result is exist
            #   (2) User's answers are not updated after result object is created
            #   (3) Answers of comparison targets are not updated after result object is created
            #   (4) Rotation matrix is not updated after result object is created
            if (
                result is not None
                and result.updated_at > user_data["updated_at"]
                and result.updated_at > max(comparison_targets_updated_at)
                and result.updated_at > rotation_matrix["updated_at"]
            ):
                return Response(
                    {"state": True, "id": result.id, "message": "Result already exist."}, status=status.HTTP_200_OK
                )

            user_dict = {"name": "나", "color": "#9b59b6", "factor_list": user_data["factor_list"]}
            target_data.append(user_dict)

            record = utilities.get_pca_result(rotation_matrix["matrix"], *target_data)
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        data = request.data
        data["record"] = record

        if category == "city_block_distance":
            data["expected_target"] = request.user.supporting_party
        elif category == "pca":
            data["x_axis_name"] = rotation_matrix["x_axis_name"]
            data["y_axis_name"] = rotation_matrix["y_axis_name"]

        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def update_cache_when_choice_updated(sender, instance, created, **kwargs):
    """
    Update cache when choice updated
    """
    redis.set_questions_cache(instance.question.survey)
def update_cache_when_question_updated(sender, instance, created, **kwargs):
    """
    Update cache when question updated
    """
    redis.set_questions_cache(instance.survey)
    redis.set_questions_count_cache(instance.survey)