From 6474c7f47c6509b903c7216e9e967287164e9147 Mon Sep 17 00:00:00 2001 From: phear Date: Wed, 23 Nov 2005 17:34:20 +0000 Subject: [PATCH] changed database backend to SqlObject. currently unusable until some bugs are fixed. --- createaccount.py | 5 +- database.py | 184 +++++++++++++++++++++++++++++++++++++++++++++++ deletegame.py | 25 ++----- filehandling.py | 25 ++++++- gamecreation.py | 15 ++-- goban.py | 59 +++------------ init_webgo.py | 6 +- login.py | 28 ++++---- logout.py | 13 ++++ main.py | 50 ++++++++----- playgame.py | 21 +++--- 11 files changed, 308 insertions(+), 123 deletions(-) create mode 100644 database.py create mode 100644 logout.py diff --git a/createaccount.py b/createaccount.py index 23e0215..31d93b3 100644 --- a/createaccount.py +++ b/createaccount.py @@ -1,4 +1,4 @@ -import helper,psql +import helper,database maxuser = 1000 @@ -42,7 +42,8 @@ def process_form(req,form): except: username = "" if (username != "") and (password1 != "") and (password2 != "") and (password1 == password2): - psql.add_webgo_user(username,password1) + newuser = database.Users(username=username,password=password1) + #.add_webgo_user(username,password1) req.write("User %s has been successfully created. Click the following button to login:
" % username) data = """
diff --git a/database.py b/database.py new file mode 100644 index 0000000..ac1ca5f --- /dev/null +++ b/database.py @@ -0,0 +1,184 @@ +#apt-get install python-sqlobject python-psycopg +from sqlobject import * + +import sys, os, time +import gnugo, helper + + + + + +#account and database name +dbname = "/home/mtsrc/daten/projekte/webgo/webgo.sqlite" +#dbname = "/tmp/webgo.sqlite" +dbdebug = "debug=t&debugOutput=t" #don't want SQL debug messages? just change to an empty string: "debug=" +#dbdebug = "debug=" + +#build connection string and connect +connection_string='sqlite:%s?%s' %(dbname,dbdebug) +connection=connectionForURI(connection_string) +__connection__ = connection + +class GobanTable(SQLObject): + """ + Abstract: + A GobanTable instance contains all data of a current goban: players, board etc. + + Details: The table looks like this: + + player1 + player2 + turn_number + size + name + description + sgf + created + lastmove + """ + player1 = StringCol() + player2 = StringCol() + size = IntCol() + name = StringCol(default = helper.generate_game_name(), unique=True,notNone=True,alternateID=True) + turn_number = 1 + description = StringCol(default=None) + sgf = gnugo.create_sgf_file(size) + created = int(time.time()) + lastmove = int(time.time()) + + def players(self): + """returns both player names as a tuple""" + return (self.player1,self.player2) + + def set_time(self): + """updates self.lastmove to current time""" + self.lastmove = int(time.time) + +#create table which has been defined above: +# if ifNotExists=True, then an existing table does not get overridden. +GobanTable.createTable(ifNotExists=True) + + +# add a game to goban table +gob = GobanTable(player1="gast",player2="gast",size=9) + + + +class Users(SQLObject): + """ + 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? + """ + username = StringCol(unique=True,notNone=True,alternateID=True) + password = StringCol() + game1 = StringCol(default=None) + game2 = StringCol(default=None) + game3 = StringCol(default=None) + game4 = StringCol(default=None) + game5 = StringCol(default=None) + game6 = StringCol(default=None) + game7 = StringCol(default=None) + game8 = StringCol(default=None) + game9 = StringCol(default=None) + game10 = StringCol(default=None) + sessionid = StringCol(default=None) + timeout = IntCol(default=None) + + def gamelist(self): + """ + return the list of all games of the given user. + """ + #TODO: how to generate this list automatically? + ret = [] + ret.append(self.game1) + ret.append(self.game2) + ret.append(self.game3) + ret.append(self.game4) + ret.append(self.game5) + ret.append(self.game6) + ret.append(self.game7) + ret.append(self.game8) + ret.append(self.game9) + ret.append(self.game10) + return ret + + def removegame(self,gamename): + """removes a game whose name is given.""" + if self.game1 == gamename: self.game1=None + if self.game2 == gamename: self.game2=None + if self.game3 == gamename: self.game3=None + if self.game4 == gamename: self.game4=None + if self.game5 == gamename: self.game5=None + if self.game6 == gamename: self.game6=None + if self.game7 == gamename: self.game7=None + if self.game8 == gamename: self.game8=None + if self.game9 == gamename: self.game9=None + if self.game10 == gamename: self.game10=None + + def free_slot_left(self): + """Returns True, if there is an empty game slot left, else returns False.""" + if self.game1 == None: return True + elif self.game2 == None: return True + elif self.game3 == None: return True + elif self.game4 == None: return True + elif self.game5 == None: return True + elif self.game6 == None: return True + elif self.game7 == None: return True + elif self.game8 == None: return True + elif self.game9 == None: return True + elif self.game10 == None: return True + else: return False + + def add_game(self,gamename): + """saves the game name into an empty slot""" + if self.game1 == None: self.game1 = gamename + elif self.game2 == None: self.game1 = gamename + elif self.game3 == None: self.game1 = gamename + elif self.game4 == None: self.game1 = gamename + elif self.game5 == None: self.game1 = gamename + elif self.game6 == None: self.game1 = gamename + elif self.game7 == None: self.game1 = gamename + elif self.game8 == None: self.game1 = gamename + elif self.game9 == None: self.game1 = gamename + elif self.game10 == None: self.game1 = gamename + else: return False + + def set_timeout(self): + self.timeout = int(time.time()) + 900 #current time in seconds + seconds for session + +def get_users_with_free_game_slots(): + """ + returns a list of users who have at least one empty game slot """ + idlist = Users.select(Users.q.free_slot_left == True) + retlist = [] + for entry in idlist: + retlist.append(Users.get(entry).username) + return retlist + + +#create table which has been defined above: +# if ifNotExists=True, then an existing table does not get overridden. +Users.createTable(ifNotExists=True) +if __name__ == "__main__": + connection_string='sqlite:%s?%s' %(os.path.abspath("webgo.sqlite"),dbdebug) + connection=connectionForURI(connection_string) + __connection__ = connection + + # add a game to goban table + user = Users(username="gast",password="gast") + #print user.gamelist() + print user.sessionid + user.sessionid=1 + print user.sessionid + + #print Users.byUsername("gast") + +#deleting a row: +#f = MyObject(1) +#f.destroySelf() \ No newline at end of file diff --git a/deletegame.py b/deletegame.py index 8dea3c2..23bd88d 100644 --- a/deletegame.py +++ b/deletegame.py @@ -1,19 +1,7 @@ -import psql,login,helper +import login,helper,database #helper = apache.import_module("helper") -def get_game_slot_of_game(player, gamename): - """ - gets playername and game name, - searches through the game slots and returns the game slot used by the game. - """ - slotlist = psql.get_user_game_list(player) - ret = "" - for i in range(0,len(slotlist)): - if slotlist[i] == gamename: - ret = "game" + str(i+1) - return ret - def main(req,form): """ get request,util.FieldStorage. @@ -27,16 +15,15 @@ def main(req,form): gamename = "" if gamename != "": #get player names from game table in database - players = psql.get_players_for_game(gamename) + mygame=database.GobanTable.byName(gamename) + players = mygame.players() #free game slots of players for player in players: - gameslot = get_game_slot_of_game(player,gamename) - helper.debug(req,form,"delete: got %s as gameslot." % gameslot) - if gameslot != "": - psql.set_game_slot(player,gameslot,"") + myuser = database.Users.byUsername(player) + myuser.removegame(gamename) #delete table - psql.drop_table(gamename) + mygame.destroySelf() #now display game overview form. login.game_overview_form(req,form) diff --git a/filehandling.py b/filehandling.py index f6b5697..71e1e41 100644 --- a/filehandling.py +++ b/filehandling.py @@ -1,6 +1,29 @@ -import os,tempfile,dircache,string,commands +import ConfigParser,os,tempfile,dircache,string,commands + +configname="webgo.conf" +def read_config(location=None): + + config = ConfigParser.ConfigParser() + if location != None: + # location of file was given on command line + try: + config.readfp(open(location)) + except: + #TODO: debug-awareness + print "(EE)[%s]: cannot open %s!"%(__name__,location) + else: + #use default config from . or /etc + try: + config.readfp(open('/etc/'+configname)) + except: + try: + config.readfp(open(configname)) + except: + #TODO: debug-awareness + print "(EE)[%s]: cannot open %s in ./ or /etc/!"%(__name__,location) + return config def read_file(filename): """ diff --git a/gamecreation.py b/gamecreation.py index b52b77b..4113327 100644 --- a/gamecreation.py +++ b/gamecreation.py @@ -1,5 +1,5 @@ from mod_python import * -import psql,helper,login +import helper,login,database def display_game_creation_form(req,form): @@ -40,6 +40,8 @@ def process_creation_form(req,form): """ validates and processes the game creation form. If everything was ok, a game will be created. + TODO: change this function, so that the original database state canbe + restored, if for example one of the users does not have a free game slot. """ player1 = form["player1"] player2 = form["player2"] @@ -53,12 +55,13 @@ def process_creation_form(req,form): #check if at least one of the players is the current user if (player1 == username) or (player2 == username): #create game - gamename = psql.create_goban_table(player1,player2,int(form["gobansize"]),description) + mygame = database.GobanTable(player1=player1,player2=player2,size=int(form["gobansize"]),description = description) + gamename = mygame.name #update entries for player one and player two for player in [player1,player2]: - gameslot = psql.get_free_game_slot(player) - if gameslot != "": - psql.set_game_slot(player,gameslot,gamename) + myplayer = database.Users.byUsername(player) + if myplayer.free_slot_left: + myplayer.add_game(gamename) else:#should not happen: no free game slot. #print error msg req.write("Error: No free game slots for player "+player+"!") @@ -77,7 +80,7 @@ def create_user_dropdown_list(listname,selected = ""): gets a name for the generated list and, optionally, the preselected value. returns a ' % listname for item in userlist: #check whether current item = item for preselection diff --git a/goban.py b/goban.py index 438344d..14f9924 100755 --- a/goban.py +++ b/goban.py @@ -4,7 +4,7 @@ DEBUG = 1 import sys,string import cgi -import psql,helper,gnugo +import helper,gnugo,database picklefile = "goban.pickledump" @@ -30,7 +30,9 @@ def display_goban(goban,req,form): """ % (form["sessionid"],form["username"],form["game"]) - sgf = psql.get_sgf(form["game"]) + #TODO: check form[game] before the following asignment + mygame = database.GobanTable.byName(form["game"]) + sgf = mygame.sgf helper.debug(req,form,sgf) gobandict = gnugo.parse_static_gnugo_sgf(sgf) @@ -133,58 +135,13 @@ def set_stone(gobandict, position,req,form): #let gnugo make the above move, let gnugo write move to file new_sgf = gnugo.make_move_in_sgf(req,form,gobandict,position) #write new sgf file into database - psql.update_goban_table_field(name,"x1","sgf",new_sgf) - psql.update_turn_number(name,turn+1) - psql.set_time(name) + mygame = database.GobanTable.byName(name) + mygame.sgf = new_sgf + mygame.turn_number = turn + 1 + mygame.set_time() return "" else: #move not ok return "This is not a legal move (says Gnugo)." else: #position not empty return "Could not make move: Field not empty." -def update_goban_dict_and_table(gobandict,gobanlite): - """ - gets a gobandict and a gobdict light (just coordinates and size). - updates the fields in gobandict and database. - returns changed gobandict and True (or False) if something has been changed (or not). - """ - tf = False - for key in gobanlite.keys(): - if gobandict[key] != gobanlite[key]: - #found difference in dicts. - #update gobandict - gobandict[key] = gobanlite[key] - #update databse table. the only valid difference can be changed goban field positions. - psql.update_goban_field(gobandict["name"],key[0],key[1],gobandict[key]) - tf = True - return gobandict,tf - - - -############################################################################### - -def main(req,form): - """# Print the required header that tells the browser how to render the text. - #(currently done by error logger) - #print "Content-Type: text/plain\n\n" - gamename = form["game"] - #do stuff - data = helper.header() - - #read goban table from database - tmplist = psql.read_table(gamename) - #make a dictionary out of the list - goban = psql.fetchall_list_to_goban_dict(tmplist) - #print goban - - (goban,retstring) = process_form(goban) - data += "

Turn number: %s, %s Player's Move.

" % (goban["turn_number"],("White","Black")[goban["turn_number"] % 2]) #eleet ;> - data += display_goban(goban) - if retstring != "": - data +="\n

"+retstring+"

\n" - - - data += helper.footer(req,form) - print data - """ - \ No newline at end of file diff --git a/init_webgo.py b/init_webgo.py index 18e2e7b..55c8896 100755 --- a/init_webgo.py +++ b/init_webgo.py @@ -1,14 +1,14 @@ -import psql +import database def clear(): try: - psql.drop_table("users") + database.Users.dropTable(ifExists=True) except: pass def create(): + database.Users.createTable(ifExists = False) #psql.create_goban_table("gast","gast2",9) - psql.create_user_table() #psql.add_webgo_user("gast","gast") #psql.add_webgo_user("gast2","gast2") diff --git a/login.py b/login.py index acb4e61..334321b 100755 --- a/login.py +++ b/login.py @@ -1,4 +1,4 @@ -import psql,init_webgo,helper,gamecreation +import database,init_webgo,helper,gamecreation from sets import Set as set from mod_python import * @@ -11,17 +11,19 @@ def process_form(req,form): if ("username" in form.keys()) and ("password" in form.keys()): #extract name and password username = form["username"] + myuser = database.Users.byUsername(username) password = form["password"] sessionid = form["sessionid"] - origpassword = psql.get_user_info(username,"password") + + origpassword = myuser.password #debug: helper.debug(req,form,'
--password:'+str(password)+' ---origpassword:'+str(origpassword)+'
') #check if user exists (else we would get an error string) if origpassword != "no such user": #no error message, now check password if password == origpassword: #login accepted - psql.set_user_sessionid(username,sessionid) - psql.set_user_timeout(username) + myuser.sessionid = sessionid + myser.set_timeout() #now display list of games. game_overview_form(req,form) else: @@ -48,7 +50,7 @@ def game_overview_form(req,form):

Current Games:

""" - gamelist = psql.get_user_game_list(username) + gamelist = myuser.gamelist() #debug helper.debug(req,form,str(gamelist)+"
\n") #display list of current games @@ -65,15 +67,16 @@ def game_overview_form(req,form): tmp += '\n' % username tmp += '\n' % item tmp += '\n' - description = psql.get_description(item) + mygame = database.GobanTable.byName(item) + description = mygame.description if (description == None) or (description == "None") or (description == ""): description = item tmp += '%s\n' % description - players = psql.get_players_for_game(item) + players = mygame.players() tmp += '%s\n' % players[0] tmp += '%s\n' % players[1] - tmp += '%s\n' % helper.format_time(psql.get_time(item,"created")) - tmp += '%s\n' % helper.format_time(psql.get_time(item,"lastmove")) + tmp += '%s\n' % helper.format_time(mygame.created) + tmp += '%s\n' % helper.format_time(mygame.lastmove) tmp += '\n' tmp += '
\n' if helper.clean_list(gamelist) != []: @@ -153,9 +156,10 @@ def logout(req,form): reads username from form and clears timeout and sessionid from users table. """ username = form["username"] - psql.set_user_sessionid(username,"") - psql.set_user_timeout(username,"") - + myuser = database.Users.byUsername(username) + myuser.sessionid = "" + myuser.timeout = 0 + def main(req,form): #debug diff --git a/logout.py b/logout.py new file mode 100644 index 0000000..5949eac --- /dev/null +++ b/logout.py @@ -0,0 +1,13 @@ +import database +import login + +def process_form(req,form): + username = form["username"] + myuser = database.Users.byUsername(username) + myuser.sessionid = None + + login.main(req,form) + + +def main(req,form): + process_form(req,form) \ No newline at end of file diff --git a/main.py b/main.py index 2ca446a..fe5f512 100755 --- a/main.py +++ b/main.py @@ -1,5 +1,5 @@ import sys, traceback,string,time -import init_webgo,psql +import init_webgo,database from mod_python import * @@ -24,33 +24,45 @@ def handler(req): sessionid="" username="" - #if sessionid=sesssionid and time < timeout: - # set_timeout - if (psql.get_user_info(username,'timeout') > int(time.time())) and (sessionid == psql.get_user_info(username,'sessionid')): - psql.set_user_timeout(username) - if "create" in form.keys(): - gamecreation = apache.import_module("gamecreation") - gamecreation.main(req,form) - elif "delete" in form.keys(): - deletegame = apache.import_module("deletegame") - deletegame.main(req,form) - elif ("play" in form.keys()) or ("refresh" in form.keys()): - playgame = apache.import_module("playgame") - playgame.main(req,form) - elif "logout" in form.keys(): - logout = apache.import_module("logout") - logout.main(req,form) + try: + myuser = database.Users.byUsername(username) + valid_user = True + except: + #no such user + valid_user = False + + if username != "" and valid_user: + if (myuser.timeout > int(time.time())) and (sessionid == myuser.sessionid): + myuser.set_timeout() + + if "create" in form.keys(): + gamecreation = apache.import_module("gamecreation") + gamecreation.main(req,form) + elif "delete" in form.keys(): + deletegame = apache.import_module("deletegame") + deletegame.main(req,form) + elif ("play" in form.keys()) or ("refresh" in form.keys()): + playgame = apache.import_module("playgame") + playgame.main(req,form) + elif "logout" in form.keys(): + logout = apache.import_module("logout") + logout.main(req,form) + else: + #call login.py + login = apache.import_module("login") + login.main(req,form) else: #call login.py login = apache.import_module("login") login.main(req,form) else: if "createaccount" in form.keys(): - createaccount = apache.import_module("createaccount") - createaccount.main(req,form) + createaccount = apache.import_module("createaccount") + createaccount.main(req,form) else:#call login.py login = apache.import_module("login") login.main(req,form) + return apache.OK except: diff --git a/playgame.py b/playgame.py index c1cbc70..edeee15 100644 --- a/playgame.py +++ b/playgame.py @@ -1,4 +1,4 @@ -import goban,helper,psql,login,gnugo +import goban,helper,database,login,gnugo import string DEBUG = 1 @@ -26,14 +26,15 @@ def create_gobandict(req,form,gamename): loads sgf, transforms it to dict, writes stuff like player names to dict returns dict """ - #read goban table from database - tmplist = psql.read_table(gamename) - #make a dictionary out of the list - tmpdict = psql.fetchall_list_to_goban_dict(tmplist) - sgf = psql.get_sgf(gamename) + #read goban sgf from database + mygame = database.GobanTable.byName(gamename) + sgf = mygame.sgf gobandict = gnugo.parse_static_gnugo_sgf(sgf) - for key in ["player1","player2","turn_number","name","sgf"]: - gobandict[key] = tmpdict[key] + gobandict["player1"] = mygame.player1 + gobandict["player2"] = mygame.player2 + gobandict["turn_number"] = mygame.turn_number + gobandict["name"] = mygame.name + gobandict["sgf"] = sgf return gobandict def main(req,form): @@ -67,7 +68,7 @@ def main(req,form): gobandict = create_gobandict(req,form,gamename) else: - helper.debug(req,form,"its not my turn.") + helper.debug(req,form,"it's not my turn.") data += """
Turn number: %s. %s plays.\n """ % (str(gobandict["turn_number"]), (string.capitalize(gobandict["play"]))) @@ -75,7 +76,7 @@ def main(req,form): #if yes: print 'your move' and display goban and process move #if not: print '...s move' and display goban. if is_my_turn(req,form,gobandict): - data += "
Its your turn.
\n" + data += "
It's your turn.
\n" else: data += "
This is not your turn. You have to wait for the move of the other player.
\n" #print goban