1 #include "butchery_requirements.h"
2
3 #include <cstddef>
4 #include <functional>
5 #include <iterator>
6 #include <set>
7 #include <string>
8
9 #include "activity_handlers.h"
10 #include "creature.h"
11 #include "debug.h"
12 #include "enum_conversions.h"
13 #include "generic_factory.h"
14 #include "item.h"
15 #include "json.h"
16 #include "requirements.h"
17
18 namespace
19 {
20 generic_factory<butchery_requirements> butchery_req_factory( "butchery_requirements" );
21 } // namespace
22
23 template<>
obj() const24 const butchery_requirements &string_id<butchery_requirements>::obj() const
25 {
26 return butchery_req_factory.obj( *this );
27 }
28
29 template<>
is_valid() const30 bool string_id<butchery_requirements>::is_valid() const
31 {
32 return butchery_req_factory.is_valid( *this );
33 }
34
load_butchery_req(const JsonObject & jo,const std::string & src)35 void butchery_requirements::load_butchery_req( const JsonObject &jo, const std::string &src )
36 {
37 butchery_req_factory.load( jo, src );
38 }
39
get_all()40 const std::vector<butchery_requirements> &butchery_requirements::get_all()
41 {
42 return butchery_req_factory.get_all();
43 }
44
reset_all()45 void butchery_requirements::reset_all()
46 {
47 butchery_req_factory.reset();
48 }
49
is_valid() const50 bool butchery_requirements::is_valid() const
51 {
52 return butchery_req_factory.is_valid( this->id );
53 }
54
load(const JsonObject & jo,const std::string &)55 void butchery_requirements::load( const JsonObject &jo, const std::string & )
56 {
57 mandatory( jo, was_loaded, "id", id );
58
59 for( const JsonMember member : jo.get_object( "requirements" ) ) {
60 float modifier = std::stof( member.name() );
61 requirements.emplace( modifier, std::map<creature_size, std::map<butcher_type, requirement_id>> {} );
62
63 int critter_size = 1;
64 for( JsonObject butcher_jo : member.get_array() ) {
65 if( critter_size == creature_size::num_sizes ) {
66 debugmsg( "ERROR: %s has too many creature sizes. must have exactly %d",
67 id.c_str(), creature_size::num_sizes - 1 );
68 break;
69 }
70 requirements[modifier].emplace( static_cast<creature_size>( critter_size ),
71 std::map<butcher_type, requirement_id> {} );
72
73 for( int i_butchery_type = 0; i_butchery_type < static_cast<int>( butcher_type::NUM_TYPES );
74 i_butchery_type++ ) {
75 butcher_type converted = static_cast<butcher_type>( i_butchery_type );
76 requirements[modifier][static_cast<creature_size>( critter_size )][converted] =
77 requirement_id( butcher_jo.get_string( io::enum_to_string( converted ) ) );
78 }
79
80 critter_size++;
81 }
82 }
83 }
84
check_consistency()85 void butchery_requirements::check_consistency()
86 {
87 for( const butchery_requirements &req : get_all() ) {
88 for( const auto &size_req : req.requirements ) {
89 if( size_req.second.size() != static_cast<size_t>( creature_size::num_sizes - 1 ) ) {
90 debugmsg( "ERROR: %s needs exactly %d entries to cover all creature sizes",
91 req.id.c_str(), static_cast<int>( creature_size::num_sizes ) - 1 );
92 }
93 for( const auto &butcher_req : size_req.second ) {
94 if( butcher_req.second.size() != static_cast<size_t>( butcher_type::NUM_TYPES ) ) {
95 debugmsg( "ERROR: %s needs exactly %d entries to cover all butchery types",
96 req.id.c_str(), static_cast<int>( butcher_type::NUM_TYPES ) );
97 }
98 }
99 }
100 }
101 }
102
get_fastest_requirements(const read_only_visitable & crafting_inv,creature_size size,butcher_type butcher) const103 std::pair<float, requirement_id> butchery_requirements::get_fastest_requirements(
104 const read_only_visitable &crafting_inv, creature_size size, butcher_type butcher ) const
105 {
106 for( const std::pair<const float, std::map<creature_size, std::map<butcher_type, requirement_id>>>
107 &riter : requirements ) {
108 if( riter.second.at( size ).at( butcher )->can_make_with_inventory( crafting_inv,
109 is_crafting_component ) ) {
110 return std::make_pair( riter.first, riter.second.at( size ).at( butcher ) );
111 }
112 }
113 // we didn't find anything we could "craft", so return the requirement that's the fastest
114 const auto first = requirements.rbegin();
115 return std::make_pair( first->first, first->second.at( size ).at( butcher ) );
116 }
117