This repository has been archived by the owner on Nov 6, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathguest.py
233 lines (190 loc) · 6.91 KB
/
guest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
from kivy.app import App
import binascii
from datetime import datetime
import hashlib
import os
from tinydb import TinyDB, Query
# constant variables
SALT = b"sr0te2eQ20Klubmyie"
ACTIVITY_IMG_DIR = os.path.join("res", "activity_img")
UNKNOWN_ACTIVITY_IMG = os.path.join("activity_unknown.jpg")
MEAL_IMG_DIR = os.path.join("res", "meal_img")
NO_ACTIVITY = {"name": "No Activity",
"rating": "easy",
"desc": "Stay on the cruise and enjoy the wonderful seascape and facilities that we offer.",
"price": 0}
# initiate tinydb objects and load files
db_guest = TinyDB("guest.json", indent=2)
tb_profiles = db_guest.table("profiles")
db_activity = TinyDB("activity.json", indent=2)
tb_details = db_activity.table("details")
tb_calendar = db_activity.table("calendar")
db_meal = TinyDB("meal.json", indent=2)
query = Query()
# return hash of given password
def hash_psw(psw):
pwd_hash = hashlib.pbkdf2_hmac('sha512', psw.encode('utf-8'), SALT, 100000)
pwd_hash = binascii.hexlify(pwd_hash)
return pwd_hash.decode('ascii')
# verify password by comparing its hash to stored hash
def verify_psw(psw, stored_hash):
return hash_psw(psw) == stored_hash
# find image of given name in given path
def find_img(name, path):
img_name = name.lower().replace(' ', '_')
for root, dirs, files in os.walk(path):
for fname in files:
if fname.startswith(img_name): # ignore extension
return os.path.join(root, fname)
return os.path.join(path, UNKNOWN_ACTIVITY_IMG)
# get the number of days from start
def get_day():
journey = db_guest.get(query.journey == "Kimberley Quest")
start_date = datetime.strptime(journey["start"], "%d%m%y")
return (datetime.today() - start_date).days + 1
class Activity:
BOOK_AHEAD = 3
def __init__(self, **kwargs):
self.name = kwargs.pop("name")
self.rating = kwargs.pop("rating")
self.desc = kwargs.pop("desc")
self.price = kwargs.pop("price")
if "day" in kwargs:
self.day = kwargs.pop("day")
@property
def img(self):
return find_img(self.name, ACTIVITY_IMG_DIR)
@classmethod
def no_activity(cls):
return cls(**NO_ACTIVITY)
@classmethod
def find(cls, name):
if name == cls.no_activity().name:
return cls.no_activity()
details = tb_details.get(query.name == name)
return cls(**details)
@classmethod
def on_day(cls, day):
# return the activities available for given day
data = tb_calendar.get(query.day == day)
activities = {}
for rating, name in data.items():
if rating != "day":
activities[rating] = cls.find(name)
# always add no activity to the list
activities["no activity"] = cls.no_activity()
return activities
class Meal:
normal = "Normal meal"
def __init__(self, **kwargs):
self.name = kwargs.pop("name")
self.desc = kwargs.pop("desc")
if "day" in kwargs:
self.day = kwargs.pop("day")
@property
def img(self):
return find_img(self.name, MEAL_IMG_DIR)
@classmethod
def find(cls, name):
details = db_meal.get(query.name == name)
return cls(**details)
@classmethod
def load(cls):
for info in db_meal.all():
yield cls(**info)
class Guest:
logged_in = ''
@staticmethod
def username(first, last, cabin):
return first[:1] + last + str(cabin)
@staticmethod
def find(username):
# return dictionary of user profiles that match the username
return tb_profiles.search(query.username == username)
@classmethod
def register(cls, first, last, usr, psw, age, cabin, gender, address, notes):
hashed = hash_psw(psw)
bookings = [Activity.no_activity().name for _ in range(14)]
meals = [Meal.normal for _ in range(14)]
tb_profiles.insert({
"username": usr,
"hash": hashed,
"last": last,
"first": first,
"cabin": int(cabin),
"age": int(age),
"gender": gender,
"notes": notes,
"address": address,
"activities": bookings,
"meals": meals
})
@classmethod
def login(cls, usr, psw):
found = cls.find(usr)
if not found:
return "User not found!"
else:
p_hash = found[0]["hash"]
if p_hash == hash_psw(psw):
cls.logged_in = usr
return
else:
return "Incorrect password!"
@classmethod
def change_psw(cls, ori_psw, new_psw):
ori_hash = cls.get_profile("hash")
if not verify_psw(ori_psw, ori_hash):
return "Incorrect original password!"
elif ori_psw == new_psw:
return "Your new password is the same as the original one!"
elif len(new_psw) < 6:
return "You new password is too short!"
else:
cls.set_profile("hash", hash_psw(new_psw))
@classmethod
def logout(cls):
cls.logged_in = None
@classmethod
def get_profile(cls, criteria):
# get given criteria from profile of logged-in user
profile = tb_profiles.get(query.username == cls.logged_in)
return profile[criteria]
@classmethod
def set_profile(cls, criteria, value):
# update given criteria in profile of logged-in user
tb_profiles.update({criteria: value}, query.username == cls.logged_in)
if criteria == "username":
cls.logged_in = value
@classmethod
def get_booked(cls, criteria, day):
# get the name of booked activity on given day
bookings = cls.get_profile(criteria)
return bookings[day - 1]
@classmethod
def book_activity(cls, criteria, day, item):
# update activity booking
if not cls.logged_in:
return
def update_booking(d, a): # change given day of booking list criteria
def transform(doc):
doc[criteria][d - 1] = a # criteria could be activity or meal
return transform
tb_profiles.update(update_booking(day, item), query.username == cls.logged_in)
@classmethod
def costs(cls):
# return sum of all activity costs
if not cls.logged_in:
return
receipt = []
total = 0
bookings = tb_profiles.get(query.username == cls.logged_in)["activities"]
day_count = 1
for name in bookings:
if name != Activity.no_activity().name: # leave out no activity
activity = Activity.find(name)
activity.day = day_count
receipt.append(activity)
total += activity.price
day_count += 1
return receipt, total