def __init__(self, xml_lattes, ano_incial, ano_final):

        self.ano_inicial = ano_incial
        self.ano_final = ano_final

        tree = ET.parse(xml_lattes)
        self.xml_root = tree.getroot()

        Alerta.addAlerta(
            "Aviso: para efeito de pontuação da produção bibliogáfica são contados os dois ultimo anos"
            " desprezando o ano corrente.")

        artigos_periodicos = self.__artigos()
        self.artigos_periodicos = artigos_periodicos[0]
        self.pontos = artigos_periodicos[1]

        trabalhos_eventos = self.__trabalho_eventos()
        self.lista_artigos_eventos = trabalhos_eventos[0]
        self.pontos += trabalhos_eventos[1]

        capitulos = self.__capitulo_livro()
        self.capitulos_livro = capitulos[0]
        self.pontos += capitulos[1]

        livros = self.__livro()
        self.lista_livros = livros[0]
        self.pontos += livros[1]
    def __parse_iniciacoes_cientificas(self):
        # Extraindo do texto os dados sobre orientacoes
        # orientacoes = page_content.split('Título:') Resumo:

        orientacoes = re.findall(r'Título:(.*?)Resumo:', self.__page_content)

        lista_orientacoes = []
        for orientacao in orientacoes:
            # if(orientacao == ""):
            #     continue

            titulo = re.search(r'(.*?)Data de início:', orientacao).group(1)
            data_inicio_str = re.search(
                r'Data de início:(.*?)Data de término:', orientacao).group(1)

            if (data_inicio_str == ""):
                Alerta.addAlerta(
                    "Iniciação Científica '" + titulo +
                    "'não computada por não ter data de início definida.")
                continue

            data_inicio_ic = datetime.strptime(data_inicio_str,
                                               '%d/%m/%Y').date()

            if (self.fim_intersticio is not None):
                if (data_inicio_ic > self.fim_intersticio
                    ):  # IC começou depois do fim do intertício.
                    continue

            data_termino_str = re.search(r'Data de término:(.*)',
                                         orientacao).group(1)
            if (data_termino_str != ""):
                data_termino = datetime.strptime(data_termino_str,
                                                 '%d/%m/%Y').date()
                if (self.inicio_intersticio != None):  # Errado!
                    if (data_termino < self.inicio_intersticio
                        ):  # orientação terminou depois do intertício.
                        continue
            else:
                data_termino = None

            tupletOrientacao = (titulo, data_inicio_ic, data_termino)
            lista_orientacoes.append(tupletOrientacao)

        return lista_orientacoes
Пример #3
0
    def __init__(self, portal_docente:PortalDocente, ficha_funcional: FichaFuncional, producao_intelectual : ProducaoIntelectual):

        #Limpa os alertas preparando para o próximo parecer.
        Alerta.lista_alertas.clear()

        self.portal_docente = portal_docente
        self.ficha_funcional = ficha_funcional
        self.producao_intelectual_lattes = producao_intelectual
        self.lista_aquivos =list()

        self.status_parecer = StatusParecer.FAVORAVEL

        if (not ficha_funcional.is_valid()):
            Alerta.addAlerta("Importante: Ficha funcional vencida. Solicitar nova ao interessado")

        dt_permitida_processo = ficha_funcional.fim_intersticio - timedelta(days=60)
        if (date.today() < dt_permitida_processo):
            Alerta.addAlerta(
                "Verificar: Possível processo prematuro de progressão. Se verificado, devolver ao interessado (Art. 26, § 1).")
Пример #4
0
    def __calcula_pontuacao(self):
        dic_pontuacao = dict()
        keys = self.dic_encargo_didatico.keys()
        if(self.nivel_ensino == NivelEnsino.POSGRADUACAO):
            for k in keys:
                dic_pontuacao[k] = (self.dic_encargo_didatico[k] / 15) * 5
            return dic_pontuacao
        else:
            for k in keys:
                if (self.dic_encargo_didatico[
                    k] <= 120):  # Até 8 horas semanais (2 disciplinas de 60 horas), fator de mult. é 5
                    dic_pontuacao[k] = (self.dic_encargo_didatico[k] / 15) * 5
                else:
                    dif = self.dic_encargo_didatico[k] - 120
                    dic_pontuacao[k] = (((120 / 15) * 5) + ((dif / 15) * 10))
                    if (dic_pontuacao[k] > 120):  # limita a 16 horas somente para graduação? @todo duvida cpad
                        dic_pontuacao[k] = 120
                        Alerta.addAlerta("Teto de encargo de ensino atingido em " + str(k))

            return dic_pontuacao
Пример #5
0
    def emitir_parecer_progressao(self, gravar_log= True):
        self.quadro_pontuacao[AnexoIII.ENSINO.value] = self.__verifica_retricoes_ensino(self.portal_docente)
        self.quadro_pontuacao[AnexoIII.ORIENTACAO.value] = self.portal_docente.orientacoes.pontos

        pontos_projeto_pesquisa = self.portal_docente.projetos_pesquisa.pontos
        pontos_acoes_extensao = self.portal_docente.acoes_extensao.pontos
        pontos_pesquisa_extensao = pontos_projeto_pesquisa+pontos_acoes_extensao
        self.quadro_pontuacao[AnexoIII.PESQUISA_EXTENSAO.value] = pontos_pesquisa_extensao

        pontos_ic = self.portal_docente.iniciacoes_cientificas.pontos
        self.quadro_pontuacao[AnexoIII.OUTRAS_ATIVIDADES.value] = pontos_ic # + ....incluir outros no futuro.

        self.quadro_pontuacao[AnexoIII.PRODUCAO_INTELECTUAL.value] = self.producao_intelectual_lattes.pontos

        if(self.__pontuacao_total() < 240):
            self.status_parecer = StatusParecer.INCONCLUSIVO
            Alerta.addAlerta("Importante: é necessário verificar outras produções do docente para atingir o mínimo de "
                             "240 pontos.")

        self.__preencher_docx_anexo3()
        if (gravar_log):
            self.gravar_log()
Пример #6
0
    def __verifica_retricoes_ensino(self, portal_docente:PortalDocente):
        #Verifica o mínimo de 120 horas por ano na graduação (Art 4 §2)
        encargo_anual = portal_docente.disciplinas_grad.encargo_docente_anual_grad()
        keys = encargo_anual.keys()
        for k in keys:
            if(encargo_anual[k] < 120):
                Alerta.addAlerta("Importante: em "+ str(k) + " não foi atingido o mínimo de 120 horas na graduacão (Art 4 §2)."
                                                             "\n      Verifique se o servidor ocupava cargo administrativo "
                                                             ", se ficou afastado, ou se admissão foi atemporal. ")
                self.status_parecer = StatusParecer.INCONCLUSIVO

        #Verifica o mínimo de 40 pontos semestre (Art 35 §3)
        pontuacao_grad = portal_docente.disciplinas_grad.pontos_semestre
        pontuacao_posgrad = portal_docente.disciplinas_posgrad.pontos_semestre

        pontos_somados_periodos = {k: pontuacao_grad.get(k, 0) + pontuacao_posgrad.get(k, 0) for k in set(pontuacao_grad)}
        keys = portal_docente.disciplinas_grad.dic_encargo_didatico.keys()
        for k in keys:
            if ((pontos_somados_periodos[k] < 40) and (k[-1] != '3')):
                Alerta.addAlerta("Importante: não foi atingido o mínimo de 40 pontos de ensino (graduação + pós) no semestre "+ str(k) + "(Art 4 §2)."
                                "\n      Verificar se o servidor ocupava cargo administrativo ou encontrava-se afastado em " + str(k))
                self.status_parecer = StatusParecer.INCONCLUSIVO

        total_pontos_ensino = portal_docente.disciplinas_grad.pontos + portal_docente.disciplinas_posgrad.pontos
        if(settings.aplicar_art52):
            fator_mult_media = 4 - settings.periodos_concluido_art52 # 4 periodos são previstos para chegar nos 160 pontos.
            total_pontos_ensino += (portal_docente.disciplinas_grad.media_pontos + portal_docente.disciplinas_posgrad.media_pontos) * fator_mult_media

            Alerta.addAlerta("Importante: Art. 52 aplicado. A pontuação da Área 1 é a média dos semestres concluídos indicados "
                             "manualmente no filtro de configurações do sistema.")


        # Verifica a pontuação mínima de 160 pontos  (Art. 37, § 1
        if(total_pontos_ensino < 160):
            Alerta.addAlerta("Importante: não foi atingido o mínimo de 160 pontos no interstício para a área de ensino. (Art. 37, §1) "
                             "\n      Verifique se o servidor ocupava cargo administrativo ou encontrava-se ou estava "
                             "afastado do período do insterstício")
            self.status_parecer = StatusParecer.INCONCLUSIVO

        return total_pontos_ensino
Пример #7
0
    def __busca_disciplinas_grad(self, remove_duplicatas=True):
        # Extraindo do texto os dados sobre as disciplinas
        # disciplinas = re.findall(r'Disciplina:(.*?)Vagas ocupadas:', self.page_content)
        disciplinas = re.split(r'Disciplina:', self.page_content)
        lista_disciplinas = list()

        # somatório disciplinas de estágio
        sum_estagio_indireto = 0
        sum_estagio_semidireto = 0

        for disciplina in disciplinas:
            if (disciplina == ''):
                continue;

            codigo_disciplina = re.search(r'Código:(.*?)Período', disciplina).group(1)

            nome_disciplina = re.search(r'(.*?)Código', disciplina).group(1)
            nome_disciplina = nome_disciplina.upper()

            periodo = re.search(r'Período:(.*?)Curso', disciplina).group(1)
            # remove disciplinas canceladas de 2020/1 devido a pandemia COVID-19. @todo Testar como fica isso com
            # disciplina da matemática industrial.
            if (codigo_disciplina.endswith("I") and periodo == "2020/1"):
                continue

            vagas_ocupadas = float(re.search(r'Vagas ocupadas:(\d+)', disciplina).group(1))
            if (vagas_ocupadas == 0):
                continue  # não conta disciplinas que não tem nenhum aluno matriculado.

            if (nome_disciplina in self.filtro_disciplina):  # remove as disciplinas de TCC (Art4,3)
                Alerta.addAlerta("Disciplina removida (Art 4, §3): " + nome_disciplina)
                continue  # @todo dúvida para CPAD

            if (periodo in self.filtro_periodo):
                try:
                    encargo_didatico = float(re.search(r'Encargo didático:(\d+.\d)', disciplina).group(1))
                except:
                    continue  # encargo_didatico = 0
            else:
                continue

            # Verificação dos estágios - somente graduação? @cpad dúvida.
            if any(nome_disciplina[0:8] in s for s in self.filtro_estagio_semidireta):
                Alerta.addAlerta("Pontuado com o estágio semi-direto (Art 35)." + nome_disciplina)
                if (float(encargo_didatico) > 60):
                    if (sum_estagio_semidireto >= 60.0):
                        encargo_didatico = 0
                        Alerta.addAlerta(" Encargo didático ZERADO (Art. 35, § 10): Máximo permitido atingido.")
                    else:
                        dif = abs(sum_estagio_semidireto - encargo_didatico)
                        encargo_didatico = dif
                        sum_estagio_semidireto += dif
                        Alerta.addAlerta(" Encargo didático LIMITADO (Art. 35, § 10): Máximo permitido atingido.")
            elif any(nome_disciplina[0:8] in s for s in self.filtro_estagio_indireta):
                Alerta.addAlerta(nome_disciplina + "(" + periodo + "):" + "Pontuado com o estágio indireto (Art 35).")
                if (float(encargo_didatico) > 15.0):
                    if (sum_estagio_indireto >= 15.0):
                        encargo_didatico = 0
                        Alerta.addAlerta(" Encargo didático ZERADO (Art. 35, § 10): Máximo permitido atingido.")
                    else:
                        dif = abs(sum_estagio_indireto - encargo_didatico)
                        encargo_didatico = dif
                        sum_estagio_indireto += dif
                        Alerta.addAlerta(
                            nome_disciplina + "(" + periodo + "):" + " estágio indireto (LIMITADO) (Art. 35, § 10).")
                        Alerta.addAlerta(" Maximo atingido! Encargo didático LIMITADO (Art. 35, § 10).")
            elif any(nome_disciplina[0:8] in s for s in self.filtro_estagio_direta):
                Alerta.addAlerta(nome_disciplina + "(" + periodo + "):" + "pontuado como estágio direto (Art 35).")

            elif (nome_disciplina.lower().find("estágio") != -1):
                Alerta.addAlerta(
                    "INFORMAÇÃO NECESSÁRIA: " + nome_disciplina + "(" + periodo + "): possívelmente pontuada erroneamente como orientação direta.")

            retorno_busca = [(x, y, z) for x, y, z in lista_disciplinas if ((x == periodo) and (y == nome_disciplina))]

            if (len(retorno_busca) > 0):
                if (remove_duplicatas):
                    Alerta.addAlerta(
                        "Atenção: a disciplina " + nome_disciplina + " aparece  duplicada  no semestre " + periodo +
                        "\n      e NÃO FOI computada (Obs. 4 Anexo I). Solicitar a chefia a documentação comprobatória de que"
                        "\n      a disciplina foi ministrada em turmas com horários diferentes e, se comprovado, SOMAR "
                        "n      " + str(encargo_didatico) + " de encargo didático no semestre.")
                    continue
                else:
                    Alerta.addAlerta(
                        "Atenção: a disciplina " + nome_disciplina + " aparece  duplicada  no semestre " + periodo +
                        "\n      e mas FOI computada (Obs. 4 Anexo I). Solicitar a chefia documentação que realmente comprove"
                        "\n      que a disciplina foi ministrada em turmas com horários diferentes e, se for o caso, REMOVER "
                        "\n      " + str(encargo_didatico) + " de encargo didático no semestre.")

            tupletDisciplina = (periodo, nome_disciplina, encargo_didatico)
            lista_disciplinas.append(tupletDisciplina)

        lista_disciplinas.sort(key=lambda tup: tup[0])  # sorts in place

        return lista_disciplinas
Пример #8
0
    def __get_detalhamento(self):
        output = self.__str__()  # resultado do parecer

        output += "== DETALHAMENTO DA PONTUAÇÃO == \n"
        output += "===== 1. Turmas de Graduação =====" "\n"
        output += formataPrint("", "Disciplinas da Graduação (Semestre, Código, Disciplina, Encargo didático)",
                               self.portal_docente.disciplinas_grad.lista_disciplinas) + "\n"

        output += (formataPrint("", "Encargo didático Graduação (média: " +
                                str(self.portal_docente.disciplinas_grad.media_encago_didatico) + ")",
                                self.portal_docente.disciplinas_grad.dic_encargo_didatico.items())) + "\n"

        output += (formataPrint("", "Pontuação Graduação (média: " +
                                str(self.portal_docente.disciplinas_grad.media_pontos) + ")",
                                self.portal_docente.disciplinas_grad.pontos_semestre.items())) + "\n"


        output += "===== 2. Turmas de Pós-Graduação =====" "\n"
        output += (formataPrint("", "Disciplinas da Pós-graduação (Semestre, Código, Disciplina, Encargo didático)",
                                self.portal_docente.disciplinas_posgrad.lista_disciplinas)) + "\n"
        output += (formataPrint("", "Encargo didático Pós-Graduação(média: " +
                                str(self.portal_docente.disciplinas_posgrad.media_encago_didatico) + ")",
                                self.portal_docente.disciplinas_posgrad.dic_encargo_didatico.items())) + "\n"
        output += (formataPrint("", "Pontuação Pós-graduação (média: " +
                                str(self.portal_docente.disciplinas_posgrad.media_pontos) + ")",
                                self.portal_docente.disciplinas_posgrad.pontos_semestre.items())) + "\n"


        output += "===== 3. Iniciações Científicas =====" "\n"
        output += formataPrint("", "Iniciações Científica (Título, Data Início, Data Término)",
                               self.portal_docente.iniciacoes_cientificas.lista_iniciacoes_cientificas) + "\n"

        output += "===== 4. Ações de Extensão =====" "\n"
        output += (formataPrint("",
                                "Ações de Extensão(Título, Data de Início, Data de Término, Papel do Docente (Lattes)",
                                self.portal_docente.acoes_extensao.lista_projetos)) + "\n"

        output += "===== 5. Projetos de Pesquisa =====" "\n"
        output += (formataPrint("",
                                "Projetos de Pesquisa (Título, Data de Início, Data de Término, Papel do Docente (Lattes))",
                                self.portal_docente.projetos_pesquisa.lista_projetos)) + "\n"
        output += ("Pontuação de Projetos de Pesquisa:" +
                   str(self.portal_docente.projetos_pesquisa.pontos)) + "\n"

        output += "===== 5. Orientações =====" "\n"
        output += (formataPrint("", "Orientações (Nível, Papel do Docente, Orientando, Data Início, Data Término",
                                self.portal_docente.orientacoes.lista_orientacoes)) + "\n"

        output += ("Pontuação de orientações (somente) do portal docente:" + str(self.portal_docente.orientacoes.pontos)) + "\n"

        output += "===== 6. Produção Bibliográfica =====" "\n"
        output += (formataPrint("", "Livros ()",
                                self.producao_intelectual_lattes.producao_bibliografica.lista_livros)) + "\n"

        output += (formataPrint("", "Capítulos de Livros ()",
                                self.producao_intelectual_lattes.producao_bibliografica.capitulos_livro)) + "\n"

        output += (formataPrint("", "Artigos em Periódicos()",
                                self.producao_intelectual_lattes.producao_bibliografica.artigos_periodicos)) + "\n"

        output += (formataPrint("", "Artigos em Eventos()",
                                self.producao_intelectual_lattes.producao_bibliografica.lista_artigos_eventos)) + "\n"

        output += ("Alertas:" + str(Alerta.texto_formatado()) + "\n")

        output += "\n Observação: análise automatizada buscando informações da: \n a) ficha funcional de progressão, " + \
                  "\n b) relatório funcional para progressão (portal docente.ufes.br), \n c) Currículo Lattes na data corrente."

        return output
Пример #9
0
                                       settings.path_xml_lattes,
                                       ficha_progressao)

        producao_intelectual_lattes = ProducaoIntelectual(settings.path_xml_lattes,
                                                          ficha_progressao)

        parecer = Parecer(portal_docente, ficha_progressao, producao_intelectual_lattes)

        parecer.emitir_parecer_progressao()

        return  parecer

if __name__ == "__main__":

    ficha_progressao = FichaFuncional(settings.path_ficha_funcional)

    portal_docente = PortalDocente(settings.path_portal_docente,
                                   settings.path_xml_lattes,
                                   ficha_progressao)

    producao_intelectual_lattes = ProducaoIntelectual(settings.path_xml_lattes,
                                                      ficha_progressao)

    parecer = Parecer(portal_docente, ficha_progressao, producao_intelectual_lattes)

    parecer.emitir_parecer_progressao()
    parecer.gravar_log()
    print(parecer)
    Alerta.print()

    def __parse_projetos(self):
        dados_lattes = self.xml_root.find('DADOS-GERAIS')
        nome_servidor_lattes = (dados_lattes.attrib['NOME-COMPLETO'])

        # Extraindo do texto os dados sobre as projetos
        projetos = re.findall(r'Nome:(.*?)Descrição:', self.__page_content)
        lista_projetos = []
        for projeto in projetos:
            nome_projeto = re.search(r'(.*?)Data de início:', projeto).group(1)

            data_inicial_str = re.search(
                r'Data de início:(.*?)Data de término', projeto).group(1)
            data_inicial_projeto = datetime.strptime(data_inicial_str,
                                                     '%d/%m/%Y').date()

            # Só irá computar projetos que iniciaram depois do início do interício devido a uma falha no portal docente
            # que não indica o término dos projetos.
            if (self.inicio_intersticio >
                    data_inicial_projeto):  # todo verificar CPAD
                continue

            data_final_str = re.search(r'Data de término:(.*?)Carga horária',
                                       projeto).group(1)
            if (data_final_str != ""):
                data_final = datetime.strptime(data_final_str,
                                               '%d/%m/%Y').date()
                # if(active_from_date != None) and (active_from_date > data_final):
                #     continue #todo verificar CPAD
            else:
                data_final = None

            # Verifica no XML do Lattes se é o coordenador. Caso não seja, é considerado integrante.
            str_papel_projeto = ""
            strProjeto = re.sub('[^a-z0-9]+', '', nome_projeto.lower())
            for projeto in (self.xml_root.findall(
                    './/PROJETO-DE-PESQUISA[@NATUREZA="PESQUISA"]')):
                nome_projeto_lattes = projeto.attrib['NOME-DO-PROJETO']
                nome_projeto_lattes = re.sub('[^a-z0-9]+', '',
                                             nome_projeto_lattes.lower())

                if (nome_projeto_lattes == strProjeto):
                    membro_equipe = projeto.find(
                        './/INTEGRANTES-DO-PROJETO[@FLAG-RESPONSAVEL="SIM"]')
                    nome = membro_equipe.attrib['NOME-COMPLETO']

                    if (nome == nome_servidor_lattes):
                        str_papel_projeto = "coordenador"
                    else:
                        str_papel_projeto = "integrante"
                    break

            if (str_papel_projeto == ""):
                str_papel_projeto = "não determinado"
                Alerta.addAlerta(
                    "Aviso: projeto de pesquisa '" + nome_projeto +
                    "' não está registrado no Lattes. "
                    "\n      O docente será considerando um participante (não coordenador) para efeito de pontuação. "
                    "\n      Se necessário, solicite documentação comprobatória e pontue manualmente."
                )

            tupletProjeto = (nome_projeto, data_inicial_projeto, data_final,
                             str_papel_projeto)
            lista_projetos.append(tupletProjeto)

        if (len(lista_projetos) < len(projetos)):
            Alerta.addAlerta(
                "Aviso: Foram encontrados projetos iniciados antes do início do interstício que "
                " ainda estão em aberto no portal docente por falha do sistema da UFES. "
                "\n      Se necessário, solicite documentação comprobatória e pontue manualmente."
            )
        return lista_projetos