Skip to content
This repository was archived by the owner on Mar 31, 2020. It is now read-only.

Commit 03b714c

Browse files
committed
Added documentation/comments and made everything pep8 compliant
1 parent 1d4855d commit 03b714c

File tree

2 files changed

+208
-63
lines changed

2 files changed

+208
-63
lines changed

src/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from .mainwindow import Tinder
22

33
if __name__ == "__main__":
4-
Tinder().start()
4+
Tinder().start()

src/mainwindow.py

Lines changed: 207 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3,170 +3,315 @@
33
import io
44
from random import randint, choice, sample
55
import asyncio
6-
import time
76
import aiohttp
87
import os
98
from pygame import mixer
109

1110

1211
class Tinder:
1312
def __init__(self):
13+
# setup for pygame mixer
1414
mixer.init()
15+
16+
# getting the directory folder for use later when opening files
1517
self.dir = os.path.dirname(os.path.realpath(__file__))
18+
19+
# setting up the tkinter root
1620
self.root = tk.Tk()
1721
self.root.title("Cat Tinder")
1822
self.root.geometry("400x500")
1923
self.root.minsize(400, 500)
2024
self.root.maxsize(400, 500)
2125
self.root.configure(background='black')
2226
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
23-
#self.root.bind('<Motion>', self.motion)
27+
28+
# getting screen width and height for use with teleporting window/jumpscare
2429
self.screen_x = self.root.winfo_screenwidth()
2530
self.screen_y = self.root.winfo_screenheight()
31+
32+
# setting class variables to be used later
2633
self.jumpscare = False
2734
self.loop = asyncio.get_event_loop()
2835
self.session = None
29-
self.images = list()
30-
31-
36+
self.cats = list()
37+
3238
def start(self):
39+
'''Starts the Tinder application'''
40+
41+
# getting a cache of cat info
3342
self.loop.run_until_complete(self.get_cache())
34-
self.new_image()
3543

44+
# starting the program loop
45+
self.new_image()
3646

3747
async def get_cache(self):
38-
print("refreshing image cache")
39-
t = time.time()
48+
'''Gets a cache of cat data and adds it to the self.cats list'''
49+
50+
# if we haven't created a session yet, do so
4051
if not self.session:
4152
self.session = aiohttp.ClientSession()
53+
54+
# Run 10 times to get 10 cats
4255
for i in range(10):
56+
# initialize a dict of cat data
4357
cat_data = dict()
44-
if randint(1,10) == 5 and i:
45-
image_number = randint(1,10)
46-
im = Image.open(os.path.join(self.dir, os.path.join("res", os.path.join("images", f"{image_number}.jpg"))))
58+
59+
# randomly make jumpscares happen, but not on the first image
60+
if randint(1, 10) == 5 and i:
61+
# get a random number for an image
62+
image_number = randint(1, 10)
63+
# open and resize the image using Pillow
64+
im = Image.open(os.path.join(self.dir, os.path.join("res",
65+
os.path.join("images", f"{image_number}.jpg"))))
4766
im = im.resize((self.screen_x, self.screen_y - 150), Image.NEAREST)
67+
# make the image a tkinter image
4868
image = ImageTk.PhotoImage(im)
49-
cat_data.update({"image" : image})
69+
# update the cat data dict
70+
cat_data.update({"image": image})
5071
cat_data.update({"jumpscare": True})
5172
else:
73+
# set jumpscare to False because it isnt a jumpscare image
5274
cat_data.update({"jumpscare": False})
75+
76+
# get a url from The Cat API
5377
async with self.session.get('https://api.thecatapi.com/v1/images/search') as res:
5478
data = await res.json()
5579
url = data[0]['url']
80+
# get image data from that url
5681
async with self.session.get(url) as res:
5782
image_bytes = await res.read()
83+
# open and the image in pillow
5884
im = Image.open(io.BytesIO(image_bytes))
5985
im = im.resize((400, 440), Image.NEAREST)
86+
# make the image a tkinter image
6087
image = ImageTk.PhotoImage(im)
61-
cat_data.update({"image":image})
62-
async with self.session.get("https://www.pawclub.com.au/assets/js/namesTemp.json") as res:
63-
data = await res.json()
64-
letter = choice(list('acdefghijklmnopqrstuvwxyz'))
65-
cat = choice(data[letter])
66-
cat_data.update({"name":cat["name"]})
67-
cat_data.update({"gender":cat["gender"]})
68-
async with self.session.get("https://gist.githubusercontent.com/mbejda/453fdb77ef8d4d3b3a67/raw/e8334f09109dc212892406e25fdee03efdc23f56/hobbies.txt") as res:
69-
text = await res.text()
70-
all_hobbies = text.split("\n")
71-
hobby_list = sample(all_hobbies, 5)
72-
list_of_hobbies = "\n •".join(hobby_list)
73-
hobbies = f"Hobbies:\n{list_of_hobbies}"
74-
cat_data.update({"hobbies":hobbies})
75-
age = str(randint(1,15))
76-
cat_data.update({"age":age})
77-
miles = randint(1,5)
78-
location = f"{miles} miles away"
79-
cat_data.update({"location":location})
80-
self.images.append(cat_data)
81-
print(time.time()-t)
88+
# update the cat data dict
89+
cat_data.update({"image": image})
8290

91+
# get a random name
92+
async with self.session.get(
93+
"https://www.pawclub.com.au/assets/js/namesTemp.json") as res:
94+
data = await res.json()
95+
# get a random letter for the name
96+
# Note: website doesn't have any b names which is why it is left out here
97+
letter = choice(list('acdefghijklmnopqrstuvwxyz'))
98+
# randomly choose a name from the json with that letter
99+
cat = choice(data[letter])
100+
# update the cat data dict
101+
cat_data.update({"name": cat["name"]})
102+
cat_data.update({"gender": cat["gender"]})
103+
104+
# get 5 random hobbies
105+
async with self.session.get(
106+
"https://gist.githubusercontent.com/mbejda/" +
107+
"453fdb77ef8d4d3b3a67/raw/e8334f09109dc212892406e25fdee03efdc23f56/" +
108+
"hobbies.txt"
109+
) as res:
110+
text = await res.text()
111+
# split the raw text of hobbies into a list
112+
all_hobbies = text.split("\n")
113+
# get 5 of those hobbies
114+
hobby_list = sample(all_hobbies, 5)
115+
# join those 5 hobbies into a bulleted list (string)
116+
list_of_hobbies = "\n •".join(hobby_list)
117+
hobbies = f"Hobbies:\n{list_of_hobbies}"
118+
# update the cat_data dict
119+
cat_data.update({"hobbies": hobbies})
120+
121+
# get a random age between 1 and 15 (avg lifespan of a cat)
122+
age = str(randint(1, 15))
123+
# update the cat data dict
124+
cat_data.update({"age": age})
125+
126+
# get a random number of miles away between 1 and 5
127+
miles = randint(1, 5)
128+
location = f"{miles} miles away"
129+
# update the cat data dict
130+
cat_data.update({"location": location})
131+
self.cats.append(cat_data)
83132

84133
def all_children(self):
134+
'''Used to get all children of the root window
135+
136+
Returns
137+
-------
138+
A `list` of tkinter objects that are children of the root window'''
139+
140+
# get children
85141
children = self.root.winfo_children()
142+
# loop through the children
86143
for item in children:
144+
# if the child has children, add them to the list
87145
if item.winfo_children():
88146
children.extend(item.winfo_children())
147+
# return the full list of children
89148
return children
90149

150+
def new_image(self, cat=None):
151+
'''Main functionality of the application
91152
92-
def new_image(self, cat= None):
153+
param
154+
cat: dict -- if you want to run the function without getting a new cat'''
155+
156+
# if the previous image was a jumpscare, resize the window and reset the variable
93157
if self.jumpscare:
94158
self.root.maxsize(400, 500)
95159
self.jumpscare = False
160+
161+
# get all children of the root window
96162
widget_list = self.all_children()
97163
for item in widget_list:
164+
# forget packs all of the children (This clears the window)
98165
item.pack_forget()
99-
self.frame = tk.Frame(self.root, bg = "black")
166+
167+
# make a new Frame
168+
self.frame = tk.Frame(self.root, bg="black")
169+
170+
# if a dict wasn't passed to the function, get a dict from self.cats
100171
if not cat:
101172
try:
102-
cat = self.images.pop(0)
173+
cat = self.cats.pop(0)
103174
except IndexError:
175+
# the cache is empty so refill it
104176
self.loop.run_until_complete(self.get_cache())
105-
cat = self.images.pop(0)
177+
cat = self.cats.pop(0)
178+
179+
# getting cat variables from the dict
106180
cat_name = cat["name"]
107181
image = cat["image"]
108182
jumpscare = cat["jumpscare"]
109183
gender = cat["gender"].capitalize()
110184
hobbies = cat["hobbies"]
111185
age = cat["age"]
112186
location = cat["location"]
187+
188+
# if the image is not a jumpscare, add a Text widget with the cat name
113189
if not jumpscare:
114-
name = tk.Text(self.frame, width = 40, height = 1)
190+
# make the Text widget
191+
name = tk.Text(self.frame, width=40, height=1)
192+
# tag to make all text in the widget centered
115193
name.tag_configure("center", justify=tk.CENTER)
194+
# insert the cat name into the widget
116195
name.insert("1.0", cat_name)
196+
# add the centered tag to all text in the widget
117197
name.tag_add("center", "1.0", tk.END)
198+
# disable the widget so the user can't type in it
118199
name.configure(state="disabled")
119-
name.pack(side = tk.TOP)
120-
tk.Label(self.frame, image=image).pack(side = tk.TOP)
200+
# pack the widget on the top of the frame
201+
name.pack(side=tk.TOP)
202+
203+
# make a Label widget with the cat/jumpscare image and pack it
204+
tk.Label(self.frame, image=image).pack(side=tk.TOP)
205+
206+
# the image is a jumpscare, so do jumpscare things
121207
if jumpscare:
208+
# remember that this image is a jumpscare
122209
self.jumpscare = True
210+
211+
# allow the root window to get bigger
123212
self.root.maxsize(self.screen_x, self.screen_y)
213+
# make the root window bigger (makes jumpscare image scarier)
124214
self.root.geometry(f"{self.screen_x}x{self.screen_y}+0+0")
125-
mixer.music.load(os.path.join(self.dir, os.path.join("res", os.path.join("sounds", "jumpscare.mp3"))))
215+
216+
# play a jumpscare sound
217+
mixer.music.load(
218+
os.path.join(self.dir, os.path.join(
219+
"res", os.path.join("sounds", "jumpscare.mp3"))
220+
)
221+
)
126222
mixer.music.play()
127-
tk.Button(self.frame, text="Like", background="green", command = self.new_image).pack(side = tk.BOTTOM)
223+
224+
# make a button to allow the user to pass through the image
225+
# Note: since everyone likes scary monsters, only make a Like button
226+
tk.Button(
227+
self.frame, text="Like", background="green", command=self.new_image
228+
).pack(side=tk.BOTTOM)
229+
230+
# image was not a jumpscare, don't do jumpscare things
128231
else:
129-
tk.Button(self.frame, text="Like", background="green", command = self.new_image).pack(side = tk.RIGHT)
130-
tk.Button(self.frame, text="Dislike", background="red", command = self.new_image).pack(side = tk.LEFT)
232+
# setting up like and dislike buttons on opposite sides of the screen
233+
tk.Button(
234+
self.frame, text="Like", background="green", command=self.new_image
235+
).pack(side=tk.RIGHT)
236+
tk.Button(
237+
self.frame, text="Dislike", background="red", command=self.new_image
238+
).pack(side=tk.LEFT)
239+
240+
# defining button functions
131241
def back_to_photo():
242+
'''Resets the window with the same cat for when the user
243+
goes to bio and clicks back'''
244+
245+
# calls the new image function and passes the current cat dict
132246
self.new_image(cat)
247+
133248
def get_bio():
249+
'''Creates the Bio Widget for the current cat'''
250+
251+
# get all children of the root window
134252
widget_list = self.all_children()
135253
for item in widget_list:
254+
# forget packs all of the children (This clears the window)
136255
item.pack_forget()
137-
self.frame = tk.Frame(self.root, bg = "black", height = 450, width= 400)
256+
257+
# make a new Frame for the bio
258+
self.frame = tk.Frame(self.root, bg="black", height=450, width=400)
259+
260+
# makes a Text widget on the Frame
138261
bio = tk.Text(self.frame)
262+
263+
# inserting all of the Bio to the text widget
139264
bio.insert(tk.END, f"Name: {cat_name} \n")
140265
bio.insert(tk.END, f"Age: {age} \n")
141266
bio.insert(tk.END, f"Gender: {gender} \n")
142267
bio.insert(tk.END, f"Location: {location} \n")
143-
bio.insert(tk.END, f"{hobbies} \n")
268+
bio.insert(tk.END, f"{hobbies} \n")
269+
# disabling the widget so users can't edit it
144270
bio.configure(state="disabled")
145-
bio.pack(side = tk.TOP)
146-
tk.Button(self.frame, text="Like", background="green", command = self.new_image).pack(side = tk.RIGHT)
147-
tk.Button(self.frame, text="Dislike", background="red", command = self.new_image).pack(side = tk.LEFT)
148-
tk.Button(self.root, text="Back To Photo", background="blue", command = back_to_photo).pack(side = tk.BOTTOM)
271+
# packing the bio
272+
bio.pack(side=tk.TOP)
273+
274+
# setting up like/dislike/Back to Photo buttons on the bio screen
275+
tk.Button(
276+
self.frame, text="Like", background="green", command=self.new_image
277+
).pack(side=tk.RIGHT)
278+
tk.Button(
279+
self.frame, text="Dislike", background="red", command=self.new_image
280+
).pack(side=tk.LEFT)
281+
tk.Button(
282+
self.root, text="Back To Photo", background="blue", command=back_to_photo
283+
).pack(side=tk.BOTTOM)
284+
285+
# packing the frame
149286
self.frame.pack()
150-
tk.Button(self.frame, text="Bio", background="blue", command = get_bio).pack(side = tk.BOTTOM)
287+
288+
# making and packing the Bio button for users to look at the cat's bio
289+
tk.Button(
290+
self.frame, text="Bio", background="blue", command=get_bio
291+
).pack(side=tk.BOTTOM)
292+
293+
# packing the frame
151294
self.frame.pack()
152-
self.root.mainloop()
153295

296+
# starting the main tkinter loop
297+
self.root.mainloop()
154298

155299
def on_closing(self):
300+
'''Teleports the window if the user tries to close the app using the red X'''
301+
302+
# checks if the image is a jumpscare (if so, can't teleport the
303+
# window because it takes up the entire screen)
156304
if not self.jumpscare:
305+
# get the max x and y values that the window can teleport
306+
# to without going off the screen
157307
max_x, max_y = self.screen_x - 400, self.screen_y - 500
308+
# getting the random x and y values to teleport to
158309
x, y = randint(0, max_x), randint(0, max_y)
310+
# moving the window to those x and y coordinates
159311
self.root.geometry(f"+{x}+{y}")
160312

161313

162-
def motion(self,event):
163-
frame_x, frame_y = self.frame.winfo_x(), self.frame.winfo_y()
164-
x, y = event.x, event.y
165-
if x > 300 and y < 15:
166-
move_x = (400 - x) + frame_x
167-
move_y = (15 - y) - frame_y
168-
self.root.geometry(f"400x500+{move_x}+{move_y}")
169-
170-
314+
# checks if this file is the main file being run
171315
if __name__ == "__main__":
172-
Tinder().start()
316+
# start the application
317+
Tinder().start()

0 commit comments

Comments
 (0)