├── .gitignore ├── Automated_Emails ├── .idea │ ├── .gitignore │ ├── Automated_Emails.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── design.txt ├── main.py ├── news.py └── people.xlsx ├── Calorie_Webapp ├── .idea │ ├── .gitignore │ ├── Calorie_Webapp.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── calorie.py ├── design.txt ├── main.py ├── static │ └── main.css ├── temperature.py └── templates │ ├── calories_form_page.html │ └── index.html ├── Cinema_Ticket_Booking ├── banking.db ├── cinema.db ├── design.txt └── main.py ├── Flatmates_Bill ├── .idea │ ├── .gitignore │ ├── Flatmates_Bill.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── flatmates_bill │ ├── files │ │ ├── design.txt │ │ └── house.png │ ├── flat.py │ ├── main.py │ └── reports.py ├── main.py ├── static │ ├── bill_form.css │ ├── home.css │ └── results.css └── templates │ ├── bill_form_page.html │ ├── index.html │ └── results.html ├── Geometry_Game ├── .idea │ ├── .gitignore │ ├── Geometry_Game.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── design.txt └── main.py ├── Instant_Dictionary_API ├── .idea │ ├── .gitignore │ ├── Instant_Dictionary_API.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── api.py ├── data.csv ├── definition.py ├── documentation.py └── main.py ├── Instant_Dictionary_Webapp ├── .idea │ ├── .gitignore │ ├── Instant_Dictionary_Webapp.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── data.csv ├── definition.py ├── design │ ├── about.png │ ├── design.txt │ ├── dictionary.png │ └── home.png ├── examples │ ├── file.html │ └── main.py ├── main.py └── webapp │ ├── about.py │ ├── dictionary.py │ ├── home.py │ ├── layout.py │ ├── navbar.py │ └── page.py ├── Math_Painting ├── .idea │ ├── .gitignore │ ├── Math_Painting.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── canvas.py ├── design.txt ├── main.py └── shapes.py ├── Photo_Searcher ├── .idea │ ├── .gitignore │ ├── Photo_Searcher.iml │ ├── inspectionProfiles │ │ └── profiles_settings.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── frontend.kv └── main.py ├── README.md └── Webcam_Photo_Sharer ├── .idea ├── .gitignore ├── Webcam_Photo_Sharer.iml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── design-frontend.png ├── design.txt ├── filesharer.py ├── frontend.kv ├── images ├── down.png └── normal.png └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | __pycache__ 3 | 4 | Flatmates_Bill/files/*.pdf 5 | Flatmates_Bill/flatmates_bill/files/*.pdf 6 | 7 | Math_Painting/*.png 8 | 9 | Photo_Searcher/files/*.png 10 | Photo_Searcher/files/*.jpg 11 | 12 | Webcam_Photo_Sharer/files/*.png -------------------------------------------------------------------------------- /Automated_Emails/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Automated_Emails/.idea/Automated_Emails.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Automated_Emails/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Automated_Emails/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Automated_Emails/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Automated_Emails/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Automated_Emails/design.txt: -------------------------------------------------------------------------------- 1 | Title: Automated Emails 2 | 3 | Description: An app that reads user names, email addresses, and interests 4 | from an Excel file and sends an email to each user with news feeds about the 5 | user's interest every morning. 6 | 7 | Objects: ExcelFile: 8 | file_path 9 | get_data() 10 | Email: 11 | sender 12 | receiver 13 | subject 14 | body 15 | send() 16 | NewsFeed: 17 | data() 18 | get() 19 | -------------------------------------------------------------------------------- /Automated_Emails/main.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import yagmail 4 | import pandas 5 | from news import NewsFeed 6 | import datetime 7 | 8 | 9 | def send_email(): 10 | today = datetime.datetime.now() 11 | news_feed = NewsFeed(interest=row['interest'], 12 | from_date=(today - datetime.timedelta(days=1)).strftime("%Y-%m-%d"), 13 | to_date=today.strftime("%Y-%m-%d")) 14 | email = yagmail.SMTP(user="pythonprocourse1@gmail.com", 15 | password="python_pro_course_1") 16 | email.send(to=row['email'], 17 | subject=f"Your {row['interest']} news for today!", 18 | contents=f"Hi {row['name']},\n See what's on about {row['interest']} today.\n{news_feed.get()}") 19 | 20 | 21 | while True: 22 | if datetime.datetime.now().hour == 17 and datetime.datetime.now().minute == 51: 23 | df = pandas.read_excel("people.xlsx") 24 | 25 | for index, row in df.iterrows(): 26 | send_email() 27 | 28 | time.sleep(60) 29 | -------------------------------------------------------------------------------- /Automated_Emails/news.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | 4 | class NewsFeed: 5 | """Representing multiple news titles and links as a single string 6 | """ 7 | base_url = "https://newsapi.org/v2/everything?" 8 | api_key = "a9c14d7269894d69bc39c744037fa4ca" 9 | 10 | def __init__(self, interest, from_date, to_date, language="en"): 11 | self.language = language 12 | self.to_date = to_date 13 | self.from_date = from_date 14 | self.interest = interest 15 | 16 | def get(self): 17 | url = self._build_url() 18 | 19 | articles = self._get_articles(url) 20 | 21 | email_body = "" 22 | for article in articles: 23 | email_body += article['title'] + "\n" + article['url'] + "\n\n" 24 | 25 | return email_body 26 | 27 | def _get_articles(self, url): 28 | response = requests.get(url) 29 | content = response.json() 30 | articles = content['articles'] 31 | return articles 32 | 33 | def _build_url(self): 34 | url = f"{self.base_url}qInTitle={self.interest}&from={self.from_date}&to={self.to_date}&language={self.language}&apiKey={self.api_key}" 35 | return url 36 | 37 | 38 | if __name__ == "__main__": 39 | news_feed = NewsFeed(interest="nasa", from_date="2023-10-14", to_date="2023-10-15", language="en") 40 | print(news_feed.get()) 41 | -------------------------------------------------------------------------------- /Automated_Emails/people.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Automated_Emails/people.xlsx -------------------------------------------------------------------------------- /Calorie_Webapp/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Calorie_Webapp/.idea/Calorie_Webapp.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Calorie_Webapp/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Calorie_Webapp/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /Calorie_Webapp/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Calorie_Webapp/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Calorie_Webapp/calorie.py: -------------------------------------------------------------------------------- 1 | from temperature import Temperature 2 | 3 | 4 | class Calorie: 5 | """Represent amount of calories calculated with 6 | BMR = 10*weight + 6.25*height - 5*age - 10*temperature 7 | """ 8 | 9 | def __init__(self, weight, height, age, temperature): 10 | self.temperature = temperature 11 | self.age = age 12 | self.height = height 13 | self.weight = weight 14 | 15 | def calculate(self): 16 | result = 10 * self.weight + 6.5 * self.height + 5*self.age - self.temperature * 10 17 | return result 18 | 19 | 20 | if __name__ == "__main__": 21 | temperature = Temperature(city='rome', country='italy').get() 22 | calorie = Calorie(temperature=temperature, weight=70, height=175, age=32) 23 | print(calorie.calculate()) 24 | -------------------------------------------------------------------------------- /Calorie_Webapp/design.txt: -------------------------------------------------------------------------------- 1 | Title: Calorie Calculator 2 | 3 | Description: An app that gets from the user's weight, height, 4 | age, city and country, and scrapes the temperature of the user's location, 5 | and calculates how many calories the user needs. 6 | 7 | Objects: Calorie: 8 | weight 9 | height 10 | age 11 | temperature 12 | calculate() 13 | Temperature: 14 | country 15 | city 16 | get() -------------------------------------------------------------------------------- /Calorie_Webapp/main.py: -------------------------------------------------------------------------------- 1 | from flask.views import MethodView 2 | from wtforms import Form, StringField, SubmitField 3 | from flask import Flask, render_template, request 4 | from calorie import Calorie 5 | from temperature import Temperature 6 | 7 | app = Flask(__name__) 8 | 9 | 10 | class HomePage(MethodView): 11 | 12 | def get(self): 13 | return render_template('index.html') 14 | 15 | 16 | class CaloriesFormPage(MethodView): 17 | 18 | def get(self): 19 | calories_form = CaloriesForm() 20 | 21 | return render_template('calories_form_page.html', 22 | calories_form=calories_form) 23 | 24 | def post(self): 25 | calories_form = CaloriesForm(request.form) 26 | 27 | temperature = Temperature(country=calories_form.country.data, 28 | city=calories_form.city.data).get() 29 | 30 | calorie = Calorie(weight=float(calories_form.weight.data), 31 | height=float(calories_form.height.data), 32 | age=float(calories_form.age.data), 33 | temperature=temperature) 34 | 35 | calories = calorie.calculate() 36 | 37 | return render_template('calories_form_page.html', 38 | calories_form=calories_form, 39 | calories=calories, 40 | result=True) 41 | 42 | 43 | class CaloriesForm(Form): 44 | weight = StringField("Weight: ", default=70) 45 | height = StringField("Height: ", default=175) 46 | age = StringField("Age: ", default=32) 47 | country = StringField("Country: ", default="USA") 48 | city = StringField("City: ", default="San Francisco") 49 | button = SubmitField("Calculate") 50 | 51 | 52 | app.add_url_rule('/', view_func=HomePage.as_view("home_page")) 53 | app.add_url_rule('/calories_form', view_func=CaloriesFormPage.as_view("calories_form_page")) 54 | 55 | app.run(debug=True) 56 | -------------------------------------------------------------------------------- /Calorie_Webapp/static/main.css: -------------------------------------------------------------------------------- 1 | h2{ 2 | color: darkgrey; 3 | text-align: center; 4 | font-size: 50px; 5 | } 6 | 7 | input[type=text] { 8 | width: 100%; 9 | padding: 8px 8px; 10 | margin: 10px 0; 11 | } 12 | 13 | input[type=submit], a{ 14 | width: 100%; 15 | background-color: YellowGreen; 16 | color: white; 17 | padding: 12px 12px; 18 | border: none; 19 | border-radius: 6px; 20 | cursor: pointer; 21 | text-decoration: none; 22 | } 23 | 24 | body{ 25 | background-color: black; 26 | color: white; 27 | padding: 20px; 28 | } -------------------------------------------------------------------------------- /Calorie_Webapp/temperature.py: -------------------------------------------------------------------------------- 1 | class Temperature: 2 | """ 3 | Represents a temperature value extracted from the timeanddate.com/weather webpage. 4 | """ 5 | 6 | def __init__(self, country, city): 7 | self.city = city 8 | self.country = country 9 | 10 | def get(self): 11 | # code for web scraping 12 | 13 | return float(18) 14 | 15 | 16 | if __name__ == "__main__": 17 | temperature = Temperature(country='usa', city='san francisco') 18 | print(temperature.get()) 19 | -------------------------------------------------------------------------------- /Calorie_Webapp/templates/calories_form_page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 |

Calories Calculation Form

10 |

Fill in the form and click the button to know how many calories you need!

11 | 12 |
13 |

Let's get some info about you first.

14 | {{calories_form.weight.label}} {{calories_form.weight}} 15 |
16 | {{calories_form.height.label}} {{calories_form.height}} 17 |
18 | {{calories_form.age.label}} {{calories_form.age}} 19 |
20 |
21 |

Today's weather counts too.
Tell us where you are, so we include today's temperature into the calculation

22 | {{calories_form.city.label}} {{calories_form.city}} 23 |
24 | {{calories_form.country.label}} {{calories_form.country}} 25 |
26 | 27 |
28 | {{calories_form.button}} 29 |
30 | {% if result == True %} 31 |

You need {{calories}} calories (kcal) today

32 | {% endif %} 33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /Calorie_Webapp/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 |

Calories Calculation

10 |

This web app is useful to calculate how many calories you should take today.

11 | Go to calculation page 12 | 13 | 14 | -------------------------------------------------------------------------------- /Cinema_Ticket_Booking/banking.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Cinema_Ticket_Booking/banking.db -------------------------------------------------------------------------------- /Cinema_Ticket_Booking/cinema.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Cinema_Ticket_Booking/cinema.db -------------------------------------------------------------------------------- /Cinema_Ticket_Booking/design.txt: -------------------------------------------------------------------------------- 1 | Title: Cinema Ticket Booking 2 | 3 | Description: An app where a user can book a cinema seat 4 | if the seat is free and if the user has balance in their card. 5 | The app generates a pdf ticket if the purchase is successful. 6 | 7 | Objects: User, Seat, Card, Ticket 8 | User: 9 | name 10 | buy(seat, card) 11 | Seat: 12 | database 13 | seat_id 14 | price 15 | availability 16 | is_free() 17 | occupy() 18 | Card: 19 | database 20 | type 21 | number 22 | cvc 23 | holder 24 | validate(price) 25 | Ticket: 26 | id 27 | user 28 | price 29 | seat 30 | to_pdf(path) -------------------------------------------------------------------------------- /Cinema_Ticket_Booking/main.py: -------------------------------------------------------------------------------- 1 | from fpdf import FPDF 2 | import random 3 | import string 4 | import sqlite3 5 | 6 | 7 | class User: 8 | """Represents a user that can buy a cinema Seat""" 9 | 10 | def __init__(self, name): 11 | self.name = name 12 | 13 | def buy(self, seat, card): 14 | """Buys the ticket if the card is valid""" 15 | if seat.is_free(): 16 | if card.validate(price=seat.get_price()): 17 | seat.occupy() 18 | ticket = Ticket(user=self, price=seat.get_price(), seat_number=seat.seat_id) 19 | ticket.to_pdf() 20 | return "Purchase Successful!" 21 | else: 22 | return "There was a problem with your card!" 23 | else: 24 | return "Seat is taken!" 25 | 26 | 27 | class Seat: 28 | """Represents a cinema seat that can be taken from a User""" 29 | 30 | database = 'cinema.db' 31 | 32 | def __init__(self, seat_id): 33 | self.seat_id = seat_id 34 | 35 | def get_price(self): 36 | """Get the price of the certain seat""" 37 | connection = sqlite3.connect(self.database) 38 | cursor = connection.cursor() 39 | cursor.execute(""" 40 | SELECT "price" FROM "Seat" WHERE "seat_id" = ? 41 | """, [self.seat_id]) 42 | price = cursor.fetchall()[0][0] 43 | 44 | return price 45 | 46 | def is_free(self): 47 | """Check in the database if a seat is taken or not""" 48 | connection = sqlite3.connect(self.database) 49 | cursor = connection.cursor() 50 | cursor.execute(""" 51 | SELECT "taken" FROM "Seat" WHERE "seat_id" = ? 52 | """, [self.seat_id]) 53 | result = cursor.fetchall()[0][0] 54 | 55 | if result == 0: 56 | return True 57 | else: 58 | return False 59 | 60 | def occupy(self): 61 | """Change value of taken in the database from 0 to 1 if seat is free""" 62 | if self.is_free(): 63 | connection = sqlite3.connect(self.database) 64 | connection.execute(""" 65 | UPDATE "Seat" SET "taken"=? WHERE "seat_id"=? 66 | """, [1, self.seat_id]) 67 | connection.commit() 68 | connection.close() 69 | 70 | 71 | class Card: 72 | """Represents a bank card needed to finalize a seat purchase""" 73 | 74 | database = 'banking.db' 75 | 76 | def __init__(self, type, number, cvc, holder): 77 | self.holder = holder 78 | self.cvc = cvc 79 | self.number = number 80 | self.type = type 81 | 82 | def validate(self, price): 83 | """Checks if card is valid and has balance. 84 | Subtracts price from balance. 85 | """ 86 | connection = sqlite3.connect(self.database) 87 | cursor = connection.cursor() 88 | cursor.execute(""" 89 | SELECT "balance" FROM "Card" WHERE "number"=? and "cvc"=? 90 | """, [self.number, self.cvc]) 91 | result = cursor.fetchall() 92 | 93 | if result: 94 | balance = result[0][0] 95 | if balance >= price: 96 | connection.execute(""" 97 | UPDATE "Card" SET "balance"=? WHERE "number"=? and "cvc"=? 98 | """, [balance - price, self.number, self.cvc]) 99 | connection.commit() 100 | connection.close() 101 | return True 102 | 103 | 104 | class Ticket: 105 | """Represents a cinema Ticket purchased by a user""" 106 | 107 | def __init__(self, user, price, seat_number): 108 | self.seat_number = seat_number 109 | self.price = price 110 | self.id = "".join([random.choice(string.ascii_letters) for i in range(8)]) 111 | self.user = user 112 | 113 | def to_pdf(self): 114 | """Creates a pdf ticket""" 115 | pdf = FPDF(orientation="P", unit='pt', format='A4') 116 | pdf.add_page() 117 | 118 | pdf.set_font(family="Times", style="B", size=24) 119 | pdf.cell(w=0, h=80, txt="Your Digital Ticket", border=1, ln=1, align="C") 120 | 121 | pdf.set_font(family="Times", style="B", size=14) 122 | pdf.cell(w=100, h=25, txt="Name: ", border=1) 123 | pdf.set_font(family="Times", style="B", size=12) 124 | pdf.cell(w=0, h=25, txt=self.user.name, border=1, ln=1) 125 | pdf.cell(w=0, h=5, txt="", border=0, ln=1) 126 | 127 | pdf.set_font(family="Times", style="B", size=14) 128 | pdf.cell(w=100, h=25, txt="Ticket ID: ", border=1) 129 | pdf.set_font(family="Times", style="B", size=12) 130 | pdf.cell(w=0, h=25, txt=self.id, border=1, ln=1) 131 | pdf.cell(w=0, h=5, txt="", border=0, ln=1) 132 | 133 | pdf.set_font(family="Times", style="B", size=14) 134 | pdf.cell(w=100, h=25, txt="Price: ", border=1) 135 | pdf.set_font(family="Times", style="B", size=12) 136 | pdf.cell(w=0, h=25, txt=str(self.price), border=1, ln=1) 137 | pdf.cell(w=0, h=5, txt="", border=0, ln=1) 138 | 139 | pdf.set_font(family="Times", style="B", size=14) 140 | pdf.cell(w=100, h=25, txt="Seat No: ", border=1) 141 | pdf.set_font(family="Times", style="B", size=12) 142 | pdf.cell(w=0, h=25, txt=str(self.seat_number), border=1, ln=1) 143 | pdf.cell(w=0, h=5, txt="", border=0, ln=1) 144 | 145 | pdf.output("sample.pdf") 146 | 147 | 148 | if __name__ == "__main__": 149 | name = input("Your full name: ") 150 | seat_id = input("Preferred seat no: ") 151 | card_type = input("Your card type: ") 152 | card_number = input("Your card number: ") 153 | card_cvc = input("Your card cvc: ") 154 | card_holder = input("Card holder name: ") 155 | 156 | user = User(name=name) 157 | seat = Seat(seat_id=seat_id) 158 | card = Card(type=card_type, number=card_number, cvc=card_cvc, holder=card_holder) 159 | 160 | print(user.buy(seat=seat, card=card)) 161 | -------------------------------------------------------------------------------- /Flatmates_Bill/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Flatmates_Bill/.idea/Flatmates_Bill.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Flatmates_Bill/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Flatmates_Bill/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /Flatmates_Bill/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Flatmates_Bill/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Flatmates_Bill/flatmates_bill/files/design.txt: -------------------------------------------------------------------------------- 1 | Title: Flatmates Bill 2 | 3 | Description: An app that gets as input the amount of a bill for a particular 4 | period and the days that each of the flatmates stayed in the house for that 5 | period and returns how much each flatmate has to pay. It also generates a 6 | PDF report stating the names of the flatmates, the period and how much each 7 | of them had to pay. 8 | 9 | Objects: Bill: 10 | amount 11 | period 12 | Flatmate: 13 | name 14 | days_in_house 15 | pays(bill) 16 | PdfReport: 17 | filename 18 | generate(flatmate1, flatmate2, bill) -------------------------------------------------------------------------------- /Flatmates_Bill/flatmates_bill/files/house.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Flatmates_Bill/flatmates_bill/files/house.png -------------------------------------------------------------------------------- /Flatmates_Bill/flatmates_bill/flat.py: -------------------------------------------------------------------------------- 1 | class Bill: 2 | """ 3 | Object that contains data about a bill, such as 4 | total amount and period of the bill. 5 | """ 6 | 7 | def __init__(self, amount, period): 8 | self.amount = amount 9 | self.period = period 10 | 11 | 12 | class Flatmate: 13 | """ 14 | Creates a flatmate person who lives in the flat 15 | and pays a share of the bill. 16 | """ 17 | 18 | def __init__(self, name, days_in_house): 19 | self.name = name 20 | self.days_in_house = days_in_house 21 | 22 | def pays(self, bill, flatmate2): 23 | weight = self.days_in_house / (self.days_in_house + flatmate2.days_in_house) 24 | to_pay = bill.amount * weight 25 | return to_pay 26 | -------------------------------------------------------------------------------- /Flatmates_Bill/flatmates_bill/main.py: -------------------------------------------------------------------------------- 1 | from flat import Bill, Flatmate 2 | from reports import PdfReport, FileSharer 3 | 4 | amount = float(input("Hey user, enter the bill amount: ")) 5 | period = input("What is the bill period? E.g. December 2020: ") 6 | 7 | name1 = input("What is your name? ") 8 | days_in_house1 = int(input("How many days did {} stay in the house during the bill period? ".format(name1))) 9 | 10 | name2 = input("What is the name of other flatmate? ") 11 | days_in_house2 = int(input("How many days did {} stay in the house during the bill period? ".format(name2))) 12 | 13 | the_bill = Bill(amount, period) 14 | flatmate1 = Flatmate(name1, days_in_house1) 15 | flatmate2 = Flatmate(name2, days_in_house2) 16 | 17 | print(f"{flatmate1.name} pays: ", flatmate1.pays(the_bill, flatmate2)) 18 | print(f"{flatmate2.name} pays: ", flatmate2.pays(the_bill, flatmate1)) 19 | 20 | pdf_report = PdfReport(filename=f'{the_bill.period}.pdf') 21 | pdf_report.generate(flatmate1, flatmate2, the_bill) 22 | 23 | file_sharer = FileSharer(filepath=pdf_report.filename) 24 | print(file_sharer.share()) -------------------------------------------------------------------------------- /Flatmates_Bill/flatmates_bill/reports.py: -------------------------------------------------------------------------------- 1 | import webbrowser 2 | import os 3 | 4 | from fpdf import FPDF 5 | from filestack import Client 6 | 7 | 8 | class PdfReport: 9 | """ 10 | Creates a pdf file that contains data about 11 | the flatmates such as their names, their due 12 | amounts and the period of the bill. 13 | """ 14 | 15 | def __init__(self, filename): 16 | self.filename = filename 17 | 18 | def generate(self, flatmate1, flatmate2, bill): 19 | flatmate1_pay = str(round(flatmate1.pays(bill, flatmate2), 2)) 20 | flatmate2_pay = str(round(flatmate2.pays(bill, flatmate1), 2)) 21 | 22 | pdf = FPDF(orientation='P', unit='pt', format='A4') 23 | pdf.add_page() 24 | 25 | # Add icon 26 | pdf.image("files/house.png", w=30, h=30) 27 | 28 | # Insert title 29 | pdf.set_font(family='Times', size=24, style='B') 30 | pdf.cell(w=0, h=80, txt='Flatmates Bill', border=0, align='C', ln=1) 31 | 32 | # Insert Period label and value 33 | pdf.set_font(family='Times', size=14, style='B') 34 | pdf.cell(w=100, h=40, txt='Period:', border=0) 35 | pdf.cell(w=150, h=40, txt=bill.period, border=0, ln=1) 36 | 37 | # Insert name and due amount of the first flatmate 38 | pdf.set_font(family='Times', size=12) 39 | pdf.cell(w=100, h=25, txt=flatmate1.name, border=0) 40 | pdf.cell(w=150, h=25, txt=flatmate1_pay, border=0, ln=1) 41 | 42 | # Insert name and due amount of the second flatmate 43 | pdf.cell(w=100, h=25, txt=flatmate2.name, border=0) 44 | pdf.cell(w=150, h=25, txt=flatmate2_pay, border=0, ln=1) 45 | 46 | # Change directory to files, generates and opens the pdf 47 | os.chdir('files') 48 | pdf.output(self.filename) 49 | webbrowser.open(self.filename) 50 | 51 | 52 | class FileSharer: 53 | """ 54 | Uploads the generated pdf to online and gives the link 55 | to access the pdf. 56 | """ 57 | 58 | def __init__(self, filepath, api_key='Aj799wiBlScSabXEs3WqDz'): 59 | self.filepath = filepath 60 | self.api_key = api_key 61 | 62 | def share(self): 63 | client = Client(self.api_key) 64 | new_filelink = client.upload(filepath=self.filepath) 65 | return new_filelink.url 66 | -------------------------------------------------------------------------------- /Flatmates_Bill/main.py: -------------------------------------------------------------------------------- 1 | from flask.views import MethodView 2 | from wtforms import Form, StringField, SubmitField 3 | from flask import Flask, render_template, request 4 | 5 | from flatmates_bill import flat 6 | 7 | app = Flask(__name__) 8 | 9 | 10 | class HomePage(MethodView): 11 | 12 | def get(self): 13 | return render_template('index.html') 14 | 15 | 16 | class BillFormPage(MethodView): 17 | 18 | def get(self): 19 | bill_form = BillForm() 20 | return render_template('bill_form_page.html', bill_form=bill_form) 21 | 22 | 23 | class ResultsPage(MethodView): 24 | 25 | def post(self): 26 | bill_form = BillForm(request.form) 27 | 28 | the_bill = flat.Bill(float(bill_form.amount.data), bill_form.period.data) 29 | flatmate1 = flat.Flatmate(bill_form.name1.data, float(bill_form.days_in_house1.data)) 30 | flatmate2 = flat.Flatmate(bill_form.name2.data, float(bill_form.days_in_house2.data)) 31 | 32 | return render_template("results.html", 33 | name1=flatmate1.name, 34 | amount1=flatmate1.pays(the_bill, flatmate2), 35 | name2=flatmate2.name, 36 | amount2=flatmate2.pays(the_bill, flatmate1)) 37 | 38 | 39 | class BillForm(Form): 40 | amount = StringField("Bill Amount: ", default=100) 41 | period = StringField("Bill Period: ", default="December 2020") 42 | 43 | name1 = StringField("Name: ", default="John") 44 | days_in_house1 = StringField("Days in the house: ", default=20) 45 | 46 | name2 = StringField("Name: ", default="Marry") 47 | days_in_house2 = StringField("Days in the house: ", default=12) 48 | 49 | button = SubmitField("Calculate") 50 | 51 | 52 | app.add_url_rule('/', view_func=HomePage.as_view('home_page')) 53 | app.add_url_rule('/bill', view_func=BillFormPage.as_view('bill_form_page')) 54 | app.add_url_rule('/results', view_func=ResultsPage.as_view('result_page')) 55 | 56 | app.run(debug=True) 57 | -------------------------------------------------------------------------------- /Flatmates_Bill/static/bill_form.css: -------------------------------------------------------------------------------- 1 | h2{ 2 | color: darkgrey; 3 | text-align: center; 4 | font-size: 50px; 5 | } 6 | 7 | input[type=text]{ 8 | width: 100%; 9 | padding: 8px 8px; 10 | margin: 10px 0; 11 | } 12 | 13 | input[type=submit]{ 14 | width: 100%; 15 | background-color: YellowGreen; 16 | color: white; 17 | padding: 12px 12px; 18 | border: none; 19 | border-radius: 6px; 20 | cursor: pointer; 21 | } 22 | 23 | body{ 24 | background-color: GhostWhite; 25 | padding: 20px; 26 | } -------------------------------------------------------------------------------- /Flatmates_Bill/static/home.css: -------------------------------------------------------------------------------- 1 | h2{ 2 | color: darkgrey; 3 | text-align: center; 4 | font-size: 50px; 5 | } 6 | 7 | body{ 8 | background-color: GhostWhite; 9 | padding: 20px; 10 | } 11 | 12 | body a{ 13 | width: 100%; 14 | background-color: YellowGreen; 15 | color: white; 16 | padding: 12px 12px; 17 | border: none; 18 | border-radius: 6px; 19 | text-decoration: none; 20 | } -------------------------------------------------------------------------------- /Flatmates_Bill/static/results.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background-color: GhostWhite; 3 | padding: 20px; 4 | } -------------------------------------------------------------------------------- /Flatmates_Bill/templates/bill_form_page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 |

The Bill Form

10 |

Fill in the form and click the button to get the results

11 |
12 | {{bill_form.amount.label}} {{bill_form.amount}} 13 |
14 | {{bill_form.period.label}} {{bill_form.period}} 15 |
16 | 17 |

First Flatmate

18 | {{bill_form.name1.label}} {{bill_form.name1}}
19 | {{bill_form.days_in_house1.label}} {{bill_form.days_in_house1}} 20 |
21 | 22 |

Second Flatmate

23 | {{bill_form.name2.label}} {{bill_form.name2}}
24 | {{bill_form.days_in_house2.label}} {{bill_form.days_in_house2}} 25 | 26 |
27 | 28 | {{bill_form.button}} 29 |
30 | 31 | -------------------------------------------------------------------------------- /Flatmates_Bill/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 |

Flatmates bill

10 |

This web app is useful to split a bill between two flatmates.

11 | Go to the bill page 12 | 13 | -------------------------------------------------------------------------------- /Flatmates_Bill/templates/results.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | {{name1}} pays: {{amount1}}
10 | {{name2}} pays: {{amount2}} 11 | 12 | 13 | -------------------------------------------------------------------------------- /Geometry_Game/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Geometry_Game/.idea/Geometry_Game.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Geometry_Game/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Geometry_Game/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Geometry_Game/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Geometry_Game/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Geometry_Game/design.txt: -------------------------------------------------------------------------------- 1 | Title: Geometry Game 2 | 3 | Description: An app that generates a rectangle with random coordinates and asks user to guess any random 4 | point (x and y) and to guess the area of rectangle and tells how off the actual area of rectangle by our guess 5 | and also draw the rectangle and point in GUI. 6 | 7 | Objects: Point: 8 | x 9 | y 10 | falls_in_rectangle(Rectangle) 11 | Rectangle: 12 | point1 13 | point2 14 | area() 15 | GuiRectangle(Rectangle): 16 | draw(canvas) 17 | GuiPoint(Rectangle): 18 | draw(canvas) -------------------------------------------------------------------------------- /Geometry_Game/main.py: -------------------------------------------------------------------------------- 1 | from random import randint 2 | import turtle 3 | 4 | 5 | class Point: 6 | """ 7 | Class that contain x and y coordinates of a point and tells 8 | the point falls in given rectangle or not. 9 | """ 10 | 11 | def __init__(self, x, y): 12 | self.x = x 13 | self.y = y 14 | 15 | def falls_in_rectangle(self, rectangle_area): 16 | return rectangle_area.point1.x < self.x < rectangle_area.point2.x \ 17 | and rectangle_area.point1.y < self.y < rectangle_area.point2.y 18 | 19 | 20 | class Rectangle: 21 | """ 22 | Class that contains lower left point (point1) and upper right 23 | (point2) of a rectangle and returns the area of rectangle. 24 | """ 25 | 26 | def __init__(self, point1, point2): 27 | self.point1 = point1 28 | self.point2 = point2 29 | 30 | def area(self): 31 | return (self.point2.x - self.point1.x) * \ 32 | (self.point2.y - self.point1.y) 33 | 34 | 35 | class GuiRectangle(Rectangle): 36 | """ 37 | Child of Rectangle class for a GUI representation of rectangle. 38 | """ 39 | def draw(self, canvas): 40 | canvas.penup() 41 | canvas.goto(self.point1.x, self.point1.y) 42 | 43 | canvas.pendown() 44 | canvas.forward(self.point2.x - self.point1.x) 45 | canvas.left(90) 46 | canvas.forward(self.point2.y - self.point1.y) 47 | canvas.left(90) 48 | canvas.forward(self.point2.x - self.point1.x) 49 | canvas.left(90) 50 | canvas.forward(self.point2.y - self.point1.y) 51 | 52 | 53 | class GuiPoint(Point): 54 | """Child of Point class for GUI representation of point""" 55 | 56 | def draw(self, canvas, size=5, color='red'): 57 | canvas.penup() 58 | canvas.goto(self.x, self.y) 59 | 60 | canvas.pendown() 61 | canvas.dot(size, color) 62 | 63 | turtle.done() 64 | 65 | 66 | # Create rectangle object 67 | rectangle = GuiRectangle(Point(randint(0, 200), randint(0, 200)), 68 | Point(randint(10, 200), randint(10, 200))) 69 | 70 | # Print rectangle coordinates 71 | print("Rectangle Coordinates: ", 72 | rectangle.point1.x, ",", 73 | rectangle.point1.y, "and", 74 | rectangle.point2.x, ",", 75 | rectangle.point2.y) 76 | 77 | # Get point and area from user 78 | user_point = GuiPoint(float(input("Guess x: ")), float(input("Guess y: "))) 79 | user_area = float(input("Guess rectangle area: ")) 80 | 81 | # Print out the game result 82 | print("Your point was inside rectangle: ", user_point.falls_in_rectangle(rectangle)) 83 | print("Your area was off by: ", rectangle.area() - user_area) 84 | 85 | myturtle = turtle.Turtle() 86 | rectangle.draw(myturtle) 87 | user_point.draw(myturtle) 88 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/.idea/Instant_Dictionary_API.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/api.py: -------------------------------------------------------------------------------- 1 | import justpy as jp 2 | import definition 3 | import json 4 | 5 | 6 | class Api: 7 | """Handle requests at /api?w=word 8 | """ 9 | 10 | @classmethod 11 | def serve(cls, req): 12 | wp = jp.WebPage() 13 | word = req.query_params.get('w') 14 | 15 | defined = definition.Definition(word).get() 16 | response = { 17 | "word": word, 18 | "definition": defined 19 | } 20 | 21 | wp.html = json.dumps(response) 22 | return wp 23 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/definition.py: -------------------------------------------------------------------------------- 1 | import pandas 2 | 3 | 4 | class Definition: 5 | 6 | def __init__(self, term): 7 | self.term = term 8 | 9 | def get(self): 10 | df = pandas.read_csv("data.csv") 11 | return tuple(df.loc[df['word'] == self.term]['definition']) 12 | 13 | 14 | if __name__ == "__main__": 15 | d = Definition(term='sun') 16 | print(d.get()) 17 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/documentation.py: -------------------------------------------------------------------------------- 1 | import justpy as jp 2 | 3 | 4 | class Doc: 5 | 6 | def serve(self): 7 | wp = jp.WebPage() 8 | 9 | div = jp.Div(a=wp, text="Instant Dictionary API", classes="bg-gray-200 h-screen") 10 | jp.Div(a=div, text="This is about page!", 11 | classes="text-4xl m-2") 12 | jp.Div(a=div, text='Get definitions of words', classes="text-lg") 13 | jp.Hr(a=div) 14 | jp.Div(a=div, text="www.example.com/api?w=moon") 15 | jp.Hr(a=div) 16 | jp.Div(a=div, text=""" 17 | {"word": "moon", "definition": ["A natural satellite of a planet.", "A month, particularly a lunar month (approximately 28 days).", "To fuss over adoringly or with great affection.", "Deliberately show ones bare ass (usually to an audience, or at a place, where this is not expected or deemed appropriate).", "To be lost in phantasies or be carried away by some internal vision, having temorarily lost (part of) contact to reality."]} 18 | """) 19 | 20 | return wp 21 | -------------------------------------------------------------------------------- /Instant_Dictionary_API/main.py: -------------------------------------------------------------------------------- 1 | import api 2 | import documentation 3 | 4 | import justpy as jp 5 | 6 | jp.Route("/api", api.Api.serve) 7 | jp.Route("/", documentation.Doc.serve) 8 | jp.justpy() 9 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/.idea/Instant_Dictionary_Webapp.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/definition.py: -------------------------------------------------------------------------------- 1 | import pandas 2 | 3 | 4 | class Definition: 5 | 6 | def __init__(self, term): 7 | self.term = term 8 | 9 | def get(self): 10 | df = pandas.read_csv("data.csv") 11 | return tuple(df.loc[df['word'] == self.term]['definition']) 12 | 13 | 14 | if __name__ == "__main__": 15 | d = Definition(term='sun') 16 | print(d.get()) 17 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/design/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Instant_Dictionary_Webapp/design/about.png -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/design/design.txt: -------------------------------------------------------------------------------- 1 | Title: Instant Dictionary Web App 2 | Description: A web app that lets users type in a term in a text box and returns the English definition 3 | of that term instantly as soon as the user has finished typing. 4 | The web app consists of a website with a navigation menu, a Home, Dictionary, and About page. 5 | Objects: Definition: 6 | term 7 | get() 8 | Navbar 9 | HomePage 10 | DictionaryPage 11 | AboutPage -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/design/dictionary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Instant_Dictionary_Webapp/design/dictionary.png -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/design/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Instant_Dictionary_Webapp/design/home.png -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/examples/file.html: -------------------------------------------------------------------------------- 1 | 27 | 28 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/examples/main.py: -------------------------------------------------------------------------------- 1 | import justpy as jp 2 | 3 | 4 | @jp.SetRoute("/") 5 | def home(): 6 | wp = jp.QuasarPage(tailwind=True) 7 | div = jp.Div(a=wp, classes="bg-gray-200 h-screen") 8 | div1 = jp.Div(a=div, classes="grid grid-cols-3 gap-4 p-4") 9 | in_1 = jp.Input(a=div1, placeholder="Enter first value", 10 | classes="form-input") 11 | in_2 = jp.Input(a=div1, placeholder="Enter second value", 12 | classes="form-input") 13 | d_output = jp.Div(a=div1, text="Result goes here...", 14 | classes="text-gray-600") 15 | jp.Div(a=div1, text="Another div...", 16 | classes="text-gray-600") 17 | jp.Div(a=div1, text="Yet another div...", 18 | classes="text-gray-600") 19 | 20 | div2 = jp.Div(a=div, classes="grid grid-cols-2 gap-4") 21 | jp.Button(a=div2, text="Calculate", click=sum_up, in_1=in_1, in_2=in_2, 22 | d=d_output, 23 | classes="border border-blue-500 m-2 py-1 px-4 rounded " 24 | "text-blue-600 hover:bg-red-500 hover:text-white") 25 | jp.Div(a=div2, text="Im a cool interactive div!", mouseenter=mouse_enter) 26 | return wp 27 | 28 | 29 | def sum_up(widget, msg): 30 | sum = float(widget.in_1.value) + float(widget.in_2.value) 31 | widget.d.text = sum 32 | 33 | 34 | def mouse_enter(widget, msg): 35 | widget.text = "Mouse entered" 36 | 37 | 38 | # jp.Route("/", home) 39 | 40 | jp.justpy() 41 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/main.py: -------------------------------------------------------------------------------- 1 | import justpy as jp 2 | 3 | from webapp.home import Home 4 | from webapp.about import About 5 | from webapp.dictionary import Dictionary 6 | 7 | jp.Route(Home.path, Home.serve) 8 | jp.Route(About.path, About.serve) 9 | jp.Route(Dictionary.path, Dictionary.serve) 10 | 11 | jp.justpy(port=8001) 12 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/webapp/about.py: -------------------------------------------------------------------------------- 1 | import justpy as jp 2 | 3 | from webapp import layout 4 | 5 | 6 | class About: 7 | path = "/about" 8 | 9 | def serve(self): 10 | wp = jp.QuasarPage(tailwind=True) 11 | 12 | lay = layout.DefaultLayout(a=wp) 13 | container = jp.QPageContainer(a=lay) 14 | 15 | div = jp.Div(a=container, classes="bg-gray-200 h-screen") 16 | jp.Div(a=div, text="This is about page!", 17 | classes="text-4xl m-2") 18 | jp.Div(a=div, text=""" 19 | long text 20 | """, classes="text-lg") 21 | 22 | return wp 23 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/webapp/dictionary.py: -------------------------------------------------------------------------------- 1 | import justpy as jp 2 | import definition 3 | 4 | from webapp import layout 5 | 6 | import requests 7 | 8 | 9 | class Dictionary: 10 | path = "/dictionary" 11 | 12 | @classmethod 13 | def serve(cls, req): 14 | wp = jp.QuasarPage(tailwind=True) 15 | 16 | lay = layout.DefaultLayout(a=wp) 17 | container = jp.QPageContainer(a=lay) 18 | 19 | div = jp.Div(a=container, classes="bg-gray-200 h-screen") 20 | jp.Div(a=div, text="Instant English Dictionary!", classes="text-4xl m-2") 21 | jp.Div(a=div, text="Get the definition of any English word instantly as you type.", 22 | classes="text-lg") 23 | 24 | input_div = jp.Div(a=div, classes="grid grid-cols-2") 25 | output_div = jp.Div(a=div, classes="m-2 p-2 text-lg border-2 h-40") 26 | 27 | input_box = jp.Input(a=input_div, placeholder="Type in a word here...", output_div=output_div, 28 | classes="m-2 bg-gray-100 border-2 border-gray-200 rounded w-64 " 29 | "focus:bg-white focus:outline-none focus:border-purple-500 py-2 px-4") 30 | input_box.on('input', cls.get_definition) 31 | 32 | return wp 33 | 34 | @staticmethod 35 | def get_definition(widget, msg): 36 | req = requests.get(f"http://127.0.0.1:8000/api?w={widget.value}") 37 | data = req.json() 38 | widget.output_div.text = " ".join(data['definition']) 39 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/webapp/home.py: -------------------------------------------------------------------------------- 1 | import justpy as jp 2 | from webapp import layout 3 | 4 | 5 | class Home: 6 | path = "/" 7 | 8 | @classmethod 9 | def serve(cls, req): 10 | wp = jp.QuasarPage(tailwind=True) 11 | 12 | lay = layout.DefaultLayout(a=wp) 13 | container = jp.QPageContainer(a=lay) 14 | 15 | div = jp.Div(a=container, classes="bg-gray-200 h-screen p-2") 16 | jp.Div(a=div, text="This is the Home page!", classes="text-4xl m-2") 17 | jp.Div(a=div, text=""" 18 | long text 19 | """, classes="text-lg") 20 | 21 | return wp 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/webapp/layout.py: -------------------------------------------------------------------------------- 1 | import justpy as jp 2 | 3 | 4 | class DefaultLayout(jp.QLayout): 5 | 6 | def __init__(self, view="hHh lpR fFf", **kwargs): 7 | 8 | super().__init__(view=view, **kwargs) 9 | 10 | header = jp.QHeader(a=self) 11 | toolbar = jp.QToolbar(a=header) 12 | 13 | drawer = jp.QDrawer(a=self, show_if_above=True, v_model="left", 14 | bordered=True) 15 | scroller = jp.QScrollArea(a=drawer, classes="fit") 16 | qlist = jp.QList(a=scroller) 17 | 18 | a_classes = "p-2 m-2 text-lg text-blue-400 hover:text-blue-700" 19 | jp.A(a=qlist, text="Home", href="/", classes=a_classes) 20 | jp.Br(a=qlist) 21 | jp.A(a=qlist, text="Dictionary", href="/dictionary", classes=a_classes) 22 | jp.Br(a=qlist) 23 | jp.A(a=qlist, text="About", href="/about", classes=a_classes) 24 | jp.Br(a=qlist) 25 | 26 | jp.QBtn(a=toolbar, dense=True, flat=True, round=True, icon="menu", 27 | click=self.move_drawer, drawer=drawer) 28 | 29 | jp.QToolbarTitle(a=toolbar, text="Instant Dictionary") 30 | 31 | @staticmethod 32 | def move_drawer(widget, msg): 33 | if widget.drawer.value: 34 | widget.drawer.value = False 35 | else: 36 | widget.drawer.value = True 37 | -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/webapp/navbar.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Instant_Dictionary_Webapp/webapp/navbar.py -------------------------------------------------------------------------------- /Instant_Dictionary_Webapp/webapp/page.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class Page(ABC): 5 | 6 | @abstractmethod 7 | def serve(self): 8 | pass 9 | -------------------------------------------------------------------------------- /Math_Painting/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Math_Painting/.idea/Math_Painting.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Math_Painting/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Math_Painting/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Math_Painting/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Math_Painting/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Math_Painting/canvas.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from PIL import Image 3 | 4 | 5 | class Canvas: 6 | """Object where all shapes are going to be drawn""" 7 | 8 | def __init__(self, height, width, color): 9 | self.color = color 10 | self.height = height 11 | self.width = width 12 | 13 | # create a 3d numpy array of zeros 14 | self.data = np.zeros((self.height, self.width, 3), dtype=np.uint8) 15 | # change [0,0,0] with user given values for colors 16 | self.data[:] = self.color 17 | 18 | def make(self, image_path): 19 | """Converts the current array into image file""" 20 | img = Image.fromarray(self.data, 'RGB') 21 | img.save(image_path) 22 | -------------------------------------------------------------------------------- /Math_Painting/design.txt: -------------------------------------------------------------------------------- 1 | Title: Math Painting 2 | 3 | Description: An App that lets the user provide the start coordinates of 4 | geometrical shapes such as squares and rectangles, their dimensions, and 5 | the program produces an image file canvas with the geometrical shapes 6 | drawn it. 7 | 8 | Objects: Squares: 9 | x 10 | y 11 | side 12 | color 13 | draw(canvas) 14 | Rectangle: 15 | x 16 | y 17 | width 18 | height 19 | color 20 | draw(canvas) 21 | Canvas: 22 | width 23 | height 24 | color 25 | make(image_path) -------------------------------------------------------------------------------- /Math_Painting/main.py: -------------------------------------------------------------------------------- 1 | from canvas import Canvas 2 | from shapes import Rectangle, Square 3 | 4 | # Get canvas width and height from the user 5 | canvas_width = int(input("Enter canvas width: ")) 6 | canvas_height = int(input("Enter canvas height: ")) 7 | 8 | # Make a dictionary of a color codes and prompts for color 9 | colors = {"white": (255, 255, 255), "black": (0, 0, 0)} 10 | canvas_color = input("Enter canvas color (white or black): ") 11 | 12 | # Create a canvas with the user data 13 | canvas = Canvas(height=canvas_height, width=canvas_width, color=colors[canvas_color]) 14 | 15 | while True: 16 | shape_type = input("What do you like to draw? Enter quit to quit. ") 17 | # Ask for rectangle data and create a rectangle if user entered 'rectangle' 18 | if shape_type.lower() == 'rectangle': 19 | rec_x = int(input("Enter x of the rectangle: ")) 20 | rec_y = int(input("Enter y of the rectangle: ")) 21 | rec_width = int(input("Enter the width of the rectangle: ")) 22 | rec_height = int(input("Enter the height of the rectangle: ")) 23 | 24 | red = int(input("How much red should the rectangle have? ")) 25 | green = int(input("How much green? ")) 26 | blue = int(input("How much blue? ")) 27 | 28 | # Create the rectangle 29 | r1 = Rectangle(x=rec_x, y=rec_y, height=rec_height, width=rec_width, color=(red, green, blue)) 30 | r1.draw(canvas) 31 | 32 | # Ask for square data and create square if user entered 'squared' 33 | elif shape_type.lower() == 'square': 34 | sqr_x = int(input("Enter x of the square: ")) 35 | sqr_y = int(input("Enter y of the square: ")) 36 | sqr_side = int(input("Enter the side of the square: ")) 37 | 38 | red = int(input("How much red should the rectangle have? ")) 39 | green = int(input("How much green? ")) 40 | blue = int(input("How much blue? ")) 41 | 42 | # Create the square 43 | s1 = Square(x=sqr_x, y=sqr_y, side=sqr_side, color=(red, green, blue)) 44 | s1.draw(canvas) 45 | 46 | # Break the loop if user entered 'quit' 47 | elif shape_type.lower() == 'quit': 48 | break 49 | 50 | canvas.make('canvas.png') 51 | -------------------------------------------------------------------------------- /Math_Painting/shapes.py: -------------------------------------------------------------------------------- 1 | class Rectangle: 2 | """A rectangle shape that can be drawn on a canvas object""" 3 | 4 | def __init__(self, x, y, height, width, color): 5 | self.x = x 6 | self.y = y 7 | self.height = height 8 | self.width = width 9 | self.color = color 10 | 11 | def draw(self, canvas): 12 | """Draws itself into the canvas""" 13 | # Changes a slice of the array with new values 14 | canvas.data[self.x: self.x + self.height, self.y: self.y + self.width] = self.color 15 | 16 | 17 | class Square: 18 | """A square shape that can be drawn on a canvas object""" 19 | 20 | def __init__(self, x, y, side, color): 21 | self.x = x 22 | self.y = y 23 | self.side = side 24 | self.color = color 25 | 26 | def draw(self, canvas): 27 | """Draws itself into the canvas""" 28 | # Changes a slice of the array with new values 29 | canvas.data[self.x: self.x + self.side, self.y: self.y + self.side] = self.color 30 | -------------------------------------------------------------------------------- /Photo_Searcher/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Photo_Searcher/.idea/Photo_Searcher.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Photo_Searcher/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Photo_Searcher/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Photo_Searcher/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Photo_Searcher/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Photo_Searcher/frontend.kv: -------------------------------------------------------------------------------- 1 | : 2 | GridLayout: 3 | cols: 1 4 | padding: 10 5 | spacing: 10 6 | Image: 7 | id: img 8 | size_hint_y: 0.8 9 | TextInput: 10 | id: user_query 11 | size_hint_y: 0.1 12 | Button: 13 | text: 'Search Image' 14 | size_hint_y: 0.1 15 | on_press: root.set_image() 16 | 17 | : 18 | FirstScreen: 19 | id: first_screen 20 | name: 'first_screen' -------------------------------------------------------------------------------- /Photo_Searcher/main.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.uix.screenmanager import ScreenManager, Screen 3 | from kivy.lang import Builder 4 | 5 | import wikipedia 6 | import requests 7 | 8 | Builder.load_file('frontend.kv') 9 | 10 | 11 | class FirstScreen(Screen): 12 | def get_image_link(self): 13 | # Get user query from text input 14 | query = self.manager.current_screen.ids.user_query.text 15 | 16 | # Get wikipedia page and first image link 17 | page = wikipedia.page(query) 18 | image_link = page.images[0] 19 | 20 | return image_link 21 | 22 | def download_image(self): 23 | # Download the image 24 | req = requests.get(self.get_image_link()) 25 | image_path = f"files/image.jpg" 26 | with open(image_path, "wb") as file: 27 | file.write(req.content) 28 | 29 | return image_path 30 | 31 | def set_image(self): 32 | # Set the image in the widget 33 | self.manager.current_screen.ids.img.source = self.download_image() 34 | 35 | 36 | class RootWidget(ScreenManager): 37 | pass 38 | 39 | 40 | class MainApp(App): 41 | def build(self): 42 | return RootWidget() 43 | 44 | 45 | MainApp().run() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python Object-Oriented Programming (OOP) Projects 2 | 3 | This repository contains a collection of Python projects that demonstrate the principles of Object-Oriented Programming (OOP). Each project is designed to showcase various aspects of OOP and can be used as educational resources for learning OOP in Python. 4 | 5 | ## Overview 6 | 7 | Object-Oriented Programming is a fundamental paradigm in software development. This repository provides a hands-on approach to OOP by implementing projects that cover a range of OOP concepts and techniques. Whether you are a beginner looking to learn OOP or an experienced developer wanting to reinforce your OOP skills, you'll find something valuable in these projects. 8 | 9 | ## Project List 10 | 11 | 1. **Class Inheritance**: An example of creating and using class inheritance in Python. 12 | 13 | 2. **Encapsulation**: Demonstrates the concept of encapsulation through access modifiers. 14 | 15 | 3. **Polymorphism**: Illustrates polymorphism through method overriding and dynamic method binding. 16 | 17 | 4. **Composition**: Shows how to create complex objects through composition. 18 | 19 | 5. **Abstraction**: Provides examples of abstract classes and methods. 20 | 21 | 6. **Design Patterns**: Includes examples of common design patterns implemented in Python. 22 | 23 | Each project includes detailed documentation and code explanations to aid your understanding. 24 | 25 | ## Getting Started 26 | 27 | To get started with the projects, clone this repository to your local machine: 28 | 29 | ```bash 30 | git clone https://github.com/pxxthik/Python-OOP-Projects.git 31 | -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/.idea/Webcam_Photo_Sharer.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/design-frontend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Webcam_Photo_Sharer/design-frontend.png -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/design.txt: -------------------------------------------------------------------------------- 1 | Title: Webcam Photo Sharer 2 | 3 | Description: An app that starts the computer webcam, lets user 4 | capture a photo and uploads the photo to the web and creates a 5 | sharable link. 6 | 7 | Objects: Webcam: 8 | start() 9 | stop() 10 | capture() 11 | FileSharer: 12 | filepath 13 | api 14 | share() -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/filesharer.py: -------------------------------------------------------------------------------- 1 | from filestack import Client 2 | 3 | 4 | class FileSharer: 5 | def __init__(self, filepath, api_key='Aj799wiBlScSabXEs3WqDz'): 6 | self.filepath = filepath 7 | self.api_key = api_key 8 | 9 | def share(self): 10 | client = Client(self.api_key) 11 | new_filelink = client.upload(filepath=self.filepath) 12 | return new_filelink.url 13 | -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/frontend.kv: -------------------------------------------------------------------------------- 1 | : 2 | GridLayout: 3 | cols: 1 4 | padding: 10 5 | spacing: 10 6 | Camera: 7 | id: camera 8 | resolution: (640, 480) 9 | play: False 10 | size_hint_y: 0.8 11 | opacity: 0 12 | Button: 13 | id: camera_button 14 | text: 'Start Camera' 15 | on_press: root.start() if root.ids.camera.play == False else root.stop() 16 | size_hint_y: 0.1 17 | background_normal: 'images/normal.png' 18 | background_down: 'images/down.png' 19 | Button: 20 | text: 'Capture' 21 | on_press: root.capture() 22 | size_hint_y: 0.1 23 | background_normal: 'images/normal.png' 24 | background_down: 'images/down.png' 25 | 26 | : 27 | GridLayout: 28 | cols: 1 29 | padding: 10 30 | spacing: 10 31 | Image: 32 | id: img 33 | size_hint_y: 0.7 34 | Button: 35 | text: 'Create sharable link' 36 | on_press: root.create_link() 37 | size_hint_y: 0.1 38 | background_normal: 'images/normal.png' 39 | background_down: 'images/down.png' 40 | Label: 41 | id: link 42 | text: '' 43 | size_hint_y: 0.1 44 | GridLayout: 45 | cols: 2 46 | size_hint_y: 0.1 47 | Button: 48 | text: 'Copy link' 49 | on_press: root.copy_link() 50 | background_normal: 'images/normal.png' 51 | background_down: 'images/down.png' 52 | Button: 53 | text: 'Open link' 54 | on_press: root.open_link() 55 | background_normal: 'images/normal.png' 56 | background_down: 'images/down.png' 57 | 58 | : 59 | canvas.before: 60 | Color: 61 | rgba: (0.9, 0.9, 0.9, 1) 62 | Rectangle: 63 | pos: self.pos 64 | size: self.size 65 | CameraScreen: 66 | id: camera_screen 67 | name: 'camera_screen' 68 | ImageScreen: 69 | id: image_screen 70 | name: 'image_screen' -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/images/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Webcam_Photo_Sharer/images/down.png -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/images/normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pxxthik/Python-OOP-Projects/82d30e657eccc66e211f3c414645d88d3a2b80d0/Webcam_Photo_Sharer/images/normal.png -------------------------------------------------------------------------------- /Webcam_Photo_Sharer/main.py: -------------------------------------------------------------------------------- 1 | from kivy.app import App 2 | from kivy.uix.screenmanager import ScreenManager, Screen 3 | from kivy.lang import Builder 4 | from kivy.core.clipboard import Clipboard 5 | 6 | import time 7 | import webbrowser 8 | 9 | from filesharer import FileSharer 10 | 11 | Builder.load_file("frontend.kv") 12 | 13 | 14 | class CameraScreen(Screen): 15 | def start(self): 16 | """Starts camera and changes button text""" 17 | self.ids.camera.opacity = 1 18 | self.ids.camera.play = True 19 | self.ids.camera_button.text = "Stop Camera" 20 | self.ids.camera.texture = self.ids.camera._camera.texture 21 | 22 | def stop(self): 23 | """Stops camera and changes button text""" 24 | self.ids.camera.opacity = 0 25 | self.ids.camera.play = False 26 | self.ids.camera_button.text = "Start Camera" 27 | self.ids.camera.texture = None 28 | 29 | def capture(self): 30 | """Creates a filename with the current time and captures 31 | and saves a photo image under that filename""" 32 | current_time = time.strftime('%Y%m%d-%H%M%S') 33 | self.filepath = f"files/{current_time}.png" 34 | self.ids.camera.export_to_png(self.filepath) 35 | self.manager.current = 'image_screen' 36 | self.manager.current_screen.ids.img.source = self.filepath 37 | 38 | 39 | class ImageScreen(Screen): 40 | link_message = "Create a link first" 41 | 42 | def create_link(self): 43 | """Access the photo filepath, uploads it to the web, 44 | and inserts the linkin the Label widget""" 45 | filepath = App.get_running_app().root.ids.camera_screen.filepath 46 | file_sharer = FileSharer(filepath=filepath) 47 | self.url = file_sharer.share() 48 | self.ids.link.text = self.url 49 | 50 | def copy_link(self): 51 | """Copy link to the clipboard available for pasting""" 52 | try: 53 | Clipboard.copy(self.url) 54 | except: 55 | self.ids.link.text = self.link_message 56 | 57 | def open_link(self): 58 | """Open link with default browser""" 59 | try: 60 | webbrowser.open(self.url) 61 | except: 62 | self.ids.link.text = self.link_message 63 | 64 | 65 | class RootWidget(ScreenManager): 66 | pass 67 | 68 | 69 | class MainApp(App): 70 | 71 | def build(self): 72 | return RootWidget() 73 | 74 | 75 | MainApp().run() 76 | --------------------------------------------------------------------------------