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_rotation_matrix_deployed(sender, instance, created, **kwargs): """ Update cache when rotation matrix deployed """ if created == False and instance.is_deployed == True: redis.set_rotation_matrix_cache(instance.survey)