1 #include "MERCListingModel.h"
2 #include "JsonObject.h"
3 #include "Soldier_Control.h"
4 #include <set>
5 #include <string_theory/format>
6 #include <utility>
7 
MERCListingModel(uint8_t index_,uint8_t profileID_,uint8_t bioIndex_,uint32_t minTotalSpending_,uint32_t minDays_,std::vector<SpeckQuote> quotes_)8 MERCListingModel::MERCListingModel(uint8_t index_, uint8_t profileID_, uint8_t bioIndex_,
9 	uint32_t minTotalSpending_, uint32_t minDays_,
10 	std::vector<SpeckQuote> quotes_
11 	) : index(index_), profileID(profileID_), bioIndex(bioIndex_),
12 	    minTotalSpending(minTotalSpending_), minDays(minDays_),
13 	    quotes(std::move(quotes_)) {}
14 
isAvailableAtStart() const15 bool MERCListingModel::isAvailableAtStart() const
16 {
17 	return this->minDays == 0 && this->minTotalSpending == 0;
18 }
19 
getQuotesByType(SpeckQuoteType type) const20 std::vector<SpeckQuote> MERCListingModel::getQuotesByType(SpeckQuoteType type) const
21 {
22 	std::vector<SpeckQuote> filtered;
23 	for (auto q : quotes)
24 	{
25 		if (q->type == type) filtered.push_back(q);
26 	}
27 	return filtered;
28 }
29 
SpeckQuoteTypefromString(std::string s)30 static SpeckQuoteType SpeckQuoteTypefromString(std::string s)
31 {
32 	if (s == "ADVERTISE") return SpeckQuoteType::ADVERTISE;
33 	if (s == "MERC_DEAD") return SpeckQuoteType::MERC_DEAD;
34 	if (s == "CROSS_SELL") return SpeckQuoteType::CROSS_SELL;
35 
36 	throw std::runtime_error("unsupported quote type: " + s);
37 }
38 
deserialize(uint8_t index,const rapidjson::Value & json)39 MERCListingModel* MERCListingModel::deserialize(uint8_t index, const rapidjson::Value& json)
40 {
41 	std::vector<SpeckQuote> quotes;
42 	for (auto& elem : json["quotes"].GetArray())
43 	{
44 		JsonObjectReader r(elem);
45 		auto quote = std::make_shared<MERCSpeckQuote>(
46 			r.GetUInt("quoteID"),
47 			SpeckQuoteTypefromString(r.GetString("type")),
48 			static_cast<uint8_t>(r.getOptionalInt("profileID"))
49 		);
50 		quotes.push_back(quote);
51 	}
52 
53 	JsonObjectReader r(json);
54 	return new MERCListingModel(
55 		index,
56 		r.GetUInt("profileID"),
57 		r.GetUInt("bioIndex"),
58 		r.getOptionalInt("minTotalSpending"),
59 		r.getOptionalInt("minDays"),
60 		quotes
61 	);
62 
63 }
64 
validateData(const std::vector<const MERCListingModel * > & models)65 void MERCListingModel::validateData(const std::vector<const MERCListingModel*>& models)
66 {
67 	std::set<uint8_t> uniqueProfileIDs;
68 	for (auto m : models)
69 	{
70 		if (m->profileID == 0 || m->profileID >= NO_PROFILE)
71 		{
72 			ST::string err = ST::format("Invalid profileID '{}'", m->profileID);
73 			throw std::runtime_error(err.to_std_string());
74 		}
75 
76 		// Check if we have duplicates
77 		if (uniqueProfileIDs.find(m->profileID) != uniqueProfileIDs.end())
78 		{
79 			ST::string err = ST::format("profileID {} has been listed more than once", m->profileID);
80 			throw std::runtime_error(err.to_std_string());
81 		}
82 		uniqueProfileIDs.insert(m->profileID);
83 	}
84 
85 	for (auto m : models)
86 	{
87 		for (const auto& quote : m->getQuotesByType(SpeckQuoteType::CROSS_SELL))
88 		{
89 			// Check if related merc is set
90 			if (!quote->relatedMercID)
91 			{
92 				ST::string err = ST::format("No related merc ID set for a CROSS_SELL quote ({})", m->profileID);
93 				throw std::runtime_error(err.to_std_string());
94 			}
95 		}
96 	}
97 }