I've been wanting to do an example of using a database with pyinsim for a while, so I knocked up a quick script today. It's a simple lapper app that tracks a users fastest lap on track and stores it in a SQLite database. SQLite is great for this as it comes as part of the Python installation, meaning you don't need to do any setup to use it. Right now the script is very simple, it just sends a message whenever you cross the start/finish line, but I hope to update it more when I have some free time. I'm not a database whizz, so my SQL code might not be the best, but for as simple an app as this it should suffice.
import sqlite3
import pyinsim
# Constants.
DB_NAME = 'lapper.db'
HOST = '127.0.0.1'
PORT = 29999
ADMIN = ''
NAME = 'PyLapper'
# Class to represent the database.
class LapperDB(object):
def __init__(self, db_name):
self.db_name = db_name
def __enter__(self):
self.db = sqlite3.connect(self.db_name)
self.db.text_factory = str # Set text-mode to ASCII
self.db.row_factory = sqlite3.Row
return self
def __exit__(self, type, value, traceback):
self.db.close()
def table_exists(self, table_name):
return self.db.execute('SELECT name FROM sqlite_master WHERE name=?', [table_name]).fetchone()
def init_db(self):
# Create laps table if it does not exist.
if not self.table_exists('laps'):
self.db.execute('CREATE TABLE laps (uname TEXT, track TEXT, car TEXT, ltime INT)')
def get_lap(self, uname, track, car):
conn = self.db.execute('SELECT ltime FROM laps WHERE uname=? AND track=? AND car=?', [uname, track, car])
return conn.fetchone()
def add_lap(self, uname, track, car, ltime):
self.db.execute('INSERT INTO laps (uname, track, car, ltime) VALUES (?, ?, ?, ?)', [uname, track, car, ltime])
def update_lap(self, uname, track, car, ltime):
self.db.execute('UPDATE laps SET ltime=? WHERE uname=? AND track=? AND car=?', [ltime, uname, track, car])
def commit(self):
# Save changes to database.
self.db.commit()
# Globals.
connections = {}
players = {}
track = None
def joined_multiplayer(insim, ism):
# When joined host ask for all players/connections.
insim.send(pyinsim.ISP_TINY, SubT=pyinsim.TINY_NCN, ReqI=1)
insim.send(pyinsim.ISP_TINY, SubT=pyinsim.TINY_NPL, ReqI=1)
def state_changed(insim, sta):
# Keep track of current track.
global track
track = sta.Track
def new_connection(insim, ncn):
connections[ncn.UCID] = ncn
def connection_left(insim, cnl):
del connections[cnl.UCID]
def new_player(insim, npl):
players[npl.PLID] = npl
def player_left(insim, pll):
del players[pll.PLID]
def lap_completed(insim, lap):
# Get player/connection from list.
npl = players[lap.PLID]
ncn = connections[npl.UCID]
# Open DB connection.
with LapperDB(DB_NAME) as db:
# Get lap for this car/track.
row = db.get_lap(ncn.UName, track, npl.CName)
if not row:
# No lap exists.
db.add_lap(ncn.UName, track, npl.CName, lap.LTime)
db.commit()
insim.sendm('first lap on %s/%s' % (track, npl.CName), ncn.UCID)
elif lap.LTime < row['ltime']:
# New fastest lap.
db.update_lap(ncn.UName, track, npl.CName, lap.LTime)
db.commit()
insim.sendm('fastest lap: %s' % pyinsim.timestr(lap.LTime), ncn.UCID)
else:
# Slower lap.
insim.sendm('slower lap: %s' % pyinsim.timestr(lap.LTime), ncn.UCID)
def error(insim, err):
print 'Error:', err
def closed(insim):
print 'Error: no host connected'
def init(insim):
print 'Connected to host (%s:%d)' % (insim.hostaddr[0], insim.hostaddr[1])
def main():
print NAME
print ''.rjust(len(NAME), '-')
# Init DB and create laps table.
print 'Initializing database...',
with LapperDB(DB_NAME) as db:
db.init_db()
print 'done'
# Init InSim and bind events.
insim = pyinsim.insim(HOST, PORT, Admin=ADMIN, IName=NAME)
insim.bind(pyinsim.EVT_ERROR, error)
insim.bind(pyinsim.EVT_CLOSE, closed)
insim.bind(pyinsim.EVT_INIT, init)
insim.bind(pyinsim.ISP_ISM, joined_multiplayer)
insim.bind(pyinsim.ISP_STA, state_changed)
insim.bind(pyinsim.ISP_NCN, new_connection)
insim.bind(pyinsim.ISP_CNL, connection_left)
insim.bind(pyinsim.ISP_NPL, new_player)
insim.bind(pyinsim.ISP_PLL, player_left)
insim.bind(pyinsim.ISP_LAP, lap_completed)
# On connecting request state and host packet.
insim.send(pyinsim.ISP_TINY, SubT=pyinsim.TINY_SST, ReqI=1)
insim.send(pyinsim.ISP_TINY, SubT=pyinsim.TINY_ISM, ReqI=1)
# Start packet receive loop.
pyinsim.run()
if __name__ == '__main__':
main()