diff --git a/database.py b/database.py index d5ed7df..64c32d2 100644 --- a/database.py +++ b/database.py @@ -12,7 +12,7 @@ import gnugo, helper 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=" +dbdebug = "debug=" #build connection string and connect connection_string='sqlite:%s?%s' %(dbname,dbdebug) @@ -41,7 +41,7 @@ class GobanTable(SQLObject): size = IntCol() turn_number = IntCol(default=1) description = StringCol(default=None) - sgf = StringCol(default=gnugo.create_sgf_file(size)) + sgf = StringCol(default=None) created = IntCol(default=int(time.time())) lastmove = IntCol(default=int(time.time())) @@ -53,12 +53,15 @@ class GobanTable(SQLObject): def set_time(self): """updates self.lastmove to current time""" self.lastmove = int(time.time()) + + def create_sgf(self): + """create an empty sgf file and safe it as a string in self.sgf.""" + self.sgf = gnugo.create_sgf_file(self.size) - class Users(SQLObject): """ creates a table named users with following columns: diff --git a/default.css b/default.css index 1e9ac56..c96f87a 100644 --- a/default.css +++ b/default.css @@ -132,6 +132,10 @@ input.submit:hover { } /* The Board--------------------------------------------------------------------------- --------------------------------- */ +#board{ + padding-top:30px; +} + #board a, a:link, a:visited { border: none; } diff --git a/gamecreation.py b/gamecreation.py index 2686b0f..206d274 100644 --- a/gamecreation.py +++ b/gamecreation.py @@ -85,6 +85,8 @@ class GameCreation: if (player1 == username) or (player2 == username): #create game mygame = database.GobanTable(player1=player1,player2=player2,size=gobansize,description = description) + #I don't know how to do create_sgf during creation of the column, so it has to be called explicitly. + mygame.create_sgf() gamename = mygame.id #update entries for player one and player two for player in [player1,player2]: diff --git a/gnugo.py b/gnugo.py index d13ec62..76e7ea0 100644 --- a/gnugo.py +++ b/gnugo.py @@ -155,7 +155,7 @@ def is_legal(gobandict,coords): tests wether proposed move is legal. returns True or False. """ - """size = gobandict["size"] + """ turn = gobandict["turn_number"] #who's turn is it? color = ["white","black"][turn % 2] #even turn: white plays, else black plays @@ -182,7 +182,7 @@ def create_sgf_file(size, filename=""): returns the content of an empty sgf file. """ conn = GTP_connection(gnugocommand) - result = conn.exec_cmd("boardsize "+str(size)) + result = conn.exec_cmd("boardsize %s" % str(size)) if filename == "": filename = filehandling.gen_temp_file() result = conn.exec_cmd("printsgf "+filename) @@ -199,16 +199,11 @@ def make_move_in_sgf(gobandict,coords,filename = ""): returns: sgf string of new file. """ size = gobandict["size"] - turn = gobandict["turn_number"] sgf = gobandict["sgf"] #convert given coordinates gnucoords = " " + helper.dict_coords_to_gnugo_coords(coords,size) # get current player - #even turn: white plays, else its blacks turn - """ - color = ["white","black"][turn % 2] - """ color = gobandict["play"] #generate tmpfile if filename == "": @@ -232,9 +227,7 @@ def parse_static_gnugo_sgf(s): """ gets a string containing the data saved by the gnugo "printsgf" order. """ - - - #dicitonary to return + #dictionary to return ret = {} #removing newlines vom given string diff --git a/login.py b/login.py index 13808fc..c9c62be 100755 --- a/login.py +++ b/login.py @@ -6,36 +6,7 @@ from cherrypy.lib import httptools -""" -def navigation_bar(req,form): - "" " - gets request object and util.FieldStorage form. - writes the following to req: - - a button to return to the game overview - - a logout button - returns string - " "" - username = form["username"] - sessionid = form["sessionid"] - game = form["game"] - #TODO: buttons - data=" "" -
- - - - - - -
- "" " % (username,sessionid,game) - return(data) - - - - -""" class Login: def index(self,username=None,password=None): """ @@ -108,40 +79,46 @@ class Overview: else: return helper.cs_render("templates/not_logged_in.cs") - def game_overview_form(self,username): + def game_overview_form(self,username=None): """ gets:name of user, prints a form with the option to select,create and delete games. """ - myuser = database.Users.byUsername(username) - - gamelist = myuser.gamelist() - - settings = {} - - cleanlist = helper.clean_list(gamelist) - #display list of current games - counter = 10 - len(cleanlist) - settings["Data.Counter"] = counter - settings["Data.Gamelist"] = cleanlist - tmp = "" - if cleanlist != []: - settings["Data.GamelistNotEmpty"] = 1 + try: + myuser = database.Users.byUsername(username) + user = True + except: + user = False + if username != "" and user: + gamelist = myuser.gamelist() + + settings = {} + + cleanlist = helper.clean_list(gamelist) + #display list of current games + counter = 10 - len(cleanlist) + settings["Data.Counter"] = counter + settings["Data.Gamelist"] = cleanlist + tmp = "" + if cleanlist != []: + settings["Data.GamelistNotEmpty"] = 1 + else: + settings["Data.GamelistNotEmpty"] = 0 + for item in gamelist: + if (item != None) and (item != "None"): + mygame = database.GobanTable.get(item) + description = mygame.description + if (description == None) or (description == "None") or (description == ""): + description = item + settings["Data.Games.%s.Description" % item] = mygame.description + settings["Data.Games.%s.Name" % item] = item + players = mygame.players() + settings["Data.Games.%s.Player1" % item] = mygame.players()[0] + settings["Data.Games.%s.Player2" % item] = mygame.players()[1] + settings["Data.Games.%s.Created" % item] = helper.format_time(mygame.created) + settings["Data.Games.%s.Lastmove" % item] = helper.format_time(mygame.lastmove) + return helper.cs_render("templates/overview.cs",settings) else: - settings["Data.GamelistNotEmpty"] = 0 - for item in gamelist: - if (item != None) and (item != "None"): - mygame = database.GobanTable.get(item) - description = mygame.description - if (description == None) or (description == "None") or (description == ""): - description = item - settings["Data.Games.%s.Description" % item] = mygame.description - settings["Data.Games.%s.Name" % item] = item - players = mygame.players() - settings["Data.Games.%s.Player1" % item] = mygame.players()[0] - settings["Data.Games.%s.Player2" % item] = mygame.players()[1] - settings["Data.Games.%s.Created" % item] = helper.format_time(mygame.created) - settings["Data.Games.%s.Lastmove" % item] = helper.format_time(mygame.lastmove) - return helper.cs_render("templates/overview.cs",settings) + return helper.cs_render("templates/not_logged_in.cs") index.exposed = True \ No newline at end of file diff --git a/main.py b/main.py index 8b1d769..94f207c 100755 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -import sys, traceback,string,time +import string,time import login,createaccount,helper,gamecreation,playgame,logout from cherrypy import cpg diff --git a/playgame.py b/playgame.py index 39ee424..75a9f0f 100644 --- a/playgame.py +++ b/playgame.py @@ -3,43 +3,6 @@ import string from cherrypy import cpg from cherrypy.lib import httptools -DEBUG = 1 - -def is_my_turn(req,form,gobandict): - """ - gets request and util.FiedStorage form. - check wether or not the current this is the players turn. - return true or false. - """ - me = form["username"] - player1 = gobandict["player1"] - player2 = gobandict["player2"] - play = gobandict["play"] - - if ((player1 == me) and (play == "white")) or ((player2 == me) and (play == "black")): - return True - else: - return False - - -def create_gobandict(req,form,gamename): - """ - gets a gamename - loads sgf, transforms it to dict, writes stuff like player names to dict - returns dict - TODO: is this function still in use? - """ - #read goban sgf from database - mygame = database.GobanTable.byName(gamename) - sgf = mygame.sgf - gobandict = gnugo.parse_static_gnugo_sgf(sgf) - gobandict["player1"] = mygame.player1 - gobandict["player2"] = mygame.player2 - gobandict["turn_number"] = mygame.turn_number - gobandict["name"] = mygame.name - gobandict["sgf"] = sgf - return gobandict - class PlayGame: """ @@ -57,6 +20,22 @@ class PlayGame: else: httptools.redirect("/login") + + def is_my_turn(self,gobandict): + """ + gets request and util.FiedStorage form. + check wether or not the current this is the players turn. + return true or false. + """ + me = gobandict["username"] + player1 = gobandict["player1"] + player2 = gobandict["player2"] + play = gobandict["play"] + + if ((player1 == me) and (play == "black")) or ((player2 == me) and (play == "white")): + return True + else: + return False def display_goban(self,gamename,settings={}): """ @@ -72,10 +51,21 @@ class PlayGame: mygame = database.GobanTable.get(gamename) sgf = mygame.sgf gobandict = gnugo.parse_static_gnugo_sgf(sgf) + gobandict["username"] = cpg.request.sessionMap["username"] + gobandict["player1"],gobandict["player2"] = mygame.players() size = mygame.size + settings["Data.TurnNumber"] = mygame.turn_number settings["Data.GobanSize"] = size settings["Data.GameName"] = gamename + settings["Data.Play"] = gobandict["play"] + if self.is_my_turn(gobandict): + settings["Data.MyTurn"] = "True" + else: + settings["Data.MyTurn"] = "False" + + print gobandict + for x in range(1,size+1): for y in range(1,size+1): settings["Data.Goban.%d.%d.x" % (x,y)] = x @@ -84,6 +74,8 @@ class PlayGame: settings["Data.Goban.%d.%d.color" % (x,y)] = "_white" elif gobandict[(x,y)] == 2: settings["Data.Goban.%d.%d.color" % (x,y)] = "_black" + else: + settings["Data.Goban.%d.%d.color" % (x,y)] = "" #now check wether or not this field is hoshi if size == 19: # 9 hoshis if (x,y) in hoshis19x19: @@ -112,21 +104,27 @@ class PlayGame: turn = mygame.turn_number sgf = mygame.sgf gobandict = gnugo.parse_static_gnugo_sgf(sgf) + gobandict["player1"],gobandict["player2"] = mygame.players() + gobandict["username"] = cpg.request.sessionMap["username"] gobandict["name"] = gamename gobandict["turn_number"] = turn gobandict["sgf"] = sgf settings = {} if (gobandict[position] == 0): #empty field - if gnugo.is_legal(gobandict,position): #gnugo says the move is ok - #let gnugo make the above move, let gnugo write move to file - new_sgf = gnugo.make_move_in_sgf(gobandict,position) - #write new sgf file into database - mygame.sgf = new_sgf - mygame.turn_number = turn + 1 - mygame.set_time() - return self.display_goban(gamename) - else: #move not ok - settings["Data.Message"] = "This is not a legal move (says Gnugo)." + if self.is_my_turn(gobandict): + if gnugo.is_legal(gobandict,position): #gnugo says the move is ok + #let gnugo make the above move, let gnugo write move to file + new_sgf = gnugo.make_move_in_sgf(gobandict,position) + #write new sgf file into database + mygame.sgf = new_sgf + mygame.turn_number = turn + 1 + mygame.set_time() + return self.display_goban(gamename) + else: #move not ok + settings["Data.Message"] = "This is not a legal move (says Gnugo)." + return self.display_goban(gamename,settings) + else: + settings["Data.Message"] = "This is not your turn. You have to wait for the other player." return self.display_goban(gamename,settings) else: #position not empty settings["Data.Message"] = "Could not make move: Field not empty." diff --git a/psql.py b/psql.py deleted file mode 100755 index b9b4bfa..0000000 --- a/psql.py +++ /dev/null @@ -1,450 +0,0 @@ -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() - - diff --git a/templates/overview.cs b/templates/overview.cs index 44496dd..ea1cdd0 100644 --- a/templates/overview.cs +++ b/templates/overview.cs @@ -2,8 +2,8 @@

Current Games:

- - +
Name of gameWhiteBlackTime of CreationTime of last move
+ diff --git a/templates/playgame.cs b/templates/playgame.cs index a3cb3a9..1239bd4 100644 --- a/templates/playgame.cs +++ b/templates/playgame.cs @@ -1,8 +1,13 @@ + + +
+Current Turn: . + Black to move.White to move. + Your Turn. +
+
- - -
Name of gameBlackWhiteTime of CreationTime of last move