关键词 > FIT1045/FIT1053

Welcome to A3.1 - The Runner's

发布时间:2024-05-18

Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

Welcome to A3.1 - The Runner's Assertion

Premise

You are nearly at the end of your journey in FIT1045/FIT1053! You started off as a little seedling, budding into the world of programming and now you are almost a natural programming genius in Python!

The last assignment is a little quirky. This is because most of the code has already been done for you! All you have to do is finish off a couple of methods and then your major task is to ensure that the code doesn't unexpectedly fail or be broken by any sort of input provided. Also, you will need to write some unit tests to ensure the correctness of the code that you have been given/have changed or written.

The theme of the assignment is to create a structure to hold information about races and process racing data. I can't think of more things to write so I asked the robot to do that for me:

You've journeyed far these ten long weeks,
From first code lines to logic peaks.
In classrooms filled with thoughts profound,
You've built a world from the ground.

In Python's language, you found your way,
Writing scripts through night and day.
With algorithms both old and new,
A coder's world is all you knew.

Now the final race is on,
A challenge that you've never known.
Foot racers, they await your call,
To speed ahead and win it all.

Assertions strong, exceptions stand,
Unit tests, your guiding hand.
These are your tools in the final fight,
As you strive to make things right.

In code and logic, you excel,
With every test, you weave your spell.
Remember this as you face the end,
Your knowledge and skill are your best friend.

So take a breath, and trust your might,
The finish line is now in sight.
For those who've worked so hard and true,
HDs and green checkmarks belong to you!

Objective

· Work ALONE ��

· Complete the four tasks

· Practice the programming concepts from the entire semester

Submission Requirements

· You will work on each task of the assignment.

· Final submission details can be found on the last slide.

You can submit your code on ed here (to be updated).

Only ONE submission per student is allowed. If you make an accidental submission, please follow the guidelines to request the staff to reopen the submission box for you.

Make sure that all functions are in the file they need to be in, with appropriate function names and arguments.

You are ONLY allowed to use the following external modules: csv, math, typing, abc, unittest. Using any other external module apart from these will result in a score of 0 for that task. (NOTE - You may not need all of these modules)

Please note that using an unapproved external module will result in deductions of upto the entire approach and test marks for that particular task.

Documentation

In this assignment, documentation will be marked. You are required to complete the following parts of documentation:

1. A well-versed concise and informative docstring. You may use any documentation standard for the docstring. A docstring needs to be present for ALL FUNCTIONS, METHODS AND CLASSES that you are writing or editing. A docstring is not required for functions that you did not write.

2. Clear type hinting for all functions and variables.

In-line comments and Variable Naming

You are expected to use in-line comments throughout your program to make sure it is clear to the reader. The amount of comments necessary depends on how clear the code is by itself. Therefore, a good habit is to write clear code, so that the amount of in-line comments required is reduced. This will also reduce the number of bugs created.

Comment your code as you write it rather than after reaching a final solution, as it is a lot easier to remember why certain decisions were made and the thought process behind them when the code is fresh in your mind.

Ensure your variable names are meaningful and concise so that your code is understandable at first read. When a reader is going through your program, it should read like a self-explanatory story, using in-line comments to explain the logic behind blocks of code and any additional information that is relevant to the functionality of the code.

You will be marked on your commenting and variable naming in this assignment as you have come to terms with Python.

Avoid repeating yourself by commenting on lines of code that are fairly self-explanatory, and instead reserve your comments to explain higher-level logic, such as explaining the overall purpose behind a small block of code.

Recommended Approach

Setting up your workspace:

· At the beginning of the assignment, you need to:

·

o Create an ed workspace for yourself OR use an IDE of your preference.

o Upload the code scaffold into workspace OR the IDE of your preference.

· You are expected to work on the program in either the workspace OR the IDE of your preference.

Note that if you are already familiar with tools like git, you may use them instead. But we will not provide technical support.

Since this is a somewhat complex project, we recommend that you set up an IDE. Ask a TA to help you set this up!

Testing your code:

· The assignment is broken up into individual coding tasks.

· You can code and test using the ed lessons.

Skeleton/Starter Code:

· Tasks will start with some skeleton/starter code for each function.

· Make sure function and variable names match what is listed in the task; these will be needed to pass automated tests.

Academic Integrity

· Your code will be checked against all other groups with a similarity checker.

· Anything you can google can be easily found by the teaching team and compared against your work.

· In this assessment, you must not use generative artificial intelligence (AI) to generate any material or content concerning the assessment task. This includes ChatGPT.

How can I avoid academic integrity issues?

· Never copy code from anywhere. If you learn something useful online, rewrite it from scratch. It is also the best way to make sure you have understood it.

· If a fellow student asks you for a solution to a question, do not give them yours or debug their solution.

· Giving your solution is just as much of an Academic Integrity breach as receiving it.

· If you feel like you physically cannot submit the assignment on time, please submit an extension request, and seek help.

· For extensions, see Moodle AU or Moodle MA.

· For help, see Moodle AU or Moodle MA.

Important Points

Please note the following points about the assignment that you are beginning:

PLEASE NOTE - This assignment's tasks demonstrate that the given scaffold and tests are INCOMPLETE! If you open any of the tasks and the scaffold given, even run the given tests (using the 'Check' button) you can see that the given code passes all the test cases! Does that mean the assignment is complete? No! You need to work on it and make further tests to ensure the correctness and validity of your code.

1. The functions/methods given to you in the scaffold need to have the names that they have been given. Please don't change this. All the effort has been made to create these functions/methods with the arguments each will need. You should not add or remove any more arguments to/from these functions/methods.

2. You can and are STRONGLY recommended to create more functions/methods in all the tasks to break down your work. This will improve your code by introducing modularity and reducing repeatability. This is one of the things you are being marked on for this assignment so ensure that you do this properly!

3. You should NOT ask the user to provide any input in this assignment. Any input functions that are required for any of the tasks have already been done for you. You may use these but please don't get the user to input anything in any of your functions as you will get an EOF error.

4. You are NOT ALLOWED to use any external modules in this assignment except csv, math, typing, abc, unittest.

5. You are strongly recommended to read and solve all of your pre-class activities before attempting the assignment. All the knowledge required to solve this assignment is either in the pre-class, the workshop, the applied, or the description of this assignment.

7. From Tasks 1 to 3, the use of Try Except statements is BANNED. You should use Try and Except ONLY IN TASK 4.

Custom Errors

Since this assignment mainly covers the topics in Weeks 10 and 11, it is YOUR RESPONSIBILITY to ensure that a proper error is raised when an invalid input is received. Here are some pointers:

· If the value received by a method is invalid or not what the method expects, then you should raise a CustomValueError

· If the type of value received by a method is invalid or not what the method expects, then you should raise a CustomTypeError

· If the value being passed to the method is not an attribute of the class, then you should raise an CustomAttributeError

· If the method is trying to get a value from a dictionary that shouldn't be returned, you should raise a CustomKeyError

These errors have been imported for you in the scaffold for each task already, you merely need to raise them. However, please include a helpful string for the user to figure out what error they have made.

There are a few other errors introduced in the tasks that you need to raise on specific conditions.

For example –

PYTHON

1

2

3

4

5

6

7

8

9

def func_that_adds_numbers(a: int, b: int) -> int:

if not isinstance(a, int):

raise CustomTypeError("wrong input")            # This is not very helpful

if not isinstance(b, int):

# This is a lot better!

raise CustomTypeError(f"Incorrect input type for b, expected int got {type(b)} instead")

return a + b

Your approach marks in every task contain marks for how descriptive your error strings are so please ensure to add these.

All of these errors have been defined in the custom_errors.py file available in each task. You may or may not need to use all of these errors.

You DO NOT need to edit/document/check this file.

How Will You Be Assessed?

Your assignment mark will come from the correctness of your code, documentation and the choices you have made on creating the code, based on the marking provided in the rubric.

Late penalties

Up to 7 days

· 10% lost per calendar day (or part thereof).

More than 7 days

· Zero (0) marks with no feedback given.

See Moodle AU or Moodle MA for how to apply for special consideration.

[Task 1] - The Runners Are Here (20%)

You are NOT allowed to use try/except blocks in Task 1.

Task Setup

In this part, you are given a class called Runner that contains a few instance variables and some class variables. The purpose of each of them is defined below:

1. max_energy (int) : The maximum energy of the runner (i.e., same for all runners).

2. name (string): The name of a runner.

3. age (int): The age of the runner.

4. country (string): The country that the runner.

5. energy (int): The current level of energy for the player. It starts at max energy.

6. sprint_speed (float): The speed at which the runner runs when participating in a short race (in meters per second).

7. endurance_speed (float) : The speed at which the runner runs when participating in a marathon (in meters per second).

What has been given (with errors)

The class also contains the following methods:

1. __init__(self, name, age, country, sprint_speed, endurance_speed) : this method creates the runner with the attributes passed to the method. There are certain limitations to the attribute values:

o name must be an alphanumeric string (can contain spaces),

o age must be an integer between 5 and 120 (both inclusive),

o country must be a string and its value must be from the ones contained in the 'name' column of the csv countries.csv provided in the directory this file is currently being run,
NOTE : You may assume that countries.csv always exists

o sprint_speed must be a float and its value should lie between 2.2 and 6.8 in meters per second (both inclusive),

o endurance_speed must be a float and its value should lie between 1.8 and 5.4 in meters per second (both inclusive).

2. drain_energy(self, drain_points) : this method gets an integer and drains the energy of the runner by the value of drain_points passed. The value of drain points cannot be less than 0 or more than the max_energy value of the runner. Also, the leftover energy of the player once the energy is drained cannot be less than 0. After this method concludes, the energy of the player should have been reduced by the value passed in the function.

3. recover_energy(self, recovery_amount) : this method gets an integer and recovers the energy of the player by the value of recovery_amount passed. The value of the energy of the player cannot exceed the maximum energy. If the energy of the player after adding recovery_amount goes over the max_energy then you should set the energy to the max_energy. You should also note that recovery_amount should not be more than max_energy.

4. run_race(self, race_type, distance) -> float : this method takes in the race type (either "short" or "long" ) and distance (in kilometers) of the race and is a float value. It then returns the floating value of the time taken (in seconds; rounded to 2 decimal places) to complete the race. After this method concludes, there should be no change in the stats of the player. Please note that if the race is a short race, use the sprint speed of the runner. If the race is a marathon, then use the endurance speed of the runner.

5. __str__(self) : this method just returns the details of the runner. You don't need to test this method.

Remember! You may need to validate the input that these methods receive and raise relevant errors. You will also need to assert the post conditions of these methods, that are mentioned above.

For You To Do

Most of the code has already been done for you. However, your TAs have become lazy and made code mistakes. :(

You are tasked with the following:

1. Fix the errors made in the class, variables, and methods based on the descriptions mentioned above.

2. Check the pre-conditions and post-conditions for each of the methods. Make sure to raise the relevant errors if incorrect values are passed to the functions.

3. Document your code including type-hinting for all variables, arguments for functions and methods, and relevant docstrings for each method and class.

4. Build on the unit tests that have already been given to you in the file test_runner.py. You are expected to create at least three tests for each method. You should create these additional tests in a separate testing function in the given class.

Important Points

Remember, it is YOUR RESPONSIBILITY to ensure that a proper custom error is raised when an invalid input is received. Here are some pointers:

· If the value received by a method is invalid or not what the method expects, then you should raise a CustomValueError.

· If the type of value received by a method is invalid or not what the method expects, then you should raise a CustomTypeError.

· If the value being passed to the method is not an attribute of the class, then you should raise an CustomAttributeError.

· If the method is trying to get a value from a dictionary that shouldn't be returned, you should raise a CustomKeyError.

[Task 2] - At The Races (25%)

You are NOT allowed to use try/except blocks in Task 2.

Task Setup

Now that we have our runners, we will turn our attention to the races. In the scaffold, you will see a (somewhat) complete code for the races. There are two types of races - Short and Marathon.

What has been given (with errors)

There are certain features and attributes that the races share in common, however, some of them are different. As was the case in the previous task, here are the details of the attributes used in these classes:

1. race_type : A string that contains the type of the race. If its a short race, this will contain the string "short" whereas if the race is a marathon, then this string will contain "long".

2. distance : A positive floating value that contains (in kilometres) the distance of the race. Distances vary even within marathons and short races.

3. runners : A list of runner objects (from the runner class in the previous task).

4. maximum_participants : An integer that defines the maximum number of participants that can participate in the race. This value is 8 for short races and 16 for marathons.

5. time_multiplier : Our calculations consider the runners running at the highest speed for the entire duration of a short race. To cater for the error, we apply a time_multiplier which fixes the time calculated for a runner to run the short race. The value of this multiplier is currently set to 1.2 for all short races. This value doesn't exist for marathon races.
For example - if a runner's speed is ��y meters per second, and the distance is ��x meters, then the time should be calculated as
time=����∗1.2time=xy∗1.2

1. energy_per_km : An integer (set to 100 for all marathons) that contains the amount of energy consumed per kilometer run of a marathon. When the race is conducted for a marathon, energy is consumed per km and the racers that run out of energy before the marathon finishes don't qualify as a finisher. This value doesn't exist for short races.

The classes given to you also has the following methods:

1. __init__(self, distance, runners = None) : this is the constructor for the Race(ABC) class that sets up the Race. As you can see, runners is an optional parameter. If the value of runners is passed as None or if no value for runners is provided, you should initialise the runners as an empty list. However, if there are values provided, then they should only be objects of the Runner class.

2. add_runner(self) : this method adds a runner to the race. However, if the runner already exists, then this method should raise a RunnerAlreadyExistsError, which has been imported for you already. You should also make sure that the number of runners don't exceed the maximum_participants. In case adding the runner will exceed the maximum participants, you should raise a RaceIsFull error.

3. remove_runner(self) : this method removes a runner from the race. However, if the runner does not exist then this method should raise a RunnerDoesntExistError, which has been imported for you already.

4. conduct_race(self) : this method should conduct a race based on the type of race that we are considering.

o For a short race: We call the run_race method for each runner and calculate the time taken to run the race.

o For a marathon race: We call the run_race method once for each runner for each kilometre of the marathon race. We also reduce the runner's energy according to the value set in the class. For this purpose, feel free to round up the distance to the nearest integer. If the runner runs out of energy, their finish time is set to 'DNF' (Did Not Finish).

After the conclusion of the conduct_race method, a list of tuples should be returned (this code is already done for you).

For You To Do

We definitely need to find better TAs because these ones keep making mistakes!

You are tasked with the following:

1. Copy and replace the code for runner.py that is given in the scaffold with your pristine code from the previous task.

2. Fix the errors that have been made in the class, variables, and methods based on the descriptions provided above. There may be cases where you need to remove some of the methods if you are implementing inheritance.
NOTE: You may need to move/remove some of the variables and methods in between the three classes once you implement proper inheritance. Please ensure that the names of the methods/variables DO NOT CHANGE from the ones given to you.

3. Check the pre-conditions and post-conditions for each of the methods. Make sure to raise the relevant errors if incorrect values are passed to the functions.

4. Document your code including type-hinting for all variables and arguments for functions and methods, as well as include relevant docstrings for each method and class.

5. Build on the unit tests that have already been given to you in the file test_races.py. You are expected to create at least three tests for each method. You should create these additional tests in a separate testing function in the given class.

Important Points

Remember, it is YOUR RESPONSIBILITY to ensure that a proper error is raised when an invalid input is received. Here are some pointers:

· If the value received by a method is invalid or not what the method expects, then you should raise a CustomValueError.

· If the type of value received by a method is invalid or not what the method expects, then you should raise a CustomTypeError.

· If the value being passed to the method is not an attribute of the class, then you should raise an CustomAttributeError.

· If the method is trying to get a value from a dictionary that shouldn't be returned, you should raise a CustomKeyError.

· If a runner is being added to a race that already exists in the race, you should raise a RunnerAlreadyExistsError.

· If a runner is being removed from a race that doesn't exist in that race, you should raise a RunnerDoesntExistError.

[Task 3] - Competition (25%)

You are NOT allowed to use try/except blocks in Task 3.

We have our runners, we have our races. Now, let's work towards creating a competition!

The competition class consists of one or several races with different runners competing for the title of the ultimate champion!

The Competition class has the following variables:

1. MAX_ROUNDS : An integer class variable that holds the number of rounds for the competition. The default value of this is set to 3.

2. runners : A list of runners being passed to the constructor.

3. rounds : A positive integer that determines how many rounds of races will be conducted in this competition. This cannot exceed MAX_ROUNDS.

4. distances_short : A list of positive floating values that serve as distances for the short_race (in km).

5. distances_marathon : A list of positive floating values that serve as distances for the marathon race (in km).

6. leaderboard : A dictionary that contains the positions of the players in this competition.

It also has the following methods:

1. __init__(self, runners, rounds, distances_short, distances_marathon) : This method is the constructor of the competition class that takes in a list of runners (can be an empty list), number of rounds and a list each of distances for short races and marathon races, and initialises these variables. It should also fill in the leaderboard with keys as the positions ('1st', '2nd', '3rd', '4th', '5th', ... etc.) based on the number of runners but the values for all these keys should be set to None. This code has already been done for you. You need to ensure that the number of rounds does not exceed MAX_ROUNDS. You should also ensure that the length of both distances lists should be the same as rounds.

2. conduct_competition(self) : This method is the main method by which the competition will be conducted until and including the value of self.rounds is reached, starting at round 1. Each round contains a short race and a marathon race with the runners added at the start of the race. The distance for each round should be retrieved from the self.distances_short and self.distances_marathon variables. After each round, you should recover the racers who did not finish the race to maximum energy. This means only the runners who Did Not Finish should recover to maximum energy. This method should return the final leaderboard.

3. conduct_race(self, race) : This method takes in an object of the race family and returns a list of the runners and their times taken to finish the race.

4. update_leaderboard(self, results) : This method takes a list of results from the conduct_race method and updates the leaderboard according to the positions obtained by the runners. The leaderboard is set as follows:

o Check the list of results and assign points based on the runner's position, inverse to the number of runners (For example, if 4 runners are running and you place first, you get 3 points. If you place second, you get 2 points; and so on). Any runner that does not finish (DNF) should get 0 points.

o If the leaderboard is empty; then you should assign the value as a tuple containing the name of the runner as well as their points.

o If the leaderboard already has players, then you should update the runners' points and then re-assign the runners if their position has changed on the leaderboard.

5. print_leaderboard(self) : This method prints the leaderboard with the position, the name and the points (in brackets) of the runners. For example:

TEXT

Leaderboard

1st - Elijah (10)

2nd - Phoebe (7)

3rd - Lauren (4)

4th - Rupert (1)

5th - Chloe (0)

Again, most of the methods are already done for you, your job is as follows:

· Copy and replace the code for runner.py and race.py that is given in the scaffold with your pristine code from the previous tasks.

· Fix the logical errors that have been made in the class, variables, and methods given above.

· Check the pre-conditions and post-conditions for each of the methods. Make sure to raise the relevant errors if incorrect values are passed to the functions

· Document your code including type-hinting for all variables and arguments for functions and methods, as well as include relevant docstrings for each method and class.

· Build on the unit tests that have already been given to you in the file test_competition.py. You are expected to create at least three tests for each method. You should create these additional tests in a separate testing function in the given class.

Sample Competition

Here is the expected CUMULATIVE leaderboard after each race of each round after running the same runners that have been provided to you at the bottom of your file:

SETUP

PYTHON

1

2

3

4

5

6

7

8

9

runners = [

Runner("Elijah", 19, 'Australia', 6.4, 5.2),

Runner("Rupert", 67, 'Botswana', 2.2, 1.8),

Runner("Phoebe", 12, 'France', 3.4, 2.8),

Runner("Lauren", 13, 'Iceland', 4.4, 5.1),

Runner("Chloe", 21, 'Timor-Leste', 5.2, 1.9)

]

competition = Competition(runners, 3, [0.5, 0.6, 1.2], [4.0, 9.0, 4.5])

ROUND 1

After Short Race:

TEXT

1

2

3

4

5

1st - Elijah (4)

2nd - Chloe (3)

3rd - Lauren (2)

4th - Phoebe (1)

5th - Rupert (0)

After Marathon Race:

TEXT

1

2

3

4

5

1st - Elijah (8)

2nd - Lauren (5)

3rd - Chloe (4)

4th - Phoebe (3)

5th - Rupert (0)

ROUND 2

After Short Race:

TEXT

1

2

3

4

5

1st - Elijah (12)

2nd - Chloe (7)

3rd - Lauren (7)

4th - Phoebe (4)

5th - Rupert (0)

After Marathon Race:

TEXT

1

2

3

4

5

1st - Elijah (16)

2nd - Lauren (10)

3rd - Chloe (8)

4th - Phoebe (6)

5th - Rupert (0)

ROUND 3

After Short Race:

TEXT

1

2

3

4

5

1st - Elijah (20)

2nd - Lauren (12)

3rd - Chloe (11)

4th - Phoebe (7)

5th - Rupert (0)

After Marathon Race:

TEXT

1

2

3

4

5

1st - Elijah (20)

2nd - Lauren (12)

3rd - Chloe (11)

4th - Phoebe (7)

5th - Rupert (0)

FINAL LEADERBOARD

TEXT

1

2

3

4

5

1st - Elijah (20)

2nd - Lauren (12)

3rd - Chloe (11)

4th - Phoebe (7)

5th - Rupert (0)

[Task 4] - It All Comes Together (30%)

You are allowed to use try/except blocks in Task 4.

You have worked over the last three tasks to create the runner's assertion with various classes.

Now, you must create a command line interface that ties it all together.

You have been given a (minimal) scaffold in this task. There are no automated tests in this task and the markers will manually check this.

Your task is as follows:

1. Create the code for the main method in the scaffold.
i) The user should be able to create a runner from scratch (i.e., enter the name, age, country, speeds, etc.). The input should be just one string that contains the name/age/country/speeds. Please see the example below.
ii) The user should be able to choose how many rounds the competition should run for, as well as the distances for the short races and marathons in the competition. The input should be the same (i.e., comma-separated). Please see the example below.

2. Document the methods given in the scaffold.

3. Ensure that your code will not break under (most) circumstances by using try and except blocks to handle the custom errors we have defined in this assignment.

4. Write a testing harness under the file test_task4.py that runs basic checks.

Testing harness for this task is NOT GRADED. Although we are not assigning any marks to this, you should still try to create some tests for this task for your own sanity check.

A run and a check button has been implemented for this task, which will let you run your task4.py and test_task4.py file respectively.

There are no automated tests for this task hence, the Test button is missing.

WARNING! All of your error handling for creating runners and creating competitions MUST be handled in the create_runner and create_competition methods. Do not create one giant main method. You are STRONGLY RECOMMENDED to create smaller functions to help modularise the code. This is something we will be grading you on.

Example Output

(Please note: this is only an indication. Your output does not need to be exactly the same. However, your program must still ask the user to create runners and competitions. It should also handle all errors that may be raised due to the creation of the runners and competition. Your tutors will enter several inputs to try and break your code so its best if you try to do the same before submitting the assignment.

TEXT

9

10

11

12

13

14

15

16

17

18

19

20

21

22

ERROR : There must be as many sprint distances as there are rounds

ERROR : There must be as many marathon distances as there are rounds

Create competition - rounds/sprint distances/marathon distances: 3/3.4,5.5,6.5/5.0,6.0,12.0

Done creating competition

Executing the competition!

Competition concluded!

Leaderboard

1st - Buser (6)

2nd - Pierre (0)

Final Submission Instructions

The submission slide is available (next slide). Like the last assignment, students must copy the files associated with each task into the submission slide and click the submit button in the top right of the slide.

There is no submission on Moodle, just edstem here.

Your submission deadline is the date and time after which you will start getting penalised for late submissions. This date can be found on Moodle. Unless you have an extension, the submission deadline is the 24th of May at 11:55 pm.

We have a set of new rules related to creating a submission. They are as follows:

· You are allowed ONE submission.

· Students may only submit once and may not continue to work on the project after this submission.

o If you submit in error and the submission deadline has not yet passed, you may request to have your submission reopened.

o Once your submission is reopened all previous submissions are voided and will not be marked.

o These requests must be made before 4 pm (AEST) to be processed on the same business day.

o Any request made after 4 pm (AEST) will not be processed until the next business day (this means we make no guarantees about requests made on weekends).

o Requests to reopen a submission will not be accepted after the submission deadline has passed. This means that you can submit late but you cannot re-submit late.

· If you have an open attempt at the time of marking, then any previous submission will not be marked and that attempt will be considered to be unsubmitted.

You must make a private post on ed and use the Resubmission Request category if you want to make a request for resubmission.

Update:

If you are awaiting a verdict from the special considerations team, please do not make a submission until you have finished, as you will not be able to continue working on your assignment.