You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
3.3 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. import collections
  2. from django.conf import settings
  3. from django.db.models import Count, Q
  4. from django.shortcuts import get_object_or_404
  5. from rest_framework.permissions import IsAuthenticated
  6. from rest_framework.response import Response
  7. from rest_framework.views import APIView
  8. from ..models import ExampleState, Project, RoleMapping
  9. from ..permissions import IsInProjectReadOnlyOrAdmin
  10. class StatisticsAPI(APIView):
  11. pagination_class = None
  12. permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]
  13. def get(self, request, *args, **kwargs):
  14. p = get_object_or_404(Project, pk=self.kwargs['project_id'])
  15. include = set(request.GET.getlist('include'))
  16. response = {}
  17. if not include or 'label' in include:
  18. label_count, user_count = self.label_per_data(p)
  19. response['label'] = label_count
  20. # TODO: Make user_label count chart
  21. response['user_label'] = user_count
  22. if not include or 'total' in include or 'remaining' in include or 'user' in include:
  23. progress = self.progress(project=p)
  24. response.update(progress)
  25. if not include or 'confirmed_count' in include:
  26. confirmed_count = self.confirmed_count(p)
  27. response['confirmed_count'] = confirmed_count
  28. if include:
  29. response = {key: value for (key, value) in response.items() if key in include}
  30. return Response(response)
  31. @staticmethod
  32. def _get_user_completion_data(annotation_class, annotation_filter):
  33. all_annotation_objects = annotation_class.objects.filter(annotation_filter)
  34. set_user_data = collections.defaultdict(set)
  35. for ind_obj in all_annotation_objects.values('user__username', 'example__id'):
  36. set_user_data[ind_obj['user__username']].add(ind_obj['example__id'])
  37. return {i: len(set_user_data[i]) for i in set_user_data}
  38. def progress(self, project):
  39. docs = project.examples
  40. annotation_class = project.get_annotation_class()
  41. total = docs.count()
  42. annotation_filter = Q(example_id__in=docs.all())
  43. user_data = self._get_user_completion_data(annotation_class, annotation_filter)
  44. if not project.collaborative_annotation:
  45. annotation_filter &= Q(user_id=self.request.user)
  46. done = annotation_class.objects.filter(annotation_filter)\
  47. .aggregate(Count('example', distinct=True))['example__count']
  48. remaining = total - done
  49. return {'total': total, 'remaining': remaining, 'user': user_data}
  50. def label_per_data(self, project):
  51. annotation_class = project.get_annotation_class()
  52. return annotation_class.objects.get_label_per_data(project=project)
  53. def confirmed_count(self, project):
  54. confirmed_count = {
  55. settings.ROLE_ANNOTATOR: 0,
  56. settings.ROLE_ANNOTATION_APPROVER: 0,
  57. settings.ROLE_PROJECT_ADMIN: 0,
  58. }
  59. # Todo: convert to one query
  60. count_by_user = ExampleState.objects.filter(example__project=project)\
  61. .values('confirmed_by')\
  62. .annotate(total=Count('confirmed_by'))
  63. for record in count_by_user:
  64. mapping = RoleMapping.objects.get(project=project, user=record['confirmed_by'])
  65. confirmed_count[mapping.role.name] += record['total']
  66. return confirmed_count