def parse_sw_json(data, owner, options): wizard_id = None parsed_runes = [] parsed_rune_crafts = [] parsed_artifacts = [] parsed_artifact_crafts = [] parsed_mons = [] parsed_inventory = {} parsed_monster_pieces = [] parsed_buildings = [] # Grab the friend if data.get('command') == 'VisitFriend': data = data['friend'] if 'wizard_info' in data: wizard_id = data['wizard_info'].get('wizard_id') building_list = data['building_list'] deco_list = data['deco_list'] inventory_info = data.get('inventory_info') # Optional unit_list = data['unit_list'] runes_info = data.get('runes') # Optional locked_mons = data.get('unit_lock_list') # Optional craft_info = data.get('rune_craft_item_list') # Optional artifact_info = data.get('artifacts') # Optional artifact_craft_info = data.get('artifact_crafts') # Optional # Buildings storage_building_id = None for building in building_list: if building: # Find which one is the storage building if building.get('building_master_id') == 25: storage_building_id = building.get('building_id') break for deco in deco_list: try: base_building = Building.objects.get(com2us_id=deco['master_id']) except Building.DoesNotExist: continue level = deco['level'] try: building_instance = BuildingInstance.objects.get( owner=owner, building=base_building) except BuildingInstance.DoesNotExist: building_instance = BuildingInstance(owner=owner, building=base_building) except BuildingInstance.MultipleObjectsReturned: # Should only be 1 ever - use the first and delete the others. building_instance = BuildingInstance.objects.filter( owner=owner, building=base_building).first() BuildingInstance.objects.filter( owner=owner, building=base_building).exclude( pk=building_instance.pk).delete() building_instance.level = level parsed_buildings.append(building_instance) # Inventory - essences and summoning pieces if inventory_info: for item in inventory_info: # Essence Inventory if item['item_master_type'] == GameItem.CATEGORY_ESSENCE: essence = inventory_essence_map.get(item['item_master_id']) quantity = item.get('item_quantity') if essence and quantity: parsed_inventory[essence] = quantity elif item['item_master_type'] == GameItem.CATEGORY_CRAFT_STUFF: craft = inventory_craft_map.get(item['item_master_id']) quantity = item.get('item_quantity') if craft and quantity: parsed_inventory[craft] = quantity elif item['item_master_type'] == GameItem.CATEGORY_MONSTER_PIECE: quantity = item.get('item_quantity') if quantity > 0: mon = get_monster_from_id(item['item_master_id']) if mon: parsed_monster_pieces.append( MonsterPiece( monster=mon, pieces=quantity, owner=owner, )) elif item[ 'item_master_type'] == GameItem.CATEGORY_MATERIAL_MONSTER: monster = inventory_enhance_monster_map.get( item['item_master_id']) quantity = item.get('item_quantity') if monster and quantity: parsed_inventory[monster] = quantity elif item['item_master_type'] == GameItem.CATEGORY_ARTIFACT_CRAFT: quantity = item.get('item_quantity') if quantity: parsed_inventory['conversion_stone'] = quantity # Extract Rune Inventory (unequipped runes) if runes_info: for rune_data in runes_info: rune = parse_rune_data(rune_data, owner) if rune: rune.owner = owner rune.assigned_to = None parsed_runes.append(rune) # Extract monsters for unit_info in unit_list: # Get base monster type com2us_id = unit_info.get('unit_id') monster_type_id = str(unit_info.get('unit_master_id')) mon = None if not options['clear_profile']: mon = MonsterInstance.objects.filter(com2us_id=com2us_id, owner=owner).first() if not mon: mon = MonsterInstance() is_new = True else: is_new = False mon.com2us_id = com2us_id # Base monster try: mon.monster = Monster.objects.get(com2us_id=monster_type_id) except Monster.DoesNotExist: # Unable to find a matching monster in the database - either crap data or brand new monster. Don't parse it. continue mon.stars = unit_info.get('class') mon.level = unit_info.get('unit_level') skills = unit_info.get('skills', []) if len(skills) >= 1: mon.skill_1_level = skills[0][1] if len(skills) >= 2: mon.skill_2_level = skills[1][1] if len(skills) >= 3: mon.skill_3_level = skills[2][1] if len(skills) >= 4: mon.skill_4_level = skills[3][1] try: created_date = get_current_timezone().localize(parse( unit_info.get('create_time')), is_dst=False) mon.created = created_date except (ValueError, TypeError): mon.created = None mon.owner = owner mon.in_storage = unit_info.get('building_id') == storage_building_id # Set priority levels if options['default_priority'] and is_new: mon.priority = options['default_priority'] if mon.monster.archetype == Monster.ARCHETYPE_MATERIAL: mon.fodder = True mon.priority = MonsterInstance.PRIORITY_DONE # Lock a monster if it's locked in game if options['lock_monsters']: mon.ignore_for_fusion = locked_mons is not None and mon.com2us_id in locked_mons # Equipped runes and artifacts equipped_runes = unit_info.get('runes') equipped_artifacts = unit_info.get('artifacts', []) # Check import options to determine if monster should be saved level_ignored = mon.stars < options['minimum_stars'] silver_ignored = options['ignore_silver'] and not mon.monster.can_awaken material_ignored = options[ 'ignore_material'] and mon.monster.archetype == Monster.ARCHETYPE_MATERIAL allow_due_to_runes = options['except_with_runes'] and ( len(equipped_runes) > 0 or len(equipped_artifacts) > 0) allow_due_to_ld = options[ 'except_light_and_dark'] and mon.monster.element in [ Monster.ELEMENT_DARK, Monster.ELEMENT_LIGHT ] and mon.monster.archetype != Monster.ARCHETYPE_MATERIAL allow_due_to_fusion = options[ 'except_fusion_ingredient'] and mon.monster.fusion_food should_be_skipped = any( [level_ignored, silver_ignored, material_ignored]) import_anyway = any( [allow_due_to_runes, allow_due_to_ld, allow_due_to_fusion]) if should_be_skipped and not import_anyway: continue # Set custom name if homunculus custom_name = unit_info.get('homunculus_name') if unit_info.get('homunculus') and custom_name: mon.custom_name = custom_name parsed_mons.append(mon) # Sometimes the runes are a dict or a list in the json. Convert to list. if isinstance(equipped_runes, dict): equipped_runes = equipped_runes.values() for rune_data in equipped_runes: rune = parse_rune_data(rune_data, owner) if rune: rune.owner = owner rune.assigned_to = mon parsed_runes.append(rune) for artifact_data in equipped_artifacts: artifact = parse_artifact_data(artifact_data, owner) if artifact: artifact.owner = owner artifact.assigned_to = mon parsed_artifacts.append(artifact) # Extract grindstones/enchant gems if craft_info: for craft_data in craft_info: craft = parse_rune_craft_data(craft_data, owner) if craft: craft.owner = owner parsed_rune_crafts.append(craft) # Extract artifact inventory if artifact_info: for artifact_data in artifact_info: artifact = parse_artifact_data(artifact_data, owner) if artifact: artifact.owner = owner artifact.assigned_to = None parsed_artifacts.append(artifact) if artifact_craft_info: for craft_data in artifact_craft_info: craft = parse_artifact_craft_data(craft_data, owner) if craft: craft.owner = owner parsed_artifact_crafts.append(craft) import_results = { 'wizard_id': wizard_id, 'monsters': parsed_mons, 'monster_pieces': parsed_monster_pieces, 'runes': parsed_runes, 'rune_crafts': parsed_rune_crafts, 'artifacts': parsed_artifacts, 'artifact_crafts': parsed_artifact_crafts, 'inventory': parsed_inventory, 'buildings': parsed_buildings, 'rta_assignments': data['world_arena_rune_equip_list'] } return import_results
def parse_sw_json(data, owner, options): errors = [] wizard_id = None parsed_runes = [] parsed_rune_crafts = [] parsed_mons = [] parsed_inventory = {} parsed_monster_pieces = [] # Grab the friend if data.get('command') == 'VisitFriend': data = data['friend'] if 'wizard_info' in data: wizard_id = data['wizard_info'].get('wizard_id') building_list = data['building_list'] inventory_info = data.get('inventory_info') # Optional unit_list = data['unit_list'] runes_info = data.get('runes') # Optional locked_mons = data.get('unit_lock_list') # Optional craft_info = data.get('rune_craft_item_list') # Optional # Buildings storage_building_id = None for building in building_list: if building: # Find which one is the storage building if building.get('building_master_id') == 25: storage_building_id = building.get('building_id') break # Inventory - essences and summoning pieces if inventory_info: for item in inventory_info: # Essence Inventory if item['item_master_type'] == inventory_type_map['essences']: essence = inventory_essence_map.get(item['item_master_id']) quantity = item.get('item_quantity') if essence and quantity: parsed_inventory[essence] = quantity elif item['item_master_type'] == inventory_type_map['craft_stuff']: craft = inventory_craft_map.get(item['item_master_id']) quantity = item.get('item_quantity') if craft and quantity: parsed_inventory[craft] = quantity elif item['item_master_type'] == inventory_type_map['monster_piece']: quantity = item.get('item_quantity') if quantity > 0: try: mon = get_monster_from_id(item['item_master_id']) except ValueError as e: errors.append(e.message) else: if mon: parsed_monster_pieces.append(MonsterPiece( monster=mon, pieces=quantity, owner=owner, uncommitted=True, )) # Extract Rune Inventory (unequipped runes) if runes_info: for rune_data in runes_info: rune = parse_rune_data(rune_data, owner) if rune: rune.owner = owner rune.assigned_to = None parsed_runes.append(rune) else: errors.append('Unable to parse rune in inventory with this data: ' + str(rune_data)) # Extract monsters for unit_info in unit_list: # Get base monster type com2us_id = unit_info.get('unit_id') monster_type_id = str(unit_info.get('unit_master_id')) mon = None if not options['clear_profile']: mon = MonsterInstance.objects.filter(com2us_id=com2us_id, owner=owner).first() if not mon: mon = MonsterInstance() is_new = True else: is_new = False # Make sure it's saved as a new instance and marked as an import mon.pk = None mon.uncommitted = True mon.com2us_id = com2us_id # Base monster try: mon.monster = Monster.objects.get(com2us_id=monster_type_id) except Monster.DoesNotExist: errors.append('Unable to parse monster data. Monster type: ' + str(unit_info.get('unit_master_id')) + '. Monster ID: ' + str(unit_info.get('unit_id'))) continue mon.stars = unit_info.get('class') mon.level = unit_info.get('unit_level') skills = unit_info.get('skills', []) if len(skills) >= 1: mon.skill_1_level = skills[0][1] if len(skills) >= 2: mon.skill_2_level = skills[1][1] if len(skills) >= 3: mon.skill_3_level = skills[2][1] if len(skills) >= 4: mon.skill_4_level = skills[3][1] try: created_date = get_current_timezone().localize(parse(unit_info.get('create_time')), is_dst=False) mon.created = created_date except (ValueError, TypeError): mon.created = None mon.owner = owner mon.in_storage = unit_info.get('building_id') == storage_building_id # Set priority levels if options['default_priority'] and is_new: mon.priority = options['default_priority'] if mon.monster.archetype == Monster.TYPE_MATERIAL: mon.fodder = True mon.priority = MonsterInstance.PRIORITY_DONE # Lock a monster if it's locked in game mon.ignore_for_fusion = locked_mons and mon.com2us_id in locked_mons # Equipped runes equipped_runes = unit_info.get('runes') # Check import options to determine if monster should be saved level_ignored = mon.stars < options['minimum_stars'] silver_ignored = options['ignore_silver'] and not mon.monster.can_awaken material_ignored = options['ignore_material'] and mon.monster.archetype == Monster.TYPE_MATERIAL allow_due_to_runes = options['except_with_runes'] and len(equipped_runes) > 0 allow_due_to_ld = options['except_light_and_dark'] and mon.monster.element in [Monster.ELEMENT_DARK, Monster.ELEMENT_LIGHT] and mon.monster.archetype != Monster.TYPE_MATERIAL if (level_ignored or silver_ignored or material_ignored) and not (allow_due_to_runes or allow_due_to_ld): continue parsed_mons.append(mon) # Sometimes the runes are a dict or a list in the json. Convert to list. if isinstance(equipped_runes, dict): equipped_runes = equipped_runes.values() for rune_data in equipped_runes: rune = parse_rune_data(rune_data, owner) if rune: rune.owner = owner rune.assigned_to = mon parsed_runes.append(rune) else: errors.append('Unable to parse rune assigned to ' + str(mon)) # Extract grindstones/enchant gems if craft_info: for craft_data in craft_info: craft = parse_rune_craft_data(craft_data, owner) if craft: craft.owner = owner parsed_rune_crafts.append(craft) else: errors.append('Unable to parse gem/grindstone in inventory with this data: ' + str(craft_data)) import_results = { 'errors': errors, 'wizard_id': wizard_id, 'monsters': parsed_mons, 'monster_pieces': parsed_monster_pieces, 'runes': parsed_runes, 'crafts': parsed_rune_crafts, 'inventory': parsed_inventory, } return import_results