This commit is contained in:
reschan 2021-10-18 11:42:04 +07:00
commit d380bb1e6c
6 changed files with 3787 additions and 5322 deletions

1555
clean.json

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -87,7 +87,7 @@
"Alka Cometflinger": 85, "Alka Cometflinger": 85,
"Alkahest": 86, "Alkahest": 86,
"Alazarin": 87, "Alazarin": 87,
"All for One": 88, "Fluorescence": 88,
"Allegro": 89, "Allegro": 89,
"Almuj's Walker": 90, "Almuj's Walker": 90,
"Alligator": 91, "Alligator": 91,
@ -420,7 +420,7 @@
"Brackenwall": 418, "Brackenwall": 418,
"Bravery": 419, "Bravery": 419,
"Bow of Wisdom": 420, "Bow of Wisdom": 420,
"Breakdown": 421, "Gert Relik": 421,
"Brass Knuckle": 422, "Brass Knuckle": 422,
"Breakbeat": 423, "Breakbeat": 423,
"Breaker Bar": 424, "Breaker Bar": 424,
@ -474,7 +474,7 @@
"Caledonia": 472, "Caledonia": 472,
"Call of the Void": 473, "Call of the Void": 473,
"Calming Torc": 474, "Calming Torc": 474,
"Cancer\u058e": 475, "Cancer֎": 475,
"Call to Concord": 476, "Call to Concord": 476,
"Canyon Spirit": 477, "Canyon Spirit": 477,
"Candlestick": 478, "Candlestick": 478,
@ -575,7 +575,7 @@
"Cobra": 573, "Cobra": 573,
"Coat of Byakko": 574, "Coat of Byakko": 574,
"Cockleburr": 575, "Cockleburr": 575,
"Coconut\u058e": 576, "Coconut֎": 576,
"Col Legno": 577, "Col Legno": 577,
"Coiled Briar": 578, "Coiled Briar": 578,
"Cold Integrity": 579, "Cold Integrity": 579,
@ -772,7 +772,7 @@
"Sacrificial": 770, "Sacrificial": 770,
"Admiral": 771, "Admiral": 771,
"Ouragan": 772, "Ouragan": 772,
"Ambivalence": 773, "Inmate Outfit": 773,
"Algaa": 774, "Algaa": 774,
"Gaping Cavity": 775, "Gaping Cavity": 775,
"Redbeard's Hand Cannon": 776, "Redbeard's Hand Cannon": 776,
@ -1658,7 +1658,7 @@
"Lizard": 1656, "Lizard": 1656,
"Loam": 1657, "Loam": 1657,
"Little Machine": 1658, "Little Machine": 1658,
"Lockpick\u058e": 1659, "Lockpick֎": 1659,
"Loaded Question": 1660, "Loaded Question": 1660,
"Locrian": 1661, "Locrian": 1661,
"Log Suit": 1662, "Log Suit": 1662,
@ -3544,98 +3544,104 @@
"Zombified Branch": 3542, "Zombified Branch": 3542,
"default": 3543, "default": 3543,
"Zipper": 3544, "Zipper": 3544,
"Anxiolytic": 3545, "First Steps": 3545,
"Panic Zealot": 3546, "Spiketop": 3546,
"Dissociation": 3547, "Waist Apron": 3547,
"Adrenaline": 3548, "Speedyboy": 3548,
"Agave": 3549, "Saltest Spear": 3549,
"Amanuensis": 3550, "Tachypsychia": 3550,
"Ataraxy": 3551, "Conspirator's Trickpockets": 3551,
"Blossom Haze": 3552, "Philosopher": 3552,
"Chain Rule": 3553, "Capsid Frame": 3553,
"Clerical": 3554, "Crystal Coil": 3554,
"Cursed Jackboots": 3555, "Phage Pins": 3555,
"Derecho": 3556, "Cold Wave": 3556,
"Double Vision": 3557, "Heat Death": 3557,
"Entanglement": 3558, "Impact Winter": 3558,
"Example": 3559, "Cracked Oak Bow": 3559,
"Fluorescence": 3560, "Cracked Oak Dagger": 3560,
"Gert Relik": 3561, "Cracked Oak Wand": 3561,
"Guillotine": 3562, "Cracked Oak Spear": 3562,
"Infernal Impulse": 3563, "Cracked Oak Relik": 3563,
"Inmate Outfit": 3564, "Advancement": 3564,
"Luminiferous Aether": 3565, "Diminution": 3565,
"Magnet Repulsor": 3566, "Intuition": 3566,
"Matchbook": 3567, "Hourslip": 3567,
"Multitool": 3568, "Longevity": 3568,
"First Steps": 3569, "Seal Breaker": 3569,
"Spiketop": 3570, "Practice": 3570,
"Waist Apron": 3571, "Slainte": 3571,
"Ophiolite": 3572, "Reversion": 3572,
"Ornithopter": 3573, "Secondsaver": 3573,
"Outrage": 3574, "Tempo Tanto": 3574,
"Panic Attack": 3575, "Metamorphosis": 3575,
"Pedometer": 3576, "Homeorhesis": 3576,
"Phantasmagoria": 3577, "Pro Tempore": 3577,
"Photon": 3578, "Multitool": 3578,
"Pro Tempore": 3579, "Amanuensis": 3580,
"Prosencephalon": 3580, "Double Vision": 3581,
"Homeorhesis": 3581, "Panic Attack": 3582,
"Abrasion": 3582, "Schist": 3583,
"Eyes on All": 3583, "Phantasmagoria": 3584,
"Metamorphosis": 3584,
"Cacophony": 3585, "Cacophony": 3585,
"Recalcitrance": 3586, "Vacarme": 3586,
"Rhythm of the Seasons": 3587, "Scarlet Veil": 3587,
"Dodge Core": 3588, "Guillotine": 3588,
"Harden Core": 3589, "Adrenaline": 3589,
"Hustle Core": 3590, "Tempo Trebuchet": 3590,
"Overload Core": 3591, "Stratosphere": 3591,
"Synchro Core": 3592, "Pedometer": 3593,
"Cinfras Souvenir T-Shirt": 3593, "Agave": 3594,
"Speedyboy": 3594, "Breakdown": 3595,
"Saltest Spear": 3595, "Ophiolite": 3596,
"Schist": 3596, "Magnet Repulsor": 3597,
"Scarlet Veil": 3597, "Rhythm of the Seasons": 3598,
"Spiritdancer": 3598, "Infernal Impulse": 3599,
"Stratosphere": 3599, "Panic Zealot": 3600,
"The Jingling Jester": 3600, "Recalcitrance": 3601,
"Vacarme": 3601, "Eyes on All": 3602,
"Capsid Frame": 3602, "Derecho": 3603,
"Phage Pins": 3603, "Synchro Core": 3604,
"Crystal Coil": 3604, "Clerical": 3605,
"Cold Wave": 3605, "Dodge Core": 3606,
"Conspirator's Trickpockets": 3606, "Ataraxy": 3607,
"Heat Death": 3607, "Ornithopter": 3608,
"Hesperium": 3608, "Photon": 3609,
"Impact Winter": 3609, "Blossom Haze": 3610,
"Cracked Oak Dagger": 3610, "Entanglement": 3612,
"Cracked Oak Relik": 3611, "Overload Core": 3613,
"Cracked Oak Spear": 3612, "Spiritdancer": 3615,
"Cracked Oak Wand": 3613, "Harden Core": 3616,
"Cracked Oak Bow": 3614, "Chain Rule": 3617,
"Philosopher": 3615, "Ambivalence": 3618,
"Advancement": 3616, "Outrage": 3619,
"Dilation": 3617, "Prosencephalon": 3620,
"Hourslip": 3618, "The Jingling Jester": 3621,
"Diminution": 3619, "Matchbook": 3622,
"Intuition": 3620, "Hustle Core": 3623,
"Longevity": 3621, "Abrasion": 3624,
"Practice": 3622, "All for One": 3625,
"Reversion": 3623, "Example": 3626,
"Seal Breaker": 3624, "Luminiferous Aether": 3627,
"Secondsaver": 3625, "Dissociation": 3628,
"Slainte": 3626, "Anxiolytic": 3629,
"Tempo Ticker": 3627, "Cursed Jackboots": 3630,
"Tempo Tanto": 3628, "Cinfras Souvenir T-Shirt": 3631,
"Tempo Totem": 3629, "Tempo Totem": 3632,
"Tempo Trebuchet": 3630, "Dilation": 3633,
"Tempo Trident": 3631, "Tempo Ticker": 3634,
"Timelocked Breath": 3632, "Timelocked Breath": 3635,
"Timelocked Coal": 3633, "Timelocked Coal": 3636,
"Timelocked Dew": 3634, "Timelocked Spark": 3637,
"Timelocked Spark": 3635, "Timelocked Dew": 3638,
"Timelocked Stone": 3636, "Tempo Trident": 3639,
"Trouble Tamer": 3637, "Timelocked Stone": 3640,
"Tachypsychia": 3638 "Trouble Tamer": 3641,
"Hesperium": 3642,
"Convergence": 3643,
"Quetzalcoatl": 3644,
"Epoch": 3645,
"Immolation": 3646,
"Oblivion": 3647,
"Narcissist": 3648
} }

View file

@ -1,66 +1,154 @@
import sys """Json diff checker for manual testing."""
import argparse
import json import json
f1 = sys.argv[1] import sys
f2 = sys.argv[2]
json1 = json.load(open(f1)) from recordclass import recordclass
json2 = json.load(open(f2))
def shorten(v): JSONDiffReporter = recordclass('JSONDiffReporter', 'val_diff len_diff type_diff path_diff get_key')
if len(v) > 100:
return v[:100] + "..."
return v
def is_basic(t):
return t is int or t is str or t is float or t is bool or t is list
def custom_input(): def shorten(val):
if custom_input.alive: """Utility for printing large functions, auto shorten"""
if len(val) > 100:
return val[:100] + "..."
return val
def is_basic(val):
"""Check if the given value is a "primitive" type in json (not object)."""
return val is int or val is str or val is float or val is bool or val is list
def __custom_input(_):
"""Read from stdin unless user has cancelled"""
if __custom_input.alive:
try: try:
return input() return input()
except: except KeyboardInterrupt:
custom_input.alive = False __custom_input.alive = False
return "" return ""
custom_input.alive = True __custom_input.alive = True
def list_diff(list1, list2, path): def __print_val_diff(val1, val2, path):
print(f"{path}: Value difference")
print(f" Left: {shorten(str(val1))}")
print(f" Right: {shorten(str(val2))}")
def __print_len_diff(val1, val2, path):
print(f"{path}: Length difference")
print(f" Left (length {len(val1)}): {shorten(str(val1))}")
print(f" Right (length {len(val2)}): {shorten(str(val2))}")
def __print_type_diff(type1, type2, path):
print(f"{path}: Type difference [{str(type1)} != {str(type2)}]")
#def __print_path_diff(left, right, key, path, side):
def __print_path_diff(_1, _2, key, path, side):
if side:
print(f"{path}.{key}: Contained in right but not left")
else:
print(f"{path}.{key}: Contained in left but not right")
print(f" Value: {shorten(str(key))}")
# Default diff reporter (just prints everything)
JSON_DIFF_PRINTER = JSONDiffReporter(
__print_val_diff,
__print_len_diff,
__print_type_diff,
__print_path_diff,
__custom_input
)
def __val_diff(val1, val2, path):
errmsg = (f"{path}: Value difference\n"
+ f" Left: {shorten(str(val1))}\n"
+ f" Right: {shorten(str(val2))}")
raise ValueError(errmsg)
def __len_diff(val1, val2, path):
errmsg = (f"{path}: Length difference\n"
+ f" Left (length {len(val1)}): {shorten(str(val1))}\n"
+ f" Right (length {len(val2)}): {shorten(str(val2))}")
raise ValueError(errmsg)
def __type_diff(type1, type2, path):
raise TypeError(f"{path}: Type difference [{str(type1)} != {str(type2)}]")
#def __print_path_diff(left, right, key, path, side):
def __path_diff(_1, _2, key, path, side):
if side:
errmsg = f"{path}.{key}: Contained in right but not left\n"
else:
errmsg = f"{path}.{key}: Contained in left but not right\n"
errmsg += f" Value: {shorten(str(key))}"
raise AttributeError(errmsg)
def get_test_diff_handler(get_key):
"""Make a JSON diff handler that throws errors on failure.
:param: get_key: key getter func
"""
return JSONDiffReporter(__val_diff, __len_diff, __type_diff, __path_diff, get_key)
def list_diff(reporter, list1, list2, path) -> bool:
"""Compute list difference between two object lists (compare by key)"""
print(f"Encountered object list {path}, enter match key: ", end="", file=sys.stderr) print(f"Encountered object list {path}, enter match key: ", end="", file=sys.stderr)
key = custom_input() key = reporter.get_key(path)
if (key == ""): if key == "":
if list1 != list2: if list1 != list2:
print(f"{path}.{k}: Value difference") reporter.val_diff(list1, list2, path)
print(f" Left: {shorten(str(v))}")
print(f" Right: {shorten(str(obj))}")
else: else:
left = {x[key]: x for x in list1} left = {x[key]: x for x in list1}
right = {x[key]: x for x in list2} right = {x[key]: x for x in list2}
object_diff(left, right, path) object_diff(reporter, left, right, path)
def object_diff(obj1, obj2, path): def object_diff(reporter, obj1, obj2, path) -> bool:
for (k, v) in obj1.items(): """Compute object difference between two objects... kinda"""
for (k, val) in obj1.items():
if k in obj2: if k in obj2:
obj = obj2[k] obj = obj2[k]
type1 = type(v) type1 = type(val)
type2 = type(obj) type2 = type(obj)
if type1 != type2: if type1 != type2:
print(f"{path}.{k}: Type difference [{str(type1)} != {str(type2)}]") reporter.type_diff(type1, type2, f"{path}.{k}")
elif type1 is list and type2 is list and not is_basic(type(v[0])): elif type1 is list:
list_diff(v, obj, path+"."+str(k)) if len(val) != len(obj):
elif (type1 is list and is_basic(type(v[0]))) or is_basic(type1) or v is None or obj2 is None: reporter.len_diff(val, obj, f"{path}.{k}")
if v != obj: elif len(val) == 0:
print(f"{path}.{k}: Value difference") continue
print(f" Left: {shorten(str(v))}") elif is_basic(type(val[0])):
print(f" Right: {shorten(str(obj))}") if val != obj:
reporter.val_diff(val, obj, f"{path}.{k}")
continue
list_diff(reporter, val, obj, path+"."+k)
elif is_basic(type1) or val is None or obj2 is None:
if val != obj:
reporter.val_diff(val, obj, f"{path}.{k}")
else: else:
object_diff(v, obj, path+"."+str(k)) object_diff(reporter, val, obj, f"{path}.{k}")
else: continue
print(f"{path}.{k}: Contained in left but not right") reporter.path_diff(obj1, obj2, k, path, True)
print(f" Value: {shorten(str(v))}") for k in obj2:
for (k, v) in obj2.items():
if k not in obj1: if k not in obj1:
print(f"{path}.{k}: Contained in right but not left") reporter.path_diff(obj1, obj2, k, path, True)
print(f" Value: {shorten(str(v))}")
if type(json1) is list and type(json2) is list: def json_diff(json1, json2, reporter=JSON_DIFF_PRINTER) -> bool:
list_diff(json1, json2, "$") """Run the json diff tool on two json objects."""
else: if isinstance(json1, list) and isinstance(json2, list):
object_diff(json1, json2, "$") return list_diff(reporter, json1, json2, "$")
return object_diff(reporter, json1, json2, "$")
if __name__ == "__main__":
argparser = argparse.ArgumentParser(description="JSON diff utility")
argparser.add_argument('file1', action='store', type=str,
help="First file to compare"
)
argparser.add_argument('file2', action='store', type=str,
help="Second file to compare"
)
args = argparser.parse_args()
with open(args.file1, 'r', encoding="utf-8") as file1:
json1 = json.load(file1)
with open(args.file2, 'r', encoding="utf-8") as file2:
json2 = json.load(file2)
json_diff(json1, json2)

View file

@ -209,7 +209,13 @@ for item in items:
items.extend(unchanged_items) items.extend(unchanged_items)
items.extend(remap_items) items.extend(remap_items)
with open("id_map.json","w") as id_mapfile:
print("{", file=id_mapfile)
outputs = []
for v, k in sorted((v, k) for k, v in id_map.items()):
outputs.append(f' "{k}": {v}')
print(',\n'.join(outputs), file=id_mapfile)
print("}", file=id_mapfile)
with open("clean.json", "w") as outfile: with open("clean.json", "w") as outfile:
json.dump(data, outfile, indent=2) json.dump(data, outfile, indent=2)
with open("compress.json", "w") as outfile: with open("compress.json", "w") as outfile:

View file

@ -1,80 +0,0 @@
import json
with open("clean.json") as infile:
olds = json.load(infile)
items = olds["items"]
item_oldnames_map = dict()
item_newnames_map = dict()
VERSION_STR = " (1.20)"
max_old_id = 0
for item in items:
item_id = item["id"]
if "displayName" in item:
displayName = item["displayName"]
else:
displayName = item["name"]
item_name = displayName.replace(VERSION_STR, "")
if item_id > 10000:
map_name = item["name"].replace(VERSION_STR, "")
item_newnames_map[map_name] = item
item["displayName"] = item_name
else:
item_oldnames_map[item_name] = item
if item_id > max_old_id:
max_old_id = item_id
dummy_items = []
for (name, item) in item_newnames_map.items():
if name in item_oldnames_map:
old_item = item_oldnames_map[name]
if "displayName" in item:
displayName = item["displayName"].replace(VERSION_STR, "")
else:
displayName = name
save_old = ["id","set","quest","drop","restrict", "name"]
old_mappings = { k: old_item[k] for k in save_old if k in old_item }
old_item.clear()
if "restrict" in item:
del item["restrict"]
for k in item:
old_item[k] = item[k]
for k in old_mappings:
old_item[k] = old_mappings[k]
save_id = item["id"]
item.clear()
item["id"] = save_id
item["name"] = str(save_id)
item["remapID"] = old_item["id"]
else:
if "restrict" in item:
in_str = input(name + " restriction: ").strip()
if in_str:
item["restrict"] = in_str
else:
del item["restrict"]
item["name"] = name
dummy_item = dict()
dummy_item["id"] = item["id"]
max_old_id += 1
item["id"] = max_old_id
dummy_item["remapID"] = item["id"]
dummy_items.append(dummy_item)
items.extend(dummy_items)
sets = olds["sets"]
data = dict()
data["items"] = items
data["sets"] = sets
with open("updated.json", "w") as outfile:
json.dump(data, outfile, indent=2)