From 897ca9ca4333ad4dfbb0f2feb3858c694240ecc7 Mon Sep 17 00:00:00 2001 From: DarkPhoenix Date: Thu, 19 Dec 2019 15:56:57 +0300 Subject: [PATCH] Update DB script to be able to work with sisi data --- db_update.py | 366 ++++++++++++++++++++++++++------------------------- 1 file changed, 189 insertions(+), 177 deletions(-) diff --git a/db_update.py b/db_update.py index 0a556acc4..ef31fb90d 100644 --- a/db_update.py +++ b/db_update.py @@ -88,52 +88,160 @@ def update_db(): # Create the database tables eos.db.gamedata_meta.create_all() - # Config dict - tables = { - 'clonegrades': ('fsd_lite', eos.gamedata.AlphaCloneSkill), - 'dogmaattributes': ('bulkdata', eos.gamedata.AttributeInfo), - 'dogmaeffects': ('bulkdata', eos.gamedata.Effect), - 'dogmatypeattributes': ('bulkdata', eos.gamedata.Attribute), - 'dogmatypeeffects': ('bulkdata', eos.gamedata.ItemEffect), - 'dogmaunits': ('bulkdata', eos.gamedata.Unit), - 'evecategories': ('fsd_lite', eos.gamedata.Category), - 'evegroups': ('fsd_lite', eos.gamedata.Group), - 'metagroups': ('fsd_binary', eos.gamedata.MetaGroup), - 'evetypes': ('fsd_lite', eos.gamedata.Item), - 'traits': ('phobos', eos.gamedata.Traits), - 'metadata': ('phobos', eos.gamedata.MetaData), - 'marketgroups': ('fsd_binary', eos.gamedata.MarketGroup)} + def _readData(minerName, jsonName, keyIdName=None): + with open(os.path.join(JSON_DIR, minerName, '{}.json'.format(jsonName)), encoding='utf-8') as f: + rawData = json.load(f) + if not keyIdName: + return rawData + # IDs in keys, rows in values + data = [] + for k, v in rawData.items(): + row = {} + row.update(v) + if keyIdName not in row: + row[keyIdName] = int(k) + data.append(row) + return data - fieldMapping = { - 'marketgroups': { - 'id': 'marketGroupID', - 'name': 'marketGroupName'}, - 'metagroups': { - 'id': 'metaGroupID'}} + def _addRows(data, cls, fieldMap=None): + if fieldMap is None: + fieldMap = {} + for row in data: + instance = cls() + for k, v in row.items(): + if isinstance(v, str): + v = v.strip() + setattr(instance, fieldMap.get(k, k), v) + eos.db.gamedata_session.add(instance) - rowsInValues = ( - 'evetypes', - 'evegroups', - 'evecategories', - 'marketgroups', - 'metagroups') + def processEveTypes(): + print('processing evetypes') + data = _readData('fsd_lite', 'evetypes', keyIdName='typeID') + for row in data: + if ( + # Apparently people really want Civilian modules available + (row['typeName'].startswith('Civilian') and "Shuttle" not in row['typeName']) or + row['typeName'] in ('Capsule', 'Dark Blood Tracking Disruptor') + ): + row['published'] = True - def convertIcons(data): - new = [] - for k, v in list(data.items()): - v['iconID'] = k - new.append(v) - return new - - def convertClones(data): newData = [] + for row in data: + if ( + row['published'] or + # group Ship Modifiers, for items like tactical t3 ship modes + row['groupID'] == 1306 or + # Micro Bombs (Fighters) + row['typeID'] in (41549, 41548, 41551, 41550) or + # Abyssal weather (environment) + row['groupID'] in ( + 1882, + 1975, + 1971, + # the "container" for the abyssal environments + 1983) + ): + newData.append(row) + _addRows(newData, eos.gamedata.Item) + return newData + + def processEveGroups(): + print('processing evegroups') + data = _readData('fsd_lite', 'evegroups', keyIdName='groupID') + _addRows(data, eos.gamedata.Group) + return data + + def processEveCategories(): + print('processing evecategories') + data = _readData('fsd_lite', 'evecategories', keyIdName='categoryID') + _addRows(data, eos.gamedata.Category) + + def processDogmaAttributes(): + print('processing dogmaattributes') + data = _readData('fsd_binary', 'dogmaattributes', keyIdName='attributeID') + _addRows(data, eos.gamedata.AttributeInfo) + + def processDogmaTypeAttributes(eveTypesData): + print('processing dogmatypeattributes') + data = _readData('fsd_binary', 'typedogma', keyIdName='typeID') + eveTypeIds = set(r['typeID'] for r in eveTypesData) + newData = [] + for typeData in data: + if typeData['typeID'] not in eveTypeIds: + continue + for row in typeData.get('dogmaAttributes', ()): + row['typeID'] = typeData['typeID'] + newData.append(row) + _addRows(newData, eos.gamedata.Attribute) + return newData + + def processDynamicItemAttributes(): + print('processing dynamicitemattributes') + data = _readData('fsd_binary', 'dynamicitemattributes') + for mutaID, mutaData in data.items(): + muta = eos.gamedata.DynamicItem() + muta.typeID = mutaID + muta.resultingTypeID = mutaData['inputOutputMapping'][0]['resultingType'] + eos.db.gamedata_session.add(muta) + + for x in mutaData['inputOutputMapping'][0]['applicableTypes']: + item = eos.gamedata.DynamicItemItem() + item.typeID = mutaID + item.applicableTypeID = x + eos.db.gamedata_session.add(item) + + for attrID, attrData in mutaData['attributeIDs'].items(): + attr = eos.gamedata.DynamicItemAttribute() + attr.typeID = mutaID + attr.attributeID = attrID + attr.min = attrData['min'] + attr.max = attrData['max'] + eos.db.gamedata_session.add(attr) + + def processDogmaEffects(): + print('processing dogmaeffects') + data = _readData('fsd_binary', 'dogmaeffects', keyIdName='effectID') + _addRows(data, eos.gamedata.Effect) + + def processDogmaTypeEffects(eveTypesData): + print('processing dogmatypeeffects') + data = _readData('fsd_binary', 'typedogma', keyIdName='typeID') + eveTypeIds = set(r['typeID'] for r in eveTypesData) + newData = [] + for typeData in data: + if typeData['typeID'] not in eveTypeIds: + continue + for row in typeData.get('dogmaEffects', ()): + row['typeID'] = typeData['typeID'] + newData.append(row) + _addRows(newData, eos.gamedata.ItemEffect) + return newData + + def processDogmaUnits(): + print('processing dogmaunits') + data = _readData('fsd_binary', 'dogmaunits', keyIdName='unitID') + _addRows(data, eos.gamedata.Unit, fieldMap={'name': 'marketGroupName'}) + + def processMarketGroups(): + print('processing marketgroups') + data = _readData('fsd_binary', 'marketgroups', keyIdName='marketGroupID') + _addRows(data, eos.gamedata.MarketGroup) + + def processMetaGroups(): + print('processing metagroups') + data = _readData('fsd_binary', 'metagroups', keyIdName='metaGroupID') + _addRows(data, eos.gamedata.MetaGroup) + + def processCloneGrades(): + print('processing clonegrades') + data = _readData('fsd_lite', 'clonegrades') + + newData = [] # December, 2017 - CCP decided to use only one set of skill levels for alpha clones. However, this is still # represented in the data as a skillset per race. To ensure that all skills are the same, we store them in a way # that we can check to make sure all races have the same skills, as well as skill levels - check = {} - for ID in data: for skill in data[ID]['skills']: newData.append({ @@ -144,18 +252,25 @@ def update_db(): if ID not in check: check[ID] = {} check[ID][int(skill['typeID'])] = int(skill['level']) - if not functools.reduce(lambda a, b: a if a == b else False, [v for _, v in check.items()]): raise Exception('Alpha Clones not all equal') - newData = [x for x in newData if x['alphaCloneID'] == 1] - if len(newData) == 0: raise Exception('Alpha Clone processing failed') - return newData + tmp = [] + for row in newData: + if row['alphaCloneID'] not in tmp: + cloneParent = eos.gamedata.AlphaClone() + setattr(cloneParent, 'alphaCloneID', row['alphaCloneID']) + setattr(cloneParent, 'alphaCloneName', row['alphaCloneName']) + eos.db.gamedata_session.add(cloneParent) + tmp.append(row['alphaCloneID']) + _addRows(newData, eos.gamedata.AlphaCloneSkill) - def convertTraits(data): + def processTraits(): + print('processing traits') + data = _readData('phobos', 'traits') def convertSection(sectionData): sectionLines = [] @@ -182,9 +297,16 @@ def update_db(): traitLine = '
\n
\n'.join(typeLines) newRow = {'typeID': typeId, 'traitText': traitLine} newData.append(newRow) - return newData - def fillReplacements(tables): + _addRows(newData, eos.gamedata.Traits) + + def processMetadata(): + print('processing metadata') + data = _readData('phobos', 'metadata') + _addRows(data, eos.gamedata.MetaData) + + def processReplacements(eveTypesData, eveGroupsData, dogmaTypeAttributesData, dogmaTypeEffectsData): + print('finding item replacements') def compareAttrs(attrs1, attrs2): # Consider items as different if they have no attrs @@ -196,7 +318,6 @@ def update_db(): return True return False - print('finding replacements') skillReqAttribs = { 182: 277, 183: 278, @@ -208,18 +329,18 @@ def update_db(): # Get data on type groups # Format: {type ID: group ID} typesGroups = {} - for row in tables['evetypes']: + for row in eveTypesData: typesGroups[row['typeID']] = row['groupID'] # Get data on item effects # Format: {type ID: set(effect, IDs)} typesEffects = {} - for row in tables['dogmatypeeffects']: + for row in dogmaTypeEffectsData: typesEffects.setdefault(row['typeID'], set()).add(row['effectID']) # Get data on type attributes # Format: {type ID: {attribute ID: attribute value}} typesNormalAttribs = {} typesSkillAttribs = {} - for row in tables['dogmatypeattributes']: + for row in dogmaTypeAttributesData: attributeID = row['attributeID'] if attributeID in skillReqAttribsFlat: typeSkillAttribs = typesSkillAttribs.setdefault(row['typeID'], {}) @@ -258,13 +379,13 @@ def update_db(): typeSkillReqs[skillType] = skillLevel # Format: {group ID: category ID} groupCategories = {} - for row in tables['evegroups']: + for row in eveGroupsData: groupCategories[row['groupID']] = row['categoryID'] # As EVE affects various types mostly depending on their group or skill requirements, # we're going to group various types up this way # Format: {(group ID, frozenset(skillreq, type, IDs), frozenset(type, effect, IDs): [type ID, {attribute ID: attribute value}]} groupedData = {} - for row in tables['evetypes']: + for row in eveTypesData: typeID = row['typeID'] # Ignore items outside of categories we need if groupCategories[typesGroups[typeID]] not in ( @@ -301,134 +422,25 @@ def update_db(): if compareAttrs(type1[1], type2[1]): replacements.setdefault(type1[0], set()).add(type2[0]) replacements.setdefault(type2[0], set()).add(type1[0]) - # Put this data into types table so that normal process hooks it up - for row in tables['evetypes']: - row['replacements'] = ','.join('{}'.format(tid) for tid in sorted(replacements.get(row['typeID'], ()))) + # Update DB session with data we generated + for item in eos.db.gamedata_session.query(eos.gamedata.Item).all(): + item.replacements = ','.join('{}'.format(tid) for tid in sorted(replacements.get(item.typeID, ()))) - data = {} - - # Dump all data to memory so we can easely cross check ignored rows - for jsonName, (minerName, cls) in tables.items(): - with open(os.path.join(JSON_DIR, minerName, '{}.json'.format(jsonName)), encoding='utf-8') as f: - tableData = json.load(f) - if jsonName in rowsInValues: - newTableData = [] - for k, v in tableData.items(): - row = {} - row.update(v) - if 'id' not in row: - row['id'] = int(k) - newTableData.append(row) - tableData = newTableData - if jsonName == 'icons': - tableData = convertIcons(tableData) - if jsonName == 'traits': - tableData = convertTraits(tableData) - if jsonName == 'clonegrades': - tableData = convertClones(tableData) - data[jsonName] = tableData - - fillReplacements(data) - - # Set with typeIDs which we will have in our database - # Sometimes CCP unpublishes some items we want to have published, we - # can do it here - just add them to initial set - eveTypes = set() - for row in data['evetypes']: - if ( - row['published'] or - row['typeName'] == 'Capsule' or - # group Ship Modifiers, for items like tactical t3 ship modes - row['groupID'] == 1306 or - # Civilian weapons - (row['typeName'].startswith('Civilian') and "Shuttle" not in row['typeName']) or - # Micro Bombs (Fighters) - row['typeID'] in (41549, 41548, 41551, 41550) or - # Abyssal weather (environment) - row['groupID'] in ( - 1882, - 1975, - 1971, - # the "container" for the abyssal environments - 1983) or - # Dark Blood Tracking Disruptor (drops, but rarely) - row['typeID'] == 32416 - ): - eveTypes.add(row['typeID']) - - # ignore checker - def isIgnored(file, row): - if file in ('evetypes', 'dogmatypeeffects', 'dogmatypeattributes') and row['typeID'] not in eveTypes: - return True - return False - - # Loop through each json file and write it away, checking ignored rows - for jsonName, table in data.items(): - fieldMap = fieldMapping.get(jsonName, {}) - tmp = [] - - print('processing {}'.format(jsonName)) - - for row in table: - # We don't care about some kind of rows, filter it out if so - if not isIgnored(jsonName, row): - if ( - jsonName == 'evetypes' and ( - # Apparently people really want Civilian modules available - (row['typeName'].startswith('Civilian') and "Shuttle" not in row['typeName']) or - row['typeName'] in ('Capsule', 'Dark Blood Tracking Disruptor')) - ): - row['published'] = True - - instance = tables[jsonName][1]() - # fix for issue 80 - if jsonName is 'icons' and 'res:/ui/texture/icons/' in str(row['iconFile']).lower(): - row['iconFile'] = row['iconFile'].lower().replace('res:/ui/texture/icons/', '').replace('.png', '') - # with res:/ui... references, it points to the actual icon file (including it's size variation of #_size_#) - # strip this info out and get the identifying info - split = row['iconFile'].split('_') - if len(split) == 3: - row['iconFile'] = '{}_{}'.format(split[0], split[2]) - if jsonName is 'icons' and 'modules/' in str(row['iconFile']).lower(): - row['iconFile'] = row['iconFile'].lower().replace('modules/', '').replace('.png', '') - - if jsonName is 'clonegrades': - if row['alphaCloneID'] not in tmp: - cloneParent = eos.gamedata.AlphaClone() - setattr(cloneParent, 'alphaCloneID', row['alphaCloneID']) - setattr(cloneParent, 'alphaCloneName', row['alphaCloneName']) - eos.db.gamedata_session.add(cloneParent) - tmp.append(row['alphaCloneID']) - - for k, v in row.items(): - if isinstance(v, str): - v = v.strip() - setattr(instance, fieldMap.get(k, k), v) - - eos.db.gamedata_session.add(instance) - - # quick and dirty hack to get this data in - with open(os.path.join(JSON_DIR, 'fsd_binary', 'dynamicitemattributes.json'), encoding='utf-8') as f: - bulkdata = json.load(f) - for mutaID, data in bulkdata.items(): - muta = eos.gamedata.DynamicItem() - muta.typeID = mutaID - muta.resultingTypeID = data['inputOutputMapping'][0]['resultingType'] - eos.db.gamedata_session.add(muta) - - for x in data['inputOutputMapping'][0]['applicableTypes']: - item = eos.gamedata.DynamicItemItem() - item.typeID = mutaID - item.applicableTypeID = x - eos.db.gamedata_session.add(item) - - for attrID, attrData in data['attributeIDs'].items(): - attr = eos.gamedata.DynamicItemAttribute() - attr.typeID = mutaID - attr.attributeID = attrID - attr.min = attrData['min'] - attr.max = attrData['max'] - eos.db.gamedata_session.add(attr) + eveTypesData = processEveTypes() + eveGroupsData = processEveGroups() + processEveCategories() + processDogmaAttributes() + dogmaTypeAttributesData = processDogmaTypeAttributes(eveTypesData) + processDynamicItemAttributes() + processDogmaEffects() + dogmaTypeEffectsData = processDogmaTypeEffects(eveTypesData) + processDogmaUnits() + processMarketGroups() + processMetaGroups() + processCloneGrades() + processTraits() + processMetadata() + processReplacements(eveTypesData, eveGroupsData, dogmaTypeAttributesData, dogmaTypeEffectsData) # Add schema version to prevent further updates metadata_schema_version = eos.gamedata.MetaData()