From 7af12cdf96db79df750b528dda34813b887d7089 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Denis=20Rodrigues?= <joao.denisr@gmail.com>
Date: Mon, 7 Aug 2017 11:54:44 -0300
Subject: [PATCH] Fix cache student + funcoes disciplinas

---
 src/course/analysis.py | 103 +++++++++++++++++++++++++++++++++++++++++
 src/script.py          |   2 +-
 src/student/models.py  |   2 +
 src/utils/data.py      |  35 ++++++++++++++
 4 files changed, 141 insertions(+), 1 deletion(-)

diff --git a/src/course/analysis.py b/src/course/analysis.py
index e69de29..290047f 100644
--- a/src/course/analysis.py
+++ b/src/course/analysis.py
@@ -0,0 +1,103 @@
+from __future__ import division
+from student.models import Student
+from klass.models import *
+from admission.models import Admission
+from course.models import *
+from degree.models import *
+from datetime import datetime
+from student.analysis import *
+
+import math
+
+def average_grade(klasses): # calcular_nota_media(turmas)
+    grade = 0
+    amount_student = 0
+    for klass in klasses:
+        student_klasses = StudentKlass.objects.filter(klass = klass,
+            situation__in = SITUATION_COURSE_VALID_GRADE)
+        for student_klass in student_klasses:
+            if student_klass.grade is not None:
+                grade += student_klass.grade
+                amount_student += 1
+
+    if amount_student == 0:
+        return -1
+    else:
+        return grade / amount_student
+
+def average_grade_standard_deviation(klasses): # calcular_nota_media_desvio_padrao
+    average_grade = average_grade(klasses)
+    amount_student = 0
+    variance = 0
+    for klass in klasses:
+        student_klasses = StudentKlass.objects.filter(klass = klass,
+            situation__in = SITUATION_COURSE_VALID_GRADE)
+        for student_klass in student_klasses:
+            if student_klass.grade is not None:
+                variance += math.pow(student_klass.grade - average_grade, 2)
+                amount_student += 1
+
+    if amount_student == 0:
+        return -1
+
+    standard_deviation = math.sqrt(variance/amount_student)
+    return (average_grade, standard_deviation)
+
+def average_grade_last_year(klasses): # calcular_nota_media_ultimo_ano
+    grades = 0
+    amount_student = 0
+    now = datetime.now()
+    for klass in klasses:
+        if klass.year == (now.year - 1):
+            student_klasses = StudentKlass.objects.filter(klass = klass)
+            for student_klass in student_klasses:
+                if student_klass.grade is not None:
+                    grades += student_klass.grade
+                    amount_student += 1
+
+    if amount_student == 0:
+        return -1
+
+    return grades / student_amount
+
+def average_grade_last_year_standard_deviation(klasses): # calcular_nota_media_ultimo_ano_desvio_padrao
+    average_grade = average_grade_last_year(klasses)
+    if average_gradde == -1:
+        return (-1, -1)
+    amount_student = 0
+    variance = 0
+    now = datetime.now()
+    for klass in klasses:
+        if klass.year == (now.year - 1):
+            student_klasses = StudentKlass.objects.filter(klass = klass)
+            for student_klass in student_klasses:
+                if student_klass.grade is not None:
+                    variance += math.pow(student_klass.grade - average_grade, 2)
+                    amount_student += 1
+
+    if amount_student == 0:
+        return (-1,-1)
+
+    standard_deviation = math.sqrt(variance / amount_student)
+
+    return (average_grade, standard_deviation)
+
+#def absolute_pass_rate(klasses): # calcular_taxa_reprovacao_absoluta
+
+def frequency_failure(klasses): # calcular_taxa_reprovacao_frequencia
+    amount_failure = 0
+    amounte_student = 0
+    for klass in klasses:
+        student_klasses = StudentKlass.objects.filter(klass = klass)
+        for student_klass in student_klasses:
+            if student_klass.situation is not None:
+                if student.situation == "Reprovado por Frequência":
+                    amount_failure += 1
+                amount_student += 1
+
+    if amount_student == 0:
+        return -1
+
+    amount_failure *= 100
+    return amount_failure / amount_student
+
diff --git a/src/script.py b/src/script.py
index 0338532..66c9131 100644
--- a/src/script.py
+++ b/src/script.py
@@ -108,7 +108,7 @@ def generate_student_data(degree, path):
 
     for student in students:
         student_klasses = StudentKlass.objects.filter(student=student)
-        amount_courses_semester = get_student_courses_completed(student_klasses)
+        amount_courses_semester = get_amount_courses_completed(student)
         failures_semester = semester_pass_rate(student)
         failures_amount_courses_semester = merge_dicts(
             ['reprovacoes', 'cursadas'],
diff --git a/src/student/models.py b/src/student/models.py
index 4ecb711..77db826 100644
--- a/src/student/models.py
+++ b/src/student/models.py
@@ -17,6 +17,8 @@ class Student(models.Model):
     klasses = models.ManyToManyField('klass.Klass', through = 'klass.StudentKlass')
 
     def get_time_in_degree(self):
+        year_end = self.admission.degree.report_year
+        semester_end = self.admission.degree.report_semester
         if self.evasion_year is not None:
             year_end = self.evasion_year
             if self.evasion_semester is None:
diff --git a/src/utils/data.py b/src/utils/data.py
index 32a9082..b00244c 100644
--- a/src/utils/data.py
+++ b/src/utils/data.py
@@ -87,6 +87,41 @@ SITUATION_FAILURE_COMPLETED = ( # Situacoes reprovacao cursada ate o fim
     u'Reprovado sem nota',
 )
 
+SITUATION_COURSES_VALID = (
+    u'Reprovado por nota',
+    u'Aprovado',
+    u'Reprovado por Frequência',
+    u'Reprovado sem nota',
+    u'Equivalência de Disciplina',
+    u'Aprovado Conhecimento',
+    u'Reprovado Conhecimento',
+    u'Aprovado Adiantamento',
+    u'Horas',
+    u'Dispensa de Disciplinas (com nota)',
+    u'Dispensa de Disciplinas (sem nota))',
+    u'Matrícula',
+)
+
+SITUATION_COURSES_LOCKED = (
+    u'Cancelado',
+    u'Trancamento Total',
+    u'Trancamento Administrativo',
+)
+
+SITUATION_COURSES_VALID_GRADE = (
+    u'Reprovado por nota',
+    u'Aprovado',
+    u'Reprovado por Frequência',
+    u'Reprovado sem nota',
+    u'Equivalência de Disciplina',
+    u'Aprovado Conhecimento',
+    u'Reprovado Conhecimento',
+    u'Aprovado Adiantamento',
+    u'Horas',
+    u'Dispensa de Disciplinas (com nota)',
+    u'Dispensa de Disciplinas (sem nota))',
+)
+
 def difference_between_semesters(year_start, semester_start, year_end, semester_end):
     return 2 * (year_end - year_start) + (semester_end - semester_start) + 1
 
-- 
GitLab