Skip to content

Commit 6cee73e

Browse files
committed
Add GitHub Classroom autograding configuration
1 parent 853a8c2 commit 6cee73e

File tree

222 files changed

+3288
-962
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

222 files changed

+3288
-962
lines changed

.github/workflows/labs.yml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
name: Design Patterns Labs
2+
3+
on:
4+
push:
5+
branches: [ main, master, develop ]
6+
pull_request:
7+
branches: [ main, master, develop ]
8+
workflow_dispatch: # Pozwala na ręczne uruchomienie
9+
10+
jobs:
11+
lab-01-intro-hello:
12+
name: "Lab 01 - Intro: Calculator (10 pts)"
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: '3.11'
23+
24+
- name: Install dependencies
25+
run: |
26+
python -m pip install --upgrade pip
27+
pip install -r requirements.txt
28+
29+
- name: Run Lab 01 tests
30+
run: |
31+
cd 0_intro/01_hello
32+
pytest -v --tb=short
33+
continue-on-error: true
34+
35+
lab-02-solid-srp:
36+
name: "Lab 02 - SOLID: SRP (10 pts)"
37+
runs-on: ubuntu-latest
38+
39+
steps:
40+
- name: Checkout code
41+
uses: actions/checkout@v4
42+
43+
- name: Set up Python
44+
uses: actions/setup-python@v5
45+
with:
46+
python-version: '3.11'
47+
48+
- name: Install dependencies
49+
run: |
50+
python -m pip install --upgrade pip
51+
pip install -r requirements.txt
52+
53+
- name: Run Lab 02 tests
54+
run: |
55+
cd 1_principles/01_solid/01_srp
56+
pytest -v --tb=short
57+
continue-on-error: true
58+
59+
lab-03-grasp-expert:
60+
name: "Lab 03 - GRASP: Expert (10 pts)"
61+
runs-on: ubuntu-latest
62+
63+
steps:
64+
- name: Checkout code
65+
uses: actions/checkout@v4
66+
67+
- name: Set up Python
68+
uses: actions/setup-python@v5
69+
with:
70+
python-version: '3.11'
71+
72+
- name: Install dependencies
73+
run: |
74+
python -m pip install --upgrade pip
75+
pip install -r requirements.txt
76+
77+
- name: Run Lab 03 tests
78+
run: |
79+
cd 1_principles/02_grasp/01_information_expert
80+
pytest -v --tb=short
81+
continue-on-error: true
82+
83+
# Summary job - pokazuje ogólny status
84+
summary:
85+
name: "Summary"
86+
runs-on: ubuntu-latest
87+
needs: [lab-01-intro-hello, lab-02-solid-srp, lab-03-grasp-expert]
88+
if: always()
89+
90+
steps:
91+
- name: Check results
92+
run: |
93+
echo "============================================"
94+
echo "Design Patterns Workshop - Test Summary"
95+
echo "============================================"
96+
echo "Lab 01 - Intro Calculator: ${{ needs.lab-01-intro-hello.result }}"
97+
echo "Lab 02 - SOLID SRP: ${{ needs.lab-02-solid-srp.result }}"
98+
echo "Lab 03 - GRASP Expert: ${{ needs.lab-03-grasp-expert.result }}"
99+
echo "============================================"

0_intro/01_hello/starter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def add(a, b):
5151
Returns:
5252
Sum of a and b
5353
"""
54-
pass
54+
return a + b
5555

5656

5757
def multiply(a, b):
@@ -65,4 +65,4 @@ def multiply(a, b):
6565
Returns:
6666
Product of a and b
6767
"""
68-
pass
68+
return a * b

0_intro/01_hello/test_hello.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import pytest
66
from starter import add, multiply
77

8+
pytestmark = pytest.mark.intro_hello
9+
810

911
class TestCalculator:
1012
"""Testy prostego kalkulatora"""
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# 📄 SRP - Report System
2+
3+
**Difficulty**: easy
4+
**Time**: 10 minutes
5+
**Focus**: Single Responsibility Principle
6+
7+
## 🎯 Zadanie
8+
Zaimplementuj `ReportPrinter` - oddziel prezentację od danych.
9+
10+
## 📋 Wymagania
11+
- [ ] `ReportPrinter.print_to_console(report)` - zwraca sformatowany string
12+
- [ ] `ReportPrinter.save_to_file(report, filename)` - zapisuje do pliku
13+
- [ ] Format: `"=== {title} ===\n{lines}"`
14+
15+
## 🚀 Jak zacząć
16+
```bash
17+
cd day0_principles/01_solid/01_srp
18+
19+
# Implementuj ReportPrinter w starter.py
20+
# Uruchom testy
21+
pytest test_srp.py -v
22+
```
23+
24+
## 💡 SRP w pigułce
25+
26+
**Single Responsibility = jeden powód do zmiany**
27+
28+
**Źle** (2 odpowiedzialności):
29+
```python
30+
class Report:
31+
def generate_content(self): ...
32+
def print_to_console(self): ... # Inna odpowiedzialność!
33+
def save_to_file(self): ... # Inna odpowiedzialność!
34+
```
35+
Powody do zmiany: (1) zmiana struktury danych, (2) zmiana formatu prezentacji
36+
37+
**Dobrze** (1 odpowiedzialność każda):
38+
```python
39+
class Report:
40+
def get_title(self): ... # TYLKO dane
41+
42+
class ReportPrinter:
43+
def print_to_console(self, report): ... # TYLKO prezentacja
44+
def save_to_file(self, report, file): ...
45+
```
46+
47+
**Korzyść**: Zmiana formatu prezentacji nie dotyka Report.
48+
49+
Sprawdź `solution_srp.py` po wykonaniu.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Single Responsibility Principle - Report System - SOLUTION
3+
4+
>>> report = Report("Sales Q4", ["Revenue: $100k", "Growth: 15%"])
5+
>>> report.get_title()
6+
'Sales Q4'
7+
>>> len(report.get_lines())
8+
2
9+
10+
>>> printer = ReportPrinter()
11+
>>> output = printer.print_to_console(report)
12+
>>> "Sales Q4" in output
13+
True
14+
>>> "Revenue: $100k" in output
15+
True
16+
17+
>>> import os
18+
>>> printer.save_to_file(report, "test_report.txt")
19+
>>> os.path.exists("test_report.txt")
20+
True
21+
>>> os.remove("test_report.txt")
22+
"""
23+
24+
25+
class Report:
26+
"""Odpowiada TYLKO za przechowywanie danych raportu"""
27+
28+
def __init__(self, title: str, lines: list[str]):
29+
self.title = title
30+
self.lines = lines
31+
32+
def get_title(self) -> str:
33+
return self.title
34+
35+
def get_lines(self) -> list[str]:
36+
return self.lines
37+
38+
39+
class ReportPrinter:
40+
"""Odpowiada TYLKO za prezentację raportu"""
41+
42+
def print_to_console(self, report: Report) -> str:
43+
"""Drukuje raport do konsoli"""
44+
output = f"=== {report.get_title()} ===\n"
45+
for line in report.get_lines():
46+
output += f"{line}\n"
47+
print(output)
48+
return output
49+
50+
def save_to_file(self, report: Report, filename: str) -> None:
51+
"""Zapisuje raport do pliku"""
52+
content = f"=== {report.get_title()} ===\n"
53+
for line in report.get_lines():
54+
content += f"{line}\n"
55+
56+
with open(filename, 'w') as f:
57+
f.write(content)
58+
59+
60+
if __name__ == "__main__":
61+
# Demo
62+
report = Report("Q4 Sales Report", [
63+
"Revenue: $100,000",
64+
"Growth: 15%",
65+
"New customers: 250"
66+
])
67+
68+
printer = ReportPrinter()
69+
printer.print_to_console(report)
70+
printer.save_to_file(report, "sales_report.txt")
71+
print("\nReport saved to sales_report.txt")
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Single Responsibility Principle - Report System
3+
4+
>>> report = Report("Sales Q4", ["Revenue: $100k", "Growth: 15%"])
5+
>>> report.get_title()
6+
'Sales Q4'
7+
>>> len(report.get_lines())
8+
2
9+
10+
>>> # Test ReportPrinter console output
11+
>>> printer = ReportPrinter()
12+
>>> output = printer.print_to_console(report)
13+
>>> "Sales Q4" in output
14+
True
15+
>>> "Revenue: $100k" in output
16+
True
17+
18+
>>> # Test ReportPrinter file save
19+
>>> import os
20+
>>> printer.save_to_file(report, "test_report.txt")
21+
>>> os.path.exists("test_report.txt")
22+
True
23+
>>> os.remove("test_report.txt")
24+
"""
25+
26+
# SRP: Single Responsibility Principle
27+
# Każda klasa powinna mieć tylko jeden powód do zmiany
28+
29+
class Report:
30+
"""Odpowiada TYLKO za przechowywanie danych raportu"""
31+
32+
def __init__(self, title: str, lines: list[str]):
33+
self.title = title
34+
self.lines = lines
35+
36+
def get_title(self) -> str:
37+
return self.title
38+
39+
def get_lines(self) -> list[str]:
40+
return self.lines
41+
42+
43+
# TODO: Zaimplementuj klasę ReportPrinter
44+
# Hint: Odpowiada TYLKO za drukowanie/zapisywanie raportu
45+
# Hint: Przyjmuje Report jako parametr w metodach
46+
47+
class ReportPrinter:
48+
"""Odpowiada TYLKO za prezentację raportu"""
49+
50+
def print_to_console(self, report: Report) -> str:
51+
"""
52+
Drukuje raport do konsoli
53+
54+
Zwraca sformatowany string z tytułem i liniami
55+
Format: "=== {title} ===\n{lines}"
56+
"""
57+
pass
58+
59+
def save_to_file(self, report: Report, filename: str) -> None:
60+
"""
61+
Zapisuje raport do pliku
62+
63+
Format taki sam jak print_to_console
64+
"""
65+
pass
66+
67+
68+
# Dlaczego SRP?
69+
# Report: zmienia się gdy zmienia się STRUKTURA danych
70+
# ReportPrinter: zmienia się gdy zmienia się FORMAT prezentacji
71+
# Dwa różne powody do zmiany = dwie klasy

0 commit comments

Comments
 (0)