Added coloured text using Rich, also better storage handling.
This commit is contained in:
parent
8897a97777
commit
d507c1b1d1
|
@ -1,3 +1,8 @@
|
||||||
beautifulsoup4==4.12.2
|
beautifulsoup4==4.12.2
|
||||||
|
colorama==0.4.6
|
||||||
lxml==4.9.2
|
lxml==4.9.2
|
||||||
|
markdown-it-py==3.0.0
|
||||||
|
mdurl==0.1.2
|
||||||
|
Pygments==2.15.1
|
||||||
|
rich==13.4.2
|
||||||
soupsieve==2.4.1
|
soupsieve==2.4.1
|
||||||
|
|
221
sheditor.py
221
sheditor.py
|
@ -1,60 +1,76 @@
|
||||||
import sys, argparse, copy, os, datetime
|
import argparse
|
||||||
|
import copy
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
import rich
|
||||||
|
from rich.console import Console
|
||||||
|
|
||||||
|
# Only "normal storage" is used to insert requested items
|
||||||
|
normal_storage_ids = [82, 632]
|
||||||
|
|
||||||
|
storage_ids = {
|
||||||
|
82: {"name": "Small storage", "capacity": 50},
|
||||||
|
632: {"name": "Large storage", "capacity": 250},
|
||||||
|
3062: {"name": "Body storage", "capacity": 20},
|
||||||
|
}
|
||||||
|
|
||||||
char_skills = {
|
char_skills = {
|
||||||
1 : "Piloting", # Likely deprecated
|
1: "Piloting", # Likely deprecated - now using code 22
|
||||||
2 : "Mining",
|
2: "Mining",
|
||||||
3 : "Botany",
|
3: "Botany",
|
||||||
4 : "Construction",
|
4: "Construction",
|
||||||
5 : "Industry",
|
5: "Industry",
|
||||||
6 : "Medical",
|
6: "Medical",
|
||||||
7 : "Gunner",
|
7: "Gunner",
|
||||||
8 : "Shielding",
|
8: "Shielding",
|
||||||
9 : "Operations",
|
9: "Operations",
|
||||||
10 : "Weapons",
|
10: "Weapons",
|
||||||
11 : "Unknown-1",
|
11: "Unknown-1",
|
||||||
12 : "Logistics", # All characters seem to have this but it doesn't show up in the UI
|
12: "Logistics", # All characters seem to have this but it doesn't show up in the UI
|
||||||
13 : "Unknown-2-enigma", # All characters seem to have this skill but what is it for?
|
13: "Unknown-2-enigma", # All characters seem to have this skill but what is it for?
|
||||||
14 : "Navigation",
|
14: "Navigation",
|
||||||
15 : "Unknown-3",
|
15: "Unknown-3",
|
||||||
16 : "Research",
|
16: "Research",
|
||||||
22 : "Piloting", # Appears to be the new piloting code?
|
22: "Piloting", # Appears to be the new piloting code?
|
||||||
}
|
}
|
||||||
|
|
||||||
char_attributes = {
|
char_attributes = {
|
||||||
210 : "Bravery",
|
210: "Bravery",
|
||||||
214 : "Preception",
|
214: "Preception",
|
||||||
213 : "Intelligence",
|
213: "Intelligence",
|
||||||
212 : "Zest",
|
212: "Zest",
|
||||||
}
|
}
|
||||||
|
|
||||||
char_traits = {
|
char_traits = {
|
||||||
"Iron Stomach" : 1533,
|
"Iron Stomach": 1533,
|
||||||
"Spacefarer" : 1045,
|
"Spacefarer": 1045,
|
||||||
"Confident" : 1046,
|
"Confident": 1046,
|
||||||
"Hard Working" : 1041,
|
"Hard Working": 1041,
|
||||||
"Antisocial" : 1037,
|
"Antisocial": 1037,
|
||||||
"Nyctophilia" : 1534,
|
"Nyctophilia": 1534,
|
||||||
"Wimp" : 655,
|
"Wimp": 655,
|
||||||
"Clumsy" : 656,
|
"Clumsy": 656,
|
||||||
"Charming" : 1048,
|
"Charming": 1048,
|
||||||
"Bloodlust" : 1036,
|
"Bloodlust": 1036,
|
||||||
"Fast Learner" : 1039,
|
"Fast Learner": 1039,
|
||||||
"Minimalist" : 1535,
|
"Minimalist": 1535,
|
||||||
"Lazy" : 1040,
|
"Lazy": 1040,
|
||||||
"Neurotic" : 1047,
|
"Neurotic": 1047,
|
||||||
"Alien Lover" : 2082,
|
"Alien Lover": 2082,
|
||||||
"Needy" : 1038,
|
"Needy": 1038,
|
||||||
"Peace-loving" : 1043,
|
"Peace-loving": 1043,
|
||||||
"Suicidal" : 1034,
|
"Suicidal": 1034,
|
||||||
"Smart" : 1035,
|
"Smart": 1035,
|
||||||
"Psychopath" : 1042,
|
"Psychopath": 1042,
|
||||||
"Hero" : 191,
|
"Hero": 191,
|
||||||
"Talkative" : 1560,
|
"Talkative": 1560,
|
||||||
"Iron-Willed" : 1044,
|
"Iron-Willed": 1044,
|
||||||
"Gourmand" : 1562,
|
"Gourmand": 1562,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ItemCodeDatabase:
|
class ItemCodeDatabase:
|
||||||
|
|
||||||
def __init__(self, database_filename):
|
def __init__(self, database_filename):
|
||||||
|
@ -88,6 +104,7 @@ class StorageArea:
|
||||||
|
|
||||||
def __init__(self, tag):
|
def __init__(self, tag):
|
||||||
self.tag = tag
|
self.tag = tag
|
||||||
|
self.type_id = None
|
||||||
self.items = []
|
self.items = []
|
||||||
self.is_abnormal_storage = False
|
self.is_abnormal_storage = False
|
||||||
|
|
||||||
|
@ -148,15 +165,24 @@ class Character:
|
||||||
return new_char
|
return new_char
|
||||||
|
|
||||||
def print_summary(self):
|
def print_summary(self):
|
||||||
print("Name: {}".format(self.name))
|
console = Console(highlight=False)
|
||||||
print()
|
console.print("Name: [bright_cyan]{}[/]".format(self.name))
|
||||||
print("Skills:")
|
console.print()
|
||||||
for skill in self.skills:
|
console.print("Skills:")
|
||||||
print("{} : {}".format(char_skills[skill['id']], skill['level']))
|
for i, skill in enumerate(self.skills):
|
||||||
print()
|
row_string = "{:20} [bright_cyan]{:2}[/]".format(char_skills[skill['id']], skill['level'])
|
||||||
print("Attributes:")
|
if i % 2 == 0:
|
||||||
for attribute in self.attributes:
|
console.print(" [on #222222]{}[/]".format(row_string))
|
||||||
print("{} : {}".format(char_attributes[attribute['id']], attribute['points']))
|
else:
|
||||||
|
console.print(" {}".format(row_string))
|
||||||
|
console.print()
|
||||||
|
console.print("Attributes:")
|
||||||
|
for i, attribute in enumerate(self.attributes):
|
||||||
|
row_string = "{:12} [bright_cyan]{:2}[/]".format(char_attributes[attribute['id']], attribute['points'])
|
||||||
|
if i % 2 == 0:
|
||||||
|
console.print(" [on #222222]{}[/]".format(row_string))
|
||||||
|
else:
|
||||||
|
console.print(" {}".format(row_string))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{} - Skills: {} - Attributes: {}".format(self.name, repr(self.skills), repr(self.attributes))
|
return "{} - Skills: {} - Attributes: {}".format(self.name, repr(self.skills), repr(self.attributes))
|
||||||
|
@ -223,6 +249,7 @@ class GameData:
|
||||||
ship_name = ship_tag['sname']
|
ship_name = ship_tag['sname']
|
||||||
# print(ship_name)
|
# print(ship_name)
|
||||||
|
|
||||||
|
# Forgotten - why did I specify owner as required here - what ships don't have owners?
|
||||||
owner_node = ship_tag.find('settings', owner=True)
|
owner_node = ship_tag.find('settings', owner=True)
|
||||||
ship_owner = owner_node['owner']
|
ship_owner = owner_node['owner']
|
||||||
ship_state = owner_node['state']
|
ship_state = owner_node['state']
|
||||||
|
@ -233,8 +260,10 @@ class GameData:
|
||||||
# Step 3 - Storage area data
|
# Step 3 - Storage area data
|
||||||
for inv_tag in ship_tag.find_all('feat', eatAllowed=True):
|
for inv_tag in ship_tag.find_all('feat', eatAllowed=True):
|
||||||
storage_area = StorageArea(inv_tag.find('inv'))
|
storage_area = StorageArea(inv_tag.find('inv'))
|
||||||
# This is a GUESS
|
# 632 is the "m" id code for LARGE storage
|
||||||
if inv_tag.find('env'):
|
storage_area.type_id = int(inv_tag.parent.parent['m'])
|
||||||
|
if storage_area.type_id not in normal_storage_ids: # TODO: Un-hardcode this AND take into account SMALL storage
|
||||||
|
# rich.print("[on #222222]Found abnormal storage id [#666666]{}[/][/]".format(inv_tag.parent.parent['m']))
|
||||||
storage_area.is_abnormal_storage = True
|
storage_area.is_abnormal_storage = True
|
||||||
ship.add_storage_area(storage_area)
|
ship.add_storage_area(storage_area)
|
||||||
# Items within storage area
|
# Items within storage area
|
||||||
|
@ -248,7 +277,7 @@ class GameData:
|
||||||
|
|
||||||
# Step 4 - Character data
|
# Step 4 - Character data
|
||||||
for character_list in ship_tag.find_all('characters'):
|
for character_list in ship_tag.find_all('characters'):
|
||||||
character_tags = character_list.find_all('c', attrs={'name':True})
|
character_tags = character_list.find_all('c', attrs={'name': True})
|
||||||
for character_tag in character_tags:
|
for character_tag in character_tags:
|
||||||
char_name = character_tag['name']
|
char_name = character_tag['name']
|
||||||
character = Character(char_name, character_tag)
|
character = Character(char_name, character_tag)
|
||||||
|
@ -263,11 +292,11 @@ class GameData:
|
||||||
skill_exp = sk_tag['exp']
|
skill_exp = sk_tag['exp']
|
||||||
skill_expd = sk_tag['expd']
|
skill_expd = sk_tag['expd']
|
||||||
skill_dict = {
|
skill_dict = {
|
||||||
'id' : int(skill_id),
|
'id': int(skill_id),
|
||||||
'level' : int(skill_level),
|
'level': int(skill_level),
|
||||||
'mxn' : int(skill_mxn),
|
'mxn': int(skill_mxn),
|
||||||
'exp' : int(skill_exp),
|
'exp': int(skill_exp),
|
||||||
'expd' : int(skill_expd),
|
'expd': int(skill_expd),
|
||||||
}
|
}
|
||||||
skills.append(skill_dict)
|
skills.append(skill_dict)
|
||||||
character.set_skills(skills)
|
character.set_skills(skills)
|
||||||
|
@ -278,13 +307,12 @@ class GameData:
|
||||||
attribute_id = a_tag['id']
|
attribute_id = a_tag['id']
|
||||||
attribute_points = a_tag['points']
|
attribute_points = a_tag['points']
|
||||||
attribute_dict = {
|
attribute_dict = {
|
||||||
'id' : int(attribute_id),
|
'id': int(attribute_id),
|
||||||
'points' : int(attribute_points),
|
'points': int(attribute_points),
|
||||||
}
|
}
|
||||||
attributes.append(attribute_dict)
|
attributes.append(attribute_dict)
|
||||||
character.set_attributes(attributes)
|
character.set_attributes(attributes)
|
||||||
|
|
||||||
|
|
||||||
def writeback(self):
|
def writeback(self):
|
||||||
def replace_id(dict, old_key, new_key):
|
def replace_id(dict, old_key, new_key):
|
||||||
dict_copy = dict.copy()
|
dict_copy = dict.copy()
|
||||||
|
@ -333,7 +361,7 @@ class GameData:
|
||||||
area_tag = storage_area.tag
|
area_tag = storage_area.tag
|
||||||
area_tag.clear()
|
area_tag.clear()
|
||||||
for item in storage_area.items:
|
for item in storage_area.items:
|
||||||
tag_dict = { 'elementaryId' : item.code, 'inStorage' : item.quantity, 'onTheWayIn' : 0, 'onTheWayOut' : 0}
|
tag_dict = {'elementaryId': item.code, 'inStorage': item.quantity, 'onTheWayIn': 0, 'onTheWayOut': 0}
|
||||||
new_tag = self.soup.new_tag('s', attrs=tag_dict)
|
new_tag = self.soup.new_tag('s', attrs=tag_dict)
|
||||||
area_tag.append(new_tag)
|
area_tag.append(new_tag)
|
||||||
|
|
||||||
|
@ -364,40 +392,53 @@ class GameData:
|
||||||
return
|
return
|
||||||
|
|
||||||
def print_detailed_character_summary(self):
|
def print_detailed_character_summary(self):
|
||||||
|
console = Console(highlight=False)
|
||||||
for ship in self.ships:
|
for ship in self.ships:
|
||||||
|
console.print("Listing characters for ship [magenta]{}[/] (owned by [bright_cyan]{}[/], state [bright_cyan]{}[/]):".format(ship.name, ship.owner, ship.state))
|
||||||
if len(ship.characters) == 0:
|
if len(ship.characters) == 0:
|
||||||
print("Ship {} (owned by {}, state {}) has no characters, skipping...".format(ship.name, ship.owner, ship.state))
|
console.print(" This ship has no characters, skipping...")
|
||||||
print()
|
console.print()
|
||||||
|
console.print()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print("Listing characters for ship {} (owned by {}, state {}):".format(ship.name, ship.owner, ship.state))
|
|
||||||
print('-----')
|
|
||||||
|
|
||||||
for character in ship.characters:
|
for character in ship.characters:
|
||||||
character.print_summary()
|
character.print_summary()
|
||||||
print('-----')
|
console.print('-----')
|
||||||
|
|
||||||
print()
|
console.print()
|
||||||
|
|
||||||
def print_detailed_item_summary(self):
|
def print_detailed_item_summary(self):
|
||||||
|
console = Console(highlight=False)
|
||||||
for ship in self.ships:
|
for ship in self.ships:
|
||||||
|
rich.print("Inventory for ship [#aa00ff]{}[/] (owned by [bright_cyan]{}[/], state [bright_cyan]{}[/]):".format(ship.name, ship.owner, ship.state))
|
||||||
if len(ship.storage_areas) == 0:
|
if len(ship.storage_areas) == 0:
|
||||||
print("Ship {} (owned by {}, state {}) has no storage areas, skipping...".format(ship.name, ship.owner, ship.state))
|
console.print(" This ship has no storage areas, skipping...")
|
||||||
print()
|
console.print()
|
||||||
|
console.print()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print("Inventory for ship {} (owned by {}, state {})".format(ship.name, ship.owner, ship.state))
|
|
||||||
for index, storage_area in enumerate(ship.storage_areas):
|
for index, storage_area in enumerate(ship.storage_areas):
|
||||||
|
console.print(" Storage area [bright_cyan]{}[/] (type: [bright_cyan]{}[/], abnormal storage: [bright_cyan]{}[/]):".format(index, storage_ids[storage_area.type_id]["name"], storage_area.is_abnormal_storage))
|
||||||
if len(storage_area.items) == 0:
|
if len(storage_area.items) == 0:
|
||||||
print(" Storage area {} is empty.".format(index))
|
console.print(" This storage area is empty.")
|
||||||
|
console.print()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(" Storage area {} (abnormal storage: {}):".format(index, storage_area.is_abnormal_storage))
|
console.print("[bold] {:>4} {:30} {:>3}[/]".format("ID", "Name", "#"))
|
||||||
for item in storage_area.items:
|
total_quantity = 0
|
||||||
print(" {:4}: {} - {}".format(item.code, item.name, item.quantity))
|
for i, item in enumerate(storage_area.items):
|
||||||
|
row_string = " {:4} {:30} {:3}".format(item.code, item.name, item.quantity)
|
||||||
print()
|
total_quantity += item.quantity
|
||||||
print()
|
if i % 2 == 0:
|
||||||
|
console.print(" [on #222222]{}[/]".format(row_string))
|
||||||
|
else:
|
||||||
|
console.print(" {}".format(row_string))
|
||||||
|
storage_area_capacity = storage_ids[storage_area.type_id]["capacity"]
|
||||||
|
console.print(" Total quantity: [bright_cyan]{}[/]/[bright_cyan]{}[/]".format(total_quantity, storage_area_capacity))
|
||||||
|
if total_quantity > storage_area_capacity:
|
||||||
|
console.print(" [dark_orange]WARNING: Storage capacity exceeded[/]")
|
||||||
|
console.print()
|
||||||
|
console.print()
|
||||||
|
|
||||||
def print_summary(self):
|
def print_summary(self):
|
||||||
print("Start game summary:")
|
print("Start game summary:")
|
||||||
|
@ -503,7 +544,6 @@ def inventory(soup, add_code, add_quantity):
|
||||||
storage_space_counter += 1
|
storage_space_counter += 1
|
||||||
print('-----')
|
print('-----')
|
||||||
|
|
||||||
|
|
||||||
print('Item total summary:')
|
print('Item total summary:')
|
||||||
print()
|
print()
|
||||||
for item in item_tracking.items():
|
for item in item_tracking.items():
|
||||||
|
@ -538,9 +578,9 @@ def list_ships(soup):
|
||||||
ship_owner = owner_node['owner']
|
ship_owner = owner_node['owner']
|
||||||
ship_state = owner_node['state']
|
ship_state = owner_node['state']
|
||||||
print('Ship found: {} owned by {} (state: {})'.format(ship_name, ship_owner, ship_state))
|
print('Ship found: {} owned by {} (state: {})'.format(ship_name, ship_owner, ship_state))
|
||||||
|
|
||||||
# print(settings_node)
|
# print(settings_node)
|
||||||
|
|
||||||
|
|
||||||
def parse_item_file(filename):
|
def parse_item_file(filename):
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
@ -591,7 +631,8 @@ def main():
|
||||||
soup = BeautifulSoup(full_text, "xml")
|
soup = BeautifulSoup(full_text, "xml")
|
||||||
|
|
||||||
item_code_database = ItemCodeDatabase('item_ids.txt')
|
item_code_database = ItemCodeDatabase('item_ids.txt')
|
||||||
print("Item code database successfully loaded")
|
print("Item code database successfully loaded.")
|
||||||
|
print()
|
||||||
|
|
||||||
game_data = GameData(soup, item_code_database)
|
game_data = GameData(soup, item_code_database)
|
||||||
game_data.populate()
|
game_data.populate()
|
||||||
|
@ -620,7 +661,7 @@ def main():
|
||||||
if args.add_item_set:
|
if args.add_item_set:
|
||||||
item_list = parse_item_file(args.add_item_set[0])
|
item_list = parse_item_file(args.add_item_set[0])
|
||||||
# print(item_list)
|
# print(item_list)
|
||||||
print ("Items to be added:")
|
print("Items to be added:")
|
||||||
for (item_code, item_quantity) in item_list:
|
for (item_code, item_quantity) in item_list:
|
||||||
print("{} : {}".format(item_code_database.get_name_from_code(item_code), item_quantity))
|
print("{} : {}".format(item_code_database.get_name_from_code(item_code), item_quantity))
|
||||||
game_data.add_item(item_code, item_quantity)
|
game_data.add_item(item_code, item_quantity)
|
||||||
|
@ -635,9 +676,6 @@ def main():
|
||||||
game_data.writeback()
|
game_data.writeback()
|
||||||
|
|
||||||
if args.test_gamedata:
|
if args.test_gamedata:
|
||||||
item_code_database = ItemCodeDatabase('item_ids.txt')
|
|
||||||
print("Item code database successfully loaded")
|
|
||||||
|
|
||||||
game_data = GameData(soup, item_code_database)
|
game_data = GameData(soup, item_code_database)
|
||||||
game_data.populate()
|
game_data.populate()
|
||||||
# game_data.add_item(1759, 100)
|
# game_data.add_item(1759, 100)
|
||||||
|
@ -675,5 +713,6 @@ def main():
|
||||||
f.write(sansfirstline)
|
f.write(sansfirstline)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Reference in New Issue