35 : m_marketGroups(nullptr),
50 sLog.Warning(
" MarketMgr",
"Market Manager has been closed." );
60 sLog.Blue(
" MarketMgr",
"Market Manager Initialized.");
75 sLog.Cyan(
" MarketMgr",
"Market Manager Updates Price History every %u hours.",
sConfig.market.HistoryUpdateTime);
116 " (regionID, typeID, historyDate, lowPrice, highPrice, avgPrice, volume, orders)"
125 " COUNT(transactionID)"
126 " FROM mktTransactions"
127 " WHERE transactionType=%u AND transactionDate < %li",
133 if (
sConfig.market.DeleteOldTransactions)
134 sDatabase.RunQuery(err,
"DELETE FROM mktTransactions WHERE transactionDate < %li", (cutoff_time -
EvE::Time::Year));
149 PyRep* result(
nullptr);
150 std::string method_name (
"GetNewHistory_");
151 method_name += std::to_string(regionID);
153 method_name += std::to_string(typeID);
162 "SELECT historyDate, lowPrice, highPrice, avgPrice, volume, orders"
164 " WHERE regionID=%u AND typeID=%u"
165 " AND historyDate > %li LIMIT %u",
171 _log(MARKET__DB_TRACE,
"MarketMgr::GetNewPriceHistory() - Fetched %u buy orders for type %u in region %u from mktTransactions", res.
GetRowCount(), typeID, regionID);
174 if (result ==
nullptr) {
175 _log(MARKET__DB_ERROR,
"Failed to load cache, generating empty contents.");
186 result->
Dump(MARKET__DB_TRACE,
" ");
191 PyRep* result(
nullptr);
192 std::string method_name (
"GetOldHistory_");
193 method_name += std::to_string(regionID);
195 method_name += std::to_string(typeID);
204 "SELECT historyDate, lowPrice, highPrice, avgPrice, volume, orders"
205 " FROM mktHistory WHERE regionID=%u AND typeID=%u"
206 " AND historyDate > %li AND historyDate < %li LIMIT %u",
212 _log(MARKET__DB_TRACE,
"MarketMgr::GetOldPriceHistory() - Fetched %u orders for type %u in region %u from mktHistory", res.
GetRowCount(), typeID, regionID);
215 if (result ==
nullptr) {
216 _log(MARKET__DB_ERROR,
"Failed to load cache, generating empty contents.");
227 result->
Dump(MARKET__DB_TRACE,
" ");
232 if (pClient ==
nullptr)
234 Notify_OnOwnOrderChanged ooc;
235 if (order !=
nullptr) {
246 ooc.reason =
"Modify";
249 ooc.reason =
"Expiry";
266 std::string method_name (
"GetOrders_");
267 method_name += std::to_string(regionID);
269 method_name += std::to_string(typeID);
307 _log(MARKET__ERROR,
"ExecuteBuyOrder - Failed to get order info for #%u.", orderID);
316 bool isPlayer(
false), isCorp(
false), isTrader(
false);
320 }
else if (oInfo.
ownerID == 1) {
328 _log(MARKET__WARNING,
"ExecuteBuyOrder - ownerID %u not corp, not char, not system, not joe.", oInfo.
ownerID);
330 seller->
SendNotifyMsg (
"Your order cannot be processed at this time, please try again later.");
336 if (iRef->
quantity() == args.quantity) {
343 }
else if (isTrader) {
347 }
else if (iRef->
quantity() > args.quantity) {
356 if (siRef.
get() ==
nullptr) {
357 _log(MARKET__ERROR,
"ExecuteBuyOrder - Failed to split %u %s.", siRef->
itemID(), siRef->
name());
375 }
else if (isTrader) {
380 uint32 qtySold(args.quantity);
391 args.quantity -= qtySold;
395 float money = args.price * qtySold;
396 std::string reason =
"DESC: Buying items in ";
397 reason +=
stDataMgr.GetStationName(args.stationID).c_str();
398 uint32 sellerWalletOwnerID = 0;
416 _log(MARKET__DEBUG,
"ExecuteBuyOrder - Seller is Corp: Price: %.2f, Tax: %.2f", money, tax);
419 _log(MARKET__DEBUG,
"ExecuteBuyOrder - Seller is Player: Price: %.2f, Tax: %.2f", money, tax);
427 reason +=
"DESC: Selling items in ";
428 reason +=
stDataMgr.GetStationName(args.stationID).c_str();
430 if (isPlayer or isCorp) {
448 data.
isCorp = args.useCorp;
451 data.
price = args.price;
455 data.
typeID = args.typeID;
458 _log(MARKET__ERROR,
"ExecuteBuyOrder - Failed to record sale side of transaction.");
461 if (isPlayer or isCorp) {
467 _log(MARKET__ERROR,
"ExecuteBuyOrder - Failed to record buy side of transaction.");
473 _log(MARKET__TRACE,
"ExecuteBuyOrder - Partially satisfied order #%u, altering quantity to %u.", orderID, newQty);
475 _log(MARKET__ERROR,
"ExecuteBuyOrder - Failed to alter quantity of order #%u.", orderID);
479 if (isPlayer or isCorp)
485 _log(MARKET__TRACE,
"ExecuteBuyOrder - Satisfied order #%u, deleting.", orderID);
488 _log(MARKET__ERROR,
"ExecuteBuyOrder - Failed to delete order #%u.", orderID);
492 if (isPlayer or isCorp)
500 _log(MARKET__ERROR,
"ExecuteSellOrder - Failed to get info about sell order %u.", orderID);
504 bool orderConsumed(
false);
507 if (args.quantity == oInfo.
quantity)
508 orderConsumed =
true;
514 float money = args.price * args.quantity;
516 std::string reason =
"DESC: Buying market items in ";
517 reason +=
stDataMgr.GetStationName(args.stationID).c_str();
522 uint32 sellerCharacterID = 0;
527 sellerCharacterID = oInfo.
ownerID;
530 uint8 accountingLevel(0);
531 uint8 taxEvasionLevel(0);
534 if (pSeller ==
nullptr) {
548 if (iRef.
get() ==
nullptr)
562 _log(MARKET__TRACE,
"ExecuteSellOrder - satisfied order #%u, deleting.", orderID);
565 _log(MARKET__ERROR,
"ExecuteSellOrder - Failed to delete order #%u.", orderID);
572 _log(MARKET__TRACE,
"ExecuteSellOrder - Partially satisfied order #%u, altering quantity to %u.", orderID, newQty);
574 _log(MARKET__ERROR,
"ExecuteSellOrder - Failed to alter quantity of order #%u.", orderID);
586 data.
isCorp = args.useCorp;
589 data.
price = args.price;
593 data.
typeID = args.typeID;
596 _log(MARKET__ERROR,
"ExecuteSellOrder - Failed to record buy side of transaction.");
604 _log(MARKET__ERROR,
"ExecuteSellOrder - Failed to record sell side of transaction.");
637 std::map<uint16, Market::matlData> mineralMap;
639 sDataMgr.GetMineralData(mineralMap);
648 std::map<uint16, Market::matlData> materialMap;
650 sDataMgr.GetComponentData(materialMap);
653 sDataMgr.GetCompoundData(materialMap);
656 sDataMgr.GetMiscCommodityData(materialMap);
659 sDataMgr.GetSalvageData(materialMap);
662 sDataMgr.GetPIResourceData(materialMap);
665 sDataMgr.GetPICommodityData(materialMap);
671 data.
name =
"Codebreaker I";
672 materialMap[22175] = data;
679 materialMap.insert(mineralMap.begin(), mineralMap.end());
684 std::map<uint16, Inv::TypeData> itemMap;
692 std::map<uint16, std::vector<EvERam::RamMaterials>> itemMatMap;
694 std::map<uint16, Inv::TypeData>::iterator itemItr = itemMap.begin();
695 for (; itemItr != itemMap.end(); ++itemItr) {
697 sDataMgr.GetType(itemItr->first, itemItr->second);
700 std::vector<EvERam::RamMaterials> matVec;
702 sDataMgr.GetRamMaterials(itemItr->first, matVec);
703 itemMatMap[itemItr->first] = matVec;
714 std::map<uint16, Inv::TypeData> missingItemMap;
715 missingItemMap.clear();
716 std::map<uint16, Market::matlData>::iterator materialItr = materialMap.begin();
717 std::map<uint16, std::vector<EvERam::RamMaterials>>::iterator itemMatItr = itemMatMap.end();
718 for (itemItr = itemMap.begin(); itemItr != itemMap.end(); ++itemItr) {
719 itemMatItr = itemMatMap.find(itemItr->first);
720 if (itemMatItr == itemMatMap.end())
724 current = itemItr->second.basePrice;
726 itemItr->second.basePrice = 0.0;
728 for (
auto cur2 : itemMatItr->second) {
729 materialItr = materialMap.find(cur2.materialTypeID);
730 if (materialItr == materialMap.end()) {
731 sLog.Error(
" SetBasePrice",
"resource %u for %s(%u) not found in materialMap", \
732 cur2.materialTypeID, itemItr->second.name.c_str(), itemItr->first);
737 itemItr->second.basePrice += (materialItr->second.price * cur2.quantity);
744 if (
sDataMgr.GetBpDataForItem(itemItr->first, bpData)) {
745 itemItr->second.basePrice += 1000 + (2500 * (bpData.
productionTime / 3600));
748 mLevel = itemItr->second.metaLvl;
750 sDataMgr.GetGroup(itemItr->second.groupID, gData);
754 switch (gData.
catID) {
756 itemItr->second.basePrice /= itemItr->second.portionSize;
760 itemItr->second.basePrice *= 2;
763 itemItr->second.basePrice *= 2.5;
766 itemItr->second.basePrice *= 3.5;
776 itemItr->second.basePrice *= mLevel;
777 itemItr->second.basePrice /= itemItr->second.portionSize;
781 itemItr->second.basePrice *= mLevel;
784 if (itemItr->first < 28000)
785 itemItr->second.basePrice /= itemItr->second.portionSize;
788 itemItr->second.basePrice *= 2;
805 itemItr->second.basePrice *= (mLevel + 1);
808 itemItr->second.basePrice *= (mLevel + 10);
816 itemItr->second.basePrice *= mLevel;
823 itemItr->second.basePrice *= 2.1;
826 itemItr->second.basePrice *= 1.2;
840 itemItr->second.basePrice *= 1.1;
847 itemItr->second.basePrice *= 1.5;
861 itemItr->second.basePrice *= 0.6;
864 itemItr->second.basePrice *= 0.35;
867 itemItr->second.basePrice *= 3;
871 itemItr->second.basePrice *= 1000;
877 itemItr->second.basePrice *= 100;
881 if (itemItr->second.basePrice < 0.01) {
882 sLog.Error(
" SetBasePrice",
"Calculated price for %s(%u) is 0", \
883 itemItr->second.name.c_str(), itemItr->first);
892 if (missingItemMap.empty()) {
898 sLog.Error(
" SetBasePrice",
"Missing material. run again.");
907 std::map<uint16, Market::matlData> mineralMap;
909 sDataMgr.GetMineralData(mineralMap);
934 sLog.Warning(
" SetBasePrice",
"Getting types.");
935 std::map<uint16, Inv::TypeData> types;
937 sLog.Green(
" SetBasePrice",
"GetTypes returned %u items. Getting price avg.", types.size());
942 sLog.Green(
" SetBasePrice",
"Got Avg prices. updating items.");
944 sLog.Cyan(
" SetBasePrice",
"Completed.");
#define IsTraderJoe(itemID)
#define sConfig
A macro for easier access to the singleton.
virtual InventoryItemRef Split(int32 qty=0, bool notify=true, bool silent=false)
void Donate(uint32 new_owner=ownerSystem, uint32 new_location=locTemp, EVEItemFlags new_flag=flagNone, bool notify=true)
void SendNotification(const PyAddress &dest, EVENotificationStream ¬i, bool seq=true)
bool GetOrderInfo(uint32 orderID, Market::OrderInfo &oInfo)
#define _log(type, fmt,...)
PyObjectEx * DBResultToCRowset(DBQueryResult &result)
void SystemStartup(SystemData &data)
int64 GetCorpRole() const
PyRep * GetMarketGroups()
static void GetMineralPrices(std::map< uint16, Market::matlData > &data)
void UpdatePriceHistory()
int32 GetCharacterID() const
PyRep * GetOldPriceHistory(uint32 regionID, uint32 typeID)
int32 GetCorporationID() const
static void UpdateInvPrice(std::map< uint16, Inv::TypeData > &data)
PyRep * GetNewPriceHistory(uint32 regionID, uint32 typeID)
UserError & AddFormatValue(const char *name, PyRep *value)
Fluent version of the protected AddKeyword, allows for adding a keyword to the exception.
void SendNotifyMsg(const char *fmt,...)
CharacterRef GetChar() const
void Dump(FILE *into, const char *pfx) const
Dumps object to file.
void InvalidateOrdersCache(uint32 regionID, uint32 typeID)
#define is_log_enabled(type)
#define sLog
Evaluates to a NewLog instance.
void SendOnOwnOrderChanged(Client *pClient, uint32 orderID, uint8 action, bool isCorp=false, PyRep *order=nullptr)
const char * c_str() const
PyRep * GetOrderRow(uint32 orderID)
static uint8 GetSkillLevel(uint32 charID, uint16 skillTypeID)
static void TranserFunds(uint32 fromID, uint32 toID, double amount, std::string reason="", uint8 entryTypeID=Journal::EntryType::Undefined, uint32 referenceID=0, uint16 fromKey=Account::KeyType::Cash, uint16 toKey=Account::KeyType::Cash, Client *pClient=nullptr)
bool AlterQuantity(int32 qty, bool notify=false)
int Initialize(PyServiceMgr *pManager)
static void GetCruPriceAvg(std::map< uint16, Inv::TypeData > &data)
#define IsPlayerCorp(itemID)
bool RecordTransaction(Market::TxData &data)
static void SetUpdateTime(int64 setTime)
#define IsCharacterID(itemID)
Python object "ccp_exceptions.UserError".
void InvalidateCache(const PyRep *objectID)
void GiveCache(const PyRep *objectID, PyRep **contents)
void ExecuteSellOrder(Client *buyer, uint32 orderID, Call_PlaceCharOrder &args)
static void GetMaterialPrices(std::map< uint16, Market::matlData > &data)
float SalesTax(float baseSalesTax, uint8 accountingLvl=0, uint8 taxEvasionLvl=0)
ObjCacheService * cache_service
static void GetManufacturedItems(std::map< uint16, Inv::TypeData > &data)
int8 GetSkillLevel(uint16 skillTypeID, bool zeroForNotInjected=true) const
bool AlterOrderQuantity(uint32 orderID, uint32 new_qty)
bool DeleteOrder(uint32 orderID)
void SystemShutdown(SystemData &data)
bool ExecuteBuyOrder(Client *seller, uint32 orderID, InventoryItemRef iRef, Call_PlaceCharOrder &args, uint16 accountKey=Account::KeyType::Cash)
PyObject * MakeObjectCachedMethodCallResult(const PyRep *objectID, const char *versionCheck="run")
static void UpdateMktPrice(std::map< uint16, Market::matlData > &data)
bool IsCacheLoaded(const PyRep *objectID) const
static int64 GetUpdateTime()
void UpdateMineralPrice()