import helper,gnugo import pgdb,sys,time DEBUG = 1 dbusername="webgouser" dbpassword="webgopassword" dbname="webgo" #pgdb.connect(connect_string) -> connection #connect_string = 'host:database:user:password:opt:tty' connect_string='localhost:'+dbname+':'+dbusername+':'+dbpassword db=pgdb.connect(connect_string) ################# table creation and removal ####################################################################### def create_table(name,layout=""): """ create_table(name:string, layout:string) returns name if successfull, None if not. simple function to create a table. the function itself would just create an empty table with the command 'CREATE TABLE ();'. The real layout is given to the function as an argument of type string. This string contains all column declarations in SQL syntax: "var1 real, var2 int" name is the name of the table """ executestring = "CREATE TABLE %s ( %s );" % (name,layout) sql_one_liner(executestring) def create_goban_table(player1,player2,size,description=""): """ gets:player1, player2, size of goban. creates postgresql table containing goban data. returns: name of created table. the table looks like this: line x1 turn_number size name description player1 player2 sgf created lastmove and the meaning of these fields: (turn_number,x1) is the current turn, (size,x1) is the length of a side of the goban, (name,x1) is the name of this goban. (description,x1) is the user-given name of this goban. (player1,x1) is the name of one player. (player2,x1) is the name of the other player. (sgf,x1) contains a sgf file with the current board. (created,x1) is the time of creation of the table (lastmove,x1) is the time of the last player move """ tablename = helper.generate_game_name() data="line text, x1 text" create_table(tablename,data) #now insert additional variables insert_into_table(tablename,strtuple("turn_number","1")) #size of goban insert_into_table(tablename,strtuple("size",size)) #name of goban (=name of table in database) insert_into_table(tablename,strtuple("name",tablename)) #description of goban (=user-given name) insert_into_table(tablename,strtuple("description",description)) #name of player1 insert_into_table(tablename,strtuple("player1",player1)) #name of player2 insert_into_table(tablename,strtuple("player2",player2)) #empty sgf file as string sgf = gnugo.create_sgf_file(size) insert_into_table(tablename,strtuple("sgf",sgf)) #time of creation insert_into_table(tablename,strtuple("created",str(int(time.time())))) #time of last move insert_into_table(tablename,strtuple("lastmove",str(int(time.time())))) return tablename def strtuple(s1,s2): """ creating a string looking like a tuple. gets 2 strings. useful for inserting something into a table. """ tmplist = [] tmplist.append(s1) tmplist.append(s2) return str(tuple(tmplist)) def create_user_table(): """ creates a table named users with following columns: name - name of user password - passsword of user game1 - the 10 game slots of this user contain names ... of goban tables game10 sessionid - id of current session timeout - when does session time out? """ data = "username varchar(15)" data += ", password text" for i in range(1,11): data += ", game"+str(i)+" text" data += ", sessionid text" data += ", timeout int" create_table("users",data) def drop_table(name): """ gets: name of table. executes DROP TABLE """ executestring = "DROP TABLE %s;" % (name) sql_one_liner(executestring) ################# generic functions ############################################################################ def insert_into_table(table, content): """ gets the name of a table and a content string. executes INSERT INTO name VALUES content; """ executestring = "INSERT INTO %s VALUES %s" % (table,content) sql_one_liner(executestring) def sql_one_liner(data): """ gets:SQL statement creates a cursor, executes , closes cursor. """ cursor=db.cursor() cursor.execute(data) # Commit the changes db.commit() cursor.close() def read_table(table): """ gets the name of a table, does a SELECT * FROM table; returns output. """ cursor=db.cursor() data="SELECT * FROM %s;" % (table) cursor.execute(data) # Commit the changes db.commit() ret = cursor.fetchall() cursor.close() return ret def update_database_field(table,column,new_value,uniqname,uniqvalue): """ wrapper for SQL UPDATE. gets: table name name of column containing field to be updated new value of field in column name of unique identifier and value of unique identifier for field (e.g. 'username' and 'testuser') """ if new_value == "": executestring ="UPDATE %s SET %s = DEFAULT WHERE %s = '%s'" % (table,column,uniqname,uniqvalue) else: executestring ="UPDATE %s SET %s = '%s' WHERE %s = '%s'" % (table,column,new_value,uniqname,uniqvalue) sql_one_liner(executestring) ################# access of users table ##################################################################### def get_user_game_list(name): """ gets a username, returns the list of games for user. """ cursor=db.cursor() ret = [] for x in range(1,11): data="SELECT game%s FROM users WHERE username = '%s'" % (x,name) try: cursor.execute(data) # Commit the changes db.commit() ret.append(cursor.fetchone()[0]) #[0], because return is a list except: ret = "could not get info of all games -- table corrupt?" cursor.close() return ret def get_user_info(name,infotype): """ gets the name of a user and the type of requested info. returns info from database. """ cursor=db.cursor() if infotype in ("password","sessionid","timeout"): data="SELECT %s FROM users WHERE username = '%s'" % (infotype,name) try: cursor.execute(data) # Commit the changes db.commit() ret = cursor.fetchone()[0] except: ret = "no such user" cursor.close() else: ret = "Are your sure about the infotype?" return ret def set_user_sessionid(username,sessionid): """ gets username and sessionid, writes sessid into database """ update_users_table_field(username,"sessionid",sessionid) def set_user_timeout(username,timeout=None): """ gets username, sets timeout to time.time + 30min """ import time if timeout == None: timeout = int(time.time()) + 900 #current time in seconds + seconds for session update_users_table_field(username,"timeout",timeout) def update_users_table_field(username,column,new_value): """ gets: username,column name, new content for field in column. executes an update_database_field with uniqname = "username" """ update_database_field("users",column,new_value,"username",username) def delete_user(username): """ gets username. deletes user from database. """ #TODO: delete all games of user before delting user? executestring ="DELETE FROM users WHERE username='%s'" %(username) sql_one_liner(executestring) return executestring def add_webgo_user(name,password): """ adds a database entry for a user. gets: username and password """ #size of goban tmplist=[] tmplist.append(name) tmplist.append(password) insert_into_table("users",str(tuple(tmplist))) def get_users_with_free_game_slots(): """ gets nothing. returns a list of all users who have at least one game slot free. """ cursor=db.cursor() data = """select username from users where (game1 IS NULL) OR (game2 IS NULL) OR (game3 IS NULL) OR (game4 IS NULL) OR (game5 IS NULL) OR (game6 IS NULL) OR (game7 IS NULL) OR (game8 IS NULL) OR (game9 IS NULL) OR (game10 IS NULL)""" cursor.execute(data) # Commit the changes db.commit() tmplist = cursor.fetchall() ret = [item[0] for item in tmplist] return ret def get_free_game_slot(username): """ gets a username returns the name of a free game slot or "" if none found. """ ret = "" for i in range(1,11): cursor=db.cursor() data = "SELECT username FROM users WHERE username='%s' AND game%i IS NULL" % (username,i) cursor.execute(data) # Commit the changes db.commit() tmp = [item[0] for item in cursor.fetchall()] if (tmp != []): ret = "game"+str(i) return ret def set_game_slot(username,gameslot,gamename): """ gets username,game slot,game name. sets the game slot for user username to game name ;> """ if (gamename == "") or (gamename == None) or (gamename == "NULL") : executestring ="UPDATE users SET %s = DEFAULT WHERE username = '%s'" %(gameslot, username) else: executestring ="UPDATE users SET %s = '%s' WHERE username = '%s'" %(gameslot,gamename, username) sql_one_liner(executestring) ################# access of goban tables #################################################################### def get_players_for_game(tablename): """ gets the name of a goban table, returns player1 and player2 as tuple. """ cursor=db.cursor() data="select x1 from %s where line='player1' OR line='player2';" % (tablename) cursor.execute(data) # Commit the changes db.commit() players = [item[0] for item in cursor.fetchall()] cursor.close() return tuple(players) def update_goban_table_field(table,column,line,new_value): """ gets: table name, column name, line name, new content for field. executes an update_database_field with uniqname = "line" """ update_database_field(table,column,new_value,"line",line) def update_turn_number(table,new_number): """ gets: name of table,new turn number modifies 'turn_number' in table """ update_goban_table_field(table,"x1","turn_number",new_number) def get_sgf(table): """ gets a table name, returns content of "sgf" field. """ cursor=db.cursor() data="select x1 from %s where line='sgf';" % (table) cursor.execute(data) # Commit the changes db.commit() sgf = cursor.fetchone()[0] cursor.close() return sgf def get_description(table): """ gets table name, returns content of "description" field. """ cursor=db.cursor() data="select x1 from %s where line='description';" % (table) cursor.execute(data) # Commit the changes db.commit() sgf = cursor.fetchone()[0] cursor.close() return sgf def fetchall_list_to_goban_dict(list): """ gets the output from read_table (a list), returns a goban dictionary. """ #create dictionary ret = {} #get size of goban for item in list: if item[0] == "size": size=int(item[1]) ret["size"] = size #populate dictionary with goban field for item in list: if item[0][0] == "y": #goban fields #get current y coordinate y = int(item[0][1:]) #fill dictionary for current y coordinate for x in range(1,size+1): ret[(x,y)]=helper.check_for_int(item[x]) else: #other variables ret[item[0]]=helper.check_for_int(item[1]) return ret def get_time(table,whichtime): """ gets: - a table name, - a string equal "created" or "lastmove". returns either the time of creation or the time of the last player move for the table, depending of whichtime. """ cursor=db.cursor() data="select x1 from %s where line='%s';" % (table,whichtime) cursor.execute(data) # Commit the changes db.commit() try: time = int(cursor.fetchone()[0]) except: time = None cursor.close() return time def set_time(tablename): """ gets name of goban table, sets lastmove to current time. """ update_goban_table_field(tablename,"x1","lastmove",int(time.time())) def test(): #create_table("test") drop_table("test") create_goban_table(9) update_goban_table_field("test","x1","turn_number",4) list = read_table("test") print list dict = fetchall_list_to_goban_dict(list) print dict print dict["turn_number"] print dict["name"] print type(dict["turn_number"]) #test()