Added commands and interface support for the new shops. Also changed how linked objects handle printing.

doc_update
Joey Hines 2018-07-20 20:50:24 -05:00
parent 29673bdfe8
commit 625e4dc796
4 changed files with 106 additions and 27 deletions

View File

@ -21,7 +21,7 @@ class UsernameLookupFailed(Exception):
class PlayerNotFound(DataBaseError):
'''Player not found in database.'''
class LocationNameNotUniqueError(DataBaseError):
class EntryNameNotUniqueError(DataBaseError):
'''A location by that name is already in the database.'''

View File

@ -11,6 +11,7 @@ from difflib import SequenceMatcher
SQL_Base = declarative_base()
def check_similarity(a, b):
ratio = SequenceMatcher(None, a, b).ratio()
@ -19,6 +20,7 @@ def check_similarity(a, b):
else:
return False
class DatabaseInterface:
def __init__(self, db_engine_arg):
@ -34,6 +36,23 @@ class DatabaseInterface:
self.database.add_object(shop)
return shop
def add_tunnel(self, owner, color, number, location_name):
if location_name is None:
if len(self.find_tunnel_by_owner(owner)):
raise EntryNameNotUniqueError
else:
location = None
else:
try:
location = self.find_location_by_name_and_owner(owner, location_name)[0]
except IndexError:
raise LocationLookUpError
tunnel = Tunnel(owner, color, number, location)
self.database.add_object(tunnel)
return tunnel
def add_item(self, owner, shop_name, item_name, price, amount):
try:
shop = self.find_shop_by_name_and_owner(owner, shop_name)
@ -75,8 +94,8 @@ class DatabaseInterface:
return self.database.query_by_filter(Location, expr)
def find_location_by_owner_name(self, owner_name):
owner = self.find_player(owner_name)
return self.find_location_by_owner(owner)
expr = Location.owner.has(Player.name.ilike(owner_name))
return self.database.query_by_filter(Location, expr)
def find_shop_by_name_and_owner(self, owner, name):
expr = (Shop.owner == owner) & (Shop.name.ilike(name))
@ -93,6 +112,15 @@ class DatabaseInterface:
return self.database.query_by_filter(Location, expr)
def find_tunnel_by_owner(self, owner):
expr = Tunnel.owner == owner
return self.database.query_by_filter(Tunnel, expr)
def find_tunnel_by_owner_name(self, owner_name):
expr = Tunnel.owner.has(Player.name.ilike(owner_name))
return self.database.query_by_filter(Tunnel, expr)
def find_item(self, item_name):
expr = ItemListing.name.ilike('%{}%'.format(item_name))
return self.database.query_by_filter(ItemListing, expr)
@ -157,6 +185,10 @@ class DiscordDatabaseInterface(DatabaseInterface):
owner = DatabaseInterface.find_player_by_discord_uuid(self, owner_uuid)
return DatabaseInterface.add_shop(self, owner, name, x_pos, y_pos, z_pos, dimension)
def add_tunnel(self, owner_uuid, color, number, location_name=""):
owner = DatabaseInterface.find_player_by_discord_uuid(self, owner_uuid)
return DatabaseInterface.add_tunnel(self, owner, color, number, location_name)
def add_item(self, owner_uuid, shop_name, item_name, price, amount):
owner = DatabaseInterface.find_player_by_discord_uuid(self, owner_uuid)
return DatabaseInterface.add_item(self, owner, shop_name, item_name, price, amount)
@ -209,7 +241,7 @@ class GeoffreyDatabase:
self.session.add(obj)
self.session.commit()
except IntegrityError:
raise LocationNameNotUniqueError
raise EntryNameNotUniqueError
def query_by_filter(self, obj_type, * args):
filter_value = self.combine_filter(args)
@ -309,7 +341,7 @@ class Tunnel(SQL_Base):
raise TunnelInitError
def __str__(self):
return '{} {} {}'.format(self.tunnel_direction.value.title(), self.tunnel_number)
return '{} {}'.format(self.tunnel_direction.value.title(), self.tunnel_number)
class Location(SQL_Base):
__tablename__ = 'Locations'
@ -320,7 +352,7 @@ class Location(SQL_Base):
y = Column(Integer)
z = Column(Integer)
tunnel = relationship("Tunnel", back_populates="location")
tunnel = relationship("Tunnel", back_populates="location", uselist=False)
dimension = Column(Enum(Dimension))
owner_id = Column(Integer, ForeignKey('Players.id'))
@ -369,6 +401,18 @@ class Shop(Location):
'polymorphic_identity': 'Shop',
}
def inv_to_str(self):
inv = ''
str_format = '{}\n\t{}'
for item in self.inventory:
inv = str_format.format(inv, item)
return inv
def __str__(self):
return Location.__str__(self) + "\n\t*Inventory*: {}".format(self.inv_to_str())
def __init__(self, name, x, y, z, owner, dimension=None):
Location.__init__(self, name, x, y, z, owner, dimension)

View File

@ -49,7 +49,7 @@ async def on_command_error(error, ctx):
elif isinstance(error.original, PlayerNotFound):
error_str = 'Make sure to use ?register first you ding dong.'
database_interface.database.session.rollback()
elif isinstance(error.original, LocationNameNotUniqueError):
elif isinstance(error.original, EntryNameNotUniqueError):
error_str = 'An entry in the database already has that name ding dong.'
database_interface.database.session.rollback()
else:
@ -65,6 +65,7 @@ async def test():
'''
await bot.say('I\'m here you ding dong')
@bot.command(pass_context=True)
async def register(ctx):
'''
@ -86,43 +87,44 @@ async def register(ctx):
async def addbase(ctx, x_pos: int, y_pos: int, z_pos: int, * args):
'''
Adds your base to the database. The name is optional.
?addbase [Shop Name] [X Coordinate] [Y Coordinate] [Z Coordinate] [Name]
?addbase [X Coordinate] [Y Coordinate] [Z Coordinate] [Base Name]
'''
if len(args) > 0:
name = args[0]
else:
name = '{}\'s Base'.format(database_interface.find_player_by_discord_uuid(ctx.message.author.id).name)
name = '{}\'s_Base'.format(database_interface.find_player_by_discord_uuid(ctx.message.author.id).name)
try:
base = database_interface.add_location(ctx.message.author.id, name, x_pos, y_pos, z_pos)
except LocationInitError:
raise commands.UserInputError
except LocationNameNotUniqueError:
await bot.say('{}, you already have a based called {}. You need to specify a different name.'.format(
except EntryNameNotUniqueError:
await bot.say('{}, a based called {} already exists. You need to specify a different name.'.format(
ctx.message.author.mention, name))
return
await bot.say('{}, your base named **{}** located at {} has been added'
' to the database.'.format(ctx.message.author.mention, base.name, base.pos_to_str()))
@bot.command(pass_context=True)
async def addshop(ctx, x_pos: int, y_pos: int, z_pos: int, *args):
'''
Adds your shop to the database. The name is optional.
?addshop [Shop Name] [X Coordinate] [Y Coordinate] [Z Coordinate] [Name]
?addshop [X Coordinate] [Y Coordinate] [Z Coordinate] [Shop Name]
'''
if len(args) > 0:
name = args[0]
else:
name = '{}\'s Shop'.format(database_interface.find_player_by_discord_uuid(ctx.message.author.id).name)
name = '{}\'s_Shop'.format(database_interface.find_player_by_discord_uuid(ctx.message.author.id).name)
try:
shop = database_interface.add_shop(ctx.message.author.id, name, x_pos, y_pos, z_pos)
except LocationInitError:
raise commands.UserInputError
except LocationNameNotUniqueError:
await bot.say('{}, you already have a shop called {}. You need to specify a different name.'.format(
except EntryNameNotUniqueError:
await bot.say('{}, a shop called {} already exists. You need to specify a different name.'.format(
ctx.message.author.mention, name))
return
@ -130,6 +132,35 @@ async def addshop(ctx, x_pos: int, y_pos: int, z_pos: int, *args):
' to the database.'.format(ctx.message.author.mention, shop.name, shop.pos_to_str()))
@bot.command(pass_context=True)
async def tunnel(ctx, tunnel_color: str, tunnel_number: int, *args):
'''
Adds your tunnel to the database. The location name is optional. If the location has a tunnel, it is updated.
?addtunnel [Tunnel Color] [Tunnel_Number] [Location Name]
'''
try:
if len(args) == 0:
location_name = None
else:
location_name = args[0]
database_interface.add_tunnel(ctx.message.author.id, tunnel_color, tunnel_number, location_name)
except EntryNameNotUniqueError:
await bot.say('{}, you already have one tunnel in the database, please specify a location.'.format(
ctx.message.author.mention))
return
except LocationLookUpError:
await bot.say('{}, you do not have a location called {}.'.format(
ctx.message.author.mention, args[0]))
return
except ValueError:
raise commands.UserInputError
await bot.say('{}, your tunnel has been added to the database'.format(ctx.message.author.mention))
@bot.command(pass_context=True)
async def find(ctx, name: str):
'''
@ -146,6 +177,7 @@ async def find(ctx, name: str):
except PlayerNotFound:
await bot.say('{}, the player **{}** is not in the database'.format(ctx.message.author.mention, name))
@bot.command(pass_context=True)
async def delete(ctx, name: str):
'''
@ -219,7 +251,7 @@ async def additem(ctx, shop_name: str, item_name: str, amount: int, diamond_pric
@bot.command(pass_context=True)
async def selling(ctx, item_name: str):
async def selling(item_name: str):
'''
Lists all the shops selling an item
@ -232,20 +264,15 @@ async def selling(ctx, item_name: str):
@bot.command(pass_context=True)
async def shopinfo(ctx, shop_name: str):
async def info(name: str):
'''
Lists the information and inventory of a shop
Displays a location's info including inventory its a shop
?shopinfo [Shop Name]
?info [Location Name]
'''
shop = database_interface.find_shop_by_name(shop_name)[0]
inv_list = database_interface.get_shop_inventory(shop)
loc = database_interface.find_location_by_name(name)[0]
item_list = ''
for item in inv_list:
item_list = item_list + '{}\n'.format(item.__str__())
await bot.say('{} \n Inventory:\n {}'.format(shop.__str__(), item_list))
await bot.say('{}'.format(loc))
# Helper Functions ************************************************************

View File

@ -71,6 +71,14 @@ class TestGeoffreyDatabase(TestCase):
self.assertEqual(loc_list[1].id, shop2.id)
def test_add_tunnel(self):
self.add_player()
args=[]
tunnel1 = self.interface.add_tunnel('143072699567177728', 'green', 155, None)
tunnel2 = self.interface.find_tunnel_by_owner_name('ZeroHD')[0]
self.assertEqual(tunnel1, tunnel2)
def test_add_item(self):
owner = self.add_player()
self.add_shop()
@ -180,7 +188,7 @@ class TestGeoffreyDatabase(TestCase):
self.add_player()
self.add_loc()
self.assertRaises(LocationNameNotUniqueError, self.interface.add_location,
self.assertRaises(EntryNameNotUniqueError, self.interface.add_location,
'143072699567177728', 'test', 0, 0, 0)