Nome: ? | Matrícula: ?

Trabalho: meuhorarioJS

Prazo e forma de entrega

O trabalho deve ser enviado para o e-mail rodrigo@dcc.ufba.br até a meia-noite do dia 29/10 (sábado), horário local de Salvador, sob a forma de um anexo contendo as respostas no formato que é obtido ao seguir o procedimento descrito a seguir. Quem fizer a questão bônus deve anexar um arquivo adicional, o arquivo HTML solicitado na questão bônus.

Salvando e carregando os dados

Para salvar suas respostas, clique no botão:

Caixa de respostas:

Clique na caixa de texto acima e selecione todo o texto (Ctrl+A), em seguida copie o texto (Ctrl+C) da caixa de texto acima e cole (Ctrl+V) em algum editor de texto. Esse texto representa suas respostas.

Para carregar suas respostas, copie (Ctrl+C) o texto que você colou anteriormente, cole na caixa de texto acima, e então clique no botão:

Código de conduta

Nós,

function(str, info) {  }

declaramos que

Introdução: meuhorarioJS

Oi, tudo bom? Você conhece o meuhorario? Trata-se de um site feito para o aluno da UFBA simular sua matrícula, escolhendo as disciplinas e turmas que deseja cursar no próximo semestre.

Neste trabalho você vai implementar um fork do meuhorario chamado meuhorarioJS, ou pelo menos uma parte importante do projeto: a listagem de disciplinas e turmas. Para isso, você precisará trabalhar com closures, currying, aplicação parcial e programação concorrente. Mas não se preocupe! Vou guiar você no passo-a-passo para transformar essa ideia em realidade.

Disciplinas e turmas

Os dados usados no meuhorarioJS são oriundos de dois arrays: disciplinas e turmas. Para começarmos a programar, vamos considerar dois exemplos desse array, exDisciplinas e exTurmas.

O array disciplinas contém objetos que representam as disciplinas:

function(str, info) { return simplesEval(str, info); }

Cada disciplina pode ter uma ou mais turmas. As turmas são representadas por um outro array de objetos:

function(str, info) { return simplesEval(str, info); }

Combinando disciplinas e turmas em um mesmo objeto

A primeira coisa que precisamos fazer é um JOIN de disciplinas e turmas, de forma a obter um array de turmas que possui também dados das disciplinas. Para isso, vamos começar realizando um produto cartesiano (CROSS JOIN) dos dois arrays, isto é, vamos criar um objeto para cada combinação possível de turma e disciplina.

Como ainda estamos esquentando os motores, vou fornecer essa função já pronta:

function(str, info) { return simplesEval(str, info); }

Se não souber o que cada função faz, consulte a documentação do Ramda.

Vamos ver o resultado do crossJoin? Abaixo, usamos console.table para exibir a lista de objetos em formato de tabela.

function(str, info) { return simplesEval(str, info); }

Legal, né? Só tem um problema, estamos misturando dados de uma disciplina com turmas de outra disciplina (afinal, o produto cartesiano faz combinação de todos os elementos de um array com todos os elementos do outro).

Agora é sua vez. Filtre as linhas do array de forma a restarem apenas as linhas nas quais id é igual a disciplina. Note que você não pode modificar o código que aparece em cores mais claras.

function(str, info) { return simplesEval(str, info); }

Ótimo! Mais uma coisa: o código da disciplina aparece em duas colunas da tabela. Além disso, queremos que o número do semestre apareça primeiro. Para fazer isso, podemos usar a função R.pick, dessa forma:

function(str, info) { return simplesEval(str, info); }

Vamos juntar tudo? Crie uma função combinaDados, que recebe os dois arrays (de disciplinas e de turmas) e retorna um array resultante das operações de crossJoin, R.filter e R.pick. Observe que a função R.pick recebe um único objeto como parâmetro, mas você precisará aplicá-la a um array de objetos…

function(str, info) { return simplesEval(str, info); }

Exibindo os dados como uma tabela HTML na página

Agora que temos os dados formatados da maneira que precisamos, precisamos exibi-los para o usuário. Para isso, vamos usar uma tabela HTML. Tabelas em HTML são modeladas como uma sequência de linhas, representadas pela tag <tr>, em que cada linha possui uma sequência de células (uma para cada coluna da tabela), representadas pela tag <td>, e tudo isso envolto na tag <table>. Exemplo:

<table>
  <tr>
    <td>mata56</td><td>Paradigmas de Linguagens de Programação</td>
  </tr>
  <tr>
    <td>mata62</td><td>Engenharia de Software I</td>
  </tr>
</table>

Resultado:

mata56Paradigmas de Linguagens de Programação
mata62Engenharia de Software I

Precisamos realizar uma sequência de operações sobre os nossos dados para transformar os dados originais em uma string que representa uma tabela HTML dos nossos dados:

// Dados originais:

[
  {id: 'mata56', nome: 'Paradigmas de Linguagens de Programação'},
  {id: 'mata62', nome: 'Engenharia de Software I'}
]

// Para cada objeto, vamos extrair seus valores:

[
  ['mata56', 'Paradigmas de Linguagens de Programação'],
  ['mata62', 'Engenharia de Software I']
]

// Para cada valor, vamos criar a representação da célula na tabela HTML:

[
  ['<td>mata56</td>', '<td>Paradigmas de Linguagens de Programação</td>'],
  ['<td>mata62</td>', '<td>Engenharia de Software I</td>']
]

// A seguir vamos juntar as células e uma única string:

[
  '<td>mata56</td><td>Paradigmas de Linguagens de Programação</td>',
  '<td>mata62</td><td>Engenharia de Software I</td>'
]

// E então envolver as strings na tag <tr>:

[
  '<tr><td>mata56</td><td>Paradigmas de Linguagens de Programação</td></tr>',
  '<tr><td>mata62</td><td>Engenharia de Software I</td></tr>'
]

// E então juntar tudo isso em uma única string:


'<tr><td>mata56</td><td>Paradigmas de Linguagens de Programação</td></tr>
<tr><td>mata62</td><td>Engenharia de Software I</td></tr>'

// E por fim envolver tudo isso na tag <table>

'<table><tr><td>mata56</td><td>Paradigmas de Linguagens de Programação</td></tr>
<tr><td>mata62</td><td>Engenharia de Software I</td></tr></table>'

Podemos construir um pipe para realizar essa sequência de transformações. Para simplificar, vamos dividir o trabalho em duas funções: uma para converter um objeto Javascript ({}) em uma string que representa uma linha da tabela HTML, e outra para combinar as linhas.

converteObjetoParaLinhaHTML = R.pipe(
  obtemValoresDoObjeto,
  R.map(envolveNaTag('td')),
  combinaStrings,
  envolveNaTag('tr')
);

converteArrayParaTabelaHTML = R.pipe(
  R.map(converteObjetoParaLinhaHTML),
  combinaStrings,
  envolveNaTag('table')
);

Seu trabalho é definir as funções obtemValoresDoObjeto, envolveNaTag e combinaStrings. Ou melhor, obtemValoresDoObjeto já está pronta:

function(str, info) { return simplesEval(str, info); }

Defina a função envolveNaTag, que recebe o nome de uma tag HTML e uma string, e envolve a string na tag. Na dúvida, veja o teste.

function(str, info) { return simplesEval(str, info); }

Agora defina a função combinaStrings, que recebe um array de strings e retorna uma única string que combina todos os elementos do array. Na dúvida, veja o teste.

function(str, info) { return simplesEval(str, info); }

Agora é o teste pra valer! Vamos ver se as funções converteObjetoParaLinhaHTML e converteArrayParaTabelaHTML vão funcionar com as funções que você acabou de implementar. Vou dar uma chance para você preencher os argumentos de R.pipe sem olhar a resposta lá em cima.

function(str, info) { return simplesEval(str, info); }

Agora vamos ver se converteArrayParaTabelaHTML também funciona. Vou dar uma chance para você preencher os argumentos de R.pipe sem olhar a resposta lá em cima.

function(str, info) { return simplesEval(str, info); }

Mostrando a tabela na página

Vamos exibir a tabela aqui, logo abaixo:

Aqui deve aparecer a tabela de turmas e horários.

Vou construir uma função que atualiza o campo da tabela com a string que for passada como parâmetro. Não se preocupe com a forma como isso é feito; isso é pogramação web, que não é o foco desta disciplina.

function(str, info) { return simplesEval(str, info); }

Veja a função rodando:

function(str, info) { return simplesEval(str, info); }

Ótimo! Agora vamos construir a função atualiza, que recebe a lista de disciplinas e a lista de turmas, e atualiza a tabela na página. Você vai precisar combinar diversas funções criadas anteriormente.

function(str, info) { return simplesEval(str, info); }

Teste a sua função. Execute o código abaixo e veja se a tabela lá em cima é atualizada.

function(str, info) { return simplesEval(str, info); }

Carregando os dados da web

Até agora fixamos os valores de exDisciplinas e exTurmas no nosso código-fonte. E se quisermos obter esses dados da Internet? Nesse caso, nosso programa precisará esperar os dados serem carregados antes de exibirmos a tabela.

Criei uma função carregaDisciplinas, que recebe uma função callback e chama esse callback com a lista de disciplinas, e uma função carregaTurmas, que recebe o código de uma disciplina e um callback, e chama o callback com a lista de turmas daquela disciplina. Vamos vê-las funcionando:

function(str, info) { return simplesEval(str, info); }
function(str, info) { return simplesEval(str, info); }

Agora é com você. Defina a função recarregaDados, que obtém os dados de todas as disciplinas e turmas, e exibe a tabela assim que todos os dados estejam carregados. Garanta que a tabela só é exibida uma única vez ao final da carga dos dados.

function(str, info) { return simplesEval(str, info); }
function(str, info) { return simplesEval(str, info); }

Bônus (+1 ponto)

Junto tudo isso em uma página HTML, reescrevendo as funções de carga de dados para usar promises.