From 916fe73f35e11346e495819341b171067d4ea111 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 27 Oct 2021 11:08:16 +0000 Subject: [PATCH 01/81] schemas: codexentry: NearestDestination *can* be an empty string. We had one user with EDMC trying to send: ```python OrderedDict([('$schemaRef', 'https://eddn.edcd.io/schemas/codexentry/1'), ('message', OrderedDict([('timestamp', '2021-10-26T11:37:57Z'), ('event', 'CodexEntry'), ('EntryID', 2420702), ('Name', '$Codex_Ent_Stratum_07_K_Name;'), ('SubCategory', '$Codex_SubCategory_Organic_Structures;'), ('Category', '$Codex_Category_Biology;'), ('Region', '$Codex_RegionName_18;'), ('System', 'Xi Ophiuchi'), ('SystemAddress', 2072061675891), ('NearestDestination', ''), ('Latitude', 79.352364), ('Longitude', 121.434044), ('horizons', True), ('odyssey', True), ('StarPos', [-3.875, 8.15625, 55.875]), ('BodyName', 'Xi Ophiuchi B 5'), ('BodyID', 14)]))]) ``` as the message. The EDDN Gateway then complains: `FAIL: []` --- schemas/codexentry-v1.0.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/schemas/codexentry-v1.0.json b/schemas/codexentry-v1.0.json index 4a4727b..d191060 100644 --- a/schemas/codexentry-v1.0.json +++ b/schemas/codexentry-v1.0.json @@ -92,8 +92,7 @@ "minLength" : 1 }, "NearestDestination": { - "type" : "string", - "minLength" : 1 + "type" : "string" }, "VoucherAmount": { "type" : "integer" From f984ce4c79174be7e993214203cc371ba93495b0 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 26 Sep 2021 13:58:49 +0000 Subject: [PATCH 02/81] schemas: Correct 'id' in navbeaconscan-v1.0.json It still had 'fssdiscoveryscan' in there, presumably from a copying. --- schemas/navbeaconscan-v1.0.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/navbeaconscan-v1.0.json b/schemas/navbeaconscan-v1.0.json index a2cb398..64d55bf 100644 --- a/schemas/navbeaconscan-v1.0.json +++ b/schemas/navbeaconscan-v1.0.json @@ -1,6 +1,6 @@ { "$schema" : "http://json-schema.org/draft-04/schema#", - "id" : "https://eddn.edcd.io/schemas/fssdiscoveryscan/1#", + "id" : "https://eddn.edcd.io/schemas/navbeaconscan/1#", "type" : "object", "additionalProperties" : false, "required": [ "$schemaRef", "header", "message" ], From b35b934d8cf414c58127f926ad9bf9dc93192245 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 29 Oct 2021 13:42:43 +0100 Subject: [PATCH 03/81] schemas: blackmarket: README Note that it turns out this is deprecated in favour of the `prohibited` array defined in the `commodity` schema, and has been that way since September 2017. --- schemas/blackmarket-README.md | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 schemas/blackmarket-README.md diff --git a/schemas/blackmarket-README.md b/schemas/blackmarket-README.md new file mode 100644 index 0000000..d278d27 --- /dev/null +++ b/schemas/blackmarket-README.md @@ -0,0 +1,53 @@ +# EDDN BlackMarket Schema + +## Introduction + +**This schema is deprecated. The same data has been made available via the +`prohibited` array in the [commodity schema](./commodity-v3.0.json) since +September 2017.** + +What follows below is only for historical curiosity. + +--- + +Here we document how to take data from an ED `BlackMArket` Journal Event and +properly structure it for sending to EDDN. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the ED Journal event `MarketSell`. + +### Key Renames +#### name +Due to how the EDDN schema is defined the `Type` key/value should +have the key renamed to `name`. + +#### prohibited +Due to how the EDDN schema is defined the `IllegalGoods` key/value should +have the key renamed to `prohibited`. + +#### marketID +The Journal documentation says this is `MarketID`, but in the schema the +`m` is lower case. + +### Elisions +You MUST remove the following key/value pairs from the data: + + - `Count` + - `TotalSale` + - `AvgPricePaid` + - `StolenGoods` + - `BlackMarket` - Because we're using this schema, so this is un-necessary. + +### Augmentations +#### systemName +The star system name for where this market is. Use the `StarSystem` value +from the prior `Docked` or `Location` event. + +#### stationName +From the `StationName` value on the prior `Docked` or `Location` event. + +#### timestamp +An additional timsestamp, presumably from the `MarketSell` event. \ No newline at end of file From ed30aa4f01dbf91adf32b01f58909296afaf5869 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 29 Oct 2021 13:54:39 +0100 Subject: [PATCH 04/81] schemas: blackmarket: No, that's no an additional `timestamp` --- schemas/blackmarket-README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/schemas/blackmarket-README.md b/schemas/blackmarket-README.md index d278d27..7193b1d 100644 --- a/schemas/blackmarket-README.md +++ b/schemas/blackmarket-README.md @@ -47,7 +47,4 @@ The star system name for where this market is. Use the `StarSystem` value from the prior `Docked` or `Location` event. #### stationName -From the `StationName` value on the prior `Docked` or `Location` event. - -#### timestamp -An additional timsestamp, presumably from the `MarketSell` event. \ No newline at end of file +From the `StationName` value on the prior `Docked` or `Location` event. \ No newline at end of file From 68160fcb8d0e7c6580b2d4182d432784cdccb240 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 29 Oct 2021 14:10:49 +0100 Subject: [PATCH 05/81] schemas: commodity: Initial README --- schemas/commodity-README.md | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 schemas/commodity-README.md diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md new file mode 100644 index 0000000..7941c36 --- /dev/null +++ b/schemas/commodity-README.md @@ -0,0 +1,46 @@ +# EDDN BlackMarket Schema + +## Introduction +Here we document how to take data from an ED `Market` Journal Event and +properly structure it for sending to EDDN. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the ED Journal event `Market`, +and the additional file, `Market.json`, that it signals the writing of. + +So, look for the `Market` event, and when it occurs open and read the +`Market.json` file which contains the actual data. Treat *that* data as +the event. + +It *is* also possible to construct this data from a CAPI `/market` query. + +### Key Renames +Many of the key names have a different case defined in this schema, make +sure you are renaming them as appropriate. + +#### StarSystem to systemName +Rename the `StarSystem` key name to `systemName`. + +### Elisions +#### Remove _Localised key/values +You MUST remove the following key/value pairs from the data: + + - `StationType` key/value. + - All keys whose name ends with `_Localised`, i.e. the `Name_Localised` + key/values in Items. + - `Producer` key/value pair in Items. + - `Rare` key/value pair in Items. + - `id` key/value pair in Items. + +#### Item Category +Remove not only the `Category_Localised` key/value, as above, but also the +`Category` key/value pair from each Item. + +### Augmentations +#### horizons flag +Use the value from the `LoadGame` event. +#### odyssey flag +Use the value from the `LoadGame` event. From 8e03a8253612b597333f452f2d4e130dde73e0a6 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 29 Oct 2021 14:27:40 +0100 Subject: [PATCH 06/81] schemas: commodity: README: Document use of CAPI data --- schemas/commodity-README.md | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md index 7941c36..290b814 100644 --- a/schemas/commodity-README.md +++ b/schemas/commodity-README.md @@ -15,7 +15,8 @@ So, look for the `Market` event, and when it occurs open and read the `Market.json` file which contains the actual data. Treat *that* data as the event. -It *is* also possible to construct this data from a CAPI `/market` query. +It *is* also possible to construct this data from a CAPI `/market` query. +See [Using CAPI data](#using-capi-data) below. ### Key Renames Many of the key names have a different case defined in this schema, make @@ -44,3 +45,36 @@ Remove not only the `Category_Localised` key/value, as above, but also the Use the value from the `LoadGame` event. #### odyssey flag Use the value from the `LoadGame` event. + +### Using CAPI data +It is *not* recommended to use CAPI data as the source as it's fraught with +additional issues. EDMarketConnector does so in order to facilitate +obtaining data without the player needing to open the commodities screen. + +1. Retrieve the commander data from the `/profile` CAPI endpoint. +2. Check that `commander['docked']` is true. If not, abort. +3. Retrieve the data from the `/market` and `/shipyard` CAPI endpoints. +4. Compare the system and station name from the CAPI market data to that + from the last `Docked` or `Location` journal event. If either does not + match then you MUST **abort**. This likely indicates that the CAPI data is + lagging behind the game client state and thus should not be used. + +Note that CAPI `/market` data will sometimes have the `StatusFlasg` per +item, which are defined as optional in this schema (because they're not in +the Market.json data). You SHOULD include this data in your message if +using CAPI as the source. + +Now you will need to construct the necessary additional fields: + +#### CAPI horizons flag +You will need to check if any of the economies from the `/market` data have +a `name` are `Colony`, if so, set this flag true. + +Additionally, you should retrieve the CAPI `/shipyard` endpoint and check if +any of the listed ships or modules have a `sku` value of +`ELITE_HORIZONS_V_PLANETARY_LANDINGS`. If so, set this flag true. + +#### CAPI odyssey flag +Unfortunately there is no method to be *certain* of this from CAPI data, so +you will have to trust in the system/station name check and use the value +from the Journal `LoadGame` event. \ No newline at end of file From 8178e61b0097abf355b4896aeb489684c9402d63 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 29 Oct 2021 15:01:02 +0100 Subject: [PATCH 07/81] schemas: commodity: README: Correct top-level header --- schemas/commodity-README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md index 290b814..bd5721b 100644 --- a/schemas/commodity-README.md +++ b/schemas/commodity-README.md @@ -1,4 +1,4 @@ -# EDDN BlackMarket Schema +# EDDN Commodity Schema ## Introduction Here we document how to take data from an ED `Market` Journal Event and From d781160e6ec9879996759be98c07d8cb16908960 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 29 Oct 2021 15:05:28 +0100 Subject: [PATCH 08/81] schemas: commodity: README: _Localised keys correction --- schemas/commodity-README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md index bd5721b..31befef 100644 --- a/schemas/commodity-README.md +++ b/schemas/commodity-README.md @@ -27,11 +27,13 @@ Rename the `StarSystem` key name to `systemName`. ### Elisions #### Remove _Localised key/values +All keys whose name ends with `_Localised`, i.e. the `Name_Localised` +key/values in Items. + +#### Other Elisions You MUST remove the following key/value pairs from the data: - - `StationType` key/value. - - All keys whose name ends with `_Localised`, i.e. the `Name_Localised` - key/values in Items. +- `StationType` key/value. - `Producer` key/value pair in Items. - `Rare` key/value pair in Items. - `id` key/value pair in Items. From fc7443b2826d36929f569c886d35211f3b9e24d4 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 29 Oct 2021 15:09:30 +0100 Subject: [PATCH 09/81] schemas: fssdiscoveryscan: README: Initial version --- schemas/fssdiscoveryscan-README.md | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 schemas/fssdiscoveryscan-README.md diff --git a/schemas/fssdiscoveryscan-README.md b/schemas/fssdiscoveryscan-README.md new file mode 100644 index 0000000..594adc4 --- /dev/null +++ b/schemas/fssdiscoveryscan-README.md @@ -0,0 +1,40 @@ +# EDDN FSSDiscoveryScan Schema + +## Introduction +Here we document how to take data from an ED `FSSDiscoveryScan` Journal +Event and properly structure it for sending to EDDN. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the ED Journal event +`FSSDiscoveryScan`. + +### Key Renames +Many of the key names have a different case defined in this schema, make +sure you are renaming them as appropriate. + +### Elisions +#### Remove _Localised key/values +All keys whose name ends with `_Localised`, i.e. the `Name_Localised` +key/values in Items. + +#### Other Elisions +You MUST remove the following key/value pairs from the data: + + - `Progress` key/value pair. + +#### Item Category +Remove not only the `Category_Localised` key/value, as above, but also the +`Category` key/value pair from each Item. + +### Augmentations +#### horizons flag +Use the value from the `LoadGame` event. +#### odyssey flag +Use the value from the `LoadGame` event. + +#### StarPos +You MUST add a `StarPos` array containing the system co-ordinates from the +last `FSDJump`, `CarrierJump`, or `Location` event. \ No newline at end of file From 635d7c269375531d175b952f89c4d7c6804c68fa Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 14:31:59 +0000 Subject: [PATCH 10/81] schemas: README: Note about key names being originally CAPI based --- schemas/README-EDDN-schemas.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 550a56e..8ce4be2 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -170,6 +170,10 @@ Each `message` object must have, at bare minimum: much more than this. Again, consult the [schemas and their documentation](./). +Note that many of the key names chosen in the schemas are based on the CAPI +data, not Journal events, because the CAPI came first. This means renaming +many of the keys from Journal events to match the schema. + EDDN is intended to transport generic data not specific to any particular Cmdr and to reflect the data that a player would see in-game in station services or the local map. To that end, uploading applications MUST ensure that messages do From fd567e69aad6b754d9812d758f72abd92a7141cb Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 14:44:28 +0000 Subject: [PATCH 11/81] schemas: journal: README: Now complete, in the generic sense Ideally all the events covered here need splitting into their own schemas, but for the time being this documentation should suffice. --- schemas/journal-README.md | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 schemas/journal-README.md diff --git a/schemas/journal-README.md b/schemas/journal-README.md new file mode 100644 index 0000000..5dd7cea --- /dev/null +++ b/schemas/journal-README.md @@ -0,0 +1,86 @@ +# EDDN Journal Schema + +## Introduction +Here we document how to take data from miscellaneous ED Journal +events and properly structure it for sending to EDDN. + +This is the historical "all Journal events" schema that will be deprecated +in the future. Please check for a schema specific to the journal event +under consideration to see if data should be sent on that event specific +schema instead. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the ED Journal events: + + - `Docked` + - `FSDJump` + - `Scan` + - `Location` + - `SAASignalsFound` + - `CarrierJump` + - `CodexEntry` - But see the separate + [codexentry schema](./codexentry-README.md) documentation. + +### Key Renames +Many of the key names have a different case defined in this schema, make +sure you are renaming them as appropriate. + +### Elisions +#### Remove _Localised key/values +All keys whose name ends with `_Localised`, i.e. the `Name_Localised` +key/values in Items. + +#### Personal data in `Docked` events +The following keys+values should be removed from `Docked` event data: + + - `Wanted` + - `ActiveFine` + - `CockpitBreach` + +#### Personal data in `FSDJump` events +The following keys+values should be removed from `FSDJump` event data: + +- `Wanted` +- `BoostUsed` +- `FuelLevel` +- `FuelUsed` +- `JumpDist` +- `HappiestSystem` from within the list of `Factions`. +- `HomeSystem` from within the list of `Factions`. +- `MyReputation` from within the list of `Factions`. +- `SquadronFaction` from within the list of `Factions`. + +#### Personal data in `Location` events +The following keys+values should be removed from `Location` event data: + +- `Wanted` +- `Latitude` +- `Longitude` +- `HappiestSystem` from within the list of `Factions`. +- `HomeSystem` from within the list of `Factions`. +- `MyReputation` from within the list of `Factions`. +- `SquadronFaction` from within the list of `Factions`. + +### Augmentations +#### horizons flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### odyssey flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### StarSystem +You MUST add a `StarSystem` key/value pair representing the name of the +system this event occurred in. Source this from either `Location`, +`FSDJump` or `CarrierJump` as appropriate. + +#### SystemAddress +You MUST add a `SystemAddress` key/value pair representing the numerical ID +of the system this event occurred in. Source this from either `Location`, +`FSDJump` or `CarrierJump` as appropriate. + +#### StarPos +You MUST add a `StarPos` array containing the system co-ordinates from the +last `FSDJump`, `CarrierJump`, or `Location` event. From 67e77136ffd0a8e4cfebbea71882cb3980cc5096 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 14:54:10 +0000 Subject: [PATCH 12/81] schemas: navbeaconscan: README: Initial version --- schemas/navbeaconscan-README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 schemas/navbeaconscan-README.md diff --git a/schemas/navbeaconscan-README.md b/schemas/navbeaconscan-README.md new file mode 100644 index 0000000..c12e91b --- /dev/null +++ b/schemas/navbeaconscan-README.md @@ -0,0 +1,31 @@ +# EDDN NavBeaconScan Schema + +## Introduction +Here we document how to take data from an ED `NavBeaconScan` Journal +Event and properly structure it for sending to EDDN. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the ED Journal event +`NavBeaconScan`. + +### Elisions +There are no elisions in this schema. + +### Augmentations +#### horizons flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### odyssey flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### StarSystem +You MUST add a `StarSystem` key/value pair representing the name of the +system this event occurred in. Source this from either `Location`, +`FSDJump` or `CarrierJump` as appropriate. + +#### StarPos +You MUST add a `StarPos` array containing the system co-ordinates from the +last `FSDJump`, `CarrierJump`, or `Location` event. From 6c1d8cff92c745e7fd98dea9e48a74b53f9fa78c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 14:58:54 +0000 Subject: [PATCH 13/81] schemas: navroute: README: Initial version --- schemas/navroute-README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 schemas/navroute-README.md diff --git a/schemas/navroute-README.md b/schemas/navroute-README.md new file mode 100644 index 0000000..3025baa --- /dev/null +++ b/schemas/navroute-README.md @@ -0,0 +1,29 @@ +# EDDN NavRoute Schema + +## Introduction +Here we document how to take data from an ED `NavRoute` Journal +Event and properly structure it for sending to EDDN. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the `NavRoute.json` file. That +it has been freshly written is signalled by the ED Journal event `NavRoute`. + +So, monitor the Journal as normal, and when you see a `NavRoute` event open +the `NavRoute.json` file for reading, read it, and close it again. Use the +data you got from reading this file, not merely the Journal event. + +The primary data to be sent is the `Route` array from the contents of the +separate file. + +### Elisions +There are no elisions in this schema. + +### Augmentations +#### horizons flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### odyssey flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. \ No newline at end of file From a32d6e2ea337650bdc18b8a3c810e0939a04337a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 15:11:15 +0000 Subject: [PATCH 14/81] schemas: outfitting: README: Initial version --- schemas/outfitting-README.md | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 schemas/outfitting-README.md diff --git a/schemas/outfitting-README.md b/schemas/outfitting-README.md new file mode 100644 index 0000000..f3e4370 --- /dev/null +++ b/schemas/outfitting-README.md @@ -0,0 +1,41 @@ +# EDDN Outfitting Schema + +## Introduction +Here we document how to take data from an ED `Outfitting` Journal +Event and properly structure it for sending to EDDN. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the ED Journal event +`Outfitting`. + +You MAY also source this data from the CAPI `/shipyard` endpoint. See +[commodity-README.md#using-capi-data](commodity-README.md#using-capi-data) +for guidance on this. + +You only need the `name` key's value for each member of the `modules` array. + +### Key Renames +Many of the key names have a different case defined in this schema, make +sure you are renaming them as appropriate. + +### Elisions +Remove items whose availability depends on the Cmdr's status rather than on the +station. Namely: + +- Items that aren't weapons/utilities (`Hpt_*`), standard/internal + modules (`Int_*`) or armour (`*_Armour_*`) (i.e. bobbleheads, decals, + paintjobs and shipkits). This is enforced by the schema. +- Items that have a non-null `"sku"` property, unless + it's `"ELITE_HORIZONS_V_PLANETARY_LANDINGS"` (i.e. PowerPlay and tech + broker items). +- The `"Int_PlanetApproachSuite"` module (for historical reasons). + +### Augmentations +#### horizons flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### odyssey flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. \ No newline at end of file From e12ebee9f8f370bc456a57eaef5d63c1229fc599 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 15:15:03 +0000 Subject: [PATCH 15/81] schemas: scanbarycentre: README: Initial version --- schemas/scanbarycentre-README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 schemas/scanbarycentre-README.md diff --git a/schemas/scanbarycentre-README.md b/schemas/scanbarycentre-README.md new file mode 100644 index 0000000..da0e178 --- /dev/null +++ b/schemas/scanbarycentre-README.md @@ -0,0 +1,26 @@ +# EDDN ScanBaryCentre Schema + +## Introduction +Here we document how to take data from an ED `ScanBaryCentre` Journal +Event and properly structure it for sending to EDDN. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the ED Journal event +`ScanBaryCentre`. + +### Elisions +There are no elisions in this schema. + +### Augmentations +#### horizons flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### odyssey flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### StarPos +You MUST add a `StarPos` array containing the system co-ordinates from the +last `FSDJump`, `CarrierJump`, or `Location` event. From 3d023bf2801b8c6660328351ba60ba05d43693f6 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 15:46:08 +0000 Subject: [PATCH 16/81] schemas: shipyard: README: Initial version --- schemas/shipyard-README.md | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 schemas/shipyard-README.md diff --git a/schemas/shipyard-README.md b/schemas/shipyard-README.md new file mode 100644 index 0000000..295ff5a --- /dev/null +++ b/schemas/shipyard-README.md @@ -0,0 +1,39 @@ +# EDDN Shipyard Schema + +## Introduction +Here we document how to take data from an ED `Shipyard` Journal +Event and properly structure it for sending to EDDN. + +Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general +documentation for a schema such as this. + +## Senders +The primary data source for this schema is the ED Journal event +`Shipyard`. + +You MAY also source this data from the CAPI `/shipyard` endpoint. See +[commodity-README.md#using-capi-data](commodity-README.md#using-capi-data) +for guidance on this. + + You only need the `name` key's value for each member of the `PriceList` +array (if using Journal, it will be from the `ships` array if using CAPI +data). + +When using CAPI data *include* ships listed in the `"unavailable_list"` +property (i.e. available at this station, but not to this Cmdr). + +This list of ship names will go in the `ships` array in the EDDN message. + +### Key Renames +Many of the key names have a different case defined in this schema, make +sure you are renaming them as appropriate. + +### Elisions +There are no elisions in this schema. + +### Augmentations +#### horizons flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### odyssey flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. From 339abce9e45591c2938a924e93a54d7551d27194 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 15:52:56 +0000 Subject: [PATCH 17/81] schemas: READMES: Consistent horizons/odyssey language --- schemas/blackmarket-README.md | 6 ++++++ schemas/codexentry-README.md | 6 ++++++ schemas/commodity-README.md | 5 +++-- schemas/fssdiscoveryscan-README.md | 5 +++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/schemas/blackmarket-README.md b/schemas/blackmarket-README.md index 7193b1d..c86035e 100644 --- a/schemas/blackmarket-README.md +++ b/schemas/blackmarket-README.md @@ -42,6 +42,12 @@ You MUST remove the following key/value pairs from the data: - `BlackMarket` - Because we're using this schema, so this is un-necessary. ### Augmentations +#### horizons flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### odyssey flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + #### systemName The star system name for where this market is. Use the `StarSystem` value from the prior `Docked` or `Location` event. diff --git a/schemas/codexentry-README.md b/schemas/codexentry-README.md index 69b6e4a..1f3725e 100644 --- a/schemas/codexentry-README.md +++ b/schemas/codexentry-README.md @@ -17,6 +17,12 @@ You MUST remove any key where the key name ends in You MUST remove the two keys `IsNewEntry` and `NewTraitsDiscovered`. ### Augmentations +#### horizons flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + +#### odyssey flag +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + #### StarPos You MUST **add** a `StarPos` key with value of type `array` containing the galaxy co-ordinates of the system. You will need to have obtained these diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md index 31befef..cdc9bc9 100644 --- a/schemas/commodity-README.md +++ b/schemas/commodity-README.md @@ -44,9 +44,10 @@ Remove not only the `Category_Localised` key/value, as above, but also the ### Augmentations #### horizons flag -Use the value from the `LoadGame` event. +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + #### odyssey flag -Use the value from the `LoadGame` event. +You SHOULD add this key/value pair, using the value from the `LoadGame` event. ### Using CAPI data It is *not* recommended to use CAPI data as the source as it's fraught with diff --git a/schemas/fssdiscoveryscan-README.md b/schemas/fssdiscoveryscan-README.md index 594adc4..de16148 100644 --- a/schemas/fssdiscoveryscan-README.md +++ b/schemas/fssdiscoveryscan-README.md @@ -31,9 +31,10 @@ Remove not only the `Category_Localised` key/value, as above, but also the ### Augmentations #### horizons flag -Use the value from the `LoadGame` event. +You SHOULD add this key/value pair, using the value from the `LoadGame` event. + #### odyssey flag -Use the value from the `LoadGame` event. +You SHOULD add this key/value pair, using the value from the `LoadGame` event. #### StarPos You MUST add a `StarPos` array containing the system co-ordinates from the From b9231cef12432fa04e6480369c3a054afaae4544 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 15:58:00 +0000 Subject: [PATCH 18/81] schemas: READMEs: Move commodity-specific elisions into its file --- schemas/README-EDDN-schemas.md | 3 --- schemas/commodity-README.md | 12 +++++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 8ce4be2..a86e1b5 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -180,9 +180,6 @@ the local map. To that end, uploading applications MUST ensure that messages do not contain any Cmdr-specific data (other than "uploaderID" and the "horizons" flag). In practice as of E:D 3.3 this means: -* commodity: Skip commodities with `"categoryname": "NonMarketable"` (i.e. - Limpets - not purchasable in station market) or `"legality":` *non-empty - string* (not normally traded at this station market). * outfitting: Skip items whose availability depends on the Cmdr's status rather than on the station. Namely: - Items that aren't weapons/utilities (`Hpt_*`), standard/internal diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md index cdc9bc9..2452530 100644 --- a/schemas/commodity-README.md +++ b/schemas/commodity-README.md @@ -34,9 +34,15 @@ key/values in Items. You MUST remove the following key/value pairs from the data: - `StationType` key/value. - - `Producer` key/value pair in Items. - - `Rare` key/value pair in Items. - - `id` key/value pair in Items. +- `Producer` key/value pair in Items. +- `Rare` key/value pair in Items. +- `id` key/value pair in Items. + +In the list of commodites: + +- Skip commodities with `"categoryname": "NonMarketable"` (i.e. + Limpets - not purchasable in station market) or a *non-empty*`"legality":` + string (not normally traded at this station market). #### Item Category Remove not only the `Category_Localised` key/value, as above, but also the From a32f047b7f8dcf93526a934b822d7e9502e4ba59 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 15:58:35 +0000 Subject: [PATCH 19/81] schemas: README: outfitting-specific elisions in that file already --- schemas/README-EDDN-schemas.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index a86e1b5..a986f5f 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -180,15 +180,6 @@ the local map. To that end, uploading applications MUST ensure that messages do not contain any Cmdr-specific data (other than "uploaderID" and the "horizons" flag). In practice as of E:D 3.3 this means: -* outfitting: Skip items whose availability depends on the Cmdr's status rather - than on the station. Namely: - - Items that aren't weapons/utilities (`Hpt_*`), standard/internal - modules (`Int_*`) or armour (`*_Armour_*`) (i.e. bobbleheads, decals, - paintjobs and shipkits). - - Items that have a non-null `"sku"` property, unless - it's `"ELITE_HORIZONS_V_PLANETARY_LANDINGS"` (i.e. PowerPlay and tech - broker items). - - The `"Int_PlanetApproachSuite"` module (for historical reasons). * shipyard: *Include* ships listed in the `"unavailable_list"` property (i.e. available at this station, but not to this Cmdr). * journal: Strip out `"..._Localised"` properties throughout the data From 57e8b9af4b8d43e212966ed7dcd1a17783b7b494 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 15:59:38 +0000 Subject: [PATCH 20/81] schemas: README: shipyard `unavailable_list` already noted in its README --- schemas/README-EDDN-schemas.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index a986f5f..ae7f5ed 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -180,8 +180,6 @@ the local map. To that end, uploading applications MUST ensure that messages do not contain any Cmdr-specific data (other than "uploaderID" and the "horizons" flag). In practice as of E:D 3.3 this means: -* shipyard: *Include* ships listed in the `"unavailable_list"` property (i.e. - available at this station, but not to this Cmdr). * journal: Strip out `"..._Localised"` properties throughout the data structure. * journal/Docked: Strip out `"Wanted"`, `"ActiveFine"`, `"CockpitBreach"` From aebf3ac4794b036804d6a4d69e96a549d4b7629f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 1 Nov 2021 16:02:12 +0000 Subject: [PATCH 21/81] schemas: README: Remove final things now mentioned in specific READMEs --- schemas/README-EDDN-schemas.md | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index ae7f5ed..e4c8c6a 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -178,19 +178,10 @@ EDDN is intended to transport generic data not specific to any particular Cmdr and to reflect the data that a player would see in-game in station services or the local map. To that end, uploading applications MUST ensure that messages do not contain any Cmdr-specific data (other than "uploaderID" and the "horizons" -flag). In practice as of E:D 3.3 this means: +flag). -* journal: Strip out `"..._Localised"` properties throughout the data - structure. -* journal/Docked: Strip out `"Wanted"`, `"ActiveFine"`, `"CockpitBreach"` - properties -* journal/FSDJump: Strip out `"Wanted"`, `"BoostUsed"`, `"FuelLevel"` - , `"FuelUsed"` and `"JumpDist"` properties. -* journal/Location: Strip out `"Wanted"`, `"Latitude"` and `"Longitude"` - properties. -* journal/Location and journal/FSDJump: strip out `"HappiestSystem"` - , `"HomeSystem"`, `"MyReputation"` and `"SquadronFaction"` properties within - the list of `"Factions"`. +The individual schemas will instruct you on various elisions (removals) to +be made to comply with this. Some of these requirements are also enforced by the schemas, and some things the schemas enforce might not be explicitly called out here, so **do** From 53acd5ed1e5af0af740763870140e3206d07d96d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 2 Nov 2021 11:20:09 +0000 Subject: [PATCH 22/81] schemas: blackmarket: README: Correct referenced Journal event --- schemas/blackmarket-README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schemas/blackmarket-README.md b/schemas/blackmarket-README.md index c86035e..11d9c76 100644 --- a/schemas/blackmarket-README.md +++ b/schemas/blackmarket-README.md @@ -10,7 +10,7 @@ What follows below is only for historical curiosity. --- -Here we document how to take data from an ED `BlackMArket` Journal Event and +Here we document how to take data from an ED `MarketSell` Journal Event and properly structure it for sending to EDDN. Please consult [EDDN Schemas README](./README-EDDN-schemas.md) for general From 6e81afc98c439991fcaef6b525f77931510b6df0 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 2 Nov 2021 11:20:43 +0000 Subject: [PATCH 23/81] schemas: blackmarket: README: `Count` doesn't need to be elided --- schemas/blackmarket-README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/schemas/blackmarket-README.md b/schemas/blackmarket-README.md index 11d9c76..0054bd1 100644 --- a/schemas/blackmarket-README.md +++ b/schemas/blackmarket-README.md @@ -35,7 +35,6 @@ The Journal documentation says this is `MarketID`, but in the schema the ### Elisions You MUST remove the following key/value pairs from the data: - - `Count` - `TotalSale` - `AvgPricePaid` - `StolenGoods` From 5b05e4879f855e6f51423042cf4971ee16f864f6 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 2 Nov 2021 11:24:37 +0000 Subject: [PATCH 24/81] schemas: commodity: README: Call out `statusFlags` --- schemas/commodity-README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md index 2452530..e50d411 100644 --- a/schemas/commodity-README.md +++ b/schemas/commodity-README.md @@ -18,6 +18,11 @@ the event. It *is* also possible to construct this data from a CAPI `/market` query. See [Using CAPI data](#using-capi-data) below. +### Statusflags +`statusFlags` is an optional augmentation that can be used to identify +`Producer`, `Consumer`, and `Rare` goods from the output of `Market.json`. +So, as per the schema, do include it if available. + ### Key Renames Many of the key names have a different case defined in this schema, make sure you are renaming them as appropriate. From 6704e1a957e92509e1c2eeed59103b75619d80c2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 2 Nov 2021 11:30:25 +0000 Subject: [PATCH 25/81] schemas: commodity: README: Allow `LoadGame` horizons flag for CAPI data --- schemas/commodity-README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md index e50d411..7abbedf 100644 --- a/schemas/commodity-README.md +++ b/schemas/commodity-README.md @@ -81,8 +81,12 @@ using CAPI as the source. Now you will need to construct the necessary additional fields: #### CAPI horizons flag -You will need to check if any of the economies from the `/market` data have -a `name` are `Colony`, if so, set this flag true. +If your application can be certain that the game client is still running, +and logged into the game (not just run to the main menu), then you can +simply use the value from the `LoadGame` journal event. + +Otherwise, you MUST check if any of the economies from the `/market` +data have a `name` of `Colony`, if so, set this flag true. Additionally, you should retrieve the CAPI `/shipyard` endpoint and check if any of the listed ships or modules have a `sku` value of From e0c1ac85fd3492fa6056f756b1474044dbb9b47a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 2 Nov 2021 11:32:54 +0000 Subject: [PATCH 26/81] schemas: fssdiscoveryscan: README: Don't over-state elisions --- schemas/fssdiscoveryscan-README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/schemas/fssdiscoveryscan-README.md b/schemas/fssdiscoveryscan-README.md index de16148..6d4d844 100644 --- a/schemas/fssdiscoveryscan-README.md +++ b/schemas/fssdiscoveryscan-README.md @@ -16,19 +16,10 @@ Many of the key names have a different case defined in this schema, make sure you are renaming them as appropriate. ### Elisions -#### Remove _Localised key/values -All keys whose name ends with `_Localised`, i.e. the `Name_Localised` -key/values in Items. - -#### Other Elisions You MUST remove the following key/value pairs from the data: - `Progress` key/value pair. -#### Item Category -Remove not only the `Category_Localised` key/value, as above, but also the -`Category` key/value pair from each Item. - ### Augmentations #### horizons flag You SHOULD add this key/value pair, using the value from the `LoadGame` event. From 1b11519ee7ebb7b47e3ba0bba36badd85933cd0a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 4 Nov 2021 11:03:51 +0000 Subject: [PATCH 27/81] schemas: READMEs: Centralise "detecting CAPI lag" advice --- schemas/README-EDDN-schemas.md | 20 +++++++++++++++++--- schemas/commodity-README.md | 10 +++------- schemas/outfitting-README.md | 7 ++++--- schemas/shipyard-README.md | 7 ++++--- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index e4c8c6a..a7461d8 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -62,13 +62,27 @@ the available endpoints and how they work. There is some [third-party documentation](https://github.com/Athanasius/fd-api/blob/main/docs/README.md) by Athanasius. +It is *not* recommended to use CAPI data as the source as it's fraught with +additional issues. EDMarketConnector does so in order to facilitate +obtaining data without the player needing to open the commodities screen. + +#### Detecting CAPI data lag + When using the Companion API please be aware that the server that supplies this data sometimes lags behind the game - usually by a few seconds, sometimes by minutes. You MUST check in the data from the CAPI that the Cmdr is -docked (`["commander"]["docked"]` is `True`) and that the station and -system (`["lastStarport"]["name"]` and `["lastSystem"]["name"]`) match those +docked, and that the station and system names match those reported from the Journal before using the data for the commodity, outfitting -and shipyard schemas. +and shipyard schemas: + +1. Retrieve the commander data from the `/profile` CAPI endpoint. +2. Check that `commander['docked']` is true. If not, abort. +3. Retrieve the data from the `/market` and `/shipyard` CAPI endpoints. +4. Compare the system and station name from the CAPI market data, + `["lastStarport"]["name"]` and `["lastSystem"]["name"]`, + to that from the last `Docked` or `Location` journal event. If either does + not match then you MUST **abort**. This likely indicates that the CAPI + data is lagging behind the game client state and thus should not be used. --- diff --git a/schemas/commodity-README.md b/schemas/commodity-README.md index 7abbedf..c2a4516 100644 --- a/schemas/commodity-README.md +++ b/schemas/commodity-README.md @@ -65,13 +65,9 @@ It is *not* recommended to use CAPI data as the source as it's fraught with additional issues. EDMarketConnector does so in order to facilitate obtaining data without the player needing to open the commodities screen. -1. Retrieve the commander data from the `/profile` CAPI endpoint. -2. Check that `commander['docked']` is true. If not, abort. -3. Retrieve the data from the `/market` and `/shipyard` CAPI endpoints. -4. Compare the system and station name from the CAPI market data to that - from the last `Docked` or `Location` journal event. If either does not - match then you MUST **abort**. This likely indicates that the CAPI data is - lagging behind the game client state and thus should not be used. +Please read +[the guidance on checking for CAPI lag](README-EDDN-schemas.md#detecting-capi-data-lag) +before utilising CAPI data for EDDN messages. Note that CAPI `/market` data will sometimes have the `StatusFlasg` per item, which are defined as optional in this schema (because they're not in diff --git a/schemas/outfitting-README.md b/schemas/outfitting-README.md index f3e4370..090fc61 100644 --- a/schemas/outfitting-README.md +++ b/schemas/outfitting-README.md @@ -11,9 +11,10 @@ documentation for a schema such as this. The primary data source for this schema is the ED Journal event `Outfitting`. -You MAY also source this data from the CAPI `/shipyard` endpoint. See -[commodity-README.md#using-capi-data](commodity-README.md#using-capi-data) -for guidance on this. +You MAY also source this data from the CAPI `/shipyard` endpoint. +Please read +[the guidance on checking for CAPI lag](README-EDDN-schemas.md#detecting-capi-data-lag) +before utilising CAPI data for EDDN messages. You only need the `name` key's value for each member of the `modules` array. diff --git a/schemas/shipyard-README.md b/schemas/shipyard-README.md index 295ff5a..33016a4 100644 --- a/schemas/shipyard-README.md +++ b/schemas/shipyard-README.md @@ -11,9 +11,10 @@ documentation for a schema such as this. The primary data source for this schema is the ED Journal event `Shipyard`. -You MAY also source this data from the CAPI `/shipyard` endpoint. See -[commodity-README.md#using-capi-data](commodity-README.md#using-capi-data) -for guidance on this. +You MAY also source this data from the CAPI `/shipyard` endpoint. +Please read +[the guidance on checking for CAPI lag](README-EDDN-schemas.md#detecting-capi-data-lag) +before utilising CAPI data for EDDN messages. You only need the `name` key's value for each member of the `PriceList` array (if using Journal, it will be from the `ships` array if using CAPI From d6a43c04d9b086d62f09223c28ffa3bdafdcb9e5 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 4 Nov 2021 11:14:47 +0000 Subject: [PATCH 28/81] schemas: README: Add 'Receiving messages' section --- schemas/README-EDDN-schemas.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index a7461d8..83f6742 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -201,3 +201,29 @@ Some of these requirements are also enforced by the schemas, and some things the schemas enforce might not be explicitly called out here, so **do** check what you're sending against the schema when implementing sending new events. + +## Receiving messages + +EDDN provides a continuous stream of information from uploaders. To use this +data you'll need to connect to the stream using ZeroMQ (a library is probably +available for your language of choice). + +The URL for the live Relay is: + + tcp://eddn.edcd.io:9500 + +Once you've connected to that you will receive messages. To access the +data you will first need to zlib-decompress each message. Then you will +have a textual JSON object as per the schemas. + +In general, check the guidance for [Uploading messages](#uploading-messages) +for the expected format of the messages. + +Consumers can utilise the `$schemaRef` value to determine which schema a +particular message is for. There is no need to validate the messages +against the schemas yourself, as that is performed on the EDDN Gateway. +Messages that do not pass the schema validation there are not forwarded to +receivers. + +There is [example code](https://github.com/EDCD/EDDN/tree/master/examples) +available for a variety of programming languages to help you get started. \ No newline at end of file From f8c1ce7a3e310ab8ab5ac9b47b3286aa3b295586 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 7 Nov 2021 16:22:14 +0000 Subject: [PATCH 29/81] Script for testing schemas --- contrib/test-schema.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 contrib/test-schema.py diff --git a/contrib/test-schema.py b/contrib/test-schema.py new file mode 100644 index 0000000..ebf0e51 --- /dev/null +++ b/contrib/test-schema.py @@ -0,0 +1,27 @@ +"""Check if a file's JSON message passes the given schema.""" +import simplejson +import sys +from jsonschema import FormatChecker, ValidationError +from jsonschema import validate as json_validate + +if len(sys.argv) < 2: + print( +f""" +Usage: {sys.argv[0]} + +Note that the entire file will be loaded by simpljson.load() and should +only contain one JSON object. +""" + ) + sys.exit(-1) + +schema_file_name = sys.argv[1] +test_file_name = sys.argv[2] + +with open(test_file_name, 'r') as test_file: + test_event = simplejson.load(test_file) + + with open(schema_file_name, 'r') as schema_file: + schema = simplejson.load(schema_file) + + json_validate(test_event, schema, format_checker=FormatChecker()) From fa118d01832234294bae7423267f18fa59de213c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 21 Dec 2021 09:37:08 +0000 Subject: [PATCH 30/81] schemas/codexentry: Clarify that what unset `status_body_name` means --- schemas/codexentry-README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schemas/codexentry-README.md b/schemas/codexentry-README.md index 1f3725e..58da99e 100644 --- a/schemas/codexentry-README.md +++ b/schemas/codexentry-README.md @@ -64,7 +64,7 @@ release, Update 7, plus one patch). away. 5. If Status.json does **not** have `BodyName` then clear `status_body_name`. 6. For a `CodexEntry` event: - 1. Check that `status_body_name` is set. If it is not, exit. + 1. Only if `status_body_name` is set: 1. Set the EDDN `codexentry` schema message `BodyName` to this value. 2. Check if it matches the `journal_body_name` value, and ONLY if they match, set `BodyID` in the EDDN `codexentry` @@ -121,4 +121,4 @@ So you might receive any of: 3. Both `BodyName` and `BodyID` keys present, with values. This SHOULD indicate a codex entry object which is on a body surface. -Adjust your local processing accordingly. \ No newline at end of file +Adjust your local processing accordingly. From 0e80c76cb564771465f61825e694227dcc3be312 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 6 Jan 2022 13:07:53 +0000 Subject: [PATCH 31/81] Gateway: Set bottle request limit to 1MiB --- src/eddn/Gateway.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 63d10d7..028e2f7 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -21,7 +21,9 @@ from eddn.core.Validator import Validator, ValidationSeverity from gevent import monkey monkey.patch_all() +import bottle from bottle import Bottle, run, request, response, get, post +bottle.BaseRequest.MEMFILE_MAX = 1024 * 1024 # 1MiB, default is/was 100KiB app = Bottle() logger = logging.getLogger(__name__) From 377bdd3833a721fc639376308745b17c2f248465 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 6 Jan 2022 13:54:33 +0000 Subject: [PATCH 32/81] Gateway: Add logging per Accepted request Actually some logging was already there, just the logger had never been set up properly, but then I decided to make the format of this message more useful. --- src/eddn/Gateway.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 028e2f7..93d22bc 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -27,6 +27,10 @@ bottle.BaseRequest.MEMFILE_MAX = 1024 * 1024 # 1MiB, default is/was 100KiB app = Bottle() logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) +logger.addHandler(logging.StreamHandler()) +logger.info('Made logger') + # This socket is used to push market data out to the Announcers over ZeroMQ. context = zmq.Context() @@ -151,10 +155,25 @@ def parse_and_error_handle(data): # Sends the parsed message to the Relay/Monitor as compressed JSON. gevent.spawn(push_message, parsed_message, parsed_message['$schemaRef']) - logger.info("Accepted %s upload from %s" % ( - parsed_message, get_remote_address() - )) + + try: + logger.info('Accepted (%d, "%s", "%s", "%s", "%s", "%s") upload from %s' % ( + request.content_length, + parsed_message['header']['uploaderID'], + parsed_message['header']['softwareName'], + parsed_message['header']['softwareVersion'], + parsed_message['$schemaRef'], + parsed_message['message']['event'] if '/journal' in + parsed_message['$schemaRef'] else '-', + get_remote_address() + )) + + except Exception as e: + print('Logging of Accepted request failed: %s' % (e.message)) + pass + return 'OK' + else: response.status = 400 statsCollector.tally("invalid") From 1371f71217286c2cb2f26ea0f7040fa28919922b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 6 Jan 2022 14:06:59 +0000 Subject: [PATCH 33/81] Gateway: Set up proper logger formatting For some reason the milliseconds portion of the %S timestamp is using a comma for decimals separator, despite 'locale' saying we're set to (US) English. /tableflip --- src/eddn/Gateway.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 93d22bc..9423c3b 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -28,7 +28,14 @@ app = Bottle() logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) -logger.addHandler(logging.StreamHandler()) +__logger_channel = logging.StreamHandler() +__logger_formatter = logging.Formatter( + '%(asctime)s - %(levelname)s - %(module)s:%(lineno)d: %(message)s' +) +__logger_formatter.default_time_format = '%Y-%m-%d %H:%M:%S' +__logger_formatter.default_msec_format = '%s.%03d' +__logger_channel.setFormatter(__logger_formatter) +logger.addHandler(__logger_channel) logger.info('Made logger') From 9f219da6a6cafba3d1b09fda2703270a401744cb Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 6 Jan 2022 17:36:39 +0000 Subject: [PATCH 34/81] Gateway: Expand on logging for interpretation of errors This includes logging the *full* (uncompressed) message if it fails to parse as JSON. --- src/eddn/Gateway.py | 94 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 9423c3b..96cb90e 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -51,6 +51,37 @@ statsCollector = StatsCollector() statsCollector.start() +def extract_message_details(parsed_message): + uploader_id = '<>' + software_name = '<>' + software_version = '<>' + schema_ref = '<>' + journal_event = '<>' + + if 'header' in parsed_message: + if 'uploaderID' in parsed_message['header']: + uploader_id = parsed_message['header']['uploaderID'] + + if 'softwareName' in parsed_message['header']: + software_name = parsed_message['header']['softwareName'] + + if 'softwareVersion' in parsed_message['header']: + software_version = parsed_message['header']['softwareVersion'] + + if '$schemaRef' in parsed_message: + schema_ref = parsed_message['$schemaRef'] + + + if '/journal/' in schema_ref: + if 'message' in parsed_message: + if 'event' in parsed_message['message']: + journal_event = parsed_message['message']['event'] + + else: + journal_event = '-' + + return uploader_id, software_name, software_version, schema_ref, journal_event + def configure(): # Get the list of transports to bind from settings. This allows us to PUB # messages to multiple announcers over a variety of socket types @@ -144,9 +175,24 @@ def parse_and_error_handle(data): ) as exc: # Something bad happened. We know this will return at least a # semi-useful error message, so do so. + try: + logger.error('Error - JSON parse failed (%d, "%s", "%s", "%s", "%s", "%s") from %s:\n%s\n' % ( + request.content_length, + '<>', + '<>', + '<>', + '<>', + '<>', + get_remote_address(), + data + )) + + except Exception as e: + print('Logging of "JSON parse failed" failed: %s' % (e.message)) + pass + response.status = 400 - logger.error("Error to %s: %s" % (get_remote_address(), exc.message)) - return str(exc) + return 'FAIL: ' + str(exc) # Here we check if an outdated schema has been passed if parsed_message["$schemaRef"] in Settings.GATEWAY_OUTDATED_SCHEMAS: @@ -164,14 +210,10 @@ def parse_and_error_handle(data): gevent.spawn(push_message, parsed_message, parsed_message['$schemaRef']) try: - logger.info('Accepted (%d, "%s", "%s", "%s", "%s", "%s") upload from %s' % ( + uploader_id, software_name, software_version, schema_ref, journal_event = extract_message_details(parsed_message) + logger.info('Accepted (%d, "%s", "%s", "%s", "%s", "%s") from %s' % ( request.content_length, - parsed_message['header']['uploaderID'], - parsed_message['header']['softwareName'], - parsed_message['header']['softwareVersion'], - parsed_message['$schemaRef'], - parsed_message['message']['event'] if '/journal' in - parsed_message['$schemaRef'] else '-', + uploader_id, software_name, software_version, schema_ref, journal_event, get_remote_address() )) @@ -182,6 +224,19 @@ def parse_and_error_handle(data): return 'OK' else: + try: + uploader_id, software_name, software_version, schema_ref, journal_event = extract_message_details(parsed_message) + logger.error('Failed Validation "%s" (%d, "%s", "%s", "%s", "%s", "%s") from %s' % ( + str(validationResults.messages), + request.content_length, + uploader_id, software_name, software_version, schema_ref, journal_event, + get_remote_address() + )) + + except Exception as e: + print('Logging of Failed Validation failed: %s' % (e.message)) + pass + response.status = 400 statsCollector.tally("invalid") return "FAIL: " + str(validationResults.messages) @@ -192,17 +247,34 @@ def upload(): try: # Body may or may not be compressed. message_body = get_decompressed_message() + except zlib.error as exc: # Some languages and libs do a crap job zlib compressing stuff. Provide # at least some kind of feedback for them to try to get pointed in # the correct direction. response.status = 400 - logger.error("gzip error with %s: %s" % (get_remote_address(), exc.message)) + try: + logger.error('gzip error (%d, "%s", "%s", "%s", "%s", "%s") from %s' % ( + request.content_length, + '<>', + '<>', + '<>', + '<>', + '<>', + get_remote_address() + )) + + except Exception as e: + print('Logging of "gzip error" failed: %s' % (e.message)) + pass + return exc.message + except MalformedUploadError as exc: # They probably sent an encoded POST, but got the key/val wrong. response.status = 400 - logger.error("Error to %s: %s" % (get_remote_address(), exc.message)) + logger.error("MalformedUploadError from %s: %s" % (get_remote_address(), exc.message)) + return exc.message statsCollector.tally("inbound") From 1134a6c9b46baf5704029e2ed3167661015c9a8f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 6 Jan 2022 17:39:01 +0000 Subject: [PATCH 35/81] Gateway: Only log first 512 characters of invalid JSON Don't want to spam the logs with up to 1MiB per bad message. --- src/eddn/Gateway.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 96cb90e..9aee4f5 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -184,7 +184,7 @@ def parse_and_error_handle(data): '<>', '<>', get_remote_address(), - data + data[:512] )) except Exception as e: From d2c4c98c2bac6ac5120cf737cdb5daced2c10142 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 7 Jan 2022 15:20:05 +0000 Subject: [PATCH 36/81] docs: Possible server responses, and handling them --- schemas/README-EDDN-schemas.md | 105 ++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 83f6742..6840a06 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -103,7 +103,8 @@ available from time to time as necessary, e.g. for testing new schemas or changes to existing ones. ### Sending data -To upload market data to EDDN, you'll need to make a POST request to the URL: +To upload market data to EDDN, you'll need to make a **POST** request to the +URL: * https://eddn.edcd.io:4430/upload/ @@ -114,6 +115,38 @@ The body of this is a JSON object, so you SHOULD set a `Content-Type` header of * `multipart/form-data` * `text/plain` +You *MAY* use gzip compression on the body of the message, but it is not +required. + +You should be prepared to handle all scenarios where sending of a message +fails: + +1. Connect refused. +2. Connection timed out. +3. Other possible responses as documented in + [Server responses](#server-responses). + +Carefully consider whether you should queue a 'failed' message for later +retry. In particular, you should ensure that one 'bad' message does not +block other messages from being successfully sent. + +You **MUST** wait some reasonable time (minimum 1 minute) before retrying +any failed message. + +You **MUST NOT** retry any message that received a HTTP `400` or `426` code. +An exception can be made if, **and only if**, *you have manually verified that +you have fixed the issues with it (i.e. updated the schema/version to a +currently supported one and adjusted the data to fit that schema/version).* + +You **MAY** retry a message that initially received a `413` response (in +the hopes that the EDDN service admins decided to increase the maximum +allowed request size), but should not do so too quickly or in perpetuity. + +In general: + +- No data is better than bad data. +- Delayed good data is better than degrading the EDDN service for others. + ### Format of uploaded messages Each message is a JSON object in utf-8 encoding containing the following key+value pairs: @@ -202,6 +235,76 @@ the schemas enforce might not be explicitly called out here, so **do** check what you're sending against the schema when implementing sending new events. +### Server responses +There are three possible sources of HTTP responses when sending an upload +to EDDN. + +1. The reverse proxy that initially accepts the request. +2. The python `bottle` module that the Gateway uses to process the + forwarded requests. This might object to a message before the actual + EDDN code gets to process it at all. +3. The actual EDDN Gateway code. + +Once a message has cleared the EDDN Gateway then there is no mechanism for any +further issue (such as a message being detected as a duplicate in the +Monitor downstream of the Gateway) to be reported back to the sender. + +To state the obvious, if there are no issues with a request then an HTTP +200 response will be received by the sender. + +#### Reverse Proxy responses +In addition to generic "you typoed the URL" and other such "you just didn't +make a valid request" responses you might experience the following: + +1. `408` - `Request Timed Out` - the sender took too long to make/complete + its request and the reverse proxy rejected it as a result. +2. `503` - `Service Unavailable` - the EDDN Gateway process is either not + running, or not responding. + +#### bottle responses +1. `413` - `Payload Too Large` - `bottle` enforces a maximum request size + and the request exceeds that. As of 2022-01-07 the limit is 1MiB, and + pertains to the plain-text size, not after gzip compression if used. + To verify the current limit check for the line that looks like: + + ``` + bottle.BaseRequest.MEMFILE_MAX = 1024 * 1024 # 1MiB, default is/was 100KiB + ``` + + in + [src/eddn/Gateway.py](https://github.com/EDCD/EDDN/blob/master/src/eddn/Gateway.py), + as added in + [commit 0e80c76cb564771465f61825e694227dcc3be312](https://github.com/EDCD/EDDN/commit/0e80c76cb564771465f61825e694227dcc3be312). + +#### EDDN Gateway responses +1. `400` - `Bad Request` - this can be for a variety of reasons, and should + come with a response body with prefix `OK: ` or `FAIL: `: + 1. `FAIL: ` - the request couldn't be + parsed as valid JSON. e.g. + + ``` + FAIL: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) + ``` + 2. `FAIL: ["]` - the JSON + message failed to pass schema validation. e.g. + + ``` + FAIL: [] + ``` + + 3. Other python exception message, e.g. if a message appeared to be + gzip compressed, but a failure was experienced when attempting to + decompress it. **NB: As of 2022-07-01 such messages won't have the + `FAIL: ` prefix.** + +2. `426` - `Upgrade Required` - You sent a message with an outdated + `$schemaRef` value. This could be either an old, deprecated version of + a schema, or an entirely deprecated schema. e.g. + + ``` + FAIL: The schema you have used is no longer supported. Please check for an updated version of your application. + ``` + ## Receiving messages EDDN provides a continuous stream of information from uploaders. To use this From 207068f156d630768d9b26be4e3dec14366b3e06 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 7 Jan 2022 15:37:07 +0000 Subject: [PATCH 37/81] docs: Cite issue on "some error bodies don't have FAIL: prefix" --- schemas/README-EDDN-schemas.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 6840a06..1fc48de 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -295,7 +295,9 @@ make a valid request" responses you might experience the following: 3. Other python exception message, e.g. if a message appeared to be gzip compressed, but a failure was experienced when attempting to decompress it. **NB: As of 2022-07-01 such messages won't have the - `FAIL: ` prefix.** + `FAIL: ` prefix.** See + [#161 - Gateway: Improve reporting of 'misc' errors ](https://github.com/EDCD/EDDN/issues/161) + for any progress/resolution on this. 2. `426` - `Upgrade Required` - You sent a message with an outdated `$schemaRef` value. This could be either an old, deprecated version of From 10b12cf74bdb12bc4915b755472a48fcec51a9b8 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 7 Jan 2022 16:04:00 +0000 Subject: [PATCH 38/81] Gateway: Properly report zlib.decompress() errors to uploaders This also adds some debug/error logging to the code path. --- src/eddn/Gateway.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 9aee4f5..63e8d3e 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -130,14 +130,18 @@ def get_decompressed_message(): content_encoding = request.headers.get('Content-Encoding', '') if content_encoding in ['gzip', 'deflate']: + logger.debug('Content-Encoding of gzip or deflate...') # Compressed request. We have to decompress the body, then figure out # if it's form-encoded. try: # Auto header checking. + logger.debug('Trying zlib.decompress (15 + 32)...') message_body = zlib.decompress(request.body.read(), 15 + 32) except zlib.error: + logger.error('zlib.error, trying zlib.decompress (-15)') # Negative wbits suppresses adler32 checksumming. message_body = zlib.decompress(request.body.read(), -15) + logger.debug('Resulting message_body:\n%s\n' % (message_body)) # At this point, we're not sure whether we're dealing with a straight # un-encoded POST body, or a form-encoded POST. Attempt to parse the @@ -268,7 +272,7 @@ def upload(): print('Logging of "gzip error" failed: %s' % (e.message)) pass - return exc.message + return 'FAIL: zlib.error: ' + exc.message except MalformedUploadError as exc: # They probably sent an encoded POST, but got the key/val wrong. From 872af7f5945dfbda4b213c1af9074435eb90679c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 7 Jan 2022 16:32:10 +0000 Subject: [PATCH 39/81] Gateway: Properly report 'badly form encoded' to uploaders This currently only applies if the data was also, validly, compressed. --- src/eddn/Gateway.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 63e8d3e..90e8ac1 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -128,6 +128,7 @@ def get_decompressed_message(): :returns: The de-compressed request body. """ content_encoding = request.headers.get('Content-Encoding', '') + logger.debug('Content-Encoding: ' + content_encoding) if content_encoding in ['gzip', 'deflate']: logger.debug('Content-Encoding of gzip or deflate...') @@ -148,6 +149,7 @@ def get_decompressed_message(): # body. If it's not form-encoded, this will return an empty dict. form_enc_parsed = urlparse.parse_qs(message_body) if form_enc_parsed: + logger.debug('Request is form-encoded') # This is a form-encoded POST. The value of the data attrib will # be the body we're looking for. try: @@ -157,6 +159,10 @@ def get_decompressed_message(): "No 'data' POST key/value found. Check your POST key " "name for spelling, and make sure you're passing a value." ) + + else: + logger.debug('Request is *NOT* form-encoded') + else: # Uncompressed request. Bottle handles all of the parsing of the # POST key/vals, or un-encoded body. @@ -279,7 +285,7 @@ def upload(): response.status = 400 logger.error("MalformedUploadError from %s: %s" % (get_remote_address(), exc.message)) - return exc.message + return 'FAIL: ' + exc.message statsCollector.tally("inbound") return parse_and_error_handle(message_body) From 10d70bfe77b0bd1a140ee3334e6a997d18f960f7 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 7 Jan 2022 16:45:37 +0000 Subject: [PATCH 40/81] Gateway: Properly report 'not compressed, badly form-encoded' to uploaders * This code worked if the request was *properly* form-encoded, with a 'data' key whose value was a valid message. * It failed to detect where the request was form-encoded, with without a 'data' key. It would just assume 'not form-encoded' in that case, then fail later on JSON parsing. Thus, re-use the `urlparse.parse_qs()` check for form-encoded format. This passes: 1. Properly, `data` key, form-encoded with valid value is fully JSON parsed, schema checked and accepted. 2. *NOT* compressed *or* form-encoded valid message is properly parsed and accepted. 2. Uncompressed, form-encoded, but no `data` key correctly returns the same error status and body as the compressed+form-encoded+no data key path. --- src/eddn/Gateway.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 90e8ac1..091088c 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -164,13 +164,28 @@ def get_decompressed_message(): logger.debug('Request is *NOT* form-encoded') else: - # Uncompressed request. Bottle handles all of the parsing of the - # POST key/vals, or un-encoded body. - data_key = request.forms.get('data') - if data_key: - # This is a form-encoded POST. Support the silly people. - message_body = data_key + logger.debug('Content-Encoding indicates *not* compressed...') + + form_enc_parsed = urlparse.parse_qs(request.body.read()) + if form_enc_parsed: + logger.debug('Request is form-encoded') + + # Uncompressed request. Bottle handles all of the parsing of the + # POST key/vals, or un-encoded body. + data_key = request.forms.get('data') + if data_key: + logger.debug('form-encoded POST request detected...') + # This is a form-encoded POST. Support the silly people. + message_body = data_key + + else: + raise MalformedUploadError( + "No 'data' POST key/value found. Check your POST key " + "name for spelling, and make sure you're passing a value." + ) + else: + logger.debug('Plain POST request detected...') # This is a non form-encoded POST body. message_body = request.body.read() From 1bb8a37c34aee5848ce371d0e9a4ead3efcfcba6 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 13:09:04 +0000 Subject: [PATCH 41/81] scripts: Add eddn-report-log-errors This looks at gateway.log files for any 'ERROR' lines. The output should be any lines representing an error that hasn't yet been reported to the softwareName's developer. NB: Absolutely relies on the developer changing the softwareVersion after applying a fix. --- eddn-report-log-errors | 191 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100755 eddn-report-log-errors diff --git a/eddn-report-log-errors b/eddn-report-log-errors new file mode 100755 index 0000000..5d2186f --- /dev/null +++ b/eddn-report-log-errors @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +# vim: wrapmargin=0 textwidth=0 smarttab expandtab tabstop=2 shiftwidth=2 +"""Produce a report on the provided EDDN Gateway log file's ERRORs.""" + +import argparse +import re + + +def parse_cl_args() -> str: + """ + Check command-line arguments for input file name. + + :returns: str - input file name + """ + parser = argparse.ArgumentParser( + prog='eddn-report-log-errors', + description='Process an EDDN Gateway log file and report on any ERROR lines found' + ) + + parser.add_argument( + 'inputfile', + metavar='', + help='Name of an EDDN Gateway log file' + ) + + args = parser.parse_args() + + return args.inputfile + + +def process_file(input_file: str) -> None: + print(f'Input file: {input_file}') + + _RE_ERROR = re.compile( + r'^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}[\.,][0-9]{3} - ERROR - Gateway:[0-9]+:' + r' (?P.+)' + r' \((?P[0-9]+),' + r' "(?P[^"]*)",' + r' "(?P[^"]*)",' + r' "(?P[^"]*)",' + r' "(?P[^"]*)",' + r' "(?P[^"]*)"\)' + r' from (?P.+)$' + ) + # TODO: Make this handle gzipped files + with open(input_file, 'r') as input: + line = input.readline() + while line: + line = line.strip() + matches = _RE_ERROR.search(line) + if matches: + # print(matches.group('err_msg')) + # print(matches.group('request_size')) + # print(matches.group('uploader_id')) + # print(matches.group('software_name')) + # print(matches.group('software_version')) + # print(matches.group('schema_ref')) + # print(matches.group('journal_event')) + # print(matches.group('sender_ip')) + # print('') + + ################################################################### + # Issues we know about and HAVE already alerted their + # developers to. + ################################################################### + if matches.group('software_name') == 'EDDiscovery': + # https://github.com/EDDiscovery/EDDiscovery/releases/latest + if matches.group('software_version') == '12.1.7.0': + if matches.group('schema_ref') in ( + 'https://eddn.edcd.io/schemas/shipyard/2', + 'https://eddn.edcd.io/schemas/outfitting/2', + ): + # Reported via Discord PM to Robby 2022-01-07 + if matches.group('err_msg') != 'Failed Validation "[]"': + print(line) + + else: + print(line) + + elif matches.group('software_name') == 'EDDLite': + # https://github.com/EDDiscovery/EDDLite/releases/tag/latest + if matches.group('software_version') == '2.0.0': + if matches.group('schema_ref') in ( + 'https://eddn.edcd.io/schemas/shipyard/2', + 'https://eddn.edcd.io/schemas/outfitting/2', + ): + # Reported via Discord PM to Robby 2022-01-07 + if matches.group('err_msg') != 'Failed Validation "[]"': + print(line) + + else: + print(line) + + elif matches.group('software_name') == 'EDDI': + # https://github.com/EDCD/EDDI/releases/latest + if matches.group('software_version') == '4.0.1': + print(line) + + elif matches.group('software_name') == 'E:D Market Connector [Windows]': + # https://github.com/EDCD/EDMarketConnector/releases/latest + if matches.group('software_version') == '5.2.4': + if matches.group('schema_ref') == 'https://eddn.edcd.io/schemas/codexentry/1': + # + if matches.group('err_msg') != 'Failed Validation "[]"': + print(matches.group('err_msg')) + print(line) + + else: + print(line) + + elif matches.group('software_name') == 'Elite G19s Companion App': + # + if matches.group('software_version') == '3.7.7888.21039': + if matches.group('schema_ref') == 'https://eddn.edcd.io/schemas/commodity/3': + # Reported via Frontier forums: + if matches.group('err_msg') != 'Failed Validation "[]"': + print(matches.group('err_msg')) + print(line) + + else: + print(line) + + elif matches.group('software_name') == 'EDSM': + # It's in-browser, no public source/releases + if matches.group('software_version') == '1.0.1': + if matches.group('schema_ref') == 'https://eddn.edcd.io/schemas/journal/1': + if matches.group('journal_event') == 'Scan': + # + if not matches.group('err_msg').startswith( + 'Failed Validation "[ + if not matches.group('err_msg').startswith( + 'Failed Validation "[ + if not matches.group('err_msg').startswith( + 'Failed Validation "[ Date: Sun, 9 Jan 2022 13:19:40 +0000 Subject: [PATCH 42/81] setup.py: Add 'enforce correct branch' TODO --- setup.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/setup.py b/setup.py index bb187fe..b6bcab4 100644 --- a/setup.py +++ b/setup.py @@ -4,6 +4,13 @@ import re import shutil from setuptools import setup, find_packages +# TODO: Enforce only using the `live` branch if `live` is in cwd, or +# `beta` branch if `beta` is in cwd. +# The idea is to have the `live` branch, *which includes documentation* +# always match what is actually running as the live service (modulo the +# small window between pull/install/restart). Thus it shouldn't use +# `master` which may have changes merged some time before they become +# live. VERSIONFILE = "src/eddn/conf/Version.py" verstr = "unknown" From 36de2145d7d8c3c789c9b270032a1e050447da2e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 14:52:41 +0000 Subject: [PATCH 43/81] docs: schemas: General improvement pass to aid new developers * Make lots of 'obvious' things explicit, e.g. HTTP 1.1, not HTTP/2, and HTTPS not plain HTTP. * The live service should always be using the schemas as present in the live branch, not master or another branch. * A 'good' message will receive 'HTTP 200' status *and* a body of `OK`. --- schemas/README-EDDN-schemas.md | 74 +++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 1fc48de..172224a 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -98,30 +98,43 @@ value, e.g. "$schemaRef": "https://eddn.edcd.io/schemas/shipyard/2/test", You MUST also utilise these test forms of the schemas when first testing your -code. There might also be a beta.eddn.edcd.io, or dev.eddn.edcd.io, service +code. + +There might also be a beta.eddn.edcd.io, or dev.eddn.edcd.io, service available from time to time as necessary, e.g. for testing new schemas or -changes to existing ones. +changes to existing ones. Ask on the `#eddn` channel of the EDCD Discord +(see https://edcd.github.io/ for an invite link). + +Alternatively you could attempt +[running your own test instance of EDDN](../docs/Running-this-software.md). ### Sending data -To upload market data to EDDN, you'll need to make a **POST** request to the -URL: +Messages sent to EDDN **MUST**: -* https://eddn.edcd.io:4430/upload/ +- Use the URL: `https://eddn.edcd.io:4430/upload/`. Note the use of + TLS-encrypted HTTPS. A plain HTTP request will elicit a `400 Bad + Request` response. +- Use the HTTP 1.1 protocol. HTTP/2 is not supported at this time. +- Use a **POST** request, with the body containing the EDDN message. No + query parameters in the URL are supported or necessary. -The body of this is a JSON object, so you SHOULD set a `Content-Type` header of -`applicaton/json`, and NOT any of: +The body of an EDDN message is a JSON object in UTF-8 encoding. You SHOULD +set a `Content-Type` header of `applicaton/json`, and NOT any of: * `application/x-www-form-urlencoded` * `multipart/form-data` * `text/plain` +For historical reasons URL form-encoded data *is* supported, **but this is +deprecated and no new software should attempt this method**. + You *MAY* use gzip compression on the body of the message, but it is not required. You should be prepared to handle all scenarios where sending of a message fails: -1. Connect refused. +1. Connection refused. 2. Connection timed out. 3. Other possible responses as documented in [Server responses](#server-responses). @@ -145,10 +158,10 @@ allowed request size), but should not do so too quickly or in perpetuity. In general: - No data is better than bad data. -- Delayed good data is better than degrading the EDDN service for others. +- *Delayed* good data is better than degrading the EDDN service for others. ### Format of uploaded messages -Each message is a JSON object in utf-8 encoding containing the following +Each message is a JSON object in UTF-8 encoding containing the following key+value pairs: 1. `$schemaRef` - Which schema (including version) this message is for. @@ -202,10 +215,17 @@ For example, a shipyard message, version 2, might look like: ``` ### Contents of `message` +Every message MUST comply with the schema its `$schemaRef` value cites. + +Apart from short time windows during deployment of a new version the live +EDDN service should always be using +[the schemas as present in the live branch](https://github.com/EDCD/EDDN/tree/live/schemas). +So, be sure you're checking those and not, e.g. those in the `master` or +other branches. Each `message` object must have, at bare minimum: -1. `timestamp` - string date and time in ISO8601 format. Whilst that +1. `timestamp` - string date and time in ISO8601 format. Whilst this technically allows for any timezone to be cited you SHOULD provide this in UTC, aka 'Zulu Time' as in the example above. You MUST ensure that you are doing this properly. Do not claim 'Z' whilst actually using a local time @@ -213,27 +233,32 @@ Each `message` object must have, at bare minimum: Listeners MAY make decisions on accepting data based on this time stamp, i.e. "too old". -2. One other key/value pair representing the data. In general there will be - much more than this. Again, consult the +2. At least one other key/value pair representing the data. In general there + will be much more than this. Consult the [schemas and their documentation](./). -Note that many of the key names chosen in the schemas are based on the CAPI -data, not Journal events, because the CAPI came first. This means renaming -many of the keys from Journal events to match the schema. +Because the first versions of some schemas were defined when only the CAPI +data was available, before Journal files existed, many of the key names chosen +in the schemas are based on the equivalent in CAPI data, not Journal events. +This means ouy MUST rename many of the keys from Journal events to match the +schemas. EDDN is intended to transport generic data not specific to any particular Cmdr -and to reflect the data that a player would see in-game in station services or -the local map. To that end, uploading applications MUST ensure that messages do -not contain any Cmdr-specific data (other than "uploaderID" and the "horizons" -flag). +and to reflect only the data that every player would see in-game in station +services or the local map. To that end, uploading applications MUST ensure +that messages do not contain any Cmdr-specific data (other than "uploaderID", +the "horizons" flag, and the "odyssey" flag). The individual schemas will instruct you on various elisions (removals) to be made to comply with this. Some of these requirements are also enforced by the schemas, and some things -the schemas enforce might not be explicitly called out here, so **do** -check what you're sending against the schema when implementing sending new -events. +the schemas enforce might not be explicitly called out here. So, **do** +check what you're sending against the relevant schema(s) when making any +changes to your code. + +It is also advisable to Watch this repository on GitHub so as to be aware +of any changes to schemas. ### Server responses There are three possible sources of HTTP responses when sending an upload @@ -250,7 +275,8 @@ further issue (such as a message being detected as a duplicate in the Monitor downstream of the Gateway) to be reported back to the sender. To state the obvious, if there are no issues with a request then an HTTP -200 response will be received by the sender. +200 response will be received by the sender. The body of the response +should be the string `OK`. #### Reverse Proxy responses In addition to generic "you typoed the URL" and other such "you just didn't From 44b5a1d789ecef5a1246a6e2c2089a97bdccb079 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 14:57:05 +0000 Subject: [PATCH 44/81] docs/schemas: slight wording tweak about live schemas --- schemas/README-EDDN-schemas.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 172224a..1c51fc8 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -220,8 +220,8 @@ Every message MUST comply with the schema its `$schemaRef` value cites. Apart from short time windows during deployment of a new version the live EDDN service should always be using [the schemas as present in the live branch](https://github.com/EDCD/EDDN/tree/live/schemas). -So, be sure you're checking those and not, e.g. those in the `master` or -other branches. +So, be sure you're checking the live versions and not, e.g. those in the +`master` or other branches. Each `message` object must have, at bare minimum: From c6a63c5a9339ce96bd96dd3cd9b7f15bdf66a200 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 15:25:55 +0000 Subject: [PATCH 45/81] docs/schemas: Journal timestamps *are* trustworthy as UTC --- schemas/README-EDDN-schemas.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 1c51fc8..0a1ead9 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -231,6 +231,13 @@ Each `message` object must have, at bare minimum: doing this properly. Do not claim 'Z' whilst actually using a local time that is offset from UTC. + If you are only utilising Journal-sourced data then simply using the + value from there should be sufficient as the PC game client is meant to + always be correctly citing UTC for this. Indeed it has been observed, + in the Odyssey 4.0.0.1002 client, that with the Windows clock behind UTC + by 21 seconds both the in-game UI clock *and* the Journal event + timestamps are still properly UTC to the nearest second. + Listeners MAY make decisions on accepting data based on this time stamp, i.e. "too old". 2. At least one other key/value pair representing the data. In general there From 613ef6deabcdb372f786dcecc2bd0a8cf002bb13 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 7 Jan 2022 16:04:00 +0000 Subject: [PATCH 46/81] Gateway: Properly report zlib.decompress() errors to uploaders This also adds some debug/error logging to the code path. --- src/eddn/Gateway.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 9aee4f5..63e8d3e 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -130,14 +130,18 @@ def get_decompressed_message(): content_encoding = request.headers.get('Content-Encoding', '') if content_encoding in ['gzip', 'deflate']: + logger.debug('Content-Encoding of gzip or deflate...') # Compressed request. We have to decompress the body, then figure out # if it's form-encoded. try: # Auto header checking. + logger.debug('Trying zlib.decompress (15 + 32)...') message_body = zlib.decompress(request.body.read(), 15 + 32) except zlib.error: + logger.error('zlib.error, trying zlib.decompress (-15)') # Negative wbits suppresses adler32 checksumming. message_body = zlib.decompress(request.body.read(), -15) + logger.debug('Resulting message_body:\n%s\n' % (message_body)) # At this point, we're not sure whether we're dealing with a straight # un-encoded POST body, or a form-encoded POST. Attempt to parse the @@ -268,7 +272,7 @@ def upload(): print('Logging of "gzip error" failed: %s' % (e.message)) pass - return exc.message + return 'FAIL: zlib.error: ' + exc.message except MalformedUploadError as exc: # They probably sent an encoded POST, but got the key/val wrong. From faa2e25d62ce01514e58de8c2cf1eb52e1ff32a1 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 7 Jan 2022 16:32:10 +0000 Subject: [PATCH 47/81] Gateway: Properly report 'badly form encoded' to uploaders This currently only applies if the data was also, validly, compressed. --- src/eddn/Gateway.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 63e8d3e..90e8ac1 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -128,6 +128,7 @@ def get_decompressed_message(): :returns: The de-compressed request body. """ content_encoding = request.headers.get('Content-Encoding', '') + logger.debug('Content-Encoding: ' + content_encoding) if content_encoding in ['gzip', 'deflate']: logger.debug('Content-Encoding of gzip or deflate...') @@ -148,6 +149,7 @@ def get_decompressed_message(): # body. If it's not form-encoded, this will return an empty dict. form_enc_parsed = urlparse.parse_qs(message_body) if form_enc_parsed: + logger.debug('Request is form-encoded') # This is a form-encoded POST. The value of the data attrib will # be the body we're looking for. try: @@ -157,6 +159,10 @@ def get_decompressed_message(): "No 'data' POST key/value found. Check your POST key " "name for spelling, and make sure you're passing a value." ) + + else: + logger.debug('Request is *NOT* form-encoded') + else: # Uncompressed request. Bottle handles all of the parsing of the # POST key/vals, or un-encoded body. @@ -279,7 +285,7 @@ def upload(): response.status = 400 logger.error("MalformedUploadError from %s: %s" % (get_remote_address(), exc.message)) - return exc.message + return 'FAIL: ' + exc.message statsCollector.tally("inbound") return parse_and_error_handle(message_body) From 81a70572c92bf42e7e0b18f8b8f35943037a0a2c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 7 Jan 2022 16:45:37 +0000 Subject: [PATCH 48/81] Gateway: Properly report 'not compressed, badly form-encoded' to uploaders * This code worked if the request was *properly* form-encoded, with a 'data' key whose value was a valid message. * It failed to detect where the request was form-encoded, with without a 'data' key. It would just assume 'not form-encoded' in that case, then fail later on JSON parsing. Thus, re-use the `urlparse.parse_qs()` check for form-encoded format. This passes: 1. Properly, `data` key, form-encoded with valid value is fully JSON parsed, schema checked and accepted. 2. *NOT* compressed *or* form-encoded valid message is properly parsed and accepted. 2. Uncompressed, form-encoded, but no `data` key correctly returns the same error status and body as the compressed+form-encoded+no data key path. --- src/eddn/Gateway.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 90e8ac1..091088c 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -164,13 +164,28 @@ def get_decompressed_message(): logger.debug('Request is *NOT* form-encoded') else: - # Uncompressed request. Bottle handles all of the parsing of the - # POST key/vals, or un-encoded body. - data_key = request.forms.get('data') - if data_key: - # This is a form-encoded POST. Support the silly people. - message_body = data_key + logger.debug('Content-Encoding indicates *not* compressed...') + + form_enc_parsed = urlparse.parse_qs(request.body.read()) + if form_enc_parsed: + logger.debug('Request is form-encoded') + + # Uncompressed request. Bottle handles all of the parsing of the + # POST key/vals, or un-encoded body. + data_key = request.forms.get('data') + if data_key: + logger.debug('form-encoded POST request detected...') + # This is a form-encoded POST. Support the silly people. + message_body = data_key + + else: + raise MalformedUploadError( + "No 'data' POST key/value found. Check your POST key " + "name for spelling, and make sure you're passing a value." + ) + else: + logger.debug('Plain POST request detected...') # This is a non form-encoded POST body. message_body = request.body.read() From 8edae919e2879b33c0aedf84159ed03621e9715c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 15:38:29 +0000 Subject: [PATCH 49/81] Gateway/errors: Call out if FAIL is specifically on JSON parsing --- schemas/README-EDDN-schemas.md | 8 ++++---- src/eddn/Gateway.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 0a1ead9..a1d6da7 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -311,12 +311,12 @@ make a valid request" responses you might experience the following: #### EDDN Gateway responses 1. `400` - `Bad Request` - this can be for a variety of reasons, and should - come with a response body with prefix `OK: ` or `FAIL: `: - 1. `FAIL: ` - the request couldn't be - parsed as valid JSON. e.g. + come with a response body with a `FAIL: ` prefix: + 1. `FAIL: JSON parsing: ` - the + request couldn't be parsed as valid JSON. e.g. ``` - FAIL: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) + FAIL: JSON parsing: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) ``` 2. `FAIL: ["]` - the JSON message failed to pass schema validation. e.g. diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 091088c..7541000 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -217,7 +217,7 @@ def parse_and_error_handle(data): pass response.status = 400 - return 'FAIL: ' + str(exc) + return 'FAIL: JSON parsing: ' + str(exc) # Here we check if an outdated schema has been passed if parsed_message["$schemaRef"] in Settings.GATEWAY_OUTDATED_SCHEMAS: From 4da60215f0dfb4fc8cd39a2ecefba0ad270dbe60 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 15:43:12 +0000 Subject: [PATCH 50/81] Gateway/errors: Tag FAIL if a zlib.error --- schemas/README-EDDN-schemas.md | 23 +++++++++++++---------- src/eddn/Gateway.py | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index a1d6da7..388a498 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -312,27 +312,30 @@ make a valid request" responses you might experience the following: #### EDDN Gateway responses 1. `400` - `Bad Request` - this can be for a variety of reasons, and should come with a response body with a `FAIL: ` prefix: - 1. `FAIL: JSON parsing: ` - the + 1. `FAIL: zlib.error: ` - A failure to decompress a message that + claimed to be compressed. + + 2. `FAIL: JSON parsing: ` - the request couldn't be parsed as valid JSON. e.g. - ``` - FAIL: JSON parsing: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) - ``` - 2. `FAIL: ["]` - the JSON + ``` + FAIL: JSON parsing: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) + ``` + 3. `FAIL: ["]` - the JSON message failed to pass schema validation. e.g. - ``` - FAIL: [] - ``` + ``` + FAIL: [] + ``` - 3. Other python exception message, e.g. if a message appeared to be + 4. Other python exception message, e.g. if a message appeared to be gzip compressed, but a failure was experienced when attempting to decompress it. **NB: As of 2022-07-01 such messages won't have the `FAIL: ` prefix.** See [#161 - Gateway: Improve reporting of 'misc' errors ](https://github.com/EDCD/EDDN/issues/161) for any progress/resolution on this. -2. `426` - `Upgrade Required` - You sent a message with an outdated +3. `426` - `Upgrade Required` - You sent a message with an outdated `$schemaRef` value. This could be either an old, deprecated version of a schema, or an entirely deprecated schema. e.g. diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 7541000..f34c514 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -300,7 +300,7 @@ def upload(): response.status = 400 logger.error("MalformedUploadError from %s: %s" % (get_remote_address(), exc.message)) - return 'FAIL: ' + exc.message + return 'FAIL: Malformed Upload: ' + exc.message statsCollector.tally("inbound") return parse_and_error_handle(message_body) From b9b59329d529c9be31399edf8f4e5c391275a14e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 15:43:51 +0000 Subject: [PATCH 51/81] Gateway/errors: Document 'Malformed Upload' error --- schemas/README-EDDN-schemas.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 388a498..c731ec4 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -315,20 +315,24 @@ make a valid request" responses you might experience the following: 1. `FAIL: zlib.error: ` - A failure to decompress a message that claimed to be compressed. - 2. `FAIL: JSON parsing: ` - the + 2. `FAIL: Malformed Upload: ` - the message looked to be + form-encoded, but either the format was bad or there was no `data` + key. + + 3. `FAIL: JSON parsing: ` - the request couldn't be parsed as valid JSON. e.g. ``` FAIL: JSON parsing: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) ``` - 3. `FAIL: ["]` - the JSON + 4. `FAIL: ["]` - the JSON message failed to pass schema validation. e.g. ``` FAIL: [] ``` - 4. Other python exception message, e.g. if a message appeared to be + 5. Other python exception message, e.g. if a message appeared to be gzip compressed, but a failure was experienced when attempting to decompress it. **NB: As of 2022-07-01 such messages won't have the `FAIL: ` prefix.** See From e931bfff96f2f211a04ad020216ea31d156d86a8 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 15:45:56 +0000 Subject: [PATCH 52/81] Gateway/errors: MalformedUploadError isn't raised upon JSON issue --- src/eddn/Gateway.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index f34c514..a45f9c7 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -196,7 +196,7 @@ def parse_and_error_handle(data): try: parsed_message = simplejson.loads(data) except ( - MalformedUploadError, TypeError, ValueError + TypeError, ValueError ) as exc: # Something bad happened. We know this will return at least a # semi-useful error message, so do so. From e111fb84152092ae44cdda290835b592bc9d2607 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 15:48:27 +0000 Subject: [PATCH 53/81] Gateway/errors: Outdate Schema: Tweak message and document --- schemas/README-EDDN-schemas.md | 8 ++++++-- src/eddn/Gateway.py | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index c731ec4..9810dfb 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -325,14 +325,18 @@ make a valid request" responses you might experience the following: ``` FAIL: JSON parsing: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) ``` - 4. `FAIL: ["]` - the JSON + + 4. `FAIL: Outdated Schema: ` - message cites a schema (or + version of) that is no longer supported. + + 6. `FAIL: ["]` - the JSON message failed to pass schema validation. e.g. ``` FAIL: [] ``` - 5. Other python exception message, e.g. if a message appeared to be + 6. Other python exception message, e.g. if a message appeared to be gzip compressed, but a failure was experienced when attempting to decompress it. **NB: As of 2022-07-01 such messages won't have the `FAIL: ` prefix.** See diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index a45f9c7..53c9981 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -223,7 +223,8 @@ def parse_and_error_handle(data): if parsed_message["$schemaRef"] in Settings.GATEWAY_OUTDATED_SCHEMAS: response.status = '426 Upgrade Required' # Bottle (and underlying httplib) don't know this one statsCollector.tally("outdated") - return "FAIL: The schema you have used is no longer supported. Please check for an updated version of your application." + return "FAIL: Outdated Schema: The schema you have used is no longer supported. Please check for an updated " \ + "version of your application." validationResults = validator.validate(parsed_message) From ccde820ba7c704d895d7c891fa800fa4bdfd4b66 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 16:02:28 +0000 Subject: [PATCH 54/81] Gateway/errors: 'Schema Validation' properly tagged and documented --- schemas/README-EDDN-schemas.md | 37 ++++++++++++++++++++++------------ src/eddn/Gateway.py | 2 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 9810dfb..ceade0b 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -320,28 +320,32 @@ make a valid request" responses you might experience the following: key. 3. `FAIL: JSON parsing: ` - the - request couldn't be parsed as valid JSON. e.g. + message couldn't be parsed as valid JSON. e.g. ``` FAIL: JSON parsing: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) ``` - 4. `FAIL: Outdated Schema: ` - message cites a schema (or - version of) that is no longer supported. + 4. `FAIL: Schema Validation: ` - the message failed to validate + against the cited schema. e.g. + + ``` + FAIL: Schema Validation: [] + ``` + + The exact detail will be very much dependent on both the schema the + message cited and the contents of the message that failed to pass the + validation. - 6. `FAIL: ["]` - the JSON - message failed to pass schema validation. e.g. + In particular, if the message contains a key that is tagged 'disallowed' in + the schema the response will look like: ``` - FAIL: [] + FAIL: Schema Validation: "[]" ``` - - 6. Other python exception message, e.g. if a message appeared to be - gzip compressed, but a failure was experienced when attempting to - decompress it. **NB: As of 2022-07-01 such messages won't have the - `FAIL: ` prefix.** See - [#161 - Gateway: Improve reporting of 'misc' errors ](https://github.com/EDCD/EDDN/issues/161) - for any progress/resolution on this. + This is due to the use of a JSON schema stanza that says "don't allow + any valid type for the value of this key" to trigger the error for such + disallowed keys. 3. `426` - `Upgrade Required` - You sent a message with an outdated `$schemaRef` value. This could be either an old, deprecated version of @@ -350,6 +354,13 @@ make a valid request" responses you might experience the following: ``` FAIL: The schema you have used is no longer supported. Please check for an updated version of your application. ``` + 4. `FAIL: Outdated Schema: ` - message cites a schema (or + version of) that is no longer supported. + + +There shouldn't be any other variants of a 'FAIL' message. If you find +any then please open an issue with as much detail as possible so we can +update this documentation. ## Receiving messages diff --git a/src/eddn/Gateway.py b/src/eddn/Gateway.py index 53c9981..ee360f1 100644 --- a/src/eddn/Gateway.py +++ b/src/eddn/Gateway.py @@ -265,7 +265,7 @@ def parse_and_error_handle(data): response.status = 400 statsCollector.tally("invalid") - return "FAIL: " + str(validationResults.messages) + return "FAIL: Schema Validation: " + str(validationResults.messages) @app.route('/upload/', method=['OPTIONS', 'POST']) From 4ad1519d1db859e83426da7b9ba3a538701c496c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 16:10:01 +0000 Subject: [PATCH 55/81] Gateway/errors: Improve general outline of documentation section --- schemas/README-EDDN-schemas.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index ceade0b..63e5955 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -310,8 +310,11 @@ make a valid request" responses you might experience the following: [commit 0e80c76cb564771465f61825e694227dcc3be312](https://github.com/EDCD/EDDN/commit/0e80c76cb564771465f61825e694227dcc3be312). #### EDDN Gateway responses -1. `400` - `Bad Request` - this can be for a variety of reasons, and should - come with a response body with a `FAIL: ` prefix: +For all failures the response body will contain text that begins `FAIL: `. + +1. `400` - `Bad Request` - This indicates something wrong with the request + body. Possibly due to a format issue (compression, form encoding), or + the actual content of the EDDN message: 1. `FAIL: zlib.error: ` - A failure to decompress a message that claimed to be compressed. @@ -347,15 +350,16 @@ make a valid request" responses you might experience the following: any valid type for the value of this key" to trigger the error for such disallowed keys. -3. `426` - `Upgrade Required` - You sent a message with an outdated - `$schemaRef` value. This could be either an old, deprecated version of - a schema, or an entirely deprecated schema. e.g. +2. `426` - `Upgrade Required` - This indicates that the cited schema, or + version thereof, is outdated. The body of the response will be: ``` - FAIL: The schema you have used is no longer supported. Please check for an updated version of your application. + FAIL: Oudated Schema: The schema you have used is no longer supported. Please check for an updated version of your application. ``` - 4. `FAIL: Outdated Schema: ` - message cites a schema (or - version of) that is no longer supported. + The wording here is aimed at users of applications that send messages + over EDDN. If you're the developer of such an application then + obviously you need to update your code to use a currently supported + schema and version thereof. There shouldn't be any other variants of a 'FAIL' message. If you find From 11d3501c59565621137066cc682711b56d7e0fda Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 16:13:01 +0000 Subject: [PATCH 56/81] Gateway/errors: More documentation tweaking --- schemas/README-EDDN-schemas.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 63e5955..99aaeb3 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -310,7 +310,7 @@ make a valid request" responses you might experience the following: [commit 0e80c76cb564771465f61825e694227dcc3be312](https://github.com/EDCD/EDDN/commit/0e80c76cb564771465f61825e694227dcc3be312). #### EDDN Gateway responses -For all failures the response body will contain text that begins `FAIL: `. +For all failures the response body will contain text that begins `FAIL: `. Currently two different HTTP status codes are utilised: 1. `400` - `Bad Request` - This indicates something wrong with the request body. Possibly due to a format issue (compression, form encoding), or @@ -318,7 +318,7 @@ For all failures the response body will contain text that begins `FAIL: `. 1. `FAIL: zlib.error: ` - A failure to decompress a message that claimed to be compressed. - 2. `FAIL: Malformed Upload: ` - the message looked to be + 2. `FAIL: Malformed Upload: ` - the message appeared to be form-encoded, but either the format was bad or there was no `data` key. @@ -363,8 +363,9 @@ For all failures the response body will contain text that begins `FAIL: `. There shouldn't be any other variants of a 'FAIL' message. If you find -any then please open an issue with as much detail as possible so we can -update this documentation. +any then please +[open an issue on GitHub](https://github.com/EDCD/EDDN/issues/new) +with as much detail as possible so that we can update this documentation. ## Receiving messages From 75c117fb1214bf84156b98b603bf97ce6d39e7ce Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 16:14:00 +0000 Subject: [PATCH 57/81] docs/schemas: form-encoded messages are deprecated and not documented At some point I might add logging to see if any sender even *is* utilising this, and if not actually remove the possibility entirely. --- schemas/README-EDDN-schemas.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/schemas/README-EDDN-schemas.md b/schemas/README-EDDN-schemas.md index 99aaeb3..170955f 100644 --- a/schemas/README-EDDN-schemas.md +++ b/schemas/README-EDDN-schemas.md @@ -126,7 +126,8 @@ set a `Content-Type` header of `applicaton/json`, and NOT any of: * `text/plain` For historical reasons URL form-encoded data *is* supported, **but this is -deprecated and no new software should attempt this method**. +deprecated and no new software should attempt this method**. We +purposefully do not further document the exact format for this. You *MAY* use gzip compression on the body of the message, but it is not required. From 2a8eb8d021fa9404c19fb35239d79c95be0edb80 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 9 Jan 2022 16:21:23 +0000 Subject: [PATCH 58/81] Gateway: Add test scripts and supporting files These are what I was using on my home server to test the prior code changes to how the Gateway code reports errors. Ultimately these should become a part of proper tests, but for now they're at least in the repository for anyone to utilise. --- scripts/testing/gateway-responses/Market.json | 330 + .../commodity-outdated-schema.json | 46 + .../commodity-too-large.json | 6576 +++++++++++++++++ .../market.json-to-schema.py | 50 + .../gateway-responses/scan-invalid-JSON.json | 37 + .../scan-invalid-no-softwarename.json | 36 + .../scan-invalid-no-starpos.json | 37 + .../testing/gateway-responses/scan-valid.json | 37 + .../gateway-responses/test-bad-gzip.py | 24 + .../gateway-responses/test-bad-gzip.sh | 6 + .../test-gzip-bad-formdata.py | 37 + .../test-gzip-correct-formdata.py | 37 + .../test-plain-bad-formdata.py | 29 + .../test-plain-correct-formdata.py | 29 + .../testing/gateway-responses/test-sender.py | 20 + 15 files changed, 7331 insertions(+) create mode 100644 scripts/testing/gateway-responses/Market.json create mode 100644 scripts/testing/gateway-responses/commodity-outdated-schema.json create mode 100644 scripts/testing/gateway-responses/commodity-too-large.json create mode 100644 scripts/testing/gateway-responses/market.json-to-schema.py create mode 100644 scripts/testing/gateway-responses/scan-invalid-JSON.json create mode 100644 scripts/testing/gateway-responses/scan-invalid-no-softwarename.json create mode 100644 scripts/testing/gateway-responses/scan-invalid-no-starpos.json create mode 100644 scripts/testing/gateway-responses/scan-valid.json create mode 100644 scripts/testing/gateway-responses/test-bad-gzip.py create mode 100644 scripts/testing/gateway-responses/test-bad-gzip.sh create mode 100644 scripts/testing/gateway-responses/test-gzip-bad-formdata.py create mode 100644 scripts/testing/gateway-responses/test-gzip-correct-formdata.py create mode 100644 scripts/testing/gateway-responses/test-plain-bad-formdata.py create mode 100644 scripts/testing/gateway-responses/test-plain-correct-formdata.py create mode 100644 scripts/testing/gateway-responses/test-sender.py diff --git a/scripts/testing/gateway-responses/Market.json b/scripts/testing/gateway-responses/Market.json new file mode 100644 index 0000000..dd69d89 --- /dev/null +++ b/scripts/testing/gateway-responses/Market.json @@ -0,0 +1,330 @@ +{ "timestamp":"2022-01-06T11:19:27Z", "event":"Market", "MarketID":128008448, "StationName":"Freeport", "StationType":"Coriolis", "StarSystem":"LP 98-132", "Items":[ +{ "id":128049152, "Name":"$platinum_name;", "Name_Localised":"Platinum", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":39557, "SellPrice":39555, "MeanPrice":58263, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049153, "Name":"$palladium_name;", "Name_Localised":"Palladium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":47901, "SellPrice":47360, "MeanPrice":50639, "StockBracket":1, "DemandBracket":0, "Stock":2, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049154, "Name":"$gold_name;", "Name_Localised":"Gold", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":44874, "SellPrice":44362, "MeanPrice":47610, "StockBracket":1, "DemandBracket":0, "Stock":2, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049155, "Name":"$silver_name;", "Name_Localised":"Silver", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":34289, "SellPrice":33471, "MeanPrice":37223, "StockBracket":1, "DemandBracket":0, "Stock":8, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049156, "Name":"$bertrandite_name;", "Name_Localised":"Bertrandite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":21216, "MeanPrice":18817, "StockBracket":0, "DemandBracket":2, "Stock":0, "Demand":1047, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049157, "Name":"$indite_name;", "Name_Localised":"Indite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":10508, "SellPrice":10238, "MeanPrice":11389, "StockBracket":1, "DemandBracket":0, "Stock":296, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049158, "Name":"$gallite_name;", "Name_Localised":"Gallite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":13829, "MeanPrice":11915, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1765, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049159, "Name":"$coltan_name;", "Name_Localised":"Coltan", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":7849, "MeanPrice":6163, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2063, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049160, "Name":"$uraninite_name;", "Name_Localised":"Uraninite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":4202, "MeanPrice":2957, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2899, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049161, "Name":"$lepidolite_name;", "Name_Localised":"Lepidolite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":4193, "SellPrice":3999, "MeanPrice":771, "StockBracket":1, "DemandBracket":0, "Stock":1271, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049162, "Name":"$cobalt_name;", "Name_Localised":"Cobalt", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":13474, "SellPrice":12870, "MeanPrice":3762, "StockBracket":1, "DemandBracket":0, "Stock":724, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049163, "Name":"$rutile_name;", "Name_Localised":"Rutile", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":11056, "MeanPrice":2083, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1306, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049165, "Name":"$bauxite_name;", "Name_Localised":"Bauxite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":10730, "SellPrice":10270, "MeanPrice":1140, "StockBracket":1, "DemandBracket":0, "Stock":595, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049166, "Name":"$water_name;", "Name_Localised":"Water", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":0, "SellPrice":599, "MeanPrice":278, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":336, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049168, "Name":"$beryllium_name;", "Name_Localised":"Beryllium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":8041, "SellPrice":7948, "MeanPrice":8243, "StockBracket":1, "DemandBracket":0, "Stock":2, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049169, "Name":"$indium_name;", "Name_Localised":"Indium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":5894, "SellPrice":5824, "MeanPrice":5845, "StockBracket":1, "DemandBracket":0, "Stock":8, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049170, "Name":"$gallium_name;", "Name_Localised":"Gallium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":5165, "SellPrice":5042, "MeanPrice":5203, "StockBracket":1, "DemandBracket":0, "Stock":11, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049171, "Name":"$tantalum_name;", "Name_Localised":"Tantalum", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":4099, "SellPrice":3999, "MeanPrice":4044, "StockBracket":1, "DemandBracket":0, "Stock":2, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049172, "Name":"$uranium_name;", "Name_Localised":"Uranium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":3139, "SellPrice":3060, "MeanPrice":2827, "StockBracket":1, "DemandBracket":0, "Stock":24, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049173, "Name":"$lithium_name;", "Name_Localised":"Lithium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":1906, "SellPrice":1855, "MeanPrice":1772, "StockBracket":1, "DemandBracket":0, "Stock":6, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049174, "Name":"$titanium_name;", "Name_Localised":"Titanium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":1377, "SellPrice":1319, "MeanPrice":1208, "StockBracket":2, "DemandBracket":0, "Stock":122, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049175, "Name":"$copper_name;", "Name_Localised":"Copper", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":1115, "SellPrice":1042, "MeanPrice":689, "StockBracket":2, "DemandBracket":0, "Stock":474, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049176, "Name":"$aluminium_name;", "Name_Localised":"Aluminium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":1127, "SellPrice":1045, "MeanPrice":551, "StockBracket":2, "DemandBracket":0, "Stock":352, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049177, "Name":"$algae_name;", "Name_Localised":"Algae", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":23, "SellPrice":22, "MeanPrice":356, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049178, "Name":"$fruitandvegetables_name;", "Name_Localised":"Fruit and Vegetables", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":0, "SellPrice":1060, "MeanPrice":509, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1637, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049180, "Name":"$grain_name;", "Name_Localised":"Grain", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":0, "SellPrice":919, "MeanPrice":410, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2980, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049182, "Name":"$animalmeat_name;", "Name_Localised":"Animal Meat", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":0, "SellPrice":1695, "MeanPrice":1539, "StockBracket":0, "DemandBracket":1, "Stock":0, "Demand":26, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049183, "Name":"$fish_name;", "Name_Localised":"Fish", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":0, "SellPrice":1008, "MeanPrice":650, "StockBracket":0, "DemandBracket":2, "Stock":0, "Demand":481, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049184, "Name":"$foodcartridges_name;", "Name_Localised":"Food Cartridges", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":0, "SellPrice":767, "MeanPrice":265, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1094, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049185, "Name":"$syntheticmeat_name;", "Name_Localised":"Synthetic Meat", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":0, "SellPrice":872, "MeanPrice":440, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":496, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049188, "Name":"$tea_name;", "Name_Localised":"Tea", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":0, "SellPrice":1923, "MeanPrice":1696, "StockBracket":0, "DemandBracket":2, "Stock":0, "Demand":43, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049189, "Name":"$coffee_name;", "Name_Localised":"Coffee", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":0, "SellPrice":2303, "MeanPrice":1499, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":527, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049190, "Name":"$leather_name;", "Name_Localised":"Leather", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":57, "SellPrice":56, "MeanPrice":435, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049191, "Name":"$naturalfabrics_name;", "Name_Localised":"Natural Fabrics", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":351, "SellPrice":350, "MeanPrice":688, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049193, "Name":"$syntheticfabrics_name;", "Name_Localised":"Synthetic Fabrics", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1705, "SellPrice":1435, "MeanPrice":416, "StockBracket":1, "DemandBracket":0, "Stock":197, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049197, "Name":"$polymers_name;", "Name_Localised":"Polymers", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":2614, "SellPrice":1960, "MeanPrice":376, "StockBracket":1, "DemandBracket":0, "Stock":272, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049199, "Name":"$semiconductors_name;", "Name_Localised":"Semiconductors", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":1415, "SellPrice":1355, "MeanPrice":1136, "StockBracket":1, "DemandBracket":0, "Stock":42, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049200, "Name":"$superconductors_name;", "Name_Localised":"Superconductors", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":6809, "SellPrice":6729, "MeanPrice":6679, "StockBracket":1, "DemandBracket":0, "Stock":14, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049202, "Name":"$hydrogenfuel_name;", "Name_Localised":"Hydrogen Fuel", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":126, "SellPrice":120, "MeanPrice":113, "StockBracket":1, "DemandBracket":0, "Stock":379, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049203, "Name":"$mineraloil_name;", "Name_Localised":"Mineral Oil", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":0, "SellPrice":1483, "MeanPrice":423, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":3336, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049204, "Name":"$explosives_name;", "Name_Localised":"Explosives", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":0, "SellPrice":2101, "MeanPrice":512, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":3964, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049205, "Name":"$pesticides_name;", "Name_Localised":"Pesticides", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":82, "SellPrice":81, "MeanPrice":437, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049208, "Name":"$agriculturalmedicines_name;", "Name_Localised":"Agri-Medicines", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":543, "SellPrice":542, "MeanPrice":1231, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049209, "Name":"$performanceenhancers_name;", "Name_Localised":"Performance Enhancers", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":0, "SellPrice":6907, "MeanPrice":6790, "StockBracket":0, "DemandBracket":1, "Stock":0, "Demand":40, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049210, "Name":"$basicmedicines_name;", "Name_Localised":"Basic Medicines", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":0, "SellPrice":963, "MeanPrice":493, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":904, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049213, "Name":"$tobacco_name;", "Name_Localised":"Tobacco", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":0, "SellPrice":5568, "MeanPrice":5325, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":398, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049214, "Name":"$beer_name;", "Name_Localised":"Beer", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":0, "SellPrice":799, "MeanPrice":430, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1777, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049215, "Name":"$wine_name;", "Name_Localised":"Wine", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":0, "SellPrice":411, "MeanPrice":507, "StockBracket":0, "DemandBracket":1, "Stock":0, "Demand":0, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049216, "Name":"$liquor_name;", "Name_Localised":"Liquor", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":0, "SellPrice":1331, "MeanPrice":879, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":453, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049217, "Name":"$powergenerators_name;", "Name_Localised":"Power Generators", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":0, "SellPrice":3475, "MeanPrice":2466, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":613, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049218, "Name":"$waterpurifiers_name;", "Name_Localised":"Water Purifiers", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":0, "SellPrice":2101, "MeanPrice":484, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1256, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049220, "Name":"$heliostaticfurnaces_name;", "Name_Localised":"Microbial Furnaces", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":0, "SellPrice":2010, "MeanPrice":434, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":537, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049221, "Name":"$mineralextractors_name;", "Name_Localised":"Mineral Extractors", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":0, "SellPrice":2647, "MeanPrice":801, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1698, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049222, "Name":"$cropharvesters_name;", "Name_Localised":"Crop Harvesters", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1564, "SellPrice":1563, "MeanPrice":2230, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049223, "Name":"$marinesupplies_name;", "Name_Localised":"Marine Equipment", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":2745, "SellPrice":2744, "MeanPrice":4135, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049225, "Name":"$computercomponents_name;", "Name_Localised":"Computer Components", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":267, "SellPrice":266, "MeanPrice":776, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049226, "Name":"$hazardousenvironmentsuits_name;", "Name_Localised":"H.E. Suits", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":0, "SellPrice":915, "MeanPrice":570, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":4363, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049227, "Name":"$robotics_name;", "Name_Localised":"Robotics", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":1447, "SellPrice":1446, "MeanPrice":2020, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049228, "Name":"$autofabricators_name;", "Name_Localised":"Auto-Fabricators", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":2685, "SellPrice":2684, "MeanPrice":3827, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049229, "Name":"$animalmonitors_name;", "Name_Localised":"Animal Monitors", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":630, "SellPrice":629, "MeanPrice":537, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049230, "Name":"$aquaponicsystems_name;", "Name_Localised":"Aquaponic Systems", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":321, "SellPrice":320, "MeanPrice":524, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049231, "Name":"$advancedcatalysers_name;", "Name_Localised":"Advanced Catalysers", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":0, "SellPrice":3756, "MeanPrice":3039, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":936, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049232, "Name":"$terrainenrichmentsystems_name;", "Name_Localised":"Land Enrichment Systems", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":3005, "SellPrice":3004, "MeanPrice":4928, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049234, "Name":"$battleweapons_name;", "Name_Localised":"Battle Weapons", "Category":"$MARKET_category_weapons;", "Category_Localised":"Weapons", "BuyPrice":4463, "SellPrice":4462, "MeanPrice":7451, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128049235, "Name":"$reactivearmour_name;", "Name_Localised":"Reactive Armour", "Category":"$MARKET_category_weapons;", "Category_Localised":"Weapons", "BuyPrice":0, "SellPrice":2669, "MeanPrice":2224, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":150, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049236, "Name":"$nonlethalweapons_name;", "Name_Localised":"Non-Lethal Weapons", "Category":"$MARKET_category_weapons;", "Category_Localised":"Weapons", "BuyPrice":0, "SellPrice":2417, "MeanPrice":1943, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":274, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049238, "Name":"$domesticappliances_name;", "Name_Localised":"Domestic Appliances", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":0, "SellPrice":1216, "MeanPrice":740, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":575, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049240, "Name":"$consumertechnology_name;", "Name_Localised":"Consumer Technology", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":0, "SellPrice":6883, "MeanPrice":6690, "StockBracket":0, "DemandBracket":1, "Stock":0, "Demand":0, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049241, "Name":"$clothing_name;", "Name_Localised":"Clothing", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":0, "SellPrice":963, "MeanPrice":546, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":955, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049244, "Name":"$biowaste_name;", "Name_Localised":"Biowaste", "Category":"$MARKET_category_waste;", "Category_Localised":"Waste", "BuyPrice":145, "SellPrice":87, "MeanPrice":358, "StockBracket":1, "DemandBracket":0, "Stock":103, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128049246, "Name":"$chemicalwaste_name;", "Name_Localised":"Chemical Waste", "Category":"$MARKET_category_waste;", "Category_Localised":"Waste", "BuyPrice":0, "SellPrice":599, "MeanPrice":672, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":159, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049248, "Name":"$scrap_name;", "Name_Localised":"Scrap", "Category":"$MARKET_category_waste;", "Category_Localised":"Waste", "BuyPrice":0, "SellPrice":625, "MeanPrice":300, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":182, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049669, "Name":"$progenitorcells_name;", "Name_Localised":"Progenitor Cells", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":0, "SellPrice":7529, "MeanPrice":6752, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":6, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049671, "Name":"$resonatingseparators_name;", "Name_Localised":"Resonating Separators", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":0, "SellPrice":7158, "MeanPrice":5937, "StockBracket":0, "DemandBracket":2, "Stock":0, "Demand":491, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128049672, "Name":"$bioreducinglichen_name;", "Name_Localised":"Bioreducing Lichen", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":0, "SellPrice":1703, "MeanPrice":1204, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":5473, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128064028, "Name":"$atmosphericextractors_name;", "Name_Localised":"Atmospheric Processors", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":331, "SellPrice":330, "MeanPrice":571, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128666746, "Name":"$eraninpearlwhisky_name;", "Name_Localised":"Eranin Pearl Whisky", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":2058, "SellPrice":2057, "MeanPrice":9040, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128666747, "Name":"$lavianbrandy_name;", "Name_Localised":"Lavian Brandy", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":3614, "SellPrice":3613, "MeanPrice":10365, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128666757, "Name":"$usscargorareartwork_name;", "Name_Localised":"Rare Artwork", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":15150, "SellPrice":15149, "MeanPrice":16807, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128667019, "Name":"$hip10175bushmeat_name;", "Name_Localised":"HIP 10175 Bush Meat", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2246, "SellPrice":2245, "MeanPrice":9382, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667020, "Name":"$albinoquechuamammoth_name;", "Name_Localised":"Albino Quechua Mammoth Meat", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2663, "SellPrice":2662, "MeanPrice":9687, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667021, "Name":"$utgaroarmillenialeggs_name;", "Name_Localised":"Utgaroar Millennial Eggs", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2217, "SellPrice":2216, "MeanPrice":9163, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667022, "Name":"$witchhaulkobebeef_name;", "Name_Localised":"Witchhaul Kobe Beef", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":4313, "SellPrice":4312, "MeanPrice":11085, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667023, "Name":"$karsukilocusts_name;", "Name_Localised":"Karsuki Locusts", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1583, "SellPrice":1582, "MeanPrice":8543, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667024, "Name":"$giantirukamasnails_name;", "Name_Localised":"Giant Irukama Snails", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2131, "SellPrice":2130, "MeanPrice":9174, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667025, "Name":"$baltahsinevacuumkrill_name;", "Name_Localised":"Baltah'sine Vacuum Krill", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1502, "SellPrice":1501, "MeanPrice":8479, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667026, "Name":"$cetirabbits_name;", "Name_Localised":"Ceti Rabbits", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2068, "SellPrice":2067, "MeanPrice":9079, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667027, "Name":"$kachiriginleaches_name;", "Name_Localised":"Kachirigin Filter Leeches", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":1359, "SellPrice":1358, "MeanPrice":8227, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667029, "Name":"$onionhead_name;", "Name_Localised":"Onionhead", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1814, "SellPrice":1813, "MeanPrice":8437, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667034, "Name":"$konggaale_name;", "Name_Localised":"Kongga Ale", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1578, "SellPrice":1577, "MeanPrice":8310, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667035, "Name":"$wuthielokufroth_name;", "Name_Localised":"Wuthielo Ku Froth", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1558, "SellPrice":1557, "MeanPrice":8194, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667036, "Name":"$alacarakmoskinart_name;", "Name_Localised":"Alacarakmo Skin Art", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1858, "SellPrice":1857, "MeanPrice":8899, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667037, "Name":"$eleuthermals_name;", "Name_Localised":"Eleu Thermals", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1571, "SellPrice":1570, "MeanPrice":8507, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667038, "Name":"$eshuumbrellas_name;", "Name_Localised":"Eshu Umbrellas", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":2187, "SellPrice":2186, "MeanPrice":9343, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667039, "Name":"$karetiicouture_name;", "Name_Localised":"Karetii Couture", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":4748, "SellPrice":4747, "MeanPrice":11582, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667040, "Name":"$njangarisaddles_name;", "Name_Localised":"Njangari Saddles", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1639, "SellPrice":1638, "MeanPrice":8356, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667041, "Name":"$anynacoffee_name;", "Name_Localised":"Any Na Coffee", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2165, "SellPrice":2164, "MeanPrice":9160, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667042, "Name":"$cd75catcoffee_name;", "Name_Localised":"CD-75 Kitten Brand Coffee", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2452, "SellPrice":2451, "MeanPrice":9571, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667043, "Name":"$gomanyauponcoffee_name;", "Name_Localised":"Goman Yaupon Coffee", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1843, "SellPrice":1842, "MeanPrice":8921, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667044, "Name":"$volkhabbeedrones_name;", "Name_Localised":"Volkhab Bee Drones", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":3849, "SellPrice":3848, "MeanPrice":10198, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667045, "Name":"$kinagoinstruments_name;", "Name_Localised":"Kinago Violins", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":6570, "SellPrice":6569, "MeanPrice":13030, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667046, "Name":"$ngunamodernantiques_name;", "Name_Localised":"Nguna Modern Antiques", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1989, "SellPrice":1988, "MeanPrice":8545, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667047, "Name":"$rajukrustoves_name;", "Name_Localised":"Rajukru Multi-Stoves", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":2346, "SellPrice":2345, "MeanPrice":8378, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667048, "Name":"$tiolcewaste2pasteunits_name;", "Name_Localised":"Tiolce Waste2Paste Units", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1648, "SellPrice":1647, "MeanPrice":8710, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667049, "Name":"$chieridanimarinepaste_name;", "Name_Localised":"Chi Eridani Marine Paste", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1426, "SellPrice":1425, "MeanPrice":8450, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667050, "Name":"$esusekucaviar_name;", "Name_Localised":"Esuseku Caviar", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2573, "SellPrice":2572, "MeanPrice":9625, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667051, "Name":"$livehecateseaworms_name;", "Name_Localised":"Live Hecate Sea Worms", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1899, "SellPrice":1898, "MeanPrice":8737, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667052, "Name":"$helvetitjpearls_name;", "Name_Localised":"Helvetitj Pearls", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":3507, "SellPrice":3506, "MeanPrice":10450, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667053, "Name":"$hip41181squid_name;", "Name_Localised":"HIP Proto-Squid", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1891, "SellPrice":1890, "MeanPrice":8947, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667054, "Name":"$coquimspongiformvictuals_name;", "Name_Localised":"Coquim Spongiform Victuals", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":10924, "SellPrice":10923, "MeanPrice":8077, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667055, "Name":"$aerialedenapple_name;", "Name_Localised":"Eden Apples Of Aerial", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1660, "SellPrice":1659, "MeanPrice":8331, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667056, "Name":"$neritusberries_name;", "Name_Localised":"Neritus Berries", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1616, "SellPrice":1615, "MeanPrice":8497, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667057, "Name":"$ochoengchillies_name;", "Name_Localised":"Ochoeng Chillies", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1659, "SellPrice":1658, "MeanPrice":8601, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667058, "Name":"$deuringastruffles_name;", "Name_Localised":"Deuringas Truffles", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2335, "SellPrice":2334, "MeanPrice":9232, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667059, "Name":"$hr7221wheat_name;", "Name_Localised":"HR 7221 Wheat", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1540, "SellPrice":1539, "MeanPrice":8190, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667060, "Name":"$jarouarice_name;", "Name_Localised":"Jaroua Rice", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2711, "SellPrice":2710, "MeanPrice":8169, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667061, "Name":"$belalansrayleather_name;", "Name_Localised":"Belalans Ray Leather", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1605, "SellPrice":1604, "MeanPrice":8519, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667062, "Name":"$damnacarapaces_name;", "Name_Localised":"Damna Carapaces", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":2925, "SellPrice":2924, "MeanPrice":8120, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667063, "Name":"$rapabaosnakeskins_name;", "Name_Localised":"Rapa Bao Snake Skins", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1726, "SellPrice":1725, "MeanPrice":8285, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667064, "Name":"$vanayequirhinofur_name;", "Name_Localised":"Vanayequi Ceratomorpha Fur", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1660, "SellPrice":1659, "MeanPrice":8331, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667065, "Name":"$bastsnakegin_name;", "Name_Localised":"Bast Snake Gin", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1724, "SellPrice":1723, "MeanPrice":8659, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667066, "Name":"$thrutiscream_name;", "Name_Localised":"Thrutis Cream", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1538, "SellPrice":1537, "MeanPrice":8550, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667067, "Name":"$wulpahyperboresystems_name;", "Name_Localised":"Wulpa Hyperbore Systems", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":2294, "SellPrice":2293, "MeanPrice":8726, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667073, "Name":"$deltaphoenicispalms_name;", "Name_Localised":"Delta Phoenicis Palms", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":1528, "SellPrice":1527, "MeanPrice":8188, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667074, "Name":"$toxandjivirocide_name;", "Name_Localised":"Toxandji Virocide", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":1678, "SellPrice":1677, "MeanPrice":8275, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667075, "Name":"$xihecompanions_name;", "Name_Localised":"Xihe Biomorphic Companions", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":4277, "SellPrice":4276, "MeanPrice":11058, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667076, "Name":"$sanumameat_name;", "Name_Localised":"Sanuma Decorative Meat", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1319, "SellPrice":1318, "MeanPrice":8504, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667077, "Name":"$ethgrezeteabuds_name;", "Name_Localised":"Ethgreze Tea Buds", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":3212, "SellPrice":3211, "MeanPrice":10197, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667078, "Name":"$ceremonialheiketea_name;", "Name_Localised":"Ceremonial Heike Tea", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2161, "SellPrice":2160, "MeanPrice":9251, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667079, "Name":"$tanmarktranquiltea_name;", "Name_Localised":"Tanmark Tranquil Tea", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2041, "SellPrice":2040, "MeanPrice":9177, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667080, "Name":"$azcancriformula42_name;", "Name_Localised":"AZ Cancri Formula 42", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":6106, "SellPrice":6105, "MeanPrice":12440, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667081, "Name":"$kamitracigars_name;", "Name_Localised":"Kamitra Cigars", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":5522, "SellPrice":5521, "MeanPrice":12282, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667082, "Name":"$rusanioldsmokey_name;", "Name_Localised":"Rusani Old Smokey", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":5179, "SellPrice":5178, "MeanPrice":11994, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667083, "Name":"$yasokondileaf_name;", "Name_Localised":"Yaso Kondi Leaf", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":5381, "SellPrice":5380, "MeanPrice":12171, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667084, "Name":"$chateaudeaegaeon_name;", "Name_Localised":"Chateau De Aegaeon", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1610, "SellPrice":1609, "MeanPrice":8791, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667085, "Name":"$watersofshintara_name;", "Name_Localised":"The Waters Of Shintara", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":7070, "SellPrice":7069, "MeanPrice":13711, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667668, "Name":"$ophiuchiexinoartefacts_name;", "Name_Localised":"Ophiuch Exino Artefacts", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":4072, "SellPrice":4071, "MeanPrice":10969, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667669, "Name":"$bakedgreebles_name;", "Name_Localised":"Baked Greebles", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1056, "SellPrice":1055, "MeanPrice":8211, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667670, "Name":"$cetiaepyornisegg_name;", "Name_Localised":"Aepyornis Egg", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2741, "SellPrice":2740, "MeanPrice":9769, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667671, "Name":"$saxonwine_name;", "Name_Localised":"Saxon Wine", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1863, "SellPrice":1862, "MeanPrice":8983, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667672, "Name":"$centaurimegagin_name;", "Name_Localised":"Centauri Mega Gin", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":3239, "SellPrice":3238, "MeanPrice":10217, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667673, "Name":"$anduligafireworks_name;", "Name_Localised":"Anduliga Fire Works", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1574, "SellPrice":1573, "MeanPrice":8519, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667674, "Name":"$bankiamphibiousleather_name;", "Name_Localised":"Banki Amphibious Leather", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1138, "SellPrice":1137, "MeanPrice":8338, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667675, "Name":"$cherbonesbloodcrystals_name;", "Name_Localised":"Cherbones Blood Crystals", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":10207, "SellPrice":10206, "MeanPrice":16714, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667678, "Name":"$gerasiangueuzebeer_name;", "Name_Localised":"Gerasian Gueuze Beer", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1067, "SellPrice":1066, "MeanPrice":8215, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667679, "Name":"$haidneblackbrew_name;", "Name_Localised":"Haiden Black Brew", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1693, "SellPrice":1692, "MeanPrice":8837, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667680, "Name":"$havasupaidreamcatcher_name;", "Name_Localised":"Havasupai Dream Catcher", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":8056, "SellPrice":8055, "MeanPrice":14639, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667682, "Name":"$hiporganophosphates_name;", "Name_Localised":"Hip Organophosphates", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":1039, "SellPrice":1038, "MeanPrice":8169, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667683, "Name":"$jaradharrepuzzlebox_name;", "Name_Localised":"Jaradharre Puzzle Box", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":10325, "SellPrice":10324, "MeanPrice":16816, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667684, "Name":"$korrokungpellets_name;", "Name_Localised":"Koro Kung Pellets", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":1190, "SellPrice":1189, "MeanPrice":8067, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667685, "Name":"$lftvoidextractcoffee_name;", "Name_Localised":"Void Extract Coffee", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2506, "SellPrice":2505, "MeanPrice":9554, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667686, "Name":"$honestypills_name;", "Name_Localised":"Honesty Pills", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":1686, "SellPrice":1685, "MeanPrice":8860, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667687, "Name":"$noneuclidianexotanks_name;", "Name_Localised":"Non Euclidian Exotanks", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1326, "SellPrice":1325, "MeanPrice":8526, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667688, "Name":"$ltthypersweet_name;", "Name_Localised":"LTT Hyper Sweet", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1233, "SellPrice":1232, "MeanPrice":8054, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667689, "Name":"$mechucoshightea_name;", "Name_Localised":"Mechucos High Tea", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1709, "SellPrice":1708, "MeanPrice":8846, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667690, "Name":"$medbstarlube_name;", "Name_Localised":"Medb Starlube", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":1953, "SellPrice":1952, "MeanPrice":8191, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667691, "Name":"$mokojingbeastfeast_name;", "Name_Localised":"Mokojing Beast Feast", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":2770, "SellPrice":2769, "MeanPrice":9788, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667692, "Name":"$mukusubiichitinos_name;", "Name_Localised":"Mukusubii Chitin-os", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1190, "SellPrice":1189, "MeanPrice":8359, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667693, "Name":"$mulachigiantfungus_name;", "Name_Localised":"Mulachi Giant Fungus", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":8230, "SellPrice":8229, "MeanPrice":7957, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667694, "Name":"$ngadandarifireopals_name;", "Name_Localised":"Ngadandari Fire Opals", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":12751, "SellPrice":12750, "MeanPrice":19112, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667695, "Name":"$tiegfriessynthsilk_name;", "Name_Localised":"Tiegfries Synth Silk", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1263, "SellPrice":1262, "MeanPrice":8478, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667696, "Name":"$uzumokulowgwings_name;", "Name_Localised":"Uzumoku Low-G Wings", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":7233, "SellPrice":7232, "MeanPrice":13845, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667697, "Name":"$vherculisbodyrub_name;", "Name_Localised":"V Herculis Body Rub", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":1730, "SellPrice":1729, "MeanPrice":8010, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667698, "Name":"$wheemetewheatcakes_name;", "Name_Localised":"Wheemete Wheat Cakes", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1164, "SellPrice":1163, "MeanPrice":8081, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667699, "Name":"$vegaslimweed_name;", "Name_Localised":"Vega Slimweed", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":2518, "SellPrice":2517, "MeanPrice":9588, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667700, "Name":"$altairianskin_name;", "Name_Localised":"Altairian Skin", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1262, "SellPrice":1261, "MeanPrice":8432, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667702, "Name":"$jotunmookah_name;", "Name_Localised":"Jotun Mookah", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1637, "SellPrice":1636, "MeanPrice":8780, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667703, "Name":"$giantverrix_name;", "Name_Localised":"Giant Verrix", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":5713, "SellPrice":5712, "MeanPrice":12496, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667704, "Name":"$indibourbon_name;", "Name_Localised":"Indi Bourbon", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1638, "SellPrice":1637, "MeanPrice":8806, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667705, "Name":"$aroucaconventualsweets_name;", "Name_Localised":"Arouca Conventual Sweets", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1557, "SellPrice":1556, "MeanPrice":8737, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667706, "Name":"$taurichimes_name;", "Name_Localised":"Tauri Chimes", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1374, "SellPrice":1373, "MeanPrice":8549, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667707, "Name":"$zeesszeantglue_name;", "Name_Localised":"Zeessze Ant Grub Glue", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1089, "SellPrice":1088, "MeanPrice":8161, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667708, "Name":"$pantaaprayersticks_name;", "Name_Localised":"Pantaa Prayer Sticks", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":2043, "SellPrice":2042, "MeanPrice":9177, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667709, "Name":"$fujintea_name;", "Name_Localised":"Fujin Tea", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1418, "SellPrice":1417, "MeanPrice":8597, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667710, "Name":"$chameleoncloth_name;", "Name_Localised":"Chameleon Cloth", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1959, "SellPrice":1958, "MeanPrice":9071, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667711, "Name":"$orrerianviciousbrew_name;", "Name_Localised":"Orrerian Vicious Brew", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1146, "SellPrice":1145, "MeanPrice":8342, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667712, "Name":"$uszaiantreegrub_name;", "Name_Localised":"Uszaian Tree Grub", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1379, "SellPrice":1378, "MeanPrice":8578, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667713, "Name":"$momusbogspaniel_name;", "Name_Localised":"Momus Bog Spaniel", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":2054, "SellPrice":2053, "MeanPrice":9184, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667714, "Name":"$disomacorn_name;", "Name_Localised":"Diso Ma Corn", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":1053, "SellPrice":1052, "MeanPrice":8134, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667715, "Name":"$leestianeviljuice_name;", "Name_Localised":"Leestian Evil Juice", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1086, "SellPrice":1085, "MeanPrice":8220, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667716, "Name":"$bluemilk_name;", "Name_Localised":"Azure Milk", "Category":"$MARKET_category_foods;", "Category_Localised":"Foods", "BuyPrice":3912, "SellPrice":3911, "MeanPrice":10805, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667717, "Name":"$alieneggs_name;", "Name_Localised":"Leathery Eggs", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":19095, "SellPrice":19094, "MeanPrice":25067, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667718, "Name":"$alyabodilysoap_name;", "Name_Localised":"Alya Body Soap", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":1078, "SellPrice":1077, "MeanPrice":8218, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667719, "Name":"$vidavantianlace_name;", "Name_Localised":"Vidavantian Lace", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":5861, "SellPrice":5860, "MeanPrice":12615, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128667760, "Name":"$transgeniconionhead_name;", "Name_Localised":"Lucan Onionhead", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1483, "SellPrice":1482, "MeanPrice":8472, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128668017, "Name":"$jaquesquinentianstill_name;", "Name_Localised":"Jaques Quinentian Still", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":7233, "SellPrice":7232, "MeanPrice":13845, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128668018, "Name":"$soontillrelics_name;", "Name_Localised":"Soontill Relics", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":13602, "SellPrice":13601, "MeanPrice":19885, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128668547, "Name":"$unknownartifact_name;", "Name_Localised":"Thargoid Sensor", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":234627, "SellPrice":234615, "MeanPrice":306252, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128668550, "Name":"$painite_name;", "Name_Localised":"Painite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":192955, "MeanPrice":53016, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":4, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128671118, "Name":"$osmium_name;", "Name_Localised":"Osmium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":23482, "SellPrice":23480, "MeanPrice":45198, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128671119, "Name":"$advert1_name;", "Name_Localised":"Ultra-Compact Processor Prototypes", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":15267, "SellPrice":15266, "MeanPrice":21542, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128671443, "Name":"$sap8corecontainer_name;", "Name_Localised":"SAP 8 Core Container", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":49112, "SellPrice":49109, "MeanPrice":67593, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672121, "Name":"$thehuttonmug_name;", "Name_Localised":"The Hutton Mug", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":2751, "SellPrice":2750, "MeanPrice":7986, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128672122, "Name":"$sothiscrystallinegold_name;", "Name_Localised":"Sothis Crystalline Gold", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":12751, "SellPrice":12750, "MeanPrice":19112, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128672124, "Name":"$encripteddatastorage_name;", "Name_Localised":"Encrypted Data Storage", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":4049, "SellPrice":4048, "MeanPrice":8313, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672127, "Name":"$comercialsamples_name;", "Name_Localised":"Commercial Samples", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":656, "SellPrice":655, "MeanPrice":1815, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672128, "Name":"$tacticaldata_name;", "Name_Localised":"Tactical Data", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":2170, "SellPrice":2169, "MeanPrice":15622, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672129, "Name":"$assaultplans_name;", "Name_Localised":"Assault Plans", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":3294, "SellPrice":3293, "MeanPrice":26074, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672130, "Name":"$encryptedcorrespondence_name;", "Name_Localised":"Encrypted Correspondence", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":3935, "SellPrice":3934, "MeanPrice":8226, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672131, "Name":"$diplomaticbag_name;", "Name_Localised":"Diplomatic Bag", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":4265, "SellPrice":4264, "MeanPrice":28625, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672132, "Name":"$scientificresearch_name;", "Name_Localised":"Scientific Research", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":13394, "SellPrice":13393, "MeanPrice":20151, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672133, "Name":"$scientificsamples_name;", "Name_Localised":"Scientific Samples", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":10878, "SellPrice":10877, "MeanPrice":7955, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672136, "Name":"$largeexplorationdatacash_name;", "Name_Localised":"Large Survey Data Cache", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":225210, "SellPrice":225198, "MeanPrice":255841, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672137, "Name":"$smallexplorationdatacash_name;", "Name_Localised":"Small Survey Data Cache", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":40615, "SellPrice":40612, "MeanPrice":25005, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672159, "Name":"$antiquejewellery_name;", "Name_Localised":"Antique Jewellery", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":158957, "SellPrice":158949, "MeanPrice":183163, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672160, "Name":"$preciousgems_name;", "Name_Localised":"Precious Gems", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":138850, "SellPrice":138843, "MeanPrice":160280, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672161, "Name":"$earthrelics_name;", "Name_Localised":"Earth Relics", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":14640, "SellPrice":14639, "MeanPrice":15161, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672162, "Name":"$genebank_name;", "Name_Localised":"Gene Bank", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":46704, "SellPrice":46701, "MeanPrice":59082, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672163, "Name":"$timecapsule_name;", "Name_Localised":"Time Capsule", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":2926, "SellPrice":2925, "MeanPrice":5364, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672294, "Name":"$cryolite_name;", "Name_Localised":"Cryolite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":14970, "MeanPrice":12173, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1166, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128672295, "Name":"$goslarite_name;", "Name_Localised":"Goslarite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":8024, "MeanPrice":5979, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1290, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128672296, "Name":"$moissanite_name;", "Name_Localised":"Moissanite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":16662, "SellPrice":16661, "MeanPrice":24833, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672297, "Name":"$pyrophyllite_name;", "Name_Localised":"Pyrophyllite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":13777, "MeanPrice":11538, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":341, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128672298, "Name":"$lanthanum_name;", "Name_Localised":"Lanthanum", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":6087, "SellPrice":6086, "MeanPrice":8707, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672299, "Name":"$thallium_name;", "Name_Localised":"Thallium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":2539, "SellPrice":2538, "MeanPrice":3745, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672300, "Name":"$bismuth_name;", "Name_Localised":"Bismuth", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":1607, "SellPrice":1606, "MeanPrice":2441, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672301, "Name":"$thorium_name;", "Name_Localised":"Thorium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":7969, "SellPrice":7968, "MeanPrice":11317, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672302, "Name":"$ceramiccomposites_name;", "Name_Localised":"Ceramic Composites", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":424, "SellPrice":423, "MeanPrice":415, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672303, "Name":"$syntheticreagents_name;", "Name_Localised":"Synthetic Reagents", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":4463, "SellPrice":4462, "MeanPrice":6651, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672305, "Name":"$surfacestabilisers_name;", "Name_Localised":"Surface Stabilisers", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":1656, "SellPrice":1550, "MeanPrice":726, "StockBracket":1, "DemandBracket":0, "Stock":67, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128672307, "Name":"$geologicalequipment_name;", "Name_Localised":"Geological Equipment", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1186, "SellPrice":1185, "MeanPrice":1886, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672308, "Name":"$thermalcoolingunits_name;", "Name_Localised":"Thermal Cooling Units", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":2516, "SellPrice":2515, "MeanPrice":3760, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672309, "Name":"$buildingfabricators_name;", "Name_Localised":"Building Fabricators", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1448, "SellPrice":1447, "MeanPrice":2312, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672310, "Name":"$mutomimager_name;", "Name_Localised":"Muon Imager", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":4218, "SellPrice":4217, "MeanPrice":6311, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672311, "Name":"$structuralregulators_name;", "Name_Localised":"Structural Regulators", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":1186, "SellPrice":1185, "MeanPrice":1932, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672313, "Name":"$skimercomponents_name;", "Name_Localised":"Skimmer Components", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":530, "SellPrice":529, "MeanPrice":1119, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672314, "Name":"$evacuationshelter_name;", "Name_Localised":"Evacuation Shelter", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":138, "SellPrice":137, "MeanPrice":522, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672315, "Name":"$geologicalsamples_name;", "Name_Localised":"Geological Samples", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":12144, "SellPrice":12143, "MeanPrice":8313, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672431, "Name":"$personalgifts_name;", "Name_Localised":"Personal Gifts", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":10000, "SellPrice":9999, "MeanPrice":16535, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128672432, "Name":"$crystallinespheres_name;", "Name_Localised":"Crystalline Spheres", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":5438, "SellPrice":5437, "MeanPrice":12216, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128672701, "Name":"$metaalloys_name;", "Name_Localised":"Meta-Alloys", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":162685, "SellPrice":162676, "MeanPrice":195453, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672775, "Name":"$taaffeite_name;", "Name_Localised":"Taaffeite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":51665, "SellPrice":51662, "MeanPrice":52089, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672776, "Name":"$jadeite_name;", "Name_Localised":"Jadeite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":40631, "SellPrice":40628, "MeanPrice":42383, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672810, "Name":"$unstabledatacore_name;", "Name_Localised":"Unstable Data Core", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":2371, "SellPrice":2370, "MeanPrice":4516, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128672812, "Name":"$onionheada_name;", "Name_Localised":"Onionhead Alpha Strain", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1272, "SellPrice":1271, "MeanPrice":8437, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128673069, "Name":"$onionheadb_name;", "Name_Localised":"Onionhead Beta Strain", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":1272, "SellPrice":1271, "MeanPrice":8437, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128673845, "Name":"$praseodymium_name;", "Name_Localised":"Praseodymium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":6708, "SellPrice":6707, "MeanPrice":8620, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673846, "Name":"$bromellite_name;", "Name_Localised":"Bromellite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":70950, "SellPrice":70946, "MeanPrice":30424, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673847, "Name":"$samarium_name;", "Name_Localised":"Samarium", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":31195, "SellPrice":31193, "MeanPrice":25852, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673848, "Name":"$lowtemperaturediamond_name;", "Name_Localised":"Low Temp. Diamonds", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":293785, "MeanPrice":106353, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128673850, "Name":"$hydrogenperoxide_name;", "Name_Localised":"Hydrogen Peroxide", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":0, "SellPrice":3301, "MeanPrice":3160, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":548, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128673851, "Name":"$liquidoxygen_name;", "Name_Localised":"Liquid oxygen", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":957, "SellPrice":850, "MeanPrice":1474, "StockBracket":1, "DemandBracket":0, "Stock":22, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128673852, "Name":"$methanolmonohydratecrystals_name;", "Name_Localised":"Methanol Monohydrate Crystals", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":1290, "SellPrice":1289, "MeanPrice":2478, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673853, "Name":"$lithiumhydroxide_name;", "Name_Localised":"Lithium Hydroxide", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":7350, "MeanPrice":5673, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":99, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128673854, "Name":"$methaneclathrate_name;", "Name_Localised":"Methane Clathrate", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":1740, "MeanPrice":1650, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2873, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128673855, "Name":"$insulatingmembrane_name;", "Name_Localised":"Insulating Membrane", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":10137, "SellPrice":10021, "MeanPrice":10724, "StockBracket":2, "DemandBracket":0, "Stock":2, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128673856, "Name":"$cmmcomposite_name;", "Name_Localised":"CMM Composite", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":3907, "SellPrice":3906, "MeanPrice":5988, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673857, "Name":"$coolinghoses_name;", "Name_Localised":"Micro-weave Cooling Hoses", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":707, "SellPrice":706, "MeanPrice":1886, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673858, "Name":"$neofabricinsulation_name;", "Name_Localised":"Neofabric Insulation", "Category":"$MARKET_category_industrial_materials;", "Category_Localised":"Industrial materials", "BuyPrice":3380, "SellPrice":3379, "MeanPrice":5978, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673859, "Name":"$articulationmotors_name;", "Name_Localised":"Articulation Motors", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":4463, "SellPrice":4462, "MeanPrice":7588, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673860, "Name":"$hnshockmount_name;", "Name_Localised":"HN Shock Mount", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1075, "SellPrice":1074, "MeanPrice":1922, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673861, "Name":"$emergencypowercells_name;", "Name_Localised":"Emergency Power Cells", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1338, "SellPrice":1337, "MeanPrice":2368, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673862, "Name":"$powerconverter_name;", "Name_Localised":"Power Converter", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":707, "SellPrice":706, "MeanPrice":1433, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673863, "Name":"$powergridassembly_name;", "Name_Localised":"Energy Grid Assembly", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1543, "SellPrice":1542, "MeanPrice":2659, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673864, "Name":"$powertransferconduits_name;", "Name_Localised":"Power Transfer Bus", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1254, "SellPrice":1253, "MeanPrice":2212, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673865, "Name":"$radiationbaffle_name;", "Name_Localised":"Radiation Baffle", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":935, "SellPrice":934, "MeanPrice":1787, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673866, "Name":"$exhaustmanifold_name;", "Name_Localised":"Exhaust Manifold", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1009, "SellPrice":1008, "MeanPrice":1873, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673867, "Name":"$reinforcedmountingplate_name;", "Name_Localised":"Reinforced Mounting Plate", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1446, "SellPrice":1445, "MeanPrice":2454, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673868, "Name":"$heatsinkinterlink_name;", "Name_Localised":"Heatsink Interlink", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1161, "SellPrice":1160, "MeanPrice":2100, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673869, "Name":"$magneticemittercoil_name;", "Name_Localised":"Magnetic Emitter Coil", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":656, "SellPrice":655, "MeanPrice":1357, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673870, "Name":"$modularterminals_name;", "Name_Localised":"Modular Terminals", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1075, "SellPrice":1074, "MeanPrice":2475, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673871, "Name":"$nanobreakers_name;", "Name_Localised":"Nanobreakers", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":1009, "SellPrice":1008, "MeanPrice":2366, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673872, "Name":"$telemetrysuite_name;", "Name_Localised":"Telemetry Suite", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":1543, "SellPrice":1542, "MeanPrice":3214, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673873, "Name":"$microcontrollers_name;", "Name_Localised":"Micro Controllers", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":3612, "SellPrice":3611, "MeanPrice":5590, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673874, "Name":"$iondistributor_name;", "Name_Localised":"Ion Distributor", "Category":"$MARKET_category_machinery;", "Category_Localised":"Machinery", "BuyPrice":1338, "SellPrice":1337, "MeanPrice":2363, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673875, "Name":"$diagnosticsensor_name;", "Name_Localised":"Hardware Diagnostic Sensor", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":4463, "SellPrice":4462, "MeanPrice":6727, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128673876, "Name":"$unknownartifact2_name;", "Name_Localised":"Thargoid Probe", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":344560, "SellPrice":344542, "MeanPrice":443535, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128682044, "Name":"$conductivefabrics_name;", "Name_Localised":"Conductive Fabrics", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":1937, "SellPrice":1810, "MeanPrice":709, "StockBracket":1, "DemandBracket":0, "Stock":55, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128682045, "Name":"$militarygradefabrics_name;", "Name_Localised":"Military Grade Fabrics", "Category":"$MARKET_category_textiles;", "Category_Localised":"Textiles", "BuyPrice":3690, "SellPrice":3527, "MeanPrice":984, "StockBracket":1, "DemandBracket":0, "Stock":46, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128682046, "Name":"$advancedmedicines_name;", "Name_Localised":"Advanced Medicines", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":0, "SellPrice":1726, "MeanPrice":1485, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":296, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128682047, "Name":"$medicaldiagnosticequipment_name;", "Name_Localised":"Medical Diagnostic Equipment", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":1779, "SellPrice":1778, "MeanPrice":3075, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128682048, "Name":"$survivalequipment_name;", "Name_Localised":"Survival Equipment", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":533, "SellPrice":532, "MeanPrice":684, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128682049, "Name":"$datacore_name;", "Name_Localised":"Data Core", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":3907, "SellPrice":3906, "MeanPrice":6791, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128682050, "Name":"$galactictravelguide_name;", "Name_Localised":"Galactic Travel Guide", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":359, "SellPrice":358, "MeanPrice":8627, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128682051, "Name":"$mysteriousidol_name;", "Name_Localised":"Mysterious Idol", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":13815, "SellPrice":13814, "MeanPrice":20863, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128682054, "Name":"$spacepioneerrelics_name;", "Name_Localised":"Space Pioneer Relics", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":5967, "SellPrice":5966, "MeanPrice":9780, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128682055, "Name":"$fossilremnants_name;", "Name_Localised":"Fossil Remnants", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":7379, "SellPrice":7378, "MeanPrice":11785, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128732183, "Name":"$ancientrelic_name;", "Name_Localised":"Guardian Relic", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":9126, "SellPrice":9125, "MeanPrice":24962, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128732184, "Name":"$ancientorb_name;", "Name_Localised":"Guardian Orb", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":5967, "SellPrice":5966, "MeanPrice":17415, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128732185, "Name":"$ancientcasket_name;", "Name_Localised":"Guardian Casket", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":5581, "SellPrice":5580, "MeanPrice":16294, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128732186, "Name":"$ancienttablet_name;", "Name_Localised":"Guardian Tablet", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":5967, "SellPrice":5966, "MeanPrice":17415, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128732187, "Name":"$ancienturn_name;", "Name_Localised":"Guardian Urn", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":3907, "SellPrice":3906, "MeanPrice":14907, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128732188, "Name":"$ancienttotem_name;", "Name_Localised":"Guardian Totem", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":7379, "SellPrice":7378, "MeanPrice":20437, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128732551, "Name":"$shanscharisorchid_name;", "Name_Localised":"Shan's Charis Orchid", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":1914, "SellPrice":1913, "MeanPrice":9043, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128737287, "Name":"$unknownresin_name;", "Name_Localised":"Thargoid Resin", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":22634, "SellPrice":22632, "MeanPrice":32825, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128737288, "Name":"$unknownbiologicalmatter_name;", "Name_Localised":"Thargoid Biological Matter", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":37090, "SellPrice":37088, "MeanPrice":51920, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128737289, "Name":"$unknowntechnologysamples_name;", "Name_Localised":"Thargoid Technology Samples", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":28012, "SellPrice":28010, "MeanPrice":39930, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128740752, "Name":"$unknownartifact3_name;", "Name_Localised":"Thargoid Link", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":37090, "SellPrice":37088, "MeanPrice":51920, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128748428, "Name":"$buckyballbeermats_name;", "Name_Localised":"Buckyball Beer Mats", "Category":"$MARKET_category_consumer_items;", "Category_Localised":"Consumer items", "BuyPrice":8230, "SellPrice":8229, "MeanPrice":7957, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128793113, "Name":"$harmasilversearum_name;", "Name_Localised":"Harma Silver Sea Rum", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":4217, "SellPrice":4216, "MeanPrice":9762, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128793114, "Name":"$platinumaloy_name;", "Name_Localised":"Platinum Alloy", "Category":"$MARKET_category_metals;", "Category_Localised":"Metals", "BuyPrice":12009, "SellPrice":12008, "MeanPrice":18333, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128793127, "Name":"$thargoidheart_name;", "Name_Localised":"Thargoid Heart", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":104381, "SellPrice":104375, "MeanPrice":140275, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128793128, "Name":"$thargoidtissuesampletype1_name;", "Name_Localised":"Thargoid Cyclops Tissue Sample", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":45421, "SellPrice":45418, "MeanPrice":63272, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128793129, "Name":"$thargoidtissuesampletype2_name;", "Name_Localised":"Thargoid Basilisk Tissue Sample", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":52545, "SellPrice":52542, "MeanPrice":72212, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128793130, "Name":"$thargoidtissuesampletype3_name;", "Name_Localised":"Thargoid Medusa Tissue Sample", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":60149, "SellPrice":60145, "MeanPrice":82435, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128824468, "Name":"$thargoidscouttissuesample_name;", "Name_Localised":"Thargoid Scout Tissue Sample", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":15982, "SellPrice":15981, "MeanPrice":23731, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128888499, "Name":"$ancientkey_name;", "Name_Localised":"Ancient Key", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":9760, "SellPrice":9759, "MeanPrice":29931, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128902652, "Name":"$thargoidtissuesampletype4_name;", "Name_Localised":"Thargoid Hydra Tissue Sample", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":79648, "SellPrice":79644, "MeanPrice":107495, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128913661, "Name":"$nanomedicines_name;", "Name_Localised":"Nanomedicines", "Category":"$MARKET_category_medicines;", "Category_Localised":"Medicines", "BuyPrice":2227, "SellPrice":2226, "MeanPrice":9859, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128922517, "Name":"$m_tissuesample_fluid_name;", "Name_Localised":"Mollusc Fluid", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":3380, "SellPrice":3379, "MeanPrice":6031, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922518, "Name":"$m_tissuesample_soft_name;", "Name_Localised":"Mollusc Soft Tissue", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":11290, "SellPrice":11289, "MeanPrice":17216, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922519, "Name":"$m_tissuesample_nerves_name;", "Name_Localised":"Mollusc Brain Tissue", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":22634, "SellPrice":22632, "MeanPrice":32825, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922520, "Name":"$s_tissuesample_cells_name;", "Name_Localised":"Pod Core Tissue", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":2532, "SellPrice":2531, "MeanPrice":4780, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922521, "Name":"$s_tissuesample_surface_name;", "Name_Localised":"Pod Dead Tissue", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":8438, "SellPrice":8437, "MeanPrice":13361, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922522, "Name":"$s_tissuesample_core_name;", "Name_Localised":"Pod Surface Tissue", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":19777, "SellPrice":19776, "MeanPrice":28819, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922523, "Name":"$p_particulatesample_name;", "Name_Localised":"Anomaly Particles", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":32061, "SellPrice":32059, "MeanPrice":45525, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922524, "Name":"$duradrives_name;", "Name_Localised":"Duradrives", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":13002, "SellPrice":13001, "MeanPrice":19356, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128922781, "Name":"$s9_tissuesample_shell_name;", "Name_Localised":"Pod Tissue", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":7890, "SellPrice":7889, "MeanPrice":12546, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922782, "Name":"$m3_tissuesample_membrane_name;", "Name_Localised":"Mollusc Membrane", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":12075, "SellPrice":12074, "MeanPrice":18352, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922783, "Name":"$m3_tissuesample_mycelium_name;", "Name_Localised":"Mollusc Mycelium", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":22634, "SellPrice":22632, "MeanPrice":32825, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922784, "Name":"$m3_tissuesample_spores_name;", "Name_Localised":"Mollusc Spores", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":3380, "SellPrice":3379, "MeanPrice":6031, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922785, "Name":"$s6_tissuesample_mesoglea_name;", "Name_Localised":"Pod Mesoglea", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":18488, "SellPrice":18487, "MeanPrice":27009, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922786, "Name":"$s6_tissuesample_cells_name;", "Name_Localised":"Pod Outer Tissue", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":4175, "SellPrice":4174, "MeanPrice":7210, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128922787, "Name":"$s6_tissuesample_coenosarc_name;", "Name_Localised":"Pod Shell Tissue", "Category":"$MARKET_category_salvage;", "Category_Localised":"Salvage", "BuyPrice":37090, "SellPrice":37088, "MeanPrice":51920, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128924325, "Name":"$rhodplumsite_name;", "Name_Localised":"Rhodplumsite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":275688, "MeanPrice":176839, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128924326, "Name":"$serendibite_name;", "Name_Localised":"Serendibite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":560027, "MeanPrice":172711, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128924327, "Name":"$monazite_name;", "Name_Localised":"Monazite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":840306, "MeanPrice":200975, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128924328, "Name":"$musgravite_name;", "Name_Localised":"Musgravite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":382972, "MeanPrice":198613, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128924329, "Name":"$benitoite_name;", "Name_Localised":"Benitoite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":570449, "MeanPrice":149395, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128924330, "Name":"$grandidierite_name;", "Name_Localised":"Grandidierite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":458141, "MeanPrice":197292, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128924331, "Name":"$alexandrite_name;", "Name_Localised":"Alexandrite", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":357530, "MeanPrice":217277, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128924332, "Name":"$opal_name;", "Name_Localised":"Void Opal", "Category":"$MARKET_category_minerals;", "Category_Localised":"Minerals", "BuyPrice":0, "SellPrice":525075, "MeanPrice":135284, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":1, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128924333, "Name":"$rockforthfertiliser_name;", "Name_Localised":"Rockforth Fertiliser", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":6, "SellPrice":5, "MeanPrice":9, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":false }, +{ "id":128924334, "Name":"$agronomictreatment_name;", "Name_Localised":"Agronomic Treatment", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":0, "SellPrice":15596, "MeanPrice":3105, "StockBracket":0, "DemandBracket":3, "Stock":0, "Demand":2, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":128958679, "Name":"$apavietii_name;", "Name_Localised":"Apa Vietii", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":3386, "SellPrice":3385, "MeanPrice":10362, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true }, +{ "id":128961249, "Name":"$tritium_name;", "Name_Localised":"Tritium", "Category":"$MARKET_category_chemicals;", "Category_Localised":"Chemicals", "BuyPrice":56235, "SellPrice":55627, "MeanPrice":51707, "StockBracket":1, "DemandBracket":0, "Stock":2, "Demand":1, "Consumer":false, "Producer":true, "Rare":false }, +{ "id":128983059, "Name":"$onionheadc_name;", "Name_Localised":"Onionhead Gamma Strain", "Category":"$MARKET_category_drugs;", "Category_Localised":"Legal drugs", "BuyPrice":0, "SellPrice":5755, "MeanPrice":4828, "StockBracket":0, "DemandBracket":1, "Stock":0, "Demand":0, "Consumer":true, "Producer":false, "Rare":false }, +{ "id":129002574, "Name":"$classifiedexperimentalequipment_name;", "Name_Localised":"Classified Experimental Equipment", "Category":"$MARKET_category_technology;", "Category_Localised":"Technology", "BuyPrice":4002, "SellPrice":4001, "MeanPrice":11423, "StockBracket":0, "DemandBracket":0, "Stock":0, "Demand":0, "Consumer":false, "Producer":false, "Rare":true } + ] } diff --git a/scripts/testing/gateway-responses/commodity-outdated-schema.json b/scripts/testing/gateway-responses/commodity-outdated-schema.json new file mode 100644 index 0000000..16225dc --- /dev/null +++ b/scripts/testing/gateway-responses/commodity-outdated-schema.json @@ -0,0 +1,46 @@ +{ + "$schemaRef": "http://schemas.elite-markets.net/eddn/commodity/2", + "message": { + "timestamp": "2022-01-06T11:19:27Z", + "systemName": "LP 98-132", + "stationName": "Freeport", + "marketId": 128008448, + "commodities": [ + { + "name": "advancedcatalysers", + "meanPrice": 3039, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3756, + "demand": 936, + "demandBracket": 3 + }, + { + "name": "advancedmedicines", + "meanPrice": 1485, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1726, + "demand": 296, + "demandBracket": 3 + }, + { + "name": "advert1", + "meanPrice": 21542, + "buyPrice": 15267, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15266, + "demand": 0, + "demandBracket": 0 + } + ] + }, + "header": { + "uploaderID": "Athanasius Testing", + "softwareName": "Athanasius Testing", + "softwareVersion": "v0.0.1" + } +} diff --git a/scripts/testing/gateway-responses/commodity-too-large.json b/scripts/testing/gateway-responses/commodity-too-large.json new file mode 100644 index 0000000..c887d1f --- /dev/null +++ b/scripts/testing/gateway-responses/commodity-too-large.json @@ -0,0 +1,6576 @@ +{ + "$schemaRef": "https://eddn.edcd.io/schemas/commodity/3", + "message": { + "timestamp": "2022-01-06T11:19:27Z", + "systemName": "LP 98-132", + "stationName": "Freeport", + "marketId": 128008448, + "commodities": [ + { + "name": "advancedcatalysers", + "meanPrice": 3039, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3756, + "demand": 936, + "demandBracket": 3 + }, + { + "name": "advancedmedicines", + "meanPrice": 1485, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1726, + "demand": 296, + "demandBracket": 3 + }, + { + "name": "advert1", + "meanPrice": 21542, + "buyPrice": 15267, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15266, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "aerialedenapple", + "meanPrice": 8331, + "buyPrice": 1660, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1659, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "agriculturalmedicines", + "meanPrice": 1231, + "buyPrice": 543, + "stock": 0, + "stockBracket": 0, + "sellPrice": 542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "agronomictreatment", + "meanPrice": 3105, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15596, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "alacarakmoskinart", + "meanPrice": 8899, + "buyPrice": 1858, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1857, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "albinoquechuamammoth", + "meanPrice": 9687, + "buyPrice": 2663, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2662, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "alexandrite", + "meanPrice": 217277, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 357530, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "algae", + "meanPrice": 356, + "buyPrice": 23, + "stock": 0, + "stockBracket": 0, + "sellPrice": 22, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "alieneggs", + "meanPrice": 25067, + "buyPrice": 19095, + "stock": 0, + "stockBracket": 0, + "sellPrice": 19094, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "altairianskin", + "meanPrice": 8432, + "buyPrice": 1262, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1261, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "aluminium", + "meanPrice": 551, + "buyPrice": 1127, + "stock": 352, + "stockBracket": 2, + "sellPrice": 1045, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "alyabodilysoap", + "meanPrice": 8218, + "buyPrice": 1078, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1077, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancientcasket", + "meanPrice": 16294, + "buyPrice": 5581, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5580, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancientkey", + "meanPrice": 29931, + "buyPrice": 9760, + "stock": 0, + "stockBracket": 0, + "sellPrice": 9759, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancientorb", + "meanPrice": 17415, + "buyPrice": 5967, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5966, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancientrelic", + "meanPrice": 24962, + "buyPrice": 9126, + "stock": 0, + "stockBracket": 0, + "sellPrice": 9125, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancienttablet", + "meanPrice": 17415, + "buyPrice": 5967, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5966, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancienttotem", + "meanPrice": 20437, + "buyPrice": 7379, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7378, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancienturn", + "meanPrice": 14907, + "buyPrice": 3907, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3906, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "anduligafireworks", + "meanPrice": 8519, + "buyPrice": 1574, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1573, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "animalmeat", + "meanPrice": 1539, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1695, + "demand": 26, + "demandBracket": 1 + }, + { + "name": "animalmonitors", + "meanPrice": 537, + "buyPrice": 630, + "stock": 0, + "stockBracket": 0, + "sellPrice": 629, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "antiquejewellery", + "meanPrice": 183163, + "buyPrice": 158957, + "stock": 0, + "stockBracket": 0, + "sellPrice": 158949, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "anynacoffee", + "meanPrice": 9160, + "buyPrice": 2165, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2164, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "apavietii", + "meanPrice": 10362, + "buyPrice": 3386, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3385, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "aquaponicsystems", + "meanPrice": 524, + "buyPrice": 321, + "stock": 0, + "stockBracket": 0, + "sellPrice": 320, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "aroucaconventualsweets", + "meanPrice": 8737, + "buyPrice": 1557, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1556, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "articulationmotors", + "meanPrice": 7588, + "buyPrice": 4463, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4462, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "assaultplans", + "meanPrice": 26074, + "buyPrice": 3294, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3293, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "atmosphericextractors", + "meanPrice": 571, + "buyPrice": 331, + "stock": 0, + "stockBracket": 0, + "sellPrice": 330, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "autofabricators", + "meanPrice": 3827, + "buyPrice": 2685, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2684, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "azcancriformula42", + "meanPrice": 12440, + "buyPrice": 6106, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6105, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bakedgreebles", + "meanPrice": 8211, + "buyPrice": 1056, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1055, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "baltahsinevacuumkrill", + "meanPrice": 8479, + "buyPrice": 1502, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1501, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bankiamphibiousleather", + "meanPrice": 8338, + "buyPrice": 1138, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1137, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "basicmedicines", + "meanPrice": 493, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 963, + "demand": 904, + "demandBracket": 3 + }, + { + "name": "bastsnakegin", + "meanPrice": 8659, + "buyPrice": 1724, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1723, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "battleweapons", + "meanPrice": 7451, + "buyPrice": 4463, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4462, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bauxite", + "meanPrice": 1140, + "buyPrice": 10730, + "stock": 595, + "stockBracket": 1, + "sellPrice": 10270, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "beer", + "meanPrice": 430, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 799, + "demand": 1777, + "demandBracket": 3 + }, + { + "name": "belalansrayleather", + "meanPrice": 8519, + "buyPrice": 1605, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1604, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "benitoite", + "meanPrice": 149395, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 570449, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "bertrandite", + "meanPrice": 18817, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 21216, + "demand": 1047, + "demandBracket": 2 + }, + { + "name": "beryllium", + "meanPrice": 8243, + "buyPrice": 8041, + "stock": 2, + "stockBracket": 1, + "sellPrice": 7948, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "bioreducinglichen", + "meanPrice": 1204, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1703, + "demand": 5473, + "demandBracket": 3 + }, + { + "name": "biowaste", + "meanPrice": 358, + "buyPrice": 145, + "stock": 103, + "stockBracket": 1, + "sellPrice": 87, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "bismuth", + "meanPrice": 2441, + "buyPrice": 1607, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1606, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bluemilk", + "meanPrice": 10805, + "buyPrice": 3912, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3911, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bromellite", + "meanPrice": 30424, + "buyPrice": 70950, + "stock": 0, + "stockBracket": 0, + "sellPrice": 70946, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "buckyballbeermats", + "meanPrice": 7957, + "buyPrice": 8230, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8229, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "buildingfabricators", + "meanPrice": 2312, + "buyPrice": 1448, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1447, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cd75catcoffee", + "meanPrice": 9571, + "buyPrice": 2452, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2451, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "centaurimegagin", + "meanPrice": 10217, + "buyPrice": 3239, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3238, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ceramiccomposites", + "meanPrice": 415, + "buyPrice": 424, + "stock": 0, + "stockBracket": 0, + "sellPrice": 423, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ceremonialheiketea", + "meanPrice": 9251, + "buyPrice": 2161, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2160, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cetiaepyornisegg", + "meanPrice": 9769, + "buyPrice": 2741, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2740, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cetirabbits", + "meanPrice": 9079, + "buyPrice": 2068, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2067, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "chameleoncloth", + "meanPrice": 9071, + "buyPrice": 1959, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1958, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "chateaudeaegaeon", + "meanPrice": 8791, + "buyPrice": 1610, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1609, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "chemicalwaste", + "meanPrice": 672, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 599, + "demand": 159, + "demandBracket": 3 + }, + { + "name": "cherbonesbloodcrystals", + "meanPrice": 16714, + "buyPrice": 10207, + "stock": 0, + "stockBracket": 0, + "sellPrice": 10206, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "chieridanimarinepaste", + "meanPrice": 8450, + "buyPrice": 1426, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1425, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "classifiedexperimentalequipment", + "meanPrice": 11423, + "buyPrice": 4002, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4001, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "clothing", + "meanPrice": 546, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 963, + "demand": 955, + "demandBracket": 3 + }, + { + "name": "cmmcomposite", + "meanPrice": 5988, + "buyPrice": 3907, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3906, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cobalt", + "meanPrice": 3762, + "buyPrice": 13474, + "stock": 724, + "stockBracket": 1, + "sellPrice": 12870, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "coffee", + "meanPrice": 1499, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2303, + "demand": 527, + "demandBracket": 3 + }, + { + "name": "coltan", + "meanPrice": 6163, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7849, + "demand": 2063, + "demandBracket": 3 + }, + { + "name": "comercialsamples", + "meanPrice": 1815, + "buyPrice": 656, + "stock": 0, + "stockBracket": 0, + "sellPrice": 655, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "computercomponents", + "meanPrice": 776, + "buyPrice": 267, + "stock": 0, + "stockBracket": 0, + "sellPrice": 266, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "conductivefabrics", + "meanPrice": 709, + "buyPrice": 1937, + "stock": 55, + "stockBracket": 1, + "sellPrice": 1810, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "consumertechnology", + "meanPrice": 6690, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6883, + "demand": 0, + "demandBracket": 1 + }, + { + "name": "coolinghoses", + "meanPrice": 1886, + "buyPrice": 707, + "stock": 0, + "stockBracket": 0, + "sellPrice": 706, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "copper", + "meanPrice": 689, + "buyPrice": 1115, + "stock": 474, + "stockBracket": 2, + "sellPrice": 1042, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "coquimspongiformvictuals", + "meanPrice": 8077, + "buyPrice": 10924, + "stock": 0, + "stockBracket": 0, + "sellPrice": 10923, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cropharvesters", + "meanPrice": 2230, + "buyPrice": 1564, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1563, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cryolite", + "meanPrice": 12173, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 14970, + "demand": 1166, + "demandBracket": 3 + }, + { + "name": "crystallinespheres", + "meanPrice": 12216, + "buyPrice": 5438, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5437, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "damnacarapaces", + "meanPrice": 8120, + "buyPrice": 2925, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2924, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "datacore", + "meanPrice": 6791, + "buyPrice": 3907, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3906, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "deltaphoenicispalms", + "meanPrice": 8188, + "buyPrice": 1528, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1527, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "deuringastruffles", + "meanPrice": 9232, + "buyPrice": 2335, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2334, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "diagnosticsensor", + "meanPrice": 6727, + "buyPrice": 4463, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4462, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "diplomaticbag", + "meanPrice": 28625, + "buyPrice": 4265, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4264, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "disomacorn", + "meanPrice": 8134, + "buyPrice": 1053, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1052, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "domesticappliances", + "meanPrice": 740, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1216, + "demand": 575, + "demandBracket": 3 + }, + { + "name": "duradrives", + "meanPrice": 19356, + "buyPrice": 13002, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13001, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "earthrelics", + "meanPrice": 15161, + "buyPrice": 14640, + "stock": 0, + "stockBracket": 0, + "sellPrice": 14639, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "eleuthermals", + "meanPrice": 8507, + "buyPrice": 1571, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1570, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "emergencypowercells", + "meanPrice": 2368, + "buyPrice": 1338, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1337, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "encripteddatastorage", + "meanPrice": 8313, + "buyPrice": 4049, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4048, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "encryptedcorrespondence", + "meanPrice": 8226, + "buyPrice": 3935, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3934, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "eraninpearlwhisky", + "meanPrice": 9040, + "buyPrice": 2058, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2057, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "eshuumbrellas", + "meanPrice": 9343, + "buyPrice": 2187, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2186, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "esusekucaviar", + "meanPrice": 9625, + "buyPrice": 2573, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2572, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ethgrezeteabuds", + "meanPrice": 10197, + "buyPrice": 3212, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3211, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "evacuationshelter", + "meanPrice": 522, + "buyPrice": 138, + "stock": 0, + "stockBracket": 0, + "sellPrice": 137, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "exhaustmanifold", + "meanPrice": 1873, + "buyPrice": 1009, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1008, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "explosives", + "meanPrice": 512, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2101, + "demand": 3964, + "demandBracket": 3 + }, + { + "name": "fish", + "meanPrice": 650, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1008, + "demand": 481, + "demandBracket": 2 + }, + { + "name": "foodcartridges", + "meanPrice": 265, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 767, + "demand": 1094, + "demandBracket": 3 + }, + { + "name": "fossilremnants", + "meanPrice": 11785, + "buyPrice": 7379, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7378, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "fruitandvegetables", + "meanPrice": 509, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1060, + "demand": 1637, + "demandBracket": 3 + }, + { + "name": "fujintea", + "meanPrice": 8597, + "buyPrice": 1418, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1417, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "galactictravelguide", + "meanPrice": 8627, + "buyPrice": 359, + "stock": 0, + "stockBracket": 0, + "sellPrice": 358, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "gallite", + "meanPrice": 11915, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13829, + "demand": 1765, + "demandBracket": 3 + }, + { + "name": "gallium", + "meanPrice": 5203, + "buyPrice": 5165, + "stock": 11, + "stockBracket": 1, + "sellPrice": 5042, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "genebank", + "meanPrice": 59082, + "buyPrice": 46704, + "stock": 0, + "stockBracket": 0, + "sellPrice": 46701, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "geologicalequipment", + "meanPrice": 1886, + "buyPrice": 1186, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1185, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "geologicalsamples", + "meanPrice": 8313, + "buyPrice": 12144, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12143, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "gerasiangueuzebeer", + "meanPrice": 8215, + "buyPrice": 1067, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1066, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "giantirukamasnails", + "meanPrice": 9174, + "buyPrice": 2131, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2130, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "giantverrix", + "meanPrice": 12496, + "buyPrice": 5713, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5712, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "gold", + "meanPrice": 47610, + "buyPrice": 44874, + "stock": 2, + "stockBracket": 1, + "sellPrice": 44362, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "gomanyauponcoffee", + "meanPrice": 8921, + "buyPrice": 1843, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1842, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "goslarite", + "meanPrice": 5979, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8024, + "demand": 1290, + "demandBracket": 3 + }, + { + "name": "grain", + "meanPrice": 410, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 919, + "demand": 2980, + "demandBracket": 3 + }, + { + "name": "grandidierite", + "meanPrice": 197292, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 458141, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "haidneblackbrew", + "meanPrice": 8837, + "buyPrice": 1693, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1692, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "harmasilversearum", + "meanPrice": 9762, + "buyPrice": 4217, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4216, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "havasupaidreamcatcher", + "meanPrice": 14639, + "buyPrice": 8056, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8055, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hazardousenvironmentsuits", + "meanPrice": 570, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 915, + "demand": 4363, + "demandBracket": 3 + }, + { + "name": "heatsinkinterlink", + "meanPrice": 2100, + "buyPrice": 1161, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1160, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "heliostaticfurnaces", + "meanPrice": 434, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2010, + "demand": 537, + "demandBracket": 3 + }, + { + "name": "helvetitjpearls", + "meanPrice": 10450, + "buyPrice": 3507, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3506, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hip10175bushmeat", + "meanPrice": 9382, + "buyPrice": 2246, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2245, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hip41181squid", + "meanPrice": 8947, + "buyPrice": 1891, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1890, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hiporganophosphates", + "meanPrice": 8169, + "buyPrice": 1039, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1038, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hnshockmount", + "meanPrice": 1922, + "buyPrice": 1075, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1074, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "honestypills", + "meanPrice": 8860, + "buyPrice": 1686, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1685, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hr7221wheat", + "meanPrice": 8190, + "buyPrice": 1540, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1539, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hydrogenfuel", + "meanPrice": 113, + "buyPrice": 126, + "stock": 379, + "stockBracket": 1, + "sellPrice": 120, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "hydrogenperoxide", + "meanPrice": 3160, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3301, + "demand": 548, + "demandBracket": 3 + }, + { + "name": "indibourbon", + "meanPrice": 8806, + "buyPrice": 1638, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1637, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "indite", + "meanPrice": 11389, + "buyPrice": 10508, + "stock": 296, + "stockBracket": 1, + "sellPrice": 10238, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "indium", + "meanPrice": 5845, + "buyPrice": 5894, + "stock": 8, + "stockBracket": 1, + "sellPrice": 5824, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "insulatingmembrane", + "meanPrice": 10724, + "buyPrice": 10137, + "stock": 2, + "stockBracket": 2, + "sellPrice": 10021, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "iondistributor", + "meanPrice": 2363, + "buyPrice": 1338, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1337, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jadeite", + "meanPrice": 42383, + "buyPrice": 40631, + "stock": 0, + "stockBracket": 0, + "sellPrice": 40628, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jaquesquinentianstill", + "meanPrice": 13845, + "buyPrice": 7233, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7232, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jaradharrepuzzlebox", + "meanPrice": 16816, + "buyPrice": 10325, + "stock": 0, + "stockBracket": 0, + "sellPrice": 10324, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jarouarice", + "meanPrice": 8169, + "buyPrice": 2711, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2710, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jotunmookah", + "meanPrice": 8780, + "buyPrice": 1637, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1636, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "kachiriginleaches", + "meanPrice": 8227, + "buyPrice": 1359, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1358, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "kamitracigars", + "meanPrice": 12282, + "buyPrice": 5522, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5521, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "karetiicouture", + "meanPrice": 11582, + "buyPrice": 4748, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4747, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "karsukilocusts", + "meanPrice": 8543, + "buyPrice": 1583, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1582, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "kinagoinstruments", + "meanPrice": 13030, + "buyPrice": 6570, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6569, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "konggaale", + "meanPrice": 8310, + "buyPrice": 1578, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1577, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "korrokungpellets", + "meanPrice": 8067, + "buyPrice": 1190, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1189, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "lanthanum", + "meanPrice": 8707, + "buyPrice": 6087, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6086, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "largeexplorationdatacash", + "meanPrice": 255841, + "buyPrice": 225210, + "stock": 0, + "stockBracket": 0, + "sellPrice": 225198, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "lavianbrandy", + "meanPrice": 10365, + "buyPrice": 3614, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3613, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "leather", + "meanPrice": 435, + "buyPrice": 57, + "stock": 0, + "stockBracket": 0, + "sellPrice": 56, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "leestianeviljuice", + "meanPrice": 8220, + "buyPrice": 1086, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1085, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "lepidolite", + "meanPrice": 771, + "buyPrice": 4193, + "stock": 1271, + "stockBracket": 1, + "sellPrice": 3999, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "lftvoidextractcoffee", + "meanPrice": 9554, + "buyPrice": 2506, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2505, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "liquidoxygen", + "meanPrice": 1474, + "buyPrice": 957, + "stock": 22, + "stockBracket": 1, + "sellPrice": 850, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "liquor", + "meanPrice": 879, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1331, + "demand": 453, + "demandBracket": 3 + }, + { + "name": "lithium", + "meanPrice": 1772, + "buyPrice": 1906, + "stock": 6, + "stockBracket": 1, + "sellPrice": 1855, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "lithiumhydroxide", + "meanPrice": 5673, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7350, + "demand": 99, + "demandBracket": 3 + }, + { + "name": "livehecateseaworms", + "meanPrice": 8737, + "buyPrice": 1899, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1898, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "lowtemperaturediamond", + "meanPrice": 106353, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 293785, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "ltthypersweet", + "meanPrice": 8054, + "buyPrice": 1233, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1232, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m3_tissuesample_membrane", + "meanPrice": 18352, + "buyPrice": 12075, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12074, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m3_tissuesample_mycelium", + "meanPrice": 32825, + "buyPrice": 22634, + "stock": 0, + "stockBracket": 0, + "sellPrice": 22632, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m3_tissuesample_spores", + "meanPrice": 6031, + "buyPrice": 3380, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3379, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m_tissuesample_fluid", + "meanPrice": 6031, + "buyPrice": 3380, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3379, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m_tissuesample_nerves", + "meanPrice": 32825, + "buyPrice": 22634, + "stock": 0, + "stockBracket": 0, + "sellPrice": 22632, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m_tissuesample_soft", + "meanPrice": 17216, + "buyPrice": 11290, + "stock": 0, + "stockBracket": 0, + "sellPrice": 11289, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "magneticemittercoil", + "meanPrice": 1357, + "buyPrice": 656, + "stock": 0, + "stockBracket": 0, + "sellPrice": 655, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "marinesupplies", + "meanPrice": 4135, + "buyPrice": 2745, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2744, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "mechucoshightea", + "meanPrice": 8846, + "buyPrice": 1709, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1708, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "medbstarlube", + "meanPrice": 8191, + "buyPrice": 1953, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1952, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "medicaldiagnosticequipment", + "meanPrice": 3075, + "buyPrice": 1779, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1778, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "metaalloys", + "meanPrice": 195453, + "buyPrice": 162685, + "stock": 0, + "stockBracket": 0, + "sellPrice": 162676, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "methaneclathrate", + "meanPrice": 1650, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1740, + "demand": 2873, + "demandBracket": 3 + }, + { + "name": "methanolmonohydratecrystals", + "meanPrice": 2478, + "buyPrice": 1290, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1289, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "microcontrollers", + "meanPrice": 5590, + "buyPrice": 3612, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3611, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "militarygradefabrics", + "meanPrice": 984, + "buyPrice": 3690, + "stock": 46, + "stockBracket": 1, + "sellPrice": 3527, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "mineralextractors", + "meanPrice": 801, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2647, + "demand": 1698, + "demandBracket": 3 + }, + { + "name": "mineraloil", + "meanPrice": 423, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1483, + "demand": 3336, + "demandBracket": 3 + }, + { + "name": "modularterminals", + "meanPrice": 2475, + "buyPrice": 1075, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1074, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "moissanite", + "meanPrice": 24833, + "buyPrice": 16662, + "stock": 0, + "stockBracket": 0, + "sellPrice": 16661, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "mokojingbeastfeast", + "meanPrice": 9788, + "buyPrice": 2770, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2769, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "momusbogspaniel", + "meanPrice": 9184, + "buyPrice": 2054, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2053, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "monazite", + "meanPrice": 200975, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 840306, + "demand": 1, + "demandBracket": 3 + }, + { + "name": "mukusubiichitinos", + "meanPrice": 8359, + "buyPrice": 1190, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1189, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "mulachigiantfungus", + "meanPrice": 7957, + "buyPrice": 8230, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8229, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "musgravite", + "meanPrice": 198613, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 382972, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "mutomimager", + "meanPrice": 6311, + "buyPrice": 4218, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4217, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "mysteriousidol", + "meanPrice": 20863, + "buyPrice": 13815, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13814, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "nanobreakers", + "meanPrice": 2366, + "buyPrice": 1009, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1008, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "nanomedicines", + "meanPrice": 9859, + "buyPrice": 2227, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2226, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "naturalfabrics", + "meanPrice": 688, + "buyPrice": 351, + "stock": 0, + "stockBracket": 0, + "sellPrice": 350, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "neofabricinsulation", + "meanPrice": 5978, + "buyPrice": 3380, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3379, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "neritusberries", + "meanPrice": 8497, + "buyPrice": 1616, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1615, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ngadandarifireopals", + "meanPrice": 19112, + "buyPrice": 12751, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12750, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ngunamodernantiques", + "meanPrice": 8545, + "buyPrice": 1989, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1988, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "njangarisaddles", + "meanPrice": 8356, + "buyPrice": 1639, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1638, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "noneuclidianexotanks", + "meanPrice": 8526, + "buyPrice": 1326, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1325, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "nonlethalweapons", + "meanPrice": 1943, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2417, + "demand": 274, + "demandBracket": 3 + }, + { + "name": "ochoengchillies", + "meanPrice": 8601, + "buyPrice": 1659, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1658, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "onionhead", + "meanPrice": 8437, + "buyPrice": 1814, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1813, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "onionheada", + "meanPrice": 8437, + "buyPrice": 1272, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1271, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "onionheadb", + "meanPrice": 8437, + "buyPrice": 1272, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1271, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "onionheadc", + "meanPrice": 4828, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5755, + "demand": 0, + "demandBracket": 1 + }, + { + "name": "opal", + "meanPrice": 135284, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 525075, + "demand": 1, + "demandBracket": 3 + }, + { + "name": "ophiuchiexinoartefacts", + "meanPrice": 10969, + "buyPrice": 4072, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4071, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "orrerianviciousbrew", + "meanPrice": 8342, + "buyPrice": 1146, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1145, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "osmium", + "meanPrice": 45198, + "buyPrice": 23482, + "stock": 0, + "stockBracket": 0, + "sellPrice": 23480, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "p_particulatesample", + "meanPrice": 45525, + "buyPrice": 32061, + "stock": 0, + "stockBracket": 0, + "sellPrice": 32059, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "painite", + "meanPrice": 53016, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 192955, + "demand": 4, + "demandBracket": 3 + }, + { + "name": "palladium", + "meanPrice": 50639, + "buyPrice": 47901, + "stock": 2, + "stockBracket": 1, + "sellPrice": 47360, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "pantaaprayersticks", + "meanPrice": 9177, + "buyPrice": 2043, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2042, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "performanceenhancers", + "meanPrice": 6790, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6907, + "demand": 40, + "demandBracket": 1 + }, + { + "name": "personalgifts", + "meanPrice": 16535, + "buyPrice": 10000, + "stock": 0, + "stockBracket": 0, + "sellPrice": 9999, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "pesticides", + "meanPrice": 437, + "buyPrice": 82, + "stock": 0, + "stockBracket": 0, + "sellPrice": 81, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "platinum", + "meanPrice": 58263, + "buyPrice": 39557, + "stock": 0, + "stockBracket": 0, + "sellPrice": 39555, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "platinumaloy", + "meanPrice": 18333, + "buyPrice": 12009, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12008, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "polymers", + "meanPrice": 376, + "buyPrice": 2614, + "stock": 272, + "stockBracket": 1, + "sellPrice": 1960, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "powerconverter", + "meanPrice": 1433, + "buyPrice": 707, + "stock": 0, + "stockBracket": 0, + "sellPrice": 706, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "powergenerators", + "meanPrice": 2466, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3475, + "demand": 613, + "demandBracket": 3 + }, + { + "name": "powergridassembly", + "meanPrice": 2659, + "buyPrice": 1543, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "powertransferconduits", + "meanPrice": 2212, + "buyPrice": 1254, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1253, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "praseodymium", + "meanPrice": 8620, + "buyPrice": 6708, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6707, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "preciousgems", + "meanPrice": 160280, + "buyPrice": 138850, + "stock": 0, + "stockBracket": 0, + "sellPrice": 138843, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "progenitorcells", + "meanPrice": 6752, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7529, + "demand": 6, + "demandBracket": 3 + }, + { + "name": "pyrophyllite", + "meanPrice": 11538, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13777, + "demand": 341, + "demandBracket": 3 + }, + { + "name": "radiationbaffle", + "meanPrice": 1787, + "buyPrice": 935, + "stock": 0, + "stockBracket": 0, + "sellPrice": 934, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rajukrustoves", + "meanPrice": 8378, + "buyPrice": 2346, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2345, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rapabaosnakeskins", + "meanPrice": 8285, + "buyPrice": 1726, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1725, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "reactivearmour", + "meanPrice": 2224, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2669, + "demand": 150, + "demandBracket": 3 + }, + { + "name": "reinforcedmountingplate", + "meanPrice": 2454, + "buyPrice": 1446, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1445, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "resonatingseparators", + "meanPrice": 5937, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7158, + "demand": 491, + "demandBracket": 2 + }, + { + "name": "rhodplumsite", + "meanPrice": 176839, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 275688, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "robotics", + "meanPrice": 2020, + "buyPrice": 1447, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1446, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rockforthfertiliser", + "meanPrice": 9, + "buyPrice": 6, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rusanioldsmokey", + "meanPrice": 11994, + "buyPrice": 5179, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5178, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rutile", + "meanPrice": 2083, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 11056, + "demand": 1306, + "demandBracket": 3 + }, + { + "name": "s6_tissuesample_cells", + "meanPrice": 7210, + "buyPrice": 4175, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4174, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s6_tissuesample_coenosarc", + "meanPrice": 51920, + "buyPrice": 37090, + "stock": 0, + "stockBracket": 0, + "sellPrice": 37088, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s6_tissuesample_mesoglea", + "meanPrice": 27009, + "buyPrice": 18488, + "stock": 0, + "stockBracket": 0, + "sellPrice": 18487, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s9_tissuesample_shell", + "meanPrice": 12546, + "buyPrice": 7890, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7889, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s_tissuesample_cells", + "meanPrice": 4780, + "buyPrice": 2532, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2531, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s_tissuesample_core", + "meanPrice": 28819, + "buyPrice": 19777, + "stock": 0, + "stockBracket": 0, + "sellPrice": 19776, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s_tissuesample_surface", + "meanPrice": 13361, + "buyPrice": 8438, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8437, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "samarium", + "meanPrice": 25852, + "buyPrice": 31195, + "stock": 0, + "stockBracket": 0, + "sellPrice": 31193, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "sanumameat", + "meanPrice": 8504, + "buyPrice": 1319, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1318, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "sap8corecontainer", + "meanPrice": 67593, + "buyPrice": 49112, + "stock": 0, + "stockBracket": 0, + "sellPrice": 49109, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "saxonwine", + "meanPrice": 8983, + "buyPrice": 1863, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1862, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "scientificresearch", + "meanPrice": 20151, + "buyPrice": 13394, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13393, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "scientificsamples", + "meanPrice": 7955, + "buyPrice": 10878, + "stock": 0, + "stockBracket": 0, + "sellPrice": 10877, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "scrap", + "meanPrice": 300, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 625, + "demand": 182, + "demandBracket": 3 + }, + { + "name": "semiconductors", + "meanPrice": 1136, + "buyPrice": 1415, + "stock": 42, + "stockBracket": 1, + "sellPrice": 1355, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "serendibite", + "meanPrice": 172711, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 560027, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "shanscharisorchid", + "meanPrice": 9043, + "buyPrice": 1914, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1913, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "silver", + "meanPrice": 37223, + "buyPrice": 34289, + "stock": 8, + "stockBracket": 1, + "sellPrice": 33471, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "skimercomponents", + "meanPrice": 1119, + "buyPrice": 530, + "stock": 0, + "stockBracket": 0, + "sellPrice": 529, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "smallexplorationdatacash", + "meanPrice": 25005, + "buyPrice": 40615, + "stock": 0, + "stockBracket": 0, + "sellPrice": 40612, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "soontillrelics", + "meanPrice": 19885, + "buyPrice": 13602, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13601, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "sothiscrystallinegold", + "meanPrice": 19112, + "buyPrice": 12751, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12750, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "spacepioneerrelics", + "meanPrice": 9780, + "buyPrice": 5967, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5966, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "structuralregulators", + "meanPrice": 1932, + "buyPrice": 1186, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1185, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "superconductors", + "meanPrice": 6679, + "buyPrice": 6809, + "stock": 14, + "stockBracket": 1, + "sellPrice": 6729, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "surfacestabilisers", + "meanPrice": 726, + "buyPrice": 1656, + "stock": 67, + "stockBracket": 1, + "sellPrice": 1550, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "survivalequipment", + "meanPrice": 684, + "buyPrice": 533, + "stock": 0, + "stockBracket": 0, + "sellPrice": 532, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "syntheticfabrics", + "meanPrice": 416, + "buyPrice": 1705, + "stock": 197, + "stockBracket": 1, + "sellPrice": 1435, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "syntheticmeat", + "meanPrice": 440, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 872, + "demand": 496, + "demandBracket": 3 + }, + { + "name": "syntheticreagents", + "meanPrice": 6651, + "buyPrice": 4463, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4462, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "taaffeite", + "meanPrice": 52089, + "buyPrice": 51665, + "stock": 0, + "stockBracket": 0, + "sellPrice": 51662, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tacticaldata", + "meanPrice": 15622, + "buyPrice": 2170, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2169, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tanmarktranquiltea", + "meanPrice": 9177, + "buyPrice": 2041, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2040, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tantalum", + "meanPrice": 4044, + "buyPrice": 4099, + "stock": 2, + "stockBracket": 1, + "sellPrice": 3999, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "taurichimes", + "meanPrice": 8549, + "buyPrice": 1374, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1373, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tea", + "meanPrice": 1696, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1923, + "demand": 43, + "demandBracket": 2 + }, + { + "name": "telemetrysuite", + "meanPrice": 3214, + "buyPrice": 1543, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "terrainenrichmentsystems", + "meanPrice": 4928, + "buyPrice": 3005, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3004, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thallium", + "meanPrice": 3745, + "buyPrice": 2539, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2538, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidheart", + "meanPrice": 140275, + "buyPrice": 104381, + "stock": 0, + "stockBracket": 0, + "sellPrice": 104375, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidscouttissuesample", + "meanPrice": 23731, + "buyPrice": 15982, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15981, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidtissuesampletype1", + "meanPrice": 63272, + "buyPrice": 45421, + "stock": 0, + "stockBracket": 0, + "sellPrice": 45418, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidtissuesampletype2", + "meanPrice": 72212, + "buyPrice": 52545, + "stock": 0, + "stockBracket": 0, + "sellPrice": 52542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidtissuesampletype3", + "meanPrice": 82435, + "buyPrice": 60149, + "stock": 0, + "stockBracket": 0, + "sellPrice": 60145, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidtissuesampletype4", + "meanPrice": 107495, + "buyPrice": 79648, + "stock": 0, + "stockBracket": 0, + "sellPrice": 79644, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thehuttonmug", + "meanPrice": 7986, + "buyPrice": 2751, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2750, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thermalcoolingunits", + "meanPrice": 3760, + "buyPrice": 2516, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2515, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thorium", + "meanPrice": 11317, + "buyPrice": 7969, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7968, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thrutiscream", + "meanPrice": 8550, + "buyPrice": 1538, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1537, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tiegfriessynthsilk", + "meanPrice": 8478, + "buyPrice": 1263, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1262, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "timecapsule", + "meanPrice": 5364, + "buyPrice": 2926, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2925, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tiolcewaste2pasteunits", + "meanPrice": 8710, + "buyPrice": 1648, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1647, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "titanium", + "meanPrice": 1208, + "buyPrice": 1377, + "stock": 122, + "stockBracket": 2, + "sellPrice": 1319, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "tobacco", + "meanPrice": 5325, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5568, + "demand": 398, + "demandBracket": 3 + }, + { + "name": "toxandjivirocide", + "meanPrice": 8275, + "buyPrice": 1678, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1677, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "transgeniconionhead", + "meanPrice": 8472, + "buyPrice": 1483, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1482, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tritium", + "meanPrice": 51707, + "buyPrice": 56235, + "stock": 2, + "stockBracket": 1, + "sellPrice": 55627, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "unknownartifact", + "meanPrice": 306252, + "buyPrice": 234627, + "stock": 0, + "stockBracket": 0, + "sellPrice": 234615, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknownartifact2", + "meanPrice": 443535, + "buyPrice": 344560, + "stock": 0, + "stockBracket": 0, + "sellPrice": 344542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknownartifact3", + "meanPrice": 51920, + "buyPrice": 37090, + "stock": 0, + "stockBracket": 0, + "sellPrice": 37088, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknownbiologicalmatter", + "meanPrice": 51920, + "buyPrice": 37090, + "stock": 0, + "stockBracket": 0, + "sellPrice": 37088, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknownresin", + "meanPrice": 32825, + "buyPrice": 22634, + "stock": 0, + "stockBracket": 0, + "sellPrice": 22632, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknowntechnologysamples", + "meanPrice": 39930, + "buyPrice": 28012, + "stock": 0, + "stockBracket": 0, + "sellPrice": 28010, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unstabledatacore", + "meanPrice": 4516, + "buyPrice": 2371, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2370, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "uraninite", + "meanPrice": 2957, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4202, + "demand": 2899, + "demandBracket": 3 + }, + { + "name": "uranium", + "meanPrice": 2827, + "buyPrice": 3139, + "stock": 24, + "stockBracket": 1, + "sellPrice": 3060, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "usscargorareartwork", + "meanPrice": 16807, + "buyPrice": 15150, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15149, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "uszaiantreegrub", + "meanPrice": 8578, + "buyPrice": 1379, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1378, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "utgaroarmillenialeggs", + "meanPrice": 9163, + "buyPrice": 2217, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2216, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "uzumokulowgwings", + "meanPrice": 13845, + "buyPrice": 7233, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7232, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "vanayequirhinofur", + "meanPrice": 8331, + "buyPrice": 1660, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1659, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "vegaslimweed", + "meanPrice": 9588, + "buyPrice": 2518, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2517, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "vherculisbodyrub", + "meanPrice": 8010, + "buyPrice": 1730, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1729, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "vidavantianlace", + "meanPrice": 12615, + "buyPrice": 5861, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5860, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "volkhabbeedrones", + "meanPrice": 10198, + "buyPrice": 3849, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3848, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "water", + "meanPrice": 278, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 599, + "demand": 336, + "demandBracket": 3 + }, + { + "name": "waterpurifiers", + "meanPrice": 484, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2101, + "demand": 1256, + "demandBracket": 3 + }, + { + "name": "watersofshintara", + "meanPrice": 13711, + "buyPrice": 7070, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7069, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "wheemetewheatcakes", + "meanPrice": 8081, + "buyPrice": 1164, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1163, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "wine", + "meanPrice": 507, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 411, + "demand": 0, + "demandBracket": 1 + }, + { + "name": "witchhaulkobebeef", + "meanPrice": 11085, + "buyPrice": 4313, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4312, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "wulpahyperboresystems", + "meanPrice": 8726, + "buyPrice": 2294, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2293, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "wuthielokufroth", + "meanPrice": 8194, + "buyPrice": 1558, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1557, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "xihecompanions", + "meanPrice": 11058, + "buyPrice": 4277, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4276, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "yasokondileaf", + "meanPrice": 12171, + "buyPrice": 5381, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5380, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "zeesszeantglue", + "meanPrice": 8161, + "buyPrice": 1089, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1088, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "advancedcatalysers", + "meanPrice": 3039, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3756, + "demand": 936, + "demandBracket": 3 + }, + { + "name": "advancedmedicines", + "meanPrice": 1485, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1726, + "demand": 296, + "demandBracket": 3 + }, + { + "name": "advert1", + "meanPrice": 21542, + "buyPrice": 15267, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15266, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "aerialedenapple", + "meanPrice": 8331, + "buyPrice": 1660, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1659, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "agriculturalmedicines", + "meanPrice": 1231, + "buyPrice": 543, + "stock": 0, + "stockBracket": 0, + "sellPrice": 542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "agronomictreatment", + "meanPrice": 3105, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15596, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "alacarakmoskinart", + "meanPrice": 8899, + "buyPrice": 1858, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1857, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "albinoquechuamammoth", + "meanPrice": 9687, + "buyPrice": 2663, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2662, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "alexandrite", + "meanPrice": 217277, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 357530, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "algae", + "meanPrice": 356, + "buyPrice": 23, + "stock": 0, + "stockBracket": 0, + "sellPrice": 22, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "alieneggs", + "meanPrice": 25067, + "buyPrice": 19095, + "stock": 0, + "stockBracket": 0, + "sellPrice": 19094, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "altairianskin", + "meanPrice": 8432, + "buyPrice": 1262, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1261, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "aluminium", + "meanPrice": 551, + "buyPrice": 1127, + "stock": 352, + "stockBracket": 2, + "sellPrice": 1045, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "alyabodilysoap", + "meanPrice": 8218, + "buyPrice": 1078, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1077, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancientcasket", + "meanPrice": 16294, + "buyPrice": 5581, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5580, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancientkey", + "meanPrice": 29931, + "buyPrice": 9760, + "stock": 0, + "stockBracket": 0, + "sellPrice": 9759, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancientorb", + "meanPrice": 17415, + "buyPrice": 5967, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5966, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancientrelic", + "meanPrice": 24962, + "buyPrice": 9126, + "stock": 0, + "stockBracket": 0, + "sellPrice": 9125, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancienttablet", + "meanPrice": 17415, + "buyPrice": 5967, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5966, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancienttotem", + "meanPrice": 20437, + "buyPrice": 7379, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7378, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ancienturn", + "meanPrice": 14907, + "buyPrice": 3907, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3906, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "anduligafireworks", + "meanPrice": 8519, + "buyPrice": 1574, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1573, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "animalmeat", + "meanPrice": 1539, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1695, + "demand": 26, + "demandBracket": 1 + }, + { + "name": "animalmonitors", + "meanPrice": 537, + "buyPrice": 630, + "stock": 0, + "stockBracket": 0, + "sellPrice": 629, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "antiquejewellery", + "meanPrice": 183163, + "buyPrice": 158957, + "stock": 0, + "stockBracket": 0, + "sellPrice": 158949, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "anynacoffee", + "meanPrice": 9160, + "buyPrice": 2165, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2164, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "apavietii", + "meanPrice": 10362, + "buyPrice": 3386, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3385, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "aquaponicsystems", + "meanPrice": 524, + "buyPrice": 321, + "stock": 0, + "stockBracket": 0, + "sellPrice": 320, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "aroucaconventualsweets", + "meanPrice": 8737, + "buyPrice": 1557, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1556, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "articulationmotors", + "meanPrice": 7588, + "buyPrice": 4463, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4462, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "assaultplans", + "meanPrice": 26074, + "buyPrice": 3294, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3293, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "atmosphericextractors", + "meanPrice": 571, + "buyPrice": 331, + "stock": 0, + "stockBracket": 0, + "sellPrice": 330, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "autofabricators", + "meanPrice": 3827, + "buyPrice": 2685, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2684, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "azcancriformula42", + "meanPrice": 12440, + "buyPrice": 6106, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6105, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bakedgreebles", + "meanPrice": 8211, + "buyPrice": 1056, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1055, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "baltahsinevacuumkrill", + "meanPrice": 8479, + "buyPrice": 1502, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1501, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bankiamphibiousleather", + "meanPrice": 8338, + "buyPrice": 1138, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1137, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "basicmedicines", + "meanPrice": 493, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 963, + "demand": 904, + "demandBracket": 3 + }, + { + "name": "bastsnakegin", + "meanPrice": 8659, + "buyPrice": 1724, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1723, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "battleweapons", + "meanPrice": 7451, + "buyPrice": 4463, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4462, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bauxite", + "meanPrice": 1140, + "buyPrice": 10730, + "stock": 595, + "stockBracket": 1, + "sellPrice": 10270, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "beer", + "meanPrice": 430, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 799, + "demand": 1777, + "demandBracket": 3 + }, + { + "name": "belalansrayleather", + "meanPrice": 8519, + "buyPrice": 1605, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1604, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "benitoite", + "meanPrice": 149395, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 570449, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "bertrandite", + "meanPrice": 18817, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 21216, + "demand": 1047, + "demandBracket": 2 + }, + { + "name": "beryllium", + "meanPrice": 8243, + "buyPrice": 8041, + "stock": 2, + "stockBracket": 1, + "sellPrice": 7948, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "bioreducinglichen", + "meanPrice": 1204, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1703, + "demand": 5473, + "demandBracket": 3 + }, + { + "name": "biowaste", + "meanPrice": 358, + "buyPrice": 145, + "stock": 103, + "stockBracket": 1, + "sellPrice": 87, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "bismuth", + "meanPrice": 2441, + "buyPrice": 1607, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1606, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bluemilk", + "meanPrice": 10805, + "buyPrice": 3912, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3911, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "bromellite", + "meanPrice": 30424, + "buyPrice": 70950, + "stock": 0, + "stockBracket": 0, + "sellPrice": 70946, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "buckyballbeermats", + "meanPrice": 7957, + "buyPrice": 8230, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8229, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "buildingfabricators", + "meanPrice": 2312, + "buyPrice": 1448, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1447, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cd75catcoffee", + "meanPrice": 9571, + "buyPrice": 2452, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2451, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "centaurimegagin", + "meanPrice": 10217, + "buyPrice": 3239, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3238, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ceramiccomposites", + "meanPrice": 415, + "buyPrice": 424, + "stock": 0, + "stockBracket": 0, + "sellPrice": 423, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ceremonialheiketea", + "meanPrice": 9251, + "buyPrice": 2161, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2160, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cetiaepyornisegg", + "meanPrice": 9769, + "buyPrice": 2741, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2740, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cetirabbits", + "meanPrice": 9079, + "buyPrice": 2068, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2067, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "chameleoncloth", + "meanPrice": 9071, + "buyPrice": 1959, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1958, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "chateaudeaegaeon", + "meanPrice": 8791, + "buyPrice": 1610, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1609, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "chemicalwaste", + "meanPrice": 672, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 599, + "demand": 159, + "demandBracket": 3 + }, + { + "name": "cherbonesbloodcrystals", + "meanPrice": 16714, + "buyPrice": 10207, + "stock": 0, + "stockBracket": 0, + "sellPrice": 10206, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "chieridanimarinepaste", + "meanPrice": 8450, + "buyPrice": 1426, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1425, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "classifiedexperimentalequipment", + "meanPrice": 11423, + "buyPrice": 4002, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4001, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "clothing", + "meanPrice": 546, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 963, + "demand": 955, + "demandBracket": 3 + }, + { + "name": "cmmcomposite", + "meanPrice": 5988, + "buyPrice": 3907, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3906, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cobalt", + "meanPrice": 3762, + "buyPrice": 13474, + "stock": 724, + "stockBracket": 1, + "sellPrice": 12870, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "coffee", + "meanPrice": 1499, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2303, + "demand": 527, + "demandBracket": 3 + }, + { + "name": "coltan", + "meanPrice": 6163, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7849, + "demand": 2063, + "demandBracket": 3 + }, + { + "name": "comercialsamples", + "meanPrice": 1815, + "buyPrice": 656, + "stock": 0, + "stockBracket": 0, + "sellPrice": 655, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "computercomponents", + "meanPrice": 776, + "buyPrice": 267, + "stock": 0, + "stockBracket": 0, + "sellPrice": 266, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "conductivefabrics", + "meanPrice": 709, + "buyPrice": 1937, + "stock": 55, + "stockBracket": 1, + "sellPrice": 1810, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "consumertechnology", + "meanPrice": 6690, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6883, + "demand": 0, + "demandBracket": 1 + }, + { + "name": "coolinghoses", + "meanPrice": 1886, + "buyPrice": 707, + "stock": 0, + "stockBracket": 0, + "sellPrice": 706, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "copper", + "meanPrice": 689, + "buyPrice": 1115, + "stock": 474, + "stockBracket": 2, + "sellPrice": 1042, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "coquimspongiformvictuals", + "meanPrice": 8077, + "buyPrice": 10924, + "stock": 0, + "stockBracket": 0, + "sellPrice": 10923, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cropharvesters", + "meanPrice": 2230, + "buyPrice": 1564, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1563, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "cryolite", + "meanPrice": 12173, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 14970, + "demand": 1166, + "demandBracket": 3 + }, + { + "name": "crystallinespheres", + "meanPrice": 12216, + "buyPrice": 5438, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5437, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "damnacarapaces", + "meanPrice": 8120, + "buyPrice": 2925, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2924, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "datacore", + "meanPrice": 6791, + "buyPrice": 3907, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3906, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "deltaphoenicispalms", + "meanPrice": 8188, + "buyPrice": 1528, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1527, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "deuringastruffles", + "meanPrice": 9232, + "buyPrice": 2335, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2334, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "diagnosticsensor", + "meanPrice": 6727, + "buyPrice": 4463, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4462, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "diplomaticbag", + "meanPrice": 28625, + "buyPrice": 4265, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4264, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "disomacorn", + "meanPrice": 8134, + "buyPrice": 1053, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1052, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "domesticappliances", + "meanPrice": 740, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1216, + "demand": 575, + "demandBracket": 3 + }, + { + "name": "duradrives", + "meanPrice": 19356, + "buyPrice": 13002, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13001, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "earthrelics", + "meanPrice": 15161, + "buyPrice": 14640, + "stock": 0, + "stockBracket": 0, + "sellPrice": 14639, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "eleuthermals", + "meanPrice": 8507, + "buyPrice": 1571, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1570, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "emergencypowercells", + "meanPrice": 2368, + "buyPrice": 1338, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1337, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "encripteddatastorage", + "meanPrice": 8313, + "buyPrice": 4049, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4048, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "encryptedcorrespondence", + "meanPrice": 8226, + "buyPrice": 3935, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3934, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "eraninpearlwhisky", + "meanPrice": 9040, + "buyPrice": 2058, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2057, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "eshuumbrellas", + "meanPrice": 9343, + "buyPrice": 2187, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2186, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "esusekucaviar", + "meanPrice": 9625, + "buyPrice": 2573, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2572, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ethgrezeteabuds", + "meanPrice": 10197, + "buyPrice": 3212, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3211, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "evacuationshelter", + "meanPrice": 522, + "buyPrice": 138, + "stock": 0, + "stockBracket": 0, + "sellPrice": 137, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "exhaustmanifold", + "meanPrice": 1873, + "buyPrice": 1009, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1008, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "explosives", + "meanPrice": 512, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2101, + "demand": 3964, + "demandBracket": 3 + }, + { + "name": "fish", + "meanPrice": 650, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1008, + "demand": 481, + "demandBracket": 2 + }, + { + "name": "foodcartridges", + "meanPrice": 265, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 767, + "demand": 1094, + "demandBracket": 3 + }, + { + "name": "fossilremnants", + "meanPrice": 11785, + "buyPrice": 7379, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7378, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "fruitandvegetables", + "meanPrice": 509, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1060, + "demand": 1637, + "demandBracket": 3 + }, + { + "name": "fujintea", + "meanPrice": 8597, + "buyPrice": 1418, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1417, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "galactictravelguide", + "meanPrice": 8627, + "buyPrice": 359, + "stock": 0, + "stockBracket": 0, + "sellPrice": 358, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "gallite", + "meanPrice": 11915, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13829, + "demand": 1765, + "demandBracket": 3 + }, + { + "name": "gallium", + "meanPrice": 5203, + "buyPrice": 5165, + "stock": 11, + "stockBracket": 1, + "sellPrice": 5042, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "genebank", + "meanPrice": 59082, + "buyPrice": 46704, + "stock": 0, + "stockBracket": 0, + "sellPrice": 46701, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "geologicalequipment", + "meanPrice": 1886, + "buyPrice": 1186, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1185, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "geologicalsamples", + "meanPrice": 8313, + "buyPrice": 12144, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12143, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "gerasiangueuzebeer", + "meanPrice": 8215, + "buyPrice": 1067, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1066, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "giantirukamasnails", + "meanPrice": 9174, + "buyPrice": 2131, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2130, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "giantverrix", + "meanPrice": 12496, + "buyPrice": 5713, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5712, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "gold", + "meanPrice": 47610, + "buyPrice": 44874, + "stock": 2, + "stockBracket": 1, + "sellPrice": 44362, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "gomanyauponcoffee", + "meanPrice": 8921, + "buyPrice": 1843, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1842, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "goslarite", + "meanPrice": 5979, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8024, + "demand": 1290, + "demandBracket": 3 + }, + { + "name": "grain", + "meanPrice": 410, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 919, + "demand": 2980, + "demandBracket": 3 + }, + { + "name": "grandidierite", + "meanPrice": 197292, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 458141, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "haidneblackbrew", + "meanPrice": 8837, + "buyPrice": 1693, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1692, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "harmasilversearum", + "meanPrice": 9762, + "buyPrice": 4217, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4216, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "havasupaidreamcatcher", + "meanPrice": 14639, + "buyPrice": 8056, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8055, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hazardousenvironmentsuits", + "meanPrice": 570, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 915, + "demand": 4363, + "demandBracket": 3 + }, + { + "name": "heatsinkinterlink", + "meanPrice": 2100, + "buyPrice": 1161, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1160, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "heliostaticfurnaces", + "meanPrice": 434, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2010, + "demand": 537, + "demandBracket": 3 + }, + { + "name": "helvetitjpearls", + "meanPrice": 10450, + "buyPrice": 3507, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3506, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hip10175bushmeat", + "meanPrice": 9382, + "buyPrice": 2246, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2245, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hip41181squid", + "meanPrice": 8947, + "buyPrice": 1891, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1890, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hiporganophosphates", + "meanPrice": 8169, + "buyPrice": 1039, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1038, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hnshockmount", + "meanPrice": 1922, + "buyPrice": 1075, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1074, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "honestypills", + "meanPrice": 8860, + "buyPrice": 1686, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1685, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hr7221wheat", + "meanPrice": 8190, + "buyPrice": 1540, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1539, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "hydrogenfuel", + "meanPrice": 113, + "buyPrice": 126, + "stock": 379, + "stockBracket": 1, + "sellPrice": 120, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "hydrogenperoxide", + "meanPrice": 3160, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3301, + "demand": 548, + "demandBracket": 3 + }, + { + "name": "indibourbon", + "meanPrice": 8806, + "buyPrice": 1638, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1637, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "indite", + "meanPrice": 11389, + "buyPrice": 10508, + "stock": 296, + "stockBracket": 1, + "sellPrice": 10238, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "indium", + "meanPrice": 5845, + "buyPrice": 5894, + "stock": 8, + "stockBracket": 1, + "sellPrice": 5824, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "insulatingmembrane", + "meanPrice": 10724, + "buyPrice": 10137, + "stock": 2, + "stockBracket": 2, + "sellPrice": 10021, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "iondistributor", + "meanPrice": 2363, + "buyPrice": 1338, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1337, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jadeite", + "meanPrice": 42383, + "buyPrice": 40631, + "stock": 0, + "stockBracket": 0, + "sellPrice": 40628, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jaquesquinentianstill", + "meanPrice": 13845, + "buyPrice": 7233, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7232, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jaradharrepuzzlebox", + "meanPrice": 16816, + "buyPrice": 10325, + "stock": 0, + "stockBracket": 0, + "sellPrice": 10324, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jarouarice", + "meanPrice": 8169, + "buyPrice": 2711, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2710, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "jotunmookah", + "meanPrice": 8780, + "buyPrice": 1637, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1636, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "kachiriginleaches", + "meanPrice": 8227, + "buyPrice": 1359, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1358, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "kamitracigars", + "meanPrice": 12282, + "buyPrice": 5522, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5521, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "karetiicouture", + "meanPrice": 11582, + "buyPrice": 4748, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4747, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "karsukilocusts", + "meanPrice": 8543, + "buyPrice": 1583, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1582, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "kinagoinstruments", + "meanPrice": 13030, + "buyPrice": 6570, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6569, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "konggaale", + "meanPrice": 8310, + "buyPrice": 1578, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1577, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "korrokungpellets", + "meanPrice": 8067, + "buyPrice": 1190, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1189, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "lanthanum", + "meanPrice": 8707, + "buyPrice": 6087, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6086, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "largeexplorationdatacash", + "meanPrice": 255841, + "buyPrice": 225210, + "stock": 0, + "stockBracket": 0, + "sellPrice": 225198, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "lavianbrandy", + "meanPrice": 10365, + "buyPrice": 3614, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3613, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "leather", + "meanPrice": 435, + "buyPrice": 57, + "stock": 0, + "stockBracket": 0, + "sellPrice": 56, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "leestianeviljuice", + "meanPrice": 8220, + "buyPrice": 1086, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1085, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "lepidolite", + "meanPrice": 771, + "buyPrice": 4193, + "stock": 1271, + "stockBracket": 1, + "sellPrice": 3999, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "lftvoidextractcoffee", + "meanPrice": 9554, + "buyPrice": 2506, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2505, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "liquidoxygen", + "meanPrice": 1474, + "buyPrice": 957, + "stock": 22, + "stockBracket": 1, + "sellPrice": 850, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "liquor", + "meanPrice": 879, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1331, + "demand": 453, + "demandBracket": 3 + }, + { + "name": "lithium", + "meanPrice": 1772, + "buyPrice": 1906, + "stock": 6, + "stockBracket": 1, + "sellPrice": 1855, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "lithiumhydroxide", + "meanPrice": 5673, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7350, + "demand": 99, + "demandBracket": 3 + }, + { + "name": "livehecateseaworms", + "meanPrice": 8737, + "buyPrice": 1899, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1898, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "lowtemperaturediamond", + "meanPrice": 106353, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 293785, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "ltthypersweet", + "meanPrice": 8054, + "buyPrice": 1233, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1232, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m3_tissuesample_membrane", + "meanPrice": 18352, + "buyPrice": 12075, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12074, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m3_tissuesample_mycelium", + "meanPrice": 32825, + "buyPrice": 22634, + "stock": 0, + "stockBracket": 0, + "sellPrice": 22632, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m3_tissuesample_spores", + "meanPrice": 6031, + "buyPrice": 3380, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3379, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m_tissuesample_fluid", + "meanPrice": 6031, + "buyPrice": 3380, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3379, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m_tissuesample_nerves", + "meanPrice": 32825, + "buyPrice": 22634, + "stock": 0, + "stockBracket": 0, + "sellPrice": 22632, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "m_tissuesample_soft", + "meanPrice": 17216, + "buyPrice": 11290, + "stock": 0, + "stockBracket": 0, + "sellPrice": 11289, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "magneticemittercoil", + "meanPrice": 1357, + "buyPrice": 656, + "stock": 0, + "stockBracket": 0, + "sellPrice": 655, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "marinesupplies", + "meanPrice": 4135, + "buyPrice": 2745, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2744, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "mechucoshightea", + "meanPrice": 8846, + "buyPrice": 1709, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1708, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "medbstarlube", + "meanPrice": 8191, + "buyPrice": 1953, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1952, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "medicaldiagnosticequipment", + "meanPrice": 3075, + "buyPrice": 1779, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1778, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "metaalloys", + "meanPrice": 195453, + "buyPrice": 162685, + "stock": 0, + "stockBracket": 0, + "sellPrice": 162676, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "methaneclathrate", + "meanPrice": 1650, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1740, + "demand": 2873, + "demandBracket": 3 + }, + { + "name": "methanolmonohydratecrystals", + "meanPrice": 2478, + "buyPrice": 1290, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1289, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "microcontrollers", + "meanPrice": 5590, + "buyPrice": 3612, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3611, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "militarygradefabrics", + "meanPrice": 984, + "buyPrice": 3690, + "stock": 46, + "stockBracket": 1, + "sellPrice": 3527, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "mineralextractors", + "meanPrice": 801, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2647, + "demand": 1698, + "demandBracket": 3 + }, + { + "name": "mineraloil", + "meanPrice": 423, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1483, + "demand": 3336, + "demandBracket": 3 + }, + { + "name": "modularterminals", + "meanPrice": 2475, + "buyPrice": 1075, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1074, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "moissanite", + "meanPrice": 24833, + "buyPrice": 16662, + "stock": 0, + "stockBracket": 0, + "sellPrice": 16661, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "mokojingbeastfeast", + "meanPrice": 9788, + "buyPrice": 2770, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2769, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "momusbogspaniel", + "meanPrice": 9184, + "buyPrice": 2054, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2053, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "monazite", + "meanPrice": 200975, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 840306, + "demand": 1, + "demandBracket": 3 + }, + { + "name": "mukusubiichitinos", + "meanPrice": 8359, + "buyPrice": 1190, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1189, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "mulachigiantfungus", + "meanPrice": 7957, + "buyPrice": 8230, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8229, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "musgravite", + "meanPrice": 198613, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 382972, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "mutomimager", + "meanPrice": 6311, + "buyPrice": 4218, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4217, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "mysteriousidol", + "meanPrice": 20863, + "buyPrice": 13815, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13814, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "nanobreakers", + "meanPrice": 2366, + "buyPrice": 1009, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1008, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "nanomedicines", + "meanPrice": 9859, + "buyPrice": 2227, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2226, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "naturalfabrics", + "meanPrice": 688, + "buyPrice": 351, + "stock": 0, + "stockBracket": 0, + "sellPrice": 350, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "neofabricinsulation", + "meanPrice": 5978, + "buyPrice": 3380, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3379, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "neritusberries", + "meanPrice": 8497, + "buyPrice": 1616, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1615, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ngadandarifireopals", + "meanPrice": 19112, + "buyPrice": 12751, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12750, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "ngunamodernantiques", + "meanPrice": 8545, + "buyPrice": 1989, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1988, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "njangarisaddles", + "meanPrice": 8356, + "buyPrice": 1639, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1638, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "noneuclidianexotanks", + "meanPrice": 8526, + "buyPrice": 1326, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1325, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "nonlethalweapons", + "meanPrice": 1943, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2417, + "demand": 274, + "demandBracket": 3 + }, + { + "name": "ochoengchillies", + "meanPrice": 8601, + "buyPrice": 1659, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1658, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "onionhead", + "meanPrice": 8437, + "buyPrice": 1814, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1813, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "onionheada", + "meanPrice": 8437, + "buyPrice": 1272, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1271, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "onionheadb", + "meanPrice": 8437, + "buyPrice": 1272, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1271, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "onionheadc", + "meanPrice": 4828, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5755, + "demand": 0, + "demandBracket": 1 + }, + { + "name": "opal", + "meanPrice": 135284, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 525075, + "demand": 1, + "demandBracket": 3 + }, + { + "name": "ophiuchiexinoartefacts", + "meanPrice": 10969, + "buyPrice": 4072, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4071, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "orrerianviciousbrew", + "meanPrice": 8342, + "buyPrice": 1146, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1145, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "osmium", + "meanPrice": 45198, + "buyPrice": 23482, + "stock": 0, + "stockBracket": 0, + "sellPrice": 23480, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "p_particulatesample", + "meanPrice": 45525, + "buyPrice": 32061, + "stock": 0, + "stockBracket": 0, + "sellPrice": 32059, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "painite", + "meanPrice": 53016, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 192955, + "demand": 4, + "demandBracket": 3 + }, + { + "name": "palladium", + "meanPrice": 50639, + "buyPrice": 47901, + "stock": 2, + "stockBracket": 1, + "sellPrice": 47360, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "pantaaprayersticks", + "meanPrice": 9177, + "buyPrice": 2043, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2042, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "performanceenhancers", + "meanPrice": 6790, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6907, + "demand": 40, + "demandBracket": 1 + }, + { + "name": "personalgifts", + "meanPrice": 16535, + "buyPrice": 10000, + "stock": 0, + "stockBracket": 0, + "sellPrice": 9999, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "pesticides", + "meanPrice": 437, + "buyPrice": 82, + "stock": 0, + "stockBracket": 0, + "sellPrice": 81, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "platinum", + "meanPrice": 58263, + "buyPrice": 39557, + "stock": 0, + "stockBracket": 0, + "sellPrice": 39555, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "platinumaloy", + "meanPrice": 18333, + "buyPrice": 12009, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12008, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "polymers", + "meanPrice": 376, + "buyPrice": 2614, + "stock": 272, + "stockBracket": 1, + "sellPrice": 1960, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "powerconverter", + "meanPrice": 1433, + "buyPrice": 707, + "stock": 0, + "stockBracket": 0, + "sellPrice": 706, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "powergenerators", + "meanPrice": 2466, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3475, + "demand": 613, + "demandBracket": 3 + }, + { + "name": "powergridassembly", + "meanPrice": 2659, + "buyPrice": 1543, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "powertransferconduits", + "meanPrice": 2212, + "buyPrice": 1254, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1253, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "praseodymium", + "meanPrice": 8620, + "buyPrice": 6708, + "stock": 0, + "stockBracket": 0, + "sellPrice": 6707, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "preciousgems", + "meanPrice": 160280, + "buyPrice": 138850, + "stock": 0, + "stockBracket": 0, + "sellPrice": 138843, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "progenitorcells", + "meanPrice": 6752, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7529, + "demand": 6, + "demandBracket": 3 + }, + { + "name": "pyrophyllite", + "meanPrice": 11538, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13777, + "demand": 341, + "demandBracket": 3 + }, + { + "name": "radiationbaffle", + "meanPrice": 1787, + "buyPrice": 935, + "stock": 0, + "stockBracket": 0, + "sellPrice": 934, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rajukrustoves", + "meanPrice": 8378, + "buyPrice": 2346, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2345, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rapabaosnakeskins", + "meanPrice": 8285, + "buyPrice": 1726, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1725, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "reactivearmour", + "meanPrice": 2224, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2669, + "demand": 150, + "demandBracket": 3 + }, + { + "name": "reinforcedmountingplate", + "meanPrice": 2454, + "buyPrice": 1446, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1445, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "resonatingseparators", + "meanPrice": 5937, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7158, + "demand": 491, + "demandBracket": 2 + }, + { + "name": "rhodplumsite", + "meanPrice": 176839, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 275688, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "robotics", + "meanPrice": 2020, + "buyPrice": 1447, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1446, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rockforthfertiliser", + "meanPrice": 9, + "buyPrice": 6, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rusanioldsmokey", + "meanPrice": 11994, + "buyPrice": 5179, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5178, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "rutile", + "meanPrice": 2083, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 11056, + "demand": 1306, + "demandBracket": 3 + }, + { + "name": "s6_tissuesample_cells", + "meanPrice": 7210, + "buyPrice": 4175, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4174, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s6_tissuesample_coenosarc", + "meanPrice": 51920, + "buyPrice": 37090, + "stock": 0, + "stockBracket": 0, + "sellPrice": 37088, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s6_tissuesample_mesoglea", + "meanPrice": 27009, + "buyPrice": 18488, + "stock": 0, + "stockBracket": 0, + "sellPrice": 18487, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s9_tissuesample_shell", + "meanPrice": 12546, + "buyPrice": 7890, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7889, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s_tissuesample_cells", + "meanPrice": 4780, + "buyPrice": 2532, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2531, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s_tissuesample_core", + "meanPrice": 28819, + "buyPrice": 19777, + "stock": 0, + "stockBracket": 0, + "sellPrice": 19776, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "s_tissuesample_surface", + "meanPrice": 13361, + "buyPrice": 8438, + "stock": 0, + "stockBracket": 0, + "sellPrice": 8437, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "samarium", + "meanPrice": 25852, + "buyPrice": 31195, + "stock": 0, + "stockBracket": 0, + "sellPrice": 31193, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "sanumameat", + "meanPrice": 8504, + "buyPrice": 1319, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1318, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "sap8corecontainer", + "meanPrice": 67593, + "buyPrice": 49112, + "stock": 0, + "stockBracket": 0, + "sellPrice": 49109, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "saxonwine", + "meanPrice": 8983, + "buyPrice": 1863, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1862, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "scientificresearch", + "meanPrice": 20151, + "buyPrice": 13394, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13393, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "scientificsamples", + "meanPrice": 7955, + "buyPrice": 10878, + "stock": 0, + "stockBracket": 0, + "sellPrice": 10877, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "scrap", + "meanPrice": 300, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 625, + "demand": 182, + "demandBracket": 3 + }, + { + "name": "semiconductors", + "meanPrice": 1136, + "buyPrice": 1415, + "stock": 42, + "stockBracket": 1, + "sellPrice": 1355, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "serendibite", + "meanPrice": 172711, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 560027, + "demand": 2, + "demandBracket": 3 + }, + { + "name": "shanscharisorchid", + "meanPrice": 9043, + "buyPrice": 1914, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1913, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "silver", + "meanPrice": 37223, + "buyPrice": 34289, + "stock": 8, + "stockBracket": 1, + "sellPrice": 33471, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "skimercomponents", + "meanPrice": 1119, + "buyPrice": 530, + "stock": 0, + "stockBracket": 0, + "sellPrice": 529, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "smallexplorationdatacash", + "meanPrice": 25005, + "buyPrice": 40615, + "stock": 0, + "stockBracket": 0, + "sellPrice": 40612, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "soontillrelics", + "meanPrice": 19885, + "buyPrice": 13602, + "stock": 0, + "stockBracket": 0, + "sellPrice": 13601, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "sothiscrystallinegold", + "meanPrice": 19112, + "buyPrice": 12751, + "stock": 0, + "stockBracket": 0, + "sellPrice": 12750, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "spacepioneerrelics", + "meanPrice": 9780, + "buyPrice": 5967, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5966, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "structuralregulators", + "meanPrice": 1932, + "buyPrice": 1186, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1185, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "superconductors", + "meanPrice": 6679, + "buyPrice": 6809, + "stock": 14, + "stockBracket": 1, + "sellPrice": 6729, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "surfacestabilisers", + "meanPrice": 726, + "buyPrice": 1656, + "stock": 67, + "stockBracket": 1, + "sellPrice": 1550, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "survivalequipment", + "meanPrice": 684, + "buyPrice": 533, + "stock": 0, + "stockBracket": 0, + "sellPrice": 532, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "syntheticfabrics", + "meanPrice": 416, + "buyPrice": 1705, + "stock": 197, + "stockBracket": 1, + "sellPrice": 1435, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "syntheticmeat", + "meanPrice": 440, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 872, + "demand": 496, + "demandBracket": 3 + }, + { + "name": "syntheticreagents", + "meanPrice": 6651, + "buyPrice": 4463, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4462, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "taaffeite", + "meanPrice": 52089, + "buyPrice": 51665, + "stock": 0, + "stockBracket": 0, + "sellPrice": 51662, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tacticaldata", + "meanPrice": 15622, + "buyPrice": 2170, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2169, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tanmarktranquiltea", + "meanPrice": 9177, + "buyPrice": 2041, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2040, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tantalum", + "meanPrice": 4044, + "buyPrice": 4099, + "stock": 2, + "stockBracket": 1, + "sellPrice": 3999, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "taurichimes", + "meanPrice": 8549, + "buyPrice": 1374, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1373, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tea", + "meanPrice": 1696, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1923, + "demand": 43, + "demandBracket": 2 + }, + { + "name": "telemetrysuite", + "meanPrice": 3214, + "buyPrice": 1543, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "terrainenrichmentsystems", + "meanPrice": 4928, + "buyPrice": 3005, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3004, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thallium", + "meanPrice": 3745, + "buyPrice": 2539, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2538, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidheart", + "meanPrice": 140275, + "buyPrice": 104381, + "stock": 0, + "stockBracket": 0, + "sellPrice": 104375, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidscouttissuesample", + "meanPrice": 23731, + "buyPrice": 15982, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15981, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidtissuesampletype1", + "meanPrice": 63272, + "buyPrice": 45421, + "stock": 0, + "stockBracket": 0, + "sellPrice": 45418, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidtissuesampletype2", + "meanPrice": 72212, + "buyPrice": 52545, + "stock": 0, + "stockBracket": 0, + "sellPrice": 52542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidtissuesampletype3", + "meanPrice": 82435, + "buyPrice": 60149, + "stock": 0, + "stockBracket": 0, + "sellPrice": 60145, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thargoidtissuesampletype4", + "meanPrice": 107495, + "buyPrice": 79648, + "stock": 0, + "stockBracket": 0, + "sellPrice": 79644, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thehuttonmug", + "meanPrice": 7986, + "buyPrice": 2751, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2750, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thermalcoolingunits", + "meanPrice": 3760, + "buyPrice": 2516, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2515, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thorium", + "meanPrice": 11317, + "buyPrice": 7969, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7968, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "thrutiscream", + "meanPrice": 8550, + "buyPrice": 1538, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1537, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tiegfriessynthsilk", + "meanPrice": 8478, + "buyPrice": 1263, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1262, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "timecapsule", + "meanPrice": 5364, + "buyPrice": 2926, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2925, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tiolcewaste2pasteunits", + "meanPrice": 8710, + "buyPrice": 1648, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1647, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "titanium", + "meanPrice": 1208, + "buyPrice": 1377, + "stock": 122, + "stockBracket": 2, + "sellPrice": 1319, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "tobacco", + "meanPrice": 5325, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5568, + "demand": 398, + "demandBracket": 3 + }, + { + "name": "toxandjivirocide", + "meanPrice": 8275, + "buyPrice": 1678, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1677, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "transgeniconionhead", + "meanPrice": 8472, + "buyPrice": 1483, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1482, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "tritium", + "meanPrice": 51707, + "buyPrice": 56235, + "stock": 2, + "stockBracket": 1, + "sellPrice": 55627, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "unknownartifact", + "meanPrice": 306252, + "buyPrice": 234627, + "stock": 0, + "stockBracket": 0, + "sellPrice": 234615, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknownartifact2", + "meanPrice": 443535, + "buyPrice": 344560, + "stock": 0, + "stockBracket": 0, + "sellPrice": 344542, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknownartifact3", + "meanPrice": 51920, + "buyPrice": 37090, + "stock": 0, + "stockBracket": 0, + "sellPrice": 37088, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknownbiologicalmatter", + "meanPrice": 51920, + "buyPrice": 37090, + "stock": 0, + "stockBracket": 0, + "sellPrice": 37088, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknownresin", + "meanPrice": 32825, + "buyPrice": 22634, + "stock": 0, + "stockBracket": 0, + "sellPrice": 22632, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unknowntechnologysamples", + "meanPrice": 39930, + "buyPrice": 28012, + "stock": 0, + "stockBracket": 0, + "sellPrice": 28010, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "unstabledatacore", + "meanPrice": 4516, + "buyPrice": 2371, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2370, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "uraninite", + "meanPrice": 2957, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4202, + "demand": 2899, + "demandBracket": 3 + }, + { + "name": "uranium", + "meanPrice": 2827, + "buyPrice": 3139, + "stock": 24, + "stockBracket": 1, + "sellPrice": 3060, + "demand": 1, + "demandBracket": 0 + }, + { + "name": "usscargorareartwork", + "meanPrice": 16807, + "buyPrice": 15150, + "stock": 0, + "stockBracket": 0, + "sellPrice": 15149, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "uszaiantreegrub", + "meanPrice": 8578, + "buyPrice": 1379, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1378, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "utgaroarmillenialeggs", + "meanPrice": 9163, + "buyPrice": 2217, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2216, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "uzumokulowgwings", + "meanPrice": 13845, + "buyPrice": 7233, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7232, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "vanayequirhinofur", + "meanPrice": 8331, + "buyPrice": 1660, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1659, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "vegaslimweed", + "meanPrice": 9588, + "buyPrice": 2518, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2517, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "vherculisbodyrub", + "meanPrice": 8010, + "buyPrice": 1730, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1729, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "vidavantianlace", + "meanPrice": 12615, + "buyPrice": 5861, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5860, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "volkhabbeedrones", + "meanPrice": 10198, + "buyPrice": 3849, + "stock": 0, + "stockBracket": 0, + "sellPrice": 3848, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "water", + "meanPrice": 278, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 599, + "demand": 336, + "demandBracket": 3 + }, + { + "name": "waterpurifiers", + "meanPrice": 484, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2101, + "demand": 1256, + "demandBracket": 3 + }, + { + "name": "watersofshintara", + "meanPrice": 13711, + "buyPrice": 7070, + "stock": 0, + "stockBracket": 0, + "sellPrice": 7069, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "wheemetewheatcakes", + "meanPrice": 8081, + "buyPrice": 1164, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1163, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "wine", + "meanPrice": 507, + "buyPrice": 0, + "stock": 0, + "stockBracket": 0, + "sellPrice": 411, + "demand": 0, + "demandBracket": 1 + }, + { + "name": "witchhaulkobebeef", + "meanPrice": 11085, + "buyPrice": 4313, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4312, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "wulpahyperboresystems", + "meanPrice": 8726, + "buyPrice": 2294, + "stock": 0, + "stockBracket": 0, + "sellPrice": 2293, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "wuthielokufroth", + "meanPrice": 8194, + "buyPrice": 1558, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1557, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "xihecompanions", + "meanPrice": 11058, + "buyPrice": 4277, + "stock": 0, + "stockBracket": 0, + "sellPrice": 4276, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "yasokondileaf", + "meanPrice": 12171, + "buyPrice": 5381, + "stock": 0, + "stockBracket": 0, + "sellPrice": 5380, + "demand": 0, + "demandBracket": 0 + }, + { + "name": "zeesszeantglue", + "meanPrice": 8161, + "buyPrice": 1089, + "stock": 0, + "stockBracket": 0, + "sellPrice": 1088, + "demand": 0, + "demandBracket": 0 + } + ] + }, + "header": { + "uploaderID": "Athanasius Testing", + "softwareName": "Athanasius Testing", + "softwareVersion": "v0.0.1" + } +} diff --git a/scripts/testing/gateway-responses/market.json-to-schema.py b/scripts/testing/gateway-responses/market.json-to-schema.py new file mode 100644 index 0000000..b484745 --- /dev/null +++ b/scripts/testing/gateway-responses/market.json-to-schema.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +import json +import re +import sys +from collections import OrderedDict + +if len(sys.argv) != 2: + print('