-
Notifications
You must be signed in to change notification settings - Fork 0
/
receipt.py
172 lines (131 loc) · 5.39 KB
/
receipt.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
from utils import regex_patterns
import uuid
import re
from decimal import Decimal
import math
class Receipt:
"""
Receipt class to store receipt data and calculate points.
Attributes:
id (str): A unique identifier for the receipt.
retailer (str): The name of the retailer.
purchaseDate (str): The date of the purchase in the format YYYY-MM-DD.
purchaseTime (str): The time of the purchase in the format HH:MM or H:MM.
total (str): The total amount of the purchase in the format (D+).DD.
items (list): A list of items purchased.
score (int): The number of points earned from the receipt.
"""
def __init__(self, receipt_json):
"""
Initialize a Receipt object from a JSON object. The JSON object must have the following fields: retailer, purchaseDate, purchaseTime, total, and items.
"""
assert "retailer" in receipt_json and \
self.validPattern("retailer", receipt_json["retailer"])
self.retailer = receipt_json["retailer"]
assert "purchaseDate" in receipt_json and \
self.validPattern("purchaseDate", receipt_json["purchaseDate"])
self.purchaseDate = receipt_json["purchaseDate"]
assert "purchaseTime" in receipt_json and \
self.validPattern("purchaseTime", receipt_json["purchaseTime"])
self.purchaseTime = receipt_json["purchaseTime"]
assert "total" in receipt_json and \
self.validPattern("total", receipt_json["total"])
self.total = receipt_json["total"]
self.items = []
assert "items" in receipt_json and \
isinstance(receipt_json["items"], list) and \
len(receipt_json["items"])>0
for item in receipt_json["items"]:
self.items.append(Item(item))
self.id = str(uuid.uuid4())
self.score = None
def validPattern(self, field, value):
"""Make sure the value matches the regex pattern for the field."""
return re.match(regex_patterns[field], value)
def getPointsFromRetailer(self):
"""One point for every alphanumeric character in the retailer name."""
alphanumeric_count = sum(c.isalnum() for c in self.retailer)
return alphanumeric_count
def getPointsFromTotal(self):
"""
50 points if the total is a round dollar amount with no cents.
25 points if the total is a multiple of 0.25.
"""
points=0
cent_val = int(self.total.split(".")[1])
if cent_val==0:
points+=50
if cent_val in [0,25,50,75]:
points+=25
return points
def getPointsFromItems(self):
"""
5 points for every two items on the receipt.
If the trimmed length of the item description is a multiple of 3, multiply the price by 0.2 and round up to the nearest integer. The result is the number of points earned.
Using Decimal to avoid floating point errors.
"""
points=0
item_count = len(self.items)
points+=(item_count//2)*5
for item in self.items:
if len(item.shortDescription.strip())%3==0:
decimal_price = Decimal(item.price)
points+=math.ceil(decimal_price*Decimal(0.2))
return points
def getPointsFromDate(self):
"""
6 points if the day in the purchase date is odd.
"""
points=0
date_val = int(self.purchaseDate.split("-")[2])
if date_val%2==1:
points+=6
return points
def getPointsFromTime(self):
"""
10 points if the time of purchase is after 2:00pm and before 4:00pm.
"""
points=0
hour_val = int(self.purchaseTime.split(":")[0])
minute_val = int(self.purchaseTime.split(":")[1])
if hour_val==15 or (hour_val==14 and minute_val>0):
points+=10
return points
def calculateScore(self):
"""
Calculates the points earned from the receipt data.
"""
points=0
points+=self.getPointsFromRetailer()
points+=self.getPointsFromTotal()
points+=self.getPointsFromItems()
points+=self.getPointsFromDate()
points+=self.getPointsFromTime()
self.score = points
def getScore(self):
"""
If the score has not been calculated, calculate it. Return the score.
"""
if self.score is None:
self.calculateScore()
return self.score
class Item:
"""
Item class to store item data.
Attributes:
shortDescription (str): A short description of the item.
price (str): The price of the item in the format (D+).DD.
"""
def __init__(self, item_json):
"""
Initialize an Item object from a JSON object. The JSON object must have the following fields: shortDescription and price.
"""
assert "shortDescription" in item_json and \
self.validPattern("shortDescription", item_json["shortDescription"])
self.shortDescription = item_json["shortDescription"]
assert "price" in item_json and \
self.validPattern("price", item_json["price"])
self.price = item_json["price"]
def validPattern(self, field, value):
"""Make sure the value matches the regex pattern for the field."""
return re.match(regex_patterns[field], value)