CardData* MtgJsonAllSetsData::createCardData( int multiverseId ) const { // Unfortunately this is a slow linear search. for( const std::string& setCode : mAllSetCodes ) { // In parse() this was vetted to be safe and yield an Array-type value. const Value& cardsValue = mDoc[setCode]["cards"]; // This is a linear search looking for the multiverse id. for( Value::ConstValueIterator iter = cardsValue.Begin(); iter != cardsValue.End(); ++iter ) { if( iter->HasMember("multiverseid") ) { const Value& multiverseIdValue = (*iter)["multiverseid"]; if( multiverseIdValue.IsInt() ) { int muid = multiverseIdValue.GetInt(); if( muid == multiverseId ) { mLogger->debug( "found muid ", muid ); return new MtgJsonCardData( setCode, *iter ); } } } } } mLogger->warn( "unable to find card multiverseId {}", multiverseId ); return nullptr; }
Value::ConstValueIterator MtgJsonAllSetsData::findCardValueByName( Value::ConstValueIterator first, Value::ConstValueIterator last, const std::string& name ) const { Value::ConstValueIterator iter = first; for( Value::ConstValueIterator iter = first; iter != last; ++iter ) { std::string nameStr( (*iter)["name"].GetString() ); if( StringUtil::icompare( nameStr, name ) ) { mLogger->debug( "found name {}", name ); return iter; } else if( iter->HasMember("names") ) { // Here we check if the card has multiple names, i.e. split // cards. If so, create a split card name and normalize the // name parameter and see if they match. std::string splitCardName = MtgJson::createSplitCardName( (*iter)["names"] ); std::string nameNormalized = MtgJson::normalizeSplitCardName( name ); if( StringUtil::icompare( nameNormalized, splitCardName ) ) { mLogger->debug( "found split name {}", name ); return iter; } } } return last; }
std::multimap<RarityType,std::string> MtgJsonAllSetsData::getCardPool( const std::string& code ) const { std::multimap<RarityType,std::string> rarityMap; if( mAllSetCodes.count(code) == 0 ) { mLogger->warn( "Unable to find set {}, returning empty card pool", code ); return rarityMap; } // In parse() this was vetted to be safe and yield an Array-type value. const Value& cardsValue = mDoc[code]["cards"]; mLogger->debug( "{:-^40}", "assembling card pool" ); for( Value::ConstValueIterator iter = cardsValue.Begin(); iter != cardsValue.End(); ++iter ) { Value::ConstMemberIterator nameIter = iter->FindMember( "name" ); Value::ConstMemberIterator rarityIter = iter->FindMember( "rarity" ); if( nameIter != iter->MemberEnd() && nameIter->value.IsString() && rarityIter != iter->MemberEnd() && rarityIter->value.IsString() ) { std::string nameStr( nameIter->value.GetString() ); std::string rarityStr( rarityIter->value.GetString() ); mLogger->debug( "json: {} : {}", nameStr, rarityStr ); // Some cards have multiple entries (i.e. split/flip/double-sided), // so make sure they are only represented once. Done by skipping // over cards whose name doesn't match the first entry of the // 'names' array (if it exists). if( iter->HasMember("names") ) { const Value& names = (*iter)["names"]; if( names.IsArray() && !names.Empty() && (nameStr != names[0]) ) { continue; } // Modify the name for split cards. if( MtgJson::isSplitCard( *iter ) ) { nameStr = MtgJson::createSplitCardName( names ); } } // Some cards have variations with multiple entries that should // only be counted once. Done by checking if there are // variations and checking a card's number for a non-digit, // non-'a' ending. if( iter->HasMember("variations") && iter->HasMember("number") ) { const Value& numberValue = (*iter)["number"]; if( numberValue.IsString() ) { const std::string numberStr( numberValue.GetString() ); const char c = numberStr.back(); if( !std::isdigit( c ) && (c != 'a') ) { continue; } } } RarityType rarity = MtgJson::getRarityFromString( rarityStr ); if( rarity != RARITY_UNKNOWN ) rarityMap.insert( std::make_pair( rarity, nameStr ) ); else mLogger->warn( "Unknown rarity type {}, ignoring!", rarityStr ); } else { mLogger->notice( "card entry without name or rarity in set {}", code ); } } return rarityMap; }