Beispiel #1
0
def recordTime(uuid, customTime=-1):
    if not uuid:
        return
    if customTime > 0:
        clockTime = customTime
    else:
        clockTime = time.time()

    #Check for incomplete time slots
    incompleteTime = db.fetchOne(queries.check_for_open, (uuid, ))
    if incompleteTime:
        #Ignore incomplete entry if over 18 hours old.
        if time.time() - incompleteTime[0] > 3600 * 18:
            print("Removed time for ", uuid)
            db.execute(queries.cancel_open_member_clock, (uuid, ))
        #Ignore accidental triggers close to login
        elif time.time() - incompleteTime[0] < DEBOUNCE:
            print("Ignoring accidental trigger.")
            return
        else:
            print("Closed time for ", uuid)
            db.execute(queries.close_clock, (
                clockTime,
                uuid,
            ))
            return
    #If no open time is found, create a login
    lastOutTime = db.fetchOne(queries.get_last_member_clock_out, (uuid, ))
    if lastOutTime and lastOutTime[0]:
        if time.time() - lastOutTime[0] < DEBOUNCE:
            print("Ignoring accidental trigger.")
            return
    print("Opened time for ", uuid)
    db.execute(queries.clock_member, (uuid, currentEvent, clockTime, -1))
Beispiel #2
0
def registerMember(name, uuid):
    #Delete old entries from uuid to be registered
    db.execute(queries.clear_member_clocks, (uuid, ))

    #Migrate past user entries to new ID
    lastUUID = db.fetchOne(queries.get_uuid_by_name, (name, ))
    if lastUUID:
        for entry in db.fetchAll(queries.get_clocks, (lastUUID[0], )):
            db.execute(queries.clock_member, (
                uuid,
                entry[0],
                entry[1],
                entry[2],
            ))
        db.execute(queries.clear_member_clocks, (lastUUID[0], ))

    #If uuid has been registered, update name and register time, otherwise insert new entry
    if db.fetchOne(queries.check_member_exists, (uuid, )):
        db.execute(queries.update_name, (
            name,
            time.time(),
            uuid,
        ))
    else:
        db.execute(queries.register_member, (uuid, name, time.time()))
Beispiel #3
0
 def formDelete(self):
     if (self.ID):
         db.fetchOne("delete from ogrencibilgi where id={}".format(self.ID))
         self.formList()
     else:
         QtWidgets.QMessageBox.critical(self, "HATA", "ID bulunamadı!")
     self.ID = 0
	def register(self, nickname="", email_reg="", **args):
		if (nickname == "" or nickname == "Nickname"):
			return self.register_complete("Username is empty")
		if (email_reg == "") or (email_reg == "E-Mail Address") or (email_reg.lower()[-7:] != "@si.lan"):
			return self.register_complete("Email address is invalid, must be @si.lan")

		SanitizeValues = dict()
		SanitizeValues["nickname"] = nickname
		SanitizeValues["email_reg"] = email_reg
		SanitizeValues = db.sanitize(**SanitizeValues)
		nickname = SanitizeValues["nickname"]
		email_reg = SanitizeValues["email_reg"]

		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,'SELECT id FROM assassins WHERE lower(nickname)=?', (nickname.lower(),))
		if row != None and len(row) != 0:
			return self.register_complete("Nickname already in use")

		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,'SELECT id FROM assassins WHERE email_address=?', (email_reg.lower(),))
		if row != None and len(row) != 0:
			return self.register_complete("Email address already in use")

		password = ''.join([random.choice(string.letters + string.digits) for i in range(8)])
		passwordhash = bcrypt.hashpw(password, bcrypt.gensalt())
		try:
			db.execute(cherrypy.thread_data.conn,"insert into Assassins(nickname, email_address, password) values(?, ?, ?)", (nickname, email_reg.lower(), passwordhash))
			self.SendEmail(email_reg.lower(), "Welcome to Nerf Assassin.\r\nYour nickname is: %s\r\nYour password is: %s\r\n\r\nPasswords are case sensitive\r\n" % (nickname, password))
			return self.register_complete("New assassin created, email sent to %s" % (email_reg), "")
		except Exception, ex:
			return self.register_complete("Error creating a new assassin")
	def stats(self):
		(ret, rows) = db.fetchAll(cherrypy.thread_data.conn,"select id, firstname, lastname, nickname, ranking from assassins where ranking is not null order by ranking, firstname, lastname, nickname")

		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id from games where end_datetime is null")
		if(row == None or len(row) == 0):
			game_id = 0
		else:
			(game_id,) = row

		StatData = []
		for Entry in rows:
			(id, firstname, lastname, nickname, ranking) = Entry
			dictEntry = dict()
			dictEntry["profile_id"] = id
			dictEntry["firstname"] = firstname
			dictEntry["lastname"] = lastname
			dictEntry["nickname"] = nickname
			dictEntry["rank"] = html.ordinal(ranking)
			dictEntry["total_assassinations"] = 0
			(ret, rowcount) = db.fetchOne(cherrypy.thread_data.conn,"Select count(killer_id) from gameinfo where killer_id=? and game_id != ?", (id, game_id))
			if(ret == True and rowcount != None):
				(dictEntry["total_assassinations"],) = rowcount
			(ret, rowcount) = db.fetchOne(cherrypy.thread_data.conn,"Select count(target_id) from gameinfo where target_id=? and killer_id is not null and killer_id != 0 and game_id != ?", (id, game_id))
			if(ret == True and rowcount != None):
				(dictEntry["total_deaths"],) = rowcount
			StatData.append(dictEntry)

		(ret, rows) = db.fetchAll(cherrypy.thread_data.conn,"select id, firstname, lastname, nickname, ranking from assassins where ranking is null order by ranking, firstname, lastname, nickname")
		for Entry in rows:
			(id, firstname, lastname, nickname, ranking) = Entry
			dictEntry = dict()
			dictEntry["profile_id"] = id
			dictEntry["firstname"] = firstname
			dictEntry["lastname"] = lastname
			dictEntry["nickname"] = nickname
			dictEntry["rank"] = html.ordinal(ranking)
			dictEntry["total_assassinations"] = 0
			(ret, rowcount) = db.fetchOne(cherrypy.thread_data.conn,"Select count(killer_id) from gameinfo where killer_id=? and game_id != ?", (id, game_id))
			if(ret == True and rowcount != None):
				(dictEntry["total_assassinations"],) = rowcount
			(ret, rowcount) = db.fetchOne(cherrypy.thread_data.conn,"Select count(target_id) from gameinfo where target_id=? and killer_id is not null and killer_id != 0 and game_id != ?", (id, game_id))
			if(ret == True and rowcount != None):
				(dictEntry["total_deaths"],) = rowcount
			StatData.append(dictEntry)

		StatHTML = open("static/stats.html","r").read()
		StatHTML = html.HTMLCheckLoggedIn(self.ValidateLogin(), StatHTML)

		return html.HTMLReplaceSection(self.ValidateLogin(), "stat", StatHTML, StatData)
Beispiel #6
0
    def formSave(self):
        isim = self.isimLe.text()
        sinif = self.sinifLe.text()
        alan = self.alanLe.text()
        email = self.emailLe.text()

        if isim and sinif and alan and email:
            db.fetchOne(
                "insert into ogrencibilgi (isim,sinif,alan,email) values ('{}','{}','{}','{}')"
                .format(isim, sinif, alan, email))
            self.formList()
        else:
            QtWidgets.QMessageBox.critical(
                self, "HATA",
                "Tüm alanlar zorunludur ve doldurmanız gerekmektedir!")
Beispiel #7
0
    def formUpdate(self):
        isim = self.isimLe.text()
        sinif = self.sinifLe.text()
        alan = self.alanLe.text()
        email = self.emailLe.text()

        if isim and sinif and alan and email and self.ID:
            db.fetchOne(
                "update ogrencibilgi set isim='{}', sinif='{}', alan='{}', email='{}' where id={}"
                .format(isim, sinif, alan, email, self.ID))
            self.formList()
        else:
            QtWidgets.QMessageBox.critical(
                self, "HATA",
                "Tüm alanlar zorunludur ve doldurmanız gerekmektedir!")
        self.ID = 0
Beispiel #8
0
def UpdateLCD():
	global lcd
	(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select sum(amount) from money")
	(Amount,) = row
	lcd.clear()
	lcd.home()
	lcd.writeString("Samantha's Money")
	lcd.setPosition(2, 0)
	lcd.writeString("%0.2f" % (Amount))
Beispiel #9
0
def sessions(id):
    room = session.get('session_id')
    sessionObject = db.fetchOne({'_id': ObjectId(room)})
    messages = sessionObject['messages']
    session['unplaced_pieces'] = sessionObject['unplaced_pieces'][
        session['user_id']]
    session['board_state'] = g.board_state = sessionObject['board_state']
    session['phase'] = sessionObject['phase']
    g.messages = [message for message in messages if len(message) == 2]
    return render_template('session.html')
Beispiel #10
0
def handle_my_custom_event(json, methods=['GET', 'POST']):
    print('received my event: ' + str(json))
    room = session.get('session_id')
    socketio.emit('my response', json, callback=messageReceived, room=room)
    gameSession = db.fetchOne({'_id': ObjectId(room)})
    gameSession['messages'].append(json)
    db.updateOne({'_id': ObjectId(room)},
                 {'$set': {
                     'messages': gameSession['messages']
                 }})
	def confirm_kill(self, **args):
		if(self.ValidateLogin()):
			if "confirm" in args:
				confirm = args["confirm"]
			else:
				confirm = cherrypy.session.pop("confirm_hash", None)

			if(confirm == None):
				return self.profile()

			if "confirmed" not in args:
				return html.HTMLReplaceSection(self.ValidateLogin(), "confirm", open("static/confirm.html","r").read(), [{"confirm":confirm, "url":"confirm_kill"}])
			else:
				if(args["confirmed"] == 0):
					#email the assassin and notify them
					(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select a.nickname, a.email_address, gi.target_id, gi.id from assassins a, gameinfo gi, games g where gi.game_id = g.id and g.end_datetime is null and gi.confirm_hash=? and a.id=gi.reporting_killer", (confirm,))
					if(row != None and len(row) != 0):
						(nickname, assassin_email, target_id, gameinfo_id) = row
						if(target_id == None):
							db.execute(cherrypy.thread_data.conn,"delete from gameinfo where id=?", (gameinfo_id,))

						self.SendEmail(assassin_email, "%s\nThe target did not confirm your kill" % (nickname))

					return html.display_message(self.ValidateLogin(), "Kill not confirmed")

			(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select gi.id, gi.target_id, gi.reporting_killer from gameinfo gi, games g where gi.game_id = g.id and g.end_datetime is null and gi.confirm_hash=? and killer_id is null", (confirm,))

			if(confirm == None or row == None or len(row) == 0):
				return html.display_message(self.ValidateLogin(), "Invalid confirmation code")

			(gameinfo_id, target_id, reporting_killer) = row

			#if no target then this was a kill without it being a known target
			if(target_id == None):
				db.execute(cherrypy.thread_data.conn,"delete from gameinfo where id=?", (gameinfo_id,))

			return self.kill_player(reporting_killer)

		elif("confirm" in args):
			cherrypy.session["confirm_hash"] = args["confirm"]
			raise cherrypy.HTTPRedirect("/login.html")

		return html.display_message(self.ValidateLogin(), "Invalid confirmation code")
	def invalidpic(self, id):
		if(self.ValidateLogin() and cherrypy.session.get("ProfileID") == 1):
			(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select nickname, email_address, picture_filename from assassins where picture_filename is not null and id=?", (id,))
			(nickname, email, picture) = row
			if(picture == None):
				return html.display_message(self.ValidateLogin(), "No picture found")

			db.execute(cherrypy.thread_data.conn,"Update assassins set picture_filename=Null where id=?", (id,))
			(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id from games where end_datetime is null")
			if(row != None and len(row) != 0):
				(gameid,) = row
				db.execute(cherrypy.thread_data.conn,"delete from gameinfo where assassin_id=? and target_id=Null and game_id=?", (id, gameid))

			os.remove("profile-images/" + picture)
			self.SendEmail(email, "Your picture was invalid and removed. If you were part of a game then you have been removed from the game for an invalid profile picture")

			return html.display_message(self.ValidateLogin(), "Picture removed and email sent")

		else:
			return html.display_message(self.ValidateLogin(), "No access")	
	def kill_player(self, killer_id):
		#called when we are to kill the local player
		profile_id = cherrypy.session.get("ProfileID")
		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select gi.id, g.id, gi.assassin_id from games g, gameinfo gi where gi.game_id = g.id and gi.target_id=? and g.end_datetime is null and gi.killer_id is null", (profile_id,))
		if(row == None or len(row) == 0):
			return html.display_message(self.ValidateLogin(), "Error updating kills")
		(gameinfo_id, game_id, assassin_id) = row

		#figure out the ranking
		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select min(ranking) from gameinfo where game_id=?", (game_id,))
		(ranking,) = row
		if(row == None or len(row) == 0 or ranking == None):
			(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select count(distinct(target_id))+1 from gameinfo where game_id=?", (game_id,))

		(ranking,) = row
		ranking = int(ranking)
		ranking = ranking - 1

		db.execute(cherrypy.thread_data.conn,"update gameinfo set killer_id=?, kill_datetime=datetime('now'), ranking=? where id=?", (killer_id, ranking, gameinfo_id))

		#lookup who this player's target was
		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select target_id from gameinfo where assassin_id=? and game_id=? and killer_id is null", (profile_id,game_id))
		(target_id,) = row

		#mark the record for this player to be no kill
		db.execute(cherrypy.thread_data.conn,"update gameinfo set killer_id=0 where game_id=? and target_id=? and assassin_id=? and killer_id is null", (game_id, target_id, profile_id)) 

		#don't insert if the assassin and target match as it is end of the game
		if(target_id != assassin_id):
			db.execute(cherrypy.thread_data.conn,"insert into gameinfo (game_id, assassin_id, target_id) values(?,?,?)", (game_id, assassin_id, target_id))

			#report the new target to the assassin
			(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select a.nickname, a.firstname, a.lastname, a.email_address, b.firstname, b.lastname, b.nickname, b.picture_filename from assassins a, assassins b, gameinfo gi where gi.game_id=? and a.id=gi.assassin_id and gi.assassin_id=? and b.id=gi.target_id and gi.killer_id is null", (game_id, assassin_id))
			(assassin_nick, assassin_first, assassin_last, assassin_email, target_first, target_last, target_nick, target_picture) = row
			self.SendEmail(assassin_email, "%s, your target is now %s, also known as %s %s. Attached is your target's picture" % (assassin_nick, target_nick, target_first, target_last), target_picture) 
		else:
			#update the last player to be first
			db.execute(cherrypy.thread_data.conn,"Update gameinfo set ranking=1 where killer_id=0 and target_id=? and game_id=? and assassin_id=?", (assassin_id, game_id, profile_id))

		return html.display_message(self.ValidateLogin(), "Thank you for confirming your death")
	def report_killed(self):
		if(self.ValidateLogin()):
			gamehash = ''.join([random.choice(string.letters + string.digits) for i in range(32)])
			(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id from games where end_datetime is null")
			if(row == None or len(row) == 0):
				return html.display_message(self.ValidateLogin(), "No active game")

			(game_id, ) = row
			db.execute(cherrypy.thread_data.conn,"insert into gameinfo(game_id, assassin_id, confirm_hash, reporting_killer) values(?,?,?,?)", (game_id, cherrypy.session.get("ProfileID"), gamehash, cherrypy.session.get("ProfileID")))

			return html.display_message(self.ValidateLogin(), "Please provide the following URL to the person you killed<br>%s" % ("http://tank:8080/confirm_kill?confirm=" + gamehash))
		else:
			raise cherrypy.HTTPRedirect("/")
	def gamecheck(self):
		#check on any games that are active or becoming active for assignment
		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id, start_datetime [timestamp], gametype from games where end_datetime is null")
		if(row == None or len(row) == 0):
			return

		#we have a game that will start or is running, determine and assign accordingly
		(gameid, starttime, gametype) = row

		#if the time is in the future, exit
		if(starttime > datetime.datetime.utcnow()):
			return

		#see if we need to do assignments
		(ret, players) = db.fetchAll(cherrypy.thread_data.conn,"select id, assassin_id, target_id from gameinfo where game_id=? order by target_id desc", (gameid,))
		if(len(players) <= 1):
			#no players or only 1 player, time is past, remove the game
			db.execute(cherrypy.thread_data.conn,"delete from games where id=?", (gameid,))
			return

		Game = NerfGames.GetGameByID(gametype)
		Game.NerfAssassin = NerfAssassin
		Game.db = db
		Game.GameID = gameid
		Game.GameTypeID = gametype

		(id, assassin_id, target_id) = players[0]
		if(target_id == None):
			Game.AssignPlayers(players)
	
		else:
			#game has assignments, see if the game is over yet
			Game = NerfAssassin.GetGameByID(gametype)
			Game.NerfAssassin = NerfAssassin
			Game.db = db
			Game.GameID = gameid
			Game.GameTypeID = gametype
			if(Game.IsGameOver()):
				#if no one left to kill, game over
				db.execute(cherrypy.thread_data.conn,"update games set end_datetime=datetime(\"now\") where id=?", (gameid,))

				#remove any outstanding reports
				db.execute(cherrypy.thread_data.conn,"delete from gameinfo where reporting_killer is not null and target_id is null and game_id=?",(gameid,))

				#do a stats update for the game type
				Game.CalculateStats()
			else:
				Game.CheckConfirmationTimeout()

		del Game
		return
Beispiel #16
0
def lastClock(uuid, events=[currentEvent]):
    if not uuid:
        return 0
    if not events or len(events) == 0:
        return 0

    eventString = "("
    for i in range(0, len(events) - 1):
        eventString += "\"" + events[i] + "\", "
    eventString += "\"" + events[len(events) - 1] + "\")"

    clock = queries.get_last_member_clock_out_by_event + eventString
    last = db.fetchOne(clock, (uuid, ))
    if last and len(last) > 0:
        return last[0]
	def target_killed(self, id):
		if(self.ValidateLogin()):
			#make sure that the request is valid
			(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select gi.id, a.email_address from gameinfo gi, games g, assassins a where gi.assassin_id=? and gi.target_id=? and gi.game_id=g.id and g.end_datetime is null and a.id=gi.target_id", (cherrypy.session.get("ProfileID"), id))
			if row != None and len(row) != 0:
				(gameinfo_id, email_address) = row

				gamehash = ''.join([random.choice(string.letters + string.digits) for i in range(32)])
				db.execute(cherrypy.thread_data.conn,"update gameinfo set confirm_hash=?, reporting_killer=? where id=?", (gamehash, cherrypy.session.get("ProfileID"), gameinfo_id))

				self.SendEmail(email_address, "It was reported that you have been assassinated. Please goto the following link to confirm your assassination.\n%s" % ("http://tank:8080/confirm_kill?confirm=" + gamehash))
				return html.display_message(self.ValidateLogin(), "Email sent")
			else:
				return html.display_message(self.ValidateLogin(), "Invalid ID")
		else:
			raise cherrypy.HTTPRedirect("/")
	def ValidateLogin(self, nickname="", password=""):
		cherrypy.session.load()
		if((nickname == "") and (password == "")):
			try:
				nickname = cherrypy.session.get("Nickname")
				password = cherrypy.session.get("Password")
				if(nickname == None or password == None):
					return False
			except:
				return False

		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id, password from assassins where lower(nickname)=?", (nickname.lower(),))
		if(row != None and len(row) != 0):
			(profileid, dbpass) = row
			if(bcrypt.hashpw(password,str(dbpass)) == str(dbpass)):
				cherrypy.session["Nickname"] = nickname
				cherrypy.session["Password"] = password
				cherrypy.session["ProfileID"] = profileid
				cherrypy.session.save()
				return True
			else:
				return False

		return False
Beispiel #19
0
import db, queries, time

#Time in seconds to wait before allowing another time event for a user.
DEBOUNCE = 5

events = []

for event in db.fetchAll(queries.get_events):
    if len(event) > 0:
        events.append(event[0])

curr = db.fetchOne(queries.get_current_event)
if curr and len(curr) > 0:
    currentEvent = curr[0]
else:
    currentEvent = events[0]


def createEvent(eventName):
    db.execute(queries.create_event, (eventName, ))
    events.append(eventName)


def registerMember(name, uuid):
    #Delete old entries from uuid to be registered
    db.execute(queries.clear_member_clocks, (uuid, ))

    #Migrate past user entries to new ID
    lastUUID = db.fetchOne(queries.get_uuid_by_name, (name, ))
    if lastUUID:
        for entry in db.fetchAll(queries.get_clocks, (lastUUID[0], )):
Beispiel #20
0
def enterGame(username=None, password=None):
    if request.method == 'POST':
        if username is None:
            username = request.form['username']
        if password is None:
            password = request.form['password']
        error = None
        session_code = None

        try:
            session_code = request.form['session_code']
            print('session found: ' + session_code)
        except:
            print('no code found')
        if session_code is None:
            session_code = get_random_alphaNumeric_string(5)
            db.createSession({
                'code': session_code,
                'users': {},
                'board_state': board.grid,
                'phase': 'preparation',
                'unplaced_pieces': {},
                'messages': []
            })
            print('session created: ' + session_code)

        if username is None:
            error = 'Please provide a username. You can make one up.'

        else:
            gameSession = db.fetchOne({'code': session_code})
            session.clear()
            # check if user exists in current session
            if username in gameSession['users']:
                print('existing username found...')
                session_id, color, phase = gameSession['_id'], gameSession[
                    'users'][username]['color'], gameSession['phase']

                if not check_password_hash(
                        gameSession['users'][username]['password'], password):
                    error = 'Incorrect password.'
            else:
                print('users\n', gameSession['users'])
                if len(gameSession['users']) == 1:
                    color = 'red'
                else:
                    color = 'blue'
                gameSession['users'].update({
                    username: {
                        'password': generate_password_hash(password),
                        'color': color
                    }
                })
                gameSession['unplaced_pieces'].update({
                    username: [(key, pieces_reference[key].maxQuantity)
                               for key in pieces_reference]
                })
                db.updateOne({'code': session_code}, {
                    '$set': {
                        'users': gameSession['users'],
                        'unplaced_pieces': gameSession['unplaced_pieces']
                    }
                })
                phase = gameSession['phase']

        session_id = str(gameSession['_id'])

        if error is None:
            session['user_id'], session['session_code'], session[
                'session_id'], session['color'], session[
                    'phase'] = username, session_code, session_id, color, phase
            return redirect(url_for('sessions', id=session_id))

        flash(error)

    return render_template('auth/login.html')
	def creategame(self, **args):
		if(self.ValidateLogin()):
			args = db.sanitize(**args)

			#make sure the user is allowed to create a game
			(ret, createcheck) = db.fetchOne(cherrypy.thread_data.conn,"select picture_filename, firstname, lastname from assassins where id=? and (firstname is Null or lastname is Null or picture_filename is Null)", (cherrypy.session.get("ProfileID"),))
			if(createcheck != None and len(createcheck) != 0):
				return html.display_message(self.ValidateLogin(), "You can not create a game until your full first and last name is filled in and a face picture is provided")

			(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"Select id from games where end_datetime is null")
			if(row == None or len(row) == 0):
				if(args["gamerules"] == "0"):
					if(args["newrules_name"] == "" or args["newrules"] == ""):
						return html.display_message(self.ValidateLogin(), "No name specified or new rules are empty")

					(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id from rules where lower(rulename) = ?", (args["newrules_name"].lower(),))
					if(row != None and len(row) != 0):
						return html.display_message(self.ValidateLogin(), "Rule already exists")

					args["newrules"] = args["newrules"].replace("\r","")
					db.execute(cherrypy.thread_data.conn,"insert into rules(rulename, rules) values(?,?)", (args["newrules_name"], args["newrules"]))
					(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id from rules where lower(rulename) = ?", (args["newrules_name"].lower(),))
					(args["gamerules"], ) = row

				try:
					Date = args["gamestart_date"].split("/")
					NewDate = "%02d/%02d/%04d" % (int(Date[0]), int(Date[1]), int(Date[2]))
					Time = args["gamestart_time"].split(":")
					if(Time[1].find(" ") != -1):
						Time2 = Time[1].split(" ")
					else:
						Time2 = []
						Time2.append(Time[1][0:2])
						Time2.append(Time[1][2:4])

					NewTime = "%02d:%02d %s" % (int(Time[0]), int(Time2[0]), Time2[1])
					
					StartDate = datetime.datetime.strptime(NewDate + " " + NewTime, "%m/%d/%Y %I:%M %p")
				except Exception, ex:
					print ex
					return html.display_message(self.ValidateLogin(), "Error converting specified date and time")

				if(StartDate < datetime.datetime.now()):
					return html.display_message(self.ValidateLogin(), "Start date and time can not be in the past")

				(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id from rules where id = ?", (args["gamerules"],))
				if(row == None or len(row) == 0):
					return html.display_message(self.ValidateLogin(), "Invalid rule")

				(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id from gametypes where id = ?", (args["gametypeid"],))
				if(row == None or len(row) == 0):
					return html.display_message(self.ValidateLogin(), "Invalid game type")

				#adjust for utc
				LocalStartDate = StartDate
				StartDate = StartDate + (datetime.datetime.utcnow() - datetime.datetime.now())
				db.execute(cherrypy.thread_data.conn,"insert into games(start_datetime, rule_id) values(datetime(?),?,?)", (StartDate.strftime("%Y-%m-%d %H:%M"), args["gamerules"], args["gametypeid"]))

				(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select id from games where end_datetime is null")
				(game_id,) = row
				db.execute(cherrypy.thread_data.conn,"insert into gameinfo(game_id, assassin_id) values(?,?)", (game_id, cherrypy.session.get("ProfileID")))

				#now email everyone
				(ret, players) = db.fetchAll(cherrypy.thread_data.conn,"select nickname, email_address from assassins where email_newgames=1")
				for Entry in players:
					(nickname, email) = Entry
					self.SendEmail(email, "%s:\nA new game is starting at %s. Login and join if you wish to play." % (nickname, LocalStartDate.strftime("%b %d, %Y %I:%M %p")))
	def games(self, **args):
		(ret, rows) = db.fetchAll(cherrypy.thread_data.conn,"select g.id, g.start_datetime [timestamp], g.end_datetime [timestamp], r.rules, g.gametype, gt.name from games g left join rules r on g.rule_id=r.id left join gametypes gt on g.gametype=gt.id order by g.start_datetime desc")

		GameHTML = open("static/games.html", "r").read()
		GameHTML = html.HTMLCheckLoggedIn(self.ValidateLogin(), GameHTML)

		ProfileID = cherrypy.session.get("ProfileID")
		if(ProfileID == None):
			ProfileID = 0
			GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "joingame", GameHTML)
			GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "newgame", GameHTML)
			GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "creategame", GameHTML)

		#the very first row is the latest game
		if(len(rows) == 0):
			#no games, fake some data so we will still create the labels as needed
			start_datetime = datetime.datetime(2000,1,1)
			end_datetime = start_datetime
		else:
			(gameid, start_datetime, end_datetime, rules) = rows[0]

		if(start_datetime > datetime.datetime.utcnow()):
			#convert back to our timezone
			curtime = datetime.datetime.utcnow() - datetime.datetime.now()
			start_datetime = start_datetime - curtime

			CounterData = [{"year":start_datetime.year, "month":start_datetime.month-1, "day":start_datetime.day, "hour":start_datetime.hour, "minute":start_datetime.minute, "serveryear":curtime.year, "servermonth":curtime.month-1,"serverday":curtime.day, "serverhour":curtime.hour, "serverminute":curtime.minute}]
			GameHTML = html.HTMLReplaceSection(self.ValidateLogin(), "counter", GameHTML, CounterData)

			if(ProfileID != 0):
				#if we have a status update, do it here as it is allowed
				if("status" in args):
					if args["status"] == "join":
						#asking to join, make sure that a profile picture and full name exists
						(ret, joincheck) = db.fetchOne(cherrypy.thread_data.conn,"select picture_filename, firstname, lastname from assassins where id=? and (firstname is Null or lastname is Null or picture_filename is Null or firstname='' or lastname='')", (ProfileID,))
						if(joincheck != None and len(joincheck) != 0):
							return html.display_message(self.ValidateLogin(), "You can not join a game until your full first and last name is filled in and a face picture is provided")

						db.execute(cherrypy.thread_data.conn,"insert into gameinfo(game_id, assassin_id) values(?,?)", (gameid, ProfileID))
					elif args["status"] == "leave":
						db.execute(cherrypy.thread_data.conn,"delete from gameinfo where game_id=? and assassin_id=?", (gameid, ProfileID))

				(ret, ingame) = db.fetchOne(cherrypy.thread_data.conn,"select id from gameinfo where game_id=? and assassin_id=?", (gameid, ProfileID))
				if(ingame != None and len(ingame) != 0):
					GameHTML = html.HTMLReplaceSection(self.ValidateLogin(), "joingame", GameHTML, [{"url":"games?status=leave","text":"Leave Game","id":""}])
				else:
					GameHTML = html.HTMLReplaceSection(self.ValidateLogin(), "joingame", GameHTML, [{"url":"games?status=join","text":"Join Game","id":""}])

				GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "newgame", GameHTML)
				GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "creategame", GameHTML)
		else:
			GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "counter", GameHTML)
			if(ProfileID != 0):
				if(end_datetime == None):
					GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "joingame", GameHTML)
					GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "newgame", GameHTML)
					GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "creategame", GameHTML)
				else:
					GameHTML = html.HTMLReplaceSection(self.ValidateLogin(), "joingame", GameHTML, [{"url":"#newgame", "text":"Start Game","id":"newgame-link"}])
					GameHTML = html.HTMLReplaceSection(self.ValidateLogin(), "newgame", GameHTML, [{"d":"d"}])

					#fill in data to allow a new game
					GameData = []
					dictEntry = dict()
					NewDate = datetime.datetime.now() + datetime.timedelta(3,60*60)
					dictEntry["startdate"] = NewDate.strftime("%m/%d/%Y")
					dictEntry["starttime"] = NewDate.strftime("%I:00 %p")
					dictEntry["SubSection"] = []

					#setup the rules
					RuleNames = []
					RuleData = []
					(ret, rulerows) = db.fetchAll(cherrypy.thread_data.conn,"select id, rulename, rules from rules order by rulename")
					for Entry in rulerows:
						NewEntry = dict()
						NewDataEntry = dict()
						(NewEntry["id"], NewEntry["name"], NewDataEntry["rules"]) = Entry
						NewDataEntry["rules"] = NewDataEntry["rules"].replace("\r","")
						NewDataEntry["rules"] = NewDataEntry["rules"].replace("\n","\\n")
						RuleNames.append(NewEntry)
						RuleData.append(NewDataEntry)

					dictEntry["SubSection"].append(("rulelist", RuleNames))
					dictEntry["SubSection"].append(("ruledata", RuleData))

					if(len(RuleData) != 0):
						dictEntry["firstindex"] = 1;
					else:
						dictEntry["firstindex"] = 0;

					GameData.append(dictEntry)
					
					GameHTML = html.HTMLReplaceSection(self.ValidateLogin(), "creategame", GameHTML, GameData)

		#if the game hasn't ended then display info about it
		if(end_datetime == None):
			rows.pop(0)

			#fill in the current game
			StatData = []
			dictEntry = dict()

			dictEntry["game_start"] = start_datetime.strftime("%b %d, %Y")
			if(rules != None):
				dictEntry["rules"] = rules.replace("\n","<br>")
			else:
				dictEntry["rules"] = ""

			#see if anyone is assigned yet as target should have a value and are either still alive or last one standing has no killer and is ranked already
			(ret, players) = db.fetchAll(cherrypy.thread_data.conn,"select distinct a.id from assassins a, gameinfo gi where gi.game_id=? and gi.target_id=a.id and ((gi.killer_id is null) or (gi.killer_id = 0 and gi.ranking = 1))", (gameid,))
			if(len(players) == 0):
				#possible that no one is assigned yet, get those that are about to play
				(ret, players) = db.fetchAll(cherrypy.thread_data.conn,"select distinct a.id from assassins a, gameinfo gi where gi.game_id=? and gi.assassin_id=a.id", (gameid,))

			dictEntry["SubSection"] = []
			SubSection = []
			AlivePlayers = []

			#set a flag as we remove the current profile from AlivePlayers so the player can see their kills
			if(players == None or len(players) == 0):
				HavePlayers = 0
			else:
				HavePlayers = 1

			for Entry in players:
				(player_id,) = Entry
				SubSection.append({"name":"Assassin"})
				if(player_id != ProfileID):
					AlivePlayers.append(player_id)
			dictEntry["SubSection"].append(("winner", SubSection))

			(ret, players) = db.fetchAll(cherrypy.thread_data.conn,"select gi.kill_datetime [timestamp], a.id, a.firstname, a.lastname, a.nickname, b.id, b.firstname, b.lastname, b.nickname, gi.ranking from assassins a, assassins b, gameinfo gi where gi.target_id=a.id and gi.killer_id=b.id and gi.game_id=? and gi.killer_id != 0 and gi.kill_datetime is not null order by gi.ranking asc", (gameid,))
			SubSection = []
			if(len(players) == 0 and HavePlayers == 0):
				SubSection.append({"kill_date":"","profile_id":"","name":"","killer_name":"","killer_profile_id":"","rank":""})
			else:
				for Entry in players:
					NewEntry = dict()
					(NewEntry["kill_date"], NewEntry["profile_id"], firstname, lastname, nickname, NewEntry["killer_profile_id"], killer_fname, killer_lname, killer_nname, ranking) = Entry
					NewEntry["name"] = str(firstname) + " " + str(lastname) + " (" + str(nickname) + ")"
					if(NewEntry["killer_profile_id"] in AlivePlayers):
						NewEntry["killer_profile_id"] = 0
						NewEntry["killer_name"] = "Assassin"
					else:
						NewEntry["killer_name"] = str(killer_fname) + " " + str(killer_lname) + " (" + str(killer_nname) + ")"
					NewEntry["rank"] = html.ordinal(ranking)
					NewEntry["kill_date"] = NewEntry["kill_date"].strftime("%b %d, %Y %H:%M")
					SubSection.append(NewEntry)
			dictEntry["SubSection"].append(("players", SubSection))

			StatData.append(dictEntry)
			GameHTML = html.HTMLReplaceSection(self.ValidateLogin(), "latest_game", GameHTML, StatData)

		else:
			GameHTML = html.HTMLRemoveSection(self.ValidateLogin(), "latest_game", GameHTML)

		#if no games, remove the game block
		if(len(rows) == 0):
			return html.HTMLRemoveSection(self.ValidateLogin(), "games", GameHTML)

		StatData = []
		for Entry in rows:
			(gameid, start_datetime, end_datetime, rules) = Entry
			dictEntry = dict()
			if(rules != None):
				dictEntry["rules"] = rules.replace("\n", "<br>")
			else:
				dictEntry["rules"] = ""

			dictEntry["game_start"] = start_datetime.strftime("%b %d, %Y")
			if(end_datetime != None):
				dictEntry["game_end"] = end_datetime.strftime("%b %d, %Y")
			else:
				dictEntry["game_end"] = ""

			(ret, players) = db.fetchAll(cherrypy.thread_data.conn,"select a.id, a.firstname, a.lastname, a.nickname, a.smack, a.picture_filename, gi.ranking from assassins a, gameinfo gi where gi.target_id = a.id and gi.game_id=? and gi.ranking = 1 order by gi.ranking asc", (gameid,))
			dictEntry["SubSection"] = []
			SubSection = []
			if(len(players) == 0):
				SubSection.append({"kill_date":"","name":"","profile_id":"","profile_image":"","nickname":"","smack":"","rank":""})
			else:
				for Entry in players:
					NewEntry = dict()
					(NewEntry["profile_id"],firstname, lastname, nickname, NewEntry["smack"], NewEntry["profile_image"], ranking) = Entry
					NewEntry["kill_date"] = "Winner"
					NewEntry["name"] = str(firstname) + " " + str(lastname) + " (" + str(nickname) + ")"
					if(NewEntry["profile_image"] == None):
						NewEntry["profile_image"] = "images/bio-pic.jpg"
					else:
						NewEntry["profile_image"] = "profile-images/" + NewEntry["profile_image"]
					NewEntry["nickname"] = nickname
					NewEntry["rank"] = html.ordinal(ranking)
					SubSection.append(NewEntry)

			dictEntry["SubSection"].append(("winner", SubSection))
			(ret, players) = db.fetchAll(cherrypy.thread_data.conn,"select gi.kill_datetime [timestamp], a.id, a.firstname, a.lastname, a.nickname, b.id, b.firstname, b.lastname, b.nickname, gi.ranking from assassins a, assassins b, gameinfo gi where gi.target_id=a.id and gi.killer_id=b.id and gi.game_id=? and gi.killer_id != 0 order by gi.ranking asc", (gameid,))

			SubSection = []
			if(len(players) == 0):
				SubSection.append({"kill_date":"","profile_id":"","name":"","killer_name":"","killer_profile_id":"","rank":""})
			else:
				for Entry in players:
					NewEntry = dict()
					(NewEntry["kill_date"], NewEntry["profile_id"], firstname, lastname, nickname, NewEntry["killer_profile_id"], killer_fname, killer_lname, killer_nname, ranking) = Entry
					NewEntry["name"] = str(firstname) + " " + str(lastname) + " (" + str(nickname) + ")"
					NewEntry["killer_name"] = str(killer_fname) + " " + str(killer_lname) + " (" + str(killer_nname) + ")"
					NewEntry["rank"] = html.ordinal(ranking)
					NewEntry["kill_date"] = NewEntry["kill_date"].strftime("%b %d, %Y %H:%M")
					SubSection.append(NewEntry)
			dictEntry["SubSection"].append(("players", SubSection))
			StatData.append(dictEntry)

		return html.HTMLReplaceSection(self.ValidateLogin(), "games", GameHTML, StatData)
	def profile(self, id=None):
		ProfileHTML = open("static/profile.html","r").read()
		ProfileHTML = html.HTMLCheckLoggedIn(self.ValidateLogin(), ProfileHTML)

		if(id == None):
			id = cherrypy.session.get("ProfileID")

		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select nickname, firstname, lastname, email_address, ranking, smack, picture_filename, email_newgames from assassins where id=?", (id,))
		if(ret == False or row == None or len(row) == 0):
			return html.display_message(self.ValidateLogin(), "Error accessing profile")
		(nickname, firstname, lastname, email, ranking, smack, picture_filename, email_newgames) = row
		if(picture_filename == None):
			picture_filename = "images/bio-pic.jpg"
		else:
			picture_filename = "profile-images/" + picture_filename

		ranking = html.ordinal(ranking)

		if(email_newgames):
			email_newgames="checked"
		else:
			email_newgames=""

		if((cherrypy.session.get("ProfileID") == None) or (int(id) != int(cherrypy.session.get("ProfileID")))):
			ProfileHTML = html.HTMLRemoveSection(self.ValidateLogin(), "edit", ProfileHTML)
			ProfileHTML = html.HTMLRemoveSection(self.ValidateLogin(), "target_header", ProfileHTML)
			ProfileHTML = html.HTMLRemoveSection(self.ValidateLogin(), "target", ProfileHTML)
		else:
			(ret, reportrow) = db.fetchOne(cherrypy.thread_data.conn,"select gi.id from gameinfo gi, games g where gi.game_id=g.id and g.end_datetime is null and gi.target_id=? and gi.killer_id is null", (id,))
			EditDict = dict()
			EditDict["nickname"] = nickname
			EditDict["firstname"] = firstname
			EditDict["lastname"] = lastname
			EditDict["email"] = email
			EditDict["smacktalk"] = smack
			EditDict["email_newgames"] = email_newgames

			EditDict["SubSection"] = []
			if(reportrow == None or len(reportrow) == 0):
				EditDict["SubSection"].append(("report_kill", []))
			else:
				EditDict["SubSection"].append(("report_kill", [{"id":""}]))
			
			ProfileHTML = html.HTMLReplaceSection(self.ValidateLogin(), "edit", ProfileHTML, [EditDict])

			#see if we have a target
			(ret, rows) = db.fetchAll(cherrypy.thread_data.conn,"select a.firstname, a.lastname, a.nickname, a.picture_filename, gi.killer_id, gi.target_id, ifnull(gi.kill_datetime, datetime('now')) as killdatetime from assassins a, gameinfo gi, games g where g.end_datetime is null and gi.game_id = g.id and gi.assassin_id=? and a.id=gi.target_id order by killdatetime desc", (id,))
			if(len(rows) == 0):
				ProfileHTML = html.HTMLRemoveSection(self.ValidateLogin(), "target", ProfileHTML)
				ProfileHTML = html.HTMLRemoveSection(self.ValidateLogin(), "target_header", ProfileHTML)
			else:
				ProfileHTML = html.HTMLReplaceSection(self.ValidateLogin(), "target_header", ProfileHTML, [{"id":""}])

				targets = []
				for Entry in rows:
					NewTarget = dict()
					(NewTarget["firstname"], NewTarget["lastname"], NewTarget["nickname"], NewTarget["target_pic"], killer_id, target_id, kill_datetime) = Entry
					if(NewTarget["target_pic"] == None):
						NewTarget["target_pic"] = "images/bio-pic.jpg"
					else:
						NewTarget["target_pic"] = "profile-images/" + NewTarget["target_pic"]

					NewTarget["SubSection"] = []
					if(killer_id == None):
						NewTarget["SubSection"].append(("kill_target", [{"id":target_id}]))
						NewTarget["SubSection"].append(("target_killed", []))
					elif(killer_id == id):
						#report if we killed them
						NewTarget["SubSection"].append(("kill_target", []))
						NewTarget["SubSection"].append(("target_killed", [{"notice":"Target Assassinated"}]))
					elif(killer_id == 0):
						#report if they survived our encounter
						NewTarget["SubSection"].append(("kill_target", []))
						NewTarget["SubSection"].append(("target_killed", [{"notice":"Target Survived"}]))
					else:
						#someone else killed them
						NewTarget["SubSection"].append(("kill_target", []))
						NewTarget["SubSection"].append(("target_killed", [{"notice":"Target Assassinated by Another Assassin"}]))
						

					if(killer_id == None):
						targets.insert(0, NewTarget)
					else:
						targets.append(NewTarget)

				ProfileHTML = html.HTMLReplaceSection(self.ValidateLogin(), "target", ProfileHTML, targets)

		(ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select count(killer_id) from gameinfo where killer_id=?", (id,))
		if(ret == False or row == None or len(row) == 0):
			return html.display_message(self.ValidateLogin(), "Error getting kill list")
		(total_assassinations,) = row

                (ret, row) = db.fetchOne(cherrypy.thread_data.conn,"select count(target_id) from gameinfo where target_id=? and killer_id != 0", (id,))
		if(ret == False or row == None or len(row) == 0):
                        return html.display_message(self.ValidateLogin(), "Error getting death list")
                (total_deaths,) = row

		ProfileHTML = html.HTMLReplaceSection(self.ValidateLogin(), "profile", ProfileHTML, [{"nickname":nickname, "firstname":firstname, "lastname":lastname, "email":email, "rank":ranking, "smacktalk":smack, "total_assassinations":total_assassinations, "total_deaths":total_deaths, "profile_pic": picture_filename}])

		StatData = []

		sql = "select g.id, g.start_datetime [timestamp], g.end_datetime [timestamp], a.nickname, a.firstname, a.lastname, gi.killer_id, gi.ranking from games g, gameinfo gi left join assassins a on gi.killer_id=a.id where gi.game_id=g.id and gi.target_id=? and gi.ranking is not null"
		if(id != cherrypy.session.get("ProfileID")):
			sql = sql + " and g.end_datetime is not null"
		sql = sql + " order by g.id desc"
		(ret, rows) = db.fetchAll(cherrypy.thread_data.conn,sql, (id,))

		if(len(rows) == 0):
			ProfileHTML = html.HTMLRemoveSection(self.ValidateLogin(), "game", ProfileHTML)
		else:
			for Entry in rows:
				dictEntry = dict()
				(game_id, dictEntry["game_start"], dictEntry["game_end"], killer_nickname, killer_firstname, killer_lastname, killer_id, ranking) = Entry
				dictEntry["game_start"] = dictEntry["game_start"].strftime("%b %d, %Y")
				if(dictEntry["game_end"] != None):
					dictEntry["game_end"] = dictEntry["game_end"].strftime("%b %d, %Y")
				dictEntry["rank"] = html.ordinal(ranking)
				if(killer_id == None or killer_id == 0):
					dictEntry["assassinated_by"] = ""
				else:
					dictEntry["assassinated_by"] = str(killer_firstname) + " " + str(killer_lastname) + " (" + str(killer_nickname) + ")"		

				(ret, subrows) = db.fetchAll(cherrypy.thread_data.conn,"select a.nickname, a.firstname, a.lastname, gi.kill_datetime [timestamp], a.id from assassins a, gameinfo gi where gi.killer_id=? and gi.game_id=? and a.id=gi.target_id order by gi.kill_datetime asc", (id, game_id))
				dictEntry["total_assassinations"] = len(subrows)
				dictEntry["SubSection"] = []
				SubSection = []
				if(len(subrows) == 0):
					SubSection.append({"kill_date":"", "rank":"", "name":"", "profile_id":""})
				else:
					for SubEntry in subrows:
						NewEntry = dict()
						(killed_nickname, killed_firstname, killed_lastname, NewEntry["kill_date"], NewEntry["profile_id"]) = SubEntry
						NewEntry["rank"] = html.ordinal(0)
						NewEntry["name"] = str(killed_firstname) + " " + str(killed_lastname) + " (" + str(killed_nickname) + ")"
						NewEntry["kill_date"] = NewEntry["kill_date"].strftime("%b %d, %Y %H:%M")
						SubSection.append(NewEntry)
				dictEntry["SubSection"].append(("game_player", SubSection))

				StatData.append(dictEntry)

			ProfileHTML = html.HTMLReplaceSection(self.ValidateLogin(), "game", ProfileHTML, StatData)

		return ProfileHTML
Beispiel #24
0
def sync_opposing_move(methods=['GET', 'POST']):
    room = session.get('session_id')
    gameSession = db.fetchOne({'_id': ObjectId(room)})
    session['board_state'], session['phase'] = [
        gameSession[attribute] for attribute in ['board_state', 'phase']
    ]
Beispiel #25
0
def handle_board_state_change(json, methods=['GET', 'POST']):
    print('received board state: ' + str(json))
    username = session['user_id']
    room = session.get('session_id')
    board_state = session.get('board_state')
    board_state = {
        row: {
            key: {
                'color': value['color'],
                'piece': value['piece']
            }
            for key, value in sorted(board_state[row].items(),
                                     key=lambda item: int(item[0]))
        }
        for row in board_state
    }
    origin_row = json['origin_cell'][0]
    origin_col = json['origin_cell'][1]
    destination_row = json['destination_cell'][0]
    destination_col = json['destination_cell'][1]

    unplaced_pieces = session.get('unplaced_pieces')
    if json['origin_cell'] != ['', '']:
        board_state[origin_row][origin_col]['piece'] = ""
        board_state[origin_row][origin_col]['color'] = "none"
    else:
        for piece in unplaced_pieces:
            if piece[0] == json['moved_piece']['piece']:
                piece[1] -= 1

    #if two pieces from different teams collide, do battle

    def combat(piece1, piece2):
        # if piece being attacked is a flag, end the game
        if piece2['piece'] == '#':
            game_over = True
        else:
            game_over = False

        # determine winning piece
        if auth.pieces_reference[piece1['piece']].weakness == piece2['piece']:
            result = piece2
        elif auth.pieces_reference[
                piece2['piece']].weakness == piece1['piece']:
            result = piece1
        elif auth.pieces_reference[piece1[
                'piece']].rank < auth.pieces_reference[piece2['piece']].rank:
            result = piece1
        elif auth.pieces_reference[piece1[
                'piece']].rank == auth.pieces_reference[piece2['piece']].rank:
            result = {'piece': "", 'color': 'none'}
        elif auth.pieces_reference[piece1[
                'piece']].rank > auth.pieces_reference[piece2['piece']].rank:
            result = piece2

        return result, game_over

    if board_state[destination_row][destination_col]['color'] not in [
            'none', json['moved_piece']['color']
    ]:
        json['moved_piece'], json['game_over'] = combat(
            json['moved_piece'], board_state[destination_row][destination_col])
        print(json)
        socketio.emit('own combat result', json, room=room)

    board_state[destination_row][destination_col] = json['moved_piece']

    # fetch room info from db
    gameSession = db.fetchOne({'_id': ObjectId(room)})
    # update unplaced pieces record
    gameSession['unplaced_pieces'][username] = unplaced_pieces
    current_phase = gameSession['phase']

    # sum up total pieces unplaced, change phases if necessary
    total_pieces = 0
    if current_phase == "preparation":
        for user in gameSession['unplaced_pieces']:
            for piece in gameSession['unplaced_pieces'][user]:
                total_pieces += piece[1]
        # check if both players have entered the game and placed all their pieces
        if (total_pieces == 0) and (len(gameSession['unplaced_pieces']) == 2):
            current_phase = "blue"

    elif current_phase == "blue":
        current_phase = "red"

    elif current_phase == "red":
        current_phase = "blue"

    try:
        if json['game_over'] == True:
            current_phase = json['responsible_team'] + '_wins'
    except KeyError:
        pass

    json['phase'] = current_phase
    # emit response to clients
    socketio.emit('my response', json, callback=messageReceived, room=room)

    # update unplaced pieces record for this player, to be re-inserted in db below
    gameSession['unplaced_pieces'][username] = unplaced_pieces
    # update board state, phase, and unplaced pieces records in database
    db.updateOne({'_id': ObjectId(room)}, {
        '$set': {
            'board_state': board_state,
            'unplaced_pieces': gameSession['unplaced_pieces'],
            'phase': current_phase
        }
    })
    # update same attributes from above in user's session cookie
    session['board_state'], session['unplaced_pieces'], session[
        'phase'] = board_state, unplaced_pieces, current_phase
    print(board_state)