Solar Generation ================ We have a text file with information about the power generated by a solar plant. Each line contains the data corresponding to a solar panel. It includes the following data separated by ``';'`` : - the id of the group where the solar panel belongs to - its localization inside the group - its status (whether is ``'on'`` or ``'off'``) - a sequence of the measures of the power generated by the panel at different times: each measure is either a :class:`float` value or the string ``'*'`` which indicates that the measurement system failed. For example, see the first 5 lines of (first 5 panels) of the file :download:`solargen_data.txt `: .. literalinclude:: solargen_data.txt :language: text :lines: 1-5 Notice that the panel ``'3-15'`` in group ``'gA'`` generated :math:`3.5+2.5+4.0+7.0+3.2+4.0 = 24.2` kWh, and the total generated by group ``'gA'`` is :math:`= 55.9` kWh ( :math:`24.2` from panel ``'3-15'`` plus :math:`31.7` from panel ``'3-17'``, and nothing from panel ``'3-16'`` since it is ``off``). You are required to implement the following functions in the module :mod:`solargen.py` (file :file:`solargen.py`): ----------------------------------------------------------------------------------- Extraction ---------- Program the function: .. py:function:: solargen_extract(filename) such that **given** a :class:`str` with the ``filename`` of a file with data from a solar generation plant as described above **returns** a :class:`list` where each component is a sublist corresponding only to the panels in ``filename`` which status is ``'on'``. For each line the sublist contains a :class:`str` with the *group id*, and a sequence of :class:`float` with the measures that are not an ``'*'``. The following example shows the result of extracting the data from the `solargen_data.txt` file: .. literalinclude:: solargen_extract-test.txt :language: python3 This file is available at :download:`solargen_extract-test.txt `. ----------------------------------------------------------------------------------- Addition -------- Program the function: .. py:function:: solargen_sum(solargen_L) such that **given** a :class:`list like the one produced by the previous function ``solargen_extract`` **returns** a :class:`dict` that associates each group name (:class:`str`) to a two-component list, both calculated according to the info in the input list ``solargen_L``: #. A :class:`float` with the **total power** of the group (namely the sum of the power measures of all the panels belonging to that group) #. An :class:`int` with the **number of** measures coming from active panels of that group The following example shows the :class:`dict` resulting from the previous list: .. literalinclude:: solargen_sum-test.txt :language: python3 This file is available at :download:`solargen_sum-test.txt `. ----------------------------------------------------------------------------------- Sorting ------- Program the function: .. py:function:: solargen_sort(sum_D) such that **given** a :class:`dict` like the one produced by the previous function ``solargen_sum`` **returns** a :class:`list` with a component for each key in ``sum_D`` (namely a group), with the info calculated and ordered according to the info in the input dict ``sum_D``. The info for each group has the form of the following 4-place tuple: #. a :class:`str` with the *group id* #. a 3-decimals :class:`float` with the **power per panel average** #. a :class:`float` with the **sum of the power** generated by all the panels belonging to that group (as in the input :class:`dict`) #. a :class:`int` with the **number of** measures coming from active panels of that group (as in the input :class:`dict`). The ordering of the list is determined by following criteria: #. Decreasing order of the integer part of the **power per panel average** #. Increasing order of the **number of measures** #. Decreasing order of the **total power** For example, given the :class:`dict` ``sumD = {'gA': 55.9, 'gB': 40.9, 'gC': 46.0}``, the output of ``solargen_sort(sum_D)`` should be ``[('gC', 3.833, 46.0, 12), ('gB', 3.408, 40.9, 12), ('gA', 3.993, 55.9, 14)]``. Notice that: #. There is a component for each group which includes the group id, the power/panel average rounded to 3 decimals, the total power of that group, and its number of measures coming from active panels. #. They would be first ordered by the integer part of the power/panel average but this is ``3`` in all groups. Therefore they are increasingly ordered by the number of panels (12, 12 and 14) and finally, decreasing but the total power: first ``gC`` with ``46.0`` and then ``gB`` with ``40.9``. The following example shows the dict resulting from the previous list: .. literalinclude:: solargen_sort-test.txt :language: python3 This file is available at :download:`solargen_sort-test.txt `. ----------------------------------------------------------------------------------- Writting -------- Program the function: .. py:function:: solargen_write(ls, filename) such that **given** - ``ls`` a :class:`list` like the one produced by the previous function ``solargen_sort`` - ``filename`` a :class:`str` with the name of an output fil does two things: - **writes** a line in the file ``filename`` for each group with the following info serparated by ``';'``: - the group - the *power per panel* average rounded to 3 decimals - the total power - the number of measures coming from active panels - **returns** the number of lines written (which should correspond to the number of groups for which the power generated has been calculated). For instance, the call ``solargen_write(ls, 'sgout.txt')``, where ``ls`` is the list produced by te previous function, should return 3 and produce the following file: .. literalinclude:: sgout.txt :language: python3 A doctest file is available at :download:`solargen_write-test.txt `.