示例#1
0
def do_reminders(game_id, dry_run = False):
    filename = SpinConfig.gamedata_component_filename('dev_reminders.json', override_game_id = game_id)
    if not os.path.exists(filename): return
    data = SpinConfig.load(filename)

    time_now = int(time.time())
    sender_name = data['sender']

    for reminder in data['reminders']:
        subject = 'Automated reminder from %s' % sender_name
        if reminder['body'] == '$XXX': # special case for six-X comments
            body = get_six_X_comments(game_id, time_now)
        else:
            body = 'Due %s %s' % (pretty_print_time(abs(reminder['deadline']-time_now)), 'from now' if reminder['deadline']>time_now else 'ago') + '\n' + reminder['body']

        if body:
            SpinReminders.send_reminders(sender_name, reminder['notify'], subject, body, dry_run = dry_run)
示例#2
0
        elif key == '--num-clusters':
            numclusters = int(val)
        elif key == '--num-sectors':
            num_sectors = int(val)
    if '--townhall-level' not in opts:
        townhall_level = int(baseDifficulty / 2)
        if townhall_level > 6:
            townhall_level = 6
    unitsInBaseCount = 0
    maxUnitsInBaseCount = gamedata['buildings']["toc"]["provides_space"][
        townhall_level - 1]
    # If you need to load an EXISTING base JSON file, here is how to do it:
    if len(args) > 1:
        filename = args[1]
        # SpinConfig.load reads JSON, and strips out comments
        old_base = SpinConfig.load(filename, stripped=True)
        # at this point, "old_base" will be a Python data structure (actually a dictionary)
        # that contains everything that was in the JSON file you loaded
        print old_base

    usedClusterXYpairs = []
    sceneryList = [
        name for name, data in gamedata['inert'].iteritems()
        if (("desert" in data.get('base_climates', [])) and (
            "home" in data.get('base_types', []))
            and data.get('auto_spawn', False))
    ]
    buildingsList = [
        name for name, data in gamedata['buildings'].iteritems()
        if (not data.get('developer_only', False))
    ]

if __name__ == '__main__':
    opts, args = getopt.gnu_getopt(sys.argv[1:], 'g:', [
        'game-id=',
    ])

    game_id = None
    for key, val in opts:
        if key == '--game-id' or key == '-g':
            game_id = val
    assert game_id

    # partial build of gamedata
    gamedata = {
        'predicate_library': SpinConfig.load(args[0]),
        'buildings': SpinConfig.load(args[1]),
        'tech': SpinConfig.load(args[2]),
        'crafting': SpinConfig.load(args[3])
    }

    out_fd = AtomicFileWrite.AtomicFileWrite(args[4],
                                             'w',
                                             ident=str(os.getpid()))

    print >> out_fd.fd, "// AUTO-GENERATED BY invert_requirements.py"

    # note pluralization of the keys - this matches what UpgradeBar expects
    requirements = {
        'building':
        prune_dict(
#!/usr/bin/env python

# Copyright (c) 2015 SpinPunch. All rights reserved.
# Use of this source code is governed by an MIT-style license that can be
# found in the LICENSE file.

import sys, os, time, getopt, re
import SpinJSON  # fast JSON library
import SpinConfig

quarries = SpinConfig.load(
    SpinConfig.gamedata_component_filename('quarries_compiled.json'))

time_now = int(time.time())


def metrics_log_iterator(filename):
    for line in open(filename).xreadlines():
        if '3830_battle_end' not in line:
            continue
        event = SpinJSON.loads(line)
        base_id = event.get('base_id', '')
        if (not base_id.startswith('q')):
            continue
        quarry_id = int(base_id[1:])
        yield quarry_id


def battle_log_dir_iterator(dirname):
    log_re = re.compile('^[0-9]+-[0-9]+-vs-[0-9]+-at-(.+).json.*$')
    for filename in os.listdir(dirname):
示例#5
0
if __name__ == '__main__':
    opts, args = getopt.gnu_getopt(sys.argv[1:], 'g:', [
        'game-id=',
    ])
    ident = str(os.getpid())

    game_id = None
    for key, val in opts:
        if key == '--game-id' or key == '-g':
            game_id = val
    assert game_id

    if game_id != 'mf':  # no mods except in old MF
        sys.exit(0)

    tech = SpinConfig.load(args[0], stripped=True)
    out_fd = AtomicFileWrite.AtomicFileWrite(args[1], 'w', ident=ident)

    print >> out_fd.fd, "// AUTO-GENERATED BY make_tech_mods.py"

    out = {}

    MOD_TYPES = [{
        'name': '_health',
        'ui_name': ' Health',
        'stat': 'max_hp',
        'method': '*=(1+strength)',
        'strength': [0.01, 0.02, 0.03, 0.04, 0.05],
        'ui_description':
        'Optimize defensive systems to withstand more damage',
        'ui_congrats': 'Defensive systems upgraded for more toughness'
示例#6
0
# Copyright (c) 2015 SpinPunch. All rights reserved.
# Use of this source code is governed by an MIT-style license that can be
# found in the LICENSE file.

# this script makes various procedurally-generated inventory items

import SpinConfig
import SpinJSON
import AtomicFileWrite
import sys, re, traceback, os, getopt

if __name__ == '__main__':
    opts, args = getopt.gnu_getopt(sys.argv[1:], '', [])
    ident = str(os.getpid())

    gamedata = {'resources': SpinConfig.load(args[0])}
    items_out = AtomicFileWrite.AtomicFileWrite(args[1], 'w', ident=ident)
    items_fd = items_out.fd
    spells_out = AtomicFileWrite.AtomicFileWrite(args[2], 'w', ident=ident)
    spells_fd = spells_out.fd

    for fd in items_fd, spells_fd:
        print >> fd, "// AUTO-GENERATED BY make_items_auto.py"

    out = {'items': [], 'spells': []}

    # create all iron/water items
    for resource, resdata in gamedata['resources'].iteritems():
        RESOURCE = resource.upper()

        # names seen by player
示例#7
0
import SpinJSON
import SpinNoSQL
import base64, lz4, SpinLZJB
import sys, time, getopt

if __name__ == '__main__':
    opts, args = getopt.gnu_getopt(sys.argv[1:], 'g:b:', [])
    game_id = SpinConfig.game()
    batch_size = None
    for key, val in opts:
        if key == '-g': game_id = val
        elif key == '-b': batch_size = int(val)

    gamedata = {}  # SpinJSON.load(open(SpinConfig.gamedata_filename()))
    gamedata['regions'] = SpinConfig.load(
        SpinConfig.gamedata_component_filename("regions.json",
                                               override_game_id=game_id))

    nosql_client = SpinNoSQL.NoSQLClient(
        SpinConfig.get_mongodb_config(SpinConfig.config['game_id']))
    TRIALS = 10
    region = None

    region_list = [name for name, data in sorted(gamedata['regions'].items()) if \
                   data.get('enable_map',1)]

    total_time = 0.0
    for region in region_list:
        start_time = time.time()

        db_time = -1
示例#8
0
            pat_ls.append(pat)

        pattern = '\\b(' + '|'.join(pat_ls) + ')\\b'
        flags = 0
        if 'i' in config['options']: flags |= re.I
        # no 'g' option, re is greedy by default
        self.bad_regex = re.compile(pattern, flags)

    def is_bad(self, input):
        return bool(self.bad_regex.search(input))

    def censor(self, input):
        return self.bad_regex.sub(lambda match: '*' * len(match.group()),
                                  input)


if __name__ == '__main__':
    import SpinConfig
    config = SpinConfig.load(
        SpinConfig.gamedata_component_filename('chat_filter.json'))
    cf = ChatFilter(config)
    TESTS = {
        'asdf': 'asdf',
        'sh!t': '****',
        'fu!ckers': '********',
        'dwarf shortage': 'dwarf shortage'
    }
    for input, expect in TESTS.iteritems():
        assert cf.censor(input) == expect
    print 'OK'
示例#9
0
# needs units.json as input for unit names

import SpinConfig
import SpinJSON
import AtomicFileWrite
import sys, getopt, os

if __name__ == '__main__':
    opts, args = getopt.gnu_getopt(sys.argv[1:], 'g:', ['game-id='])
    game_id = SpinConfig.game()

    for key, val in opts:
        # allow override of game_id
        if key == '-g' or key == '--game-id': game_id = val

    units = SpinConfig.load(args[0])
    out_fd = AtomicFileWrite.AtomicFileWrite(args[1],
                                             'w',
                                             ident=str(os.getpid()))

    print >> out_fd.fd, "// AUTO-GENERATED BY make_art_items.py"

    units = SpinConfig.load(args[0])

    out = {}
    outkeys = []

    # create unit inventory icons
    EXTRA_UNITS = []  # not included in units.json but icons are needed
    if game_id == 'tr':
        EXTRA_UNITS += [('ch47', {'art_asset': 'ch47'})]
def do_slave(task):
    date = task['date']
    game_id = task['game_id']
    verbose = task['verbose']
    dry_run = task['dry_run']

    start_time = SpinConfig.cal_to_unix(
        (int(date[0:4]), int(date[4:6]), int(date[6:8])))
    end_time = start_time + 86400

    if verbose:
        print >> sys.stderr, 'converting date', date, 'start_time', start_time, 'end_time', end_time, '...'

    # gamedata = SpinJSON.load(open(SpinConfig.gamedata_filename(override_game_id = game_id)))
    if not verbose: filterwarnings('ignore', category=MySQLdb.Warning)
    quarries = SpinConfig.load(
        SpinConfig.gamedata_component_filename('quarries_compiled.json'))
    hives = SpinConfig.load(
        SpinConfig.gamedata_component_filename('hives_compiled.json'))

    # ensure that the spawn list is ordered by id_start - necessary for find_template() below
    for spawn_list in quarries['spawn'], hives['spawn']:
        spawn_list.sort(key=lambda x: x['id_start'])

    cfg = SpinConfig.get_mysql_config(game_id + '_upcache')
    con = MySQLdb.connect(*cfg['connect_args'], **cfg['connect_kwargs'])
    battles_table = cfg['table_prefix'] + game_id + '_battles'

    if 0:
        # find any already-converted battles
        cur = con.cursor()
        cur.execute(
            "SELECT COUNT(*) FROM %s WHERE time >= %%s and time < %%s" %
            battles_table, (start_time, end_time))
        row = cur.fetchone()
        con.commit()
        if row and row[0] > 0:
            print >> sys.stderr, 'there are already', row[
                0], 'entries in this time range, aborting!'
            return

    s3 = SpinS3.S3(SpinConfig.aws_key_file())
    bucket = 'spinpunch-%sprod-battle-logs' % game_id

    for entry in s3.list_bucket(bucket,
                                prefix='%s-battles-%s/%s' %
                                (game_id, date[0:6], date)):
        filename = entry['name'].split('/')[-1]
        event_time, attacker_id, defender_id, base_id = parse_battle_log_filename(
            filename)
        if (not base_id) or event_time < start_time or event_time >= end_time:
            continue
        if base_id[0] != 'v': continue  # only look at hives

        print >> sys.stderr, event_time, SpinLog.pretty_time(
            time.gmtime(event_time)), filename
        fd = s3.get_open(bucket, entry['name'], allow_keepalive=False)
        unzipper = subprocess.Popen(['gunzip', '-c', '-'],
                                    stdin=fd.fileno(),
                                    stdout=subprocess.PIPE)
        battle_start = None
        battle_end = None
        for line in unzipper.stdout.xreadlines():
            if '3820_battle_start' in line:
                battle_start = SpinJSON.loads(line)
            elif '3830_battle_end' in line:
                battle_end = SpinJSON.loads(line)
        if (not battle_start) or (not battle_end): continue

        base_template = find_template(hives['spawn'], int(base_id[1:]))
        if not base_template:
            sys.stderr.write('unknown hive %s\n' % base_id)
            continue

        # generate a fake summary
        summary = {
            'time':
            event_time,
            'attacker_id':
            battle_start['attacker_user_id'],
            'attacker_level':
            battle_start['attacker_level'],
            'attacker_outcome':
            battle_end['battle_outcome'],
            'defender_id':
            battle_start['opponent_user_id'],
            'defender_level':
            battle_start['opponent_level'],
            'defender_outcome':
            'victory'
            if battle_end['battle_outcome'] == 'defeat' else 'defeat',
            'base_damage':
            battle_end['base_damage'],
            'base_id':
            battle_start['base_id'],
            'base_type':
            'hive',
            'base_template':
            base_template,
            'loot':
            battle_end['loot']
        }

        cur = con.cursor()
        cur.execute(
            "SELECT battle_id FROM %s WHERE time = %%s and attacker_id = %%s and defender_id = %%s"
            % battles_table, (event_time, battle_start['attacker_user_id'],
                              battle_start['opponent_user_id']))
        row = cur.fetchone()
        con.commit()
        if row:
            sys.stderr.write('appears to be a duplicate, skipping!\n')
            continue

        id_generator.set_time(int(time.time()))
        battle_id = id_generator.generate()  # arbitrary

        keys = [
            'battle_id',
        ]
        values = [
            battle_id,
        ]

        for kname, ktype in battle_fields.iteritems():
            path = kname.split(':')
            probe = summary
            val = None
            for i in xrange(len(path)):
                if path[i] not in probe:
                    break
                elif i == len(path) - 1:
                    val = probe[path[i]]
                    break
                else:
                    probe = probe[path[i]]

            if val is not None:
                keys.append(kname)
                values.append(val)

        query = "INSERT INTO " + battles_table + \
                    "("+', '.join(['`'+x+'`' for x in keys])+")"+ \
                    " VALUES ("+', '.join(['%s'] * len(values)) +")"
        print >> sys.stderr, query
        print >> sys.stderr, values

        if not dry_run:
            cur = con.cursor()
            cur.execute(query, values)
            con.commit()
    elif hours > 0:
        if minutes > 0:
            return '%.1fh' % (float(duration % 86400) / 3600)
        else:
            return '%dh' % hours
    elif minutes > 0:
        return '%dm' % minutes
    else:
        return ''

if __name__ == '__main__':
    opts, args = getopt.gnu_getopt(sys.argv[1:], '', [])
    ident = str(os.getpid())

    # read unit data
    gamedata = {'units': SpinConfig.load(args[0])}
    out_fd = AtomicFileWrite.AtomicFileWrite(args[1], 'w', ident=ident)

    # provide special behaviour for unit-type boosts
    unit_types = {'rover': {'name': 'rover', 'ui_name': 'Infantry', 'ui_name_plural': 'infantry'},
                  'transport': {'name': 'transport', 'ui_name': 'Armor', 'ui_name_plural': 'armored units'},
                  'starcraft': {'name': 'starcraft', 'ui_name': 'Aircraft', 'ui_name_plural': 'aircraft'}}

    # templates for different boost types and their properties
    boost_types = {'damage': {'name': '{unit[name]}_damage_boost_{pct}pct{name_duration}', 'ui_name': '{pct}% {unit[ui_name]} Damage Boost ({ui_name_duration})',
                              'ui_description': 'Activate to increase damage done by your {unit[ui_name_plural]} by {pct}%. Lasts {ui_description_duration}.',
                              'icon': 'inventory_damage_{unit[name]}_{icon_color}', 'aura': '{unit[name]}_damage_boosted'},
                   'damage_resist': {'name': '{unit[name]}_damage_resist_boost_{pct}pct{name_duration}', 'ui_name': '{pct}% {unit[ui_name]} Toughness Boost ({ui_name_duration})',
                                    'ui_description': 'Activate to reduce damage taken by your {unit[ui_name_plural]} by {pct}%. Lasts {ui_description_duration}.',
                                    'icon': 'inventory_armor_{unit[name]}_{icon_color}', 'aura': '{unit[name]}_damage_resist_boosted'},
                   'range': {'name': '{unit[name]}_range_boost_{pct}pct{name_duration}', 'ui_name': '{pct}% {unit[ui_name]} Range Boost ({ui_name_duration})',
if __name__ == '__main__':
    opts, args = getopt.gnu_getopt(sys.argv[1:], 'g:', [
        'game-id=',
    ])

    game_id = None
    for key, val in opts:
        if key == '--game-id' or key == '-g':
            game_id = val
    assert game_id

    if game_id != 'mf':  # no mods except in old MF
        sys.exit(0)

    gamedata = SpinConfig.load(args[0],
                               stripped=True)  # main_options.json only
    tech = SpinConfig.load(args[1], stripped=True)
    out_fd = AtomicFileWrite.AtomicFileWrite(args[2],
                                             'w',
                                             ident=str(os.getpid()))

    print >> out_fd.fd, "// AUTO-GENERATED BY make_tech_mod_quests.py"

    out = {}

    VALUES = [
        {
            'name':
            'health',
            'ui_name':
            'Health',
#!/usr/bin/env python

# Copyright (c) 2015 SpinPunch. All rights reserved.
# Use of this source code is governed by an MIT-style license that can be
# found in the LICENSE file.

# load some standard Python libraries
import sys, urllib, urllib2, getopt, socket
import SpinConfig
import SpinFacebook

# just load achievements.json, not all of gamedata, so we can populate before running make-gamedata.sh
gamedata = {
    'achievements':
    SpinConfig.load(
        SpinConfig.gamedata_component_filename('achievements.json'))
}


def get_endpoint_url(params):
    port = SpinConfig.config['proxyserver']['external_http_port']
    port_str = (':%d' % port) if port != 80 else ''
    # note: use stable ordering of key/value pairs for the query string, so that the canonical URL is deterministic
    qs = urllib.urlencode(sorted(params.items(), key=lambda k_v: k_v[0]))
    return ("http://%s%s/OGPAPI?" % (SpinConfig.config['proxyserver'].get(
        'external_host', socket.gethostname()), port_str)) + qs


if __name__ == '__main__':
    opts, args = getopt.gnu_getopt(sys.argv[1:], '', ['dry-run'])
    dry_run = False
示例#14
0
#!/usr/bin/env python

# Copyright (c) 2015 SpinPunch. All rights reserved.
# Use of this source code is governed by an MIT-style license that can be
# found in the LICENSE file.

# obsolete AI base analytics tool

import SpinJSON
import SpinConfig
import sys, os, glob, re, gzip, traceback

gamedata = SpinJSON.load(open(SpinConfig.gamedata_filename()))
gamedata['ai_bases'] = SpinConfig.load(
    SpinConfig.gamedata_component_filename("ai_bases_compiled.json"))

ai_ids = sorted(map(int, gamedata['ai_bases']['bases'].keys()))
ai_id_set = set(ai_ids)


def get_leveled_quantity(qty, level):
    if type(qty) == list:
        return qty[level - 1]
    return qty


def check_bad_units():
    for id in ai_ids:
        base = gamedata['ai_bases']['bases'][str(id)]
        level = base['resources']['player_level']