diff --git a/.gitignore b/.gitignore index 0205d62..e8d7d09 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ *.pyc .DS_Store +.venv +*.sqlite3 \ No newline at end of file diff --git a/README.md b/README.md index cad4a3c..a23be0a 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,8 @@ # PROCESSO DE SELEÇÃO DE PESSOA DESENVOLVEDORA - -Se você não tem experiência com o Django, recomendamos que você faça pelo menos -este tutorial antes de começar: -https://docs.djangoproject.com/en/3.1/intro/tutorial01/ - -Neste repositório, encontra-se o código de um sistema simples desenvolvido em -Django(3.1.X). O sistema consiste em uma página que contém uma questão de -múltipla escolha, ao respondê-la o usuário recebe um feedback de acerto ou erro. - - -## Para participar desta parte do processo você deve: -- Clonar esse repositório; -- Criar uma branch com o nome observando o padrão `desafio-nome-sobrenome` (por exemplo: `desafio-maria-silva`); -- Desenvolver as histórias abaixo na branch que você criou, de preferência com pelo menos um commit na finalização de cada história; -- Colocar no arquivo Readme: seu nome, email e outras observações que julgar adequadas; -- Ao terminar o desenvolvimento, abra um pull request para a branch `master`. Se não tiver permissão, nos informe seu usuário do Github; -- Nos avise por email quando concluir. +- Artur Felipe da Silva Veloso +- arturfdasveloso@gmail.com +- (86) 99927-2370 +- Teresina/PI ## Considerações: - Se não for possível fazer todas as histórias, entregue apenas as histórias que você fez. diff --git a/question/admin.py b/question/admin.py index 8c38f3f..45ae909 100644 --- a/question/admin.py +++ b/question/admin.py @@ -1,3 +1,24 @@ from django.contrib import admin +from .models import Question, Alternatives, QuestionLogs -# Register your models here. +# Register admin models +admin.site.register(Question) + +@admin.register(Alternatives) +class AlternativesAdmin(admin.ModelAdmin): + list_display = ( + 'alternative_order', + 'question', + 'alternative_text', + 'is_correct' + ) + +@admin.register(QuestionLogs) +class QuestionLogsAdmin(admin.ModelAdmin): + list_display = ( + 'user', + 'question', + 'chosen_alternative', + 'is_correct', + 'answer_date' + ) \ No newline at end of file diff --git a/question/models.py b/question/models.py index 71a8362..e87101a 100644 --- a/question/models.py +++ b/question/models.py @@ -1,3 +1,58 @@ from django.db import models +from django.contrib.auth.models import User -# Create your models here. +# Models +class Question(models.Model): + question_text = models.TextField(verbose_name="Questão") + + def __str__(self): + return self.question_text + + class Meta: + ordering = ('pk',) + verbose_name = 'Questão' + verbose_name_plural = 'Questões' + +class Alternatives(models.Model): + alternative_order = models.CharField(max_length=4, verbose_name="Alternativa") + question = models.ForeignKey( + 'Question', + on_delete=models.CASCADE, + verbose_name="Questão" + ) + alternative_text = models.TextField(verbose_name="Questão") + is_correct = models.BooleanField( + verbose_name="Está correta?", + default=False + ) + + def __str__(self): + return self.alternative_text + + class Meta: + ordering = ('alternative_order',) + verbose_name = 'Alternativa' + verbose_name_plural = 'Alternativas' + +class QuestionLogs(models.Model): + user = models.ForeignKey(User, verbose_name="Usuário", on_delete=models.CASCADE, null=True, blank=True) + + question = models.ForeignKey( + 'Question', + on_delete=models.CASCADE, + verbose_name="Questão" + ) + chosen_alternative = models.CharField(max_length=4, verbose_name="Alternativa", null=True, blank=True) + is_correct = models.BooleanField( + verbose_name="Está correta?", + default=False + ) + answer_date = models.DateField(null=True, blank=True) + + def __str__(self): + return self.question.question_text + + class Meta: + ordering = ('pk',) + verbose_name = 'Log' + verbose_name_plural = 'Logs' \ No newline at end of file diff --git a/question/templates/question/answer.html b/question/templates/question/answer.html index 6917832..95bbaa4 100644 --- a/question/templates/question/answer.html +++ b/question/templates/question/answer.html @@ -13,7 +13,17 @@

- Tente novamente + {% if id and next %} + Tente novamente + + Próxima questão + + {% if request.user.is_authenticated %} + Logs deste usuário + {% endif %} + + {% endif %} + \ No newline at end of file diff --git a/question/templates/question/question.html b/question/templates/question/question.html index 3cd26ca..740a6b9 100644 --- a/question/templates/question/question.html +++ b/question/templates/question/question.html @@ -1,16 +1,16 @@ - Questão 1 + Questão {{ questions.question_complete.id }}
{% csrf_token %} -

{{ question_text}}

+

{{ questions.question }}

- {% for letter, value in answers.items %} - {{ letter }}. {{ value }}
+ {% for alternative in questions.alternatives %} + {{ alternative.alternative_order }}. {{ alternative }}
{% endfor %}
diff --git a/question/templates/question/question_logs.html b/question/templates/question/question_logs.html new file mode 100644 index 0000000..703d504 --- /dev/null +++ b/question/templates/question/question_logs.html @@ -0,0 +1,15 @@ + + + + Logs + + + +

Logs de respostas do usuário: {{ user }}

+ {% for log in logs %} +

{{ log.user }} | {{ log.question }} | {{ log.chosen_alternative }} | {% if log.is_correct %} Correto {% else %} Errado {% endif %} | {{ log.answer_date }}

+ {% endfor %} + Home +
+ + \ No newline at end of file diff --git a/question/tests.py b/question/tests.py index 7ce503c..a82c4d9 100644 --- a/question/tests.py +++ b/question/tests.py @@ -1,3 +1,142 @@ from django.test import TestCase +from .models import Question, Alternatives, QuestionLogs -# Create your tests here. +# Tests +class TestViewQuestion(TestCase): + + # Test home access + def test_home_view(self): + # Test Question Response + response_question = self.client.get('') + self.assertEqual( + 200, + response_question.status_code + ) + + # Test question access + def test_question_view(self): + + # Question 1 + question1 = Question.objects.create( + id = 1, + question_text = "Quanto é 1 + 1?" + ) + + # Test Question Response with id error + response_question = self.client.get('/2/') + self.assertEqual( + 404, + response_question.status_code + ) + + # Test Question Response + response_question = self.client.get('/1/') + self.assertEqual( + 200, + response_question.status_code + ) + + # Test the return of the question object + self.assertEqual( + question1, + response_question.context["questions"]['question_complete'] + ) + + # Test the return of the question text + self.assertEqual( + "Quanto é 1 + 1?", + response_question.context["questions"]['question'], + ) + + # Test the feedback if you have no alternatives for this question + self.assertEqual( + 0, + response_question.context["questions"]['alternatives'].count(), + ) + + alternative1 = Alternatives.objects.create( + alternative_order = 'a', + question = question1, + alternative_text = "2", + is_correct = True + ) + + alternative2 = Alternatives.objects.create( + alternative_order = 'b', + question = question1, + alternative_text = "10", + is_correct = False + ) + + response_question = self.client.get('/1/') + # Test the feedback if you have one or more alternatives for this question + self.assertEqual( + 2, + response_question.context["questions"]['alternatives'].count(), + ) + + # Test anser access + def test_answer_view(self): + question1 = Question.objects.create( + id = 1, + question_text = "Quanto é 1 + 1?" + ) + + alternative1 = Alternatives.objects.create( + alternative_order = 'a', + question = question1, + alternative_text = "2", + is_correct = True + ) + + alternative2 = Alternatives.objects.create( + alternative_order = 'b', + question = question1, + alternative_text = "10", + is_correct = False + ) + + response_answer = self.client.post( + '/resposta/', + {'answer': alternative1.id} + ) + + # Testar se deu certo o acesso + self.assertEqual( + 200, + response_answer.status_code + ) + + # Testar se a respostar está correta + self.assertEqual( + True, + response_answer.context["is_correct"] + ) + + # Testar se foi gerado o log + self.assertEqual( + True, + response_answer.context["is_correct"] + ) + + # Testar um acesso errado a url + response_answer = self.client.post( + '/resposta/123', + {'answer': 'a'} + ) + + self.assertEqual( + 404, + response_answer.status_code + ) + + # Testar uma resposta errada + response_answer = self.client.post( + '/resposta/', + {'answer': alternative2.id} + ) + + self.assertEqual( + False, + response_answer.context["is_correct"] + ) \ No newline at end of file diff --git a/question/urls.py b/question/urls.py index 3fc3fa2..c9a0eac 100644 --- a/question/urls.py +++ b/question/urls.py @@ -1,11 +1,12 @@ #coding: utf8 -from django.urls import path, re_path +from django.urls import path from . import views urlpatterns = [ - re_path(r'^$', views.question, name='question'), - re_path(r'^resposta/$', views.question_answer, name='question_answer'), - + path('', views.home, name='question_home'), + path('/', views.question, name='question'), + path('resposta/', views.question_answer, name='question_answer'), + path('log-questoes/', views.logs, name='logs'), ] \ No newline at end of file diff --git a/question/views.py b/question/views.py index 229e20f..ebb7fd0 100644 --- a/question/views.py +++ b/question/views.py @@ -1,32 +1,85 @@ #coding: utf8 -from django.shortcuts import render +from django.shortcuts import render, redirect +from .models import Question, Alternatives, QuestionLogs +import datetime +def home(request): + questions = Question.objects.all().first() + + if questions: + return redirect('question', questions.id) + else: + context = {} + return render(request, 'question/question.html', context=context) -def question(request): - text = 'Quanto é 2^5?' - - # BUG: as respostas estão ficando fora de ordem - answers = { - 'a': '0', - 'b': '2', - 'c': '16', - 'd': '32', - 'e': '128', - } - +def question(request, id): + questions = Question.objects.get(id=id) + context = { - 'question_text': text, - 'answers': answers, - } - + "questions":{}, + } + + if questions: + alternatives = Alternatives.objects.filter(question__id=id) + context['questions'] = { + "question_complete":questions, + "question":questions.question_text, + "alternatives":alternatives + } + return render(request, 'question/question.html', context=context) - + def question_answer(request): - answer = request.POST.get('answer', 'z') - is_correct = answer == 'd' + questions = Question.objects.all() + try: + answer_id = request.POST.get('answer') + + alternative = Alternatives.objects.get(id=answer_id) - context = { - 'is_correct': is_correct, - } + context = { + 'is_correct': alternative.is_correct, + 'id': alternative.question.id, + 'user_logged': request.user.is_authenticated + } + + if alternative.question.id < len(questions): + context['next'] = alternative.question.id + 1 + else: + questions = Question.objects.all().first() + context['next'] = questions.id + + question = Question.objects.get(id=alternative.question.id) + + if request.user.is_authenticated: + QuestionLogs.objects.create( + user = request.user, + question = question, + chosen_alternative = alternative.alternative_order, + is_correct = alternative.is_correct, + answer_date = datetime.date.today() + ) + else: + QuestionLogs.objects.create( + question = question, + chosen_alternative = alternative.alternative_order, + is_correct = alternative.is_correct, + answer_date = datetime.date.today() + ) + + return render(request, 'question/answer.html', context=context) + except: + return redirect('question_home') - return render(request, 'question/answer.html', context=context) \ No newline at end of file +def logs(request): + + if request.user.is_authenticated: + logs = QuestionLogs.objects.filter(user=request.user) + + context = { + 'user': request.user, + 'logs': logs + } + + return render(request, 'question/question_logs.html', context=context) + else: + return redirect('question_home') \ No newline at end of file