pymerc


Namepymerc JSON
Version 0.6.0 PyPI version JSON
download
home_pagehttps://github.com/jmgilman/pymerc
SummaryA Python library for interacting with the Mercatorio browser based game
upload_time2024-06-02 19:21:48
maintainerNone
docs_urlNone
authorJoshua Gilman
requires_python<4.0,>=3.11
licenseMIT
keywords mercatorio python library game
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Pymerc

> A Python library for interacting with the [Mercatorio] browser based game

## Usage

You must first [generate API credentials](https://play.mercatorio.io/settings/api).
Once generated, you can instantiate a `Client` instance using the credentials.

```python
from pymerc.client import Client

# Create a new client
client = Client(os.environ["API_USER"], os.environ["API_TOKEN"])
```

### Game Objects

The `pymerc` package provides both low-level API calls as well as high-level objects that wrap those calls.
In almost all cases, you should plan to use the higher-level objects.
If something is missing in one of these objects, please submit an issue or PR.

Most logic is contained within the `Player` object:

```python
player = await client.player()
```

Creating the player object can take a few seconds as it results in several requests being sent to the API.
It's recommended you re-use the player object instead of recreating it multiple times.
The data for the player object can be updated with:

```python
await player.load()
```

#### Storehouse

Check our balance of beer and then buy some from the local market:

```python
>>> from pymerc.api.models.common import Item
>>> beer = player.storehouse.items[Item.Beer]
>>> beer.balance
41.5
>>> beer.market_data
TownMarketItem(price=2.894, last_price=2.894, average_price=2.894, moving_average=2.868, highest_bid=2.894, lowest_ask=3.0, volume=95, volume_prev_12=1085, bid_volume_10=2, ask_volume_10=20)
>>> details = await beer.fetch_market_details()  # More fine-grained details
>>> details.asks
[ItemOrder(volume=20, price=3.0),
 ItemOrder(volume=1, price=3.425),
 ItemOrder(volume=3, price=3.475),
 ItemOrder(volume=1, price=3.526)]
>>> result = await beer.buy(1, 3.0)
>>> result.settlements[0].volume
1
```

Adjust the price and volume of beer we are selling:

```python
>>> beer.manager
InventoryManager(buy_price=5.45, buy_volume=0, capacity=100, max_holding=None, sell_price=2.8, sell_volume=25)
>>> await beer.patch_manager(sell_price=2.7, sell_volume=26)
>>> player.storehouse.items[Item.Beer].manager
InventoryManager(buy_price=5.45, buy_volume=0, capacity=100, max_holding=None, sell_price=2.7, sell_volume=26)
```

#### Transports

Load the transport that is currently docked in Aderhampton:

```python
>>> tr = player.transports.by_town_name('Aderhampton')[0]
>>> tr.docked
True
```

List the items we are exporting here:

```python
>>> list(tr.exports.keys())
[<Item.Cloth: 'cloth'>,
 <Item.DyedCloth: 'dyed cloth'>,
 <Item.Garments: 'garments'>]
```

Check how much cloth we exported last turn:

```python
>>> tr.exports[Item.Cloth].manager.sell_volume
37
>>> tr.exports[Item.Cloth].volume_flowed
37
```

Looks like we are at max capacity for our export.
Bump our export volume and then buy some more cloth off the Aderhampton market:

```python
>>> await tr.exports[Item.Cloth].patch_manager(sell_volume=38)
>>> details = await tr.exports[Item.Cloth].fetch_market_details()
>>> details.bids
[ItemOrder(volume=1, price=8.99),
 ItemOrder(volume=3, price=8.856),
 ItemOrder(volume=1, price=8.822),
 ItemOrder(volume=1, price=8.478),
 ItemOrder(volume=5, price=8.441),
 ItemOrder(volume=1, price=5.414)]
>>> player.storehouse.items[Item.Cloth].balance
1477.096
>>> await tr.exports[Item.Cloth].sell(1, 8.99)
>>> player.storehouse.items[Item.Cloth].balance
1476.096
```

#### Operations

Get the operations for all of our weaveries:

```python
>>> from pymerc.api.models.common import BuildingType
>>> player.operations.by_building_type(BuildingType.Weavery)
OperationsList([<pymerc.game.operation.Operation at 0x7ffbb00de6f0>])
```

We have a single operation going on associated with a weavery.
Check how much it is currently outputting:

```python
>>> player.operations.by_building_type(BuildingType.Weavery).outputs
{<Item.Cloth: 'cloth'>: 400.0}
```

Check all of our operations that are taking cloth as an input:

```python
>>> player.operations.by_item_input(Item.Cloth)
OperationsList([<pymerc.game.operation.Operation at 0x7ffbb00debd0>,
                <pymerc.game.operation.Operation at 0x7ffbb00dede0>,
                <pymerc.game.operation.Operation at 0x7ffbb00dee70>,
                <pymerc.game.operation.Operation at 0x7ffbb00dcf80>])
```

Check how much cloth all of these operations are consuming in total:

```python
>>> player.operations.by_item_input(Item.Cloth).inputs[Item.Cloth]
197.0
```

#### Data Analysis

Compare our total and actual imports:

```python
>>> player.imports.volume
426
>>> player.imports.volume_flowed
281  # Importing a little over half of our target volume
>>> player.imports.cost
3669.11
>>> player.imports.cost_flowed
1715.167  # Importing at half of our target cost (yay!)
```

See how our cloth production is doing:

```python
>>> cloth = player.storehouse.items[Item.Cloth]
>>> cloth.produced
400.0
>>> cloth.production_cost
2383.614
>>> excess = cloth.produced - cloth.consumed
>>> excess_value = excess * cloth.average_cost
>>> value_flowed = cloth.sale_value + player.exports[Item.Cloth].value_flowed
>>> value_flowed > excess_value
False  # Looks like we're not making money on our excess cloth!
```

## Testing

Since this library parses live API endpoints, mocking values makes little sense.
Instead, you must provide a `.env` file with your API credentials:

```text
API_USER="<USER>"
API_TOKEN="<TOKEN>"
```

The tests will utilize this to validate that all endpoints are parsing correctly:

```shell
pytest .
```

Additionally, you can create an instance of the client/player to test with using `ipython`:

```shell
> ipython
In [1]: from shell import main; await main(); from shell import client;
In [2]: player = await client.player()
```

[Mercatorio]: https://mercatorio.io

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jmgilman/pymerc",
    "name": "pymerc",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.11",
    "maintainer_email": null,
    "keywords": "mercatorio, python, library, game",
    "author": "Joshua Gilman",
    "author_email": "joshuagilman@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/07/54/c7ce42801127c06ea3dc1d992c1203f20e8c8398eaa422644b9899aa06b8/pymerc-0.6.0.tar.gz",
    "platform": null,
    "description": "# Pymerc\n\n> A Python library for interacting with the [Mercatorio] browser based game\n\n## Usage\n\nYou must first [generate API credentials](https://play.mercatorio.io/settings/api).\nOnce generated, you can instantiate a `Client` instance using the credentials.\n\n```python\nfrom pymerc.client import Client\n\n# Create a new client\nclient = Client(os.environ[\"API_USER\"], os.environ[\"API_TOKEN\"])\n```\n\n### Game Objects\n\nThe `pymerc` package provides both low-level API calls as well as high-level objects that wrap those calls.\nIn almost all cases, you should plan to use the higher-level objects.\nIf something is missing in one of these objects, please submit an issue or PR.\n\nMost logic is contained within the `Player` object:\n\n```python\nplayer = await client.player()\n```\n\nCreating the player object can take a few seconds as it results in several requests being sent to the API.\nIt's recommended you re-use the player object instead of recreating it multiple times.\nThe data for the player object can be updated with:\n\n```python\nawait player.load()\n```\n\n#### Storehouse\n\nCheck our balance of beer and then buy some from the local market:\n\n```python\n>>> from pymerc.api.models.common import Item\n>>> beer = player.storehouse.items[Item.Beer]\n>>> beer.balance\n41.5\n>>> beer.market_data\nTownMarketItem(price=2.894, last_price=2.894, average_price=2.894, moving_average=2.868, highest_bid=2.894, lowest_ask=3.0, volume=95, volume_prev_12=1085, bid_volume_10=2, ask_volume_10=20)\n>>> details = await beer.fetch_market_details()  # More fine-grained details\n>>> details.asks\n[ItemOrder(volume=20, price=3.0),\n ItemOrder(volume=1, price=3.425),\n ItemOrder(volume=3, price=3.475),\n ItemOrder(volume=1, price=3.526)]\n>>> result = await beer.buy(1, 3.0)\n>>> result.settlements[0].volume\n1\n```\n\nAdjust the price and volume of beer we are selling:\n\n```python\n>>> beer.manager\nInventoryManager(buy_price=5.45, buy_volume=0, capacity=100, max_holding=None, sell_price=2.8, sell_volume=25)\n>>> await beer.patch_manager(sell_price=2.7, sell_volume=26)\n>>> player.storehouse.items[Item.Beer].manager\nInventoryManager(buy_price=5.45, buy_volume=0, capacity=100, max_holding=None, sell_price=2.7, sell_volume=26)\n```\n\n#### Transports\n\nLoad the transport that is currently docked in Aderhampton:\n\n```python\n>>> tr = player.transports.by_town_name('Aderhampton')[0]\n>>> tr.docked\nTrue\n```\n\nList the items we are exporting here:\n\n```python\n>>> list(tr.exports.keys())\n[<Item.Cloth: 'cloth'>,\n <Item.DyedCloth: 'dyed cloth'>,\n <Item.Garments: 'garments'>]\n```\n\nCheck how much cloth we exported last turn:\n\n```python\n>>> tr.exports[Item.Cloth].manager.sell_volume\n37\n>>> tr.exports[Item.Cloth].volume_flowed\n37\n```\n\nLooks like we are at max capacity for our export.\nBump our export volume and then buy some more cloth off the Aderhampton market:\n\n```python\n>>> await tr.exports[Item.Cloth].patch_manager(sell_volume=38)\n>>> details = await tr.exports[Item.Cloth].fetch_market_details()\n>>> details.bids\n[ItemOrder(volume=1, price=8.99),\n ItemOrder(volume=3, price=8.856),\n ItemOrder(volume=1, price=8.822),\n ItemOrder(volume=1, price=8.478),\n ItemOrder(volume=5, price=8.441),\n ItemOrder(volume=1, price=5.414)]\n>>> player.storehouse.items[Item.Cloth].balance\n1477.096\n>>> await tr.exports[Item.Cloth].sell(1, 8.99)\n>>> player.storehouse.items[Item.Cloth].balance\n1476.096\n```\n\n#### Operations\n\nGet the operations for all of our weaveries:\n\n```python\n>>> from pymerc.api.models.common import BuildingType\n>>> player.operations.by_building_type(BuildingType.Weavery)\nOperationsList([<pymerc.game.operation.Operation at 0x7ffbb00de6f0>])\n```\n\nWe have a single operation going on associated with a weavery.\nCheck how much it is currently outputting:\n\n```python\n>>> player.operations.by_building_type(BuildingType.Weavery).outputs\n{<Item.Cloth: 'cloth'>: 400.0}\n```\n\nCheck all of our operations that are taking cloth as an input:\n\n```python\n>>> player.operations.by_item_input(Item.Cloth)\nOperationsList([<pymerc.game.operation.Operation at 0x7ffbb00debd0>,\n                <pymerc.game.operation.Operation at 0x7ffbb00dede0>,\n                <pymerc.game.operation.Operation at 0x7ffbb00dee70>,\n                <pymerc.game.operation.Operation at 0x7ffbb00dcf80>])\n```\n\nCheck how much cloth all of these operations are consuming in total:\n\n```python\n>>> player.operations.by_item_input(Item.Cloth).inputs[Item.Cloth]\n197.0\n```\n\n#### Data Analysis\n\nCompare our total and actual imports:\n\n```python\n>>> player.imports.volume\n426\n>>> player.imports.volume_flowed\n281  # Importing a little over half of our target volume\n>>> player.imports.cost\n3669.11\n>>> player.imports.cost_flowed\n1715.167  # Importing at half of our target cost (yay!)\n```\n\nSee how our cloth production is doing:\n\n```python\n>>> cloth = player.storehouse.items[Item.Cloth]\n>>> cloth.produced\n400.0\n>>> cloth.production_cost\n2383.614\n>>> excess = cloth.produced - cloth.consumed\n>>> excess_value = excess * cloth.average_cost\n>>> value_flowed = cloth.sale_value + player.exports[Item.Cloth].value_flowed\n>>> value_flowed > excess_value\nFalse  # Looks like we're not making money on our excess cloth!\n```\n\n## Testing\n\nSince this library parses live API endpoints, mocking values makes little sense.\nInstead, you must provide a `.env` file with your API credentials:\n\n```text\nAPI_USER=\"<USER>\"\nAPI_TOKEN=\"<TOKEN>\"\n```\n\nThe tests will utilize this to validate that all endpoints are parsing correctly:\n\n```shell\npytest .\n```\n\nAdditionally, you can create an instance of the client/player to test with using `ipython`:\n\n```shell\n> ipython\nIn [1]: from shell import main; await main(); from shell import client;\nIn [2]: player = await client.player()\n```\n\n[Mercatorio]: https://mercatorio.io\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A Python library for interacting with the Mercatorio browser based game",
    "version": "0.6.0",
    "project_urls": {
        "Homepage": "https://github.com/jmgilman/pymerc"
    },
    "split_keywords": [
        "mercatorio",
        " python",
        " library",
        " game"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0cb481c770d64253c93186e6711bf15c4cd822c6bddf538def3ff2829d7c1c9d",
                "md5": "f9379403957140baec6ce7bdfcc0f84e",
                "sha256": "16727c81bce07beff4a8a07ab7d0eacb99a51523e228b6d1b3c6632b15218d69"
            },
            "downloads": -1,
            "filename": "pymerc-0.6.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f9379403957140baec6ce7bdfcc0f84e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.11",
            "size": 36974,
            "upload_time": "2024-06-02T19:21:47",
            "upload_time_iso_8601": "2024-06-02T19:21:47.003836Z",
            "url": "https://files.pythonhosted.org/packages/0c/b4/81c770d64253c93186e6711bf15c4cd822c6bddf538def3ff2829d7c1c9d/pymerc-0.6.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0754c7ce42801127c06ea3dc1d992c1203f20e8c8398eaa422644b9899aa06b8",
                "md5": "1591aa5dbdd89033699c5a32b2359b30",
                "sha256": "5a3c03764d47b4d67d7a374ba47f0b0e52a3dd537d1010d659da0675e1cd3d82"
            },
            "downloads": -1,
            "filename": "pymerc-0.6.0.tar.gz",
            "has_sig": false,
            "md5_digest": "1591aa5dbdd89033699c5a32b2359b30",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.11",
            "size": 27252,
            "upload_time": "2024-06-02T19:21:48",
            "upload_time_iso_8601": "2024-06-02T19:21:48.722229Z",
            "url": "https://files.pythonhosted.org/packages/07/54/c7ce42801127c06ea3dc1d992c1203f20e8c8398eaa422644b9899aa06b8/pymerc-0.6.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-06-02 19:21:48",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jmgilman",
    "github_project": "pymerc",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pymerc"
}
        
Elapsed time: 0.57340s