소스 검색

Update js/assistant/assistant.js

victor_passos 2 년 전
부모
커밋
c1b70ad435
1개의 변경된 파일316개의 추가작업 그리고 199개의 파일을 삭제
  1. 316 199
      js/assistant/assistant.js

+ 316 - 199
js/assistant/assistant.js

@@ -1,223 +1,340 @@
-// Dados constantes
-const exerciseTheme = [ "Leitura e Escrita",
-												"Manipulação de Entrada",
-												"Lógica",
-												"Matemática",
-												"Condição",
-												"Condição de Parada",
-												"Laço",
-												"Vetor"]
 
-const testCaseTypes = [ "Caso Geral",
-												"Caso Limite",
-												"Caso Nulo",
-												"Caso Negativo",
-												"Igualdade",
-												"Tipo de Entrada"]
-
-										
-
-
-
-// Aquisição de dados externos
-// Dados vindos do Avaliador Automático
-let exerciseType = [exerciseTheme[getRandomInt(0, exerciseTheme.length)],
-										exerciseTheme[getRandomInt(0, exerciseTheme.length)]];
-
-let testCases = [ {tag: testCaseTypes[getRandomInt(0, testCaseTypes.length)], incorrect: getRandomInt(0,2)},
-									{tag: testCaseTypes[getRandomInt(0, testCaseTypes.length)], incorrect: getRandomInt(0,2)},
-									{tag: testCaseTypes[getRandomInt(0, testCaseTypes.length)], incorrect: getRandomInt(0,2)},
-									{tag: testCaseTypes[getRandomInt(0, testCaseTypes.length)], incorrect: getRandomInt(0,2)},
-									{tag: testCaseTypes[getRandomInt(0, testCaseTypes.length)], incorrect: getRandomInt(0,2)},
-									{tag: testCaseTypes[getRandomInt(0, testCaseTypes.length)], incorrect: getRandomInt(0,2)}];
-
-let allIncorrect = true;
-
-// Dados vindos da base de dados associada ao aluno
-let types = [ {type: exerciseTheme[0], total: 1, errors: 0},
-							{type: exerciseTheme[1], total: 3, errors: 0},
-							{type: exerciseTheme[2], total: 2, errors: 0},
-							{type: exerciseTheme[3], total: 1, errors: 0},
-							{type: exerciseTheme[4], total: 2, errors: 0},
-							{type: exerciseTheme[5], total: 9, errors: 2},
-							{type: exerciseTheme[6], total: 4, errors: 0},
-							{type: exerciseTheme[7], total: 1, errors: 0}];
-
-let tags = [{tag: testCaseTypes[0], total: 15, errors: 0},
-						{tag: testCaseTypes[1], total: 8, errors: 1},
-						{tag: testCaseTypes[2], total: 5, errors: 1},
-						{tag: testCaseTypes[3], total: 6, errors: 0},
-						{tag: testCaseTypes[4], total: 7, errors: 0},
-						{tag: testCaseTypes[5], total: 4, errors: 0}];
-
-let lastErrorsPerType = []; // Fila com os últimos 50 erros 
-
-for (let i = 0; i<50; i++){
-	lastErrorsPerType.push(exerciseTheme[getRandomInt(0, exerciseTheme.length)])
-}
-
-let lastErrorsPerTag = []; // Fila com os últimos 50 erros 
-
-for (let i = 0; i<50; i++){
-	lastErrorsPerTag.push(testCaseTypes[getRandomInt(0,testCaseTypes.length)])
-}
-
-
-
-
-// Variáveis internas
-let incorrect = false;
-let sugestions = [];
-let performance = [];
-
-let wrongTags = [];
-let wrongTagsAux = [];
-
-let lastErrorsPerTypeGraph = {};
-let lastErrorsPerTagGraph = {};
-
-
-
-// Funções auxiliares
-// Função que retorna um valor inteiro aleatório a partir de um intervalo definido
-function getRandomInt(min, max) {
-  min = Math.ceil(min);
-  max = Math.floor(max);
-  return Math.floor(Math.random() * (max - min)) + min;
-}
-
-// Função que encontra um objeto dentro de um array a partir do valor de uma de suas chaves
-function findObject(array,key,value) {
-	for(let i = 0; i < array.length; i++) {
-		if(array[i][key] === value) {
-				return i
+export class Assistant {
+	
+	constructor () {
+		this.incorrect = false;
+		this.allWrong = true;
+		this.wrongTags = [];
+		this.wrongTagsAux = [];
+		this.lastErrorsPerTypeGraph = [];
+		this.lastErrorsPerTagGraph = [];
+		this.suggestions = [{subject: "Leitura e Escrita", suggestion: `A Leitura e a Escrita são partes fundamentais na criação de um código, pois permitem a interação do usuário com o código e muitas vezes são fundamentais para a aquisição de entradas e para o fornecimento de saídas em um programa.<br><br>
+																																	<img src='http://127.0.0.1:81/moodle/mod/iassign/ilm/iVProg/1.0.20200221/ivprog/img/leitura.png' alt='leitura.png' style='float:right;max-width:100%;'>
+																																	<img src='http://127.0.0.1:81/moodle/mod/iassign/ilm/iVProg/1.0.20200221/ivprog/img/escrita.png' alt='escrita.png' vspace='30' style='float:right;max-width:100%;'>
+																																	Erros em exercícios de Leitura e Escrita geralmente estão associados a erros de digitação e a atribuições erradas de tipo de variável.<br><br>
+																																	<a href='https://edisciplinas.usp.br/mod/assign/view.php?id=LeituraeEscrita'>https://edisciplinas.usp.br/mod/assign/view.php?id=LeituraeEscrita</a><br><br>`},
+											 {subject: "Manipulação de Entrada", suggestion: `A Manipulação de Entrada ocorre quando a entrada completa ou fragmentos da entrada devem ser alterados, trocados, substituídos pelo programa.<br><br>
+											 																								 Erros em exercícios de Manipulação de Entrada geralmente estão relacionados a atribuições erradas de variáveis.<br><br>
+											 																								 <a href='https://edisciplinas.usp.br/mod/assign/view.php?id=ManipulacaodeEntrada'>https://edisciplinas.usp.br/mod/assign/view.php?id=ManipulacaodeEntrada</a><br><br>`},
+											 {subject: "Lógica", suggestion: `A Lógica é parte fundamental na elaboração de um programa, já que códigos são compostos de construções e operações lógicas. O desenvolvimento de raciocínio lógico é parte crucial na jornada de aprendizagem de programação.<br><br>
+											 																 Erros em exercícios de Lógica geralmente estão relacionados a um entendimento errôneo do enunciado do exercício e a uma falta de consideração de todos os cenários possíveis para o exercício.<br><br>
+											 																 <a href='https://edisciplinas.usp.br/mod/assign/view.php?id=Logica'>https://edisciplinas.usp.br/mod/assign/view.php?id=Logica</a><br><br>`},
+											 {subject: "Matemática", suggestion: `Problemas de Matemática são muito utilizados no ensino de programação, seu formato lógico permite a aplicação quase que direta de problemas matemáticos vistos no Ensino Fundamental e Médio, sendo uma boa porta de entrada para transpor problemas para o ambiente virtual para que possam ser resolvidos através de programação.<br><br>
+											 																		 Erros em exercício de Matemática geralmente estão relacionados a erros em operações matemáticas e a falta de conhecimento sobre um conceito matemático.<br><br>
+											 																		 <a href='https://edisciplinas.usp.br/mod/assign/view.php?id=Matematica'>https://edisciplinas.usp.br/mod/assign/view.php?id=Matematica</a><br><br>`},
+											 {subject: "Condição", suggestion: `O uso de Condições é muito importante na programação, pois permite que se construa programas com comportamentos diferentes para situações diferentes, permitindo uma grande aplicabilidade aos códigos.<br>
+											 																	 <img src='http://127.0.0.1:81/moodle/mod/iassign/ilm/iVProg/1.0.20200221/ivprog/img/condicao.png' alt='condicao.png' vspace='30' style='float:right;max-width:100%;'>
+																												 Erros em exercícios de Condição estão geralmente relacionados ao limite da condição, ou seja, nos valores adjacentes aos valores que satisfazem a condição.<br><br>
+																												 <a href='https://edisciplinas.usp.br/mod/assign/view.php?id=Condicao'>https://edisciplinas.usp.br/mod/assign/view.php?id=Condicao</a><br><br>`},
+											 {subject: "Laço", suggestion: `O conceito de Laço tem muita importância para a programação, pois permite a repetição de uma tarefa até que uma condição de parada seja satisfeita, eliminando a necessidade de ter que ficar escrevendo diversas vezes o código da tarefa.<br>
+											 															 <img src='http://127.0.0.1:81/moodle/mod/iassign/ilm/iVProg/1.0.20200221/ivprog/img/laco1.png' alt='laco1.png' vspace='30' style='float:right;max-width:100%;'>
+											 															 <img src='http://127.0.0.1:81/moodle/mod/iassign/ilm/iVProg/1.0.20200221/ivprog/img/laco2.png' alt='laco2.png' style='float:right;max-width:100%;'>
+											 															 <img src='http://127.0.0.1:81/moodle/mod/iassign/ilm/iVProg/1.0.20200221/ivprog/img/laco3.png' alt='laco3.png' vspace='30' style='float:right;max-width:100%;'>
+											 															 Erros em exercícios de Laços geralmente estão relacionados à condição de parada, à atribuição da variável da condição de parada antes do laço e à manipulação da variável da condição de parada depois do laço.<br><br>
+											 															 <a href='https://edisciplinas.usp.br/mod/assign/view.php?id=Lacos'>https://edisciplinas.usp.br/mod/assign/view.php?id=Lacos</a><br><br>`},
+											 {subject: "Vetor", suggestion: `O uso de Vetores acrescenta diversas possibilidades a um programa, permite que conjuntos de dados sejam armazenados e manipulados de forma mais eficiente, o que facilita o uso de conjuntos de dados em programas.<br>
+											 																<img src='http://127.0.0.1:81/moodle/mod/iassign/ilm/iVProg/1.0.20200221/ivprog/img/vetor.png' alt='vetor.png' vspace='30' style='float:right;max-width:100%;'>
+																											Erros em exercícios com Vetores geralmente estão relacionados a erros no uso do índice dos vetores, o que resulta no uso de dados errados, por isso sempre é importante checar se os índices estão sendo usados da forma correta.<br><br>
+																											<a href='https://edisciplinas.usp.br/mod/assign/view.php?id=Vetor'>https://edisciplinas.usp.br/mod/assign/view.php?id=Vetor</a><br><br>`},
+											 {subject: "Caso Geral", suggestion: `Quando um programa é utilizado, geralmente a maioria de suas execuções ocorrerá em um Caso Geral, em função disso a maioria dos testes são iniciados testando Casos Gerais, a fim de verificar o funcionamento da região do programa que concrentrará a maioria dos casos.<br><br>
+											 																		 Os Casos Gerais ocorrem nos valores que não apresentam um comportamento especial, ou seja, os casos comuns, que não se encaixam nos outros Tipos de Caso Teste.<br><br>
+																													 <a href='https://edisciplinas.usp.br/mod/assign/view.php?id=CasoGeral'>https://edisciplinas.usp.br/mod/assign/view.php?id=CasoGeral</a><br><br>`},
+											 {subject: "Caso Limite", suggestion: `Levantar quais são os Casos Limites do problema a ser resolvido é fundamental para se avaliar o funcionamento adequado do programa desenvolvido, pois ao se testá-los podem ser encontrados erros que não são observados nos Casos Gerais.<br><br>
+											 																			Os Casos Limites ocorrem nos valores que se encontram no limite da mudança de comportamento do programa. Por exemplo, em um programa que retorna se um número inteiro é maior que 5, os Casos Limites seriam os valores 5 e 6.<br><br>
+																														<a href='https://edisciplinas.usp.br/mod/assign/view.php?id=CasoLimite'>https://edisciplinas.usp.br/mod/assign/view.php?id=CasoLimite</a><br><br>`},
+											 {subject: "Caso Nulo", suggestion: `É sempre importante testar o funcionamento adequado do programa desenvolvido em casos de entrada nula (Caso Nulo), pois o zero pode ter um impacto muito grande em diferentes cálculos, sempre deve se tomar cuidado com possíveis multiplicações e divisões por zero.<br><br>
+											 																		O Caso Nulo ocorre quando a entrada do programa é nula. Por exemplo, em um programa que trabalha com números, um Caso Nulo ocorre quando uma das entradas é zero, já em um programa que trabalha com texto, um Caso Nulo ocorre quando a entrada é um texto vazio.<br><br>
+																													<a href='https://edisciplinas.usp.br/mod/assign/view.php?id=CasoNulo'>https://edisciplinas.usp.br/mod/assign/view.php?id=CasoNulo</a><br><br>`},
+											 {subject: "Caso Negativo", suggestion: `É sempre importante testar o funcionamento adequado do programa desenvolvido em casos de entradas negativas (Caso Negativo), já que números negativos podem inverter comportamentos esperados e bagunçar cálculos que não esperavam por números negativos, sempre deve se checar se os cálculos realizados estão preparados para lidar com números negativos.<br><br>
+											 																				O Caso Negativo ocorre quando a entrada do programa é negativa. Por exemplo, em um programa que multiplica dois números, um exemplo de Caso Negativo seriam os valores 5 e -6.<br><br>
+																															<a href='https://edisciplinas.usp.br/mod/assign/view.php?id=CasoNegativo'>https://edisciplinas.usp.br/mod/assign/view.php?id=CasoNegativo</a><br><br>`},
+											 {subject: "Igualdade", suggestion: `Entradas iguais podem causar resultados inesperados, por isso é importante se testar Igualdade, tanto em casos numéricos quanto em casos textuais<br><br>
+											 																		A Igualdade ocorre quando o programa apresenta entradas idênticas, por exemplo, em um progama que recebe uma lista de números e tem que retornar os números primos presentes nessa lista sem repetir números.<br><br>
+											 																		<a href='https://edisciplinas.usp.br/mod/assign/view.php?id=Igualdade'>https://edisciplinas.usp.br/mod/assign/view.php?id=Igualdade</a><br><br>`},
+											 {subject: "Tipo de Entrada", suggestion: `Ao se elaborar um programa, é fundamental garantir que os Tipos de Entrada estão que estão sendo recebidos estão corretos, pois uma entrada de um tipo inesperado pode afetar gravemente o funcionamento de um programa.<br><br>
+											 																					O Tipo de Entrada é testado quando se fornece um tipo de entrada diferente do esperado. Um exemplo de um teste de Tipo de Entrada é fornecer um número real em um programa que recebe números inteiros.<br><br>
+											 																					<a href='https://edisciplinas.usp.br/mod/assign/view.php?id=TipodeEntrada'>https://edisciplinas.usp.br/mod/assign/view.php?id=TipodeEntrada</a><br><br>`}];
+	}
+	
+	// Função que encontra um objeto dentro de um array a partir do valor de uma de suas chaves
+	findObject(array,key,value) {
+		for(let i = 0; i < array.length; i++) {
+			if(array[i][key] === value) {
+					return i
+			}
 		}
 	}
-}
-
 
-
-// Funções do agente
-// Função que analisa o exercício em relação às tags
-function updateTags(testCases,tags,lastErrorsPerTag) {
-	for (var i = 0; i < testCases.length; i++) {
-		for (var j = 0; j < tags.length; j++) {
-			if (testCases[i].tag === tags[j].tag) {
-				tags[j].total += 1;
-				if (testCases[i].incorrect) {
-					incorrect = true;
-					tags[j].errors += 1;
-					lastErrorsPerTag.push(testCases[i].tag);
-					if (lastErrorsPerTag.length > 50) {
-						lastErrorsPerTag.shift();
+	// Funções do agente
+	// Função que analisa o exercício em relação às tags
+	updateTags(testCases,performance) {
+		for (let i = 0; i < testCases.length; i++) {
+			for (let j = 0; j < performance.tag.length; j++) {
+				if (testCases[i].tags.toString() === performance.tag[j].tag) {
+					performance.tag[j].total += 1;
+					if (!testCases[i].grade) {
+						this.incorrect = true;
+						performance.tag[j].errors += 1;
+						performance.lastTagErrors.push(testCases[i].tags.toString());
+						if (performance.lastTagErrors.length > 50) {
+							performance.lastTagErrors.shift();
+						}
+						this.wrongTagsAux.push(testCases[i].tags.toString());
+					}
+					else {
+						this.allWrong = false;
 					}
-					wrongTagsAux.push(testCases[i].tag);
 				}
 			}
 		}
+		this.wrongTags = this.wrongTagsAux.filter((element, i) => this.wrongTagsAux.indexOf(element) === i);
 	}
-   wrongTags = wrongTagsAux.filter((element, i) => wrongTagsAux.indexOf(element) === i)
-	//wrongTags = [...new Set(wrongTagsAux)]; // CUIDADO com o set
-}
-
-// Função que analisa o exercício em relação aos types
-function updateTypes(exerciseType,types,lastErrorsPerType) {
-	for (var i = 0; i < exerciseType.length; i++) {
-		for (var j = 0; j < types.length; j++) { 
-			if (exerciseType[i] === types[j].type) {
-				types[j].total += 1;
-				if (incorrect) {
-					types[j].errors += 1;
-					lastErrorsPerType.push(exerciseType[i]);
-					if (lastErrorsPerType.length > 50) {
-						lastErrorsPerType.shift();
+	
+	// Função que analisa o exercício em relação aos types
+	updateTypes(exerciseType,performance) {
+		for (let i = 0; i < exerciseType.length; i++) {
+			for (let j = 0; j < performance.type.length; j++) { 
+				if (exerciseType[i] === performance.type[j].type) {
+					performance.type[j].total += 1;
+					if (this.incorrect) {
+						performance.type[j].errors += 1;
+						performance.lastTypeErrors.push(exerciseType[i]);
+						if (performance.lastTypeErrors.length > 50) {
+							performance.lastTypeErrors.shift();
+						}
 					}
 				}
 			}
 		}
 	}
-}
+	
+	// Função que contabiliza as ocorrências dentro das fila de últimos erros
+	lastErrors(performance) {
+		performance.lastTypeErrors.forEach((x) => this.lastErrorsPerTypeGraph[x] = (this.lastErrorsPerTypeGraph[x] || 0)+1);
+		performance.lastTagErrors.forEach((x) => this.lastErrorsPerTagGraph[x] = (this.lastErrorsPerTagGraph[x] || 0)+1);
+	}
+	
+	// Função que adiciona o desempenho à saída
+	addPerformance(exerciseType,wrongTags,performance) {
+		let performanceText = "";//"Desempenho\n\n";
+		performanceText += `Neste exercício relacionado a ${exerciseType[0]}`;
+		for (let i = 1; i < exerciseType.length; i++) {
+			if (i+1 === exerciseType.length) {
+				performanceText += ` e ${exerciseType[i]}`;
+			}
+			else {
+				performanceText += `, ${exerciseType[i]}`;
+			}
+		}
+		performanceText += ` você `;
+		if(this.allWrong) {
+			performanceText += `errou todos os testes`;
+		}
+		else {
+			if (this.incorrect) {
+				performanceText += `errou os teste que envolvem ${wrongTags[0]}`;
+				for (let i = 1; i < wrongTags.length; i++) {
+					if (i+1 === wrongTags.length) {
+						performanceText += ` e ${wrongTags[i]}`;
+					}
+					else {
+						performanceText += `, ${wrongTags[i]}`;
+					}
+				}
+			}
+			else{
+				performanceText += `acertou todos os teste`;
+			}
+		}
+		performanceText += `.<br><br><br>`;
+		for (let i = 0; i < exerciseType.length; i++) {
+			let obj = this.findObject(performance.type,"type",exerciseType[i]);
+			performanceText += `Seu desempenho em exercícios com ${exerciseType[i]} é de ${(100*(1-performance.type[obj].errors/performance.type[obj].total)).toFixed(2)}% de sucesso.<br><br>`;
+		}
+		if (this.incorrect & !this.allWrong) {
+			for (let i = 0; i < wrongTags.length; i++) {
+				let obj = this.findObject(performance.tag,"tag",wrongTags[i]);
+				performanceText += `Seu desempenho em testes de ${wrongTags[i]} é de ${(100*(1-performance.tag[obj].errors/performance.tag[obj].total)).toFixed(2)}% de sucesso.<br><br>`;
+				performanceText += `Dos seus últimos ${performance.lastTagErrors.length} erros ${(100*(this.lastErrorsPerTagGraph[wrongTags[i]]/performance.lastTagErrors.length)).toFixed(2)}% foram em testes de ${wrongTags[i]}.<br><br>`;
+			}
+			performanceText += `<table align='center' cellpadding='4' bgcolor='transparent' style='width: 40%;'><tr><td align='center' colspan='2' style='height: 50px;'><b>Últimos ${performance.lastTagErrors.length} Erros</b></td></tr>`;
+			performanceText += `<tr style='height: 250px;'><td colspan='2' class='piechart'>
+														<style>
+														.piechart {
+															display: block;
+															position: absolute;
+															width: 17%;
+															height:0;
+															padding-bottom: 17%;
+															border-radius: 50%;
+															background-image: conic-gradient(`;
+			let dg = 0;
+			if (this.lastErrorsPerTagGraph[performance.tag[0].tag]) {
+				performanceText += `pink ${360*this.lastErrorsPerTagGraph[performance.tag[0].tag]/performance.lastTagErrors.length}deg,`;
+				dg += 360*this.lastErrorsPerTagGraph[performance.tag[0].tag]/performance.lastTagErrors.length;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[1].tag]) {
+				performanceText += `red 0 ${dg+360*this.lastErrorsPerTagGraph[performance.tag[1].tag]/performance.lastTagErrors.length}deg,`;
+				dg += 360*this.lastErrorsPerTagGraph[performance.tag[1].tag]/performance.lastTagErrors.length;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[2].tag]) {
+				performanceText += `blue 0 ${dg+360*this.lastErrorsPerTagGraph[performance.tag[2].tag]/performance.lastTagErrors.length}deg,`;
+				dg += 360*this.lastErrorsPerTagGraph[performance.tag[2].tag]/performance.lastTagErrors.length;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[3].tag]) {
+				performanceText += `yellow 0 ${dg+360*this.lastErrorsPerTagGraph[performance.tag[3].tag]/performance.lastTagErrors.length}deg,`;
+				dg += 360*this.lastErrorsPerTagGraph[performance.tag[3].tag]/performance.lastTagErrors.length;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[4].tag]) {
+				performanceText += `green 0 ${dg+360*this.lastErrorsPerTagGraph[performance.tag[4].tag]/performance.lastTagErrors.length}deg,`;
+			}
 
-// Função que contabiliza as ocorrências dentro das fila de últimos erros
-function lastErrors() {
-	lastErrorsPerType.forEach((x) => lastErrorsPerTypeGraph[x] = (lastErrorsPerTypeGraph[x] || 0)+1);
-	lastErrorsPerTag.forEach((x) => lastErrorsPerTagGraph[x] = (lastErrorsPerTagGraph[x] || 0)+1);
-}
+			performanceText += `white 0);
+													}
+													body,
+													.piechart {
+														display: flex;
+														justify-content: center;
+														align-items: center;
+													}
+													</style></td></tr>`;
+
+			if (this.lastErrorsPerTagGraph[performance.tag[0].tag]) {
+				performanceText += `<tr style='background-color:pink;'><td>${performance.tag[0].tag}</td><td style='text-align: center;'>${(100*(this.lastErrorsPerTagGraph[performance.tag[0].tag]/performance.lastTagErrors.length)).toFixed(2)}%</td></tr>`;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[1].tag]) {
+				performanceText += `<tr style='background-color:red;'><td style='color: white;'>${performance.tag[1].tag}</td><td style='text-align: center; color: white;'>${(100*(this.lastErrorsPerTagGraph[performance.tag[1].tag]/performance.lastTagErrors.length)).toFixed(2)}%</td></tr>`;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[2].tag]) {
+				performanceText += `<tr style='background-color:blue;'><td style='color: white;'>${performance.tag[2].tag}</td><td style='text-align: center; color: white;'>${(100*(this.lastErrorsPerTagGraph[performance.tag[2].tag]/performance.lastTagErrors.length)).toFixed(2)}%</td></tr>`;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[3].tag]) {
+				performanceText += `<tr style='background-color:yellow;'><td>${performance.tag[3].tag}</td><td style='text-align: center;'>${(100*(this.lastErrorsPerTagGraph[performance.tag[3].tag]/performance.lastTagErrors.length)).toFixed(2)}%</td></tr>`;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[4].tag]) {
+				performanceText += `<tr style='background-color:green;'><td style='color: white;'>${performance.tag[4].tag}</td><td style='text-align: center; color: white;'>${(100*(this.lastErrorsPerTagGraph[performance.tag[4].tag]/performance.lastTagErrors.length)).toFixed(2)}%</td></tr>`;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[5].tag]) {
+				performanceText += `<tr style='background-color:white;'><td>${performance.tag[5].tag}</td><td style='text-align: center;'>${(100*(this.lastErrorsPerTagGraph[performance.tag[5].tag]/performance.lastTagErrors.length)).toFixed(2)}%</td></tr>`;
+			}
+			performanceText += `</table>`;
+/*
+
+			for (let i = 0; i < performance.tag.length; i++) {
+				if (this.lastErrorsPerTagGraph[performance.tag[i].tag]) {
+					if (wrongTags.includes(performance.tag[i].tag)) {
+						performanceText += `<tr style='background-color:orange;'><td><b>${performance.tag[i].tag}</b></td><td style='text-align: center;'><b>${(100*(this.lastErrorsPerTagGraph[performance.tag[i].tag]/performance.lastTagErrors.length)).toFixed(2)}%</b></td></tr>`;
+					}
+					else {
+						performanceText += `<tr style='background-color:white;'><td>${performance.tag[i].tag}</td><td style='text-align: center;'>${(100*(this.lastErrorsPerTagGraph[performance.tag[i].tag]/performance.lastTagErrors.length)).toFixed(2)}%</td></tr>`;
+					}
 
-// Função que adiciona o desempenho à saída
-function addPerformance(exerciseType,wrongTags) {
-	let performanceText = "Desempenho\n\n";
-	performanceText += `Neste exercício relacionado a ${exerciseType} você `;
-	if (incorrect) {
-		performanceText += `errou os teste que envolvem ${wrongTags}.\n\n`;
+				}
+			}
+			performanceText += `</table>`;
+			performanceText += `<p class='piechart'>
+														<style>
+														.piechart {
+															display: block;
+															position: absolute;
+															width: 15%;
+															height:0;
+															padding-bottom: 15%;
+															border-radius: 50%;
+															background-image: conic-gradient(`;
+			let dg = 0;
+			if (this.lastErrorsPerTagGraph[performance.tag[0].tag]) {
+				performanceText += `pink ${360*this.lastErrorsPerTagGraph[performance.tag[0].tag]/performance.lastTagErrors.length}deg,`;
+				dg += 360*this.lastErrorsPerTagGraph[performance.tag[0].tag]/performance.lastTagErrors.length;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[1].tag]) {
+				performanceText += `red 0 ${dg+360*this.lastErrorsPerTagGraph[performance.tag[1].tag]/performance.lastTagErrors.length}deg,`;
+				dg += 360*this.lastErrorsPerTagGraph[performance.tag[1].tag]/performance.lastTagErrors.length;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[2].tag]) {
+				performanceText += `blue 0 ${dg+360*this.lastErrorsPerTagGraph[performance.tag[2].tag]/performance.lastTagErrors.length}deg,`;
+				dg += 360*this.lastErrorsPerTagGraph[performance.tag[2].tag]/performance.lastTagErrors.length;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[3].tag]) {
+				performanceText += `yellow 0 ${dg+360*this.lastErrorsPerTagGraph[performance.tag[3].tag]/performance.lastTagErrors.length}deg,`;
+				dg += 360*this.lastErrorsPerTagGraph[performance.tag[3].tag]/performance.lastTagErrors.length;
+			}
+			if (this.lastErrorsPerTagGraph[performance.tag[4].tag]) {
+				performanceText += `green 0 ${dg+360*this.lastErrorsPerTagGraph[performance.tag[4].tag]/performance.lastTagErrors.length}deg,`;
+			}
+
+			performanceText += `white 0);
+													}
+													body,
+													.piechart {
+														display: flex;
+														justify-content: center;
+														align-items: center;
+													}
+													</style>
+													</p>`;*/
+		}
+		return performanceText;
 	}
-	else {
-		performanceText += `acertou todos os teste.\n\n`;
+	
+	// Função que adiciona a sugestão à saída
+	addSuggestion(exerciseType,wrongTags) {
+		let suggestionText = "";//"Sugestões\n\n";
+		if (this.incorrect) {
+			if (!this.allWrong) {
+				for (let i = 0; i < wrongTags.length; i++) {
+					let obj = this.findObject(this.suggestions,"subject",wrongTags[i]);
+					suggestionText += this.suggestions[obj].suggestion;
+				}
+				for (let i = 0; i < exerciseType.length; i++) {
+					let obj = this.findObject(this.suggestions,"subject",exerciseType[i]);
+					suggestionText += this.suggestions[obj].suggestion;
+				}
+			}
+			else {
+				suggestionText += `Sempre é importante testar o programa desenvolvido antes de aplicá-lo em um ambiente real, lembre-se de testar o programa antes de submetê-lo à avaliação automática.<br><br>`;
+				for (let i = 0; i < exerciseType.length; i++) {
+					let obj = this.findObject(this.suggestions,"subject",exerciseType[i]);
+					suggestionText += this.suggestions[obj].suggestion;
+				}
+			}
+		}
+		else {
+			suggestionText += `Parabéns!!! Seu exercício não apresentou erros.<br><br>`;
+		}
+		return suggestionText;
 	}
-	for (let i = 0; i < exerciseType.length; i++) {
-		let obj = findObject(types,"type",exerciseType[i]);
-		performanceText += `Seu desempenho em exercícios com ${exerciseType[i]} é de ${(100*(1-types[obj].errors/types[obj].total)).toFixed(2)}% de sucesso\n\n`;
+	
+	async get(url) {
+		let response = await fetch(url);
+		let data = await response.json();
+		return data
 	}
-	if (incorrect) {
-		for (let i = 0; i < wrongTags.length; i++) {
-			let obj = findObject(tags,"tag",wrongTags[i]);
-			performanceText += `Seu desempenho em testes de ${wrongTags[i]} é de ${(100*(1-tags[obj].errors/tags[obj].total)).toFixed(2)}% de sucesso\n\n`;
-			performanceText += `Dos seus últimos 50 erros ${(100*(lastErrorsPerTagGraph[wrongTags[i]]/lastErrorsPerTag.length)).toFixed(2)}% foram em testes de ${wrongTags[i]}\n\n`;
+	
+	async post(url, data) {
+		let payload = new FormData();
+		payload.append("data",JSON.stringify(data));
+		let options = {
+			method : "POST",
+			body : payload
 		}
+		let response = await fetch(url, options);
+		await response.text();
 	}
-	console.log(performanceText);
-}
-
-// Função que adiciona a sugestão à saída
-function addSugestion(wrongTypes,wrongTags) {
-	let sugestionText = "Sugestões\n\n";
-	if (incorrect) {
-		sugestionText += `Levantar quais são os Casos Limites do problema a ser resolvido é fundamental para se avaliar o funcionamento adequado do programa desenvolvido, pois ao se testá-los podem ser encontrados erros que não são observados nos Casos Gerais.\n\n`;
-		sugestionText += `[Explicação de Casos Limites]\n\n`;
-		sugestionText += `[Exemplo de Casos Limites e Casos Gerais]\n\n`;
-		sugestionText += `[Material ou link sobre Casos Limites]\n\n\n`;
-		sugestionText += `O conceito de Laço é muito importante na programação, pois com ele ….\n\n`;
-		sugestionText += `[Explicação sobre Laços]\n\n`;
-		sugestionText += `[Exemplo do uso de Laços no iVProg]\n\n`;
-		sugestionText += `[Material ou link sobre Laços]\n\n`;
-	}
-	else {
-		sugestionText += `Parabéns!!! Seu exercício não apresentou erros.\n\n`;
+	
+	async analise(url,exerciseType,testCases) {	
+		let data = this.get(url);
+		return Promise.resolve(data).then((performance) => {
+			this.updateTags(testCases,performance);
+			this.updateTypes(exerciseType,performance);
+			this.lastErrors(performance);
+			let assistantData = {exerciseType: exerciseType, testCases: testCases, performance: performance};
+			this.post(url,assistantData);
+			let text = [];
+			text.push(this.addPerformance(exerciseType,this.wrongTags,performance));
+			text.push(this.addSuggestion(exerciseType,this.wrongTags));
+			return text;
+		});
 	}
-	console.log(sugestionText);
 }
 
-
-
-// Exibição dos valores recebidos
-console.log("\nAntes da Execução\n");
-console.table(exerciseType);
-console.table(testCases);
-console.table(types);
-console.table(tags);
-//console.table(lastErrorsPerType);
-//console.table(lastErrorsPerTag);
-console.log("*****************************************************************\n");
-
-
-
-// Execução do agente
-updateTags(testCases,tags,lastErrorsPerTag);
-updateTypes(exerciseType,types,lastErrorsPerType);
-lastErrors();
-addPerformance(exerciseType,wrongTags);
-addSugestion(exerciseType,wrongTags);
-console.log("*****************************************************************\n");
-
-
-
-// Reescrita do dados na base de dados associada ao aluno
-console.log("Após Execução\n");
-console.table(types);
-console.table(tags);
-console.table(lastErrorsPerTypeGraph);
-console.table(lastErrorsPerTagGraph);
-//console.table(lastErrorsPerType);
-//console.table(lastErrorsPerTag);
-console.log("\n");
-