Way To Shop server implementation
The following files are the source code for the server that supports Way To Shop. For more information about multi-process servers visit Writing a multi-process server with python. Also if you want to see a simple implementation of the server working with the data base you can check the principal project page Way to Shop
DBmethods.py
This program supports the interaction with mysql server. You can get more information about the developing of this program here Databases in MYSQL and here Database implementation
#Connection import import MySQLdb #Creating the connection db = MySQLdb.connect(host='localhost', user='guillermo', passwd='olaquease', db='wtsdatabase') #Creting a cursor cursor = db.cursor() #------------------------------------Users table methods------------------------------------# #Retrieving the password of an user: def get_password(username): try: cursor.execute("select password from Users where username='%s';" % username) return cursor.fetchone() [0] except: return "None/*/" #Registering a new user: def write_user(username, password, name, email): try: result = cursor.execute("INSERT INTO `Users` (`username`, `password`, `name`, `mail`) VALUES ( '%s' , '%s', '%s', '%s');" % (username, password , name, email)) db.commit() except: result = 0 return result #Changing the privileges of a user: def modify_privileges(username, privileges): result = cursor.execute("UPDATE Users SET privileges=%s WHERE username = '%s';" % (privileges, username)) db.commit() return result #Changing the password of an user def change_password(username, password): result = cursor.execute("UPDATE Users SET password='%s' WHERE username = '%s';" % (password, username)) db.commit() return result #Retrieving the privileges of an user def get_privileges(username): cursor.execute("SELECT privileges FROM Users WHERE username= '%s';" % username) return cursor.fetchone()[0] #Retrieving the email of an user def get_email(username): cursor.execute("SELECT mail FROM Users WHERE username= '%s';" % username) return cursor.fetchone()[0] #Adding a submit to an user def add_submit(username): try: result = cursor.execute("UPDATE Users SET submits = submits + 1 WHERE username = '%s';" % username) db.commit() except: result = 0 return result #Retrieving the times an user has submitted something def get_submits(username): cursor.execute("SELECT submits FROM Users WHERE username= '%s';" % username) return cursor.fetchone()[0] #------------------------------------Items table methods------------------------------------# #Registering a new item def write_item(barcode, name, brand, quantity, description, image): try: result= cursor.execute("INSERT INTO Items (barcode, name, brand, quantity, description, image) VALUES (%s, '%s', '%s', '%s', '%s', '%s');" % (barcode, name, brand, quantity, description, image)) db.commit() except: result = 0 return result #Modifying an item def modify_item(barcode, name, brand, quantity, description, image): try: result = cursor.execute("UPDATE Items SET name = '%s', brand = '%s', quantity = '%s', description = '%s', image = '%s' WHERE barcode= %s;" % (name, brand, quantity, description, image, barcode)) db.commit() except: result = 0 return result #Retrieving the information of an item def get_item(barcode): cursor.execute("SELECT * FROM Items WHERE barcode = %s;" % barcode) return cursor.fetchone() #------------------------------------Stores table methods------------------------------------# #Registering a new store def write_store(name, location, latitude, longitude): try: result = cursor.execute("INSERT INTO Stores (name, location, latitude, longitude) VALUES ( '%s', '%s', %s, %s);" % (name, location, latitude, longitude)) db.commit() except: result = 0 return result #Modifying a store def modify_store(storeid, name, location, latitude, longitude): try: result = cursor.execute("UPDATE Stores SET name = '%s', location = '%s', latitude = %s, longitude = %s WHERE storeid= %s;"% (name, location, latitude, longitude, storeid)) db.commit() except: result = 0 return result #Retrieving the coordinates from a store def get_coordinates(storeid): cursor.execute("SELECT latitude, longitude FROM Stores WHERE storeid= %s;" % storeid) return cursor.fetchone() #Retrieving storeid def get_storeid(latitude, longitude): cursor.execute("SELECT storeid FROM Stores WHERE latitude = %s AND longitude = %s;" %(latitude, longitude)) return cursor.fetchone() #Retrieving store name and location def get_storename(storeid): cursor.execute("SELECT name, location FROM Stores WHERE storeid= %s;" %storeid) return cursor.fetchone() #Retrieving the stores inside a given radius def get_stores(latitude, longitude, radius): cursor.execute("SELECT storeid, location, name FROM Stores WHERE (latitude > %s) AND (latitude < %s) AND (longitude > %s) AND (longitude < %s);" % ((latitude-radius), (latitude+radius), (longitude-radius), (longitude+radius))) return cursor.fetchall() #------------------------------------Lists_users table methods------------------------------------# #Creating a new list for an user def write_list_user(listname,username): try: result = cursor.execute("INSERT INTO Lists_users (listname , username) VALUES ('%s', '%s');" % (listname,username)) db.commit() except: result = 0 return result #Retrieving the lists of an user def get_lists(username): cursor.execute("SELECT listid, listname FROM Lists_users WHERE username = '%s';" % username) return cursor.fetchall() #Retrieving the list id def get_listid(username, listname): cursor.execute("SELECT listid FROM Lists_users WHERE username ='%s' AND listname = '%s';"%(username, listname)) return cursor.fetchone()[0] #Deleting a list (also affects Lists_items) def delete_list(listid): try: result1 = cursor.execute("DELETE FROM Lists_items WHERE listid = %s;" % (listid)) result2 = cursor.execute("DELETE FROM Lists_users WHERE listid = %s;" % (listid)) result = [result1,result2] db.commit() except: result = [0,0] return result #------------------------------------Lists_items table methods------------------------------------# #Adding an item to a list def write_list_item(listid,barcode): try: result = cursor.execute("INSERT INTO Lists_items (listid,barcode) VALUES (%s, %s);" % (listid,barcode)) db.commit() except: result = 0 return result #Deleting an item from a list def delete_item(listid,barcode): try: result = cursor.execute("DELETE FROM Lists_items WHERE listid = %s AND barcode = %s;" % (listid,barcode)) db.commit() except: result = 0 return result #Retrieving all items on a list def get_all_items(listid): cursor.execute("SELECT * FROM Lists_items WHERE listid= %s;" % listid) return cursor.fetchall() #------------------------------------Items_stores table methods------------------------------------# #Adding an item to a store def write_item_store(barcode,storeid,price): try: result = cursor.execute("INSERT INTO Items_stores (barcode,storeid,price) VALUES (%s,%s,%s);" % (barcode,storeid,price)) db.commit() except: result = 0 return result #Get storeid where barcode exist def get_storeid_barcode(barcode): cursor.execute("SELECT storeid FROM Items_stores WHERE barcode = %s;" % barcode) return cursor.fetchall() #Modifying an item price def set_item_price(barcode,storeid,price): try: result = cursor.execute("UPDATE Items_stores SET price = %s WHERE barcode= %s AND storeid= %s;"% (price, barcode, storeid)) db.commit() except: result = 0 return result #Retrieving the lowest price of an item def get_lowest_price(barcode): cursor.execute("SELECT storeid, price FROM Items_stores WHERE barcode = %s ORDER BY price ASC ;" % barcode) return cursor.fetchone() #Retrieving the different prices for an item and its corresponding store def get_prices_stores(barcode): cursor.execute("SELECT storeid, price FROM Items_stores WHERE barcode = %s ORDER BY price ASC;" % barcode) return cursor.fetchall() #Retrieving the average price of an item def get_avgprice(barcode): cursor.execute("SELECT AVG(price) FROM Items_stores WHERE barcode = %s;" % barcode) return cursor.fetchone() #Retrieving the lowest price of an item between certain coordinates (Due to a radius) def get_nearlowestprice(barcode, latitude, longitude, radius): cursor.execute("SELECT storeid FROM Stores WHERE (latitude > %s) AND (latitude < %s) AND (longitude > %s) AND (longitude < %s);" % ((latitude-radius), (latitude+radius), (longitude-radius), (longitude+radius))) storelist = cursor.fetchall() cursor.execute("SELECT storeid, price FROM Items_stores WHERE barcode = %s ORDER BY price ;" % barcode) pricelist = cursor.fetchall() i = 0 j = 0 result = '' while i < len(pricelist): while j < len(storelist): if storelist[j][0] == pricelist[i][0]: return [str(pricelist[i][1]), str(storelist[j][0])] j += 1 i += 1 j = 0
The next files: server.py, client_server.py and client.py has a similar function to the one exposed in the main project page. Remember that the idea of client file is to test the functioning of the components. The final goal is to support an android app.
server.py
import socket, os import client_server from client_server import Client_server def socket_setup(): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = ('localhost', 10100) server.bind(server_address) server.listen(1) print "server created and configured" return server def wait_connection(server): wait_connection = True while wait_connection: print "Online and waiting for new requests" client_socket, client_address = server.accept() newproc = os.fork() if newproc == 0: wait_connection = False client_sver = Client_server(client_socket) client_sver.decide() client_sver = None print 'lost connection' os._exit(1) def main(): server = socket_setup() wait_connection(server) if __name__== "__main__": main()
client_server
import socket import DBmethods as dbm class Client_server: def __init__(self, client_socket): self.client_socket = client_socket self.ratio = 0.03 self.username = "" def __del__(self): del self.client_socket def decide(self): self.client_socket.settimeout(900) while True: try: msg = self.client_socket.recv(4096) except socket.timeout: self.client_socket.close() break instruction = [] instruction = msg.split('<>') command = instruction[0] #choose a function if command == 'printf': self.printf(instruction) elif command == 'login': self.login(instruction) elif command == 'signup': self.signup(instruction) elif command == 'storeinratio': self.storeinratio(instruction) elif command == 'addstore': self.addstore(instruction) elif command == 'submititem': self.submititem(instruction) elif command == 'edititem': self.edititem(instruction) elif command == 'newlist': self.newlist(instruction) elif command == 'delist': self.delist(instruction) elif command == 'requestlists': self.requestlists() elif command == 'addtolist': self.addtolist(instruction) elif command == 'delfromlist': self.delfromlist(instruction) elif command == 'seekitem': self.seekitem(instruction) def answer(self, answer): self.client_socket.sendall(answer) def printf(self, msg_list): print msg_list[1] self.answer("Success") def login(self, msg_list): # login<>username<>password if msg_list[2] == dbm.get_password(msg_list[1]): self.answer("login<>success") self.username = msg_list[1] else: self.answer("login<>invalid username/password combination") def signup(self, msg_list): # write_user(username, password, real name, email) status = dbm.write_user(msg_list[1], msg_list[2], msg_list[3],msg_list[4]) if status: self.answer("signup<>success") else: self.answer("signup<>invalid username") def storeinratio(self, msg_list): coordinates = msg_list[1].split("%/") #get_stores(latitude, longitude, radius) data = dbm.get_stores(float(coordinates[0]), float(coordinates[1]), self.ratio) i = 0 answer = "" while len(data) > i: answer += '<>' answer += data[i][1]+', '+data[i][2]+'%/'+str(data[i][0]) j = 1 i += 1 answer = 'storeinratio' + answer self.answer(answer) def addstore(self, msg_list): #write_store(name, location, latitude, longitude) coordinates = msg_list[3].split('%/') status = dbm.write_store(msg_list[1], msg_list[2], float(coordinates[0]), float(coordinates[1])) storeid = float(dbm.get_storeid(float(coordinates[0]), float(coordinates[1]))[0]) if status: self.answer('addstore<>success<>'+str(storeid)) else: self.answer('addstore<>data base error') def submititem(self, msg_list): # according to communication protocol submititem<>barcode<>name<>brand<>quantity<>descripton<>image<>price<>storeid # write_item(barcode, name, brand, quantity, description, image): dbm.write_item(msg_list[1], msg_list[2], msg_list[3], msg_list[4], msg_list[5], msg_list[6]) # write_item_store(barcode,storeid,price) dbm.write_item_store(msg_list[1], msg_list[8], msg_list[7]) self.answer('submititem<>success') def edititem(self, msg_list): # modify_item(barcode, name, brand, quantity, description, image) dbm.modify_item(msg_list[1], msg_list[2], msg_list[3], msg_list[4], msg_list[5], msg_list[6]) ids = dbm.get_storeid_barcode(msg_list[1]) isnew = True i = 0 while i < len(ids): if int(ids[i][0])== int(msg_list[8]): isnew = False i+=1 if isnew: dbm.write_item_store(msg_list[1], msg_list[8], msg_list[7]) else: # set_item_price(barcode,storeid,price) dbm.set_item_price(msg_list[1], msg_list[8], msg_list[7]) self.answer('submititem<>success') def newlist(self, msg_list): #write_list_user(listname,username) dbm.write_list_user(msg_list[1], self.username) self.answer('newlist<>succesful') def delist(self, msg_list): #get_listid(username, listname) listid = dbm.get_listid(self.username, msg_list[1]) #def delete_list(listid) dbm.delete_list(listid) self.answer('delist<>succesful') def requestlists(self): #get_lists(username) lists = dbm.get_lists(self.username) data = '' i = 0 while i < len(lists): data += lists[i][1] if i != (len(lists)-1): data += '%/' i += 1 message = 'requestlists<>'+data self.answer(message) def addtolist(self, msg_list): #get_listid(username, listname) listid = dbm.get_listid(self.username, msg_list[1]) #write_list_item(listid,barcode) dbm.write_list_item(listid, msg_list[2]) self.answer('addtolist<>succesful') def delfromlist(self, msg_list): #get_listid(username, listname) listid = dbm.get_listid(self.username, msg_list[1]) #delete_item(listid,barcode) dbm.delete_item(listid, msg_list[2]) self.answer('delfromlist<>succesful') def seekitem(self, msg_list): #get item information #get_item(barcode) infolist = dbm.get_item(msg_list[1]) iteminfo = '' if infolist == None: self.answer('seekitem<>notfound') return else: i = 1 while i < len(infolist): iteminfo += '<>'+infolist[i] i+=1 #get lowest price and store lowestprice = str(dbm.get_lowest_price(msg_list[1])[1]) storeid = int(dbm.get_lowest_price(msg_list[1])[0]) lowestprice_store = dbm.get_storename(storeid)[0]+', '+dbm.get_storename(storeid)[1] #get closest lower price and store #def get_nearlowestprice(barcode, latitude, longitude, radius) coordinates = msg_list[2].split('%/') closest_price = dbm.get_nearlowestprice(msg_list[1], float(coordinates[0]), float(coordinates[1]), self.ratio) closest_store = dbm.get_storename(closest_price[1])[0]+', '+dbm.get_storename(closest_price[1])[1] closest_lower = closest_price[0]+'<>'+closest_store self.answer('seekitem'+iteminfo+'<>'+lowestprice+'<>'+lowestprice_store+'<>'+closest_lower)
client.py
import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = ('localhost', 10100) print "socket created" client.connect(server_address) print "connection established, write a command" def ask_info(): info = raw_input() return info print '/n' exit = False while not exit: command = ask_info() if command == "exit": exit = True #secret command print elif command == 'print': info = ask_info() message = 'printf<>'+info client.sendall(message) print client.recv(100) #signup elif command == "signup": tmplist = ['username', 'password', 'name', 'mail'] j = 0 for i in tmplist: print i, tmplist[j] = ask_info() j += 1 info = reduce(lambda x,y: x+'<>'+y, tmplist) message = command+'<>'+info client.sendall(message) print client.recv(100) # check if the operation succeded #login elif command == "login": tmplist = ['username', 'password'] j = 0 for i in tmplist: print i, tmplist[j] = ask_info() j += 1 info = reduce(lambda x,y: x+'<>'+y, tmplist) message = command+'<>'+info client.sendall(message) print client.recv(100) #storeinratio elif command == "storeinratio": print 'latitude' latitude = ask_info() print 'longitude' longitude = ask_info() message = command+'<>'+latitude+'%/'+longitude client.sendall(message) print client.recv(100) #addstore elif command == 'addstore': print 'name' name = ask_info() print 'location' location = ask_info() print 'latitude' latitude = ask_info() print 'longitude' longitude = ask_info() message = command+'<>'+name+'<>'+location+'<>'+latitude+'%/'+longitude client.sendall(message) print client.recv(100) #submit item elif command == 'submititem': print 'introduce: barcode<>name<>brand<>quantity<>descripton<>image<>price<>storeid' data = ask_info() message = 'submititem<>'+data client.sendall(message) print client.recv(100) #edit item elif command == 'edititem': print 'introduce: barcode<>name<>brand<>quantity<>descripton<>image<>price<>storeid' data = ask_info() message = 'edititem<>'+data client.sendall(message) print client.recv(100) #new list elif command == 'newlist': print 'introduce: list name' data = ask_info() message = 'newlist<>'+data client.sendall(message) print client.recv(100) #delete list elif command == 'delist': print 'introduce: list name' data = ask_info() message = 'delist<>'+data client.sendall(message) print client.recv(100) #request lists elif command == 'requestlists': client.sendall('requestlists') print client.recv(100) # add item to list elif command == 'addtolist': print 'introduce: listname<>barcode' data = ask_info() message = 'addtolist<>'+data client.sendall(message) print client.recv(100) #delete item from list elif command == 'delfromlist': print 'introduce: listname<>barcode' data = ask_info() message = 'delfromlist<>'+data client.sendall(message) print client.recv(100) #seek item elif command == 'seekitem': print 'introduce: barcode<>latitude%/logitude' data = ask_info() message = 'seekitem<>'+data client.sendall(message) print client.recv(4096)
Finally the next file present the Way to Shop function algorithms. The ones that allow the server to generate an optimized route for a shopping list.
wts_algorithms
#this is pseudo-code #these are the route generation and optimization algorithms for Way To Shop #miscellaneous functions #this function distributes the items between the stores, according with their position #in storelist def assignitems(itemlist, storelist): storedic = {} for storeid in storelist: storedic[storeid] = 0 for storeid in storelist: temp = '' price = 0.0 if len(itemlist) == 0: break for itemN in itemlist: if match(itemN, storeid): temp += name(itemN) price += price(storeid, itemN) itemlist.remove(itemN) storedic[storeid] = temp+str(price) return storedic #this function sort the storeid according with nearest neighbour algorithm (http://en.wikipedia.org/wiki/Nearest_neighbour_algorithm) def sortdistance(initposition, storelist): improvedlist = [] position = initposition while len(storelist) > 0: templist = [] for storeid in storeidlist: dist = calcdist(position, position(storeid)) templist.append((storeid, dist)) templist = sorted(templist, key=lambda x:x[1]) improvedlist.append(templist[0][0]) storelist.remove(templist[0][0]) position = position(templist[0][0]) return improvedlist #Function to organize the stores from cheaper to most expensive def savemymoney(itemlist, storelist): storepoints = {} for storeid in storelist: storepoints[storeid] = 0 for itemN in itemlist: lowest = (0, float('inf') for storeid in storelist: if match(itemN, storeid): newprice = price(itemN, storeid) if newprice < lowest[1]: lowest = (storeid, newprice) storepoints[lowest[0]) += 1 templist = storepoints.items() templist = sorted(templist, key=lambda x:x[1]) storelist = [storeid[0] for storeid in templist] assignedlist = assignitems(itemlist, storelist) storelist = sortdistance(initposition, assignedlist.keys()) message = '' for storeid in storelist: message += name(storelist)+assignedlist[storeid] #Function to organize the stores according with amount of item on it def savemytime(itemlist, storelist): storepoints = [] for storeid in storelist: points = 0 for itemN in itemlist: if match(itemN, storeid): points += 1 storepoints.append((storeid, points)) storepoints = sorted(storepoints, key=lambda x:x[1]) storelist = [storeid[0] for storeid in storepoints] assignedlist = assignitems(itemlist, storelist) storelist = sortdistance(initposition, assignedlist.keys()] message = "" for storeid in storelist: message += name(storeid) + assignedlist[storeid]