예제 #1
0
def obtainReward(clearReward, args):
    presentType = clearReward['presentType']
    quantity = clearReward['quantity']
    if presentType == 'DOPPEL':
        userDoppel, exists = newtil.createUserDoppel(clearReward['genericId'])
        if not exists:
            dt.setUserObject('userDoppelList', clearReward['genericId'],
                             userDoppel)
        args['userDoppelList'] = args.get('userDoppelList', []) + [userDoppel]
    elif presentType == 'GEM':  # only Iroha's gems are rewards, so no need to check missing chara
        userChara = dt.getUserObject('userCharaList', clearReward['genericId'])
        userChara['lbItemNum'] += quantity
        dt.setUserObject('userCharaList', clearReward['genericId'], userChara)
        args['userCharaList'] = args.get('userCharaList', []) + [userChara]
    elif presentType == 'ITEM':
        userItem = dt.getUserObject('userItemList', clearReward['itemId'])
        userItem['quantity'] += quantity
        dt.setUserObject('userItemList', clearReward['itemId'], userItem)
        args['userItemList'] = args.get('userItemList', []) + [userItem]
    elif presentType == 'LIVE2D':
        newLive2d, exists = newtil.createUserLive2d(clearReward['genericId'],
                                                    clearReward['genericCode'],
                                                    clearReward['displayName'])
        if not exists:
            userLive2dList = dt.readJson('data/user/userLive2dList.json')
            dt.saveJson('data/user/userLive2dList.json',
                        userLive2dList + [newLive2d])
        args['userLive2dList'] = args.get('userLive2dList', []) + [newLive2d]
    elif presentType == 'PIECE':
        args['userPieceList'] = args.get('userPieceList', [])
        for _ in range(quantity):
            newPiece = newtil.createUserMemoria(clearReward['genericId'])
            args['userPieceList'].append(newPiece)
            dt.setUserObject('userPieceList', newPiece['id'], newPiece)
    return args
예제 #2
0
def save():
    body = flask.request.json

    # sometimes, when you continue to edit a team, the deckType isn't sent at all,
    # so we have to store it
    # not sure if the request ever doesn't have a deckType on the first time you edit a team
    if 'deckType' in body:
        deckType = body['deckType']
        dt.saveJson('data/user/deckType.json',{'deckType': body['deckType']})
    else:
        deckType = dt.readJson('data/user/deckType.json')['deckType']

    userDeck = dt.getUserObject('userDeckList', deckType)
    if userDeck is None:
        userDeck = {'createdAt': nowstr(), 'userId': dt.userId, 'deckType': deckType}
    
    userDeck['name'] = body['name']
    
    if 'questPositionHelper' in body.keys():
        userDeck['questPositionHelper'] = body['questPositionHelper']
    if 'episodeUserCardId' in body.keys():
        userDeck['questEpisodeUserCardId'] = body['episodeUserCardId']
    if 'formationSheetId' in body.keys():
        userDeck['formationSheetId'] = body['formationSheetId']
        
    userFormation = dt.getUserObject('userFormationSheetList', body['formationSheetId'])
    if userFormation is None:
        flask.abort(400, description='{"errorTxt": "Trying to use a nonexistent formation","resultCode": "error","title": "Error"}')

    userDeck['formationSheet'] = userFormation['formationSheet']

    keys = set(userDeck.keys())
    for key in keys:
        if key.startswith('questPositionId') or key.startswith('userCardId') or key.startswith('userPieceId'):
            del userDeck[key]        

    for i, positionId in enumerate(body['questPositionIds']):
        userDeck['questPositionId'+str(i+1)] = positionId
    
    for i, cardId in enumerate(body['userCardIds']):
        userDeck['userCardId'+str(i+1)] = cardId

    for i, pieceIdList in enumerate(body['userPieceIdLists']):
        numSlots = dt.getUserObject('userCardList', userDeck['userCardId'+str(i+1)])['revision'] + 1
        numMemoriaAssigned = 0
        for j, pieceId in enumerate(pieceIdList):
            userDeck['userPieceId0'+str(i+1)+str(j+1)] = pieceId
            numMemoriaAssigned += 1
            if numMemoriaAssigned >= numSlots:
                break

    dt.setUserObject('userDeckList', deckType, userDeck)
    gameUser = dt.setGameUserValue('deckType', deckType)
    
    return flask.jsonify({
        'resultCode': 'success',
        'userDeckList': [userDeck],
        'gameUser': gameUser
    })
예제 #3
0
def resetShop():
    today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
    lastMonth = today.month - 1
    skipTypes = ['PIECE', 'MAXPIECE', 'FORMATION_SHEET',
                 'CARD']  # afaik these don't need to be reset...

    shopList = dt.readJson('data/shopList.json')

    # figure out if it needs to be reset (end date is prior to today), then reset it
    # kinda hacky way to get the last time the shop was reset
    # finds the first limited (and available) item in the mirrors coins shop, then takes its end time
    # reverse order because limited items are at the bottom of the shopItempList.
    for shopItem in reversed(shopList[1]['shopItemList']):
        if 'endAt' in shopItem:
            shopExpiryTime = shopItem['endAt']
            if shopExpiryTime != "2050/01/01 00:00:00":
                break

    if not beforeToday(shopExpiryTime):
        return

    for shopIdx in range(
            4):  # magia chips, mirrors coins, support pts, daily coins
        shopItems = shopList[shopIdx]['shopItemList']
        deleteIdxs = [
            i for i in range(len(shopItems))
            if 'endAt' in shopItems[i] and beforeToday(shopItems[i]['endAt'])
            and not shopItems[i]['shopItemType'] in skipTypes
        ]
        for i in reversed(deleteIdxs):
            del shopItems[i]

        # from Stack Overflow
        endOfMonth = today.replace(day=28) + timedelta(days=4)
        endOfMonth = ((endOfMonth - timedelta(days=endOfMonth.day)).replace(
            hour=23, minute=59, second=59)).strftime(DATE_FORMAT)
        newItems = []

        alreadyCopied = set([])
        for item in shopItems:
            if 'endAt' not in item \
                or item['endAt']!= "2050/01/01 00:00:00" \
                or item['shopItemType'] in skipTypes \
                or item['genericId'] in alreadyCopied:
                continue
            alreadyCopied.add(item['genericId'])
            newItem = copy.deepcopy(item)
            newItem['startAt'] = today.strftime(DATE_FORMAT)
            newItem['endAt'] = endOfMonth

            newItems.append(newItem)

            # also need to clear out the user's history
            dt.deleteUserObject('userShopItemList', newItem['id'])

        shopList[shopIdx]['shopItemList'] += newItems

    dt.saveJson('data/shopList.json', shopList)
예제 #4
0
def addMissingLive2d():
    existingCharas = dt.listUserObjectKeys('userCharaList')
    newLive2ds = []
    
    for charaId in existingCharas:
        newLive2d, exists = newtil.createUserLive2d(charaId, '00', 'Magical Girl')
        if not exists:
                newLive2ds.append(newLive2d)
                
    live2dPath = 'data/user/userLive2dList.json'  
    dt.saveJson(live2dPath, dt.readJson(live2dPath) + newLive2ds)
예제 #5
0
def addDuoLive2d():
    existingCharas = dt.listUserObjectKeys('userCharaList')
    duos = [1301, 1118, 3501] # IroYachi, Swimnees, RikaRen
    duos = [duo for duo in duos if duo in existingCharas]

    newLive2ds = []
    for duo in duos:
        name = dt.masterCards[duo]['chara']['name']
        if '&' in name:
            names = ['Magical Girl (' + singleName + ')' for singleName in name.split(' & ')]
        else:
            names = ['']*2

        for costume in range(1, 3):
            newLive2d, exists = newtil.createUserLive2d(duo, '0' + str(costume), names[costume-1])
            if not exists:
                newLive2ds.append(newLive2d)

    live2dPath = 'data/user/userLive2dList.json'
    dt.saveJson(live2dPath, dt.readJson(live2dPath) + newLive2ds)
예제 #6
0
def addMissingMss():
    allSectionIds = dt.masterSections.keys()
    userSectionIds = dt.listUserObjectKeys('userSectionList')
    userCharaIds = dt.listUserObjectKeys('userCharaList') # don't need to dedupe because this already is a set
    missingMSSections = [sectionId for sectionId in allSectionIds if not sectionId in userSectionIds and str(sectionId).startswith('3')]
    addSections = [sectionId for sectionId in missingMSSections if int(str(sectionId)[1:5]) in userCharaIds]
    userSectionList = dt.readJson('data/user/userSectionList.json')
    for sectionId in addSections:
        userSection, _ = newtil.createUserSection(sectionId)
        userSectionList.append(userSection)
    dt.saveJson('data/user/userSectionList.json', userSectionList)

    allBattleIds = dt.masterBattles.keys()
    userBattleIds = dt.listUserObjectKeys('userQuestBattleList')
    missingMSSBattles = [battleId for battleId in allBattleIds if not battleId in userBattleIds and str(battleId).startswith('3')]
    addBattles = [battleId for battleId in missingMSSBattles if int(str(battleId)[1:5]) in userCharaIds]
    userQuestBattleList = dt.readJson('data/user/userQuestBattleList.json')
    for battleId in addBattles:
        userBattle, _ = newtil.createUserQuestBattle(battleId)
        userQuestBattleList.append(userBattle)
    dt.saveJson('data/user/userQuestBattleList.json', userQuestBattleList)
예제 #7
0
def progressMirrors(response):
    currPoints = response['userArenaBattle']['freeRankArenaPoint']
    # if it's the last available layer
    if currPoints >= dt.arenaClassList[1]['requiredPoint']:
        response['userArenaBattle']['freeRankArenaPoint'] = dt.arenaClassList[
            1]['requiredPoint']
        dt.saveJson('data/user/userArenaBattle.json',
                    response['userArenaBattle'])
        return response

    # find which layer you're on with the given points
    arenaClassIdx = -1
    for i, arenaClass in enumerate(dt.arenaClassList[1:]):
        if currPoints >= arenaClass['requiredPoint']:
            arenaClassIdx = i
            break
    if arenaClassIdx == -1:
        arenaClassIdx = len(dt.arenaClassList) - 1

    # if it's not the same layer as what's in the user's data, go to the next layer
    if dt.arenaClassList[arenaClassIdx]['arenaBattleFreeRankClass'] != response[
            'userArenaBattle']['currentFreeRankClassType']:
        response['userArenaBattle'][
            'currentFreeRankClassType'] = dt.arenaClassList[arenaClassIdx][
                'arenaBattleFreeRankClass']
        response['userArenaBattle']['currentFreeRankClass'] = response[
            'userArenaBattle']['nextFreeRankClass']

        # set the 'nextClass' key if the new layer isn't the last, delete if it is
        if 'nextClass' in dt.arenaClassList[arenaClassIdx]:
            response['userArenaBattle'][
                'nextFreeRankClass'] = dt.arenaClassList[arenaClassIdx - 1]
        elif 'nextFreeRankClass' in response['userArenaBattle']:
            del response['userArenaBattle']['nextFreeRankClass']

        response = obtainReward(
            dt.arenaClassList[arenaClassIdx]['bonusRewardList'][0], response)

    dt.saveJson('data/user/userArenaBattle.json', response['userArenaBattle'])
    return response
예제 #8
0
def addMeguca(charaId):
    userChara = dt.getUserObject('userCharaList', charaId)
    foundExisting = userChara is not None

    live2ds = []
    if not foundExisting:
        userCard, userChara, userLive2d = newtil.createUserMeguca(charaId)
        dt.setUserObject('userCardList', userCard['id'], userCard)
        dt.setUserObject('userCharaList', charaId, userChara)
        live2ds += [userLive2d]

        if 'doubleUnitFlg' in userChara['chara'] and userChara['chara']['doubleUnitFlg']:
            live2ds += addDuoLive2d(userChara['chara'])
        live2dPath = 'data/user/userLive2dList.json'
        dt.saveJson(live2dPath, dt.readJson(live2dPath) + live2ds)
    else:
        userChara['lbItemNum'] += 1
        dt.setUserObject('userCharaList', charaId, userChara)

        userCard = dt.getUserObject('userCardList', userChara['userCardId'])
        userLive2d = dt.getUserObject('userLive2dList', int(str(charaId)+'00'))
        live2ds = [userLive2d]

    return userCard, userChara, live2ds, foundExisting
예제 #9
0
def resetDaily():
    path = 'data/user/userDailyChallengeList.json'
    userDailyChallenges = dt.readJson(path)
    for challenge in userDailyChallenges:
        challenge['clearedCount'] = 0
    dt.saveJson(path, userDailyChallenges)
예제 #10
0
def get():
    body = flask.request.json
    battle = dt.readJson('data/user/userQuestBattleResult.json')
    isMirrors = battle['battleType'] == "ARENA"

    if isMirrors:
        arenaBattle = dt.readJson('data/user/userArenaBattleResult.json')
        if not arenaBattle['userQuestBattleResultId'] == battle['id']:
            flask.abort(
                500,
                description=
                '{"errorTxt": "Something weird happened with order of battles","resultCode": "error","title": "Error"}'
            )

    if not battle['id'] == body['userQuestBattleResultId']:
        flask.abort(
            400,
            description=
            '{"errorTxt": "You didn\'t really start this quest, or something...","resultCode": "error","title": "Error"}'
        )

    # grab team info
    deck = dt.getUserObject('userDeckList', battle['deckType'])
    battleData = {
        'playerList': [],
        'artList': [],
        'magiaList': [],
        'connectList': [],
        'doppelList': [],
        'memoria': []
    }
    for key in battle.keys():
        if key.startswith('userCardId'):
            addUserToBattle(battleData, int(key[-1]), deck)

    # do the same, but now for the helper
    # TODO: use actual support
    if not isMirrors:
        npcs = dt.readJson('data/npc.json')
        helper = None
        for npc in npcs:
            if npc['npcHelpId'] == battle['npcHelpId']:
                helper = npc
        helperCard = helper['userCardList'][0]
        helperChara = helper['userCharaList'][0]
        helperPieces = helper['userPieceList']

        helperMemoriae = battleTranslate(battleData, helperCard, helperPieces)

        battleInfo = {
            'helper': True,
            'friend': True,  # TODO: actually change this
            'pos': deck['questPositionHelper'],
            'leader': False,
            'memoriaList': helperMemoriae
        }
        battleData['playerList'].append(
            cardToPlayer(helperCard, helperChara, battleInfo))

        # add support points
        supportPoints = dt.getUserObject('userItemList', 'YELL')
        supportPoints['quantity'] += 60
        dt.setUserObject('userItemList', 'YELL', supportPoints)

    # spend AP/BP
    apStatus = spendAP(battle)

    # change quest status
    battle['questBattleStatus'] = 'LOTTERY'
    dt.saveJson('data/user/userQuestBattleResult.json', battle)

    # TODO: use follower
    userFollowList = []

    # set last used team
    gameUser = dt.setGameUserValue('deckType', battle['deckType'])

    # compile web data
    webData = {
        "gameUser": gameUser,
        "userStatusList": [apStatus],
        "userQuestBattleResultList": [battle],
        "resultCode": "success",
        "userFollowList": userFollowList,
    }
    if not isMirrors:
        webData["userItemList"] = [supportPoints]

    # add opponent stuff
    if not isMirrors:
        if battle['questBattleId'] in dt.masterWaves:
            waves = getQuestData(battle['questBattleId'], battleData)
        else:
            waves = [dt.readJson('data/hardCodedWave.json')]
    else:
        opponent = dt.readJson('data/arenaEnemies/' +
                               arenaBattle['opponentUserId'] + '.json')
        waves = [{
            "field": 21181,
            "boss": False,
            "sheetType": 9,
            "enemyList": opponent['enemyList']
        }]
        # this is a mess lol, only the arts from the memoria are in artList
        battleData['memoria'] += opponent['memoriaList']
        battleData['artList'] += opponent['artList']

        # the rest have to be extracted from the cards
        for enemyCard in opponent['opponentUserArenaBattleInfo'][
                'userCardList']:
            battleTranslate(battleData, enemyCard, [])

    response = {
        'battleType': 'QUEST' if not isMirrors else
        'ARENA',  # TODO: change for tutorials, challenge quests
        'scenario': mirrorScenario if isMirrors else battle['scenario'],
        'waveList': waves,
        'playerList': battleData['playerList'],
        'doppelList': dedupeDictList(battleData['doppelList'], 'doppelId'),
        'artList': dedupeDictList(battleData['artList'], 'artId'),
        'memoriaList': dedupeDictList(battleData['memoria'], 'memoriaId'),
        'connectList': dedupeDictList(battleData['connectList'], 'connectId'),
        'magiaList': dedupeDictList(battleData['magiaList'], 'magiaId'),
        'continuable': True,
        'isHalfSkill': False,
        'webData': webData
    }
    return flask.jsonify(response)
예제 #11
0
def dropItems(battleId, waveList):
    # get list of enemyLists in waveList, then flatten
    flatEnemies = [
        enemy for enemyList in [wave['enemyList'] for wave in waveList]
        for enemy in enemyList
    ]
    uniqueEnemyIds = {enemy['charId'] for enemy in flatEnemies}
    enemyCounts = {
        enemyId:
        len([enemy for enemy in flatEnemies if enemy['charId'] == enemyId])
        for enemyId in uniqueEnemyIds
    }
    enemyIdxs = {}
    for i, wave in enumerate(waveList):
        enemyList = wave['enemyList']
        for j, enemy in enumerate(enemyList):
            enemyId = enemy['charId']
            enemyIdxs[enemyId] = enemyIdxs.get(enemyId, []) + [(i, j)]

    battle = dt.masterBattles[battleId]
    possibleDropCodes = {}
    for key in battle.keys():
        if dropItemPattern.fullmatch(key):
            possibleDropCodes[battle[key]['dropItemId']] = [
                v for k, v in battle[key].items() if k.startswith('rewardCode')
            ]

    # TODO: change rates to what they really are...
    dropRates = {drop: 2 for drop in possibleDropCodes}
    promisedDrops = {'questBattleId': battleId}

    # handle items that can only be dropped by particular enemies
    # get list of who can drop
    dropsToEnemies = {
        int(k): v
        for k, v in dt.readJson('data/enemyDrops.json').items()
    }
    extractGiftCode = lambda x: int(x.split('_')[1])
    # this can't handle dropItemIds that have both gifts and items as dropCodes, but maybe we don't need to
    possibleDropToEnemyIds = {}
    for dropItemId, dropCodes in possibleDropCodes.items():
        enemies = []
        for dropCode in dropCodes:
            if not dropCode.startswith('GIFT') or not extractGiftCode(
                    dropCode) in dropsToEnemies:
                enemies = []
                break
            for enemyId in dropsToEnemies[extractGiftCode(dropCode)]:
                if enemyId in uniqueEnemyIds:
                    enemies.append(enemyId)
        if not len(enemies) == 0:
            possibleDropToEnemyIds[dropItemId] = enemies

    boxTypes = [None, 'BRONZE', 'SILVER', 'GOLD']
    availableIdxs = [
        enemyIdx for _, enemyIdxList in enemyIdxs.items()
        for enemyIdx in enemyIdxList
    ]
    for dropId, enemyIds in possibleDropToEnemyIds.items():
        numDroppers = sum([enemyCounts[enemyId] for enemyId in enemyIds])
        if numDroppers == 0: continue

        conditionalRate = min(1, dropRates[dropId] / numDroppers)
        for enemyId in enemyIds:
            if len(enemyIdxs[enemyId]) == 0:
                continue

            numDrops = np.random.binomial(enemyCounts[enemyId],
                                          conditionalRate)
            idxs = np.random.choice(len(enemyIdxs[enemyId]),
                                    numDrops,
                                    replace=False)
            removeIdxs = []
            for enemyIdx in idxs:
                giftId = extractGiftCode(
                    np.random.choice(possibleDropCodes[dropId], 1)[0])
                rarity = dt.masterGifts[giftId]['rank']

                waveNo, idx = enemyIdxs[enemyId][enemyIdx]
                # this is going to change waveList, actually, because this list was created using references
                waveList[waveNo]['enemyList'][idx][
                    'dropItemType'] = 'BOX_' + boxTypes[rarity]
                promisedDrops['GIFT_' + str(giftId) +
                              '_1'] = promisedDrops.get(
                                  'GIFT_' + str(giftId) + '_1', 0) + 1
                removeIdxs.append((waveNo, idx))
                availableIdxs.remove((waveNo, idx))
            for removeIdx in removeIdxs:
                enemyIdxs[enemyId].remove(removeIdx)

    # handle drops that can be dropped by anyone
    for dropItemId, codes in possibleDropCodes.items():
        numEnemies = len(availableIdxs)
        if numEnemies == 0: continue

        conditionalRate = min(1, dropRates[dropItemId] / numEnemies)
        numDrops = np.random.binomial(numEnemies, conditionalRate)
        idxs = np.random.choice(len(availableIdxs), numDrops, replace=False)
        removeIdxs = []
        for availableIdx in idxs:
            code = np.random.choice(codes, 1)[0]
            if code.startswith('RICHE'):
                rarityBox = 'BOX_BRONZE'
            elif code.startswith('ITEM'):
                itemId = '_'.join(code.split('_')[1:-1])
                rarityBox = 'BOX_' + dt.masterItems[itemId][
                    'treasureChestColor']
            elif code.startswith('GIFT'):
                giftId = extractGiftCode(code)
                rarityBox = 'BOX_' + boxTypes[dt.masterGifts[giftId]['rank']]
                if extractGiftCode(code) in possibleDropToEnemyIds:
                    continue

            waveNo, enemyIdx = availableIdxs[availableIdx]
            waveList[waveNo]['enemyList'][enemyIdx]['dropItemType'] = rarityBox
            promisedDrops[code] = promisedDrops.get(code, 0) + 1
            removeIdxs.append((waveNo, enemyIdx))
        for removeIdx in removeIdxs:
            availableIdxs.remove(removeIdx)

    # first clear reward
    userQuestBattle = dt.getUserObject('userQuestBattleList', battleId)
    if 'cleared' not in userQuestBattle or not userQuestBattle[
            'cleared'] and 'firstClearRewardCodes' in battle:
        code = battle['firstClearRewardCodes']
        if code.startswith('RICHE'):
            rarityBox = 'BOX_BRONZE'
        elif code.startswith('ITEM'):
            itemId = '_'.join(code.split('_')[1:-1])
            rarityBox = 'BOX_' + dt.masterItems[itemId]['treasureChestColor']
        elif code.startswith('GIFT'):
            giftId = extractGiftCode(code)
            rarityBox = 'BOX_' + boxTypes[dt.masterGifts[giftId]['rank']]

        if len(availableIdxs) != 0:
            waveNo, enemyIdx = availableIdxs[np.random.choice(
                len(availableIdxs), 1)[0]]
            waveList[waveNo]['enemyList'][enemyIdx]['dropItemType'] = rarityBox
        promisedDrops[code] = promisedDrops.get(code, 0) + 1

    dt.saveJson('data/user/promisedDrops.json', promisedDrops)
    return waveList
예제 #12
0
def draw():
    # handle different types of gachas
    body = flask.request.json

    chosenGacha = None
    for gacha in dt.readJson('data/gachaScheduleList.json'):
        if gacha['id'] == body['gachaScheduleId']:
            chosenGacha = gacha
            break
    if chosenGacha is None:
        flask.abort(404, description="Tried to pull on a gacha that doesn't exist...")

    if 'gachaGroupId' in chosenGacha.keys():
        _, pity = setUpPity(chosenGacha['gachaGroupId'])
    else:
        pity = 0

    # draw
    draw10 = body['gachaBeanKind'].endswith('10') or body['gachaBeanKind'] == 'SELECTABLE_TUTORIAL'
    isFreePull = False
    results = []
    itemTypes = []
    if body['gachaBeanKind'].startswith('NORMAL'):
        if draw10:
            results, itemTypes = drawTenNormal()
            isFreePull = beforeToday(dt.getGameUserValue('freeGachaAt'))
        else:
            results, itemTypes = drawOneNormal()
    else:
        if draw10:
            results, itemTypes, pity = drawTenPremium(pity)
        else:
            results, itemTypes, pity = drawOnePremium(pity)

    if 'gachaGroupId' in chosenGacha.keys():
        pityGroup, _ = setUpPity(chosenGacha['gachaGroupId'], pity)
    else:
        pityGroup = None
    
    # sort into lists
    userCardList = []
    userCharaList = []
    userPieceList = []
    userLive2dList = []
    userItemList = []
    userSectionList = []
    userQuestBattleList = []

    responseList = []

    for result, itemType in zip(results, itemTypes):
        if itemType.startswith('g'):
            userItemList.append(addGem(result))
            responseList.append({
                "direction": 5,
                "displayName": result['name'],
                "isNew": False,
                "itemId": result['itemCode'],
                "rarity": 'RANK_'+str(result['name'].count('+')+1),
                "type": "ITEM"
            })
        if itemType.startswith('p'):
            card, chara, live2ds, foundExisting = addMeguca(result['charaId'])
            if not foundExisting:
                userCardList.append(card)
                userLive2dList += live2ds
                newSectionList, newQuestBattleList = addStory(result['charaId'])
                userSectionList += newSectionList
                userQuestBattleList += newQuestBattleList
            userCharaList.append(chara)
            directionType = 3
            if result['cardList'][0]['card']['rank'][-1] == "4":
                # give it the rainbow swirlies
                directionType = 4
            responseList.append({
                "type": "CARD",
                "rarity": result['cardList'][0]['card']['rank'],
                "maxRarity": result['cardList'][-1]['card']['rank'],
                "cardId": result['cardList'][0]['cardId'],
                "attributeId": result['chara']['attributeId'],
                "charaId": result['charaId'],
                "direction": directionType,
                "displayName": result['chara']['name'],
                "isNew": not foundExisting
            })
            if foundExisting:
                responseList[-1]["itemId"] = "LIMIT_BREAK_CHARA"
        if itemType.startswith('m'):
            userPiece, foundExisting = addPiece(result['pieceId'])
            userPieceList.append(userPiece)
            directionType = 1
            if result['rank'][-1] == "4":
                # give it the memoria equivalent of the rainbow swirlies
                directionType = 2
            responseList.append({
                "type": "PIECE",
                "rarity": result['rank'],
                "pieceId": result['pieceId'],
                "direction": directionType,
                "displayName": result['pieceName'],
                "isNew": not foundExisting
            })

    # spend items
    gachaKind = None
    for kind in chosenGacha['gachaKindList']:
        if kind['beanKind'] == body['gachaBeanKind']:
            gachaKind = kind

    if not isFreePull:
        userItemList += \
            spend(gachaKind['needPointKind'], 
                gachaKind['needQuantity'], 
                gachaKind['substituteItemId'] if 'substituteItemId' in gachaKind else None)

    # create response
    gachaAnimation = {
            "live2dDetail": gachaKind['live2dDetail'],
            "messageId": gachaKind['messageId'],
            "message": gachaKind['message'],
            # Determines which picture to show in the intro animation
            #
            # first picture
            # 1 = flower thingy (default, no real meaning)
            # 2 = inverted flower thingy (should mean at least 1 3+ star CARD (not necessarily meguca, could be memoria))
            "direction1": 1,
            #
            # second picture
            # 1 = mokyuu (default, no real meaning)
            # 2 = attribute (specified with "direction2AttributeId")
            "direction2": 1,
            #
            # third picture
            # 1 = spear thingy (default, no real meaning)
            # 2 = iroha (should mean at least 1 3+ star)
            # 3 = mikazuki villa (at least 1 4 star)
            "direction3": 1,
            "gachaResultList": responseList
        }

    high_rarity_pulled = [thingy for thingy in responseList if thingy["rarity"] == "RANK_3" or thingy["rarity"] == "RANK_4"]
    cards_pulled = [thingy for thingy in responseList if thingy["type"] == "CARD"]
    any_3stars_pulled = [card for card in cards_pulled if card["rarity"] == "RANK_3"]
    any_4stars_pulled = [card for card in cards_pulled if card["rarity"] == "RANK_4"]

    # if any high rarity thingies pulled, set direction1
    if len(high_rarity_pulled) >= 1:
        gachaAnimation["direction1"] = 2

    # 50-50 chance of displaying a random card's attribute symbol instead of mokyuu
    # but only if cards were pulled (i.e. not for FP gacha)
    if len(cards_pulled) >= 1 and random.randint(1, 2) == 2:
        random_card = random.choice(cards_pulled)
        gachaAnimation["direction2"] = 2
        gachaAnimation["direction2AttributeId"] = random_card["attributeId"]

    if len(any_4stars_pulled) >= 1:
        # show mikazuki villa if any 4 stars were pulled
        gachaAnimation["direction3"] = 3
    elif len(any_3stars_pulled) >= 1:
        # show iroha if any 3 stars were pulled
        gachaAnimation["direction3"] = 2

    if pityGroup is not None:
        gachaAnimation["userGachaGroup"] = pityGroup
    response = {
        "resultCode": "success",
        "gachaAnimation": gachaAnimation,
        "userCardList": userCardList,
        "userCharaList": userCharaList,
        "userLive2dList": userLive2dList,
        "userItemList": userItemList,
        "userPieceList": userPieceList
    }

    if isFreePull:
        response['gameUser'] = dt.setGameUserValue('freeGachaAt', nowstr())

    if len(userSectionList) > 0: response['userSectionList'] = userSectionList
    if len(userQuestBattleList) > 0: response['userQuestBattleList'] = userQuestBattleList

    # add to user history
    pullId = str(uuid1())
    if not os.path.exists('data/user/gachaHistory'):
        os.mkdir('data/user/gachaHistory')
    dt.saveJson('data/user/gachaHistory/'+pullId+'.json', {'gachaAnimation': gachaAnimation})
    newHistory = {
        "id": pullId,
        "userId": dt.userId,
        "gachaScheduleId": body['gachaScheduleId'],
        "gachaSchedule": chosenGacha,
        "gachaBeanKind": body['gachaBeanKind'],
        "bonusTimeFlg": False,
        "createdAt": nowstr()
    }
    dt.setUserObject('gachaHistoryList', pullId, newHistory)
    return flask.jsonify(response)
예제 #13
0
def sendArena(request, response):
    """
        The response has 7 values:
        gameUser (should be in response),
        resultCode="success"
        userArenaBattle,
        userArenaBattleResultList,
        userDailyChallengeList,
        userItemList,
        userQuestBattleResultList (should be in response),

    """
    userArenaBattle = dt.readJson('data/user/userArenaBattle.json')
    userArenaBattleResult = dt.readJson('data/user/userArenaBattleResult.json')

    coins = dt.getUserObject('userItemList', 'ARENA_COIN')

    if (request['result'] == 'SUCCESSFUL'):
        coins['quantity'] += 3

        numTurnsCapped = min(max(request['totalTurn'], 2), 7)  # cap to 2 and 7
        turnBonus = 1.0 + 0.1 * (7 - numTurnsCapped)
        opponentBonus = {
            'SAME': 1.0,
            'HIGHER': 1.2,
            'LOWER': 0.8
        }[userArenaBattleResult['arenaBattleOpponentType']]
        consecBonus = [0, 1, 2, 3, 5, 7, 10
                       ][userArenaBattleResult['numberOfConsecutiveWins'] - 1]
        getPoints = 10 * turnBonus * opponentBonus + consecBonus
        userArenaBattle['freeRankArenaPoint'] += getPoints

        userArenaBattleResult['arenaBattleStatus'] = 'WIN'
        userArenaBattleResult[
            'numberOfConsecutiveWins'] = userArenaBattleResult[
                'numberOfConsecutiveWins'] % 7 + 1
        userArenaBattleResult['point'] = getPoints

        dt.setGameUserValue(
            'numberOfFreeRankTotalWins',
            dt.getGameUserValue('numberOfFreeRankTotalWins') + 1)
    else:
        userArenaBattleResult['arenaBattleStatus'] = 'LOSE'
        coins['quantity'] += 1
        userArenaBattleResult['numberOfConsecutiveWins'] = 0

        userArenaBattle['freeRankArenaPoint'] += 3
        userArenaBattleResult['point'] = userArenaBattle['freeRankArenaPoint']

    dt.setGameUserValue('freeRankArenaPoint',
                        userArenaBattle['freeRankArenaPoint'])
    gameUser = dt.setGameUserValue(
        'numberOfFreeRankConsecutiveWins',
        userArenaBattleResult['numberOfConsecutiveWins'])

    dt.saveJson('data/user/userArenaBattle.json', userArenaBattle)
    dt.saveJson('data/user/userArenaBattleResult.json', userArenaBattleResult)

    # updating coins
    dt.setUserObject('userItemList', 'ARENA_COIN', coins)
    userItemList = [coins]

    resultCode = "success"
    response.update({
        'gameUser': gameUser,
        'userArenaBattle': userArenaBattle,
        'userItemList': userItemList,
        'userArenaBattleResultList': [userArenaBattleResult],
        'resultCode': resultCode
    })
    response = storyUtil.progressMirrors(response)
    return flask.jsonify(response)
예제 #14
0
def buy():
    body = flask.request.json
    shopList = dt.readJson('data/shopList.json')

    currShop = {}
    for shop in shopList:
        if shop['shopId'] == body['shopId']:
            currShop = shop
            break
    if currShop == {}:
        flask.abort(
            400,
            description=
            '{"errorTxt": "Trying to buy from a nonexistent shop","resultCode": "error","title": "Error"}'
        )

    item = {}
    for shopItem in shop['shopItemList']:
        if shopItem['id'] == body['shopItemId']:
            item = shopItem
            break
    if item == {}:
        flask.abort(
            400,
            description=
            '{"errorTxt": "Trying to buy something not in this shop","resultCode": "error","title": "Error"}'
        )

    # get the thing
    args = {}
    if item['shopItemType'] == 'SET':
        obtainSet(item, body, args)
    else:
        obtain(item, body, args)

    # spend items
    if item['consumeType'] == 'ITEM':
        spendArgs = getItem(item['needItemId'],
                            -1 * item['needNumber'] * body['num'])
        if 'userItemList' in args:
            args['userItemList'] += spendArgs['userItemList']
        else:
            args = dt.updateJson(args, spendArgs)
    elif item['consumeType'] == 'MONEY':
        itemList = gacha.spend('MONEY', item['needNumber'] * body['num'])
        if 'userItemList' in args:
            args['userItemList'] += itemList
        else:
            args['userItemList'] = itemList

    userShopItem = {
        "createdAt": nowstr(),
        "num": body['num'],
        "shopItemId": body['shopItemId'],
        "userId": dt.userId
    }
    args['userShopItemList'] = [userShopItem]
    path = 'data/user/userShopItemList.json'
    dt.saveJson(path, dt.readJson(path) + [userShopItem])

    return flask.jsonify(args)
예제 #15
0
def arenaStart(response):
    body = flask.request.json

    chosenTeam = dt.getUserObject('userDeckList', 21)
    if chosenTeam is None:
        flask.abort(
            400,
            '{"errorTxt": "You don\'t have a mirrors team...","resultCode": "error","title": "Error"}'
        )

    chosenFormation = dt.getUserObject('userFormationSheetList',
                                       chosenTeam['formationSheetId'])
    if chosenFormation is None:
        flask.abort(
            400,
            '{"errorTxt": "You don\'t have that formation.","resultCode": "error","title": "Error"}'
        )

    battleId = str(uuid1())
    userQuestBattleResult = {
        "battleType": "ARENA",
        "bondsPt1": 0,
        "bondsPt2": 0,
        "bondsPt3": 0,
        "bondsPt4": 0,
        "bondsPt5": 0,
        "bondsPt6": 0,
        "bondsPt7": 0,
        "bondsPt8": 0,
        "bondsPt9": 0,
        "clearedMission1": False,
        "clearedMission2": False,
        "clearedMission3": False,
        "connectNum": 0,
        "continuedNum": 0,
        "createdAt": nowstr(),
        "deadNum": 0,
        "deckType": 21,
        "diskAcceleNum": 0,
        "diskBlastNum": 0,
        "diskChargeNum": 0,
        "doppelNum": 0,
        "enemyNum": 0,
        "episodeUserCardId": chosenTeam['questEpisodeUserCardId'],
        "exp": 0,
        "follow": True,
        "follower": True,
        "formationSheetId": chosenTeam['formationSheetId'],
        "formationSheet": chosenFormation,
        "id": battleId,
        "level": dt.getUserValue('level'),
        "magiaNum": 0,
        "nativeClearTime": 0,
        "questBattleStatus": "CREATED",
        "riche": 0,
        "serverClearTime": 0,
        "skillNum": 0,
        "turns": 0,
        "userId": dt.userId
    }

    for i in range(5):
        numberedId = 'userCardId' + str(i + 1)
        if numberedId in chosenTeam:
            userQuestBattleResult['userCardId' + str(chosenTeam[
                'questPositionId' + str(i + 1)])] = chosenTeam[numberedId]

    userArenaBattle = dt.readJson('data/user/userArenaBattle.json')
    userArenaBattleResult = dt.readJson('data/user/userArenaBattleResult.json')
    if userArenaBattleResult is None:
        userArenaBattleResult = {"numberOfConsecutiveWins": 0}
    userArenaBattleResult.update({
        "userQuestBattleResultId": battleId,
        "userId": dt.userId,
        "opponentUserId": body['opponentUserId'],
        "arenaBattleType": "FREE_RANK",
        "arenaBattleStatus": "CREATED",
        "arenaBattleOpponentType": "SAME",
        "point": userArenaBattle['freeRankArenaPoint'],
        "createdAt": nowstr()
    })

    response.update({
        "resultCode": "success",
        "userQuestBattleResultList": [userQuestBattleResult],
        'userArenaBattleResult': [userArenaBattleResult]
    })

    dt.saveJson('data/user/userQuestBattleResult.json', userQuestBattleResult)
    dt.saveJson('data/user/userArenaBattleResult.json', userArenaBattleResult)