Beispiel #1
0
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
Beispiel #2
0
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_shrine = {}
    parsed_monster_pieces = []
    parsed_buildings = {}

    server_id_mapping = {
        None: None,
        1: Summoner.SERVER_GLOBAL,
        2: Summoner.SERVER_KOREA,
        3: Summoner.SERVER_JAPAN,
        4: Summoner.SERVER_CHINA,
        5: Summoner.SERVER_ASIA,
        6: Summoner.SERVER_EUROPE,
    }

    server_id = server_id_mapping[data.get('server_id', None)]

    # 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
    monster_shrine_info = data.get('unit_storage_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

    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()

        if building_instance.level != level:
            building_instance.level = level
            parsed_buildings[building_instance.pk] = {
                'obj': building_instance,
                'new': True,
            }
        else:
            parsed_buildings[building_instance.pk] = {
                'obj': building_instance,
                'new': False,
            }

    # Inventory - essences and summoning pieces
    if inventory_info:
        for item in inventory_info:
            # Essence Inventory
            if (item['item_master_type'] == GameItem.CATEGORY_ESSENCE or
                    item['item_master_type'] == GameItem.CATEGORY_CRAFT_STUFF
                    or item['item_master_type']
                    == GameItem.CATEGORY_MATERIAL_MONSTER
                    or item['item_master_type']
                    == GameItem.CATEGORY_ARTIFACT_CRAFT):
                parsed_inventory[
                    item['item_master_id']] = item['item_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:
                        has_changed = False
                        monster_piece, created = MonsterPiece.objects.get_or_create(
                            owner=owner,
                            monster=mon,
                            defaults={
                                'pieces': quantity,
                            })
                        if not created and monster_piece.pieces != quantity:
                            monster_piece.pieces = quantity
                            has_changed = True

                        parsed_monster_pieces.append({
                            'obj':
                            monster_piece,
                            'new':
                            has_changed or created,
                        })

    if monster_shrine_info:
        for item in monster_shrine_info:
            parsed_monster_shrine[item['unit_master_id']] = item['quantity']

    # Extract Rune Inventory (unequipped runes)
    if runes_info:
        for rune_data in runes_info:
            rune = parse_rune_data(rune_data, owner)
            if rune:
                parsed_runes[rune.pk] = 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:
            temp_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

        # Equipped runes and artifacts
        equipped_runes = unit_info.get('runes')
        equipped_artifacts = unit_info.get('artifacts', [])

        # 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()

        mon_runes = []
        for rune_data in equipped_runes:
            rune = parse_rune_data(rune_data, owner)
            if rune:
                parsed_runes[rune.pk] = rune
                mon_runes.append(rune)

        mon_artifacts = []
        for artifact_data in equipped_artifacts:
            artifact = parse_artifact_data(artifact_data, owner)
            if artifact:
                parsed_artifacts[artifact.pk] = artifact
                mon_artifacts.append(artifact)

        skills = unit_info.get('skills', [])
        temp_skill_1_level = skills[0][1] if len(skills) >= 1 else None
        temp_skill_2_level = skills[1][1] if len(skills) >= 2 else None
        temp_skill_3_level = skills[2][1] if len(skills) >= 3 else None
        temp_skill_4_level = skills[3][1] if len(skills) >= 4 else None

        mon.monster = temp_monster
        mon.stars = unit_info.get('class')
        mon.level = unit_info.get('unit_level')

        # 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

        if temp_skill_1_level:
            mon.skill_1_level = temp_skill_1_level
        if temp_skill_2_level:
            mon.skill_2_level = temp_skill_2_level
        if temp_skill_3_level:
            mon.skill_3_level = temp_skill_3_level
        if temp_skill_4_level:
            mon.skill_4_level = temp_skill_4_level

        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

        # 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[mon.pk] = {
            "obj": mon,
            "runes": mon_runes,
            "artifacts": mon_artifacts
        }

    # Extract grindstones/enchant gems
    if craft_info:
        for craft_data in craft_info:
            craft, has_changed_or_new = parse_rune_craft_data(
                craft_data, owner)
            if craft:
                if has_changed_or_new:
                    craft.owner = owner
                parsed_rune_crafts[craft.pk] = {
                    'obj': craft,
                    'new': has_changed_or_new
                }

    # Extract artifact inventory
    if artifact_info:
        for artifact_data in artifact_info:
            artifact = parse_artifact_data(artifact_data, owner)
            if artifact:
                parsed_artifacts[artifact.pk] = artifact

    if artifact_craft_info:
        for craft_data in artifact_craft_info:
            craft, has_changed_or_new = parse_artifact_craft_data(
                craft_data, owner)
            if craft:
                if has_changed_or_new:
                    craft.owner = owner
                parsed_artifact_crafts[craft.pk] = {
                    'obj': craft,
                    'new': has_changed_or_new,
                }

    import_results = {
        'wizard_id': wizard_id,
        'server_id': server_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,
        'monster_shrine': parsed_monster_shrine,
        'buildings': parsed_buildings,
        'rta_assignments': data['world_arena_rune_equip_list'],
        'rta_assignments_artifacts': data['world_arena_artifact_equip_list'],
    }

    return import_results