Student Grades ============== We consider an scenario (that should be familiar to you) of students, sujects they are taking and grades obtained from various evaluation activities. We have a file with information about the grades (which is not fixed) of the students of a certain group in a certain subject. The specific format this **Grades File** is as follows: - The *file name* (for example ``grades_11_PRG_2526.csv``) is a string containing the following infos separated by the character ``_`` and terminated with the extension ``.csv``. - the word ``grades`` (:class:`str`) - the grup number (:class:`int`) - The subject code: 3 capital letters (:class:`str`) - The course (a 4-digits number). - The *header* has to lines: #. The words ``IDN,GRADES`` (:class:`str`). #. A line with a number of ``=`` (:class:`str`). - The *lines*: Each line (for example ``8156,2.5,5.9,4.8,5.3``) has the informations of one student, separated by coma (``','``): - The 4-digits student identification number IDN (:class:`int`) - A non-fixed number of grades (:class:`float` rounded to 1 decimal). The file :download:`grades_11_PRG_2526.csv ` is an example: .. literalinclude:: grades_11_PRG_2526.csv :language: pycon In this exam you are required to deliver two different functions in separate files both taking a *Grades File* as primary input. ---------------------------------------------------------------------------------------------------------------------- Firstly, given a *grades file* we need to produce a file with those students whose average is equal or higher than a given threshold. The **average grade** is computed by **discarding the lowest grade** and applying the standard formula. The format of the resulting **Average Grades File** corresponding to a given *Grades File* **f** and a threshold value **grade_th** should be as follows: - The *file name*: A string containing the following infos separated by the character ``_`` and terminated with the extension ``.csv``. - the *grade_th* (:class:`float`). - the word ``avg_grades`` (:class:`str`). - the grup number (:class:`int`). - The subject code: 3 capital letters (:class:`str`). - The course (a 4-digits number). For example ``7.0_avg_grades_11_PRG_2526.csv``. - The *header*: It has to lines: #. The words ``'IDN,AVG,GRADES'``. #. A line of ``'='`` with the same lenght. - The *lines*: Each line of the file has the informations corresponding to a student, separated by coma (``','``): - The 4-digits student identification number IDN (:class:`int`). - The student's grade average calculated from that (:class:`float` rounded to 2 decimals). - the number of grades is has been calculated from (:class:`int`). - that same number of grades (:class:`float` rounded to 1 decimal). The file :download:`7.0_avg_grades_11_PRG_2526.csv <7.0_avg_grades_11_PRG_2526.csv>` is an example: .. literalinclude:: 7.0_avg_grades_11_PRG_2526.csv :language: pycon To this purpose you are required to delivered he following function in the module :mod:`std_filter` (file :file:`std_filter.py`): .. py:function:: std_filter(grades_filename, grade_th) such that **given** - ``grades_filename``, :class:`str` the name of a textfile in **Grade File** format as described above - ``grade_th``, :class:`float` does two things: #. **writes** the *Average Grade File* corresponding to the *grades_filename* file as described above resulting from filtering the student whose average grade is equal or higher than the ``grade_th`` value. Bear in mind that: - The name of this file must be as described in the average grades file format description above. - The lowest grade is **discarded** before computing the average. - In case that student passes the threshold, the discarded grade shoud not be included in the grades list. #. **returns**: - The number of students processed (:class:`int`). - The number of students that passed the filter and whose average data is included in the output file (:class:`int`). For example the call ``std_filter('grades_11_PRG_2526.csv', 7.0)`` should return ``(5, 2)`` and write a file called :download:`7.0_avg_grades_11_PRG_2526.csv <7.0_avg_grades_11_PRG_2526.csv>` with the following info: .. literalinclude:: 7.0_avg_grades_11_PRG_2526.csv :language: python Find the doctest file at :download:`std_filter_test.txt ` and all necessary files are available at the following compressed file: :download:`std_filter_test_files.zip `. ----------------------------------------------------------------------------------------- Secondly, given a *Grades File* we need to update the information in the **Academic Record** which has the information of the grades for a number of students. For each student, we have personal information and the average grades of the various subjects the student is enroled in. See a very mall example of that in the file :download:`AR_2526.csv `: .. literalinclude:: AR_2526.csv :language: pycon Specificly, the format of an **Academic Record File** is as follows: - The file can be anything. - The *header* has to lines: #. The string ``IDN,NAME,GROUP,SUBJECTS`` (:class:`str`). #. A line with a number of ``=`` (:class:`str`). - The *lines*: Each line (for example ``8156,Aina Vilaplana Puig,11,ALG,4.5,CLC,5.9,FSC,4.8,QMC,7.5``) has the informations of one student, separated by coma (``','``): - The 4-digits student identification number IDN (:class:`int`) - The full name (:class:`int`) - The group (:class:`int`) - A non-fixed number of pairs, each with a subject code (3 capital letters string) an a grade (:class:`float` between 0.0 and 10.0 rounded to 2 decimals). The purpose of this function is to incorporate the average grades fo a subject for a number of students (provided in a Grade Files as described above). To this purpose you are required to deliver the following function in the module :mod:`std_update` (file :file:`std_update.py`): .. py:function:: std_update(grades_filename, ar_filename) such that **given** - ``grades_filename``, :class:`str` the name of a textfile in **Grade File** format as descrie above - ``ar_filename``, :class:`str` the name of a textfile in **Academic Record** format as descrie above does two things: #. **updates** the ``ar_filename`` file by adding the subject and the average grade from ``grades_filename`` at the end of each student in ``ar_filename``. Grades of students in ``grades_filename`` file not found in the ``ar_filename`` file will not be included. Bear in mind that: - You can get the subject name from the graes filename (see the filename specification in the Grades format). - The average grade must be calculated like in the previous function. #. **returns**: - the number of students processed (:class:`int`) - the number of students that has been updated in the ``ar_filename`` file (:class:`int`) - a :class:`list` with the IDN of the students in ``grades_filename`` not found in the ``ar_filename``. For example, considering the file grade file :download:`grades_12_PRG_2526.csv `: .. literalinclude:: grades_12_PRG_2526.csv :language: pycon and the Academic Record above :download:`AR_2526.csv `: .. literalinclude:: AR_2526.csv :language: pycon the call ``std_update('grades_12_PRG_2526.csv', 'AR_2526.csv')`` should return ``(5, 3, ['2233', '4431'])`` and rewrite the ``AR_2526.csv``, let's call it :download:`AR_2526_12.ref `, with the following info: .. literalinclude:: AR_2526_12.ref :language: pycon Doctests are available at the :download:`std_update_test.txt ` file and the files necessary to pass those tests are available at the following compressed file: :download:`AR_2526.zip `. .. note:: - Using a dictionnary to keep the data coming form the Academic Record is recommended.