diff --git a/__pycache__/pydb.cpython-310.pyc b/__pycache__/pydb.cpython-310.pyc new file mode 100644 index 0000000..0c1c811 Binary files /dev/null and b/__pycache__/pydb.cpython-310.pyc differ diff --git a/client.py b/client.py index e9ada57..81d6ca8 100644 --- a/client.py +++ b/client.py @@ -1,34 +1,40 @@ -#client +# client import socket print("Welcome to the stock trading application!\n") -#create socket +# create socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -#get server address and create address pair +# get server address and create address pair connectCmd = input("Please input a server address and port: ") -address = (connectCmd[0:connectCmd.find(":")], int(connectCmd[connectCmd.find(":") + 1:])) +address = (connectCmd[0:connectCmd.find(":")], + int(connectCmd[connectCmd.find(":") + 1:])) connection = False MSGLEN = 32 -#try to connect to server - error and exit program if it fails -try: +# try to connect to server - error and exit program if it fails +try: s.connect(address) connection = True - print(f"Connection successfully established with {address[0]}:{address[1]}\n") + print( + f"Connection successfully established with {address[0]}:{address[1]}\n") except Exception as e: - print(f"Connection could not be established with server on {address[0]}:{address[1]} \nException is " + str(e) + "\nProgram exiting...") + print(f"Connection could not be established with server on {address[0]}:{address[1]} \nException is " + str( + e) + "\nProgram exiting...") + def quitClient(): s.close() print("Connection broken - Program exiting...") - global connection + global connection connection = False return -#sends input string of max length MSGLEN to the server +# sends input string of max length MSGLEN to the server + + def sendMsg(msg): totalSent = 0 while len(msg) < MSGLEN: @@ -43,7 +49,9 @@ def sendMsg(msg): totalSent += sent print("msg '" + msg.strip() + "' sent with total bytes: " + str(totalSent)) -#recieves string from server +# recieves string from server + + def recieveMsg(): chunks = [] bytesRecieved = 0 @@ -61,16 +69,19 @@ def recieveMsg(): returnStr = returnStr + c.decode("utf-8") return returnStr.strip() -#main client command loop - "quit" to quit the program and "shutdown" to shutdown the server + +# main client command loop - "quit" to quit the program and "shutdown" to shutdown the server while connection: cmd = input("CMD>> ") if cmd[0:8].lower() == "balance".lower(): sendMsg(cmd) - #does nothing yet + # does nothing yet + elif cmd.lower() == "buy": + sendMsg(cmd) elif cmd.lower() == "shutdown".lower(): sendMsg(cmd) print("Shutting down server...") quitClient() elif cmd.lower() == "quit".lower(): sendMsg("quit") - quitClient() \ No newline at end of file + quitClient() diff --git a/pydb.py b/pydb.py index 26702a8..94a7a35 100644 --- a/pydb.py +++ b/pydb.py @@ -1,9 +1,10 @@ -#database file +# database file import sqlite3 as sql DBNAME = "stockDB" + def initDB(): db = sql.connect(DBNAME) print("Database " + DBNAME + " created") @@ -31,5 +32,3 @@ def initDB(): FOREIGN KEY (user_id) REFERENCES Users (ID) ); ''') print("Stocks table created in database") - - diff --git a/server.py b/server.py index eefe907..b072dad 100644 --- a/server.py +++ b/server.py @@ -1,4 +1,4 @@ -#server +# server import socket import sqlite3 as sql @@ -6,39 +6,44 @@ import pydb -#setup port as last 4 of umid and address setup as a pair +# setup port as last 4 of umid and address setup as a pair PORT = 8414 serverAddress = ("localhost", PORT) status = False MSGLEN = 32 DBNAME = "stockDB" -#create server socket +# create server socket serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -#test connection with serverAddress - error if it doesn't work and exit program +# test connection with serverAddress - error if it doesn't work and exit program try: serverSocket.bind(serverAddress) status = True serverSocket.listen(5) - print(f"Server started on {serverAddress[0]} and is listening on port {serverAddress[1]}\n") + print( + f"Server started on {serverAddress[0]} and is listening on port {serverAddress[1]}\n") except Exception as e: - print(f"Server failed to start on {serverAddress[0]}:{serverAddress[1]} \nException is" + str(e) + "\nProgram exiting...") + print(f"Server failed to start on {serverAddress[0]}:{serverAddress[1]} \nException is" + str( + e) + "\nProgram exiting...") -#connect to DB +# connect to DB if not os.path.isfile(DBNAME): pydb.initDB() db = sql.connect(DBNAME) print("Connected to database: " + DBNAME) cur = db.cursor() + def shutdown(): global status status = False print("Server shutting down...") serverSocket.close() -#sends input string to client of max length MSGLEN +# sends input string to client of max length MSGLEN + + def sendMsg(msg): totalSent = 0 while len(msg) < MSGLEN: @@ -53,7 +58,9 @@ def sendMsg(msg): totalSent += sent print("msg '" + msg.strip() + "' sent with total bytes: " + str(totalSent)) -#recieves string from client +# recieves string from client + + def recieveMsg(): chunks = [] bytesRecieved = 0 @@ -71,7 +78,72 @@ def recieveMsg(): returnStr = returnStr + c.decode("utf-8") return returnStr.strip() -#main server loop - accept connection - runs command loop until quit or shutdown is recieved +def buy_stock(ticker, quantity, stock_price, user_id): + # Check if user has sufficient funds + query = "SELECT usd_balance FROM Users WHERE ID = ?" + cur.execute(query, (user_id,)) + balance = cur.fetchone()[0] + if balance < quantity * stock_price: + raise Exception("Insufficient funds") + + # Update stock quantity + query = "SELECT user_id FROM Stocks WHERE stock_symbol = ?" + cur.execute(query, (ticker)) + stock = cur.fetchone() + if stock is not None: + query = "UPDATE Stocks SET stock_balance = stock_balance + ? WHERE stock_symbol = ?" + cur.execute(query, (quantity, ticker)) + query = "INSERT INTO Stocks (stock_symbol, stock_balance) VALUES (?, ?)" + cur.execute(query, (ticker, quantity)) + + # Update user balance + query = "UPDATE Users SET usd_balance = usd_balance - ? WHERE ID = ?" + cur.execute(query, (quantity * stock_price, user_id)) + + db.commit() + +#Here we will need the stock price as well to update the balance when the user sells the stock: check line 122-124 +def sell_stock(ticker, quantity, stock_price, user_id): + query = "SELECT stock_balance FROM Stocks WHERE user_id = ? AND stock_symbol = ?" + cur.execute(query, (user_id, ticker)) + result = cur.fetchone() + if result is None: + print("User does not hold the stock with ticker '{}'".format(ticker)) + return + query = "SELECT quantity FROM Stocks WHERE stock_symbol = ? AND user_id = ?" + cur.execute(query, (ticker, user_id)) + stock_balance = cur.fetchone()[0] + if stock_balance < quantity: + raise Exception("Insufficient stock quantity") + # Update stock quantity + query = "UPDATE Stocks SET stock_balance = stock_balance - ? WHERE stock_symbol = ? AND user_id = ?" + cur.execute(query, (quantity, ticker, user_id)) + + # Update user balance + query = "UPDATE Users SET usd_balance = usd_balance + ? WHERE ID = ?" + cur.execute(query, (quantity * stock_price, user_id)) + + db.commit() + + +def balance(user_id): + UI = pydb.getUserInfo(5) + query = "SELECT usd_balance FROM Users WHERE ID = ?" + cur.execute(query, (user_id,)) + balance = cur.fetchall() + return balance + db.commit() + + +def list_stocks(user_id): + query = "SELECT stock_name FROM Stocks WHERE user_id = ?" + cur.execute(query, (user_id)) + stocks = cur.fetchall() + return stocks + db.commit() + + +# main server loop - accept connection - runs command loop until quit or shutdown is recieved while status: (clientSocket, clientAddr) = serverSocket.accept() print(f"Connection accepted from {clientAddr[0]}:{clientAddr[1]}\n") @@ -84,4 +156,15 @@ def recieveMsg(): shutdown() elif msg.lower() == "quit".lower(): client = False - \ No newline at end of file + elif msg[0:3].lower() == "buy".lower(): + arguments = msg.split(' ') + function_arguments = arguments[1:] + buy_stock(*function_arguments) + elif msg[0:3].lower() == "sell".lower(): + arguments = msg.split(' ') + function_arguments = arguments[1:] + sell_stock(*function_arguments) + elif msg.lower() == "balance".lower(): + balance(1) + elif msg.lower() == "list".lower(): + list_stocks(1) diff --git a/stockDB b/stockDB new file mode 100644 index 0000000..081d49e Binary files /dev/null and b/stockDB differ