package pt.estgp.estgweb.services.questionarios.pedagogico;
import org.apache.log4j.Logger;
import pt.estgp.estgweb.utils.Globals;
import pt.estgp.estgweb.domain.*;
import pt.estgp.estgweb.domain.dao.DaoFactory;
import pt.estgp.estgweb.services.jobs.ServiceJob;
import pt.estgp.estgweb.services.logresults.ILogMessages;
import pt.estgp.estgweb.services.logresults.LogMessageTypeEnum;
import pt.estgp.estgweb.services.logresults.impl.DefaultLogMessage;
import pt.estgp.estgweb.services.logresults.impl.DefaultLogMessages;
import pt.estgp.estgweb.web.exceptions.NotAuthorizedException;
import java.io.IOException;
import java.util.*;
/**
* Created by jorgemachado on 28/05/16.
*/
public class AnswersAlunosProcessor
extends ServiceJob
{
int unidadesNaoUtilizadas =
0;
int unidadesUtilizadas =
0;
int unidadesMarcadas =
0;
int unidadesNaoVistasProf =
0;
int unidadesNaoVistasAlunos =
0;
int cursosUtilizados =
0;
int respostasRequisitadas =
0;
private static 1.5.0/docs/api/java/util/logging/Logger.html">Logger logger =
1.5.0/docs/api/java/util/logging/Logger.html">Logger.
getLogger(AnswersAlunosProcessor.
class);
/**
* ############# JOB TASK ############
* ############# JOB TASK ############
* @return
* @throws Throwable
*/
@
1.5.0/docs/api/java/lang/Override.html">Override
protected ILogMessages runJobServiceTask
() throws 1.5.0/docs/api/java/lang/Throwable.html">Throwable
{
long questionarioId =
1.5.0/docs/api/java/lang/Long.html">Long.
parseLong(getParametersMap
().
get(ServiceJob.
JOB_questionario_id_KEY).
getObject());
DefaultLogMessages logMessages =
new DefaultLogMessages
();
/*****VERIFICACAO DE RESPOSTAS********/
long respostas = DaoFactory.
getQuestionarioDaoImpl().
getNumeroRespostas(questionarioId
);
if(respostas
> 0
)
{
logMessages.
addMessage(new DefaultLogMessage
("error.questionario.com.respostas.nao.pode.efetuar.op", LogMessageTypeEnum.
WARNING,
"Operação não permitida, Existem Respostas"));
logger.
warn(logMessages.
getLastMessage());
serviceLogError
(logMessages.
getLastMessage());
throw new NotAuthorizedException
("Nao tem autorização para agendar atribuições de cursos num questioário com respostas");
}
unidadesNaoUtilizadas =
0;
unidadesUtilizadas =
0;
unidadesMarcadas =
0;
unidadesNaoVistasProf =
0;
unidadesNaoVistasAlunos =
0;
cursosUtilizados =
0;
respostasRequisitadas =
0;
QuestionarioImpl q =
(QuestionarioImpl
) DaoFactory.
getQuestionarioDaoImpl().
load(questionarioId
);
//Colocamos já aqui o estado para nao se poder mudar o Ano e o Semestre
/**logging**/
1.5.0/docs/api/java/lang/String.html">String msg =
"Starting running service answers generation for questionario: " + q.
getId() +
" - " + q.
getiAnswersProcessorClass().
getTitle();
serviceLogInfo
(msg
);
logger.
info(msg
);
List
<Long
> cursosAfetosIds = DaoFactory.
getQuestionarioPedagogicoCursoAfetoDaoImpl().
findCursosAfetosIds(questionarioId
);
int count =
0;
UpdateCoursesAndUnitsJobService.
revertAllRespostasCandidatas(questionarioId,
this);
for(1.5.0/docs/api/java/lang/Long.html">Long cursoAfetoId : cursosAfetosIds
)
{
/** COMMIT OPERATION **/
count++
;
cursosUtilizados++
;
setProgress
((int)((((float)count
)/
((float)cursosAfetosIds.
size()))*100.0f
));
commitPartially
();
/** COMMIT OPERATION **/
QuestionarioPedagogicoCursoAfeto cu = DaoFactory.
getQuestionarioPedagogicoCursoAfetoDaoImpl().
get(cursoAfetoId
);
msg =
"(+) Iniciando atribuição de respostas de alunos para o curso " + cu.
getNome() +
" (" + cu.
getCodigoCurso() +
") escola " + cu.
getNomeInstituicao() +
"(" + cu.
getCodigoInstituicao() +
")";
logger.
info(msg
);
serviceLogInfo
(msg
);
int unidades
;
if(cu.
getUnidadesAfetas() !=
null)
{
unidades = cu.
getUnidadesAfetas().
size();
int countUnidades =
0;
for(QuestionarioPedagogicoUnidadeCurricularAfeta unidadeCurricularAfeta: cu.
getUnidadesAfetas())
{
countUnidades++
;
msg = unidadeCurricularAfeta.
isUsar() ? "(+)" :
"(----IGNORADA-----)";
msg +=
"(" + countUnidades +
"/" + unidades +
") Iniciando atribuição de Unidade Curricular Afeta " + unidadeCurricularAfeta.
getCodigoUnidade() +
" - " + unidadeCurricularAfeta.
getNome();
logger.
info(msg
);
serviceLogInfo
(msg
);
if(!unidadeCurricularAfeta.
isUsar())
{
unidadesNaoUtilizadas++
;
msg =
"!!! A unidade está marcada para NÃO SER UTILIZADA, passando à próxima";
serviceLogWarn
(msg
);
logger.
warn(msg
);
logMessages.
addMessage(new DefaultLogMessage
("questionario.answers.assigning", LogMessageTypeEnum.
WARNING,msg
));
}
else
{
CourseUnitImpl cuImpl =
(CourseUnitImpl
) DaoFactory.
getCourseUnitDaoImpl().
narrow(unidadeCurricularAfeta.
getCourseUnit());
CourseImpl courseImpl =
(CourseImpl
) DaoFactory.
getCourseDaoImpl().
narrow(unidadeCurricularAfeta.
getCourseUnit().
getCourse());
//boolean separateTurmas = false;
//try{
// separateTurmas = ImportCourseService.loadCourseYearTurmasPolicy(Integer.parseInt(unidadeCurricularAfeta.getCursoAfeto().getCodigoCurso()), q.getYear(), logMessages, this);
//}catch(Throwable e)
//{
// msg = "!!! Código de Curso inválido a tentar verificar politica de turmas separadas, vai assumir falso";
// serviceLogError(msg);
// logger.error(msg);
// logMessages.addMessage(new DefaultLogMessage("questionario.answers.assigning", LogMessageTypeEnum.ERROR,msg));
//}
unidadesUtilizadas++
;
verificaAlertasUnidade
(logMessages, unidadeCurricularAfeta
);
List
<CourseUnitImpl.
Tipologia> tipologias
;
if(unidadeCurricularAfeta.
getCursoAfeto().
isUsarTipologias())
{
tipologias = cuImpl.
getTipologiasClass().
obtainMergeTipologias();
//TODO ALTERAR QUANDO GERIRMOS USADAS PARA JA SO SE USAM SUMARIOS
for(CourseUnitImpl.
Tipologia tMerge: tipologias
)
{
//AQUI E QUE SE TEM DE TER CUIDADO
//TEMOS DE OLHAR PARA AS MARCADAS PRA NAO USAR E AQUI USA-SE ISSO
//COMO TESTE
//if(tMerge.isSumario())
//{
if(!tMerge.
isExclude())
tMerge.
setUse(true);
else
tMerge.
setUse(false);
// break;
//}
}
}
else
{
tipologias = cuImpl.
getTipologiasClass().
obtainTipologiasSimples(unidadeCurricularAfeta.
getCourseUnit());
//TODO ALTERAR QUANDO GERIRMOS USADAS PARA JA SO SE USAM SUMARIOS
for(CourseUnitImpl.
Tipologia tMerge: tipologias
)
{
if(!tMerge.
isExclude())
{
tMerge.
setUse(true);
}
else
tMerge.
setUse(false);
}
}
/**
* Iterar as tipologias e tentar criar com as turmas e os docentes
* Os que não derem resultados devolvem falso e são retirados da lista
* A verificação do falso é feita sempre que uma turma falhe a abrir ou tenha zero alunos
*/
Iterator
<CourseUnitImpl.
Tipologia> iterTipologias = tipologias.
iterator();
while(iterTipologias.
hasNext())
{
CourseUnitImpl.
Tipologia tipologia = iterTipologias.
next();
boolean criada = criarTipologiasRequisitadas
(logMessages, q,
(QuestionarioPedagogicoUnidadeCurricularAfetaImpl
) unidadeCurricularAfeta,
(QuestionarioPedagogicoCursoAfetoImpl
)cu, cuImpl, tipologia
);
if(criada
)
{
((QuestionarioPedagogicoUnidadeCurricularAfetaImpl
)unidadeCurricularAfeta
).
incStatTipologiasRequisitadas();
((QuestionarioPedagogicoCursoAfetoImpl
)cu
).
incStatTipologiasRequisitadas();
}
else
{
iterTipologias.
remove();
}
}
//TODO TIPOLOGIAS ASSOCIACAO README
//CASO ALGUM TENHA FALHADO VAMOS ENTAO ADICIONA-LOS AS TURMAS TODAS
//OU NAO TENHA VINDO TIPOLOGIA PARA ELE
//todo ESTE PROBLEMA DEVE SER RESOLVIDO COM A ADICAO DE TIPOLOGIAS SIMPLES PARA AS ASSOCIACOES
//todo T_DOC_TURMA Mudar no DisciplinaDao na importação de cursos
//NOVO 2017 vai ser resolvido adicionando então as tipologias simples nas tipologias T_DOC_TURMA
// uma vez que o metodo obtainTipologias Simples ja comtemla a adição dessas tipologias t_doc_turma
Map
<String,Teacher
> professoresEsperados =
new HashMap
<String, Teacher
>();
for(Teacher t: cuImpl.
getTeachers())
{
professoresEsperados.
put(t.
getSigesCode() +
"", t
);
}
for(CourseUnitImpl.
Tipologia tMerge: tipologias
)
{
professoresEsperados.
remove(tMerge.
getCdDocente());
}
List
<CourseUnitImpl.
Tipologia> tipologiasEmFalta = criarTipologiasRequisitadasSimplesParaProfsForaDasTurmasPorFaltaDeSumarios
(logMessages, q, unidadeCurricularAfeta, cuImpl, professoresEsperados
);
//tipologias.addAll(tipologiasEmFalta);
for(CourseUnitImpl.
Tipologia emFalta: tipologiasEmFalta
)
{
msg =
"Criando tipologia em falta (docente:" + emFalta.
getCdDocente() +
", turma: " + emFalta.
getCdTurma() +
") para a unidade: " + unidadeCurricularAfeta.
getCodigoUnidade() +
" " + unidadeCurricularAfeta.
getNome() +
" do curso de " + unidadeCurricularAfeta.
getCursoAfeto().
getNome() +
"(" + unidadeCurricularAfeta.
getCursoAfeto().
getCodigoCurso() +
")";
serviceLogWarn
(msg
);
logger.
warn(msg
);
logMessages.
addMessage(new DefaultLogMessage
("questionario.answers.assigning", LogMessageTypeEnum.
WARNING,msg
));
((QuestionarioPedagogicoUnidadeCurricularAfetaImpl
)unidadeCurricularAfeta
).
incStatTipologiasRequisitadas();
((QuestionarioPedagogicoCursoAfetoImpl
)cu
).
incStatTipologiasRequisitadas();
criarTipologiasRequisitadas
(logMessages, q,
(QuestionarioPedagogicoUnidadeCurricularAfetaImpl
) unidadeCurricularAfeta,
(QuestionarioPedagogicoCursoAfetoImpl
)cu, cuImpl, emFalta
);
}
}
}
}
}
/** COMMIT OPERATION **/
setProgress
(100
);
commitPartially
();
DaoFactory.
getQuestionarioDaoImpl().
update(q
);
/** COMMIT OPERATION **/
msg =
"Set courses state as " + QuestionarioImpl.
SubStatePedagogico.
ANSWERS_ASSIGNED.
name();
serviceLogInfo
(msg
);
logger.
info(msg
);
q.
setSubStatePedagogicoClass(QuestionarioImpl.
SubStatePedagogico.
ANSWERS_ASSIGNED);
commitPartially
();
serviceLogInfo
("######################################");
serviceLogInfo
("######################################");
serviceLogInfo
("#unidadesNaoUtilizadas:" + unidadesNaoUtilizadas
);
serviceLogInfo
("#unidadesUtilizadas:" + unidadesUtilizadas
);
serviceLogInfo
("#unidadesMarcadas:" + unidadesMarcadas
);
serviceLogInfo
("#unidadesNaoVistasProf:" + unidadesNaoVistasProf
);
serviceLogInfo
("#unidadesNaoVistasAlunos:" + unidadesNaoVistasAlunos
);
serviceLogInfo
("#cursosUtilizados:" + cursosUtilizados
);
serviceLogInfo
("#respostasRequisitadas:" + respostasRequisitadas
);
logger.
info("######################################");
logger.
info("######################################");
logger.
info("#unidadesNaoUtilizadas:" + unidadesNaoUtilizadas
);
logger.
info("#unidadesUtilizadas:" + unidadesUtilizadas
);
logger.
info("#unidadesMarcadas:" + unidadesMarcadas
);
logger.
info("#unidadesNaoVistasProf:" + unidadesNaoVistasProf
);
logger.
info("#unidadesNaoVistasAlunos:" + unidadesNaoVistasAlunos
);
logger.
info("#cursosUtilizados:" + cursosUtilizados
);
logger.
info("#respostasRequisitadas:" + respostasRequisitadas
);
return logMessages
;
}
public static boolean canUse
(QuestionarioPedagogicoTipologiaRequisitada tipologiaRequisitada,CourseUnitImpl cuImpl
) throws 1.5.0/docs/api/java/io/IOException.html">IOException
{
ArrayList
<CourseUnitImpl.
Tipologia> tipologiasMerged = cuImpl.
getTipologiasClass().
obtainMergeTipologias();
for(CourseUnitImpl.
Tipologia tipologia: tipologiasMerged
)
{
CourseUnitImpl.
Tipologia proto =
new CourseUnitImpl.
Tipologia();
proto.
setCdDocente(tipologiaRequisitada.
getCdDocente());
proto.
setCdTurma(tipologiaRequisitada.
getCdTurma());
proto.
setCdTipologia(tipologiaRequisitada.
getCdTipologia());
if(proto.
equals(tipologia
))
{
if(tipologia.
isExclude())
return false;
}
}
return true;
}
private List
<CourseUnitImpl.
Tipologia> criarTipologiasRequisitadasSimplesParaProfsForaDasTurmasPorFaltaDeSumarios
(DefaultLogMessages logMessages, QuestionarioImpl q, QuestionarioPedagogicoUnidadeCurricularAfeta unidadeCurricularAfeta, CourseUnitImpl cuImpl, Map
<String, Teacher
> teachersAffected
) {
1.5.0/docs/api/java/lang/String.html">String msg
;
List
<CourseUnitImpl.
Tipologia> tipologias =
new ArrayList
<CourseUnitImpl.
Tipologia>();
if(teachersAffected.
size() > 0)
{
msg =
"!!! Existem " + teachersAffected.
size() +
"professores que não tinham tipologias de sumário associadas na unidade " + cuImpl.
getCode() +
"(" + cuImpl.
getName() +
")" +
", associando uma tipologia simples por turma para este docente";
serviceLogWarn
(msg
);
logger.
warn(msg
);
logMessages.
addMessage(new DefaultLogMessage
("questionario.answers.assigning", LogMessageTypeEnum.
WARNING,msg
));
for(Teacher t: teachersAffected.
values())
{
if(cuImpl.
getTurmas() !=
null)
{
for(CourseUnitTurma turma: cuImpl.
getTurmas())
{
msg =
"!!! Criando tipologia Simples para (Prof: " + t.
getSigesCode() +
" " + t.
getName() +
" turma: " + turma.
getTurma() +
" ) " ;
serviceLogWarn
(msg
);
logger.
warn(msg
);
logMessages.
addMessage(new DefaultLogMessage
("questionario.answers.assigning", LogMessageTypeEnum.
WARNING,msg
));
CourseUnitImpl.
Tipologia tipo =
new CourseUnitImpl.
Tipologia();
tipo.
setCdDocente(t.
getSigesCode() +
"");
tipo.
setCdTipologia(Globals.
BACO_TIPOLOGIA_SIMPLES_VIRTUAL_CODE);
tipo.
setCdTurma(turma.
getTurma());
tipo.
setDsTipologia(Globals.
BACO_TIPOLOGIA_SIMPLES_DS);
tipo.
setUse(true);
tipologias.
add(tipo
);
}
}
}
}
return tipologias
;
}
/**
* Devolve true se conseguiu criar pelo menos uma resposta a um aluno caso contrario a turma pode não existir ou ser lixo
* @param logMessages
* @param q
* @param unidadeCurricularAfeta
* @param cursoAfeto
* @param cuImpl
* @param tMerge
* @return
*/
private boolean criarTipologiasRequisitadas
(DefaultLogMessages logMessages,
QuestionarioImpl q,
QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidadeCurricularAfeta,
QuestionarioPedagogicoCursoAfetoImpl cursoAfeto,
CourseUnitImpl cuImpl,
CourseUnitImpl.
Tipologia tMerge
) {
1.5.0/docs/api/java/lang/String.html">String msg
;
//NESTE MOMENTO ELE MARCA TUDO COMO REQUISITADA NA LINHA
if(tMerge.
isUse())
{
//todo Criar Tipologia Requisitada
1.5.0/docs/api/java/lang/String.html">String cdDocente = tMerge.
getCdDocente();
1.5.0/docs/api/java/lang/String.html">String cdTipologia = tMerge.
getCdTipologia();
1.5.0/docs/api/java/lang/String.html">String dsTipologia = tMerge.
getDsTipologia();
1.5.0/docs/api/java/lang/String.html">String cdTurma = tMerge.
getCdTurma();
QuestionarioPedagogicoTipologiaRequisitadaImpl tipo = DomainObjectFactory.
createQuestionarioPedagogicoTipologiaRequisitadaImpl();
tipo.
setCdDocente(cdDocente
);
tipo.
setCdTipologia(cdTipologia
);
tipo.
setCdTurma(cdTurma
);
tipo.
setDsTipologia(dsTipologia
);
tipo.
setUnidadeAfeta(unidadeCurricularAfeta
);
try{
CourseUnitImpl.
TipologiaPersistent tMergePersistente = cuImpl.
loadPersistent(tMerge
);
tipo.
setNomeDocente(tMergePersistente.
getTeacher().
getName());
tipo.
setDocenteAfeto(tMergePersistente.
getTeacher());
tipo.
setTurmaAfeta(tMergePersistente.
getCourseUnitTurma());
DaoFactory.
getQuestionarioPedagogicoTipologiaRequisitadaDaoImpl().
save(tipo
);
return criarAlunosRequisitados
(q, tipo, tMergePersistente.
getCourseUnitTurma(),unidadeCurricularAfeta,cursoAfeto
);
}
catch(CourseUnitImpl.
TipologiaLoadExeption exp
)
{
msg =
"Tipologia não devolve persistente " + exp.
getMessage() +
" (docente:" + tMerge.
getCdDocente() +
", turma: " + tMerge.
getCdTurma() +
") para a unidade: " + unidadeCurricularAfeta.
getCodigoUnidade() +
" " + unidadeCurricularAfeta.
getNome() +
" do curso de " + cursoAfeto.
getNome() +
"(" + cursoAfeto.
getCodigoCurso() +
")";
serviceLogError
(msg
);
logger.
error(msg
);
logMessages.
addMessage(new DefaultLogMessage
("questionario.answers.assigning", LogMessageTypeEnum.
ERROR,msg
));
return false;
}
//Depois o home tem de procurar respostas requisitadas sem resposta
//para cada uma vai pelo aluno requisitado buscar a turma o docente e pela
//unidade afeta a unidade e o curso
//apresenta o questionario com o id da resposta requisitada
}
return false;
}
/**
* Return true se encotrou pelo menos um aluno
* @param q
* @param tipo
* @param turma
* @param unidadeAfeta
* @param cursoAfeto
* @return
*/
private boolean criarAlunosRequisitados
(QuestionarioImpl q,
QuestionarioPedagogicoTipologiaRequisitadaImpl tipo,
CourseUnitTurma turma,
QuestionarioPedagogicoUnidadeCurricularAfetaImpl unidadeAfeta,
QuestionarioPedagogicoCursoAfetoImpl cursoAfeto
)
{
if(turma.
getStudents() !=
null && turma.
getStudents().
size()>0
)
{
for(Student s: turma.
getStudents())
{
unidadeAfeta.
incStatRespostasRequisitadas();
cursoAfeto.
incStatRespostasRequisitadas();
QuestionarioRespostaRequisitadaImpl respostaRequisitada = DomainObjectFactory.
createQuestionarioRespostaRequisitadaImpl();
respostaRequisitada.
setQuestionario(q
);
respostaRequisitada.
setUser(s
);
DaoFactory.
getQuestionarioRespostaRequisitadaDaoImplImpl().
save(respostaRequisitada
);
QuestionarioPedagogicoAlunoRequisitadoImpl alunoRequisitado = DomainObjectFactory.
createQuestionarioPedagogicoAlunoRequisitadoImpl();
alunoRequisitado.
setTipologiaRequisitada(tipo
);
alunoRequisitado.
setAluno(s
);
alunoRequisitado.
setRespostaRequisitada(respostaRequisitada
);
DaoFactory.
getQuestionarioPedagogicoAlunoRequisitadoDaoImpl().
save(alunoRequisitado
);
respostasRequisitadas++
;
}
return true;
}
return false;
}
private void verificaAlertasUnidade
(DefaultLogMessages logMessages, QuestionarioPedagogicoUnidadeCurricularAfeta unidadeCurricularAfeta
) {
1.5.0/docs/api/java/lang/String.html">String msg
;
if(unidadeCurricularAfeta.
isMarked() ||
!unidadeCurricularAfeta.
isVista() ||
!unidadeCurricularAfeta.
isVistaProfs())
{
msg =
" !!!! ALERTA :--> ";
if(unidadeCurricularAfeta.
isMarked())
{
unidadesMarcadas++
;
msg+=
" MARCADA ; ";
}
if(!unidadeCurricularAfeta.
isVista())
{
unidadesNaoVistasAlunos++
;
msg+=
" NÃO VISTA ALUNOS ; ";
}
if(!unidadeCurricularAfeta.
isVistaProfs())
{
unidadesNaoVistasProf++
;
msg+=
" NÃO VISTA PROFS ; ";
}
serviceLogWarn
(msg
);
logger.
warn(msg
);
logMessages.
addMessage(new DefaultLogMessage
("questionario.answers.assigning", LogMessageTypeEnum.
WARNING,msg
));
}
}
}