· 4 years ago · Feb 12, 2021, 12:18 PM
1import secrets
2import sqlite3
3
4
5class Card:
6
7 def __init__(self, card_number, pin=None, balance=0):
8 # if pin == None:
9 # self.set_pin()
10
11 self.card_number = card_number
12 self.pin = pin
13 self.balance = balance
14
15 def get_number(self):
16 return self.card_number
17
18 def get_balance(self):
19 return self.balance
20
21 def update_balance(self, balance):
22 self.balance = balance
23
24 def set_pin(self, pin=None):
25 if pin is None:
26 pin = []
27 for i in range(4):
28 pin.append(str(secrets.randbelow(10)))
29 pin = ''.join(pin)
30
31 self.pin = pin
32 return pin
33
34 def auth(self, pin):
35 return self.pin == pin
36
37
38# storage for cards, lol
39class CardStorage:
40
41 def __init__(self, iin):
42 self.iin = iin
43 self.table_name = 'card'
44 self.connection = sqlite3.connect('card.s3db')
45 self.cursor = self.connection.cursor()
46 self.cursor.execute('CREATE TABLE IF NOT EXISTS {} ('
47 'id INTEGER PRIMARY KEY AUTOINCREMENT,'
48 'number TEXT NOT NULL,'
49 'pin TEXT NOT NULL,'
50 'balance INTEGER DEFAULT 0'
51 ');'.format(self.table_name))
52 self.connection.commit()
53
54 def add(self, card_obj, pin):
55 if not isinstance(card_obj, Card) or self.find(card_obj.get_number()) is not None:
56 return
57
58 self.cursor.execute('INSERT INTO {} (number, pin)'
59 'VALUES (?,?);'.format(self.table_name), (card_obj.get_number(), pin))
60 self.connection.commit()
61
62 def remove_card(self, card_number):
63 self.cursor.execute('DELETE FROM {} '
64 'WHERE number = ?'.format(self.table_name), (card_number,))
65 self.connection.commit()
66 # idgaf to check result
67
68 def find(self, card_number):
69 self.cursor.execute('SELECT number, pin, balance FROM {} WHERE number = ?'.format(self.table_name), (card_number,))
70 result = self.cursor.fetchone()
71 if result is None:
72 return None
73 return Card(result[0], result[1], result[2])
74
75 def generate_num(self):
76 while True:
77 card_number = [ch for ch in self.iin]
78 for i in range(9):
79 card_number.append(str(secrets.randbelow(10)))
80
81 card_number.append(self.count_lunh(card_number))
82
83 card_number = ''.join(card_number)
84 if self.find(card_number) is None:
85 return card_number
86
87 def create_card(self):
88 card_number = self.generate_num()
89 card_obj = Card(card_number)
90 pin = card_obj.set_pin()
91 self.add(card_obj, pin)
92 return {'card_obj': card_obj, 'pin': pin}
93
94 def sync(self, card_obj, diff=None):
95 self.cursor.execute('SELECT balance FROM {} '
96 'WHERE number = ?;'.format(self.table_name), (card_obj.get_number(),))
97 result = self.cursor.fetchone()
98 if result is None:
99 return
100 current_balance = result[0]
101 if current_balance != card_obj.get_balance():
102 card_obj.update_balance(current_balance)
103
104 if diff is not None:
105 card_obj.update_balance(current_balance + diff)
106 self.cursor.execute('UPDATE {} SET balance = ?'
107 'WHERE number = ?;'.format(self.table_name),
108 (card_obj.get_balance(), card_obj.get_number()))
109 self.connection.commit()
110
111 @staticmethod
112 def count_lunh(card_number):
113 card_number = [int(i) for i in card_number]
114 for i in range(len(card_number)):
115 if i % 2 == 0:
116 card_number[i] *= 2
117 if card_number[i] > 9:
118 card_number[i] -= 9
119 luhn_sum = 10 - (sum(card_number) % 10)
120 if luhn_sum == 10:
121 luhn_sum = 0
122 return str(luhn_sum)
123
124
125storage = CardStorage('400000')
126stage = []
127current_card = None
128
129while True:
130 if len(stage) == 0:
131 print("1. Create an account")
132 print("2. Log into account")
133 print("0. Exit")
134 action = input().strip()
135 if action == '1':
136 stage.append('create')
137 elif action == '2':
138 stage.append('login')
139 elif action == '0':
140 stage.append('exit')
141
142 elif stage[0] == 'create':
143 print("Your card has been created")
144 response = storage.create_card()
145
146 print("Your card number:")
147 print(response['card_obj'].get_number())
148
149 print("Your card PIN:")
150 print(response['pin'])
151
152 stage.pop()
153
154 elif stage[0] == 'login':
155 print("Enter your card number:")
156 card_number = input().strip()
157 print("Enter your PIN:")
158 pin = input().strip()
159
160 card_obj = storage.find(card_number)
161
162 if card_obj is not None and card_obj.auth(pin):
163 print("You have successfully logged in!")
164 current_card = card_obj
165 stage.pop()
166 stage.append('panel')
167 else:
168 print("Wrong card number or PIN!")
169 stage.pop()
170 continue
171
172 elif stage[0] == 'panel':
173 if len(stage) == 1:
174 print("1. Balance")
175 print("2. Add income")
176 print("3. Do transfer")
177 print("4. Close account")
178 print("5. Log out")
179 print("0. Exit")
180 action = input().strip()
181 if action == '1':
182 storage.sync(current_card)
183 print("Balance: " + str(current_card.get_balance()))
184 elif action == '2':
185 stage.append('add')
186 elif action == '3':
187 stage.append('transfer')
188 elif action == '4':
189 stage.append('close')
190 elif action == '5':
191 print("You have successfully logged out!")
192 current_card = None
193 stage.pop()
194 elif action == '0':
195 stage.pop()
196 stage.append('exit')
197 else:
198 if stage[1] == 'add':
199 print("Enter income:")
200 income = int(input().strip())
201 storage.sync(current_card, income)
202 print("Income was added!")
203 stage.pop()
204
205 elif stage[1] == 'transfer':
206 print("Transfer")
207 print("Enter card number:")
208 card_number = input().strip()
209 if storage.count_lunh(card_number[0:-1]) != card_number[-1]:
210 print("Probably you made a mistake in the card number. Please try again!")
211 else:
212 recipient = storage.find(card_number)
213 if recipient is None:
214 print("Such a card does not exist.")
215 else:
216 print("Enter how much money you want to transfer:")
217 amount = int(input().strip())
218 if current_card.get_balance() < amount:
219 print("Not enough money!")
220 else:
221 storage.sync(current_card, amount * (-1))
222 storage.sync(recipient, amount)
223 print("Success!")
224 stage.pop()
225
226 elif stage[1] == 'close':
227 print("The account has been closed!")
228 storage.remove_card(current_card.get_number())
229 current_card = None
230 stage.clear()
231
232 elif stage[0] == 'exit':
233 print("Bye!")
234 break
235