I'm creating a code that should allow a user to select multiple objects from a list. Each user has an allotted amount of space, and each object has a specified size. I'm trying to populate the list based on the rarity of the object, and to only show the items that have a size at or under what allotted space the user has left.
However, once the user has selected an object and the list is updated with only those objects within their remaining size range, the code for showing the list no longer works, and the following error is received:
AttributeError: 'str' object has no attribute 'items'
user_stage1_objects = []
selected_objects_size = 0
timeframe1 = {
"Option1": {
"Common": [{"Item Name": "A1", "Size": 3}, {"Item Name": "A2", "Size": 4}],
"Uncommon": [{"Item Name": "B1", "Size": 2}, {"Item Name": "B2", "Size": 1}]
},
"Option2": {
"Common": [{"Item Name": "C1", "Size": 3}, {"Item Name": "C2", "Size": 1}],
"Uncommon": [{"Item Name": "D1", "Size": 2}, {"Item Name": "D2", "Size": 4}]
}
}
timeframe2 = {
"Option1": {
"Common": [{"Item Name": "A1", "Size": 3}, {"Item Name": "A3", "Size": 2}],
"Uncommon": [{"Item Name": "B1", "Size": 2}, {"Item Name": "B2", "Size": 1}]
},
"Option2": {
"Common": [{"Item Name": "C2", "Size": 1}, {"Item Name": "C3", "Size": 3}],
"Uncommon": [{"Item Name": "D1", "Size": 2}, {"Item Name": "D2", "Size": 4}]
}
}
def stage1_selection():
global max_amount_limit, selected_objects_size, available_objects_list, user_stage1_objects
objects_chosen = None
user_stage1_objects = []
available_objects_list = []
timeframe_choice = input("""
Select Timeframe1 or Timeframe2
1 - Timeframe1
2 - Timeframe2
> """)
if timeframe_choice == "1":
chosen_timeframe = timeframe1
elif timeframe_choice == "2":
chosen_timeframe = timeframe2
else:
print("Not a valid choice, try again")
while objects_chosen is None:
if (max_amount_limit - selected_objects_size) > 3:
if chosen_timeframe == timeframe1:
available_objects_list = timeframe1["Option1"]["Common"]
elif chosen_timeframe == timeframe2:
available_objects_list = timeframe2["Option2"]["Common"]
elif (max_amount_limit - selected_objects_size) < 4:
available_objects_list = []
if chosen_timeframe == timeframe1:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 4
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe1.items()
if option == "Option1"
}
elif chosen_timeframe == timeframe2:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 4
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe2.items()
if option == "Option1"
}
elif (max_amount_limit - selected_objects_size) < 3:
available_objects_list = []
if chosen_timeframe == timeframe1:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 3
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe1.items()
if option == "Option1"
}
elif chosen_timeframe == timeframe2:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 3
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe2.items()
if option == "Option1"
}
object_availability = available_objects_list
object_itr = 0
for i in object_availability:
print(object_itr, end=' - ')
for key, val in i.items():
print(key, ": ", val, end='\n ')
print()
object_itr = object_itr+1
chosen_object_index = input("> ")
chosen_object_index = int(chosen_object_index)
user_stage1_objects.append(object_availability[chosen_object_index]["Item Name"])
selected_objects_size = selected_objects_size + object_availability[chosen_object_index]["Size"]
if max_amount_limit == selected_objects_size:
objects_chosen = "Done"
else:
continue_object_selection = input("""
You have """+str(int(max_amount_limit - selected_objects_size))+""" amounts left.
Do you want to select more objects from Option1, or move on to Option2?
1 - Continue with Option1
2 - Move on to Option2
>""")
if continue_object_selection == "1":
objects_chosen is None
elif continue_object_selection == "2":
objects_chosen - "Done"
else:
print("Not a valid choice, try again")
def fill_chosen_objects():
global max_amount_limit, selected_objects_size, available_objects_list, user_stage1_objects
max_amount_limit = 5
selecting_objects = input("""
Would you like to see available choices from Option1?
1 - Yes
2 - No
> """)
if selecting_objects == "1":
stage1_selection()
elif selecting_objects == "2":
objects_chosen = "Done"
return user_stage1_objects
fill_chosen_objects()
Sorry for the long code drop here, but I've tried posting smaller sections of code before and what works then doesn't seem to work when applied to the larger codebase.
Basically, the user should never see objects with a size larger than what they have remaining once they've factored in the max_amount_limit - the accumulated items they've already chosen.
I am able to see the object list the first time through, but it crashes when I try and look through the list to choose a second object.
The AttributeError: 'str' object has no attribute 'items' error appears at this line
for key, val in i.items():
Thank you
Check out this simplification that calculates a remaining space and offers the user a list of items that will fit in it. I think this might get you unblocked.
def get_timeframe():
timeframe1 = {
"Option1": {
"Common": [
{"Item Name": "A1", "Size": 3},
{"Item Name": "A2", "Size": 4}
],
"Uncommon": [
{"Item Name": "B1", "Size": 2},
{"Item Name": "B2", "Size": 1}
]
},
"Option2": {
"Common": [
{"Item Name": "C1", "Size": 3},
{"Item Name": "C2", "Size": 1}
],
"Uncommon": [
{"Item Name": "D1", "Size": 2},
{"Item Name": "D2", "Size": 4}
]
}
}
timeframe2 = {
"Option1": {
"Common": [
{"Item Name": "A1", "Size": 3},
{"Item Name": "A3", "Size": 2}
],
"Uncommon": [
{"Item Name": "B1", "Size": 2},
{"Item Name": "B2", "Size": 1}
]
},
"Option2": {
"Common": [
{"Item Name": "C2", "Size": 1},
{"Item Name": "C3", "Size": 3}
],
"Uncommon": [
{"Item Name": "D1", "Size": 2},
{"Item Name": "D2", "Size": 4}
]
}
}
while True:
timeframe_choice = input("""
Select Timeframe1 or Timeframe2
1 - Timeframe1
2 - Timeframe2
> """)
if timeframe_choice == "1":
return timeframe1
if timeframe_choice == "2":
return timeframe2
print("Not a valid choice, try again")
def select_item(available_objects_list):
while True:
for index, item in enumerate(available_objects_list):
print(index, item)
chosen_object_index = int(input("Pick One: "))
try:
return available_objects_list[chosen_object_index]
except IndexError:
pass
def stage1_selection(max_amount_limit, chosen_timeframe):
user_stage1_objects = []
available_objects_list = []
option_choice = "Option1"
while (remaining_space := max_amount_limit - sum(item["Size"] for item in user_stage1_objects)) > 0:
print(f"You have {remaining_space} space left in your pack.")
available_objects_list = [
{**item, **{"rarity": rarity}}
for rarity, items in chosen_timeframe[option_choice].items()
for item in items
if item["Size"] <= remaining_space
]
user_stage1_objects.append(select_item(available_objects_list))
return user_stage1_objects
max_amount_limit = 5
chosen_timeframe = get_timeframe()
user_stage1_objects = stage1_selection(max_amount_limit, chosen_timeframe)
print("You have selected: ")
for item in user_stage1_objects:
print(f"\t{item}")