various bugfixes and cleanups

This commit is contained in:
phear 2006-05-17 12:38:28 +00:00
parent c4ee02e046
commit 5ea601efc8
10 changed files with 107 additions and 575 deletions

View File

@ -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:

View File

@ -132,6 +132,10 @@ input.submit:hover {
}
/* The Board--------------------------------------------------------------------------- --------------------------------- */
#board{
padding-top:30px;
}
#board a, a:link, a:visited {
border: none;
}

View File

@ -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]:

View File

@ -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

View File

@ -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=" ""
<form method="post">
<input type="hidden" name="username" value="%s">
<input type="hidden" name="sessionid" value="%s">
<input type="hidden" name="game" value="%s">
<input type="submit" class="submit" name="logout" value="logout">
<input type="submit" class="submit" name="game overview" value="game overview">
<input type="submit" class="submit" name="refresh" value="refresh">
</form>
"" " % (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

View File

@ -1,4 +1,4 @@
import sys, traceback,string,time
import string,time
import login,createaccount,helper,gamecreation,playgame,logout
from cherrypy import cpg

View File

@ -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."

450
psql.py
View File

@ -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 <name>
"""
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 <statement>, 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()

View File

@ -2,8 +2,8 @@
<h2> Current Games: </h2>
<?cs if:Data.GamelistNotEmpty ?>
<table><tr><td></td><td>Name of game</td><td>White</td>
<td>Black</td><td>Time of Creation</td><td>Time of last move</td>
<table><tr><td></td><td>Name of game</td><td>Black</td>
<td>White</td><td>Time of Creation</td><td>Time of last move</td>
<td></td></tr>

View File

@ -1,8 +1,13 @@
<?cs include:"templates/header.cs" ?>
<?cs var:Data.Message ?><br>
Current Turn: <?cs var:Data.TurnNumber ?>.
<?cs if:(Data.Play == "black") ?> Black to move.<?cs elif:(Data.Play == "white") ?>White to move.<?cs /if ?>
<?cs if:(Data.MyTurn == "True") ?> Your Turn.<?cs /if ?>
<br>
<div id="board">
<?cs var:Data.Message ?>
<?cs loop:x = #1, #Data.GobanSize, #1
?><?cs loop:y = #1, Data.GobanSize, #1
?><?cs