123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- 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
- 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;
- }
- }
- }
- }
- this.wrongTags = this.wrongTagsAux.filter((element, i) => this.wrongTagsAux.indexOf(element) === i);
- }
-
- // 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,`;
- }
- 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>`;
- }
- }
- }
- 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;
- }
-
- // 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;
- }
-
- async get(url) {
- let response = await fetch(url);
- let data = await response.json();
- return data
- }
-
- 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();
- }
-
- 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;
- });
- }
- }
|