From 13cf154cef3a14a246ce48eea0b6931dba5e4af5 Mon Sep 17 00:00:00 2001 From: Oleksii Proshchenko <80070761+MasterpieceElbow@users.noreply.github.com> Date: Tue, 18 Jan 2022 11:05:17 +0200 Subject: [PATCH 01/25] Initial commit --- .flake8 | 5 +++++ .github/workflows/test.yml | 30 ++++++++++++++++++++++++++++++ .gitignore | 8 ++++++++ README.md | 4 ++++ app/main.py | 3 +++ requirements.txt | 2 ++ tests/__init__.py | 0 tests/test_main.py | 6 ++++++ 8 files changed, 58 insertions(+) create mode 100644 .flake8 create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app/main.py create mode 100644 requirements.txt create mode 100644 tests/__init__.py create mode 100644 tests/test_main.py diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..794c2d3fe --- /dev/null +++ b/.flake8 @@ -0,0 +1,5 @@ +[flake8] +ignore = E203, E266 +max-line-length = 79 +max-complexity = 18 +select = B,C,E,F,W,T4,B9 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..245d0ed78 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,30 @@ +name: Test + +on: + pull_request: + branches: + - "master" + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Set Up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: Install pytest and flake8 + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run flake8 + run: flake8 app/ + - name: Run tests + run: pytest tests/ + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b26d61168 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.idea/ +.vscode/ +*.iml +.env +.DS_Store +venv/ +.pytest_cache/ +**__pycache__/ diff --git a/README.md b/README.md new file mode 100644 index 000000000..5be5cadc5 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Python boilerplate for GitHub tasks + +- Read [the guideline](https://github.com/mate-academy/py-task-guideline/blob/main/README.md) before start +- Implement the task described [here](app/main.py) diff --git a/app/main.py b/app/main.py new file mode 100644 index 000000000..773a588bb --- /dev/null +++ b/app/main.py @@ -0,0 +1,3 @@ +# TODO: add initial code +def hello_world(): + return "Hello, world!" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..7c8a737cf --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pytest==6.2.5 +flake8==4.0.1 \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_main.py b/tests/test_main.py new file mode 100644 index 000000000..6d8b32356 --- /dev/null +++ b/tests/test_main.py @@ -0,0 +1,6 @@ +# TODO: add tests +from app.main import hello_world + + +def test_hello_world(): + assert hello_world() == "Hello, world!" From 08d54c19fe676aedcbd3f8d15677edd0be5fd92a Mon Sep 17 00:00:00 2001 From: Oleksii Proshchenko <80070761+MasterpieceElbow@users.noreply.github.com> Date: Tue, 18 Jan 2022 15:04:12 +0200 Subject: [PATCH 02/25] Init --- README.md | 78 +++++++++++++++++++++++++++++++++- app/main.py | 11 +++-- tests/test_main.py | 101 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 181 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 5be5cadc5..e5ff08b90 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,78 @@ -# Python boilerplate for GitHub tasks +# Washing Station - Read [the guideline](https://github.com/mate-academy/py-task-guideline/blob/main/README.md) before start -- Implement the task described [here](app/main.py) + +You own a car washing station. Washing cost calculation +takes a lot of time, and you decide to automate this +calculation. The washing cost will depend on car comfort +class, car cleanness degree, wash station average rating +and car wash distance from the center of the city. + +Create class `Car`, its constructor takes and stores +3 arguments: +1. `comfort_class` - comfort class of a car, from 1 to 7 +3. `clean_mark` - car cleanness mark, from very +dirty - 1 to absolute clean - 10 +4. `brand` - brand of the car + +Create class `CarWashStation`, its constructor takes and +stores 4 arguments: +1. `distance_from_cite_center` - how far station from +the city center, from 1.0 to 10.0 +2. `clean_power` - `clean_mark` to which this car wash station +washes +3. `average_rating` - average rating of the station, +from 1.0 to 5.0, rounded to 1 decimal +4. `count_of_ratings` - number of people who rated + +`CarWashStation` should have such methods: +1. `serve_cars` Method that takes a list of `Car`'s, washes only +cars with `clean_mark` < `clean_power` of wash station +and returns total wash cost, rounded to 1 decimal +2. `calculate_washing_price` Method that calculates cost for a +single car wash, +cost is calculated as: car's comfort class * difference of car's +clean mark and wash station's clean power * car wash station +rating / car wash station +distance to the center of the city, returns number rounded +to 1 decimal +3. `wash_single_car` Every car after wash is clean, so it should +have `clean_mark` equals wash station's `clean_power`, +make individual method for this. +4. `rate_service` Method to add a single rate. + +You can add own methods if you need. + +Example: +```python +bmw = Car(3, 3, 'BMW') +audi = Car(4, 9, 'Audi') +mercedes = Car(7, 1, 'Mercedes') + +ws = CarWashingStation(6, 8, 3.9, 11) + +income = ws.serve_cars([ + bmw, + audi, + mercedes +]) + +income == 41.6 + +bmw.clean_mark == 8 +audi.clean_mark == 9 +mercedes.clean_mark == 8 +# audi wasn't washed +# all other cars are washed to '8' + +ford = Car(2, 1, 'Ford') +wash_cost = ws.calculate_washing_price(ford) +# only calculating cost, not washing +wash_cost == 11.7 +ford.clean_mark == 1 + +ws.rate_service(5) + +ws.count_of_ratings == 12 +ws.average_rating == 4.0 +``` \ No newline at end of file diff --git a/app/main.py b/app/main.py index 773a588bb..b2d096bda 100644 --- a/app/main.py +++ b/app/main.py @@ -1,3 +1,8 @@ -# TODO: add initial code -def hello_world(): - return "Hello, world!" +class Car: + # write your code here + pass + + +class CarWashStation: + # write your code here + pass diff --git a/tests/test_main.py b/tests/test_main.py index 6d8b32356..196a72a92 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,6 +1,99 @@ -# TODO: add tests -from app.main import hello_world +import pytest +from app.main import Car, CarWashStation -def test_hello_world(): - assert hello_world() == "Hello, world!" + +def test_car(): + bmw = Car(2, 3, "BMW") + assert bmw.comfort_class == 2, "Class Car should store 'comfort_class'" + assert bmw.clean_mark == 3, "Class Car should store 'clean_mark'" + assert bmw.brand == "BMW", "Class Car should store 'brand'" + + +@pytest.mark.parametrize( + "cars,washstation,total_cost", + [ + ([], CarWashStation(3, 9, 4.4, 144), 0), + ([Car(2, 1, "Ford")], CarWashStation(3, 9, 4.2, 11), 22.4), + ([Car(2, 9, "Ford")], CarWashStation(3, 8, 4.2, 11), 0), + ( + [Car(3, 3, "BMW"), Car(4, 5, "Audi"), Car(7, 1, "Mercedes")], + CarWashStation(6, 7, 3.9, 11), + 40.3, + ), + ( + [Car(3, 3, "BMW"), Car(4, 5, "Audi"), Car(7, 9, "Mercedes")], + CarWashStation(6, 7, 3.9, 11), + 13.0, + ), + ( + [Car(3, 8, "BMW"), Car(4, 8, "Audi"), Car(7, 9, "Mercedes")], + CarWashStation(6, 7, 3.9, 11), + 0, + ), + ], +) +def test_car_wash_station(cars, washstation, total_cost): + income = washstation.serve_cars(cars) + assert income == total_cost, f"Income should equal to {total_cost}" + + +@pytest.mark.parametrize( + "cars,washstation,cars_clean_marks", + [ + ([Car(2, 1, "Ford")], CarWashStation(3, 9, 4.2, 11), [9]), + ([Car(2, 9, "Ford")], CarWashStation(3, 8, 4.2, 11), [9]), + ( + [Car(3, 3, "BMW"), Car(4, 5, "Audi"), Car(7, 1, "Mercedes")], + CarWashStation(6, 7, 3.9, 11), + [7, 7, 7], + ), + ( + [Car(3, 3, "BMW"), Car(4, 5, "Audi"), Car(7, 9, "Mercedes")], + CarWashStation(2, 8, 4.8, 13), + [8, 8, 9], + ), + ], +) +def test_car_is_washed(cars, washstation, cars_clean_marks): + income = washstation.serve_cars(cars) + assert [car.clean_mark for car in cars] == cars_clean_marks, ( + f"Car should keep his 'clear_mark' if it >= 'clear_power' of wash station, " + f"otherwise it should equal to 'clear_power'" + ) + + +@pytest.mark.parametrize( + "car,washstation,mark", + [ + (Car(2, 1, "Ford"), CarWashStation(3, 10, 4.2, 11), 1), + (Car(4, 5, "Audi"), CarWashStation(6, 8, 3.9, 11), 5), + (Car(3, 3, "BMW"), CarWashStation(2, 9, 4.8, 13), 3), + ], +) +def test_car_cost_check_not_washed(car, washstation, mark): + cost = washstation.calculate_washing_price(car) + assert car.clean_mark == mark, ( + f"Method 'calculate_washing_price' should not change" f"'car.clean_mark'" + ) + + +@pytest.mark.parametrize( + "init_avg_rating,init_num_ratings,mark,result_avg_rating,result_num_ratings", + [ + (2.2, 2, 5, 3.1, 3), + (2.4, 11, 5, 2.6, 12), + (3.8, 7, 2, 3.6, 8), + (4.4, 42, 4, 4.4, 43), + ], +) +def test_rate_service( + init_avg_rating, init_num_ratings, mark, result_avg_rating, result_num_ratings +): + ws = CarWashStation(2, 9, init_avg_rating, init_num_ratings) + ws.rate_service(mark) + assert ws.average_rating == result_avg_rating, ( + f"'average_rating' should equal to {result_avg_rating}, " + f"when initial 'average_rating' was {init_avg_rating}, " + f"and initial 'count_of_ratings' was {init_num_ratings}" + ) From 4440bbbdc3f89a7add85629d7da0f2fe1b5b06f4 Mon Sep 17 00:00:00 2001 From: Oleksii Proshchenko <80070761+MasterpieceElbow@users.noreply.github.com> Date: Tue, 18 Jan 2022 17:30:25 +0200 Subject: [PATCH 03/25] Edited --- README.md | 25 +++++++++++++------------ tests/test_main.py | 22 +++++++++++++--------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index e5ff08b90..e51a0da28 100644 --- a/README.md +++ b/README.md @@ -6,40 +6,41 @@ You own a car washing station. Washing cost calculation takes a lot of time, and you decide to automate this calculation. The washing cost will depend on car comfort class, car cleanness degree, wash station average rating -and car wash distance from the center of the city. +and wash station distance from the center of the city. Create class `Car`, its constructor takes and stores 3 arguments: 1. `comfort_class` - comfort class of a car, from 1 to 7 -3. `clean_mark` - car cleanness mark, from very +2. `clean_mark` - car cleanness mark, from very dirty - 1 to absolute clean - 10 -4. `brand` - brand of the car +3. `brand` - brand of the car Create class `CarWashStation`, its constructor takes and stores 4 arguments: -1. `distance_from_cite_center` - how far station from +1. `distance_from_city_center` - how far station from the city center, from 1.0 to 10.0 2. `clean_power` - `clean_mark` to which this car wash station -washes +washes (yes, not all stations can clean your car completely) 3. `average_rating` - average rating of the station, from 1.0 to 5.0, rounded to 1 decimal 4. `count_of_ratings` - number of people who rated `CarWashStation` should have such methods: -1. `serve_cars` Method that takes a list of `Car`'s, washes only +1. `serve_cars` - method, that takes a list of `Car`'s, washes only cars with `clean_mark` < `clean_power` of wash station -and returns total wash cost, rounded to 1 decimal -2. `calculate_washing_price` Method that calculates cost for a +and returns income of CarWashStation for serving this list of Car's, +rounded to 1 decimal +2. `calculate_washing_price` - method, that calculates cost for a single car wash, -cost is calculated as: car's comfort class * difference of car's -clean mark and wash station's clean power * car wash station +cost is calculated as: car's comfort class * difference between +wash station's clean power and car's clean mark * car wash station rating / car wash station distance to the center of the city, returns number rounded to 1 decimal -3. `wash_single_car` Every car after wash is clean, so it should +3. `wash_single_car` - every car after wash is clean, so it should have `clean_mark` equals wash station's `clean_power`, make individual method for this. -4. `rate_service` Method to add a single rate. +4. `rate_service` - method to add a single rate. You can add own methods if you need. diff --git a/tests/test_main.py b/tests/test_main.py index 196a72a92..9e8b54785 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -11,7 +11,7 @@ def test_car(): @pytest.mark.parametrize( - "cars,washstation,total_cost", + "cars,wash_station,total_cost", [ ([], CarWashStation(3, 9, 4.4, 144), 0), ([Car(2, 1, "Ford")], CarWashStation(3, 9, 4.2, 11), 22.4), @@ -33,13 +33,13 @@ def test_car(): ), ], ) -def test_car_wash_station(cars, washstation, total_cost): - income = washstation.serve_cars(cars) +def test_car_wash_station(cars, wash_station, total_cost): + income = wash_station.serve_cars(cars) assert income == total_cost, f"Income should equal to {total_cost}" @pytest.mark.parametrize( - "cars,washstation,cars_clean_marks", + "cars,wash_station,cars_clean_marks", [ ([Car(2, 1, "Ford")], CarWashStation(3, 9, 4.2, 11), [9]), ([Car(2, 9, "Ford")], CarWashStation(3, 8, 4.2, 11), [9]), @@ -55,8 +55,8 @@ def test_car_wash_station(cars, washstation, total_cost): ), ], ) -def test_car_is_washed(cars, washstation, cars_clean_marks): - income = washstation.serve_cars(cars) +def test_car_is_washed(cars, wash_station, cars_clean_marks): + wash_station.serve_cars(cars) assert [car.clean_mark for car in cars] == cars_clean_marks, ( f"Car should keep his 'clear_mark' if it >= 'clear_power' of wash station, " f"otherwise it should equal to 'clear_power'" @@ -64,15 +64,15 @@ def test_car_is_washed(cars, washstation, cars_clean_marks): @pytest.mark.parametrize( - "car,washstation,mark", + "car,wash_station,mark", [ (Car(2, 1, "Ford"), CarWashStation(3, 10, 4.2, 11), 1), (Car(4, 5, "Audi"), CarWashStation(6, 8, 3.9, 11), 5), (Car(3, 3, "BMW"), CarWashStation(2, 9, 4.8, 13), 3), ], ) -def test_car_cost_check_not_washed(car, washstation, mark): - cost = washstation.calculate_washing_price(car) +def test_car_cost_check_not_washed(car, wash_station, mark): + wash_station.calculate_washing_price(car) assert car.clean_mark == mark, ( f"Method 'calculate_washing_price' should not change" f"'car.clean_mark'" ) @@ -97,3 +97,7 @@ def test_rate_service( f"when initial 'average_rating' was {init_avg_rating}, " f"and initial 'count_of_ratings' was {init_num_ratings}" ) + assert ws.count_of_ratings == result_num_ratings, ( + f"'count_of_ratings' should equal to {result_num_ratings}, " + f"when initial 'count_of_ratings' was {init_num_ratings}" + ) From 74beef48ab30399d65b2b4b2a306955fb86452ab Mon Sep 17 00:00:00 2001 From: Oleksii Proshchenko <80070761+MasterpieceElbow@users.noreply.github.com> Date: Tue, 18 Jan 2022 19:30:39 +0200 Subject: [PATCH 04/25] edited --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e51a0da28..bd74e69d9 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Create class `Car`, its constructor takes and stores 3 arguments: 1. `comfort_class` - comfort class of a car, from 1 to 7 2. `clean_mark` - car cleanness mark, from very -dirty - 1 to absolute clean - 10 +dirty - 1 to absolutely clean - 10 3. `brand` - brand of the car Create class `CarWashStation`, its constructor takes and @@ -37,9 +37,9 @@ wash station's clean power and car's clean mark * car wash station rating / car wash station distance to the center of the city, returns number rounded to 1 decimal -3. `wash_single_car` - every car after wash is clean, so it should -have `clean_mark` equals wash station's `clean_power`, -make individual method for this. +3. `wash_single_car` - method, that washes a single car, so it should +have `clean_mark` equals wash station's `clean_power`, if +`wash_station.clean_power` is greater than `car.clean_mark` 4. `rate_service` - method to add a single rate. You can add own methods if you need. From 1dd8c9b97d5165aaf925c0ccb866aeeed3debf12 Mon Sep 17 00:00:00 2001 From: Alex Zhidkov Date: Tue, 3 May 2022 10:50:26 +0300 Subject: [PATCH 05/25] add exclude venv and tests in .flake8 --- .flake8 | 1 + 1 file changed, 1 insertion(+) diff --git a/.flake8 b/.flake8 index 794c2d3fe..03f8b03bc 100644 --- a/.flake8 +++ b/.flake8 @@ -3,3 +3,4 @@ ignore = E203, E266 max-line-length = 79 max-complexity = 18 select = B,C,E,F,W,T4,B9 +exclude = venv, tests From 806831d96dcc3455d8229da68d1d14054e9318dd Mon Sep 17 00:00:00 2001 From: Alex Zhidkov Date: Wed, 11 May 2022 19:00:16 +0300 Subject: [PATCH 06/25] fix readme.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bd74e69d9..b4339dcf1 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ bmw = Car(3, 3, 'BMW') audi = Car(4, 9, 'Audi') mercedes = Car(7, 1, 'Mercedes') -ws = CarWashingStation(6, 8, 3.9, 11) +ws = CarWashStation(6, 8, 3.9, 11) income = ws.serve_cars([ bmw, @@ -58,7 +58,7 @@ income = ws.serve_cars([ mercedes ]) -income == 41.6 +income == 41.7 bmw.clean_mark == 8 audi.clean_mark == 9 @@ -69,7 +69,7 @@ mercedes.clean_mark == 8 ford = Car(2, 1, 'Ford') wash_cost = ws.calculate_washing_price(ford) # only calculating cost, not washing -wash_cost == 11.7 +wash_cost == 9.1 ford.clean_mark == 1 ws.rate_service(5) From dda2a4c0e71a3618681a963b91d7c64b60b2a9a3 Mon Sep 17 00:00:00 2001 From: Alex Zhidkov Date: Thu, 9 Jun 2022 14:59:21 +0300 Subject: [PATCH 07/25] add timeout on tests --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 245d0ed78..94a793271 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,5 +26,6 @@ jobs: - name: Run flake8 run: flake8 app/ - name: Run tests + timeout-minutes: 5 run: pytest tests/ From 2392e6e19c7e7c7482be786cc8487f568dbdba53 Mon Sep 17 00:00:00 2001 From: Alex Zhidkov <72562232+Abnormaltype@users.noreply.github.com> Date: Fri, 10 Jun 2022 12:24:52 +0300 Subject: [PATCH 08/25] Update test.yml --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 94a793271..c2ed2b734 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,10 +13,10 @@ jobs: - name: Checkout repo uses: actions/checkout@v2 - - name: Set Up Python 3.8 + - name: Set Up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: "3.10" - name: Install pytest and flake8 run: | From 06d531d94e3457e5ff5b43b6a71e3ade0933bd42 Mon Sep 17 00:00:00 2001 From: Dmytro Svirsa <104418771+DmytroSvirsa@users.noreply.github.com> Date: Tue, 6 Sep 2022 12:23:53 +0300 Subject: [PATCH 09/25] checklist and test for coment added --- README.md | 4 ++- checklist.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++ tests/test_main.py | 14 ++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 checklist.md diff --git a/README.md b/README.md index b4339dcf1..fe2aa2f2e 100644 --- a/README.md +++ b/README.md @@ -76,4 +76,6 @@ ws.rate_service(5) ws.count_of_ratings == 12 ws.average_rating == 4.0 -``` \ No newline at end of file +``` + +### Note: Check your code using this [checklist](checklist.md) before pushing your solution. diff --git a/checklist.md b/checklist.md new file mode 100644 index 000000000..f66d77fee --- /dev/null +++ b/checklist.md @@ -0,0 +1,69 @@ +# Check Your Code Against the Following Points + +## Code Style + +1. If you have some long math, you can split it onto additional variables. + +Good example: + +```python +fuel_consumption = max_fuel_consumption * height_fuel_consumption_coeficient +estimated_speed = plan_max_speed - wind_awerage_speed * wind_angle_coefisient +estimated_time = distance_to_the_destinatoin / estimated_speed +how_much_fuel_needed = fuel_consumption * estimated_time * overlap_coeficient +``` + +Bad example: + +```python +how_much_fuel_needed = max_fuel_consumption \ + * height_fuel_consumption_coeficient \ + * distance_to_the_destinatoin / ( + plan_max_speed + - wind_awerage_speed + * wind_angle_coefisient + ) * overlap_coeficient +``` + +## Code Efficiency + +2. Use descriptive and correct variable names. + +Good example: + +```python +def get_full_name(first_name: str, last_name: str): + return f"{first_name} {last_name}" +``` + +Bad example: +```python +def get_full_name(x: str, y: str): + return f"{x} {y}" +``` + +## Clean Code + +1. You can avoid else when have return statement. + +Good example: + +```python +def is_adult(age): + if age >= 18: + return "adult" + return "not an adult" +``` + +Bad example: + +```python +def is_adult(age): + if age >= 18: + return "adult" + else: + return "not an adult" +``` + +2. Add comments, prints, and functions to check your solution when you write your code. +Don't forget to delete them when you are ready to commit and push your code. diff --git a/tests/test_main.py b/tests/test_main.py index 9e8b54785..158af067a 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -101,3 +101,17 @@ def test_rate_service( f"'count_of_ratings' should equal to {result_num_ratings}, " f"when initial 'count_of_ratings' was {init_num_ratings}" ) + + +def test_unnecessary_comment(): + if os.path.exists(os.path.join(os.pardir, "app", "main.py")): + main_path = os.path.join(os.pardir, "app", "main.py") + else: + main_path = os.path.join("app", "main.py") + + with open(main_path, "r") as main: + main_content = main.read() + + assert ( + "# write your code here" not in main_content + ), "Remove unnecessary comment" From 5a44a08d24908b2a9cffe2a92cc7af0b42d90b78 Mon Sep 17 00:00:00 2001 From: Yaroslav Havryliv Date: Tue, 6 Sep 2022 13:32:37 +0300 Subject: [PATCH 10/25] description to rate_service and serve_cars methods added --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b4339dcf1..20ab22828 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Washing Station -- Read [the guideline](https://github.com/mate-academy/py-task-guideline/blob/main/README.md) before start +Read [the guideline](https://github.com/mate-academy/py-task-guideline/blob/main/README.md) before starting. You own a car washing station. Washing cost calculation takes a lot of time, and you decide to automate this @@ -28,19 +28,85 @@ from 1.0 to 5.0, rounded to 1 decimal `CarWashStation` should have such methods: 1. `serve_cars` - method, that takes a list of `Car`'s, washes only cars with `clean_mark` < `clean_power` of wash station -and returns income of CarWashStation for serving this list of Car's, -rounded to 1 decimal +and returns income of `CarWashStation` for serving this list of Car's, +rounded to 1 decimal: + +```python +bmw = Car(comfort_class=3, clean_mark=3, brand='BMW') +audi = Car(comfort_class=4, clean_mark=9, brand='Audi') + +print(bmw.clean_mark) # 3 + +wash_station = CarWashStation( + distance_from_city_center=5, + clean_power=6, + average_rating=3.5, + count_of_ratings=6 +) + +income = wash_station.serve_cars([bmw, audi]) + +print(income) # 6.3 +print(bmw.clean_mark) # 6 +``` + +So, only bmw was washed, because `audi.clean_mark` > `wash_station.clean_power`, +and `bmw.clean_mark` has changed, because we washed it. + +If `audi.clean_mark` was below `wash_station.clean_power` then `audi` would have been washed as well +and the income would have raised: + +```python +bmw = Car(comfort_class=3, clean_mark=3, brand='BMW') +audi = Car(comfort_class=4, clean_mark=2, brand='Audi') + +print(bmw.clean_mark) # 3 +print(audi.clean_mark) # 2 + +wash_station = CarWashStation( + distance_from_city_center=5, + clean_power=6, + average_rating=3.5, + count_of_ratings=6 +) + +income = wash_station.serve_cars([bmw, audi]) + +print(income) # 17.5 + +print(bmw.clean_mark) # 6 +print(audi.clean_mark) # 6 +``` + 2. `calculate_washing_price` - method, that calculates cost for a single car wash, cost is calculated as: car's comfort class * difference between wash station's clean power and car's clean mark * car wash station rating / car wash station distance to the center of the city, returns number rounded -to 1 decimal +to 1 decimal; 3. `wash_single_car` - method, that washes a single car, so it should have `clean_mark` equals wash station's `clean_power`, if -`wash_station.clean_power` is greater than `car.clean_mark` -4. `rate_service` - method to add a single rate. +`wash_station.clean_power` is greater than `car.clean_mark`; +4. `rate_service` - method that adds a single rate to the wash station, and based on this single rate +`average_rating` and `count_of_ratings` should be changed: + +```python +wash_station = CarWashStation( + distance_from_city_center=6, + clean_power=8, + average_rating=3.9, + count_of_ratings=11 +) + +print(wash_station.average_rating) # 3.9 +print(wash_station.count_of_ratings) # 11 + +wash_station.rate_service(5) + +print(wash_station.average_rating) # 4.0 +print(wash_station.count_of_ratings) # 12 +``` You can add own methods if you need. From b53c4037a9c3f175618a7ebe65b4fd795ec43fd6 Mon Sep 17 00:00:00 2001 From: Oleksii Proshchenko <80070761+MasterpieceElbow@users.noreply.github.com> Date: Fri, 16 Sep 2022 11:22:41 +0300 Subject: [PATCH 11/25] Update .flake8 --- .flake8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.flake8 b/.flake8 index 03f8b03bc..9f7ad3ba5 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -ignore = E203, E266 +ignore = E203, E266, W503 max-line-length = 79 max-complexity = 18 select = B,C,E,F,W,T4,B9 From a07cd98360e56004c269d1e28d9cb04b230f14cf Mon Sep 17 00:00:00 2001 From: Dmytro Svirsa <104418771+DmytroSvirsa@users.noreply.github.com> Date: Mon, 19 Sep 2022 11:03:45 +0300 Subject: [PATCH 12/25] test added --- checklist.md | 25 ++++++++++++++++++------- tests/test_main.py | 8 ++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/checklist.md b/checklist.md index f66d77fee..5598f87dc 100644 --- a/checklist.md +++ b/checklist.md @@ -2,7 +2,8 @@ ## Code Style -1. If you have some long math, you can split it onto additional variables. +1. If you have some long math, you can split it onto additional variables, +or break after binary operations (not before - it cause the W504 errors) Good example: @@ -13,6 +14,18 @@ estimated_time = distance_to_the_destinatoin / estimated_speed how_much_fuel_needed = fuel_consumption * estimated_time * overlap_coeficient ``` +Good example: + +```python +how_much_fuel_needed = (max_fuel_consumption + * height_fuel_consumption_coeficient + * distance_to_the_destinatoin + / (plan_max_speed + - wind_awerage_speed + * wind_angle_coefisient) + * overlap_coeficient) +``` + Bad example: ```python @@ -25,20 +38,18 @@ how_much_fuel_needed = max_fuel_consumption \ ) * overlap_coeficient ``` -## Code Efficiency - 2. Use descriptive and correct variable names. Good example: ```python -def get_full_name(first_name: str, last_name: str): +def get_full_name(first_name: str, last_name: str) -> str: return f"{first_name} {last_name}" ``` Bad example: ```python -def get_full_name(x: str, y: str): +def get_full_name(x: str, y: str) -> str: return f"{x} {y}" ``` @@ -49,7 +60,7 @@ def get_full_name(x: str, y: str): Good example: ```python -def is_adult(age): +def is_adult(age: int) -> str: if age >= 18: return "adult" return "not an adult" @@ -58,7 +69,7 @@ def is_adult(age): Bad example: ```python -def is_adult(age): +def is_adult(age: int) -> str: if age >= 18: return "adult" else: diff --git a/tests/test_main.py b/tests/test_main.py index 158af067a..7928f9ae5 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,3 +1,5 @@ +from unittest.mock import patch + import pytest from app.main import Car, CarWashStation @@ -37,6 +39,12 @@ def test_car_wash_station(cars, wash_station, total_cost): income = wash_station.serve_cars(cars) assert income == total_cost, f"Income should equal to {total_cost}" +def test_wash_single_car_is_called(): + with patch.object(CarWashStation, 'wash_single_car') as mock_method: + CarWashStation(3, 9, 4, 11).serve_cars([Car(2, 1, "Ford")]) + assert mock_method.called, "Expected 'wash_single_car' to have " \ + "been called inside 'serve_cars' method" + @pytest.mark.parametrize( "cars,wash_station,cars_clean_marks", From 00e88af32895a50d7534c43e3939949be4ca1922 Mon Sep 17 00:00:00 2001 From: Dmytro Svirsa <104418771+DmytroSvirsa@users.noreply.github.com> Date: Mon, 19 Sep 2022 12:17:32 +0300 Subject: [PATCH 13/25] Update test_main.py --- tests/test_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_main.py b/tests/test_main.py index 7928f9ae5..23fe3a061 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,6 +1,6 @@ from unittest.mock import patch - import pytest +import os from app.main import Car, CarWashStation From 29404769f3d685b03de5700d1d9efc2cc971a02a Mon Sep 17 00:00:00 2001 From: Danylo Tiutiushkin <48014331+danylott@users.noreply.github.com> Date: Wed, 5 Oct 2022 13:38:38 +0300 Subject: [PATCH 14/25] Update .flake8 --- .flake8 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index 9f7ad3ba5..d7459204e 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,7 @@ [flake8] -ignore = E203, E266, W503 +inline-quotes = " +ignore = E203, E266, W503, ANN002, ANN003, ANN101, ANN102, ANN401, N807, N818 max-line-length = 79 max-complexity = 18 -select = B,C,E,F,W,T4,B9 +select = B,C,E,F,W,T4,B9,ANN,Q0,N8,VNE exclude = venv, tests From d1b65941f1374d2e9401ebd6437dc99fb25c7eac Mon Sep 17 00:00:00 2001 From: Danylo Tiutiushkin <48014331+danylott@users.noreply.github.com> Date: Wed, 5 Oct 2022 13:38:56 +0300 Subject: [PATCH 15/25] Update requirements.txt --- requirements.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 7c8a737cf..3f202d6e7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,6 @@ -pytest==6.2.5 -flake8==4.0.1 \ No newline at end of file +flake8==5.0.4 +flake8-annotations==2.9.1 +flake8-quotes==3.3.1 +flake8-variables-names==0.0.5 +pep8-naming==0.13.2 +pytest==7.1.3 From c418a39cc13f1f31515ca4164932e073ab0da419 Mon Sep 17 00:00:00 2001 From: Yaroslav <104159378+Y-Havryliv@users.noreply.github.com> Date: Thu, 23 Feb 2023 12:20:56 +0200 Subject: [PATCH 16/25] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3e8150f03..906a089b5 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,14 @@ calculation. The washing cost will depend on car comfort class, car cleanness degree, wash station average rating and wash station distance from the center of the city. -Create class `Car`, its constructor takes and stores +Create class `Car`, its `__init__` method takes and stores 3 arguments: 1. `comfort_class` - comfort class of a car, from 1 to 7 2. `clean_mark` - car cleanness mark, from very dirty - 1 to absolutely clean - 10 3. `brand` - brand of the car -Create class `CarWashStation`, its constructor takes and +Create class `CarWashStation`, its `__init__` method takes and stores 4 arguments: 1. `distance_from_city_center` - how far station from the city center, from 1.0 to 10.0 From ee215a2f84235840ba43d4086a6a4a468ed92ab3 Mon Sep 17 00:00:00 2001 From: Ihor Nahnybida <79282749+ihor-jpeg@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:25:56 +0300 Subject: [PATCH 17/25] Update test.yml change pull_request to pull_reauest_target --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c2ed2b734..9e72740ba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,7 +1,7 @@ name: Test on: - pull_request: + pull_request_target: branches: - "master" From 16d8349604674f8bd51ff5b4cb31e0a2acdec719 Mon Sep 17 00:00:00 2001 From: Ihor Nahnybida <79282749+ihor-jpeg@users.noreply.github.com> Date: Tue, 29 Aug 2023 17:30:30 +0300 Subject: [PATCH 18/25] Update test.yml --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9e72740ba..c2ed2b734 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,7 +1,7 @@ name: Test on: - pull_request_target: + pull_request: branches: - "master" From 3723e54373e5099733a1260717de4ed1e8eeb7c2 Mon Sep 17 00:00:00 2001 From: Vitrikus Yuriy Date: Thu, 1 May 2025 00:01:14 +0300 Subject: [PATCH 19/25] =?UTF-8?q?=D0=94=D0=BE=D0=B4=D0=B0=D1=8E=20Python-?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D1=94=D0=BA=D1=82=D0=B8=20=D0=B4=D0=BE=20pul?= =?UTF-8?q?l=20request?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- py-count-occurrences | 1 + py-linter-formatter | 1 + py-mutable-immutable | 1 + 3 files changed, 3 insertions(+) create mode 160000 py-count-occurrences create mode 160000 py-linter-formatter create mode 160000 py-mutable-immutable diff --git a/py-count-occurrences b/py-count-occurrences new file mode 160000 index 000000000..5c39139b2 --- /dev/null +++ b/py-count-occurrences @@ -0,0 +1 @@ +Subproject commit 5c39139b2cf7e3180fdd9761cb62385be7538fa4 diff --git a/py-linter-formatter b/py-linter-formatter new file mode 160000 index 000000000..cb39fb5a6 --- /dev/null +++ b/py-linter-formatter @@ -0,0 +1 @@ +Subproject commit cb39fb5a60bf5c4ccf5ef8de7ed7b5af9db8bb43 diff --git a/py-mutable-immutable b/py-mutable-immutable new file mode 160000 index 000000000..e67b5ea9f --- /dev/null +++ b/py-mutable-immutable @@ -0,0 +1 @@ +Subproject commit e67b5ea9f5ff235bcb076f2bf73ecc33ffce1813 From 7a7cbdd362a7b7e93ff17074decf05e65c1429ca Mon Sep 17 00:00:00 2001 From: YURIY Date: Sat, 10 May 2025 11:53:31 +0300 Subject: [PATCH 20/25] =?UTF-8?q?=D0=9E=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BA=D0=BE=D0=B4:=20=D0=B2=D0=B8=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BD=D1=8F=20=D1=96=D0=BC=D0=BF?= =?UTF-8?q?=D0=BE=D1=80=D1=82=D1=83=20=D1=82=D0=B0=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=96=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/main.py b/app/main.py index 0dea438cc..b5e0d0f86 100644 --- a/app/main.py +++ b/app/main.py @@ -1,9 +1,9 @@ -class Car: - pass - - class CarWashStation: - pass + def __init__(self, slots, max_cars, water_usage, operating_hours): + self.slots = slots + self.max_cars = max_cars + self.water_usage = water_usage + self.operating_hours = operating_hours lucky_number = 777 pi = 3.14 From 520beed527dd4213f4447eb4aa965b808e1b39bd Mon Sep 17 00:00:00 2001 From: YURIY Date: Sat, 10 May 2025 12:00:56 +0300 Subject: [PATCH 21/25] =?UTF-8?q?=D0=92=D0=B8=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=BD?= =?UTF-8?q?=D1=96=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B8=20=D0=B7=20=D0=B2=D1=96?= =?UTF-8?q?=D0=B4=D1=81=D1=82=D0=B5=D0=B6=D0=B5=D0=BD=D0=BD=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/workflow.yml | 30 ++++++++++++++++++++++++++++++ .gitignore | 3 +++ py-linter-formatter | 2 +- py-mutable-immutable | 2 +- 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/workflow.yml diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml new file mode 100644 index 000000000..4d80e79b3 --- /dev/null +++ b/.github/workflows/workflow.yml @@ -0,0 +1,30 @@ +name: Test + +on: + pull_request: + branches: + - "master" + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Set Up Python 3.10 + uses: actions/setup-python@v2 + with: + python-version: "3.10" + + - name: Install pytest and flake8 + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run flake8 + run: flake8 app/ + - name: Run tests + timeout-minutes: 5 + run: pytest tests/ diff --git a/.gitignore b/.gitignore index a9b868fe1..25df122fb 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ venv/ **__pycache__/ ======= >>>>>>> upstream/master +AppData/ +Cookies/ +Templates/ diff --git a/py-linter-formatter b/py-linter-formatter index cb39fb5a6..232325907 160000 --- a/py-linter-formatter +++ b/py-linter-formatter @@ -1 +1 @@ -Subproject commit cb39fb5a60bf5c4ccf5ef8de7ed7b5af9db8bb43 +Subproject commit 2323259074cec14a564b352ed349a2d68a80bf76 diff --git a/py-mutable-immutable b/py-mutable-immutable index e67b5ea9f..b9a8d03c8 160000 --- a/py-mutable-immutable +++ b/py-mutable-immutable @@ -1 +1 @@ -Subproject commit e67b5ea9f5ff235bcb076f2bf73ecc33ffce1813 +Subproject commit b9a8d03c839bcbed3ce71d2f963b890e1a966d67 From c2329ecf54ba70803463915b473f54fb0cc9b520 Mon Sep 17 00:00:00 2001 From: YURIY Date: Sat, 10 May 2025 12:04:14 +0300 Subject: [PATCH 22/25] =?UTF-8?q?=D0=94=D0=BE=D0=B4=D0=B0=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=B2=D0=B8=D0=BD=D1=8F=D1=82=D0=BA=D0=B8=20=D1=83=20.gitignor?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 25df122fb..384b5e77e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ venv/ AppData/ Cookies/ Templates/ +AppData/ +Local Settings/ +NTUSER.DAT* From aa6766b73cd2dcc264cbb6a49ba4afd76abcb9a2 Mon Sep 17 00:00:00 2001 From: YURIY Date: Sat, 10 May 2025 12:30:12 +0300 Subject: [PATCH 23/25] =?UTF-8?q?=D0=92=D0=B8=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20IndentationError=20=D1=82=D0=B0=20?= =?UTF-8?q?=D0=B2=D0=B8=D1=80=D1=96=D0=B2=D0=BD=D1=8E=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/main.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/main.py b/app/main.py index b5e0d0f86..944118b31 100644 --- a/app/main.py +++ b/app/main.py @@ -1,10 +1,17 @@ class CarWashStation: - def __init__(self, slots, max_cars, water_usage, operating_hours): + def __init__( + self, + slots: int, + max_cars: int, + water_usage: float, + operating_hours: int, + ) -> None: self.slots = slots self.max_cars = max_cars self.water_usage = water_usage self.operating_hours = operating_hours + lucky_number = 777 pi = 3.14 one_is_a_prime_number = False From c6797809d12c17dbc5da5fe6632a04031dc1480f Mon Sep 17 00:00:00 2001 From: YURIY Date: Sat, 10 May 2025 15:03:08 +0300 Subject: [PATCH 24/25] =?UTF-8?q?=D0=92=D0=B8=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20E302=20=D1=82=D0=B0=20E305=20(=D1=84?= =?UTF-8?q?=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D1=83=D0=B2=D0=B0=D0=BD=D0=BD?= =?UTF-8?q?=D1=8F=20=D1=80=D1=8F=D0=B4=D0=BA=D1=96=D0=B2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/main.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/main.py b/app/main.py index 944118b31..ac1c1033f 100644 --- a/app/main.py +++ b/app/main.py @@ -1,3 +1,10 @@ +class Car: + def __init__(self, brand: str, model: str, year: int) -> None: + self.brand = brand + self.model = model + self.year = year + + class CarWashStation: def __init__( self, From bbf7b9d5d7faf546ae3600e8f33fff730c3b68c6 Mon Sep 17 00:00:00 2001 From: YURIY Date: Sun, 11 May 2025 00:51:22 +0300 Subject: [PATCH 25/25] =?UTF-8?q?=D0=92=D0=B8=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20F811,=20E302,=20E305=20=D1=83=20CarW?= =?UTF-8?q?ashStation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/main.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/app/main.py b/app/main.py index ac1c1033f..e61a6f8cc 100644 --- a/app/main.py +++ b/app/main.py @@ -6,17 +6,8 @@ def __init__(self, brand: str, model: str, year: int) -> None: class CarWashStation: - def __init__( - self, - slots: int, - max_cars: int, - water_usage: float, - operating_hours: int, - ) -> None: - self.slots = slots - self.max_cars = max_cars - self.water_usage = water_usage - self.operating_hours = operating_hours + def wash_single_car(self, car: Car) -> float: + return 10.0 lucky_number = 777