|[Home](home)|[Cronograma](cronograma)|[Sprints](sprints)|[Requisitos](requisitos)|[Gerência de Projeto](gp)|[Horários Disponiveis](horarios)| |:---:|:---:|:---:|:---:|:---:|:---:| |[Mockups](mockups)|[**Banco de Dados**](banco_dados)|[Material de estudo](material-de-estudo)|[Arquitetura](arquitetura)|[Git Workflow](git-workflow)|[Configuração](configuracao)| |[Padronização do Código](padronização)|[Testes](testes) # Página do Banco de Dados A aplicação utiliza o [Firebase](https://firebase.google.com/) Realtime Database para a persistência de dados. O Realtime Database é um banco de dados de documentos NoSQL, sendo possível armazenar documentos JSON em qualquer estrutura, sem restrições de integridade (_schema-less_). --- ![Modelo conceitual do banco de dados.](files/db-conceitual.png) **Modelo conceitual do banco de dados.** --- ## Dados armazenados ### Fichas de anamnese Considerando que *todas* as informações de identificação de um usuário estão relacionadas a uma anamnese, atributos como nome, email e data de nascimento, por exemplo, estão ligados à entidade _Anamnese_, e não a _Usuário_. O atributo _modificações_ contém o nome dos atributos que foram modificados entre uma ficha de anamnese e a ficha imediatamente anterior. Essa informação é armazenada no Firebase para melhorar o desempenho da aplicação e reduzir a quantidade de requisições ao serviço de banco de dados. Desse modo, a diferença entre duas fichas é calculada apenas uma vez (na sua criação), e não toda vez que a mesma é exibida (o que necessitaria de uma requisição extra pela ficha anterior, além da execução de um algoritmo de _diffing_). Os sub-atributos _frequência_, dos atributos _medicamentos_ e _hábitos_, possuem uma restrição de integridade de domínio: pode ser apenas um valor de um conjunto de códigos de frequência suportados pela aplicação. Os valores predefinidos, e o significado dos mesmos, podem ser vistos na tabela abaixo. **Domínio dos valores dos sub-atributos _frequência_ dos atributos _medicamentos_ e _sintomas_.** | Valor do campo | Descrição | | -------------- | ------------------------------ | | `6-6h` | a cada 6h | | `8-8h` | a cada 8h | | `12-12h` | a cada 12h | | `24-24h` | a cada 24h | | `1xw` | uma vez por semana | | `1-3xw` | de uma a três vezes por semana | | `3xw` | três vezes por semana | | `+3xw` | mais de três vezes por semana | | `sm:-1d` | menos de um maço por dia | | `sm:1d` | um maço por dia | | `sm:+2d` | mais de dois maços por dia | | `daily` | diariamente | | `occasionaly` | ocasionalmente | | `rarely` | raramente | | `never` | nunca | #### Esquema físico1 O objeto `AnamnesisRecord` armazena as informações de uma ficha de anamnese, conforme definido abaixo: ```typescript class AnamnesisRecord { name: string // nome email: string // email birthDate: string // data de nascimento: formato ISO 8601 (YYYY-MM-DD) weight: number // peso: decimal, quilogramas height: number // altura: inteiro, centímetros symptoms: string[] // sintomas pathologies: string[] // patologias familyPathologies: string[] // histórico familiar lifeRhythm: string // ritmo de vida eatingStyle: string // alimentação medicines: { // medicamentos name: string // nome frequency: string // frequência (restrição de domínio) }[] habits: { // hábitos name: string // nome frequency: string // frequência (restrição de domínio) }[] changes: string[] // modificações } ``` ### Acompanhamento diário O usuário deve conseguir usar a aplicação para um acompanhamento diário do seu humor, medicamentos, sintomas, nível de estresse e pressão arterial. O acompanhamento do humor deve ser feito através do uso de emojis, para que o usuário possa facilmente indicar como se sente no momento que responde ao questionário de acompanhamento. Como emojis são caracteres [Unicode](https://home.unicode.org/), é possível armazená-los como dado textual no Firebase. Por conta disso, não foi preciso definir uma enumeração para mapear uma imagem para texto, nem persistir imagens dos emojis no Firebase. Isso permitiu a simplificação do modelo e da implementação da aplicação. #### Esquema físico1 O objeto `JournalEntry` armazena as informações de uma entrada no acompanhamento diário, conforme definido abaixo: ```typescript class JournalEntry { humor: { emotion: string // emoji text: string // descrição do humor (raiva, feliz, ...) } bloodPressure: string // pressão arterial: XX/YY, XX e YY são números (ex. 12/8, 9/5, ...) stressLevel: string // nível de estresse symptoms: string[] // sintomas medicines: string[] // medicamentos } ``` ### Exames O app oferece a funcionalidade de persistir imagens de exames realizados pelo usuário: a pessoa pode selecionar várias imagens da galeria do dispositivo (ou tirar fotos com a câmera dentro do app), e atribuir um nome e uma descrição ao conjunto de imagens. A aplicação persiste essas informações no Firebase, para que o usuário possa ter acesso rápido aos seus exames de qualquer lugar. Um desafio para a implementação dessa funcionalidade se dá pela persistência das imagens: como isso pode ser feito com o React Native e coordenado com o Firebase. O Firebase permite armazenar arquivos de qualquer tipo usado o [Storage](https://firebase.google.com/docs/storage). As imagens são armazenadas da forma que a pessoa desenvolvedora desejar, sendo necessário apenas atribuir um caminho para a mesma. As imagens foram organizadas no Storage de acordo com o usuário e o exame aos quais estão relacionadas: o caminho para uma imagem é dado pelo ID do usuário e pela data de criação do exame, conforme exemplo abaixo: ``` //exams// /user-id-x/exams/1573478824428/img-ajfhskd.jpg ``` #### Esquema físico1 O objeto `Exam` armazena as informações de um exame, conforme definido abaixo: ```typescript class Exam { name: string // nome description: string // descrição images: string[] // nomes das imagens no Storage } ``` --- ## Esquema físico do banco de dados1 Definiu-se que os dados serão armazenados no Firebase de acordo com a identificação do usuário. A partir do objeto raiz, cada usuário possui um objeto onde seu id é a chave, e suas anamneses, entradas no diário e exames são seu valor, conforme exemplo abaixo: ```typescript { // raiz do Realtime Database [userId: string]: { anamneses: { [creationDate: number /* timestamp */]: AnamnesisRecord } journalEntries: { [date: number /* YYYYMMDD */]: { [time: number /* HHmmss */]: JournalEntry } } exams: { [creationDate: number /* timestamp */]: Exam } } } ``` ## Esquema físico do Storage1 Seguindo o que foi feito no Realtime Database, os arquivos armazenados no Storage são organizados de acordo com a identificação do usuário. A partir do objeto raiz, cada usuário possui uma "pasta" onde seu id é a chave. Para permitir extensões futuras, como uma nova funcionalidade que requer a persistência de arquivos, as subpastas diretas são de acordo com a feature. As imagens de exames ficam na pasta `exams`, e uma possível futura feature que necessite usar o Storage pode usar uma outra pasta no mesmo nível. A partir do objeto raiz, a organização do Storage segue o exemplo abaixo: ```typescript { // raiz do Storage [userId: string]: { exams: { [creationDate: number /* timestamp */]: File[] // imagens do exame } } } ``` --- **1:** a definição dos esquemas físicos está usando uma sintaxe parecida com a do [TypeScript](https://www.typescriptlang.org/), por ser bastante parecida com a sintaxe de JSON (com a adição de tipos).