mirror of
https://github.com/AkaiiKitsune/nijiiro-toolset.git
synced 2024-11-13 22:17:36 +01:00
476 lines
15 KiB
Python
476 lines
15 KiB
Python
|
from enum import Enum
|
||
|
import gzip
|
||
|
from encryption import decrypt_file
|
||
|
import json
|
||
|
import os
|
||
|
|
||
|
# "japaneseText"
|
||
|
# "englishUsText"
|
||
|
# "chineseTText"
|
||
|
# "koreanText"
|
||
|
# "chineseSText"
|
||
|
language = "englishUsText"
|
||
|
|
||
|
isCHN = False
|
||
|
|
||
|
# region Loading files
|
||
|
checkFile = {}
|
||
|
|
||
|
# Loading musicinfo.bin
|
||
|
try:
|
||
|
infos = json.load(gzip.open("./Data/x64/datatable/musicinfo.bin", "rb"))["items"]
|
||
|
except:
|
||
|
try:
|
||
|
infos = json.loads(
|
||
|
decrypt_file(input_file="./Data/x64/datatable/musicinfo.bin")
|
||
|
)["items"]
|
||
|
isCHN = True
|
||
|
except:
|
||
|
print("Couldn't load musicinfo.bin, exiting.")
|
||
|
exit(0)
|
||
|
|
||
|
# Loading music_usbsetting.bin
|
||
|
try:
|
||
|
usb = (
|
||
|
json.loads(
|
||
|
decrypt_file(input_file="./Data/x64/datatable/music_usbsetting.bin")
|
||
|
)["items"]
|
||
|
if isCHN
|
||
|
else None
|
||
|
)
|
||
|
except:
|
||
|
usb = None
|
||
|
|
||
|
# Loading music_order.bin
|
||
|
try:
|
||
|
order = (
|
||
|
json.loads(decrypt_file(input_file="./Data/x64/datatable/music_order.bin"))[
|
||
|
"items"
|
||
|
]
|
||
|
if isCHN
|
||
|
else json.load(gzip.open("./Data/x64/datatable/music_order.bin", "rb"))["items"]
|
||
|
)
|
||
|
except:
|
||
|
order = None
|
||
|
|
||
|
# Loading music_attribute.bin
|
||
|
try:
|
||
|
attributes = (
|
||
|
json.loads(decrypt_file(input_file="./Data/x64/datatable/music_attribute.bin"))[
|
||
|
"items"
|
||
|
]
|
||
|
if isCHN
|
||
|
else json.load(gzip.open("./Data/x64/datatable/music_attribute.bin", "rb"))[
|
||
|
"items"
|
||
|
]
|
||
|
)
|
||
|
except:
|
||
|
attributes = None
|
||
|
|
||
|
# Loading wordlist.bin
|
||
|
try:
|
||
|
words = (
|
||
|
json.loads(decrypt_file(input_file="./Data/x64/datatable/wordlist.bin"))[
|
||
|
"items"
|
||
|
]
|
||
|
if isCHN
|
||
|
else json.load(gzip.open("./Data/x64/datatable/wordlist.bin", "rb"))["items"]
|
||
|
)
|
||
|
except:
|
||
|
words = None
|
||
|
# endregion
|
||
|
|
||
|
# Forcing japanese language on 08.18 as this is what is usually used for omnimix.
|
||
|
if isCHN:
|
||
|
language = "japaneseText"
|
||
|
|
||
|
|
||
|
# region Classes And Methods
|
||
|
class Genres(Enum):
|
||
|
Unknown = -1
|
||
|
Pop = 0
|
||
|
Anime = 1
|
||
|
Kids = 2
|
||
|
Vocaloid = 3
|
||
|
GameMusic = 4
|
||
|
NamcoOriginal = 5
|
||
|
Variety = 6 if not isCHN else 7
|
||
|
Classical = 7 if not isCHN else 8
|
||
|
if not isCHN:
|
||
|
Custom = 9
|
||
|
|
||
|
@classmethod
|
||
|
def _missing_(cls, value):
|
||
|
return cls.Unknown
|
||
|
|
||
|
|
||
|
def findKeyInList(list: list, key: str, keyValue, value=None):
|
||
|
for object in list:
|
||
|
if object[key] == keyValue:
|
||
|
if value is not None:
|
||
|
return object[value]
|
||
|
else:
|
||
|
return object
|
||
|
|
||
|
if value is not None:
|
||
|
return ""
|
||
|
else:
|
||
|
return None
|
||
|
|
||
|
|
||
|
def findAllObjects(list: list, key: str, keyValue):
|
||
|
templist = []
|
||
|
templist.append(list)
|
||
|
objects = []
|
||
|
|
||
|
for element in templist[0]:
|
||
|
if element[key] == keyValue:
|
||
|
objects.append(element)
|
||
|
|
||
|
return objects
|
||
|
|
||
|
|
||
|
def findDoubloninList(list: list, key: str, keyValue):
|
||
|
if len(findAllObjects(list=list, key=key, keyValue=keyValue)) > 1:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
|
||
|
def doesPathExist(path: str):
|
||
|
if os.path.exists(path):
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
|
||
|
def initCheckFile():
|
||
|
global checkFile
|
||
|
checkFile = {
|
||
|
"musicinfo.json": {
|
||
|
"TotalEntries": len(infos),
|
||
|
"MaxId": max(infos, key=lambda ev: ev["uniqueId"])["uniqueId"],
|
||
|
"UniqueIdTooHigh": 0,
|
||
|
"UniqueIdTooHighList": [],
|
||
|
"UnusedUniqueIds": 0,
|
||
|
"UnusedUniqueIdsList": [],
|
||
|
"Doublons": 0,
|
||
|
"DoublonsList": [],
|
||
|
"GenreNoList": [],
|
||
|
},
|
||
|
}
|
||
|
|
||
|
if attributes is not None:
|
||
|
checkFile["music_attribute.json"] = {
|
||
|
"TotalEntries": len(attributes),
|
||
|
"Missing": 0,
|
||
|
"MissingList": [],
|
||
|
"Mismatch": 0,
|
||
|
"MismatchList": [],
|
||
|
"Doublons": 0,
|
||
|
"DoublonsList": [],
|
||
|
}
|
||
|
|
||
|
if order is not None:
|
||
|
checkFile["music_order.json"] = {
|
||
|
"TotalEntries": len(order),
|
||
|
"UniqueEntries": 0,
|
||
|
"UniqueEntriesList": [],
|
||
|
"GenreNoList": [],
|
||
|
"Missing": 0,
|
||
|
"MissingList": [],
|
||
|
"Mismatch": 0,
|
||
|
"MismatchList": [],
|
||
|
}
|
||
|
|
||
|
if usb is not None:
|
||
|
checkFile["music_usbsetting.json"] = {
|
||
|
"TotalEntries": len(usb),
|
||
|
"Missing": 0,
|
||
|
"MissingList": [],
|
||
|
"Mismatch": 0,
|
||
|
"MismatchList": [],
|
||
|
"Doublons": 0,
|
||
|
"DoublonsList": [],
|
||
|
}
|
||
|
|
||
|
if words is not None:
|
||
|
checkFile["wordlist.json"] = {
|
||
|
"TotalEntries": len(words),
|
||
|
"MissingSongName": 0,
|
||
|
"MissingSongNameList": [],
|
||
|
"MissingSongSub": 0,
|
||
|
"MissingSongSubList": [],
|
||
|
"MissingSongDetail": 0,
|
||
|
"MissingSongDetailList": [],
|
||
|
"Doublons": 0,
|
||
|
"DoublonsList": [],
|
||
|
}
|
||
|
|
||
|
checkFile.update(
|
||
|
{
|
||
|
"GameFiles": {
|
||
|
"MissingSound": 0,
|
||
|
"MissingSoundList": [],
|
||
|
"MissingFumen": 0,
|
||
|
"MissingFumenList": [],
|
||
|
},
|
||
|
}
|
||
|
)
|
||
|
|
||
|
|
||
|
class Song:
|
||
|
id = ""
|
||
|
uniqueId = -1
|
||
|
genreNo = -1
|
||
|
name = ""
|
||
|
sub = ""
|
||
|
detail = ""
|
||
|
|
||
|
def __init__(self, id, uniqueId, genreNo, name, sub, detail):
|
||
|
self.id = id
|
||
|
self.uniqueId = uniqueId
|
||
|
self.genreNo = genreNo
|
||
|
self.name = name
|
||
|
self.sub = sub
|
||
|
self.detail = detail
|
||
|
|
||
|
|
||
|
# endregion
|
||
|
|
||
|
# Loading all songs from musicinfo in an array
|
||
|
songs = []
|
||
|
|
||
|
for song in infos:
|
||
|
name = findKeyInList(
|
||
|
list=words,
|
||
|
key="key",
|
||
|
keyValue="song_" + song["id"],
|
||
|
value=language,
|
||
|
)
|
||
|
sub = findKeyInList(
|
||
|
list=words,
|
||
|
key="key",
|
||
|
keyValue="song_sub_" + song["id"],
|
||
|
value=language,
|
||
|
)
|
||
|
detail = findKeyInList(
|
||
|
list=words,
|
||
|
key="key",
|
||
|
keyValue="song_detail_" + song["id"],
|
||
|
value=language,
|
||
|
)
|
||
|
|
||
|
songs.append(
|
||
|
Song(
|
||
|
id=song["id"],
|
||
|
uniqueId=song["uniqueId"],
|
||
|
genreNo=song["genreNo"],
|
||
|
name=name,
|
||
|
sub=sub,
|
||
|
detail=detail,
|
||
|
)
|
||
|
)
|
||
|
|
||
|
# Preparing the json file containing the results of this checking script
|
||
|
initCheckFile()
|
||
|
|
||
|
# Checking...
|
||
|
for song in songs:
|
||
|
# musicinfo.json
|
||
|
if infos is not None:
|
||
|
# Checking for too high of an id
|
||
|
if song.uniqueId > 1599:
|
||
|
checkFile["musicinfo.json"]["UniqueIdTooHigh"] += 1
|
||
|
checkFile["musicinfo.json"]["UniqueIdTooHighList"].append(
|
||
|
{
|
||
|
"id": song.id,
|
||
|
"uniqueId": song.uniqueId,
|
||
|
}
|
||
|
)
|
||
|
# Listing genres and counting entries for each genres
|
||
|
genre = {
|
||
|
"GenreNo": song.genreNo,
|
||
|
"Name": Genres(song.genreNo).name,
|
||
|
"NumberofSongs": 0,
|
||
|
}
|
||
|
if (
|
||
|
findKeyInList(
|
||
|
list=checkFile["musicinfo.json"]["GenreNoList"],
|
||
|
key="GenreNo",
|
||
|
keyValue=song.genreNo,
|
||
|
)
|
||
|
is None
|
||
|
):
|
||
|
genre["NumberofSongs"] = len(
|
||
|
findAllObjects(list=infos, key="genreNo", keyValue=song.genreNo)
|
||
|
)
|
||
|
checkFile["musicinfo.json"]["GenreNoList"].append(genre)
|
||
|
# Search doublons
|
||
|
if findDoubloninList(list=infos, key="id", keyValue=song.id):
|
||
|
if song.id not in checkFile["musicinfo.json"]["DoublonsList"]:
|
||
|
checkFile["musicinfo.json"]["Doublons"] += 1
|
||
|
checkFile["musicinfo.json"]["DoublonsList"].append(song.id)
|
||
|
|
||
|
# music_usbsetting.json
|
||
|
if usb is not None:
|
||
|
# Check for missing uniqueIds or id and uniqueId mismatches
|
||
|
orderOccurences = findAllObjects(list=usb, key="id", keyValue=song.id)
|
||
|
if len(orderOccurences) == 0:
|
||
|
checkFile["music_usbsetting.json"]["Missing"] += 1
|
||
|
checkFile["music_usbsetting.json"]["MissingList"].append(song.id)
|
||
|
else:
|
||
|
for occurence in orderOccurences:
|
||
|
if not all(
|
||
|
[song.id == occurence["id"], song.uniqueId == occurence["uniqueId"]]
|
||
|
):
|
||
|
if (
|
||
|
song.id
|
||
|
not in checkFile["music_usbsetting.json"]["MismatchList"]
|
||
|
):
|
||
|
checkFile["music_usbsetting.json"]["Mismatch"] += 1
|
||
|
checkFile["music_usbsetting.json"]["MismatchList"].append(
|
||
|
{
|
||
|
"id": song.id,
|
||
|
"ExpectedUniqueId": song.uniqueId,
|
||
|
"CurrentUniqueId": occurence["uniqueId"],
|
||
|
}
|
||
|
)
|
||
|
|
||
|
# Search doublons
|
||
|
if findDoubloninList(list=usb, key="id", keyValue=song.id):
|
||
|
if song.id not in checkFile["music_usbsetting.json"]["DoublonsList"]:
|
||
|
checkFile["music_usbsetting.json"]["Doublons"] += 1
|
||
|
checkFile["music_usbsetting.json"]["DoublonsList"].append(song.id)
|
||
|
|
||
|
# music_attribute.json
|
||
|
if attributes is not None:
|
||
|
# Check for missing uniqueIds or id and uniqueId mismatches
|
||
|
orderOccurences = findAllObjects(list=attributes, key="id", keyValue=song.id)
|
||
|
if len(orderOccurences) == 0:
|
||
|
checkFile["music_attribute.json"]["Missing"] += 1
|
||
|
checkFile["music_attribute.json"]["MissingList"].append(song.id)
|
||
|
else:
|
||
|
for occurence in orderOccurences:
|
||
|
if not all(
|
||
|
[song.id == occurence["id"], song.uniqueId == occurence["uniqueId"]]
|
||
|
):
|
||
|
if song.id not in checkFile["music_attribute.json"]["MismatchList"]:
|
||
|
checkFile["music_attribute.json"]["Mismatch"] += 1
|
||
|
checkFile["music_attribute.json"]["MismatchList"].append(
|
||
|
{
|
||
|
"id": song.id,
|
||
|
"ExpectedUniqueId": song.uniqueId,
|
||
|
"CurrentUniqueId": occurence["uniqueId"],
|
||
|
}
|
||
|
)
|
||
|
if findDoubloninList(list=attributes, key="id", keyValue=song.id):
|
||
|
if song.id not in checkFile["music_attribute.json"]["DoublonsList"]:
|
||
|
checkFile["music_attribute.json"]["Doublons"] += 1
|
||
|
checkFile["music_attribute.json"]["DoublonsList"].append(song.id)
|
||
|
|
||
|
# music_order.json
|
||
|
if order is not None:
|
||
|
# Check for missing uniqueIds or id and uniqueId mismatches
|
||
|
orderOccurences = findAllObjects(list=order, key="id", keyValue=song.id)
|
||
|
if len(orderOccurences) == 0:
|
||
|
checkFile["music_order.json"]["Missing"] += 1
|
||
|
checkFile["music_order.json"]["MissingList"].append(song.id)
|
||
|
else:
|
||
|
songGenres = []
|
||
|
for occurence in orderOccurences:
|
||
|
songGenres.append(occurence["genreNo"])
|
||
|
if not all(
|
||
|
[song.id == occurence["id"], song.uniqueId == occurence["uniqueId"]]
|
||
|
):
|
||
|
if song.id not in checkFile["music_order.json"]["MismatchList"]:
|
||
|
checkFile["music_order.json"]["Mismatch"] += 1
|
||
|
checkFile["music_order.json"]["MismatchList"].append(
|
||
|
{
|
||
|
"id": song.id,
|
||
|
"ExpectedUniqueId": song.uniqueId,
|
||
|
"CurrentUniqueId": occurence["uniqueId"],
|
||
|
}
|
||
|
)
|
||
|
|
||
|
# Counting unique entries
|
||
|
checkFile["music_order.json"]["UniqueEntries"] += 1
|
||
|
checkFile["music_order.json"]["UniqueEntriesList"].append(
|
||
|
{
|
||
|
song.id: songGenres,
|
||
|
}
|
||
|
)
|
||
|
|
||
|
# wordlist.json
|
||
|
if words is not None:
|
||
|
if song.name == "":
|
||
|
checkFile["wordlist.json"]["MissingSongName"] += 1
|
||
|
checkFile["wordlist.json"]["MissingSongNameList"].append(song.id)
|
||
|
if song.sub == "":
|
||
|
checkFile["wordlist.json"]["MissingSongSub"] += 1
|
||
|
checkFile["wordlist.json"]["MissingSongSubList"].append(song.id)
|
||
|
if song.detail == "":
|
||
|
checkFile["wordlist.json"]["MissingSongDetail"] += 1
|
||
|
checkFile["wordlist.json"]["MissingSongDetailList"].append(song.id)
|
||
|
|
||
|
# Gamefiles
|
||
|
if not doesPathExist("./Data/x64/sound/" + "song_" + song.id + ".nus3bank"):
|
||
|
checkFile["GameFiles"]["MissingSound"] += 1
|
||
|
checkFile["GameFiles"]["MissingSoundList"].append(song.id)
|
||
|
if not doesPathExist("./Data/x64/fumen/" + song.id):
|
||
|
checkFile["GameFiles"]["MissingFumen"] += 1
|
||
|
checkFile["GameFiles"]["MissingFumenList"].append(song.id)
|
||
|
|
||
|
# Checking for vacant uniqueIds
|
||
|
for i in range(max(checkFile["musicinfo.json"]["MaxId"], 1600)):
|
||
|
key = findKeyInList(list=infos, key="uniqueId", keyValue=i)
|
||
|
|
||
|
if key is not None:
|
||
|
# Updating GenreNoList of music_order.json
|
||
|
for song in findAllObjects(
|
||
|
list=order, key="uniqueId", keyValue=key["uniqueId"]
|
||
|
):
|
||
|
genre = {
|
||
|
"GenreNo": song["genreNo"],
|
||
|
"Name": Genres(song["genreNo"]).name,
|
||
|
"NumberofSongs": 0,
|
||
|
}
|
||
|
if (
|
||
|
findKeyInList(
|
||
|
list=checkFile["music_order.json"]["GenreNoList"],
|
||
|
key="GenreNo",
|
||
|
keyValue=song["genreNo"],
|
||
|
)
|
||
|
is None
|
||
|
):
|
||
|
genre["NumberofSongs"] = len(
|
||
|
findAllObjects(list=order, key="genreNo", keyValue=song["genreNo"])
|
||
|
)
|
||
|
checkFile["music_order.json"]["GenreNoList"].append(genre)
|
||
|
else:
|
||
|
# Finding unused Ids bellow 1599
|
||
|
if i < 1600:
|
||
|
checkFile["musicinfo.json"]["UnusedUniqueIds"] += 1
|
||
|
checkFile["musicinfo.json"]["UnusedUniqueIdsList"].append(i)
|
||
|
|
||
|
# Checking for doublons in wordlist
|
||
|
if words is not None:
|
||
|
for word in words:
|
||
|
if findDoubloninList(list=words, key="key", keyValue=word["key"]):
|
||
|
if word["key"] not in checkFile["wordlist.json"]["DoublonsList"]:
|
||
|
checkFile["wordlist.json"]["Doublons"] += 1
|
||
|
checkFile["wordlist.json"]["DoublonsList"].append(word["key"])
|
||
|
|
||
|
# Sorting some values for better readability
|
||
|
checkFile["musicinfo.json"]["GenreNoList"].sort(
|
||
|
key=lambda x: x["GenreNo"], reverse=False
|
||
|
)
|
||
|
checkFile["music_order.json"]["GenreNoList"].sort(
|
||
|
key=lambda x: x["GenreNo"], reverse=False
|
||
|
)
|
||
|
|
||
|
# Writing everything to checks.json
|
||
|
json_object = json.dumps(checkFile, ensure_ascii=False, indent="\t")
|
||
|
# json_object = json.dumps(jsonList, ensure_ascii=False, indent="\t")
|
||
|
with open("./checks.json", "w", encoding="utf8") as outfile:
|
||
|
outfile.write(json_object)
|
||
|
print("Wrote checks.\n")
|