示例#1
0
def check_materials(np):
    #print('Plushie Tycoon: Checking on materials.')
    np.get(path_materials)
    material_prices = []
    material_owned = []
    buy_links = []
    accessories_owned = defaultdict(int)
    for cat in range(0, 4):
        np.get(path_materials, f'Cat={cat}')
        tbl = np.search(r"<table width='80%'.*?>(.*?)</table>")[1]
        rows = lib.table_to_tuples(tbl, raw=True)

        material_prices.append([amt(x) for x in rows[-1]])
        if len(rows[-3]) > 1:
            material_owned.append([amt(x) for x in rows[-3]])
        else:
            material_owned.append([0, 0, 0, 0])

        links = []
        for link_text in rows[1]:
            links.append(re.search(r"onClick=buying\('(.*?)',", link_text)[1])
        buy_links.append(links)

        if cat == 2 and np.contains("table  width='80%'"):
            tbl2 = np.search(r"<table  width='80%' .*?>(.*?)</table>")[1]
            rows = lib.table_to_tuples(tbl2)[2:]
            for s, quant, kind, _ in rows:
                if quant:
                    accessories_owned[s] += amt(quant)
    return material_prices, material_owned, accessories_owned, buy_links
示例#2
0
def check_materials(np):
    #print('Plushie Tycoon: Checking on materials.')
    np.get(path_materials)
    material_prices = []
    material_owned = []
    buy_links = []
    accessories_owned = defaultdict(int)
    for cat in range(0, 4):
        np.get(path_materials, f'Cat={cat}')
        tbl = np.search(r"<table width='80%'.*?>(.*?)</table>")[1]
        rows = lib.table_to_tuples(tbl, raw=True)

        material_prices.append([amt(x) for x in rows[-1]])
        if len(rows[-3]) > 1:
            material_owned.append([amt(x) for x in rows[-3]])
        else:
            material_owned.append([0, 0, 0, 0])

        links = []
        for link_text in rows[1]:
            links.append(re.search(r"onClick=buying\('(.*?)',", link_text)[1])
        buy_links.append(links)

        if cat == 2 and np.contains("table  width='80%'"):
            tbl2 = np.search(r"<table  width='80%' .*?>(.*?)</table>")[1]
            rows = lib.table_to_tuples(tbl2)[2:]
            for s, quant, kind, _ in rows:
                if quant:
                    accessories_owned[s] += amt(quant)
    return material_prices, material_owned, accessories_owned, buy_links
示例#3
0
def check_store(np):
    #print('Plushie Tycoon: Checking on store.')
    species_stats = {}
    np.get(path_store)
    np.get(path_store, 'Cat=0', 'invent=2')
    tbl = np.search(r"<table width='75%'.*?>(.*?)</table>")
    inv = []
    past_sales = []
    if tbl:
        tbl = tbl[1]
        inv = lib.table_to_tuples(tbl)[1:]
        plushies_to_sell = sum(int(x[1]) - int(x[4]) for x in inv)
        jobs_to_sell = len(inv)
    else:
        plushies_to_sell = 0
        jobs_to_sell = 0
    print(
        f'Plushie Tycoon: Store has {plushies_to_sell} plushies over {jobs_to_sell} jobs left to sell.'
    )
    np.get(path_store, 'Cat=0', 'invent=1')
    tbl = np.search(r"<table width='75%'.*?>(.*?)</table>")
    if tbl:
        tbl = tbl[1]
        past_sales = lib.table_to_tuples(tbl)[1:]
    # TODO: Is inv in the correct order?
    prices = defaultdict(list)
    for row in past_sales + inv:
        species = row[0]
        price = int(row[2])
        prices[species].append(price)
    for species in prices.keys():
        ps = prices[species]
        n = len(ps)
        last = ps[-1]
        avg = sum(ps) / n
        stdev = (sum((p - avg)**2 for p in ps) / n)**0.5
        species_stats[species] = {
            'n': n,
            'last': last,
            'min': min(ps),
            'max': max(ps),
            'avg': avg,
            'med': ps[len(ps) // 2],
            'stdev': stdev,
        }
    #np.get(path_store, 'Cat=2')
    #size = int(np.search(r'You now have a size (\d+) store')[1])
    return species_stats
示例#4
0
def check_store(np):
    #print('Plushie Tycoon: Checking on store.')
    species_stats = {}
    np.get(path_store)
    np.get(path_store, 'Cat=0', 'invent=2')
    tbl = np.search(r"<table width='75%'.*?>(.*?)</table>")
    inv = []
    past_sales = []
    if tbl:
        tbl = tbl[1]
        inv = lib.table_to_tuples(tbl)[1:]
        plushies_to_sell = sum(int(x[1]) - int(x[4]) for x in inv)
        jobs_to_sell = len(inv)
    else:
        plushies_to_sell = 0
        jobs_to_sell = 0
    print(f'Plushie Tycoon: Store has {plushies_to_sell} plushies over {jobs_to_sell} jobs left to sell.')
    np.get(path_store, 'Cat=0', 'invent=1')
    tbl = np.search(r"<table width='75%'.*?>(.*?)</table>")
    if tbl:
        tbl = tbl[1]
        past_sales = lib.table_to_tuples(tbl)[1:]
    # TODO: Is inv in the correct order?
    prices = defaultdict(list)
    for row in past_sales + inv:
        species = row[0]
        price = int(row[2])
        prices[species].append(price)
    for species in prices.keys():
        ps = prices[species]
        n = len(ps)
        last = ps[-1]
        avg = sum(ps) / n
        stdev = (sum((p - avg)**2 for p in ps) / n)**0.5
        species_stats[species] = {
            'n': n,
            'last': last,
            'min': min(ps),
            'max': max(ps),
            'avg': avg,
            'med': ps[len(ps) // 2],
            'stdev': stdev,
        }
    #np.get(path_store, 'Cat=2')
    #size = int(np.search(r'You now have a size (\d+) store')[1])
    return species_stats
示例#5
0
def check_factory(np, hire=False):
    # Check status of jobs.
    # If less than 500 plushies remain, fire all workers.
    # Else, hire up to 250 Trainees and 25 Managers.
    #print('Plushie Tycoon: Checking on factory.')
    np.get(path_factory, 'exist=1')
    tbl = np.search(r"<table border='0' width='70%'.*?>(.*?)</table>")[1]
    jobs = lib.table_to_tuples(tbl)[1:-1]
    num_factory_jobs = len(jobs)
    num_plushies = sum(int(total) - int(done) for pet, total, done in jobs)
    print(
        f'Plushie Tycoon: Factory has {num_plushies} plushies in {num_factory_jobs} jobs.'
    )
    if hire:
        if num_plushies > 400 or num_factory_jobs >= 5:
            np.get(path_factory, 'personnel=1')
            if np.contains('many unemployed pets'):
                # Use the default workforce
                np.get(path_factory, 'set_def=2', 'personnel=1')
                print('Plushie Tycoon: Hired the default workforce.')
                # TODO: Calculate a good workforce and hire it.
                #np.get(path_factory, 'personnel=2', 'hire=1')
                #np.get(path_workers_hire, 'worker=2')
                #np.post(path_process_hire, 'amt=250', 'worker=2')
                #np.get(path_workers_hire, 'worker=4')
                #np.post(path_process_hire, 'amt=10', 'worker=4')
                #np.get(path_workers_hire, 'worker=4')
                #np.post(path_process_hire, 'amt=10', 'worker=4')
                #np.get(path_workers_hire, 'worker=4')
                #np.post(path_process_hire, 'amt=4', 'worker=4')
                #print('Plushie Tycoon: Hired up to 250 Trainees and 25 Managers.')
            else:
                print('Plushie Tycoon: Already have workers.')
        else:
            np.get(path_factory, 'personnel=1')
            if np.contains('factory.phtml?personnel=2&fire=1'):
                np.get(path_factory, 'personnel=2', 'fire=1')
                if np.contains('fire_all=1'):
                    np.get(path_factory, 'fire_all=1')
                    print('Plushie Tycoon: Fired all workers.')
            else:
                print('Plushie Tycoon: Already fired all workers.')
    return num_factory_jobs
示例#6
0
def check_factory(np, hire=False):
    # Check status of jobs.
    # If less than 500 plushies remain, fire all workers.
    # Else, hire up to 250 Trainees and 25 Managers.
    #print('Plushie Tycoon: Checking on factory.')
    np.get(path_factory, 'exist=1')
    tbl = np.search(r"<table border='0' width='70%'.*?>(.*?)</table>")[1]
    jobs = lib.table_to_tuples(tbl)[1:-1]
    num_factory_jobs = len(jobs)
    num_plushies = sum(int(total) - int(done) for pet, total, done in jobs)
    print(f'Plushie Tycoon: Factory has {num_plushies} plushies in {num_factory_jobs} jobs.')
    if hire:
        if num_plushies > 400 or num_factory_jobs >= 5:
            np.get(path_factory, 'personnel=1')
            if np.contains('many unemployed pets'):
                # Use the default workforce
                np.get(path_factory, 'set_def=2', 'personnel=1')
                print('Plushie Tycoon: Hired the default workforce.')
                # TODO: Calculate a good workforce and hire it.
                #np.get(path_factory, 'personnel=2', 'hire=1')
                #np.get(path_workers_hire, 'worker=2')
                #np.post(path_process_hire, 'amt=250', 'worker=2')
                #np.get(path_workers_hire, 'worker=4')
                #np.post(path_process_hire, 'amt=10', 'worker=4')
                #np.get(path_workers_hire, 'worker=4')
                #np.post(path_process_hire, 'amt=10', 'worker=4')
                #np.get(path_workers_hire, 'worker=4')
                #np.post(path_process_hire, 'amt=4', 'worker=4')
                #print('Plushie Tycoon: Hired up to 250 Trainees and 25 Managers.')
            else:
                print('Plushie Tycoon: Already have workers.')
        else:
            np.get(path_factory, 'personnel=1')
            if np.contains('factory.phtml?personnel=2&fire=1'):
                np.get(path_factory, 'personnel=2', 'fire=1')
                if np.contains('fire_all=1'):
                    np.get(path_factory, 'fire_all=1')
                    print('Plushie Tycoon: Fired all workers.')
            else:
                print('Plushie Tycoon: Already fired all workers.')
    return num_factory_jobs
示例#7
0
def check_warehouse(np):
    #print('Plushie Tycoon: Checking on warehouse.')
    np.get(path_warehouse)
    tbl = np.search(r"<table border='0' width='90%'.*?>(.*?)</table>")[1]
    to_ship = lib.table_to_tuples(tbl, raw=True)[2:-2]
    if to_ship:
        print(f'Plushie Tycoon: Warehouse is loading {len(to_ship)} jobs.')
    args = []
    for row in to_ship:
        status = row[4]
        if status == 'Loaded':
            chkbox = row[5]
            result = re.search(r"name='(.*?)' value='(.*?)'", chkbox)
            name = result[1]
            value = result[2]
            args.append(f'{name}={value}')
    if args:
        # TODO: Only ship items to the store if it is advantageous.
        # (tax situations?)
        print(f'Plushie Tycoon: Shipping {len(args)} jobs to the store.')
        args.append('submit=Ship Plushies')
        np.post(path_warehouse, *args)
示例#8
0
def check_warehouse(np):
    #print('Plushie Tycoon: Checking on warehouse.')
    np.get(path_warehouse)
    tbl = np.search(r"<table border='0' width='90%'.*?>(.*?)</table>")[1]
    to_ship = lib.table_to_tuples(tbl, raw=True)[2:-2]
    if to_ship:
        print(f'Plushie Tycoon: Warehouse is loading {len(to_ship)} jobs.')
    args = []
    for row in to_ship:
        status = row[4]
        if status == 'Loaded':
            chkbox = row[5]
            result = re.search(r"name='(.*?)' value='(.*?)'", chkbox)
            name = result[1]
            value = result[2]
            args.append(f'{name}={value}')
    if args:
        # TODO: Only ship items to the store if it is advantageous.
        # (tax situations?)
        print(f'Plushie Tycoon: Shipping {len(args)} jobs to the store.')
        args.append('submit=Ship Plushies')
        np.post(path_warehouse, *args)
示例#9
0
def update_prices(item_name, laxness=1):
    char_groups = 'an0 bo1 cp2 dq3 er4 fs5 gt6 hu7 iv8 jw9 kx_ ly mz'.split()
    c2g = dict(sum(([(c, i) for c in cs] for i, cs in enumerate(char_groups)), []))
    markets = defaultdict(dict)
    ub_count = 0
    search_count = 0

    np = NeoPage('/market.phtml?type=wizard')
    opts = []
    opts.append('type=process_wizard')
    opts.append('feedset=0')
    opts.append(f'shopwizard={item_name}')
    opts.append('table=shop')
    opts.append('criteria=exact')
    opts.append('min_price=0')
    opts.append('max_price=999999')

    # Repeatedly search the shop wizard, collecting all results seen.
    while not markets or any(len(market_data) < len(char_groups) - laxness for market_data in markets.values()):
        print(f'\r({sum(len(md) for md in markets.values())}/{len(markets) * len(char_groups)}) ', end='')
        np.post('/market.phtml', *opts)
        tbl = np.search(r'<table width="600".*?>(.*?)</table>')
        if not tbl:
            if np.contains('Whoa there, too many'):
                print('Shop wizard banned.')
                raise ShopWizardBannedException
            ub_count += 1
            if ub_count >= 5: break
            continue
        tbl = tbl[1]
        rows = lib.table_to_tuples(tbl, raw=True)[1:]
        search_count += 1
        if search_count >= 50: break
        market_data = []
        obj_info_id = None
        for owner, item, stock, price in rows:
            result = re.search(r'<a href="(.*?)"><b>(.*?)</b></a>', owner)
            link = result[1]
            owner = result[2]
            result = re.search(r'/browseshop.phtml\?owner=(.*?)&buy_obj_info_id=(.*?)&buy_cost_neopoints=(\d+)', link)
            obj_info_id = int(result[2])
            price = lib.amt(lib.strip_tags(price))
            stock = lib.amt(stock)
            market_data.append((price, stock, link))
        g = c2g[lib.strip_tags(rows[0][0])[0]]
        markets[obj_info_id][g] = market_data

    level2_by_item = {}
    # Consolidate results for each item into a quote.

    if markets:
        for obj_info_id, market_data in markets.items():
            # TODO: Check suspiciously cheap prices to see if owners are frozen.
            level2 = sorted(sum(market_data.values(), []))
            level2_by_item[obj_info_id] = level2
            # The price of an item for our purposes is the price of the 2nd
            # cheapest item in the market.
            cur_amt = 0
            cur_price = UNBUYABLE_PRICE
            for price, stock, link in level2:
                cur_price = price
                cur_amt += stock
                if cur_amt >= 2:
                    break
            print(f'The price of {item_name} (id {obj_info_id}) is {cur_price} NP.')
            cur_amt = 0
            for price, stock, link in level2:
                cur_amt += stock
                if cur_amt >= 30:
                    break
            c = conn.cursor()
            c.execute('''
            SELECT name FROM items WHERE obj_info_id=?
            ''', (obj_info_id,))
            result = c.fetchone()
            if not result or result[0][0] != item_name:
                for market_data in level2:
                    # Visit the shop and populate a bunch of fields
                    np.get(market_data[2])
                    res = np.search(r'''<A href=".*?" onClick=".*?"><img src="http://images.neopets.com/items/(.*?)" .*? title="(.*?)" border="1"></a> <br> <b>(.*?)</b>''')
                    if not res:
                        print(f'{market_data[2]} is froze?')
                        continue
                    image = res[1]
                    desc = res[2]
                    name = res[3]
                    c.execute('''
                    INSERT INTO items (name, image, desc, obj_info_id, last_updated)
                    VALUES (?, ?, ?, ?, datetime('now'))
                    ON CONFLICT (name, image)
                    DO UPDATE SET desc=?, obj_info_id=?, last_updated=datetime('now')
                    ''', (name, image, desc, obj_info_id, desc, obj_info_id))
                    print(f'The object id of {name} is {obj_info_id}')
                    break
                else:
                    print('Unable to find legit seller for {obj_info_id}. Will not store it in itemdb.')
                    continue
            c.execute('''
            UPDATE items SET price=?, price_last_updated=datetime('now') WHERE obj_info_id=?
            ''', (cur_price, obj_info_id))
    else:
        print(f'It seems {item_name} is unbuyable.')
        # Item could not be found; assume it's unbuyable.
        # We use a cheap price estimate of 1,000,001 NP.
        # TODO: Items inserted in this way will have a wonky image property.
        c = conn.cursor()
        c.execute('''
        INSERT INTO items (name, image, last_updated, price, price_last_updated)
        VALUES (?, NULL, datetime('now'), 1000001, datetime('now'))
        ON CONFLICT (name, image)
        DO UPDATE SET last_updated=datetime('now'), price=1000001, price_last_updated=datetime('now')
        ''', (item_name,))

    conn.commit()
    return level2_by_item
示例#10
0
def update_prices(item_name, laxness=5):
    now = datetime.now()
    if g.last_ban and (now - last_ban < timedelta(minutes=1) or (now - last_ban < timedelta(hours=1) and now.hour == last_ban.hour)):
        print('Still wiz banned.')
        raise ShopWizardBannedException

    char_groups = 'an0 bo1 cp2 dq3 er4 fs5 gt6 hu7 iv8 jw9 kx_ ly mz'.split()
    c2grp = dict(sum(([(c, i) for c in cs] for i, cs in enumerate(char_groups)), []))
    obj_info_ids = set()
    ub_count = 0
    search_count = 0
    lowest_price = UNBUYABLE_PRICE

    np = NeoPage('/market.phtml?type=wizard')
    opts = []
    opts.append('type=process_wizard')
    opts.append('feedset=0')
    opts.append(f'shopwizard={item_name}')
    opts.append('table=shop')
    opts.append('criteria=exact')
    opts.append('min_price=0')
    opts.append('max_price=999999')

    grps_needed = len(char_groups) - laxness

    def print_status():
        found = sum(min(grps_needed, len(g.markets[i])) for i in obj_info_ids)
        total = len(obj_info_ids) * grps_needed
        print(f'\r({item_name}: {lowest_price} NP; {found}/{total}; {search_count}) ', end='')

    # Repeatedly search the shop wizard, collecting all results seen.
    try:
        while not obj_info_ids or any(len(g.markets[i]) < grps_needed for i in obj_info_ids):
            print_status()
            np.post('/market.phtml', *opts)
            if np.contains('Whoa there, too many'):
                print('Shop wizard banned.')
                last_ban = datetime.now()
                raise ShopWizardBannedException

            search_count += 1
            if not '<table width="600"' in np.content:
                ub_count += 1
                if ub_count >= 15: break
                continue

            tbl = np.search(r'<table width="600".*?>(.*?)</table>')
            tbl = tbl[1]
            rows = lib.table_to_tuples(tbl, raw=True)[1:]
            market_data = []
            obj_info_id = None
            for owner, item, stock, price in rows:
                result = re.search(r'<a href="(.*?)"><b>(.*?)</b></a>', owner)
                link = result[1]
                owner = result[2]
                result = re.search(r'/browseshop.phtml\?owner=(.*?)&buy_obj_info_id=(.*?)&buy_cost_neopoints=(\d+)', link)
                obj_info_id = int(result[2])
                price = lib.amt(lib.strip_tags(price))
                stock = lib.amt(stock)
                market_data.append((price, stock, link))
                lowest_price = min(lowest_price, price)

            obj_info_ids.add(obj_info_id)
            grp = c2grp[lib.strip_tags(rows[0][0])[0]]
            g.markets[obj_info_id][grp] = market_data
            if search_count >= 30 * max(1, len(obj_info_ids)): break
    except KeyboardInterrupt:
        laxness = len(char_groups) - min(len(g.markets[i]) for i in obj_info_ids) if obj_info_ids else 0
        print(f'Interrupted. Actual laxness is {laxness}')

    print_status()

    # Consolidate results for each item into a quote.
    if obj_info_ids:
        for obj_info_id in obj_info_ids:
            level2 = sorted(sum(g.markets[obj_info_id].values(), []))
            g.level2_cache[obj_info_id] = level2

            cur_amt = 0
            cur_price = 0
            image, desc, name = None, None, None

            # The price of an item for our purposes is the cheapest price such
            # that:
            # - it is the second cheapest price, OR
            # - the next cheapest is at most 10% more expensive.
            print()
            if len(obj_info_ids) > 1:
                print(f'({obj_info_id}):')
            for price, stock, link in level2:
                # Our own prices don't count for pricing purposes
                if f'owner={os.environ.get("NP_USER")}' in link:
                    print('Skipping our own shop')
                    continue
                np.get(link)
                res = np.search(r'''<A href=".*?" onClick=".*?"><img src="http://images.neopets.com/items/(.*?)" .*? title="(.*?)" border="1"></a> <br> <b>(.*?)</b>''')
                if not res:
                    print(f'{link} is frozen?')
                    continue
                image, desc, name = res[1], res[2], res[3]
                print(f'{link} has {stock}')
                if price < cur_price * 1.1:
                    break
                cur_price = price
                if stock >= 2:
                    break
                cur_amt += stock
                if cur_amt >= 2:
                    break
            else:
                print(f'Unable to find enough sellers for {obj_info_id}. Assuming unbuyable.')
                cur_price = UNBUYABLE_PRICE

            print(f'The price of {item_name} (id {obj_info_id}) is {cur_price} NP.')

            for _ in range(2):
                try:
                    update_item(name, image=image, desc=desc,
                            obj_info_id=obj_info_id, price=cur_price,
                            price_laxness=laxness)
                    break
                except sqlite3.IntegrityError:
                    # TODO: IDK how we end up with bad obj_info_ids
                    c = conn.cursor()
                    c.execute('''DELETE FROM items WHERE obj_info_id = ?''', (obj_info_id,))
    else:
        print(f'It seems {item_name} is unbuyable.')
        # Item could not be found; assume it's unbuyable.
        # We use a cheap price estimate of 1,000,001 NP.
        # TODO: Items inserted in this way will have a wonky image property
        # since we have no way to look up their image.

        update_item(item_name, price=1000001, price_laxness=laxness)

    conn.commit()