Atoms Crowd  7.0.0
BehaviourModuleAttributeCache.h
1 #pragma once
2 // ===========================================================================
3 // Copyright (c) 2015 Toolchefs Ltd. All rights reserved.
4 //
5 // Use of this software is subject to the terms of the Toolchefs license
6 // agreement provided at the time of installation or download, or which
7 // otherwise accompanies this software in either electronic or hard copy form.
8 // ===========================================================================
9 
10 #include <Atoms/Globals.h>
11 #include <Atoms/GlobalNames.h>
12 #include <AtomsCore/Metadata/All.h>
13 #include <AtomsUtils/AtomsMath.h>
14 #include <Atoms/Agent.h>
15 #include <vector>
16 #include <functional>
17 #include <AtomsJIT/AtomsScriptLang.h>
18 #include <Atoms/AtomsScriptUtils.h>
19 #include <ToolchefsSTL/String.h>
20 
21 namespace Atoms
22 {
23 
24  template<typename T>
26  {
27  typedef T Type;
28  };
29 
30  template<>
31  struct AttributeCacheScriptType<std::string>
32  {
33  typedef ToolchefsSTL::String Type;
34  };
35 
37 
39  template <typename T>
41  {
42  public:
43 
44  typedef typename AttributeCacheScriptType<T>::Type InternalType;
45 
47  BehaviourModuleAttributeCache<T>():m_agentGroupWrapper(nullptr)
48  {
49  m_mode = -1;
50  m_seed = 0;
51  m_minValue = AtomsMath::numeric_limits<T>::min();
52  m_maxValue = AtomsMath::numeric_limits<T>::max();
53  m_listValue.clear();
54  m_agentGroup = nullptr;
55  }
56 
57  void fillOverrideList(const AtomsCore::MapMetadata& attributes, const std::string& attributeName)
58  {
59  auto listPtr = attributes.getTypedEntry<AtomsCore::TypedArrayMetadata<T>>(attributeName + ATOMS_BEHAVIOUR_OVERRIDE_LIST_SUFFIX);
60  if (listPtr)
61  {
62  m_listValue.clear();
63  for (auto v : listPtr->get())
64  m_listValue.push_back(v);
65  }
66  }
67 
70  const AtomsCore::MapMetadata& attributes, const std::string& attributeName,
71  const std::string& behaviourModuleName, class AgentGroup* agentGroup):
72  m_agentGroupWrapper(agentGroup)
73  {
74  m_mode = -1;
75  m_seed = 0;
76  m_minValue = AtomsMath::numeric_limits<T>::min();
77  m_maxValue = AtomsMath::numeric_limits<T>::max();
78  m_listValue.clear();
79  m_agentGroup = agentGroup;
80 
81  m_metadataName = behaviourModuleName + "@" + attributeName;
82 
83  auto attrPtr = attributes.getTypedEntry<AtomsCore::MetadataImpl<T>>(attributeName);
84  if (!attrPtr)
85  return;
86 
87  m_defaultValue = attrPtr->get();
88  m_overrideMap = attributes.getTypedEntry<AtomsCore::MapMetadata>(attributeName + "_override");
89 
90  auto modePtr = attributes.getTypedEntry<AtomsCore::MetadataImpl<int>>(attributeName + ATOMS_BEHAVIOUR_OVERRIDE_RANDOM_MODE_SUFFIX);
91  if (modePtr)
92  m_mode = modePtr->value();
93 
94  auto seedPtr = attributes.getTypedEntry<AtomsCore::MetadataImpl<int>>(attributeName + ATOMS_BEHAVIOUR_OVERRIDE_RANDOM_SEED_SUFFIX);
95  if (seedPtr)
96  m_seed = seedPtr->value();
97 
98  auto minValuePtr = attributes.getTypedEntry<AtomsCore::MetadataImpl<T>>(attributeName + ATOMS_BEHAVIOUR_OVERRIDE_MIN_VALUE_SUFFIX);
99  if (minValuePtr)
100  m_minValue = minValuePtr->value();
101 
102  auto maxValuePtr = attributes.getTypedEntry<AtomsCore::MetadataImpl<T>>(attributeName + ATOMS_BEHAVIOUR_OVERRIDE_MAX_VALUE_SUFFIX);
103  if (maxValuePtr)
104  m_maxValue = maxValuePtr->value();
105  /*
106  auto listPtr = attributes.getTypedEntry<AtomsCore::TypedArrayMetadata<T>>(attributeName + ATOMS_BEHAVIOUR_OVERRIDE_LIST_SUFFIX);
107  if (listPtr)
108  {
109  m_listValue.clear();
110  for (auto v : listPtr->get())
111  m_listValue.push_back(v);
112  }
113  */
114  fillOverrideList(attributes, attributeName);
115 
116  auto expressionMetaPtr = attributes.getTypedEntry<AtomsCore::StringMetadata>(attributeName + "_expression");
117  if (m_mode == 3 && expressionMetaPtr && !expressionMetaPtr->get().empty())
118  {
119  AtomsCore::MurmurHash3 hasher;
120  hasher.append(expressionMetaPtr->get());
122  if (baseType == AtomsCore::StringMetadata::staticBaseTypeStr())
123  {
124  baseType = "String";
125  }
126  std::string functionName = "__expression_" + behaviourModuleName + "__" + attributeName + "_" + hasher.string();
127  std::string expressionCode;
128  expressionCode += "#include <Atoms/AtomsScriptUtils.h>\n";
129  expressionCode += "using namespace AtomsScriptUtils;\n";
130  expressionCode += "using namespace AtomsMath;\n";
131  expressionCode += "using namespace AtomsUtils;\n";
132  expressionCode += "using namespace ToolchefsSTL;\n";
133  expressionCode += "void " + functionName + "(";
134  expressionCode += baseType + "& output";
135  expressionCode += ", const AgentWrapper& agent, const AgentGroupWrapper& agentGroup";
136  expressionCode += ", const "+ baseType +"& defaultValue";
137  expressionCode += "){\n";
138  expressionCode += expressionMetaPtr->get();
139  expressionCode += "\n }";
140 
141  auto& compiler = Atoms::AtomsScriptLang::instance();
142  if (!compiler.addCode(functionName, expressionCode))
143  {
144  AtomsUtils::Logger::error() << "Unable to compile expression for attribute " << attributeName << " in module " << behaviourModuleName;
145  }
146  else
147  {
148  m_script = compiler.lookup<void(InternalType&, const AtomsScriptUtils::AgentWrapper&, const AtomsScriptUtils::AgentGroupWrapper&, const InternalType&)>(functionName, functionName);
149  }
150  }
151  }
152 
154  const T getAttributeValue(const int groupId, const std::string &groupIdStr, class Agent* agent) const
155  {
156  if (agent)
157  {
158  const auto& agentMetadata = agent->metadata();
159  auto agentDataPtr = agentMetadata.getTypedEntry<AtomsCore::MetadataImpl<T>>(m_metadataName);
160  if (agentDataPtr)
161  {
162  return agentDataPtr->value();
163  }
164  }
165 
166  if (m_overrideMap)
167  {
168  auto dataPtr = m_overrideMap->getTypedEntry<AtomsCore::MetadataImpl<T>>(groupIdStr);
169  if (dataPtr)
170  return dataPtr->value();
171  }
172 
173  if (m_mode == -1)
174  return m_defaultValue;
175 
176  AtomsCore::Rand48 random;
177  random.init(m_seed + groupId);
178 
179  switch (m_mode)
180  {
181  case 0:
182  {
183  return m_defaultValue;
184  }
185  case 1:
186  {
187  return AtomsMath::RandomValue<T>::value(random, m_minValue, m_maxValue);
188  }
189  case 2:
190  {
191  if (m_listValue.size() > 0)
192  return m_listValue[random.nexti() % m_listValue.size()];
193  }
194  case 3:
195  if (m_script)
196  {
197  T outValue = m_defaultValue;
198  AtomsScriptUtils::AgentWrapper wrapper(agent);
199  m_script(outValue, wrapper, m_agentGroupWrapper, m_defaultValue);
200  return outValue;
201  }
202  return m_defaultValue;
203  }
204 
205  return m_defaultValue;
206  }
207 
209  inline const bool hasOverride(const std::string& groupId)
210  {
211  return m_overrideMap ? m_overrideMap->hasKey(groupId) : false;
212  }
213 
214  inline const T& defaultValue() const { return m_defaultValue; }
215 
216  private:
217  std::vector<T> m_listValue;
218  std::string m_metadataName;
219 
220 
221 
222  std::function<void(InternalType&, const AtomsScriptUtils::AgentWrapper&, const AtomsScriptUtils::AgentGroupWrapper&, const InternalType&)> m_script;
223 
224  T m_defaultValue;
225 
226  int m_mode;
227  int m_seed;
228  T m_minValue;
229  T m_maxValue;
230 
231  AtomsPtr<const AtomsCore::MapMetadata> m_overrideMap;
232 
233  class AgentGroup* m_agentGroup;
234  AtomsScriptUtils::AgentGroupWrapper m_agentGroupWrapper;
235  };
236 
237  template<> ATOMS_EXPORT const std::string BehaviourModuleAttributeCache<std::string>::getAttributeValue(const int groupId, const std::string& groupIdStr, class Agent* agent) const;
238  template<> ATOMS_EXPORT void BehaviourModuleAttributeCache<bool>::fillOverrideList(const AtomsCore::MapMetadata& attributes, const std::string& attributeName);
239 
240 }
Agent group.
Definition: AgentGroup.h:36
Agent.
Definition: Agent.h:44
AtomsCore::MapMetadata & metadata()
Gets the agent metadata map.
Definition: Agent.impl.h:32
Behaviour Module Attribute Cache.
Definition: BehaviourModuleAttributeCache.h:41
const bool hasOverride(const std::string &groupId)
check if there is any override for the specified groupId
Definition: BehaviourModuleAttributeCache.h:209
const T getAttributeValue(const int groupId, const std::string &groupIdStr, class Agent *agent) const
generates a random value
Definition: BehaviourModuleAttributeCache.h:154
MapMetadata class.
Definition: MapMetadata.h:24
AtomsPtr< T > getTypedEntry(const Key &key)
Get a typed entry.
Definition: MapMetadata.impl.h:4
Metadata template class.
Definition: MetadataImpl.h:158
T value() const
Get value.
Definition: MetadataImpl.impl.h:76
static std::string staticBaseTypeStr()
Class static base type string.
Definition: Hash.h:23
Metadata template class.
Definition: TypedArrayMetadata.h:160
Definition: AtomsMath.h:340
Definition: AtomsMath.h:196
Definition: AtomsScriptUtils.h:260
Definition: AtomsScriptUtils.h:125
static LogProxy error()
Get logger proxy error.
Definition: String.h:19
Atoms namespace.
Definition: Agent.h:29
Definition: BehaviourModuleAttributeCache.h:26