コード例 #1
0
ファイル: bishi.py プロジェクト: vangar/bemaniutils
    def format_profile(self, profile: ValidatedDict, playstats: ValidatedDict) -> Dict[str, Any]:
        name = 'なし'  # Nothing
        shop = '未設定'  # Not set
        shop_area = '未設定'  # Not set

        for i in range(len(profile['strdatas'])):
            strdata = profile['strdatas'][i]

            # Figure out the profile type
            csvs = strdata.split(b',')
            if len(csvs) < 2:
                # Not long enough to care about
                continue
            datatype = csvs[1].decode('ascii')
            if datatype != 'IBBDAT00':
                # Not the right profile type requested
                continue

            name = self.__update_value(name, csvs[27])
            shop = self.__update_value(shop, csvs[30])
            shop_area = self.__update_value(shop_area, csvs[31])

        return {
            'name': name,
            'extid': ID.format_extid(profile.get_int('extid')),
            'shop': shop,
            'shop_area': shop_area,
            'first_play_time': playstats.get_int('first_play_timestamp'),
            'last_play_time': playstats.get_int('last_play_timestamp'),
            'plays': playstats.get_int('total_plays'),
        }
コード例 #2
0
ファイル: base.py プロジェクト: vangar/bemaniutils
 def format_profile(self, profile: ValidatedDict, playstats: ValidatedDict) -> Dict[str, Any]:
     return {
         'name': profile.get_str('name'),
         'extid': ID.format_extid(profile.get_int('extid')),
         'first_play_time': playstats.get_int('first_play_timestamp'),
         'last_play_time': playstats.get_int('last_play_timestamp'),
     }
コード例 #3
0
ファイル: reflecbeat.py プロジェクト: wolskiCN/bemaniutils
    def handle_pcbinfo_get_request(self, request: Node) -> Node:
        shop_id = ID.parse_machine_id(request.child_value('lid'))
        machine = self.get_machine_by_id(shop_id)
        if machine is not None:
            machine_name = machine.name
            close = machine.data.get_bool('close')
            hour = machine.data.get_int('hour')
            minute = machine.data.get_int('minute')
            pref = machine.data.get_int('pref', 51)
        else:
            machine_name = ''
            close = False
            hour = 0
            minute = 0
            pref = 51

        root = Node.void('pcbinfo')
        info = Node.void('info')
        root.add_child(info)

        info.add_child(Node.string('name', machine_name))
        info.add_child(Node.s16('pref', pref))
        info.add_child(Node.bool('close', close))
        info.add_child(Node.u8('hour', hour))
        info.add_child(Node.u8('min', minute))

        return root
コード例 #4
0
ファイル: common.py プロジェクト: vangar/bemaniutils
    def handle_game_3_new_request(self, request: Node) -> Node:
        refid = request.child_value('refid')
        name = request.child_value('name')
        loc = ID.parse_machine_id(request.child_value('locid'))
        self.new_profile_by_refid(refid, name, loc)

        root = Node.void('game_3')
        return root
コード例 #5
0
ファイル: core.py プロジェクト: wolskiCN/bemaniutils
    def handle_facility_get_request(self, request: Node) -> Node:
        """
        Handle a facility request. The only method of note is the 'get' request,
        which expects to return a bunch of information about the arcade this
        cabinet is in, as well as some settings for URLs and the name of the cab.
        """
        machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])

        root = Node.void('facility')
        root.set_attribute('expire', '600')
        location = Node.void('location')
        location.add_child(Node.string('id', ID.format_machine_id(machine.id)))
        location.add_child(Node.string('country', 'US'))
        location.add_child(Node.string('region', '.'))
        location.add_child(Node.string('name', machine.name))
        location.add_child(Node.u8('type', 0))

        line = Node.void('line')
        line.add_child(Node.string('id', '.'))
        line.add_child(Node.u8('class', 0))

        portfw = Node.void('portfw')
        portfw.add_child(Node.ipv4('globalip', self.config['client']['address']))
        portfw.add_child(Node.u16('globalport', machine.port))
        portfw.add_child(Node.u16('privateport', machine.port))

        public = Node.void('public')
        public.add_child(Node.u8('flag', 1))
        public.add_child(Node.string('name', '.'))
        public.add_child(Node.string('latitude', '0'))
        public.add_child(Node.string('longitude', '0'))

        share = Node.void('share')
        eacoin = Node.void('eacoin')
        eacoin.add_child(Node.s32('notchamount', 3000))
        eacoin.add_child(Node.s32('notchcount', 3))
        eacoin.add_child(Node.s32('supplylimit', 10000))

        eapass = Node.void('eapass')
        eapass.add_child(Node.u16('valid', 365))

        url = Node.void('url')
        url.add_child(Node.string('eapass', self.config['server']['uri'] or 'www.ea-pass.konami.net'))
        url.add_child(Node.string('arcadefan', self.config['server']['uri'] or 'www.konami.jp/am'))
        url.add_child(Node.string('konaminetdx', self.config['server']['uri'] or 'http://am.573.jp'))
        url.add_child(Node.string('konamiid', self.config['server']['uri'] or 'https://id.konami.net'))
        url.add_child(Node.string('eagate', self.config['server']['uri'] or 'http://eagate.573.jp'))

        share.add_child(eacoin)
        share.add_child(url)
        share.add_child(eapass)
        root.add_child(location)
        root.add_child(line)
        root.add_child(portfw)
        root.add_child(public)
        root.add_child(share)
        return root
コード例 #6
0
ファイル: ddrace.py プロジェクト: wolskiCN/bemaniutils
    def __handle_usernew(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None:
        if userid is None:
            raise Exception('Expecting valid UserID to create new profile!')

        machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
        self.put_profile(userid, ValidatedDict({
            'lid': machine.id,
        }))
        profile = self.get_profile(userid)

        response.add_child(Node.string('seq', ID.format_extid(profile.get_int('extid'))))
        response.add_child(Node.s32('code', profile.get_int('extid')))
        response.add_child(Node.string('shoparea', ''))
コード例 #7
0
ファイル: booth.py プロジェクト: vangar/bemaniutils
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        game = Node.void('game')

        # Generic profile stuff
        game.add_child(Node.string('name', profile.get_str('name')))
        game.add_child(
            Node.string('code', ID.format_extid(profile.get_int('extid'))))
        game.add_child(Node.u32('gamecoin_packet', profile.get_int('packet')))
        game.add_child(Node.u32('gamecoin_block', profile.get_int('block')))
        game.add_child(Node.u32('exp_point', profile.get_int('exp')))
        game.add_child(Node.u32('m_user_cnt', profile.get_int('m_user_cnt')))

        game_config = self.get_game_config()
        if game_config.get_bool('force_unlock_cards'):
            game.add_child(Node.bool_array('have_item', [True] * 512))
        else:
            game.add_child(
                Node.bool_array(
                    'have_item',
                    [x > 0 for x in profile.get_int_array('have_item', 512)]))
        if game_config.get_bool('force_unlock_songs'):
            game.add_child(Node.bool_array('have_note', [True] * 512))
        else:
            game.add_child(
                Node.bool_array(
                    'have_note',
                    [x > 0 for x in profile.get_int_array('have_note', 512)]))

        # Last played stuff
        lastdict = profile.get_dict('last')
        last = Node.void('last')
        game.add_child(last)
        last.set_attribute('music_id', str(lastdict.get_int('music_id')))
        last.set_attribute('music_type', str(lastdict.get_int('music_type')))
        last.set_attribute('sort_type', str(lastdict.get_int('sort_type')))
        last.set_attribute('headphone', str(lastdict.get_int('headphone')))
        last.set_attribute('hispeed', str(lastdict.get_int('hispeed')))
        last.set_attribute('appeal_id', str(lastdict.get_int('appeal_id')))
        last.set_attribute('frame0', str(lastdict.get_int('frame0')))
        last.set_attribute('frame1', str(lastdict.get_int('frame1')))
        last.set_attribute('frame2', str(lastdict.get_int('frame2')))
        last.set_attribute('frame3', str(lastdict.get_int('frame3')))
        last.set_attribute('frame4', str(lastdict.get_int('frame4')))

        return game
コード例 #8
0
ファイル: endpoints.py プロジェクト: vangar/bemaniutils
def searchrivals() -> Dict[str, Any]:
    frontend = SoundVoltexFrontend(g.data, g.config, g.cache)
    version = int(request.get_json()['version'])
    name = request.get_json()['term']

    # Try to treat the term as an extid
    extid = ID.parse_extid(name)

    matches = set()
    profiles = g.data.remote.user.get_all_profiles(GameConstants.SDVX, version)
    for (userid, profile) in profiles:
        if profile.get_int('extid') == extid or profile.get_str('name').lower() == name.lower():
            matches.add(userid)

    playerinfo = frontend.get_all_player_info(list(matches), allow_remote=True)
    return {
        'results': playerinfo,
    }
コード例 #9
0
    def handle_pcb_rb5_pcb_boot_request(self, request: Node) -> Node:
        shop_id = ID.parse_machine_id(request.child_value('lid'))
        machine = self.get_machine_by_id(shop_id)
        if machine is not None:
            machine_name = machine.name
            close = machine.data.get_bool('close')
            hour = machine.data.get_int('hour')
            minute = machine.data.get_int('minute')
        else:
            machine_name = ''
            close = False
            hour = 0
            minute = 0

        root = Node.void('pcb')
        sinfo = Node.void('sinfo')
        root.add_child(sinfo)
        sinfo.add_child(Node.string('nm', machine_name))
        sinfo.add_child(Node.bool('cl_enbl', close))
        sinfo.add_child(Node.u8('cl_h', hour))
        sinfo.add_child(Node.u8('cl_m', minute))
        sinfo.add_child(Node.bool('shop_flag', True))
        return root
コード例 #10
0
    def handle_playerdata_request(self, request: Node) -> Optional[Node]:
        method = request.attribute('method')

        if method == 'expire':
            return Node.void('playerdata')

        elif method == 'logout':
            return Node.void('playerdata')

        elif method == 'get':
            modelstring = request.attribute('model')
            refid = request.child_value('ref_id')
            root = self.get_profile_by_refid(
                refid,
                self.NEW_PROFILE_ONLY
                if modelstring is None else self.OLD_PROFILE_ONLY,
            )
            if root is None:
                root = Node.void('playerdata')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'conversion':
            refid = request.child_value('ref_id')
            name = request.child_value('name')
            chara = request.child_value('chara')
            root = self.new_profile_by_refid(refid, name, chara)
            if root is None:
                root = Node.void('playerdata')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'new':
            refid = request.child_value('ref_id')
            name = request.child_value('name')
            root = self.new_profile_by_refid(refid, name)
            if root is None:
                root = Node.void('playerdata')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'set':
            refid = request.attribute('ref_id')

            root = Node.void('playerdata')
            root.add_child(Node.s8('pref', -1))
            if refid is None:
                return root

            userid = self.data.remote.user.from_refid(self.game, self.version,
                                                      refid)
            if userid is None:
                return root

            oldprofile = self.get_profile(userid) or ValidatedDict()
            newprofile = self.unformat_profile(userid, request, oldprofile)

            if newprofile is not None:
                self.put_profile(userid, newprofile)
                root.add_child(Node.string('name', newprofile['name']))

            return root

        elif method == 'friend':
            refid = request.attribute('ref_id')
            root = Node.void('playerdata')

            # Look up our own user ID based on the RefID provided.
            userid = self.data.remote.user.from_refid(self.game, self.version,
                                                      refid)
            if userid is None:
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            # Grab the links that we care about.
            links = self.data.local.user.get_links(self.game, self.version,
                                                   userid)
            profiles: Dict[UserID, ValidatedDict] = {}
            rivals: List[Link] = []
            for link in links:
                if link.type != 'rival':
                    continue

                other_profile = self.get_profile(link.other_userid)
                if other_profile is None:
                    continue
                profiles[link.other_userid] = other_profile
                rivals.append(link)

            for rival in links[:2]:
                rivalid = rival.other_userid
                rivalprofile = profiles[rivalid]
                scores = self.data.remote.music.get_scores(
                    self.game, self.version, rivalid)

                # First, output general profile info.
                friend = Node.void('friend')
                root.add_child(friend)

                # This might be for having non-active or non-confirmed friends, but setting to 0 makes the
                # ranking numbers disappear and the player icon show a questionmark.
                friend.add_child(Node.s8('open', 1))

                # Set up some sane defaults.
                friend.add_child(
                    Node.string('name', rivalprofile.get_str('name', 'なし')))
                friend.add_child(
                    Node.string('g_pm_id',
                                ID.format_extid(
                                    rivalprofile.get_int('extid'))))
                friend.add_child(
                    Node.s16('chara', rivalprofile.get_int('chara', -1)))

                # Perform hiscore/medal conversion.
                hiscore_array = [0] * int(
                    (((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8)
                clear_medal = [0] * self.GAME_MAX_MUSIC_ID
                for score in scores:
                    if score.id > self.GAME_MAX_MUSIC_ID:
                        continue

                    # Skip any scores for chart types we don't support
                    if score.chart not in [
                            self.CHART_TYPE_EASY,
                            self.CHART_TYPE_NORMAL,
                            self.CHART_TYPE_HYPER,
                            self.CHART_TYPE_EX,
                    ]:
                        continue

                    points = score.points
                    clear_medal[score.id] = clear_medal[
                        score.id] | self.__format_medal_for_score(score)

                    hiscore_index = (score.id * 4) + {
                        self.CHART_TYPE_EASY:
                        self.GAME_CHART_TYPE_EASY_POSITION,
                        self.CHART_TYPE_NORMAL:
                        self.GAME_CHART_TYPE_NORMAL_POSITION,
                        self.CHART_TYPE_HYPER:
                        self.GAME_CHART_TYPE_HYPER_POSITION,
                        self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX_POSITION,
                    }[score.chart]
                    hiscore_byte_pos = int((hiscore_index * 17) / 8)
                    hiscore_bit_pos = int((hiscore_index * 17) % 8)
                    hiscore_value = points << hiscore_bit_pos
                    hiscore_array[hiscore_byte_pos] = hiscore_array[
                        hiscore_byte_pos] | (hiscore_value & 0xFF)
                    hiscore_array[hiscore_byte_pos +
                                  1] = hiscore_array[hiscore_byte_pos + 1] | (
                                      (hiscore_value >> 8) & 0xFF)
                    hiscore_array[hiscore_byte_pos +
                                  2] = hiscore_array[hiscore_byte_pos + 2] | (
                                      (hiscore_value >> 16) & 0xFF)

                hiscore = bytes(hiscore_array)
                friend.add_child(Node.u16_array('clear_medal', clear_medal))
                friend.add_child(Node.binary('hiscore', hiscore))

            return root

        # Invalid method
        return None
コード例 #11
0
ファイル: reflecbeat.py プロジェクト: wolskiCN/bemaniutils
    def unformat_profile(self, userid: UserID, request: Node,
                         oldprofile: ValidatedDict) -> ValidatedDict:
        game_config = self.get_game_config()
        newprofile = copy.deepcopy(oldprofile)

        newprofile.replace_int('lid',
                               ID.parse_machine_id(request.child_value('lid')))
        newprofile.replace_str('name', request.child_value('pdata/base/name'))
        newprofile.replace_int('lvl', request.child_value('pdata/base/lv'))
        newprofile.replace_int('exp', request.child_value('pdata/base/exp'))
        newprofile.replace_int('mg', request.child_value('pdata/base/mg'))
        newprofile.replace_int('ap', request.child_value('pdata/base/ap'))
        newprofile.replace_int('flag', request.child_value('pdata/base/flag'))

        customdict = newprofile.get_dict('custom')
        custom = request.child('pdata/custom')
        if custom:
            customdict.replace_int('bgm_m', custom.child_value('bgm_m'))
            customdict.replace_int('st_f', custom.child_value('st_f'))
            customdict.replace_int('st_bg', custom.child_value('st_bg'))
            customdict.replace_int('st_bg_b', custom.child_value('st_bg_b'))
            customdict.replace_int('eff_e', custom.child_value('eff_e'))
            customdict.replace_int('se_s', custom.child_value('se_s'))
            customdict.replace_int('se_s_v', custom.child_value('se_s_v'))
        newprofile.replace_dict('custom', customdict)

        # Music unlocks and other stuff
        released = request.child('pdata/released')
        if released:
            for child in released.children:
                if child.name != 'info':
                    continue

                item_id = child.child_value('id')
                item_type = child.child_value('type')
                if game_config.get_bool(
                        'force_unlock_songs') and item_type == 0:
                    # Don't save unlocks when we're force unlocking
                    continue

                self.data.local.user.put_achievement(
                    self.game,
                    self.version,
                    userid,
                    item_id,
                    'item_{}'.format(item_type),
                    {},
                )

        # Grab any new records set during this play session. Reflec Beat original only sends
        # the top record back for songs that were played at least once during the session.
        # Note that it sends the top record, so if you play the song twice, it will return
        # only one record. Also, if you get a lower score than a previous try, it will return
        # the previous try. So, we must also look at the battle log for the actual play scores,
        # and combine the data if we can.
        savedrecords: Dict[int, Dict[int, Dict[str, int]]] = {}
        songplays = request.child('pdata/record')
        if songplays:
            for child in songplays.children:
                if child.name != 'rec':
                    continue

                songid = child.child_value('mid')
                chart = child.child_value('ng')

                # These don't get sent with the battle logs, so we try to construct
                # the values here.
                if songid not in savedrecords:
                    savedrecords[songid] = {}
                savedrecords[songid][chart] = {
                    'achievement_rate': child.child_value('ar') * 10,
                    'points': child.child_value('bs'),
                    'combo': child.child_value('mc'),
                    'miss_count': child.child_value('bmc'),
                    'win': child.child_value('win'),
                    'lose': child.child_value('lose'),
                    'draw': child.child_value('draw'),
                }

        # Now, see the actual battles that were played. If we can, unify the data with a record.
        # We only do that when the record achievement rate and score matches the battle achievement
        # rate and score, so we know for a fact that that record was generated by this battle.
        battlelogs = request.child('pdata/blog')
        if battlelogs:
            for child in battlelogs.children:
                if child.name != 'log':
                    continue

                songid = child.child_value('mid')
                chart = child.child_value('ng')

                clear_type = child.child_value('myself/ct')
                achievement_rate = child.child_value('myself/ar') * 10
                points = child.child_value('myself/s')

                clear_type, combo_type = self.__game_to_db_clear_type(
                    clear_type, achievement_rate)

                combo = None
                miss_count = -1
                stats = None

                if songid in savedrecords:
                    if chart in savedrecords[songid]:
                        data = savedrecords[songid][chart]

                        if (data['achievement_rate'] == achievement_rate
                                and data['points'] == points):
                            # This is the same record! Use the stats from it to update our
                            # internal representation.
                            combo = data['combo']
                            miss_count = data['miss_count']
                            stats = {
                                'win': data['win'],
                                'lose': data['lose'],
                                'draw': data['draw'],
                            }

                self.update_score(
                    userid,
                    songid,
                    chart,
                    points,
                    achievement_rate,
                    clear_type,
                    combo_type,
                    miss_count,
                    combo=combo,
                    stats=stats,
                )

        # Keep track of play statistics
        self.update_play_statistics(userid)

        return newprofile
コード例 #12
0
ファイル: common.py プロジェクト: vangar/bemaniutils
    def handle_game_3_hiscore_request(self, request: Node) -> Node:
        # Grab location for local scores
        locid = ID.parse_machine_id(request.child_value('locid'))

        # Start the response packet
        game = Node.void('game_3')

        # First, grab hit chart
        playcounts = self.data.local.music.get_hit_chart(
            self.game, self.version, 1024)

        hitchart = Node.void('hitchart')
        game.add_child(hitchart)
        for (songid, count) in playcounts:
            info = Node.void('info')
            hitchart.add_child(info)
            info.add_child(Node.u32('id', songid))
            info.add_child(Node.u32('cnt', count))

        # Now, grab user records
        records = self.data.remote.music.get_all_records(
            self.game, self.version)
        users = {
            uid: prof
            for (uid, prof) in self.get_any_profiles([r[0] for r in records])
        }

        hiscore_allover = Node.void('hiscore_allover')
        game.add_child(hiscore_allover)

        # Output records
        for (userid, score) in records:
            info = Node.void('info')

            if userid not in users:
                raise Exception(
                    'Logic error, could not find profile for user!')
            profile = users[userid]

            info.add_child(Node.u32('id', score.id))
            info.add_child(Node.u32('type', score.chart))
            info.add_child(Node.string('name', profile.get_str('name')))
            info.add_child(
                Node.string('seq', ID.format_extid(profile.get_int('extid'))))
            info.add_child(Node.u32('score', score.points))

            # Add to global scores
            hiscore_allover.add_child(info)

        # Now, grab local records
        area_users = [
            uid for (uid, prof) in self.data.local.user.get_all_profiles(
                self.game, self.version) if prof.get_int('loc', -1) == locid
        ]
        records = self.data.local.music.get_all_records(self.game,
                                                        self.version,
                                                        userlist=area_users)
        missing_players = [uid for (uid, _) in records if uid not in users]
        for (uid, prof) in self.get_any_profiles(missing_players):
            users[uid] = prof

        hiscore_location = Node.void('hiscore_location')
        game.add_child(hiscore_location)

        # Output records
        for (userid, score) in records:
            info = Node.void('info')

            if userid not in users:
                raise Exception(
                    'Logic error, could not find profile for user!')
            profile = users[userid]

            info.add_child(Node.u32('id', score.id))
            info.add_child(Node.u32('type', score.chart))
            info.add_child(Node.string('name', profile.get_str('name')))
            info.add_child(
                Node.string('seq', ID.format_extid(profile.get_int('extid'))))
            info.add_child(Node.u32('score', score.points))

            # Add to global scores
            hiscore_location.add_child(info)

        # Now, grab clear rates
        clear_rate = Node.void('clear_rate')
        game.add_child(clear_rate)

        clears = self.get_clear_rates()
        for songid in clears:
            for chart in clears[songid]:
                if clears[songid][chart]['total'] > 0:
                    rate = float(clears[songid][chart]['clears']) / float(
                        clears[songid][chart]['total'])
                    dnode = Node.void('d')
                    clear_rate.add_child(dnode)
                    dnode.add_child(Node.u32('id', songid))
                    dnode.add_child(Node.u32('type', chart))
                    dnode.add_child(Node.s16('cr', int(rate * 10000)))

        return game
コード例 #13
0
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        game = Node.void('game_3')

        # Generic profile stuff
        game.add_child(Node.string('name', profile.get_str('name')))
        game.add_child(Node.string('code', ID.format_extid(profile.get_int('extid'))))
        game.add_child(Node.u32('gamecoin_packet', profile.get_int('packet')))
        game.add_child(Node.u32('gamecoin_block', profile.get_int('block')))
        game.add_child(Node.s16('skill_name_id', profile.get_int('skill_name_id', -1)))
        game.add_child(Node.s32_array('hidden_param', profile.get_int_array('hidden_param', 20)))
        game.add_child(Node.u32('blaster_energy', profile.get_int('blaster_energy')))
        game.add_child(Node.u32('blaster_count', profile.get_int('blaster_count')))

        # Enable Ryusei Festa
        ryusei_festa = Node.void('ryusei_festa')
        game.add_child(ryusei_festa)
        ryusei_festa.add_child(Node.bool('ryusei_festa_trigger', True))

        # Play statistics
        statistics = self.get_play_statistics(userid)
        last_play_date = statistics.get_int_array('last_play_date', 3)
        today_play_date = Time.todays_date()
        if (
            last_play_date[0] == today_play_date[0] and
            last_play_date[1] == today_play_date[1] and
            last_play_date[2] == today_play_date[2]
        ):
            today_count = statistics.get_int('today_plays', 0)
        else:
            today_count = 0
        game.add_child(Node.u32('play_count', statistics.get_int('total_plays', 0)))
        game.add_child(Node.u32('daily_count', today_count))
        game.add_child(Node.u32('play_chain', statistics.get_int('consecutive_days', 0)))

        # Last played stuff
        if 'last' in profile:
            lastdict = profile.get_dict('last')
            last = Node.void('last')
            game.add_child(last)
            last.add_child(Node.s32('music_id', lastdict.get_int('music_id', -1)))
            last.add_child(Node.u8('music_type', lastdict.get_int('music_type')))
            last.add_child(Node.u8('sort_type', lastdict.get_int('sort_type')))
            last.add_child(Node.u8('narrow_down', lastdict.get_int('narrow_down')))
            last.add_child(Node.u8('headphone', lastdict.get_int('headphone')))
            last.add_child(Node.u16('appeal_id', lastdict.get_int('appeal_id', 1001)))
            last.add_child(Node.u16('comment_id', lastdict.get_int('comment_id')))
            last.add_child(Node.u8('gauge_option', lastdict.get_int('gauge_option')))

        # Item unlocks
        itemnode = Node.void('item')
        game.add_child(itemnode)

        game_config = self.get_game_config()
        achievements = self.data.local.user.get_achievements(self.game, self.version, userid)

        for item in achievements:
            if item.type[:5] != 'item_':
                continue
            itemtype = int(item.type[5:])

            if game_config.get_bool('force_unlock_songs') and itemtype == self.GAME_CATALOG_TYPE_SONG:
                # Don't echo unlocked songs, we will add all of them later
                continue

            info = Node.void('info')
            itemnode.add_child(info)
            info.add_child(Node.u8('type', itemtype))
            info.add_child(Node.u32('id', item.id))
            info.add_child(Node.u32('param', item.data.get_int('param')))
            if 'diff_param' in item.data:
                info.add_child(Node.s32('diff_param', item.data.get_int('diff_param')))

        if game_config.get_bool('force_unlock_songs'):
            ids: Dict[int, int] = {}
            songs = self.data.local.music.get_all_songs(self.game, self.version)
            for song in songs:
                if song.id not in ids:
                    ids[song.id] = 0

                if song.data.get_int('difficulty') > 0:
                    ids[song.id] = ids[song.id] | (1 << song.chart)

            for itemid in ids:
                if ids[itemid] == 0:
                    continue

                info = Node.void('info')
                itemnode.add_child(info)
                info.add_child(Node.u8('type', self.GAME_CATALOG_TYPE_SONG))
                info.add_child(Node.u32('id', itemid))
                info.add_child(Node.u32('param', ids[itemid]))

        return game
コード例 #14
0
    def verify_usergamedata_send(self,
                                 ref_id: str,
                                 ext_id: int,
                                 msg_type: str,
                                 send_only_common: bool = False) -> None:
        call = self.call_node()

        # Set up profile write
        profiledata = {
            'COMMON': [
                b'1',
                b'0',  # shoparea spot, filled in below
                b'3c880f8',
                b'1',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'ffffffffffffffff',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'',  # Name spot, filled in below
                ID.format_extid(ext_id).encode('ascii'),
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
            ],
            'OPTION': [
                b'0',
                b'3',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'3',
                b'0',
                b'0',
                b'0',
                b'0',
                b'1',
                b'2',
                b'0',
                b'0',
                b'0',
                b'10.000000',
                b'10.000000',
                b'10.000000',
                b'10.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
            ],
            'LAST': [
                b'1',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
            ],
            'RIVAL': [
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'0.000000',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
                b'',
            ]
        }

        if msg_type == 'new':
            # New profile gets blank name, because we save over it at the end of the round.
            profiledata['COMMON'][1] = b'0'
            profiledata['COMMON'][25] = b''

        elif msg_type == 'existing':
            # Exiting profile gets our hardcoded name saved.
            profiledata['COMMON'][1] = b'3a'
            profiledata['COMMON'][25] = self.NAME.encode('shift-jis')

        else:
            raise Exception(f'Unknown message type {msg_type}!')

        if send_only_common:
            profiledata = {'COMMON': profiledata['COMMON']}

        # Construct node
        playerdata = Node.void('playerdata')
        call.add_child(playerdata)
        playerdata.set_attribute('method', 'usergamedata_send')
        playerdata.add_child(Node.u32('retrycnt', 0))
        info = Node.void('info')
        playerdata.add_child(info)
        info.add_child(Node.s32('version', 1))
        data = Node.void('data')
        playerdata.add_child(data)
        data.add_child(Node.string('refid', ref_id))
        data.add_child(Node.string('dataid', ref_id))
        data.add_child(Node.string('gamekind', 'MDX'))
        data.add_child(Node.u32('datanum', len(profiledata.keys())))
        record = Node.void('record')
        data.add_child(record)
        for ptype in profiledata:
            profile = [b'ffffffff', ptype.encode('ascii')] + profiledata[ptype]
            d = Node.string(
                'd',
                base64.b64encode(b','.join(profile)).decode('ascii'))
            record.add_child(d)
            d.add_child(Node.string('bin1', ''))

        # Swap with server
        resp = self.exchange('', call)
        self.assert_path(resp, "response/playerdata/result")
コード例 #15
0
ファイル: limelight.py プロジェクト: Subject38/bemaniutils
    def unformat_profile(self, userid: UserID, request: Node,
                         oldprofile: ValidatedDict) -> ValidatedDict:
        game_config = self.get_game_config()
        newprofile = copy.deepcopy(oldprofile)

        newprofile.replace_int('lid',
                               ID.parse_machine_id(request.child_value('lid')))
        newprofile.replace_str('name', request.child_value('pdata/base/name'))
        newprofile.replace_int('icon',
                               request.child_value('pdata/base/icon_id'))
        newprofile.replace_int('lvl', request.child_value('pdata/base/lv'))
        newprofile.replace_int('exp', request.child_value('pdata/base/exp'))
        newprofile.replace_int('mg', request.child_value('pdata/base/mg'))
        newprofile.replace_int('ap', request.child_value('pdata/base/ap'))
        newprofile.replace_int('pc', request.child_value('pdata/base/pc'))
        newprofile.replace_int('uattr',
                               request.child_value('pdata/base/uattr'))

        customdict = newprofile.get_dict('custom')
        custom = request.child('pdata/custom')
        if custom:
            customdict.replace_int('s_gls', custom.child_value('s_gls'))
            customdict.replace_int('bgm_m', custom.child_value('bgm_m'))
            customdict.replace_int('st_f', custom.child_value('st_f'))
            customdict.replace_int('st_bg', custom.child_value('st_bg'))
            customdict.replace_int('st_bg_b', custom.child_value('st_bg_b'))
            customdict.replace_int('eff_e', custom.child_value('eff_e'))
            customdict.replace_int('se_s', custom.child_value('se_s'))
            customdict.replace_int('se_s_v', custom.child_value('se_s_v'))
            customdict.replace_int('last_music_id',
                                   custom.child_value('last_music_id'))
            customdict.replace_int('last_note_grade',
                                   custom.child_value('last_note_grade'))
            customdict.replace_int('sort_type',
                                   custom.child_value('sort_type'))
            customdict.replace_int('narrowdown_type',
                                   custom.child_value('narrowdown_type'))
            customdict.replace_bool(
                'is_begginer', custom.child_value(
                    'is_begginer'))  # Yes, this is spelled right
            customdict.replace_bool('is_tut', custom.child_value('is_tut'))
            customdict.replace_int_array('symbol_chat_0', 6,
                                         custom.child_value('symbol_chat_0'))
            customdict.replace_int_array('symbol_chat_1', 6,
                                         custom.child_value('symbol_chat_1'))
            customdict.replace_int('gauge_style',
                                   custom.child_value('gauge_style'))
            customdict.replace_int('obj_shade',
                                   custom.child_value('obj_shade'))
            customdict.replace_int('obj_size', custom.child_value('obj_size'))
            customdict.replace_int_array('byword', 2,
                                         custom.child_value('byword'))
            customdict.replace_bool_array('is_auto_byword', 2,
                                          custom.child_value('is_auto_byword'))
            customdict.replace_bool('is_tweet', custom.child_value('is_tweet'))
            customdict.replace_bool('is_link_twitter',
                                    custom.child_value('is_link_twitter'))
            customdict.replace_int('mrec_type',
                                   custom.child_value('mrec_type'))
            customdict.replace_int('card_disp_type',
                                   custom.child_value('card_disp_type'))
            customdict.replace_int('tab_sel', custom.child_value('tab_sel'))
            customdict.replace_int_array('hidden_param', 20,
                                         custom.child_value('hidden_param'))
        newprofile.replace_dict('custom', customdict)

        # Music unlocks and other stuff
        released = request.child('pdata/released')
        if released:
            for child in released.children:
                if child.name != 'info':
                    continue

                item_id = child.child_value('id')
                item_type = child.child_value('type')
                param = child.child_value('param')
                if game_config.get_bool(
                        'force_unlock_songs') and item_type == 0:
                    # Don't save unlocks when we're force unlocking
                    continue

                self.data.local.user.put_achievement(
                    self.game,
                    self.version,
                    userid,
                    item_id,
                    f'item_{item_type}',
                    {
                        'param': param,
                    },
                )

        # Grab any new records set during this play session. Reflec Beat Limelight only sends
        # the top record back for songs that were played at least once during the session.
        # Note that it sends the top record, so if you play the song twice, it will return
        # only one record. Also, if you get a lower score than a previous try, it will return
        # the previous try. So, we must also look at the battle log for the actual play scores,
        # and combine the data if we can.
        savedrecords: Dict[int, Dict[int, Dict[str, int]]] = {}
        songplays = request.child('pdata/record')
        if songplays:
            for child in songplays.children:
                if child.name != 'rec':
                    continue

                songid = child.child_value('mid')
                chart = child.child_value('ng')

                # These don't get sent with the battle logs, so we try to construct
                # the values here.
                if songid not in savedrecords:
                    savedrecords[songid] = {}
                savedrecords[songid][chart] = {
                    'achievement_rate': child.child_value('mrec_0/ar') * 10,
                    'points': child.child_value('mrec_0/bs'),
                    'combo': child.child_value('mrec_0/mc'),
                    'miss_count': child.child_value('mrec_0/bmc'),
                    'win': child.child_value('mrec_0/win'),
                    'lose': child.child_value('mrec_0/lose'),
                    'draw': child.child_value('mrec_0/draw'),
                    'earned_points': child.child_value('point'),
                }

        # Now, see the actual battles that were played. If we can, unify the data with a record.
        # We only do that when the record achievement rate and score matches the battle achievement
        # rate and score, so we know for a fact that that record was generated by this battle.
        battlelogs = request.child('pdata/blog')
        if battlelogs:
            for child in battlelogs.children:
                if child.name != 'log':
                    continue

                songid = child.child_value('mid')
                chart = child.child_value('ng')

                clear_type = child.child_value('myself/ct')
                achievement_rate = child.child_value('myself/ar') * 10
                points = child.child_value('myself/s')

                clear_type, combo_type = self.__game_to_db_clear_type(
                    clear_type)

                combo = None
                miss_count = -1
                stats = None

                if songid in savedrecords:
                    if chart in savedrecords[songid]:
                        data = savedrecords[songid][chart]

                        if (data['achievement_rate'] == achievement_rate
                                and data['points'] == points):
                            # This is the same record! Use the stats from it to update our
                            # internal representation.
                            combo = data['combo']
                            miss_count = data['miss_count']
                            stats = {
                                'win': data['win'],
                                'lose': data['lose'],
                                'draw': data['draw'],
                                'earned_points': data['earned_points'],
                            }

                self.update_score(
                    userid,
                    songid,
                    chart,
                    points,
                    achievement_rate,
                    clear_type,
                    combo_type,
                    miss_count,
                    combo=combo,
                    stats=stats,
                )

        # Keep track of glass points so unlocks work
        glass = request.child('pdata/glass')
        if glass:
            for child in glass.children:
                if child.name != 'g':
                    continue

                gid = child.child_value('id')
                exp = child.child_value('exp')
                self.data.local.user.put_achievement(
                    self.game,
                    self.version,
                    userid,
                    gid,
                    'glass',
                    {
                        'exp': exp,
                    },
                )

        # Keep track of favorite music selections
        fav_music_slot = request.child('pdata/fav_music_slot')
        if fav_music_slot:
            for child in fav_music_slot.children:
                if child.name != 'slot':
                    continue

                slot_id = child.child_value('slot_id')
                music_id = child.child_value('music_id')
                if music_id == -1:
                    # Delete this favorite
                    self.data.local.user.destroy_achievement(
                        self.game,
                        self.version,
                        userid,
                        slot_id,
                        'music',
                    )
                else:
                    # Add/update this favorite
                    self.data.local.user.put_achievement(
                        self.game,
                        self.version,
                        userid,
                        slot_id,
                        'music',
                        {
                            'music_id': music_id,
                        },
                    )

        # Keep track of play statistics
        self.update_play_statistics(userid)

        return newprofile
コード例 #16
0
ファイル: fantasia.py プロジェクト: wolskiCN/bemaniutils
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        root = Node.void('playerdata')

        # Set up the base profile
        base = Node.void('base')
        root.add_child(base)
        base.add_child(Node.string('name', profile.get_str('name', 'なし')))
        base.add_child(
            Node.string('g_pm_id', ID.format_extid(profile.get_int('extid'))))
        base.add_child(Node.u8('mode', profile.get_int('mode', 0)))
        base.add_child(Node.s8('button', profile.get_int('button', 0)))
        base.add_child(
            Node.s8('last_play_flag', profile.get_int('last_play_flag', -1)))
        base.add_child(
            Node.u8('medal_and_friend', profile.get_int('medal_and_friend',
                                                        0)))
        base.add_child(Node.s8('category', profile.get_int('category', -1)))
        base.add_child(
            Node.s8('sub_category', profile.get_int('sub_category', -1)))
        base.add_child(Node.s16('chara', profile.get_int('chara', -1)))
        base.add_child(
            Node.s8('chara_category', profile.get_int('chara_category', -1)))
        base.add_child(Node.u8('collabo', profile.get_int('collabo', 255)))
        base.add_child(Node.u8('sheet', profile.get_int('sheet', 0)))
        base.add_child(Node.s8('tutorial', profile.get_int('tutorial', 0)))
        base.add_child(
            Node.s32('music_open_pt', profile.get_int('music_open_pt', 0)))
        base.add_child(Node.s8('is_conv', -1))
        base.add_child(Node.s32('option', profile.get_int('option', 0)))
        base.add_child(Node.s16('music', profile.get_int('music', -1)))
        base.add_child(Node.u16('ep', profile.get_int('ep', 0)))
        base.add_child(
            Node.s32_array('sp_color_flg',
                           profile.get_int_array('sp_color_flg', 2)))
        base.add_child(Node.s32('read_news', profile.get_int('read_news', 0)))
        base.add_child(
            Node.s16('consecutive_days_coupon',
                     profile.get_int('consecutive_days_coupon', 0)))
        base.add_child(Node.s8('staff', 0))

        # Player card section
        player_card_dict = profile.get_dict('player_card')
        player_card = Node.void('player_card')
        root.add_child(player_card)
        player_card.add_child(
            Node.u8_array('title',
                          player_card_dict.get_int_array('title', 2, [0, 1])))
        player_card.add_child(
            Node.u8('frame', player_card_dict.get_int('frame')))
        player_card.add_child(Node.u8('base',
                                      player_card_dict.get_int('base')))
        player_card.add_child(
            Node.u8_array('seal', player_card_dict.get_int_array('seal', 2)))
        player_card.add_child(
            Node.s32_array('get_title',
                           player_card_dict.get_int_array('get_title', 4)))
        player_card.add_child(
            Node.s32('get_frame', player_card_dict.get_int('get_frame')))
        player_card.add_child(
            Node.s32('get_base', player_card_dict.get_int('get_base')))
        player_card.add_child(
            Node.s32_array('get_seal',
                           player_card_dict.get_int_array('get_seal', 2)))

        # Player card EX section
        player_card_ex = Node.void('player_card_ex')
        root.add_child(player_card_ex)
        player_card_ex.add_child(
            Node.s32('get_title_ex', player_card_dict.get_int('get_title_ex')))
        player_card_ex.add_child(
            Node.s32('get_frame_ex', player_card_dict.get_int('get_frame_ex')))
        player_card_ex.add_child(
            Node.s32('get_base_ex', player_card_dict.get_int('get_base_ex')))
        player_card_ex.add_child(
            Node.s32('get_seal_ex', player_card_dict.get_int('get_seal_ex')))

        # Statistics section and scores section
        statistics = self.get_play_statistics(userid)
        last_play_date = statistics.get_int_array('last_play_date', 3)
        today_play_date = Time.todays_date()
        if (last_play_date[0] == today_play_date[0]
                and last_play_date[1] == today_play_date[1]
                and last_play_date[2] == today_play_date[2]):
            today_count = statistics.get_int('today_plays', 0)
        else:
            today_count = 0
        base.add_child(Node.u8('active_fr_num',
                               0))  # TODO: Hook up rivals code?
        base.add_child(
            Node.s32('total_play_cnt', statistics.get_int('total_plays', 0)))
        base.add_child(Node.s16('today_play_cnt', today_count))
        base.add_child(
            Node.s16('consecutive_days',
                     statistics.get_int('consecutive_days', 0)))

        last_played = [
            x[0] for x in self.data.local.music.get_last_played(
                self.game, self.version, userid, 3)
        ]
        most_played = [
            x[0] for x in self.data.local.music.get_most_played(
                self.game, self.version, userid, 20)
        ]
        while len(last_played) < 3:
            last_played.append(-1)
        while len(most_played) < 20:
            most_played.append(-1)

        hiscore_array = [0] * int(
            (((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8)
        clear_medal = [0] * self.GAME_MAX_MUSIC_ID
        clear_medal_sub = [0] * self.GAME_MAX_MUSIC_ID

        scores = self.data.remote.music.get_scores(self.game, self.version,
                                                   userid)
        for score in scores:
            if score.id > self.GAME_MAX_MUSIC_ID:
                continue

            # Skip any scores for chart types we don't support
            if score.chart not in [
                    self.CHART_TYPE_EASY,
                    self.CHART_TYPE_NORMAL,
                    self.CHART_TYPE_HYPER,
                    self.CHART_TYPE_EX,
            ]:
                continue

            points = score.points
            clear_medal[score.id] = clear_medal[
                score.id] | self.__format_medal_for_score(score)

            hiscore_index = (score.id * 4) + {
                self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
                self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
                self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER_POSITION,
                self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX_POSITION,
            }[score.chart]
            hiscore_byte_pos = int((hiscore_index * 17) / 8)
            hiscore_bit_pos = int((hiscore_index * 17) % 8)
            hiscore_value = points << hiscore_bit_pos
            hiscore_array[hiscore_byte_pos] = hiscore_array[
                hiscore_byte_pos] | (hiscore_value & 0xFF)
            hiscore_array[hiscore_byte_pos +
                          1] = hiscore_array[hiscore_byte_pos + 1] | (
                              (hiscore_value >> 8) & 0xFF)
            hiscore_array[hiscore_byte_pos +
                          2] = hiscore_array[hiscore_byte_pos + 2] | (
                              (hiscore_value >> 16) & 0xFF)

        hiscore = bytes(hiscore_array)

        player_card.add_child(Node.s16_array('best_music', most_played[0:3]))
        base.add_child(Node.s16_array('my_best', most_played))
        base.add_child(Node.s16_array('latest_music', last_played))
        base.add_child(Node.u16_array('clear_medal', clear_medal))
        base.add_child(Node.u8_array('clear_medal_sub', clear_medal_sub))

        # Goes outside of base for some reason
        root.add_child(Node.binary('hiscore', hiscore))

        # Net VS section
        netvs = Node.void('netvs')
        root.add_child(netvs)
        netvs.add_child(Node.s32_array('get_ojama', [0, 0]))
        netvs.add_child(Node.s32('rank_point', 0))
        netvs.add_child(Node.s32('play_point', 0))
        netvs.add_child(Node.s16_array('record', [0, 0, 0, 0, 0, 0]))
        netvs.add_child(Node.u8('rank', 0))
        netvs.add_child(Node.s8_array('ojama_condition', [0] * 74))
        netvs.add_child(Node.s8_array('set_ojama', [0, 0, 0]))
        netvs.add_child(Node.s8_array('set_recommend', [0, 0, 0]))
        netvs.add_child(Node.s8_array('jewelry', [0] * 15))
        for dialog in [0, 1, 2, 3, 4, 5]:
            # TODO: Configure this, maybe?
            netvs.add_child(Node.string('dialog', 'dialog#{}'.format(dialog)))

        sp_data = Node.void('sp_data')
        root.add_child(sp_data)
        sp_data.add_child(Node.s32('sp', profile.get_int('sp', 0)))

        reflec_data = Node.void('reflec_data')
        root.add_child(reflec_data)
        reflec_data.add_child(
            Node.s8_array('reflec', profile.get_int_array('reflec', 2)))

        # Navigate section
        navigate_dict = profile.get_dict('navigate')
        navigate = Node.void('navigate')
        root.add_child(navigate)
        navigate.add_child(Node.s8('genre', navigate_dict.get_int('genre')))
        navigate.add_child(Node.s8('image', navigate_dict.get_int('image')))
        navigate.add_child(Node.s8('level', navigate_dict.get_int('level')))
        navigate.add_child(Node.s8('ojama', navigate_dict.get_int('ojama')))
        navigate.add_child(
            Node.s16('limit_num', navigate_dict.get_int('limit_num')))
        navigate.add_child(Node.s8('button', navigate_dict.get_int('button')))
        navigate.add_child(Node.s8('life', navigate_dict.get_int('life')))
        navigate.add_child(
            Node.s16('progress', navigate_dict.get_int('progress')))

        return root
コード例 #17
0
ファイル: limelight.py プロジェクト: Subject38/bemaniutils
    def handle_event_r_get_all_request(self, request: Node) -> Node:
        limit = request.child_value('limit')

        comments = [
            achievement for achievement in self.data.local.user.
            get_all_time_based_achievements(self.game, self.version)
            if achievement[1].type == 'puzzle_comment'
        ]
        comments.sort(key=lambda x: x[1].timestamp, reverse=True)
        statuses = self.data.local.lobby.get_all_play_session_infos(
            self.game, self.version)
        statuses.sort(key=lambda x: x[1]['time'], reverse=True)

        # Cap all comment blocks to the limit
        if limit >= 0:
            comments = comments[:limit]
            statuses = statuses[:limit]

        # Mapping of profiles to userIDs
        uid_mapping = {
            uid: prof
            for (uid, prof) in self.get_any_profiles([c[0] for c in comments] +
                                                     [s[0] for s in statuses])
        }

        # Mapping of location ID to machine name
        lid_mapping: Dict[int, str] = {}

        root = Node.void('event_r')
        root.add_child(Node.s32('time', Time.now()))
        statusnode = Node.void('status')
        root.add_child(statusnode)
        commentnode = Node.void('comment')
        root.add_child(commentnode)

        for (uid, comment) in comments:
            lid = ID.parse_machine_id(comment.data.get_str('lid'))

            # Look up external data for the request
            if lid not in lid_mapping:
                machine = self.get_machine_by_id(lid)
                if machine is not None:
                    lid_mapping[lid] = machine.name
                else:
                    lid_mapping[lid] = ''

            c = Node.void('c')
            commentnode.add_child(c)
            c.add_child(Node.s32('uid', uid_mapping[uid].get_int('extid')))
            c.add_child(Node.string('p_name',
                                    uid_mapping[uid].get_str('name')))
            c.add_child(Node.s32('exp', uid_mapping[uid].get_int('exp')))
            c.add_child(
                Node.s32('customize', comment.data.get_int('customize')))
            c.add_child(Node.s32('tid', comment.data.get_int('teamid')))
            c.add_child(Node.string('t_name',
                                    comment.data.get_str('teamname')))
            c.add_child(Node.string('lid', comment.data.get_str('lid')))
            c.add_child(Node.string('s_name', lid_mapping[lid]))
            c.add_child(Node.s8('pref', comment.data.get_int('prefecture')))
            c.add_child(Node.s32('time', comment.timestamp))
            c.add_child(Node.string('comment',
                                    comment.data.get_str('comment')))
            c.add_child(Node.bool('is_tweet', comment.data.get_bool('tweet')))

        for (uid, status) in statuses:
            lid = ID.parse_machine_id(status.get_str('lid'))

            # Look up external data for the request
            if lid not in lid_mapping:
                machine = self.get_machine_by_id(lid)
                if machine is not None:
                    lid_mapping[lid] = machine.name
                else:
                    lid_mapping[lid] = ''

            s = Node.void('s')
            statusnode.add_child(s)
            s.add_child(Node.s32('uid', uid_mapping[uid].get_int('extid')))
            s.add_child(Node.string('p_name',
                                    uid_mapping[uid].get_str('name')))
            s.add_child(Node.s32('exp', uid_mapping[uid].get_int('exp')))
            s.add_child(Node.s32('customize', status.get_int('customize')))
            s.add_child(
                Node.s32('tid', uid_mapping[uid].get_int('team_id', -1)))
            s.add_child(
                Node.string('t_name',
                            uid_mapping[uid].get_str('team_name', '')))
            s.add_child(Node.string('lid', status.get_str('lid')))
            s.add_child(Node.string('s_name', lid_mapping[lid]))
            s.add_child(Node.s8('pref', status.get_int('prefecture')))
            s.add_child(Node.s32('time', status.get_int('time')))
            s.add_child(Node.s8('status', status.get_int('status')))
            s.add_child(Node.s8('stage', status.get_int('stage')))
            s.add_child(Node.s32('mid', status.get_int('mid')))
            s.add_child(Node.s8('ng', status.get_int('ng')))

        return root
コード例 #18
0
ファイル: test_ID.py プロジェクト: vangar/bemaniutils
 def test_format_extid(self) -> None:
     self.assertEqual(ID.format_extid(12345678), '1234-5678')
     self.assertEqual(ID.parse_extid('1234-5678'), 12345678)
     self.assertEqual(ID.parse_extid('bla'), None)
     self.assertEqual(ID.parse_extid('blah-blah'), None)
コード例 #19
0
ファイル: lapistoria.py プロジェクト: yungsun09/bemaniutils
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        root = Node.void('player22')

        # Result
        root.add_child(Node.s8('result', 0))

        # Set up account
        account = Node.void('account')
        root.add_child(account)
        account.add_child(Node.string('name', profile.get_str('name', 'なし')))
        account.add_child(
            Node.string('g_pm_id', ID.format_extid(profile.get_int('extid'))))
        account.add_child(Node.s8('tutorial', profile.get_int('tutorial', -1)))
        account.add_child(
            Node.s16('read_news', profile.get_int('read_news', 0)))
        account.add_child(Node.s8('staff', 0))
        account.add_child(Node.s8('is_conv', 0))
        account.add_child(Node.s16('item_type', 0))
        account.add_child(Node.s16('item_id', 0))
        account.add_child(
            Node.s16_array('license_data',
                           [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]))

        # Statistics section and scores section
        statistics = self.get_play_statistics(userid)
        last_play_date = statistics.get_int_array('last_play_date', 3)
        today_play_date = Time.todays_date()
        if (last_play_date[0] == today_play_date[0]
                and last_play_date[1] == today_play_date[1]
                and last_play_date[2] == today_play_date[2]):
            today_count = statistics.get_int('today_plays', 0)
        else:
            today_count = 0
        account.add_child(Node.u8('active_fr_num',
                                  0))  # TODO: Hook up rivals code?
        account.add_child(
            Node.s16('total_play_cnt', statistics.get_int('total_plays', 0)))
        account.add_child(Node.s16('today_play_cnt', today_count))
        account.add_child(
            Node.s16('consecutive_days',
                     statistics.get_int('consecutive_days', 0)))
        account.add_child(
            Node.s16('total_days', statistics.get_int('total_days', 0)))
        account.add_child(Node.s16('interval_day', 0))

        # Add scores section
        last_played = [
            x[0] for x in self.data.local.music.get_last_played(
                self.game, self.version, userid, 5)
        ]
        most_played = [
            x[0] for x in self.data.local.music.get_most_played(
                self.game, self.version, userid, 10)
        ]
        while len(last_played) < 5:
            last_played.append(-1)
        while len(most_played) < 10:
            most_played.append(-1)

        account.add_child(Node.s16_array('my_best', most_played))
        account.add_child(Node.s16_array('latest_music', last_played))

        scores = self.data.remote.music.get_scores(self.game, self.version,
                                                   userid)
        for score in scores:
            # Skip any scores for chart types we don't support
            if score.chart not in [
                    self.CHART_TYPE_EASY,
                    self.CHART_TYPE_NORMAL,
                    self.CHART_TYPE_HYPER,
                    self.CHART_TYPE_EX,
            ]:
                continue

            points = score.points
            medal = score.data.get_int('medal')

            music = Node.void('music')
            root.add_child(music)
            music.add_child(Node.s16('music_num', score.id))
            music.add_child(
                Node.u8(
                    'sheet_num', {
                        self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY,
                        self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL,
                        self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER,
                        self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX,
                    }[score.chart]))
            music.add_child(Node.s16('cnt', score.plays))
            music.add_child(Node.s32('score', points))
            music.add_child(
                Node.u8(
                    'clear_type', {
                        self.PLAY_MEDAL_CIRCLE_FAILED:
                        self.GAME_PLAY_MEDAL_CIRCLE_FAILED,
                        self.PLAY_MEDAL_DIAMOND_FAILED:
                        self.GAME_PLAY_MEDAL_DIAMOND_FAILED,
                        self.PLAY_MEDAL_STAR_FAILED:
                        self.GAME_PLAY_MEDAL_STAR_FAILED,
                        self.PLAY_MEDAL_EASY_CLEAR:
                        self.GAME_PLAY_MEDAL_EASY_CLEAR,
                        self.PLAY_MEDAL_CIRCLE_CLEARED:
                        self.GAME_PLAY_MEDAL_CIRCLE_CLEARED,
                        self.PLAY_MEDAL_DIAMOND_CLEARED:
                        self.GAME_PLAY_MEDAL_DIAMOND_CLEARED,
                        self.PLAY_MEDAL_STAR_CLEARED:
                        self.GAME_PLAY_MEDAL_STAR_CLEARED,
                        self.PLAY_MEDAL_CIRCLE_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO,
                        self.PLAY_MEDAL_DIAMOND_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO,
                        self.PLAY_MEDAL_STAR_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_STAR_FULL_COMBO,
                        self.PLAY_MEDAL_PERFECT: self.GAME_PLAY_MEDAL_PERFECT,
                    }[medal]))
            music.add_child(Node.s32('old_score', 0))
            music.add_child(Node.u8('old_clear_type', 0))

        # Net VS section
        netvs = Node.void('netvs')
        root.add_child(netvs)
        netvs.add_child(Node.s32('rank_point', 0))
        netvs.add_child(Node.s16_array('record', [0, 0, 0, 0, 0, 0]))
        netvs.add_child(Node.u8('rank', 0))
        netvs.add_child(Node.s8('vs_rank_old', 0))
        netvs.add_child(Node.s8_array('ojama_condition', [0] * 74))
        netvs.add_child(Node.s8_array('set_ojama', [0, 0, 0]))
        netvs.add_child(Node.s8_array('set_recommend', [0, 0, 0]))
        netvs.add_child(Node.u32('netvs_play_cnt', 0))
        for dialog in [0, 1, 2, 3, 4, 5]:
            # TODO: Configure this, maybe?
            netvs.add_child(Node.string('dialog', f'dialog#{dialog}'))

        # Set up config
        config = Node.void('config')
        root.add_child(config)
        config.add_child(Node.u8('mode', profile.get_int('mode', 0)))
        config.add_child(Node.s16('chara', profile.get_int('chara', -1)))
        config.add_child(Node.s16('music', profile.get_int('music', -1)))
        config.add_child(Node.u8('sheet', profile.get_int('sheet', 0)))
        config.add_child(Node.s8('category', profile.get_int('category', 1)))
        config.add_child(
            Node.s8('sub_category', profile.get_int('sub_category', -1)))
        config.add_child(
            Node.s8('chara_category', profile.get_int('chara_category', -1)))
        config.add_child(Node.s16('story_id', profile.get_int('story_id', -1)))
        config.add_child(
            Node.s16('course_id', profile.get_int('course_id', -1)))
        config.add_child(
            Node.s8('course_folder', profile.get_int('course_folder', -1)))
        config.add_child(
            Node.s8('story_folder', profile.get_int('story_folder', -1)))
        config.add_child(
            Node.s8('ms_banner_disp', profile.get_int('ms_banner_disp')))
        config.add_child(
            Node.s8('ms_down_info', profile.get_int('ms_down_info')))
        config.add_child(
            Node.s8('ms_side_info', profile.get_int('ms_side_info')))
        config.add_child(
            Node.s8('ms_raise_type', profile.get_int('ms_raise_type')))
        config.add_child(Node.s8('ms_rnd_type',
                                 profile.get_int('ms_rnd_type')))

        # Set up option
        option_dict = profile.get_dict('option')
        option = Node.void('option')
        root.add_child(option)
        option.add_child(
            Node.s16('hispeed', option_dict.get_int('hispeed', 10)))
        option.add_child(Node.u8('popkun', option_dict.get_int('popkun', 0)))
        option.add_child(
            Node.bool('hidden', option_dict.get_bool('hidden', False)))
        option.add_child(
            Node.s16('hidden_rate', option_dict.get_int('hidden_rate', -1)))
        option.add_child(
            Node.bool('sudden', option_dict.get_bool('sudden', False)))
        option.add_child(
            Node.s16('sudden_rate', option_dict.get_int('sudden_rate', -1)))
        option.add_child(Node.s8('randmir', option_dict.get_int('randmir', 0)))
        option.add_child(
            Node.s8('gauge_type', option_dict.get_int('gauge_type', 0)))
        option.add_child(Node.u8('ojama_0', option_dict.get_int('ojama_0', 0)))
        option.add_child(Node.u8('ojama_1', option_dict.get_int('ojama_1', 0)))
        option.add_child(
            Node.bool('forever_0', option_dict.get_bool('forever_0', False)))
        option.add_child(
            Node.bool('forever_1', option_dict.get_bool('forever_1', False)))
        option.add_child(
            Node.bool('full_setting',
                      option_dict.get_bool('full_setting', False)))

        # Set up info
        info = Node.void('info')
        root.add_child(info)
        info.add_child(Node.u16('ep', profile.get_int('ep', 0)))
        info.add_child(Node.u16('ap', profile.get_int('ap', 0)))

        # Set up custom_cate
        custom_cate = Node.void('custom_cate')
        root.add_child(custom_cate)
        custom_cate.add_child(Node.s8('valid', 0))
        custom_cate.add_child(Node.s8('lv_min', -1))
        custom_cate.add_child(Node.s8('lv_max', -1))
        custom_cate.add_child(Node.s8('medal_min', -1))
        custom_cate.add_child(Node.s8('medal_max', -1))
        custom_cate.add_child(Node.s8('friend_no', -1))
        custom_cate.add_child(Node.s8('score_flg', -1))

        # Set up customize
        customize_dict = profile.get_dict('customize')
        customize = Node.void('customize')
        root.add_child(customize)
        customize.add_child(
            Node.u16('effect', customize_dict.get_int('effect')))
        customize.add_child(
            Node.u16('hukidashi', customize_dict.get_int('hukidashi')))
        customize.add_child(Node.u16('font', customize_dict.get_int('font')))
        customize.add_child(
            Node.u16('comment_1', customize_dict.get_int('comment_1')))
        customize.add_child(
            Node.u16('comment_2', customize_dict.get_int('comment_2')))

        # Set up achievements
        achievements = self.data.local.user.get_achievements(
            self.game, self.version, userid)
        for achievement in achievements:
            if achievement.type == 'item':
                itemtype = achievement.data.get_int('type')
                param = achievement.data.get_int('param')

                item = Node.void('item')
                root.add_child(item)
                item.add_child(Node.u8('type', itemtype))
                item.add_child(Node.u16('id', achievement.id))
                item.add_child(Node.u16('param', param))
                item.add_child(Node.bool('is_new', False))

            elif achievement.type == 'achievement':
                count = achievement.data.get_int('count')

                ach_node = Node.void('achievement')
                root.add_child(ach_node)
                ach_node.add_child(Node.u8('type', achievement.id))
                ach_node.add_child(Node.u32('count', count))

            elif achievement.type == 'chara':
                friendship = achievement.data.get_int('friendship')

                chara = Node.void('chara_param')
                root.add_child(chara)
                chara.add_child(Node.u16('chara_id', achievement.id))
                chara.add_child(Node.u16('friendship', friendship))

            elif achievement.type == 'story':
                chapter = achievement.data.get_int('chapter')
                gauge = achievement.data.get_int('gauge')
                cleared = achievement.data.get_bool('cleared')
                clear_chapter = achievement.data.get_int('clear_chapter')

                story = Node.void('story')
                root.add_child(story)
                story.add_child(Node.u32('story_id', achievement.id))
                story.add_child(Node.u32('chapter_id', chapter))
                story.add_child(Node.u16('gauge_point', gauge))
                story.add_child(Node.bool('is_cleared', cleared))
                story.add_child(Node.u32('clear_chapter', clear_chapter))

        return root
コード例 #20
0
    def handle_player22_request(self, request: Node) -> Optional[Node]:
        method = request.attribute('method')

        if method == 'read':
            refid = request.child_value('ref_id')
            # Pop'n Music 22 doesn't send a modelstring to load old profiles,
            # it just expects us to know. So always look for old profiles in
            # Pop'n 22 land.
            root = self.get_profile_by_refid(refid,
                                             self.OLD_PROFILE_FALLTHROUGH)
            if root is None:
                root = Node.void('player22')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'new':
            refid = request.child_value('ref_id')
            name = request.child_value('name')
            root = self.new_profile_by_refid(refid, name)
            if root is None:
                root = Node.void('player22')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'start':
            return Node.void('player22')

        elif method == 'logout':
            return Node.void('player22')

        elif method == 'write':
            refid = request.child_value('ref_id')

            root = Node.void('player22')
            if refid is None:
                return root

            userid = self.data.remote.user.from_refid(self.game, self.version,
                                                      refid)
            if userid is None:
                return root

            oldprofile = self.get_profile(userid) or ValidatedDict()
            newprofile = self.unformat_profile(userid, request, oldprofile)

            if newprofile is not None:
                self.put_profile(userid, newprofile)

            return root

        elif method == 'friend':
            refid = request.attribute('ref_id')
            no = int(request.attribute('no', '-1'))

            root = Node.void('player22')
            if no < 0:
                root.add_child(Node.s8('result', 2))
                return root

            # Look up our own user ID based on the RefID provided.
            userid = self.data.remote.user.from_refid(self.game, self.version,
                                                      refid)
            if userid is None:
                root.add_child(Node.s8('result', 2))
                return root

            # Grab the links that we care about.
            links = self.data.local.user.get_links(self.game, self.version,
                                                   userid)
            profiles: Dict[UserID, ValidatedDict] = {}
            rivals: List[Link] = []
            for link in links:
                if link.type != 'rival':
                    continue

                other_profile = self.get_profile(link.other_userid)
                if other_profile is None:
                    continue
                profiles[link.other_userid] = other_profile
                rivals.append(link)

            # Somehow requested an invalid profile.
            if no >= len(rivals):
                root.add_child(Node.s8('result', 2))
                return root
            rivalid = links[no].other_userid
            rivalprofile = profiles[rivalid]
            scores = self.data.remote.music.get_scores(self.game, self.version,
                                                       rivalid)

            # First, output general profile info.
            friend = Node.void('friend')
            root.add_child(friend)
            friend.add_child(Node.s16('no', no))
            friend.add_child(
                Node.string('g_pm_id',
                            ID.format_extid(rivalprofile.get_int('extid'))))
            friend.add_child(
                Node.string('name', rivalprofile.get_str('name', 'なし')))
            friend.add_child(
                Node.s16('chara', rivalprofile.get_int('chara', -1)))
            # This might be for having non-active or non-confirmed friends, but setting to 0 makes the
            # ranking numbers disappear and the player icon show a questionmark.
            friend.add_child(Node.s8('is_open', 1))

            for score in scores:
                # Skip any scores for chart types we don't support
                if score.chart not in [
                        self.CHART_TYPE_EASY,
                        self.CHART_TYPE_NORMAL,
                        self.CHART_TYPE_HYPER,
                        self.CHART_TYPE_EX,
                ]:
                    continue

                points = score.points
                medal = score.data.get_int('medal')

                music = Node.void('music')
                friend.add_child(music)
                music.set_attribute('music_num', str(score.id))
                music.set_attribute(
                    'sheet_num',
                    str({
                        self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY,
                        self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL,
                        self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER,
                        self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX,
                    }[score.chart]))
                music.set_attribute('score', str(points))
                music.set_attribute(
                    'clearmedal',
                    str({
                        self.PLAY_MEDAL_CIRCLE_FAILED:
                        self.GAME_PLAY_MEDAL_CIRCLE_FAILED,
                        self.PLAY_MEDAL_DIAMOND_FAILED:
                        self.GAME_PLAY_MEDAL_DIAMOND_FAILED,
                        self.PLAY_MEDAL_STAR_FAILED:
                        self.GAME_PLAY_MEDAL_STAR_FAILED,
                        self.PLAY_MEDAL_EASY_CLEAR:
                        self.GAME_PLAY_MEDAL_EASY_CLEAR,
                        self.PLAY_MEDAL_CIRCLE_CLEARED:
                        self.GAME_PLAY_MEDAL_CIRCLE_CLEARED,
                        self.PLAY_MEDAL_DIAMOND_CLEARED:
                        self.GAME_PLAY_MEDAL_DIAMOND_CLEARED,
                        self.PLAY_MEDAL_STAR_CLEARED:
                        self.GAME_PLAY_MEDAL_STAR_CLEARED,
                        self.PLAY_MEDAL_CIRCLE_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO,
                        self.PLAY_MEDAL_DIAMOND_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO,
                        self.PLAY_MEDAL_STAR_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_STAR_FULL_COMBO,
                        self.PLAY_MEDAL_PERFECT: self.GAME_PLAY_MEDAL_PERFECT,
                    }[medal]))

            return root

        elif method == 'conversion':
            refid = request.child_value('ref_id')
            name = request.child_value('name')
            chara = request.child_value('chara')
            root = self.new_profile_by_refid(refid, name, chara)
            if root is None:
                root = Node.void('playerdata')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'write_music':
            refid = request.child_value('ref_id')

            root = Node.void('player22')
            if refid is None:
                return root

            userid = self.data.remote.user.from_refid(self.game, self.version,
                                                      refid)
            if userid is None:
                return root

            songid = request.child_value('music_num')
            chart = {
                self.GAME_CHART_TYPE_EASY: self.CHART_TYPE_EASY,
                self.GAME_CHART_TYPE_NORMAL: self.CHART_TYPE_NORMAL,
                self.GAME_CHART_TYPE_HYPER: self.CHART_TYPE_HYPER,
                self.GAME_CHART_TYPE_EX: self.CHART_TYPE_EX,
            }[request.child_value('sheet_num')]
            medal = request.child_value('clearmedal')
            points = request.child_value('score')
            combo = request.child_value('combo')
            stats = {
                'cool': request.child_value('cool'),
                'great': request.child_value('great'),
                'good': request.child_value('good'),
                'bad': request.child_value('bad')
            }
            medal = {
                self.GAME_PLAY_MEDAL_CIRCLE_FAILED:
                self.PLAY_MEDAL_CIRCLE_FAILED,
                self.GAME_PLAY_MEDAL_DIAMOND_FAILED:
                self.PLAY_MEDAL_DIAMOND_FAILED,
                self.GAME_PLAY_MEDAL_STAR_FAILED: self.PLAY_MEDAL_STAR_FAILED,
                self.GAME_PLAY_MEDAL_EASY_CLEAR: self.PLAY_MEDAL_EASY_CLEAR,
                self.GAME_PLAY_MEDAL_CIRCLE_CLEARED:
                self.PLAY_MEDAL_CIRCLE_CLEARED,
                self.GAME_PLAY_MEDAL_DIAMOND_CLEARED:
                self.PLAY_MEDAL_DIAMOND_CLEARED,
                self.GAME_PLAY_MEDAL_STAR_CLEARED:
                self.PLAY_MEDAL_STAR_CLEARED,
                self.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO:
                self.PLAY_MEDAL_CIRCLE_FULL_COMBO,
                self.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO:
                self.PLAY_MEDAL_DIAMOND_FULL_COMBO,
                self.GAME_PLAY_MEDAL_STAR_FULL_COMBO:
                self.PLAY_MEDAL_STAR_FULL_COMBO,
                self.GAME_PLAY_MEDAL_PERFECT: self.PLAY_MEDAL_PERFECT,
            }[medal]
            self.update_score(userid,
                              songid,
                              chart,
                              points,
                              medal,
                              combo=combo,
                              stats=stats)
            return root

        # Invalid method
        return None
コード例 #21
0
    def unformat_profile(self, userid: UserID, request: Node,
                         oldprofile: ValidatedDict) -> ValidatedDict:
        game_config = self.get_game_config()
        newprofile = copy.deepcopy(oldprofile)

        # Save base player profile info
        newprofile.replace_int(
            'lid',
            ID.parse_machine_id(request.child_value('pdata/account/lid')))
        newprofile.replace_str('name', request.child_value('pdata/base/name'))
        newprofile.replace_int('mg', request.child_value('pdata/base/mg'))
        newprofile.replace_int('ap', request.child_value('pdata/base/ap'))
        newprofile.replace_int('uattr',
                               request.child_value('pdata/base/uattr'))
        newprofile.replace_int('money',
                               request.child_value('pdata/base/money'))
        newprofile.replace_int('class',
                               request.child_value('pdata/base/class'))
        newprofile.replace_int('class_ar',
                               request.child_value('pdata/base/class_ar'))
        newprofile.replace_int('skill_point',
                               request.child_value('pdata/base/skill_point'))
        newprofile.replace_int('mgid',
                               request.child_value('pdata/minigame/mgid'))
        newprofile.replace_int('mgsc',
                               request.child_value('pdata/minigame/sc'))
        newprofile.replace_int_array(
            'favorites', 30, request.child_value('pdata/mylist/list/mlst'))

        # Save player config
        configdict = newprofile.get_dict('config')
        config = request.child('pdata/config')
        if config:
            configdict.replace_int('msel_bgm', config.child_value('msel_bgm'))
            configdict.replace_int('narrowdown_type',
                                   config.child_value('narrowdown_type'))
            configdict.replace_int('icon_id', config.child_value('icon_id'))
            configdict.replace_int('byword_0', config.child_value('byword_0'))
            configdict.replace_int('byword_1', config.child_value('byword_1'))
            configdict.replace_bool('is_auto_byword_0',
                                    config.child_value('is_auto_byword_0'))
            configdict.replace_bool('is_auto_byword_1',
                                    config.child_value('is_auto_byword_1'))
            configdict.replace_int('mrec_type',
                                   config.child_value('mrec_type'))
            configdict.replace_int('tab_sel', config.child_value('tab_sel'))
            configdict.replace_int('card_disp',
                                   config.child_value('card_disp'))
            configdict.replace_int('score_tab_disp',
                                   config.child_value('score_tab_disp'))
            configdict.replace_int('last_music_id',
                                   config.child_value('last_music_id'))
            configdict.replace_int('last_note_grade',
                                   config.child_value('last_note_grade'))
            configdict.replace_int('sort_type',
                                   config.child_value('sort_type'))
            configdict.replace_int('rival_panel_type',
                                   config.child_value('rival_panel_type'))
            configdict.replace_int('random_entry_work',
                                   config.child_value('random_entry_work'))
            configdict.replace_int('custom_folder_work',
                                   config.child_value('custom_folder_work'))
            configdict.replace_int('folder_type',
                                   config.child_value('folder_type'))
            configdict.replace_int('folder_lamp_type',
                                   config.child_value('folder_lamp_type'))
            configdict.replace_bool('is_tweet', config.child_value('is_tweet'))
            configdict.replace_bool('is_link_twitter',
                                    config.child_value('is_link_twitter'))
        newprofile.replace_dict('config', configdict)

        # Save player custom settings
        customdict = newprofile.get_dict('custom')
        custom = request.child('pdata/custom')
        if custom:
            customdict.replace_int('st_shot', custom.child_value('st_shot'))
            customdict.replace_int('st_frame', custom.child_value('st_frame'))
            customdict.replace_int('st_expl', custom.child_value('st_expl'))
            customdict.replace_int('st_bg', custom.child_value('st_bg'))
            customdict.replace_int('st_shot_vol',
                                   custom.child_value('st_shot_vol'))
            customdict.replace_int('st_bg_bri',
                                   custom.child_value('st_bg_bri'))
            customdict.replace_int('st_obj_size',
                                   custom.child_value('st_obj_size'))
            customdict.replace_int('st_jr_gauge',
                                   custom.child_value('st_jr_gauge'))
            customdict.replace_int('st_clr_gauge',
                                   custom.child_value('st_clr_gauge'))
            customdict.replace_int('st_gr_gauge_type',
                                   custom.child_value('st_gr_gauge_type'))
            customdict.replace_int('voice_message_set',
                                   custom.child_value('voice_message_set'))
            customdict.replace_int('same_time_note_disp',
                                   custom.child_value('same_time_note_disp'))
            customdict.replace_int('st_score_disp_type',
                                   custom.child_value('st_score_disp_type'))
            customdict.replace_int('st_bonus_type',
                                   custom.child_value('st_bonus_type'))
            customdict.replace_int('st_rivalnote_type',
                                   custom.child_value('st_rivalnote_type'))
            customdict.replace_int('st_topassist_type',
                                   custom.child_value('st_topassist_type'))
            customdict.replace_int('high_speed',
                                   custom.child_value('high_speed'))
            customdict.replace_int('st_hazard',
                                   custom.child_value('st_hazard'))
            customdict.replace_int('st_clr_cond',
                                   custom.child_value('st_clr_cond'))
            customdict.replace_int('voice_message_volume',
                                   custom.child_value('voice_message_volume'))
        newprofile.replace_dict('custom', customdict)

        # Save player parameter info
        params = request.child('pdata/player_param')
        if params:
            for child in params.children:
                if child.name != 'item':
                    continue

                item_type = child.child_value('type')
                bank = child.child_value('bank')
                data = child.child_value('data')
                while len(data) < 256:
                    data.append(0)
                self.data.local.user.put_achievement(
                    self.game,
                    self.version,
                    userid,
                    bank,
                    f'player_param_{item_type}',
                    {
                        'data': data,
                    },
                )

        # Save player episode info
        episode = request.child('pdata/episode')
        if episode:
            for child in episode.children:
                if child.name != 'info':
                    continue

                # I assume this is copypasta, but I want to be sure
                extid = child.child_value('user_id')
                if extid != newprofile.get_int('extid'):
                    raise Exception(
                        f'Unexpected user ID, got {extid} expecting {newprofile.get_int("extid")}'
                    )

                episode_type = child.child_value('type')
                episode_value0 = child.child_value('value0')
                episode_value1 = child.child_value('value1')
                episode_text = child.child_value('text')
                episode_time = child.child_value('time')
                self.data.local.user.put_achievement(
                    self.game,
                    self.version,
                    userid,
                    episode_type,
                    'episode',
                    {
                        'value0': episode_value0,
                        'value1': episode_value1,
                        'text': episode_text,
                        'time': episode_time,
                    },
                )

        # Save released info
        released = request.child('pdata/released')
        if released:
            for child in released.children:
                if child.name != 'info':
                    continue

                item_id = child.child_value('id')
                item_type = child.child_value('type')
                param = child.child_value('param')
                time = child.child_value('insert_time') or Time.now()
                if game_config.get_bool(
                        'force_unlock_songs') and item_type == 0:
                    # Don't save unlocks when we're force unlocking
                    continue

                self.data.local.user.put_achievement(
                    self.game,
                    self.version,
                    userid,
                    item_id,
                    f'item_{item_type}',
                    {
                        'param': param,
                        'time': time,
                    },
                )

        # Save announce info
        announce = request.child('pdata/announce')
        if announce:
            for child in announce.children:
                if child.name != 'info':
                    continue

                announce_id = child.child_value('id')
                announce_type = child.child_value('type')
                param = child.child_value('param')
                need = child.child_value('bneedannounce')
                self.data.local.user.put_achievement(
                    self.game,
                    self.version,
                    userid,
                    announce_id,
                    f'announcement_{announce_type}',
                    {
                        'param': param,
                        'need': need,
                    },
                )

        # Grab any new records set during this play session
        songplays = request.child('pdata/stglog')
        if songplays:
            for child in songplays.children:
                if child.name != 'log':
                    continue

                songid = child.child_value('mid')
                chart = child.child_value('ng')
                clear_type = child.child_value('ct')
                if songid == 0 and chart == 0 and clear_type == -1:
                    # Dummy song save during profile create
                    continue

                points = child.child_value('sc')
                achievement_rate = child.child_value('ar')
                param = child.child_value('param')
                miss_count = child.child_value('jt_ms')
                k_flag = child.child_value('k_flag')

                # Param is some random bits along with the combo type
                combo_type = param & 0x3
                param = param ^ combo_type

                clear_type = self._game_to_db_clear_type(clear_type)
                combo_type = self._game_to_db_combo_type(
                    combo_type, miss_count)
                self.update_score(
                    userid,
                    songid,
                    chart,
                    points,
                    achievement_rate,
                    clear_type,
                    combo_type,
                    miss_count,
                    param=param,
                    kflag=k_flag,
                )

        # Grab any new rivals added during this play session
        rivalnode = request.child('pdata/rival')
        if rivalnode:
            for child in rivalnode.children:
                if child.name != 'r':
                    continue

                extid = child.child_value('id')
                other_userid = self.data.remote.user.from_extid(
                    self.game, self.version, extid)
                if other_userid is None:
                    continue

                self.data.local.user.put_link(
                    self.game,
                    self.version,
                    userid,
                    'rival',
                    other_userid,
                    {},
                )

        # Save player dojo
        dojo = request.child('pdata/dojo')
        if dojo:
            dojoid = dojo.child_value('class')
            clear_type = dojo.child_value('clear_type')
            ar = dojo.child_value('t_ar')
            score = dojo.child_value('t_score')

            # Figure out timestamp stuff
            data = self.data.local.user.get_achievement(
                self.game,
                self.version,
                userid,
                dojoid,
                'dojo',
            ) or ValidatedDict()

            if ar >= data.get_int('ar'):
                # We set a new achievement rate, keep the new values
                record_time = Time.now()
            else:
                # We didn't, keep the old values for achievement rate, but
                # override score and clear_type only if they were better.
                record_time = data.get_int('record_timestamp')
                ar = data.get_int('ar')
                score = max(score, data.get_int('score'))
                clear_type = max(clear_type, data.get_int('clear_type'))

            play_time = Time.now()
            plays = data.get_int('plays') + 1

            self.data.local.user.put_achievement(
                self.game,
                self.version,
                userid,
                dojoid,
                'dojo',
                {
                    'clear_type': clear_type,
                    'ar': ar,
                    'score': score,
                    'plays': plays,
                    'play_timestamp': play_time,
                    'record_timestamp': record_time,
                },
            )

        # Save yurukome stuff
        yurukome_list = request.child('pdata/yurukome_list')
        if yurukome_list:
            for child in yurukome_list.children:
                if child.name != 'yurukome':
                    continue

                yurukome_id = child.child_value('yurukome_id')
                self.data.local.user.put_achievement(
                    self.game,
                    self.version,
                    userid,
                    yurukome_id,
                    'yurukome',
                    {},
                )

        # Save mycourse stuff
        mycoursedict = newprofile.get_dict('mycourse')
        mycourse = request.child('pdata/mycourse')
        if mycourse:
            # Only replace course if it was a new record score-wise.
            score_1 = mycourse.child_value('score_1')
            score_2 = mycourse.child_value('score_2')
            score_3 = mycourse.child_value('score_3')
            score_4 = mycourse.child_value('score_4')
            total = 0
            for score in [score_1, score_2, score_3, score_4]:
                if score is not None and score >= 0:
                    total = total + score

            oldtotal = (mycoursedict.get_int('score_1', 0) +
                        mycoursedict.get_int('score_2', 0) +
                        mycoursedict.get_int('score_3', 0) +
                        mycoursedict.get_int('score_4', 0))

            if total >= oldtotal:
                mycoursedict.replace_int('music_id_1',
                                         mycourse.child_value('music_id_1'))
                mycoursedict.replace_int('note_grade_1',
                                         mycourse.child_value('note_grade_1'))
                mycoursedict.replace_int('score_1', score_1)
                mycoursedict.replace_int('music_id_2',
                                         mycourse.child_value('music_id_2'))
                mycoursedict.replace_int('note_grade_2',
                                         mycourse.child_value('note_grade_2'))
                mycoursedict.replace_int('score_2', score_2)
                mycoursedict.replace_int('music_id_3',
                                         mycourse.child_value('music_id_3'))
                mycoursedict.replace_int('note_grade_3',
                                         mycourse.child_value('note_grade_3'))
                mycoursedict.replace_int('score_3', score_3)
                mycoursedict.replace_int('music_id_4',
                                         mycourse.child_value('music_id_4'))
                mycoursedict.replace_int('note_grade_4',
                                         mycourse.child_value('note_grade_4'))
                mycoursedict.replace_int('score_4', score_4)
                mycoursedict.replace_int('insert_time', Time.now())
        newprofile.replace_dict('mycourse', mycoursedict)

        # Keep track of play statistics
        self.update_play_statistics(userid)

        return newprofile
コード例 #22
0
ファイル: sunnypark.py プロジェクト: wolskiCN/bemaniutils
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        root = Node.void('playerdata')

        # Set up the base profile
        base = Node.void('base')
        root.add_child(base)
        base.add_child(Node.string('name', profile.get_str('name', 'なし')))
        base.add_child(
            Node.string('g_pm_id', ID.format_extid(profile.get_int('extid'))))
        base.add_child(Node.u8('mode', profile.get_int('mode', 0)))
        base.add_child(Node.s8('button', profile.get_int('button', 0)))
        base.add_child(
            Node.s8('last_play_flag', profile.get_int('last_play_flag', -1)))
        base.add_child(
            Node.u8('medal_and_friend', profile.get_int('medal_and_friend',
                                                        0)))
        base.add_child(Node.s8('category', profile.get_int('category', -1)))
        base.add_child(
            Node.s8('sub_category', profile.get_int('sub_category', -1)))
        base.add_child(Node.s16('chara', profile.get_int('chara', -1)))
        base.add_child(
            Node.s8('chara_category', profile.get_int('chara_category', -1)))
        base.add_child(Node.u8('collabo', 255))
        base.add_child(Node.u8('sheet', profile.get_int('sheet', 0)))
        base.add_child(Node.s8('tutorial', profile.get_int('tutorial', 0)))
        base.add_child(
            Node.s8('music_open_pt', profile.get_int('music_open_pt', 0)))
        base.add_child(Node.s8('is_conv', -1))
        base.add_child(Node.s32('option', profile.get_int('option', 0)))
        base.add_child(Node.s16('music', profile.get_int('music', -1)))
        base.add_child(Node.u16('ep', profile.get_int('ep', 0)))
        base.add_child(
            Node.s32_array('sp_color_flg',
                           profile.get_int_array('sp_color_flg', 2)))
        base.add_child(Node.s32('read_news', profile.get_int('read_news', 0)))
        base.add_child(
            Node.s16('consecutive_days_coupon',
                     profile.get_int('consecutive_days_coupon', 0)))
        base.add_child(Node.s8('staff', 0))
        # These are probably from an old event, but if they aren't present and defaulted,
        # then different songs show up in the Zoo event.
        base.add_child(
            Node.u16_array(
                'gitadora_point',
                profile.get_int_array('gitadora_point', 3,
                                      [2000, 2000, 2000])))
        base.add_child(
            Node.u8('gitadora_select', profile.get_int('gitadora_select', 2)))

        # Statistics section and scores section
        statistics = self.get_play_statistics(userid)
        last_play_date = statistics.get_int_array('last_play_date', 3)
        today_play_date = Time.todays_date()
        if (last_play_date[0] == today_play_date[0]
                and last_play_date[1] == today_play_date[1]
                and last_play_date[2] == today_play_date[2]):
            today_count = statistics.get_int('today_plays', 0)
        else:
            today_count = 0
        base.add_child(Node.u8('active_fr_num',
                               0))  # TODO: Hook up rivals code?
        base.add_child(
            Node.s32('total_play_cnt', statistics.get_int('total_plays', 0)))
        base.add_child(Node.s16('today_play_cnt', today_count))
        base.add_child(
            Node.s16('consecutive_days',
                     statistics.get_int('consecutive_days', 0)))

        last_played = [
            x[0] for x in self.data.local.music.get_last_played(
                self.game, self.version, userid, 3)
        ]
        most_played = [
            x[0] for x in self.data.local.music.get_most_played(
                self.game, self.version, userid, 20)
        ]
        while len(last_played) < 3:
            last_played.append(-1)
        while len(most_played) < 20:
            most_played.append(-1)

        hiscore_array = [0] * int(
            (((self.GAME_MAX_MUSIC_ID * 4) * 17) + 7) / 8)
        clear_medal = [0] * self.GAME_MAX_MUSIC_ID
        clear_medal_sub = [0] * self.GAME_MAX_MUSIC_ID

        scores = self.data.remote.music.get_scores(self.game, self.version,
                                                   userid)
        for score in scores:
            if score.id > self.GAME_MAX_MUSIC_ID:
                continue

            # Skip any scores for chart types we don't support
            if score.chart not in [
                    self.CHART_TYPE_EASY,
                    self.CHART_TYPE_NORMAL,
                    self.CHART_TYPE_HYPER,
                    self.CHART_TYPE_EX,
            ]:
                continue

            points = score.points
            medal = {
                self.PLAY_MEDAL_CIRCLE_FAILED:
                self.GAME_PLAY_MEDAL_CIRCLE_FAILED,
                self.PLAY_MEDAL_DIAMOND_FAILED:
                self.GAME_PLAY_MEDAL_DIAMOND_FAILED,
                self.PLAY_MEDAL_STAR_FAILED: self.GAME_PLAY_MEDAL_STAR_FAILED,
                self.PLAY_MEDAL_EASY_CLEAR:
                self.GAME_PLAY_MEDAL_CIRCLE_CLEARED,  # Map approximately
                self.PLAY_MEDAL_CIRCLE_CLEARED:
                self.GAME_PLAY_MEDAL_CIRCLE_CLEARED,
                self.PLAY_MEDAL_DIAMOND_CLEARED:
                self.GAME_PLAY_MEDAL_DIAMOND_CLEARED,
                self.PLAY_MEDAL_STAR_CLEARED:
                self.GAME_PLAY_MEDAL_STAR_CLEARED,
                self.PLAY_MEDAL_CIRCLE_FULL_COMBO:
                self.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO,
                self.PLAY_MEDAL_DIAMOND_FULL_COMBO:
                self.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO,
                self.PLAY_MEDAL_STAR_FULL_COMBO:
                self.GAME_PLAY_MEDAL_STAR_FULL_COMBO,
                self.PLAY_MEDAL_PERFECT: self.GAME_PLAY_MEDAL_PERFECT,
            }[score.data.get_int('medal')]
            clear_medal[score.id] = clear_medal[score.id] | (medal <<
                                                             (score.chart * 4))

            hiscore_index = (score.id * 4) + {
                self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY_POSITION,
                self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL_POSITION,
                self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER_POSITION,
                self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX_POSITION,
            }[score.chart]
            hiscore_byte_pos = int((hiscore_index * 17) / 8)
            hiscore_bit_pos = int((hiscore_index * 17) % 8)
            hiscore_value = points << hiscore_bit_pos
            hiscore_array[hiscore_byte_pos] = hiscore_array[
                hiscore_byte_pos] | (hiscore_value & 0xFF)
            hiscore_array[hiscore_byte_pos +
                          1] = hiscore_array[hiscore_byte_pos + 1] | (
                              (hiscore_value >> 8) & 0xFF)
            hiscore_array[hiscore_byte_pos +
                          2] = hiscore_array[hiscore_byte_pos + 2] | (
                              (hiscore_value >> 16) & 0xFF)

        hiscore = bytes(hiscore_array)

        base.add_child(Node.s16_array('my_best', most_played))
        base.add_child(Node.s16_array('latest_music', last_played))
        base.add_child(Node.u16_array('clear_medal', clear_medal))
        base.add_child(Node.u8_array('clear_medal_sub', clear_medal_sub))

        # Goes outside of base for some reason
        root.add_child(Node.binary('hiscore', hiscore))

        # Avatar section
        avatar_dict = profile.get_dict('avatar')
        avatar = Node.void('avatar')
        root.add_child(avatar)
        avatar.add_child(Node.u8('hair', avatar_dict.get_int('hair', 0)))
        avatar.add_child(Node.u8('face', avatar_dict.get_int('face', 0)))
        avatar.add_child(Node.u8('body', avatar_dict.get_int('body', 0)))
        avatar.add_child(Node.u8('effect', avatar_dict.get_int('effect', 0)))
        avatar.add_child(Node.u8('object', avatar_dict.get_int('object', 0)))
        avatar.add_child(
            Node.u8_array('comment', avatar_dict.get_int_array('comment', 2)))
        avatar.add_child(
            Node.s32_array('get_hair',
                           avatar_dict.get_int_array('get_hair', 2)))
        avatar.add_child(
            Node.s32_array('get_face',
                           avatar_dict.get_int_array('get_face', 2)))
        avatar.add_child(
            Node.s32_array('get_body',
                           avatar_dict.get_int_array('get_body', 2)))
        avatar.add_child(
            Node.s32_array('get_effect',
                           avatar_dict.get_int_array('get_effect', 2)))
        avatar.add_child(
            Node.s32_array('get_object',
                           avatar_dict.get_int_array('get_object', 2)))
        avatar.add_child(
            Node.s32_array('get_comment_over',
                           avatar_dict.get_int_array('get_comment_over', 3)))
        avatar.add_child(
            Node.s32_array('get_comment_under',
                           avatar_dict.get_int_array('get_comment_under', 3)))

        # Avatar add section
        avatar_add_dict = profile.get_dict('avatar_add')
        avatar_add = Node.void('avatar_add')
        root.add_child(avatar_add)
        avatar_add.add_child(
            Node.s32_array('get_hair',
                           avatar_add_dict.get_int_array('get_hair', 2)))
        avatar_add.add_child(
            Node.s32_array('get_face',
                           avatar_add_dict.get_int_array('get_face', 2)))
        avatar_add.add_child(
            Node.s32_array('get_body',
                           avatar_add_dict.get_int_array('get_body', 2)))
        avatar_add.add_child(
            Node.s32_array('get_effect',
                           avatar_add_dict.get_int_array('get_effect', 2)))
        avatar_add.add_child(
            Node.s32_array('get_object',
                           avatar_add_dict.get_int_array('get_object', 2)))
        avatar_add.add_child(
            Node.s32_array(
                'get_comment_over',
                avatar_add_dict.get_int_array('get_comment_over', 2)))
        avatar_add.add_child(
            Node.s32_array(
                'get_comment_under',
                avatar_add_dict.get_int_array('get_comment_under', 2)))
        avatar_add.add_child(
            Node.s32_array('new_hair',
                           avatar_add_dict.get_int_array('new_hair', 2)))
        avatar_add.add_child(
            Node.s32_array('new_face',
                           avatar_add_dict.get_int_array('new_face', 2)))
        avatar_add.add_child(
            Node.s32_array('new_body',
                           avatar_add_dict.get_int_array('new_body', 2)))
        avatar_add.add_child(
            Node.s32_array('new_effect',
                           avatar_add_dict.get_int_array('new_effect', 2)))
        avatar_add.add_child(
            Node.s32_array('new_object',
                           avatar_add_dict.get_int_array('new_object', 2)))
        avatar_add.add_child(
            Node.s32_array(
                'new_comment_over',
                avatar_add_dict.get_int_array('new_comment_over', 2)))
        avatar_add.add_child(
            Node.s32_array(
                'new_comment_under',
                avatar_add_dict.get_int_array('new_comment_under', 2)))

        # Net VS section
        netvs = Node.void('netvs')
        root.add_child(netvs)
        netvs.add_child(Node.s32('rank_point', 0))
        netvs.add_child(Node.s16_array('record', [0, 0, 0, 0, 0, 0]))
        netvs.add_child(Node.u8('rank', 0))
        netvs.add_child(Node.s8('vs_rank_old', 0))
        netvs.add_child(Node.s8_array('ojama_condition', [0] * 74))
        netvs.add_child(Node.s8_array('set_ojama', [0, 0, 0]))
        netvs.add_child(Node.s8_array('set_recommend', [0, 0, 0]))
        netvs.add_child(Node.u8('netvs_play_cnt', 0))
        for dialog in [0, 1, 2, 3, 4, 5]:
            # TODO: Configure this, maybe?
            netvs.add_child(Node.string('dialog', 'dialog#{}'.format(dialog)))

        sp_data = Node.void('sp_data')
        root.add_child(sp_data)
        sp_data.add_child(Node.s32('sp', profile.get_int('sp', 0)))

        gakuen = Node.void('gakuen_data')
        root.add_child(gakuen)
        gakuen.add_child(Node.s32('music_list', -1))

        saucer = Node.void('flying_saucer')
        root.add_child(saucer)
        saucer.add_child(Node.s32('music_list', -1))
        saucer.add_child(Node.s32('tune_count', -1))
        saucer.add_child(Node.u32('clear_norma', 0))
        saucer.add_child(Node.u32('clear_norma_add', 0))

        zoo_dict = profile.get_dict('zoo')
        zoo = Node.void('zoo')
        root.add_child(zoo)
        zoo.add_child(
            Node.u16_array('point', zoo_dict.get_int_array('point', 5)))
        zoo.add_child(
            Node.s32_array('music_list',
                           zoo_dict.get_int_array('music_list', 2)))
        zoo.add_child(
            Node.s8_array('today_play_flag',
                          zoo_dict.get_int_array('today_play_flag', 4)))

        triple = Node.void('triple_journey')
        root.add_child(triple)
        triple.add_child(Node.s32('music_list', -1))
        triple.add_child(
            Node.s32_array('boss_damage', [65534, 65534, 65534, 65534]))
        triple.add_child(Node.s32_array('boss_stun', [0, 0, 0, 0]))
        triple.add_child(Node.s32('magic_gauge', 0))
        triple.add_child(Node.s32('today_party', 0))
        triple.add_child(Node.bool('union_magic', False))
        triple.add_child(Node.float('base_attack_rate', 1.0))
        triple.add_child(Node.s32('iidx_play_num', 0))
        triple.add_child(Node.s32('reflec_play_num', 0))
        triple.add_child(Node.s32('voltex_play_num', 0))
        triple.add_child(Node.bool('iidx_play_flg', True))
        triple.add_child(Node.bool('reflec_play_flg', True))
        triple.add_child(Node.bool('voltex_play_flg', True))

        ios = Node.void('ios')
        root.add_child(ios)
        ios.add_child(Node.s32('continueRightAnswer', 30))
        ios.add_child(Node.s32('totalRightAnswer', 30))

        kac2013 = Node.void('kac2013')
        root.add_child(kac2013)
        kac2013.add_child(Node.s8('music_num', 0))
        kac2013.add_child(Node.s16('music', 0))
        kac2013.add_child(Node.u8('sheet', 0))

        baseball = Node.void('baseball_data')
        root.add_child(baseball)
        baseball.add_child(Node.s64('music_list', -1))

        for id in [3, 5, 7]:
            node = Node.void('floor_infection')
            root.add_child(node)
            node.add_child(Node.s32('infection_id', id))
            node.add_child(Node.s32('music_list', -1))

        return root
コード例 #23
0
ファイル: test_ID.py プロジェクト: vangar/bemaniutils
 def test_format_machine_id(self) -> None:
     self.assertEqual(ID.format_machine_id(123), 'US-123')
     self.assertEqual(ID.parse_machine_id('US-123'), 123)
     self.assertEqual(ID.parse_machine_id('bla'), None)
     self.assertEqual(ID.parse_machine_id('US-blah'), None)