mirror of
https://github.com/Xevion/thaumic-itemstack.git
synced 2025-12-07 07:16:38 -06:00
inital restructure to use proper sorting methods
This commit is contained in:
215
thaumic.py
215
thaumic.py
@@ -7,11 +7,9 @@ print = pp.pprint
|
|||||||
|
|
||||||
|
|
||||||
# Open the file and load
|
# Open the file and load
|
||||||
with open(os.path.join(sys.path[0], 'thaumicjei_itemstack_aspects.json'), 'r') as file:
|
thuamicJSON = os.path.join(sys.path[0], 'thaumicjei_itemstack_aspects.json')
|
||||||
data = json.load(file)
|
aspectJSON = os.path.join(sys.path[0], 'aspect_tiers.json')
|
||||||
|
data, tiers = json.load(open(thuamicJSON, 'r')), json.load(open(aspectJSON, 'r'))
|
||||||
with open(os.path.join(sys.path[0], 'aspect_tiers.json'), 'r') as file:
|
|
||||||
tiers = json.load(file)
|
|
||||||
|
|
||||||
# Dictionary object for keying items
|
# Dictionary object for keying items
|
||||||
# build = {
|
# build = {
|
||||||
@@ -52,155 +50,70 @@ for aspect in range(len(data)):
|
|||||||
build[key]['aspects'] = {}
|
build[key]['aspects'] = {}
|
||||||
build[key]['aspects'][curAspect] = int(value)
|
build[key]['aspects'][curAspect] = int(value)
|
||||||
|
|
||||||
# Allows recursive. Sorts by the number of (different) aspects in the list.
|
|
||||||
# current=key list
|
|
||||||
# aspect=aspect dictionary
|
|
||||||
# reverse=reverses how the keys are changed in the key array
|
|
||||||
def sort_aspect_count(current, aspects, descending=False):
|
|
||||||
coefficient = max(list(map(len, aspects))) # Maximum value in the list
|
|
||||||
current = list(map(lambda x : x * (coefficient + 1), current)) # Multiply by coefficient + 1
|
|
||||||
# Reversal is done just by counting down FROM the cofficient (maximum value)
|
|
||||||
if descending:
|
|
||||||
for index in range(len(aspects)):
|
|
||||||
current[index] += coefficient - len(aspects[index].keys()) # Add value for the key
|
|
||||||
# Regular
|
|
||||||
elif not descending:
|
|
||||||
for index in range(len(aspects)):
|
|
||||||
current[index] += len(aspects[index].keys()) # Add value for the key
|
|
||||||
return current
|
|
||||||
|
|
||||||
# For use in process_sorts(), returns a function where descending has been predetermined
|
|
||||||
sort_aspect_count_prepare = lambda desc : partial(sort_aspect_count, descending=desc)
|
|
||||||
|
|
||||||
# current=key list
|
|
||||||
# aspect=aspect dictionary
|
|
||||||
# target=if specified, only count of a target aspect is considered
|
|
||||||
def sort_aspect_sum(current, aspects, targets=None, descending=False):
|
|
||||||
# Target is specified, have to account for the new maximum coefficient
|
|
||||||
if targets:
|
|
||||||
coefficient = 0
|
|
||||||
for aspectDict in aspects:
|
|
||||||
# Calculate which targets are in the aspectDict
|
|
||||||
available = [target for target in targets if target in aspectDict.keys()]
|
|
||||||
# If any are in it
|
|
||||||
if len(available) > 0:
|
|
||||||
# Calculate the sum of the target aspect's count's
|
|
||||||
# length of available is taken into account, items with higher target counts are prioritized
|
|
||||||
coefficient = max(coefficient, sum([aspectDict[target] for target in available]))
|
|
||||||
# Target is not specified, get a blanket sum
|
|
||||||
elif not targets:
|
|
||||||
coefficient = max(list(map(sum, [x.values() for x in aspects])))
|
|
||||||
# Multiply key list by coefficient
|
|
||||||
current = list(map(lambda x : x * (coefficient + 1), current))
|
|
||||||
# Target is specified
|
|
||||||
if targets:
|
|
||||||
# Descending: += (coefficient - value)
|
|
||||||
# Ascending: += (value)
|
|
||||||
if descending:
|
|
||||||
for index in range(len(current)):
|
|
||||||
# If the target aspect is actually in the dictionary
|
|
||||||
# then add it's count as the key 'change'
|
|
||||||
# edit: changed to allow for list of targets, using sum()
|
|
||||||
available = [target for target in targets if target in aspects[index].keys()]
|
|
||||||
if len(available) > 0:
|
|
||||||
current[index] += sum([aspects[index][target] for target in available])
|
|
||||||
elif not descending:
|
|
||||||
for index in range(len(current)):
|
|
||||||
available = [target for target in targets if target in aspects[index].keys()]
|
|
||||||
if len(available) > 0:
|
|
||||||
current[index] += coefficient - (sum([aspects[index][target] for target in available]))
|
|
||||||
elif not targets:
|
|
||||||
if descending:
|
|
||||||
for index in range(len(current)):
|
|
||||||
# Just add the sum instead
|
|
||||||
current[index] += sum(aspects[index].values())
|
|
||||||
elif not descending:
|
|
||||||
for index in range(len(current)):
|
|
||||||
current[index] += coefficient - sum(aspects[index].values())
|
|
||||||
return current
|
|
||||||
|
|
||||||
# For use in process_sorts, returns a function where target and descending have been predetermined
|
|
||||||
sort_aspect_sum_target = lambda targs, desc=False : partial(sort_aspect_sum, targets=targs, descending=desc)
|
|
||||||
|
|
||||||
def sort_target_ratio(current, aspects, targets, descending=False):
|
|
||||||
keylist = []
|
|
||||||
for item in aspects:
|
|
||||||
available = [aspect for aspect in item if aspect in targets]
|
|
||||||
sum_target = sum([item[aspect] for aspect in available]) # Sum of target counts
|
|
||||||
sum_non_target = sum(item.values()) - sum_target # Sum of non-target counts
|
|
||||||
if sum_non_target == 0:
|
|
||||||
ratio = sum_target
|
|
||||||
else:
|
|
||||||
ratio = sum_target / sum_non_target
|
|
||||||
keylist.append(ratio)
|
|
||||||
|
|
||||||
pIndex = [i for i in range(len(keylist))] # Create an index for every item in current to preserve order
|
|
||||||
preSort = list(zip(pIndex, aspects, keylist))
|
|
||||||
preSort.sort(key=lambda x : x[2])
|
|
||||||
pIndex, aspects, keylist = dezip(preSort)
|
|
||||||
|
|
||||||
# Multiply values to maintain coefficient
|
|
||||||
coefficient = len(keylist)
|
|
||||||
current = [value * (coefficient + 1) for value in current]
|
|
||||||
|
|
||||||
# Add values to complete 'sorting'
|
|
||||||
for index in range(len(keylist)):
|
|
||||||
current[pIndex[index]] += coefficient - index
|
|
||||||
return current
|
|
||||||
|
|
||||||
sort_target_ratio_prepare = lambda targs, descending=True : partial(sort_target_ratio, targets=targs, descending=descending)
|
|
||||||
|
|
||||||
# Processes a list of sort_functions against a list of names, aspects and a possible keylist
|
|
||||||
def process_sorts(sort_functions, names, aspects, keylist=None, reverse=True):
|
|
||||||
if keylist == None:
|
|
||||||
keylist = [1 for _ in range(len(names))]
|
|
||||||
for sort_func in sort_functions:
|
|
||||||
keylist = sort_func(keylist, aspects)
|
|
||||||
zipped = list(zip(names, aspects, keylist))
|
|
||||||
zipped.sort(key=lambda x : x[2], reverse=reverse)
|
|
||||||
newNames, newAspects, newKeylist = dezip(zipped)
|
|
||||||
return newNames, newAspects, newKeylist
|
|
||||||
|
|
||||||
# Filters for or against specific aspects
|
|
||||||
def filter_aspects(names, aspects, keylist, targets=[], doBlacklist=False):
|
|
||||||
zipped = zip(names, aspects, keylist)
|
|
||||||
if not doBlacklist:
|
|
||||||
zipped = [item for item in zipped if all(target in item[1].keys() for target in targets)]
|
|
||||||
elif doBlacklist:
|
|
||||||
zipped = [item for item in zipped if not any(target in item[1].keys() for target in targets)]
|
|
||||||
names, aspects, keylist = dezip(zipped)
|
|
||||||
return names, aspects, keylist
|
|
||||||
|
|
||||||
# Quick function to eliminate the tri element unzipping process
|
|
||||||
def dezip(zipped):
|
|
||||||
x, y, z = zip(*zipped)
|
|
||||||
x, y, z = list(x), list(y), list(z)
|
|
||||||
return x, y, z
|
|
||||||
|
|
||||||
# Filters for or against a specific mod or set of mods.
|
|
||||||
def filter_mods(names, aspects, keylist, targets=[], doBlacklist=False):
|
|
||||||
zipped = zip(names, aspects, keylist)
|
|
||||||
evaluate = lambda item, flip=False : flip ^ (item[0].split(':')[0] in targets)
|
|
||||||
if doBlacklist:
|
|
||||||
evaluate = partial(evaluate, flip=True)
|
|
||||||
zipped = [item for item in zipped if evaluate(item)]
|
|
||||||
names, aspects, keylist = dezip(zipped)
|
|
||||||
return names, aspects, keylist
|
|
||||||
|
|
||||||
# Get the names, aspects and the keylist generated
|
# Get the names, aspects and the keylist generated
|
||||||
names = build.keys()
|
names = build.keys()
|
||||||
aspects = [build[key]['aspects'] for key in build.keys()]
|
aspects = [build[key]['aspects'] for key in build.keys()]
|
||||||
current = [1 for _ in range(len(names))]
|
current = [1 for _ in range(len(names))]
|
||||||
|
|
||||||
whitelist = ['ordo']
|
# Returns a ratio of the selected (whitelist) aspects compared to others.
|
||||||
blacklist = []
|
# Reverse will make the whitelist into a blacklist.
|
||||||
blacklistMods = ['botania', 'twilightforest']
|
def ratio_selected_to_others(item, whitelist, reverse=False):
|
||||||
|
others = filter_count(item, whitelist)
|
||||||
|
selected = sum(item[1]['aspects'].values()) - others
|
||||||
|
if reverse: selected, others = others, selected
|
||||||
|
return selected / max(1.0, others)
|
||||||
|
|
||||||
# Mod Filtering
|
# Returns the count of the selected aspects for an item.
|
||||||
names, aspects, current = filter_mods(names, aspects, current, targets=blacklistMods, doBlacklist=True)
|
# Reverse will make the whitelist into a blacklist.
|
||||||
# Aspect Filtering, first
|
def filter_count(item, whitelist, reverse=False):
|
||||||
names, aspects, current = filter_aspects(names, aspects, current, targets=whitelist)
|
if not reverse:
|
||||||
names, aspects, current = filter_aspects(names, aspects, current, targets=blacklist, doBlacklist=True)
|
return sum(item[1]['aspects'][subitem] for subitem in item[1]['aspects'].keys() if subitem in whitelist)
|
||||||
# Sorting, aspect type count, aspect target sum
|
elif reverse:
|
||||||
names, aspects, current = process_sorts([sort_target_ratio_prepare(whitelist, descending=True), sort_aspect_sum_target(targs=whitelist)], names, aspects, reverse=True)
|
return sum(item[1]['aspects'][subitem] for subitem in item[1]['aspects'].keys() if subitem not in whitelist)
|
||||||
print(list(zip(names, aspects)))
|
|
||||||
|
# Returns True if the mod is in the whitelist.
|
||||||
|
# Reverse turns the whitelist into a blacklist.
|
||||||
|
def mod_filter(item, whitelist, reverse=False):
|
||||||
|
mod = item[0].split(':')[0]
|
||||||
|
value = mod in whitelist
|
||||||
|
return not value if reverse else value
|
||||||
|
|
||||||
|
# Returns True if the item is in the whitelist.
|
||||||
|
# Reverse turns the whitelist into a blacklist
|
||||||
|
def item_filter(item, whitelist, reverse=False):
|
||||||
|
item = item[0].split(':')[0]
|
||||||
|
value = item in whitelist
|
||||||
|
return not value if reverse else value
|
||||||
|
|
||||||
|
# Constants for sorting/filtering
|
||||||
|
# Empty blacklist/whitelist will do nothing. Both being non-empty may cause unintended behavior.
|
||||||
|
selected_aspects = ['terra']
|
||||||
|
whitelistItems = []
|
||||||
|
blacklistItems = []
|
||||||
|
whitelistMods = ['bloodmagic']
|
||||||
|
blacklistMods = []
|
||||||
|
|
||||||
|
# Filter the items
|
||||||
|
build_items = list(build.items())
|
||||||
|
# Blacklist Mods
|
||||||
|
if blacklistMods: build_items = list(filter(partial(mod_filter, whitelist=blacklistMods, reverse=True), build_items))
|
||||||
|
# Whitelist Mods
|
||||||
|
if whitelistMods: build_items = list(filter(partial(mod_filter, whitelist=whitelistMods, reverse=False), build_items))
|
||||||
|
# Blackist Items
|
||||||
|
if blacklistItems: build_items = list(filter(partial(item, whitelist=whitelistItems, reverse=True), build_items))
|
||||||
|
# # Whitelist Items
|
||||||
|
if whitelistItems: build_items = list(filter(partial(item_filter, whitelist=whitelistItems, reverse=False), build_items))
|
||||||
|
# build_items = list(filter)
|
||||||
|
|
||||||
|
# Builds the maps
|
||||||
|
map_selected_ratio = map(partial(ratio_selected_to_others, reverse=True, whitelist=selected_aspects), build_items)
|
||||||
|
map_selected_count = map(partial(filter_count, reverse=False, whitelist=selected_aspects), build_items)
|
||||||
|
# Zip the ratios and the items
|
||||||
|
zipped = list(zip(build_items, map_selected_ratio, map_selected_count))
|
||||||
|
# Sort the zipped item based on the maps zipped within
|
||||||
|
zipped.sort(key=lambda item : item[1:])
|
||||||
|
print(zipped[-100:])
|
||||||
|
|
||||||
|
# x = build_items[0]
|
||||||
|
# print(x)
|
||||||
|
# print(mod_filter(x, whitelist=['minecraft']))
|
||||||
Reference in New Issue
Block a user