Como contribuir?
=================

.. note::

   O guia completo para contribuidores — incluindo configuração do ambiente, ferramentas de qualidade de código, execução de testes e fluxo de pull request — está disponível no arquivo `CONTRIBUTING.md <https://github.com/rjmalves/inewave/blob/main/CONTRIBUTING.md>`_ na raiz do repositório.

   Esta página descreve as convenções de modelagem específicas do *inewave* e as referências ao framework *cfinterface*, que utilizam recursos de marcação próprios do Sphinx.


O framework `cfinterface` e a modelagem de arquivos
----------------------------------------------------

O módulo *inewave* é desenvolvido considerando o framework proposto no módulo `cfinterface <https://github.com/rjmalves/cfi>`_.

A abordagem proposta no framework consiste em classificar os arquivos processados com relação à sua construção. São definidas três classes de arquvos:

- :obj:`~cfinterface.files.blockfile.BlockFile`
- :obj:`~cfinterface.files.sectionfile.SectionFile`
- :obj:`~cfinterface.files.registerfile.RegisterFile`

Esta classificação independe do arquivo ser constituído de armazenamento no formato texto ou binário, sendo que
esta informação é fornecida na declaração da classe que modela o arquivo em questão. Também é possível fornecer
informações sobre a codificação padrão utilizada em casos de arquivos gerados com caracteres especiais.

A modelagem de arquivos como :obj:`~cfinterface.files.blockfile.BlockFile` se baseia na definição de blocos do arquivo que
possuem um padrão específico, binário ou textual, que indica o início de um conjunto de informações que seja
autocontido e bem definido. Opcionalmente, também pode haver um padrão de terminação, ou o bloco pode determinar
a sua terminação seguindo outros critérios. Um bloco é definido como um elemento da classe :obj:`~cfinterface.components.block.Block`.
Exemplos de arquivos do módulo *inewave* que são implementados através deste modelo são o :ref:`pmo.dat <pmo>` e :ref:`parp.dat <parp>`.

O uso dos modelos da :obj:`~cfinterface.files.sectionfile.SectionFile` se baseia na definição de seções do arquivo que
sempre aparecem em uma mesma ordem e são obrigatórias. Da mesma forma, o arquivo pode ser binário ou textual. Diferentemente da modelagem
por :obj:`~cfinterface.files.blockfile.BlockFile`, que permite que um mesmo bloco apareça diversas vezes no arquivo, a abordagem
por seções não permite flexibilidade na definição de quais conteúdos aparecem e na ordem que aparecem. Podem, cada objeto
:obj:`~cfinterface.components.section.Section` pode definir o seu critério de fim, permitindo uma certa flexibilidade dentro de cada
seção. Exemplos de arquivos do módulo *inewave* que são implementados através deste modelo são o :ref:`dger.dat <dger>` e :ref:`sistema.dat <sistema>`.

Por fim, a abordagem por :obj:`~cfinterface.files.registerfile.RegisterFile` se baseia na definição de unidades mínimas de conteúdo
que ocupam sempre uma única linha e tem formato constante, que são chamadas de registros. Da mesma forma, o arquivo pode ser binário ou textual.
Registros podem ser vistos como blocos de uma só linha mas, devido à sua simplicidade, são de mais fácil definição, através da classe
:obj:`~cfinterface.components.register.Register`. A implementação de um registro consiste apenas na sua definição, visto que
a leitura e a escrita deste são inteiramente obtidas do formato dos seus campos. No *inewave*, apenas o arquivo :ref:`modif.dat <modif>` é modelado
seguindo esta abordagem.


Diretrizes de modelagem para o módulo `inewave`
------------------------------------------------

A principal diretriz para o desenvolvimento do *inewave* é a relação entre arquivos do modelo NEWAVE e as classes
disponíveis para uso. Cada arquivo de entrada do modelo é mapeado para uma classe do módulo, que segue
o nome geralmente utilizado para o arquivo nos casos de exemplo que são fornecidos junto com o modelo pelo desenvolvedor
ou pelo ONS para publicação dos decks de PMO. É utilizado sempre `PascalCase` para determinação dos nomes
das classes, sendo que abreviações que possivelmente se encontram nos nomes dos arquivos são ignoradas na mudança de caso. Por exemplo:

- `arquivos.dat` é modelado na classe :ref:`Arquivos <arquivos>`
- `confhd.dat` é modelado na classe :ref:`Confhd <confhd>`
- `earmfpXXX.out` é modelado na classe :ref:`Earmfp <earmfp>`

É convencionado, sempre que possível, que as propriedades das classes que contém os dados processados dos arquivos
lidem com objetos do tipo :obj:`~pandas.DataFrame` para a representação de dados tabulares. Além disso, se possível,
é recomendado processar a informação contida nos arquivos para que esteja na seguindo as formas normais
para dados tabulares, mesmo quando há divergência na representação textual nos arquivos de entrada do NEWAVE. Um exemplo
pode ser visto na modelagem dos arquivos de saída do NWLISTOP quando executado na opção 2.

O arquivo `gttotsin.out`, modelado na classe :ref:`Gttotsin <gttotsin>`, contém informações escritas em
tabelas que são dividas por ano de estudo. Dentro de cada tabela, cada linha representa os 12 meses do ano
para uma das séries utilizadas na simulação final realizada no modelo:

.. code-block:: text

      PMO ABRIL - 2022 - Niveis para 26/03 NW Versao 28
         GERACAO TERMICA TOTAL PARA O SIN (MWmes)

         ANO: 2022
    SERIE   PAT      1        2        3        4        5        6        7        8        9       10       11       12     MEDIA
        1    1      0.0      0.0      0.0    915.3   1341.4   1687.3   1920.0   2132.3   1714.0   1604.4   1297.0   1144.2   1528.4
             2      0.0      0.0      0.0    761.0    741.8    943.9   1104.8   1135.7   1322.1   1315.5   1621.5   1377.7   1147.1
             3      0.0      0.0      0.0   1792.1   1697.5   2189.7   2643.9   2479.4   2839.8   3048.9   2918.5   2313.9   2436.0
         TOTAL      0.0      0.0      0.0   3468.4   3780.6   4820.9   5668.8   5747.3   5875.9   5968.8   5836.9   4835.8   5111.5
        2    1      0.0      0.0      0.0    915.3   1341.4   1695.9   1920.0   2132.3   1788.2   1604.4   1297.0   1144.2   1537.6
             2      0.0      0.0      0.0    761.0    741.8    948.8   1104.8   1135.7   1379.3   1315.5   1621.5   1377.7   1154.0
             3      0.0      0.0      0.0   1792.1   1697.5   2200.8   2643.9   2479.4   2962.8   3048.9   2918.5   2313.9   2450.9
                                                       .
                                                       .
                                                       .
    MEDIA           0.0      0.0      0.0   3566.9   3846.3   4845.3   5682.0   5811.2   5937.0   6037.4   5893.9   4892.9   5168.1
    DPADRAO         0.0      0.0      0.0    138.5    129.5     33.8     64.1    131.9    114.0    143.1    206.0    242.5
    MIN             0.0      0.0      0.0   3463.3   3780.6   4820.9   5644.2   5722.7   5851.3   5944.2   5812.3   4811.2
    P5              0.0      0.0      0.0   3468.4   3780.6   4820.9   5644.2   5747.3   5875.9   5968.8   5812.3   4811.2
    P95             0.0      0.0      0.0   3738.4   4180.8   4957.9   5781.1   6001.8   6130.4   6335.6   6203.7   5292.0
    MAX             0.0      0.0      0.0   3868.6   4822.5   5242.2   6699.3   6902.6   6922.1   7138.0  10175.4   9677.2

Quando processado, as informações contidas neste arquivo são convertidas para um formato normal, com uma coluna para representar `data`, `patamar`, `serie` e `valor`.
Quando as informações contidas nos arquivos não forem representadas em formato semelhante, é recomendado que seja feita uma transformação
semelhante, visto que a maioria das informações armazenadas em bancos de dados estão em formato semelhante.


.. code-block:: python

    from inewave.nwlistop import Gttotsin
    arquivo_gttot = Gttotsin.read("./gttotsin.out")
    arquivo_gttot.valores

                data patamar serie   valor
    0     2022-01-01       1     1     0.0
    1     2022-02-01       1     1     0.0
    2     2022-03-01       1     1     0.0
    3     2022-04-01       1     1   915.3
    4     2022-05-01       1     1  1341.4
    ...          ...     ...   ...     ...
    95995 2022-08-01   TOTAL  2000  5747.3
    95996 2022-09-01   TOTAL  2000  5875.9
    95997 2022-10-01   TOTAL  2000  5968.8
    95998 2022-11-01   TOTAL  2000  5812.3
    95999 2022-12-01   TOTAL  2000  4811.2


As propriedades das classes e também as colunas dos :obj:`~pandas.DataFrame` que são produzidos são convencionados de
serem nomeados em `snake_case`. Além disso, deve-se evitar ao máximo ambiguidades na escolha dos nomes das propriedades e
das colunas. Alguns pontos recorrentes onde são encontradas ambiguidades e deve-se adotar um termo único são:

- Propriedade ou :obj:`~pandas.DataFrame` que contenha informações de usinas (hidrelétricas, termelétricas, etc.) e venham e conter atributos
  como código (`int`) e nome (`str`) convenciona-se chamar de *nome_usina* e *codigo_usina*, para garantir o único sentido possível.
- Propriedade ou :obj:`~pandas.DataFrame` que contenha informações relativas aos submercados de energia, que ora são
  mencionados como subsistemas de energia, adota-se o termo único *submercado*. De modo semelhante, locais onde apareçam
  informações desta entendidade são denominados *codigo_submercado* e *nome_submercado*. O mesmo raciocínio se aplica
  ao se referir a REE.


Configuracao do ambiente e procedimentos de qualidade
------------------------------------------------------

Para instalar as dependências de desenvolvimento::

    $ git clone https://github.com/rjmalves/inewave.git
    $ cd inewave
    $ uv sync --extra dev
    $ uv run pre-commit install

.. warning::

   O conteúdo da documentação não deve ser movido para o repositório. Isto é feito
   automaticamente pelos scripts de CI no caso de qualquer modificação no branch `main`.

Antes de realizar um ``git push`` é recomendado executar os procedimentos de qualidade que serão novamente executados pelo ambiente de CI::

    $ uv run ruff check ./inewave
    $ uv run ruff format ./inewave
    $ uv run mypy ./inewave
    $ uv run pytest ./tests
