Module swordie_db.character
This module holds the Character class for the SwordieDB package.
Copyright 2020 TEAM SPIRIT. All rights reserved. Use of this source code is governed by a MIT-style license that can be found in the LICENSE file. Refer to database.py or the project wiki on GitHub for usage examples.
Expand source code
"""This module holds the Character class for the SwordieDB package.
Copyright 2020 TEAM SPIRIT. All rights reserved.
Use of this source code is governed by a MIT-style license that can be found in the LICENSE file.
Refer to database.py or the project wiki on GitHub for usage examples.
"""
import mysql.connector as con
from swordie_db import JOBS
from swordie_db.inventory import Inventory
from swordie_db.user import User
class Character:
"""Character object; models SwordieMS characters.
Using instance method SwordieDB::get_char_by_name(name) will create a Character object instance with
attributes identical to the character with IGN "name" in the connected Swordie-based database.
This class contains the appropriate getter and setter methods for said attributes.
Attributes:
user: User, A User object
stats: Dictionary of all character stats obtained from the characterstats table
level: Integer, representing character level
job: Integer, representing character job ID
name: String, representing character name (aka IGN)
money: String, representing character wealth (aka Meso count)
fame: Integer, representing character popularity
map: String, representing the Map ID of the map that the character is currently in
face: Integer, representing the Face ID of the character
hair: Integer, representing the Hair ID of the character
skin: Integer, representing the Skin ID of the character
exp: String, representing character EXP pool (amount)
strength: Integer, representing character STR stat pool
dex: Integer, representing character DEX stat pool
inte: Integer, representing character INT stat pool
luk: Integer, representing character LUK stat pool
max_hp: Integer, representing character Max HP stat pool
max_mp: Integer, representing character Max MP stat pool
ap: Integer, representing character free Ability Points (AP) pool
sp: Integer, representing character free SP points pool
equip_inv_id: Integer, representing the "equip" inventory id
equipped_inv_id: Integer, representing the "equipped" (i.e. Hotkey "E" in-game) inventory id
consume_inv_id: Integer, representing "consume" (aka USE) inventory id
etc_inv_id: Integer, representing "etc" (aka ETC) inventory id
install_inv_id: Integer, representing "install" (aka SETUP) inventory id
cash_inv_id: Integer, representing "cash" (aka CASH) inventory id
"""
def __init__(self, char_stats, database_config):
"""Emulates how character object is handled server-sided
Args:
char_stats: dictionary of character stats, formatted in SwordieMS style
database_config: dictionary of protected attributes from a SwordieDB object
"""
self._stats = char_stats
self._database_config = database_config
self._vague_id = 0
self._character_id = 0
self._character_id_for_log = 0
self._world_id = 0
self._name = ""
self._gender = 0
self._skin = 0
self._face = 0
self._hair = 0
self._mix_base_hair_color = 0
self._mix_add_hair_color = 0
self._mix_hair_base_prob = 0
self._level = 0
self._job = 0
self._strength = 0
self._dex = 0
self._inte = 0
self._luk = 0
self._hp = 0
self._max_hp = 0
self._mp = 0
self._max_mp = 0
self._ap = 0
self._sp = 0
self._exp = 0
self._pop = 0 # fame
self._money = 0
self._wp = 0
self._position_map = 0
self._portal = 0
self._sub_job = 0
self.init_stats()
# These attributes are separate from characterstats table in database
self._equip_inv_id = 0
self._equipped_inv_id = 0
self._consume_inv_id = 0
self._etc_inv_id = 0
self._install_inv_id = 0
self._cash_inv_id = 0
self._inventory = None
# Create Inventory object instance via class constructor, using details from Character object instance
self.init_inv_id()
# Create User object instance via class constructor, using details from Character object instance
self._user = self.init_user()
def init_stats(self):
"""Given a dictionary of stats from Swordie's DB we add them to Character object's attributes
Runs near the end of Character::__init__(char_stats, database_config).
It assigns the character attributes in char_stats to their respective protected attributes belonging to
the Character object instance.
"""
self._vague_id = self._stats["id"]
self._character_id = self._stats["characterid"]
self._character_id_for_log = self._stats["characteridforlog"]
self._world_id = self._stats["worldidforlog"]
self._name = self._stats["name"]
self._gender = self._stats["gender"]
self._skin = self._stats["skin"]
self._face = self._stats["face"]
self._hair = self._stats["hair"]
self._mix_base_hair_color = self._stats["mixbasehaircolor"]
self._mix_add_hair_color = self._stats["mixaddhaircolor"]
self._mix_hair_base_prob = self._stats["mixhairbaseprob"]
self._level = self._stats["level"]
self._job = self._stats["job"]
self._strength = self._stats["str"]
self._dex = self._stats["dex"]
self._inte = self._stats["inte"]
self._luk = self._stats["luk"]
self._hp = self._stats["hp"]
self._max_hp = self._stats["maxhp"]
self._mp = self._stats["mp"]
self._max_mp = self._stats["maxmp"]
self._ap = self._stats["ap"]
self._sp = self._stats["sp"]
self._exp = self._stats["exp"]
self._pop = self._stats["pop"] # fame
self._money = self._stats["money"]
self._wp = self._stats["wp"]
self._position_map = self._stats["posmap"]
self._portal = self._stats["portal"]
self._sub_job = self._stats["subjob"]
def init_user(self):
"""Fetch a dictionary of user attributes from Swordie's DB and use it to instantiate a new User object
Runs at the end of Character::__init__(char_stats, database_config).
Checks the User ID associated with the character instance, and uses the User class constructor to create
a new User object instance, with the relevant user attributes from the database.
Returns:
User object with attributes identical to its corresponding entry in the database
Raises:
Generic error on failure - handled by the Character::get_db() method
"""
user_id = self.get_user_id()
user_stats = self.get_db(
self._database_config,
f"SELECT * FROM users WHERE id = '{user_id}'"
) # The row will always be 0 because there should be no characters with the same name
user = User(user_stats, self.database_config)
return user
def init_inv_id(self):
"""Fetch a dictionary of user attributes from Swordie's DB and use it to instantiate a new (custom) Inventory object
(Stipulated algorithm for unfinished sequence)
Runs near the end of Character::__init__(char_stats, database_config).
Uses the Character ID associated with the character instance, and the Inventory class constructor to create
a new Inventory object instance, with the relevant character attributes from the database.
Raises:
Generic error on failure - handled by the Character::get_db() method
"""
inventory_ids = self.get_db(
self._database_config,
f"SELECT equippedinventory, equipinventory, consumeinventory, etcinventory, installinventory, cashinventory "
f"FROM characters WHERE id = '{self.character_id}'"
) # The row will always be 0 because there should be no characters with the same ID
self._equip_inv_id = inventory_ids["equipinventory"]
self._equipped_inv_id = inventory_ids["equippedinventory"]
self._consume_inv_id = inventory_ids["consumeinventory"]
self._etc_inv_id = inventory_ids["etcinventory"]
self._install_inv_id = inventory_ids["installinventory"]
self._cash_inv_id = inventory_ids["cashinventory"]
self._inventory = Inventory(self.get_inventory_ids(), self.database_config)
# Static method for fetching DB
@staticmethod
def get_db(config, query):
"""Generic static method for fetching data from DB using the provided DB config and query
This method assumes that only one character is found - it always defaults to the first result.
An effort has been made to convert this to a decorator so that it may also be applied to
Character::set_stat_by_column() & Character::get_user_id(), which ultimately ended in failure.
Args:
config, dictionary, representing database config attributes
query, String, representing SQL query
Returns:
String representing the result of the provided SQL query, using the provided DB connection attributes
"""
try:
database = con.connect(
host=config["host"],
user=config["user"],
password=config["password"],
database=config["schema"],
port=config["port"]
)
cursor = database.cursor(dictionary=True)
cursor.execute(query)
data = cursor.fetchall()[0]
database.disconnect()
return data
except Exception as e:
print("CRITICAL: Error encountered whilst attempting to connect to the database! \n", e)
@property
def database_config(self):
return self._database_config
@property
def stats(self):
return self._stats
@property
def character_id(self):
return self._character_id
@property
def level(self):
return self._level
@level.setter
def level(self, x):
self.set_stat_by_column("level", x)
self._level = x
def add_level(self, amount):
"""Adds the specified amount to the current level count
Args:
amount: Int, representing the number of levels to be added to the current count
"""
new_level = int(self.level) + amount
self.level = new_level
@property
def job(self):
return self._job
@job.setter
def job(self, job_id):
self.set_stat_by_column("job", job_id)
self._job = job_id
def get_job_name(self):
"""Returns the actual name of the job from job id
Returns:
String, representing the job name corresponding to a job ID
"""
return JOBS[str(self.job)]
def get_gender_name(self):
if self._gender == 0:
return "Male"
return "Female"
@property
def name(self):
return self._name
@name.setter
def name(self, new_name):
"""Set a new name for the character
Args:
new_name: string, representing the new character name that will be set in the database
"""
self.set_stat_by_column("name", new_name)
self._name = new_name
@property
def money(self):
return self._money
@money.setter
def money(self, amount):
self.set_stat_by_column("money", amount)
self._money = amount
def add_mesos(self, amount):
"""Adds the specified amount to the current meso count
Args:
amount: Int, representing the amount of mesos to be added to the current count
"""
new_amount = int(self.money) + amount
self.money = str(new_amount) # money is a String; converting back to String for consistency
@property
def fame(self):
return self._pop
@fame.setter
def fame(self, amount):
self.set_stat_by_column("pop", amount)
self._pop = amount
def add_fame(self, amount):
"""Adds the specified amount to the current fame count
Args:
amount: Int, representing the number of fames to be added to the current count
"""
new_fame = int(self.fame) + amount
self.fame = new_fame
@property
def map(self):
return self._position_map
@map.setter
def map(self, map_id):
self.set_stat_by_column("posmap", map_id)
self._position_map = map_id
@property
def face(self):
return self._face
@face.setter
def face(self, face_id):
self.set_stat_by_column("face", face_id)
self._face = face_id
@property
def hair(self):
return self._hair
@hair.setter
def hair(self, hair_id):
self.set_stat_by_column("hair", hair_id)
self._hair = hair_id
@property
def skin(self):
return self._skin
@skin.setter
def skin(self, skin_id):
self.set_stat_by_column("skin", skin_id)
self._skin = skin_id
@property
def exp(self):
return self._exp
@exp.setter
def exp(self, exp_amount):
self.set_stat_by_column("exp", exp_amount)
self._exp = exp_amount
def add_exp(self, amount):
"""Add the specified amount to the current existing EXP pool
Args:
amount: Int, representing the amount of EXP to be added to the current pool
"""
new_exp = int(self.exp) + amount
self.exp = str(new_exp) # EXP is a String; converting back to String for consistency
@property
def strength(self):
return self._strength
@strength.setter
def strength(self, amount):
self.set_stat_by_column("str", amount)
self._strength = amount
def add_str(self, amount):
"""Add the specified amount to the current existing STR pool
Args:
amount: Int, representing the amount of STR to be added to the current pool
"""
new_str = int(self.strength) + amount
self.strength = new_str
@property
def dex(self):
return self._dex
@dex.setter
def dex(self, amount):
self.set_stat_by_column("dex", amount)
self._dex = amount
def add_dex(self, amount):
"""Add the specified amount to the current existing DEX pool
Args:
amount: Int, representing the amount of DEX to be added to the current pool
"""
new_dex = int(self.dex) + amount
self.dex = new_dex
@property
def inte(self):
return self._inte
@inte.setter
def inte(self, amount):
self.set_stat_by_column("inte", amount)
self._inte = amount
def add_inte(self, amount):
"""Add the specified amount to the current existing INT pool
Args:
amount: Int, representing the amount of INT to be added to the current pool
"""
new_inte = int(self.inte) + amount
self.inte = new_inte
@property
def luk(self):
return self._luk
@luk.setter
def luk(self, amount):
self.set_stat_by_column("luk", amount)
self._luk = amount
def add_luk(self, amount):
"""Add the specified amount to the current existing LUK pool
Args:
amount: Int, representing the amount of LUK to be added to the current pool
"""
new_luk = int(self.luk) + amount
self.luk = new_luk
def get_primary_stats(self):
"""Returns str, int, dex, luk values in a dictionary
Returns:
dictionary of primary stats
"""
primary_stats = {
"str": self.strength,
"dex": self.dex,
"int": self.inte,
"luk": self.luk
}
return primary_stats
def get_inventory_ids(self):
"""Returns equip_inv_id, equipped_inv_id, consume_inv_id, etc_inv_id, install_inv_id, cash_inv_id in a dict
Returns:
dictionary of all inventory ids from corresponding character
"""
inventory_ids = {
"equip_inv_id": self.equip_inv_id,
"equipped_inv_id": self.equipped_inv_id,
"consume_inv_id": self.consume_inv_id,
"etc_inv_id": self.etc_inv_id,
"install_inv_id": self.install_inv_id,
"cash_inv_id": self.cash_inv_id
}
return inventory_ids
@property
def max_hp(self):
return self._max_hp
@max_hp.setter
def max_hp(self, amount):
self.set_stat_by_column("maxhp", amount)
self._max_hp = amount
def add_max_hp(self, amount):
"""Add the specified amount to the current existing Max HP pool
Args:
amount: Int, representing the amount of Max HP to be added to the current pool
"""
new_hp = int(self.max_hp) + amount
self.max_hp = new_hp
@property
def max_mp(self):
return self._max_mp
@max_mp.setter
def max_mp(self, amount):
self.set_stat_by_column("maxmp", amount)
self._max_mp = amount
def add_max_mp(self, amount):
"""Add the specified amount to the current existing Max MP pool
Args:
amount: Int, representing the amount of max MP to be added to the current pool
"""
new_mp = int(self.max_mp) + amount
self.max_mp = new_mp
@property
def ap(self):
return self._ap
@ap.setter
def ap(self, amount):
self.set_stat_by_column("ap", amount)
self._ap = amount
def add_ap(self, amount):
"""Add the specified amount to the current existing free AP pool
Args:
amount: Int, representing the amount of free AP to be added to the current pool
"""
new_ap = int(self.ap) + amount
self.ap = new_ap
@property
def sp(self):
return self._sp
@sp.setter
def sp(self, amount):
self.set_stat_by_column("sp", amount)
self._sp = amount
def add_sp(self, amount):
"""Add the specified amount to the current existing free SP pool
Args:
amount: Int, representing the amount of free SP to be added to the current pool
"""
new_sp = int(self.sp) + amount
self.sp = new_sp
@property
def user(self):
return self._user
@property
def equipped_inv_id(self):
return self._equipped_inv_id
@property
def consume_inv_id(self):
return self._consume_inv_id
@property
def etc_inv_id(self):
return self._etc_inv_id
@property
def install_inv_id(self):
return self._install_inv_id
@property
def cash_inv_id(self):
return self._cash_inv_id
@property
def equip_inv_id(self):
return self._equip_inv_id
@property
def inventory(self):
return self._inventory
def get_char_img(self):
equipped_items = [self.face, self.hair]
equipped_inv = self.inventory.equipped_inv
for item in equipped_inv:
item_id = equipped_inv[item]["itemid"]
equipped_items.append(item_id)
url = f"https://maplestory.io/api/GMS/216/Character/200{self.skin}/{str(equipped_items)[1:-1]}/stand1/1".replace(" ", "")
return url
@staticmethod
def get_user_id_by_name(config, char_name):
"""Given a character name, retrieve its corresponding user id from database
Used by Character::get_user_id() & SwordieDB::get_user_id_by_name()
There is no direct way of obtaining this information.
Hence, this method will fetch the character ID from the database, using the character name.
Then, fetch the account ID from the database, using the character ID.
Then, fetch the user ID from the database, using the account ID.
Args:
config: dictionary, representing database config attributes
char_name: string, representing the character name in the database
Returns:
String, representing the user ID in the database
Defaults to None if the operation fails.
Raises:
SQL Error 2003: Can't cannect to DB
WinError 10060: No response from DB
List index out of range: Wrong character name
"""
try:
database = con.connect(
host=config["host"],
user=config["user"],
password=config["password"],
database=config["schema"],
port=config["port"]
)
cursor = database.cursor(dictionary=True)
cursor.execute(f"SELECT characterid FROM characterstats WHERE name = '{char_name}'")
char_id = cursor.fetchall()[0]["characterid"]
cursor.execute(f"SELECT accid FROM characters WHERE id = '{char_id}'")
account_id = cursor.fetchall()[0]["accid"]
cursor.execute(f"SELECT userid FROM accounts WHERE id = '{account_id}'")
user_id = cursor.fetchall()[0]["userid"]
database.disconnect()
return user_id
except Exception as e:
print("[ERROR] Error trying to get user id from database.", e)
return None # Return None if there was an error
def get_user_id(self):
"""Queries the database to obtain the User ID associated with this character instance
Uses static method Character::get_user_id_by_name() for core logic
Returns:
Int, representing the User ID
Returns None if User ID is not found
Raises:
Errors are handled and thrown by Character::get_user_id_by_name()
SQL Error 2003: Can't cannect to DB
WinError 10060: No response from DB
List index out of range: Wrong character name
"""
return self.get_user_id_by_name(self._database_config, self._name)
def set_stat_by_column(self, column, value):
"""Update a character's stats from column name in database
Grabs the database attributes provided through the class constructor.
Uses these attributes to attempt a database connection.
Attempts to update the field represented by the provided column in characterstats, with the provided value.
Not recommended to use this alone, as it won't update the character object which this was used from.
Args:
value: int or string, representing the value to be set in the database
column: string, representing the column in the database that is to be updated
Returns:
A boolean representing whether the operation was successful
Raises:
SQL Error 2003: Can't cannect to DB
WinError 10060: No response from DB
List index out of range: Wrong column name
"""
host = self._database_config["host"]
user = self._database_config["user"]
password = self._database_config["password"]
schema = self._database_config["schema"]
port = self._database_config["port"]
try:
database = con.connect(host=host, user=user, password=password, database=schema, port=port)
cursor = database.cursor(dictionary=True)
cursor.execute(f"UPDATE characterstats SET {column} = '{value}' WHERE name = '{self.name}'")
database.commit()
print(f"Successfully updated {column} value for character: {self.name}.")
self._stats[column] = value # Update the stats in the dictionary
database.disconnect()
return True
except Exception as e:
print("[ERROR] Error trying to set stats in database.", e)
return False
def get_stat_by_column(self, column):
"""Given a column name, return its value in the database
Args:
column: string, representing the column in the database from which the value is to be fetched from
Returns:
string, representing the value in the database associated with the provided column
Raises:
Generic error on failure
"""
try:
return self.stats[column]
except Exception as e:
print("[ERROR] Error trying to get stats from given column.", e)
return False
Classes
class Character (char_stats, database_config)
-
Character object; models SwordieMS characters.
Using instance method SwordieDB::get_char_by_name(name) will create a Character object instance with attributes identical to the character with IGN "name" in the connected Swordie-based database. This class contains the appropriate getter and setter methods for said attributes.
Attributes
user
- User, A User object
stats
- Dictionary of all character stats obtained from the characterstats table
level
- Integer, representing character level
job
- Integer, representing character job ID
name
- String, representing character name (aka IGN)
money
- String, representing character wealth (aka Meso count)
fame
- Integer, representing character popularity
map
- String, representing the Map ID of the map that the character is currently in
face
- Integer, representing the Face ID of the character
hair
- Integer, representing the Hair ID of the character
skin
- Integer, representing the Skin ID of the character
exp
- String, representing character EXP pool (amount)
strength
- Integer, representing character STR stat pool
dex
- Integer, representing character DEX stat pool
inte
- Integer, representing character INT stat pool
luk
- Integer, representing character LUK stat pool
max_hp
- Integer, representing character Max HP stat pool
max_mp
- Integer, representing character Max MP stat pool
ap
- Integer, representing character free Ability Points (AP) pool
sp
- Integer, representing character free SP points pool
equip_inv_id
- Integer, representing the "equip" inventory id
equipped_inv_id
- Integer, representing the "equipped" (i.e. Hotkey "E" in-game) inventory id
consume_inv_id
- Integer, representing "consume" (aka USE) inventory id
etc_inv_id
- Integer, representing "etc" (aka ETC) inventory id
install_inv_id
- Integer, representing "install" (aka SETUP) inventory id
cash_inv_id
- Integer, representing "cash" (aka CASH) inventory id
Emulates how character object is handled server-sided
Args
char_stats
- dictionary of character stats, formatted in SwordieMS style
database_config
- dictionary of protected attributes from a SwordieDB object
Expand source code
class Character: """Character object; models SwordieMS characters. Using instance method SwordieDB::get_char_by_name(name) will create a Character object instance with attributes identical to the character with IGN "name" in the connected Swordie-based database. This class contains the appropriate getter and setter methods for said attributes. Attributes: user: User, A User object stats: Dictionary of all character stats obtained from the characterstats table level: Integer, representing character level job: Integer, representing character job ID name: String, representing character name (aka IGN) money: String, representing character wealth (aka Meso count) fame: Integer, representing character popularity map: String, representing the Map ID of the map that the character is currently in face: Integer, representing the Face ID of the character hair: Integer, representing the Hair ID of the character skin: Integer, representing the Skin ID of the character exp: String, representing character EXP pool (amount) strength: Integer, representing character STR stat pool dex: Integer, representing character DEX stat pool inte: Integer, representing character INT stat pool luk: Integer, representing character LUK stat pool max_hp: Integer, representing character Max HP stat pool max_mp: Integer, representing character Max MP stat pool ap: Integer, representing character free Ability Points (AP) pool sp: Integer, representing character free SP points pool equip_inv_id: Integer, representing the "equip" inventory id equipped_inv_id: Integer, representing the "equipped" (i.e. Hotkey "E" in-game) inventory id consume_inv_id: Integer, representing "consume" (aka USE) inventory id etc_inv_id: Integer, representing "etc" (aka ETC) inventory id install_inv_id: Integer, representing "install" (aka SETUP) inventory id cash_inv_id: Integer, representing "cash" (aka CASH) inventory id """ def __init__(self, char_stats, database_config): """Emulates how character object is handled server-sided Args: char_stats: dictionary of character stats, formatted in SwordieMS style database_config: dictionary of protected attributes from a SwordieDB object """ self._stats = char_stats self._database_config = database_config self._vague_id = 0 self._character_id = 0 self._character_id_for_log = 0 self._world_id = 0 self._name = "" self._gender = 0 self._skin = 0 self._face = 0 self._hair = 0 self._mix_base_hair_color = 0 self._mix_add_hair_color = 0 self._mix_hair_base_prob = 0 self._level = 0 self._job = 0 self._strength = 0 self._dex = 0 self._inte = 0 self._luk = 0 self._hp = 0 self._max_hp = 0 self._mp = 0 self._max_mp = 0 self._ap = 0 self._sp = 0 self._exp = 0 self._pop = 0 # fame self._money = 0 self._wp = 0 self._position_map = 0 self._portal = 0 self._sub_job = 0 self.init_stats() # These attributes are separate from characterstats table in database self._equip_inv_id = 0 self._equipped_inv_id = 0 self._consume_inv_id = 0 self._etc_inv_id = 0 self._install_inv_id = 0 self._cash_inv_id = 0 self._inventory = None # Create Inventory object instance via class constructor, using details from Character object instance self.init_inv_id() # Create User object instance via class constructor, using details from Character object instance self._user = self.init_user() def init_stats(self): """Given a dictionary of stats from Swordie's DB we add them to Character object's attributes Runs near the end of Character::__init__(char_stats, database_config). It assigns the character attributes in char_stats to their respective protected attributes belonging to the Character object instance. """ self._vague_id = self._stats["id"] self._character_id = self._stats["characterid"] self._character_id_for_log = self._stats["characteridforlog"] self._world_id = self._stats["worldidforlog"] self._name = self._stats["name"] self._gender = self._stats["gender"] self._skin = self._stats["skin"] self._face = self._stats["face"] self._hair = self._stats["hair"] self._mix_base_hair_color = self._stats["mixbasehaircolor"] self._mix_add_hair_color = self._stats["mixaddhaircolor"] self._mix_hair_base_prob = self._stats["mixhairbaseprob"] self._level = self._stats["level"] self._job = self._stats["job"] self._strength = self._stats["str"] self._dex = self._stats["dex"] self._inte = self._stats["inte"] self._luk = self._stats["luk"] self._hp = self._stats["hp"] self._max_hp = self._stats["maxhp"] self._mp = self._stats["mp"] self._max_mp = self._stats["maxmp"] self._ap = self._stats["ap"] self._sp = self._stats["sp"] self._exp = self._stats["exp"] self._pop = self._stats["pop"] # fame self._money = self._stats["money"] self._wp = self._stats["wp"] self._position_map = self._stats["posmap"] self._portal = self._stats["portal"] self._sub_job = self._stats["subjob"] def init_user(self): """Fetch a dictionary of user attributes from Swordie's DB and use it to instantiate a new User object Runs at the end of Character::__init__(char_stats, database_config). Checks the User ID associated with the character instance, and uses the User class constructor to create a new User object instance, with the relevant user attributes from the database. Returns: User object with attributes identical to its corresponding entry in the database Raises: Generic error on failure - handled by the Character::get_db() method """ user_id = self.get_user_id() user_stats = self.get_db( self._database_config, f"SELECT * FROM users WHERE id = '{user_id}'" ) # The row will always be 0 because there should be no characters with the same name user = User(user_stats, self.database_config) return user def init_inv_id(self): """Fetch a dictionary of user attributes from Swordie's DB and use it to instantiate a new (custom) Inventory object (Stipulated algorithm for unfinished sequence) Runs near the end of Character::__init__(char_stats, database_config). Uses the Character ID associated with the character instance, and the Inventory class constructor to create a new Inventory object instance, with the relevant character attributes from the database. Raises: Generic error on failure - handled by the Character::get_db() method """ inventory_ids = self.get_db( self._database_config, f"SELECT equippedinventory, equipinventory, consumeinventory, etcinventory, installinventory, cashinventory " f"FROM characters WHERE id = '{self.character_id}'" ) # The row will always be 0 because there should be no characters with the same ID self._equip_inv_id = inventory_ids["equipinventory"] self._equipped_inv_id = inventory_ids["equippedinventory"] self._consume_inv_id = inventory_ids["consumeinventory"] self._etc_inv_id = inventory_ids["etcinventory"] self._install_inv_id = inventory_ids["installinventory"] self._cash_inv_id = inventory_ids["cashinventory"] self._inventory = Inventory(self.get_inventory_ids(), self.database_config) # Static method for fetching DB @staticmethod def get_db(config, query): """Generic static method for fetching data from DB using the provided DB config and query This method assumes that only one character is found - it always defaults to the first result. An effort has been made to convert this to a decorator so that it may also be applied to Character::set_stat_by_column() & Character::get_user_id(), which ultimately ended in failure. Args: config, dictionary, representing database config attributes query, String, representing SQL query Returns: String representing the result of the provided SQL query, using the provided DB connection attributes """ try: database = con.connect( host=config["host"], user=config["user"], password=config["password"], database=config["schema"], port=config["port"] ) cursor = database.cursor(dictionary=True) cursor.execute(query) data = cursor.fetchall()[0] database.disconnect() return data except Exception as e: print("CRITICAL: Error encountered whilst attempting to connect to the database! \n", e) @property def database_config(self): return self._database_config @property def stats(self): return self._stats @property def character_id(self): return self._character_id @property def level(self): return self._level @level.setter def level(self, x): self.set_stat_by_column("level", x) self._level = x def add_level(self, amount): """Adds the specified amount to the current level count Args: amount: Int, representing the number of levels to be added to the current count """ new_level = int(self.level) + amount self.level = new_level @property def job(self): return self._job @job.setter def job(self, job_id): self.set_stat_by_column("job", job_id) self._job = job_id def get_job_name(self): """Returns the actual name of the job from job id Returns: String, representing the job name corresponding to a job ID """ return JOBS[str(self.job)] def get_gender_name(self): if self._gender == 0: return "Male" return "Female" @property def name(self): return self._name @name.setter def name(self, new_name): """Set a new name for the character Args: new_name: string, representing the new character name that will be set in the database """ self.set_stat_by_column("name", new_name) self._name = new_name @property def money(self): return self._money @money.setter def money(self, amount): self.set_stat_by_column("money", amount) self._money = amount def add_mesos(self, amount): """Adds the specified amount to the current meso count Args: amount: Int, representing the amount of mesos to be added to the current count """ new_amount = int(self.money) + amount self.money = str(new_amount) # money is a String; converting back to String for consistency @property def fame(self): return self._pop @fame.setter def fame(self, amount): self.set_stat_by_column("pop", amount) self._pop = amount def add_fame(self, amount): """Adds the specified amount to the current fame count Args: amount: Int, representing the number of fames to be added to the current count """ new_fame = int(self.fame) + amount self.fame = new_fame @property def map(self): return self._position_map @map.setter def map(self, map_id): self.set_stat_by_column("posmap", map_id) self._position_map = map_id @property def face(self): return self._face @face.setter def face(self, face_id): self.set_stat_by_column("face", face_id) self._face = face_id @property def hair(self): return self._hair @hair.setter def hair(self, hair_id): self.set_stat_by_column("hair", hair_id) self._hair = hair_id @property def skin(self): return self._skin @skin.setter def skin(self, skin_id): self.set_stat_by_column("skin", skin_id) self._skin = skin_id @property def exp(self): return self._exp @exp.setter def exp(self, exp_amount): self.set_stat_by_column("exp", exp_amount) self._exp = exp_amount def add_exp(self, amount): """Add the specified amount to the current existing EXP pool Args: amount: Int, representing the amount of EXP to be added to the current pool """ new_exp = int(self.exp) + amount self.exp = str(new_exp) # EXP is a String; converting back to String for consistency @property def strength(self): return self._strength @strength.setter def strength(self, amount): self.set_stat_by_column("str", amount) self._strength = amount def add_str(self, amount): """Add the specified amount to the current existing STR pool Args: amount: Int, representing the amount of STR to be added to the current pool """ new_str = int(self.strength) + amount self.strength = new_str @property def dex(self): return self._dex @dex.setter def dex(self, amount): self.set_stat_by_column("dex", amount) self._dex = amount def add_dex(self, amount): """Add the specified amount to the current existing DEX pool Args: amount: Int, representing the amount of DEX to be added to the current pool """ new_dex = int(self.dex) + amount self.dex = new_dex @property def inte(self): return self._inte @inte.setter def inte(self, amount): self.set_stat_by_column("inte", amount) self._inte = amount def add_inte(self, amount): """Add the specified amount to the current existing INT pool Args: amount: Int, representing the amount of INT to be added to the current pool """ new_inte = int(self.inte) + amount self.inte = new_inte @property def luk(self): return self._luk @luk.setter def luk(self, amount): self.set_stat_by_column("luk", amount) self._luk = amount def add_luk(self, amount): """Add the specified amount to the current existing LUK pool Args: amount: Int, representing the amount of LUK to be added to the current pool """ new_luk = int(self.luk) + amount self.luk = new_luk def get_primary_stats(self): """Returns str, int, dex, luk values in a dictionary Returns: dictionary of primary stats """ primary_stats = { "str": self.strength, "dex": self.dex, "int": self.inte, "luk": self.luk } return primary_stats def get_inventory_ids(self): """Returns equip_inv_id, equipped_inv_id, consume_inv_id, etc_inv_id, install_inv_id, cash_inv_id in a dict Returns: dictionary of all inventory ids from corresponding character """ inventory_ids = { "equip_inv_id": self.equip_inv_id, "equipped_inv_id": self.equipped_inv_id, "consume_inv_id": self.consume_inv_id, "etc_inv_id": self.etc_inv_id, "install_inv_id": self.install_inv_id, "cash_inv_id": self.cash_inv_id } return inventory_ids @property def max_hp(self): return self._max_hp @max_hp.setter def max_hp(self, amount): self.set_stat_by_column("maxhp", amount) self._max_hp = amount def add_max_hp(self, amount): """Add the specified amount to the current existing Max HP pool Args: amount: Int, representing the amount of Max HP to be added to the current pool """ new_hp = int(self.max_hp) + amount self.max_hp = new_hp @property def max_mp(self): return self._max_mp @max_mp.setter def max_mp(self, amount): self.set_stat_by_column("maxmp", amount) self._max_mp = amount def add_max_mp(self, amount): """Add the specified amount to the current existing Max MP pool Args: amount: Int, representing the amount of max MP to be added to the current pool """ new_mp = int(self.max_mp) + amount self.max_mp = new_mp @property def ap(self): return self._ap @ap.setter def ap(self, amount): self.set_stat_by_column("ap", amount) self._ap = amount def add_ap(self, amount): """Add the specified amount to the current existing free AP pool Args: amount: Int, representing the amount of free AP to be added to the current pool """ new_ap = int(self.ap) + amount self.ap = new_ap @property def sp(self): return self._sp @sp.setter def sp(self, amount): self.set_stat_by_column("sp", amount) self._sp = amount def add_sp(self, amount): """Add the specified amount to the current existing free SP pool Args: amount: Int, representing the amount of free SP to be added to the current pool """ new_sp = int(self.sp) + amount self.sp = new_sp @property def user(self): return self._user @property def equipped_inv_id(self): return self._equipped_inv_id @property def consume_inv_id(self): return self._consume_inv_id @property def etc_inv_id(self): return self._etc_inv_id @property def install_inv_id(self): return self._install_inv_id @property def cash_inv_id(self): return self._cash_inv_id @property def equip_inv_id(self): return self._equip_inv_id @property def inventory(self): return self._inventory def get_char_img(self): equipped_items = [self.face, self.hair] equipped_inv = self.inventory.equipped_inv for item in equipped_inv: item_id = equipped_inv[item]["itemid"] equipped_items.append(item_id) url = f"https://maplestory.io/api/GMS/216/Character/200{self.skin}/{str(equipped_items)[1:-1]}/stand1/1".replace(" ", "") return url @staticmethod def get_user_id_by_name(config, char_name): """Given a character name, retrieve its corresponding user id from database Used by Character::get_user_id() & SwordieDB::get_user_id_by_name() There is no direct way of obtaining this information. Hence, this method will fetch the character ID from the database, using the character name. Then, fetch the account ID from the database, using the character ID. Then, fetch the user ID from the database, using the account ID. Args: config: dictionary, representing database config attributes char_name: string, representing the character name in the database Returns: String, representing the user ID in the database Defaults to None if the operation fails. Raises: SQL Error 2003: Can't cannect to DB WinError 10060: No response from DB List index out of range: Wrong character name """ try: database = con.connect( host=config["host"], user=config["user"], password=config["password"], database=config["schema"], port=config["port"] ) cursor = database.cursor(dictionary=True) cursor.execute(f"SELECT characterid FROM characterstats WHERE name = '{char_name}'") char_id = cursor.fetchall()[0]["characterid"] cursor.execute(f"SELECT accid FROM characters WHERE id = '{char_id}'") account_id = cursor.fetchall()[0]["accid"] cursor.execute(f"SELECT userid FROM accounts WHERE id = '{account_id}'") user_id = cursor.fetchall()[0]["userid"] database.disconnect() return user_id except Exception as e: print("[ERROR] Error trying to get user id from database.", e) return None # Return None if there was an error def get_user_id(self): """Queries the database to obtain the User ID associated with this character instance Uses static method Character::get_user_id_by_name() for core logic Returns: Int, representing the User ID Returns None if User ID is not found Raises: Errors are handled and thrown by Character::get_user_id_by_name() SQL Error 2003: Can't cannect to DB WinError 10060: No response from DB List index out of range: Wrong character name """ return self.get_user_id_by_name(self._database_config, self._name) def set_stat_by_column(self, column, value): """Update a character's stats from column name in database Grabs the database attributes provided through the class constructor. Uses these attributes to attempt a database connection. Attempts to update the field represented by the provided column in characterstats, with the provided value. Not recommended to use this alone, as it won't update the character object which this was used from. Args: value: int or string, representing the value to be set in the database column: string, representing the column in the database that is to be updated Returns: A boolean representing whether the operation was successful Raises: SQL Error 2003: Can't cannect to DB WinError 10060: No response from DB List index out of range: Wrong column name """ host = self._database_config["host"] user = self._database_config["user"] password = self._database_config["password"] schema = self._database_config["schema"] port = self._database_config["port"] try: database = con.connect(host=host, user=user, password=password, database=schema, port=port) cursor = database.cursor(dictionary=True) cursor.execute(f"UPDATE characterstats SET {column} = '{value}' WHERE name = '{self.name}'") database.commit() print(f"Successfully updated {column} value for character: {self.name}.") self._stats[column] = value # Update the stats in the dictionary database.disconnect() return True except Exception as e: print("[ERROR] Error trying to set stats in database.", e) return False def get_stat_by_column(self, column): """Given a column name, return its value in the database Args: column: string, representing the column in the database from which the value is to be fetched from Returns: string, representing the value in the database associated with the provided column Raises: Generic error on failure """ try: return self.stats[column] except Exception as e: print("[ERROR] Error trying to get stats from given column.", e) return False
Static methods
def get_db(config, query)
-
Generic static method for fetching data from DB using the provided DB config and query
This method assumes that only one character is found - it always defaults to the first result. An effort has been made to convert this to a decorator so that it may also be applied to Character::set_stat_by_column() & Character::get_user_id(), which ultimately ended in failure.
Args
config, dictionary, representing database config attributes query, String, representing SQL query
Returns
String representing the result of the provided SQL query, using the provided DB connection attributes
Expand source code
@staticmethod def get_db(config, query): """Generic static method for fetching data from DB using the provided DB config and query This method assumes that only one character is found - it always defaults to the first result. An effort has been made to convert this to a decorator so that it may also be applied to Character::set_stat_by_column() & Character::get_user_id(), which ultimately ended in failure. Args: config, dictionary, representing database config attributes query, String, representing SQL query Returns: String representing the result of the provided SQL query, using the provided DB connection attributes """ try: database = con.connect( host=config["host"], user=config["user"], password=config["password"], database=config["schema"], port=config["port"] ) cursor = database.cursor(dictionary=True) cursor.execute(query) data = cursor.fetchall()[0] database.disconnect() return data except Exception as e: print("CRITICAL: Error encountered whilst attempting to connect to the database! \n", e)
def get_user_id_by_name(config, char_name)
-
Given a character name, retrieve its corresponding user id from database
Used by Character::get_user_id() & SwordieDB::get_user_id_by_name() There is no direct way of obtaining this information. Hence, this method will fetch the character ID from the database, using the character name. Then, fetch the account ID from the database, using the character ID. Then, fetch the user ID from the database, using the account ID.
Args
config
- dictionary, representing database config attributes
char_name
- string, representing the character name in the database
Returns
String, representing the user ID in the database Defaults to None if the operation fails.
Raises
SQL Error 2003
- Can't cannect to DB
WinError 10060
- No response from DB
List index out
ofrange
- Wrong character name
Expand source code
@staticmethod def get_user_id_by_name(config, char_name): """Given a character name, retrieve its corresponding user id from database Used by Character::get_user_id() & SwordieDB::get_user_id_by_name() There is no direct way of obtaining this information. Hence, this method will fetch the character ID from the database, using the character name. Then, fetch the account ID from the database, using the character ID. Then, fetch the user ID from the database, using the account ID. Args: config: dictionary, representing database config attributes char_name: string, representing the character name in the database Returns: String, representing the user ID in the database Defaults to None if the operation fails. Raises: SQL Error 2003: Can't cannect to DB WinError 10060: No response from DB List index out of range: Wrong character name """ try: database = con.connect( host=config["host"], user=config["user"], password=config["password"], database=config["schema"], port=config["port"] ) cursor = database.cursor(dictionary=True) cursor.execute(f"SELECT characterid FROM characterstats WHERE name = '{char_name}'") char_id = cursor.fetchall()[0]["characterid"] cursor.execute(f"SELECT accid FROM characters WHERE id = '{char_id}'") account_id = cursor.fetchall()[0]["accid"] cursor.execute(f"SELECT userid FROM accounts WHERE id = '{account_id}'") user_id = cursor.fetchall()[0]["userid"] database.disconnect() return user_id except Exception as e: print("[ERROR] Error trying to get user id from database.", e) return None # Return None if there was an error
Instance variables
var ap
-
Expand source code
@property def ap(self): return self._ap
var cash_inv_id
-
Expand source code
@property def cash_inv_id(self): return self._cash_inv_id
var character_id
-
Expand source code
@property def character_id(self): return self._character_id
var consume_inv_id
-
Expand source code
@property def consume_inv_id(self): return self._consume_inv_id
var database_config
-
Expand source code
@property def database_config(self): return self._database_config
var dex
-
Expand source code
@property def dex(self): return self._dex
var equip_inv_id
-
Expand source code
@property def equip_inv_id(self): return self._equip_inv_id
var equipped_inv_id
-
Expand source code
@property def equipped_inv_id(self): return self._equipped_inv_id
var etc_inv_id
-
Expand source code
@property def etc_inv_id(self): return self._etc_inv_id
var exp
-
Expand source code
@property def exp(self): return self._exp
var face
-
Expand source code
@property def face(self): return self._face
var fame
-
Expand source code
@property def fame(self): return self._pop
var hair
-
Expand source code
@property def hair(self): return self._hair
var install_inv_id
-
Expand source code
@property def install_inv_id(self): return self._install_inv_id
var inte
-
Expand source code
@property def inte(self): return self._inte
var inventory
-
Expand source code
@property def inventory(self): return self._inventory
var job
-
Expand source code
@property def job(self): return self._job
var level
-
Expand source code
@property def level(self): return self._level
var luk
-
Expand source code
@property def luk(self): return self._luk
var map
-
Expand source code
@property def map(self): return self._position_map
var max_hp
-
Expand source code
@property def max_hp(self): return self._max_hp
var max_mp
-
Expand source code
@property def max_mp(self): return self._max_mp
var money
-
Expand source code
@property def money(self): return self._money
var name
-
Expand source code
@property def name(self): return self._name
var skin
-
Expand source code
@property def skin(self): return self._skin
var sp
-
Expand source code
@property def sp(self): return self._sp
var stats
-
Expand source code
@property def stats(self): return self._stats
var strength
-
Expand source code
@property def strength(self): return self._strength
var user
-
Expand source code
@property def user(self): return self._user
Methods
def add_ap(self, amount)
-
Add the specified amount to the current existing free AP pool
Args
amount
- Int, representing the amount of free AP to be added to the current pool
Expand source code
def add_ap(self, amount): """Add the specified amount to the current existing free AP pool Args: amount: Int, representing the amount of free AP to be added to the current pool """ new_ap = int(self.ap) + amount self.ap = new_ap
def add_dex(self, amount)
-
Add the specified amount to the current existing DEX pool
Args
amount
- Int, representing the amount of DEX to be added to the current pool
Expand source code
def add_dex(self, amount): """Add the specified amount to the current existing DEX pool Args: amount: Int, representing the amount of DEX to be added to the current pool """ new_dex = int(self.dex) + amount self.dex = new_dex
def add_exp(self, amount)
-
Add the specified amount to the current existing EXP pool
Args
amount
- Int, representing the amount of EXP to be added to the current pool
Expand source code
def add_exp(self, amount): """Add the specified amount to the current existing EXP pool Args: amount: Int, representing the amount of EXP to be added to the current pool """ new_exp = int(self.exp) + amount self.exp = str(new_exp) # EXP is a String; converting back to String for consistency
def add_fame(self, amount)
-
Adds the specified amount to the current fame count
Args
amount
- Int, representing the number of fames to be added to the current count
Expand source code
def add_fame(self, amount): """Adds the specified amount to the current fame count Args: amount: Int, representing the number of fames to be added to the current count """ new_fame = int(self.fame) + amount self.fame = new_fame
def add_inte(self, amount)
-
Add the specified amount to the current existing INT pool
Args
amount
- Int, representing the amount of INT to be added to the current pool
Expand source code
def add_inte(self, amount): """Add the specified amount to the current existing INT pool Args: amount: Int, representing the amount of INT to be added to the current pool """ new_inte = int(self.inte) + amount self.inte = new_inte
def add_level(self, amount)
-
Adds the specified amount to the current level count
Args
amount
- Int, representing the number of levels to be added to the current count
Expand source code
def add_level(self, amount): """Adds the specified amount to the current level count Args: amount: Int, representing the number of levels to be added to the current count """ new_level = int(self.level) + amount self.level = new_level
def add_luk(self, amount)
-
Add the specified amount to the current existing LUK pool
Args
amount
- Int, representing the amount of LUK to be added to the current pool
Expand source code
def add_luk(self, amount): """Add the specified amount to the current existing LUK pool Args: amount: Int, representing the amount of LUK to be added to the current pool """ new_luk = int(self.luk) + amount self.luk = new_luk
def add_max_hp(self, amount)
-
Add the specified amount to the current existing Max HP pool
Args
amount
- Int, representing the amount of Max HP to be added to the current pool
Expand source code
def add_max_hp(self, amount): """Add the specified amount to the current existing Max HP pool Args: amount: Int, representing the amount of Max HP to be added to the current pool """ new_hp = int(self.max_hp) + amount self.max_hp = new_hp
def add_max_mp(self, amount)
-
Add the specified amount to the current existing Max MP pool
Args
amount
- Int, representing the amount of max MP to be added to the current pool
Expand source code
def add_max_mp(self, amount): """Add the specified amount to the current existing Max MP pool Args: amount: Int, representing the amount of max MP to be added to the current pool """ new_mp = int(self.max_mp) + amount self.max_mp = new_mp
def add_mesos(self, amount)
-
Adds the specified amount to the current meso count
Args
amount
- Int, representing the amount of mesos to be added to the current count
Expand source code
def add_mesos(self, amount): """Adds the specified amount to the current meso count Args: amount: Int, representing the amount of mesos to be added to the current count """ new_amount = int(self.money) + amount self.money = str(new_amount) # money is a String; converting back to String for consistency
def add_sp(self, amount)
-
Add the specified amount to the current existing free SP pool
Args
amount
- Int, representing the amount of free SP to be added to the current pool
Expand source code
def add_sp(self, amount): """Add the specified amount to the current existing free SP pool Args: amount: Int, representing the amount of free SP to be added to the current pool """ new_sp = int(self.sp) + amount self.sp = new_sp
def add_str(self, amount)
-
Add the specified amount to the current existing STR pool
Args
amount
- Int, representing the amount of STR to be added to the current pool
Expand source code
def add_str(self, amount): """Add the specified amount to the current existing STR pool Args: amount: Int, representing the amount of STR to be added to the current pool """ new_str = int(self.strength) + amount self.strength = new_str
def get_char_img(self)
-
Expand source code
def get_char_img(self): equipped_items = [self.face, self.hair] equipped_inv = self.inventory.equipped_inv for item in equipped_inv: item_id = equipped_inv[item]["itemid"] equipped_items.append(item_id) url = f"https://maplestory.io/api/GMS/216/Character/200{self.skin}/{str(equipped_items)[1:-1]}/stand1/1".replace(" ", "") return url
def get_gender_name(self)
-
Expand source code
def get_gender_name(self): if self._gender == 0: return "Male" return "Female"
def get_inventory_ids(self)
-
Returns equip_inv_id, equipped_inv_id, consume_inv_id, etc_inv_id, install_inv_id, cash_inv_id in a dict
Returns
dictionary of all inventory ids from corresponding character
Expand source code
def get_inventory_ids(self): """Returns equip_inv_id, equipped_inv_id, consume_inv_id, etc_inv_id, install_inv_id, cash_inv_id in a dict Returns: dictionary of all inventory ids from corresponding character """ inventory_ids = { "equip_inv_id": self.equip_inv_id, "equipped_inv_id": self.equipped_inv_id, "consume_inv_id": self.consume_inv_id, "etc_inv_id": self.etc_inv_id, "install_inv_id": self.install_inv_id, "cash_inv_id": self.cash_inv_id } return inventory_ids
def get_job_name(self)
-
Returns the actual name of the job from job id
Returns
String, representing the job name corresponding to a job ID
Expand source code
def get_job_name(self): """Returns the actual name of the job from job id Returns: String, representing the job name corresponding to a job ID """ return JOBS[str(self.job)]
def get_primary_stats(self)
-
Returns str, int, dex, luk values in a dictionary
Returns
dictionary of primary stats
Expand source code
def get_primary_stats(self): """Returns str, int, dex, luk values in a dictionary Returns: dictionary of primary stats """ primary_stats = { "str": self.strength, "dex": self.dex, "int": self.inte, "luk": self.luk } return primary_stats
def get_stat_by_column(self, column)
-
Given a column name, return its value in the database
Args
column
- string, representing the column in the database from which the value is to be fetched from
Returns
string, representing the value in the database associated with the provided column
Raises
Generic error on failure
Expand source code
def get_stat_by_column(self, column): """Given a column name, return its value in the database Args: column: string, representing the column in the database from which the value is to be fetched from Returns: string, representing the value in the database associated with the provided column Raises: Generic error on failure """ try: return self.stats[column] except Exception as e: print("[ERROR] Error trying to get stats from given column.", e) return False
def get_user_id(self)
-
Queries the database to obtain the User ID associated with this character instance
Uses static method Character::get_user_id_by_name() for core logic
Returns
Int, representing the User ID Returns None if User ID is not found
Raises
- Errors are handled and thrown by Character::get_user_id_by_name()
SQL Error 2003
- Can't cannect to DB
WinError 10060
- No response from DB
List index out
ofrange
- Wrong character name
Expand source code
def get_user_id(self): """Queries the database to obtain the User ID associated with this character instance Uses static method Character::get_user_id_by_name() for core logic Returns: Int, representing the User ID Returns None if User ID is not found Raises: Errors are handled and thrown by Character::get_user_id_by_name() SQL Error 2003: Can't cannect to DB WinError 10060: No response from DB List index out of range: Wrong character name """ return self.get_user_id_by_name(self._database_config, self._name)
def init_inv_id(self)
-
Fetch a dictionary of user attributes from Swordie's DB and use it to instantiate a new (custom) Inventory object
(Stipulated algorithm for unfinished sequence) Runs near the end of Character::init(char_stats, database_config). Uses the Character ID associated with the character instance, and the Inventory class constructor to create a new Inventory object instance, with the relevant character attributes from the database.
Raises
Generic error on failure - handled by the Character::get_db() method
Expand source code
def init_inv_id(self): """Fetch a dictionary of user attributes from Swordie's DB and use it to instantiate a new (custom) Inventory object (Stipulated algorithm for unfinished sequence) Runs near the end of Character::__init__(char_stats, database_config). Uses the Character ID associated with the character instance, and the Inventory class constructor to create a new Inventory object instance, with the relevant character attributes from the database. Raises: Generic error on failure - handled by the Character::get_db() method """ inventory_ids = self.get_db( self._database_config, f"SELECT equippedinventory, equipinventory, consumeinventory, etcinventory, installinventory, cashinventory " f"FROM characters WHERE id = '{self.character_id}'" ) # The row will always be 0 because there should be no characters with the same ID self._equip_inv_id = inventory_ids["equipinventory"] self._equipped_inv_id = inventory_ids["equippedinventory"] self._consume_inv_id = inventory_ids["consumeinventory"] self._etc_inv_id = inventory_ids["etcinventory"] self._install_inv_id = inventory_ids["installinventory"] self._cash_inv_id = inventory_ids["cashinventory"] self._inventory = Inventory(self.get_inventory_ids(), self.database_config)
def init_stats(self)
-
Given a dictionary of stats from Swordie's DB we add them to Character object's attributes
Runs near the end of Character::init(char_stats, database_config). It assigns the character attributes in char_stats to their respective protected attributes belonging to the Character object instance.
Expand source code
def init_stats(self): """Given a dictionary of stats from Swordie's DB we add them to Character object's attributes Runs near the end of Character::__init__(char_stats, database_config). It assigns the character attributes in char_stats to their respective protected attributes belonging to the Character object instance. """ self._vague_id = self._stats["id"] self._character_id = self._stats["characterid"] self._character_id_for_log = self._stats["characteridforlog"] self._world_id = self._stats["worldidforlog"] self._name = self._stats["name"] self._gender = self._stats["gender"] self._skin = self._stats["skin"] self._face = self._stats["face"] self._hair = self._stats["hair"] self._mix_base_hair_color = self._stats["mixbasehaircolor"] self._mix_add_hair_color = self._stats["mixaddhaircolor"] self._mix_hair_base_prob = self._stats["mixhairbaseprob"] self._level = self._stats["level"] self._job = self._stats["job"] self._strength = self._stats["str"] self._dex = self._stats["dex"] self._inte = self._stats["inte"] self._luk = self._stats["luk"] self._hp = self._stats["hp"] self._max_hp = self._stats["maxhp"] self._mp = self._stats["mp"] self._max_mp = self._stats["maxmp"] self._ap = self._stats["ap"] self._sp = self._stats["sp"] self._exp = self._stats["exp"] self._pop = self._stats["pop"] # fame self._money = self._stats["money"] self._wp = self._stats["wp"] self._position_map = self._stats["posmap"] self._portal = self._stats["portal"] self._sub_job = self._stats["subjob"]
def init_user(self)
-
Fetch a dictionary of user attributes from Swordie's DB and use it to instantiate a new User object
Runs at the end of Character::init(char_stats, database_config). Checks the User ID associated with the character instance, and uses the User class constructor to create a new User object instance, with the relevant user attributes from the database.
Returns
User object with attributes identical to its corresponding entry in the database
Raises
Generic error on failure - handled by the Character::get_db() method
Expand source code
def init_user(self): """Fetch a dictionary of user attributes from Swordie's DB and use it to instantiate a new User object Runs at the end of Character::__init__(char_stats, database_config). Checks the User ID associated with the character instance, and uses the User class constructor to create a new User object instance, with the relevant user attributes from the database. Returns: User object with attributes identical to its corresponding entry in the database Raises: Generic error on failure - handled by the Character::get_db() method """ user_id = self.get_user_id() user_stats = self.get_db( self._database_config, f"SELECT * FROM users WHERE id = '{user_id}'" ) # The row will always be 0 because there should be no characters with the same name user = User(user_stats, self.database_config) return user
def set_stat_by_column(self, column, value)
-
Update a character's stats from column name in database
Grabs the database attributes provided through the class constructor. Uses these attributes to attempt a database connection. Attempts to update the field represented by the provided column in characterstats, with the provided value. Not recommended to use this alone, as it won't update the character object which this was used from.
Args
value
- int or string, representing the value to be set in the database
column
- string, representing the column in the database that is to be updated
Returns
A boolean representing whether the operation was successful
Raises
SQL Error 2003
- Can't cannect to DB
WinError 10060
- No response from DB
List index out
ofrange
- Wrong column name
Expand source code
def set_stat_by_column(self, column, value): """Update a character's stats from column name in database Grabs the database attributes provided through the class constructor. Uses these attributes to attempt a database connection. Attempts to update the field represented by the provided column in characterstats, with the provided value. Not recommended to use this alone, as it won't update the character object which this was used from. Args: value: int or string, representing the value to be set in the database column: string, representing the column in the database that is to be updated Returns: A boolean representing whether the operation was successful Raises: SQL Error 2003: Can't cannect to DB WinError 10060: No response from DB List index out of range: Wrong column name """ host = self._database_config["host"] user = self._database_config["user"] password = self._database_config["password"] schema = self._database_config["schema"] port = self._database_config["port"] try: database = con.connect(host=host, user=user, password=password, database=schema, port=port) cursor = database.cursor(dictionary=True) cursor.execute(f"UPDATE characterstats SET {column} = '{value}' WHERE name = '{self.name}'") database.commit() print(f"Successfully updated {column} value for character: {self.name}.") self._stats[column] = value # Update the stats in the dictionary database.disconnect() return True except Exception as e: print("[ERROR] Error trying to set stats in database.", e) return False