diff --git a/build.gradle b/build.gradle index 0779dda..6ff2e66 100644 --- a/build.gradle +++ b/build.gradle @@ -58,6 +58,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'com.github.chen0040:java-lda:1.0.4' + // Use JUnit test framework testImplementation 'junit:junit:4.13' } diff --git a/src/main/java/sacip/sti/agents/GrouperAgent.java b/src/main/java/sacip/sti/agents/GrouperAgent.java index 1326632..231b7ec 100644 --- a/src/main/java/sacip/sti/agents/GrouperAgent.java +++ b/src/main/java/sacip/sti/agents/GrouperAgent.java @@ -1,35 +1,190 @@ package sacip.sti.agents; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Map; +import com.github.chen0040.data.utils.TupleTwo; +import com.github.chen0040.lda.Doc; +import com.github.chen0040.lda.Lda; +import com.github.chen0040.lda.LdaResult; +import org.midas.as.AgentServer; import org.midas.as.agent.templates.Agent; import org.midas.as.agent.templates.LifeCycleException; import org.midas.as.agent.templates.ServiceException; +import org.midas.as.manager.execution.ServiceWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import sacip.sti.dataentities.Student; -public class GrouperAgent extends Agent{ +public class GrouperAgent extends Agent { + + private static Logger LOG = LoggerFactory.getLogger(AgentServer.class); @Override public void provide(String service, Map in, List out) throws ServiceException { - // TODO Auto-generated method stub - if(service.equals("getStudentGroups")) - { - System.out.println("Buscando alunos no banco"); - System.out.println("Classificando alunos"); - - Student aluno = (Student) in.get("estudante"); - - System.out.println("Selecionando cluster de aluno "+aluno.getName()+" requisitado"); - System.out.println("retornando grupo"); + + try { + switch (service) { + case "getStudentGroups": + out.add(findStudentSimilars((Student) in.get("estudante"))); + break; + + default: + break; + } + } catch (Exception e) { + + } + if (service.equals("getStudentGroups")) { + try { + + } catch (Exception e) { + LOG.error("ERRO NO AGENT AGRUPADOR", e); + } } } @Override protected void lifeCycle() throws LifeCycleException, InterruptedException { // TODO Auto-generated method stub + + } + + public static void main(String[] args) { + System.setProperty("hadoop.home.dir", "c:\\winutil\\"); + GrouperAgent agent = new GrouperAgent(); + //agent.findStudentGroup(null); + } + + public List findStudentGroup(Student alunoRequisitado) + { + //List estudantes = getUsers(); + List grupo = new ArrayList<>(); + + List docs = Arrays.asList("carros animes youtube História", "comédia animes História Livros", "monstros cultura comédia Tecnologia", "Livros", "mitologia animes", "Livros matemática"); + + Lda method = new Lda(); + method.setTopicCount(3); + method.setMaxVocabularySize(20000); + //method.setStemmerEnabled(true); + //method.setRemoveNumbers(true); + //method.setRemoveXmlTag(true); + //method.addStopWords(Arrays.asList("we", "they")); + + LdaResult result = method.fit(docs); + + + // //System.out.println("Topic Count: "+result.topicCount()); + // for(int topicIndex = 0; topicIndex < result.topicCount(); ++topicIndex){ + // String topicSummary = result.topicSummary(topicIndex); + // List> topKeyWords = result.topKeyWords(topicIndex, 10); + // List> topStrings = result.topDocuments(topicIndex, 5); + + // //System.out.println("Topic #" + (topicIndex+1) + ": " + topicSummary); + + // for(TupleTwo entry : topKeyWords){ + // String keyword = entry._1(); + // int score = entry._2(); + // //System.out.println("Keyword: " + keyword + "(" + score + ")"); + // } + + // for(TupleTwo entry : topStrings){ + // double score = entry._2(); + // int docIndex = entry._1().getDocIndex(); + // String docContent = entry._1().getContent(); + // //System.out.println("Doc (" + docIndex + ", " + score + ")): " + docContent); + // } + // } + + for(Doc doc : result.documents()){ + List> topTopics = doc.topTopics(3); + System.out.println("Doc: {"+doc.getDocIndex()+"}"+"TOP TOPIC: {"+topTopics.get(0)._1()+"}"); + } + + return grupo; } + private List findStudentSimilars(Student alunoRequisitado) + { + List estudantes = getUsers(); + + if(estudantes.size()<20) + { + return new ArrayList<>(); + } + + List sortedStudents = new ArrayList(){ + @Override + public boolean add(Student e) { + super.add(e); + Collections.sort(this, new Comparator(){ + @Override + public int compare(Student o1, Student o2) { + return o2.pontos-o1.pontos; + } + }); + return true; + } + }; + + for (Student student : estudantes) + { + List preferencias = student.getPreferencias(); + + if(!alunoRequisitado.getName().equals(student.getName())) + { + for (String preferencia : preferencias) + { + if(alunoRequisitado.getPreferencias().contains(preferencia)) + { + student.pontos++; + } + // else{ + // student.pontos--; + // } + } + + if(student.getNivelEducacional().equals(alunoRequisitado.getNivelEducacional())) + { + student.pontos+=5; + } + sortedStudents.add(student); + } + } + + List grupoDe10 = new ArrayList<>(); + + for (int i = 0; i < 10; i++) { + grupoDe10.add(sortedStudents.get(i)); + } + + return grupoDe10; + } + + private List getUsers() + { + try + { + ServiceWrapper pegarEstudantes = require("SACIP", "findStudents"); + List result = pegarEstudantes.run(); + if(result.get(0) instanceof String) + { + return null; + } + return (List) result.get(0); + } + catch (Exception e) + { + LOG.error("ERRO AO REQUISITAR USUARIOS DO SISTEMA", e); + return null; + } + } + + } diff --git a/src/main/java/sacip/sti/agents/PedagogicalAgent.java b/src/main/java/sacip/sti/agents/PedagogicalAgent.java index b779c74..d7d7df4 100644 --- a/src/main/java/sacip/sti/agents/PedagogicalAgent.java +++ b/src/main/java/sacip/sti/agents/PedagogicalAgent.java @@ -37,7 +37,7 @@ private void montarAlunoExemplo() List preferencias = new ArrayList<>(); preferencias.add("animes"); preferencias.add("filmes"); - this.student = new Student("Adson", "123456", "link", "masculino", 24, "graduação", preferencias); + preferencias.add("jogos"); List trilha = new ArrayList(){{ add("2dcznTNvej"); add("Jvp1ma0QEN"); @@ -45,7 +45,7 @@ private void montarAlunoExemplo() add("tsxlrStu9a"); add("UlGW3aVSZI"); }}; - this.student.setTrilha(trilha); + this.student = new Student("Adson", "123456", "link", "masculino", 24, "Graduação", preferencias, trilha); } private void registrarConteudosDaTrilhaDoAluno() @@ -115,7 +115,7 @@ private String suggestContent() //Pedir recomendação para o recomendador ServiceWrapper servicoGetContent = require("SACIP", "getRecommendedContent"); servicoGetContent.addParameter("estudante", getAluno()); - servicoGetContent.addParameter("grupo", grupo); + servicoGetContent.addParameter("grupo", grupo.get(0)); servicoGetContent.addParameter("trilha", this.trilha); List resultado = servicoGetContent.run(); if(resultado.isEmpty()) diff --git a/src/main/java/sacip/sti/agents/RecommenderAgent.java b/src/main/java/sacip/sti/agents/RecommenderAgent.java index 0e28900..3c36386 100644 --- a/src/main/java/sacip/sti/agents/RecommenderAgent.java +++ b/src/main/java/sacip/sti/agents/RecommenderAgent.java @@ -5,11 +5,11 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import org.midas.as.AgentServer; import org.midas.as.agent.templates.Agent; @@ -72,19 +72,6 @@ public int compare(Content o1, Content o2) { try { - List caracteristicas = new ArrayList<>(); - - if(!grupo.isEmpty()) - { - System.out.println("Verificando semelhanças entre alunos"); - - caracteristicas.add("exemplo"); - } - else - { - caracteristicas.addAll(preferenciasAluno); - } - //Verificar os tópicos e níveis que o aluno utilizou HashMap> nivelETopico = descobrirNiveisETopicos(trilha); Integer[] niveisFeitos = nivelETopico.keySet().toArray(new Integer[nivelETopico.size()]); @@ -98,6 +85,21 @@ public int compare(Content o1, Content o2) { return "não há conteúdos"; } List conteudos = (List) resultado.get(0); + List conteudosDoGrupoNaoFeitos = new ArrayList<>(); + if(!grupo.isEmpty()) + { + //VERIFICAR TRILHAS E PEGAR CONTEUDOS UTILIZADOS NOS SEMELHANTES + List conteudosDasTrilhas = filtrarConteudosDasTrilhasDosAlunosDoGrupo(grupo, conteudos); + + for (Content content : conteudosDasTrilhas) { + if(!aluno.getTrilha().contains(content.getName())) + { + conteudos.remove(content); + conteudosDoGrupoNaoFeitos.add(content); + } + } + } + //CONTEUDOS DO TÓPICO EM QUE ELE ESTÁ @@ -110,7 +112,7 @@ public int compare(Content o1, Content o2) { conteudosPorNovasTaxonomias = descobrirConteudosDeTaxonomia(conteudos, taxonomiasPorTopicos); //FILTRAR POR TAGS - conteudosPorNovasTaxonomias = filtrarConteudosPorTags(conteudosPorNovasTaxonomias, caracteristicas); + conteudosPorNovasTaxonomias = filtrarConteudosPorTags(conteudosPorNovasTaxonomias, preferenciasAluno); } @@ -145,11 +147,12 @@ public int compare(Content o1, Content o2) { { conteudos = filtrarConteudosPorTopicos(conteudos, topicosFaltantes); } - conteudos = filtrarConteudosPorTags(conteudos, caracteristicas); + conteudos = filtrarConteudosPorTags(conteudos, preferenciasAluno); Set conteudosFiltrados = new HashSet<>(); conteudosFiltrados.addAll(conteudosPorNovasTaxonomias); conteudosFiltrados.addAll(conteudos); + conteudosFiltrados.addAll(conteudosDoGrupoNaoFeitos); //PRIORIZAR POR PONTOS for (Content content : conteudosFiltrados) { @@ -161,8 +164,14 @@ public int compare(Content o1, Content o2) { sortedContent.add(content); } + List top10Conteudos = new ArrayList<>(); + + for (int i = 0; i < 10; i++) { + top10Conteudos.add(sortedContent.get(i)); + } + //retornando conteudos - String exercicio = sortedContent.toString(); + String exercicio = top10Conteudos.toString(); return exercicio; } catch (Exception e) @@ -324,4 +333,61 @@ private List descobrirConteudosDeTaxonomia(List conteudos, Map return conteudosRecomendados; } + + private List filtrarConteudosDasTrilhasDosAlunosDoGrupo(List grupo, List conteudos) + { + List conteudosEmTodos = new ArrayList<>(); + + Map conteudosDoGrupo = new HashMap<>(); + + for (Student aluno : grupo) + { + List trilha = aluno.getTrilha(); + for (String conteudo : trilha) { + if(conteudosDoGrupo.containsKey(conteudo)) + { + conteudosDoGrupo.put(conteudo, conteudosDoGrupo.get(conteudo)+1); + } + else + { + conteudosDoGrupo.put(conteudo, 1); + } + } + } + + Map conteudosOrdenados = sortByValue(conteudosDoGrupo); + + if(conteudosOrdenados.size()>10) + { + conteudosOrdenados = conteudosOrdenados.entrySet().stream() + .limit(10) + .collect(LinkedHashMap::new, (m, e) -> m.put(e.getKey(), e.getValue()), Map::putAll); + + } + + for (Entry entry : conteudosOrdenados.entrySet()) + { + for (Content content : conteudos) { + if(content.getName().equals(entry.getKey())) + { + content.pontos+=entry.getValue(); + conteudosEmTodos.add(content); + } + } + } + + return conteudosEmTodos; + } + + public > Map sortByValue(Map map) { + List> list = new ArrayList<>(map.entrySet()); + list.sort(Entry.comparingByValue()); + Collections.reverse(list); + Map result = new LinkedHashMap<>(); + for (Entry entry : list) { + result.put(entry.getKey(), entry.getValue()); + } + + return result; + } } diff --git a/src/main/java/sacip/sti/components/DBConnection.java b/src/main/java/sacip/sti/components/DBConnection.java index bd7a638..d254a89 100644 --- a/src/main/java/sacip/sti/components/DBConnection.java +++ b/src/main/java/sacip/sti/components/DBConnection.java @@ -35,65 +35,71 @@ public DBConnection() { @Override public void provide(String service, Map in, List out) throws ServiceException { - switch (service) - { - case "createStudent": - out.add(createUser((Student)in.get("conta"))); - break; - - case "findStudents": - out.add(getUsers(in)); - break; - - case "editStudent": - out.add(editUser((String)in.get("name"), (String)in.get("attrName"), (String)in.get("newValue"))); - break; - - case "editStudentListAttr": - out.add(editUserListAttr((String)in.get("name"), (String)in.get("attrName"), (JsonNode)in.get("newValue"))); - break; - - case "getLogsDoAluno": - out.add(getUserLogInformation((String)in.get("name"), (String)in.get("type"))); - break; - - case "deleteStudent": - out.add(deleteUser((String) in.get("name"))); - break; - - case "storeStudentUseData": - out.add(addClickInformation((String)in.get("name"), (Map)in.get("data"))); - break; - - case "storeStudentContentUse": - out.add(addContentUseInformation((String)in.get("name"), (JsonNode)in.get("content"))); - break; - - case "getStudentsContentUse": - out.add(getUserLogInformation((String)in.get("name"), (String)in.get("type"))); - break; - - case "createContent": - out.add(createContent((Content)in.get("conteudo"), (String)in.get("conteudoRelacionado"), (int)in.get("valorRelacao"))); - break; - - case "findContents": - out.add(getContents(in)); - break; - - case "getContentByTags": - out.add(getContentsByTags((List) in.get("tags"))); - break; - - case "editContent": - out.add(editContent((String)in.get("name"), (String)in.get("attrName"), (String)in.get("newValue"))); - break; - - case "deleteContent": - out.add(deleteContent((String) in.get("name"))); - break; - + try { + switch (service) + { + case "createStudent": + out.add(createUser((Student)in.get("conta"))); + break; + + case "findStudents": + out.add(getUsers(in)); + break; + + case "editStudent": + out.add(editUser((String)in.get("name"), (String)in.get("attrName"), (String)in.get("newValue"))); + break; + + case "editStudentListAttr": + out.add(editUserListAttr((String)in.get("name"), (String)in.get("attrName"), (JsonNode)in.get("newValue"))); + break; + + case "getLogsDoAluno": + out.add(getUserLogInformation((String)in.get("name"), (String)in.get("type"))); + break; + + case "deleteStudent": + out.add(deleteUser((String) in.get("name"))); + break; + + case "storeStudentUseData": + out.add(addClickInformation((String)in.get("name"), (Map)in.get("data"))); + break; + + case "storeStudentContentUse": + out.add(addContentUseInformation((String)in.get("name"), (JsonNode)in.get("content"))); + break; + + case "getStudentsContentUse": + out.add(getUserLogInformation((String)in.get("name"), (String)in.get("type"))); + break; + + case "createContent": + out.add(createContent((Content)in.get("conteudo"), (String)in.get("conteudoRelacionado"), (int)in.get("valorRelacao"))); + break; + + case "findContents": + out.add(getContents(in)); + break; + + case "getContentByTags": + out.add(getContentsByTags((List) in.get("tags"))); + break; + + case "editContent": + out.add(editContent((String)in.get("name"), (String)in.get("attrName"), (String)in.get("newValue"))); + break; + + case "deleteContent": + out.add(deleteContent((String) in.get("name"))); + break; + + } + } catch (Exception e) { + out.add(e.getMessage()); + LOG.error("ERRO NOS SERVICOS DE CONEXAO DO BANCO DE DADOS", e); } + } private Student instanceStudent(Map in) @@ -103,9 +109,10 @@ private Student instanceStudent(Map in) (String)in.get("password"), (String)in.get("avatar"), (String)in.get("genero"), - (Integer)in.get("idade"), + ((Long)in.get("idade")).intValue(), (String)in.get("nivelEdu"), - (List) in.get("preferencias")); + (List) in.get("preferencias"), + (List) in.get("trilha")); } catch (Exception e) { LOG.error("Não foi possível instanciar o estudante", e); return null; @@ -278,6 +285,7 @@ private Object getUsers(Map attributes) { { //Cria query necessária StringBuilder query = new StringBuilder("MATCH (n:USER)"); + if(!attributes.isEmpty()) for (Map.Entry entry : attributes.entrySet()) { query.append("\nWHERE n."); query.append(entry.getKey()); @@ -290,6 +298,14 @@ private Object getUsers(Map attributes) { } query.deleteCharAt(query.length()-1); } + else if(entry.getValue() instanceof Integer[]) + { + Integer[] attrs = (Integer[]) entry.getValue(); + for (Integer attr : attrs) { + query.append(""+attr+","); + } + query.deleteCharAt(query.length()-1); + } else { query.append("'"+entry.getValue()+"'"); @@ -432,6 +448,7 @@ private Object getContents(Map attributes) try { //Cria query necessária StringBuilder query = new StringBuilder("MATCH (n:CONTENT)"); + if(!attributes.isEmpty()) for (Map.Entry entry : attributes.entrySet()) { query.append("\nWHERE n."); query.append(entry.getKey()); diff --git a/src/main/java/sacip/sti/dataentities/Student.java b/src/main/java/sacip/sti/dataentities/Student.java index 81f0177..c5c6f1e 100644 --- a/src/main/java/sacip/sti/dataentities/Student.java +++ b/src/main/java/sacip/sti/dataentities/Student.java @@ -25,11 +25,13 @@ public class Student extends MidasBean{ private List errosDoEstudante; private Map tempoTag; + public int pontos = 0; + public Student() { super(); } - public Student(String name, String password, String avatar, String genero, int idade, String nivelEducacional, List preferencias) { + public Student(String name, String password, String avatar, String genero, int idade, String nivelEducacional, List preferencias, List trilha) { this.name = name; this.password = password; this.avatar = avatar; @@ -37,7 +39,7 @@ public Student(String name, String password, String avatar, String genero, int i this.idade = idade; this.nivelEducacional = nivelEducacional; this.preferencias = preferencias; - this.trilha = new ArrayList<>(); + this.trilha = trilha; this.exerciciosResolvidos = new ArrayList<>(); this.tempoResolucao = 0; this.errosDoEstudante = new ArrayList<>();