Agent_base.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2006-2008 by Antonello Lobianco                         *
00003  *   http://regmas.org                                                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 3 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include "Agent_base.h"
00021 #include "ThreadManager.h"
00022 #include "Scheduler.h"
00023 #include "Output.h"
00024 #include "Agent_space.h"
00025 #include "Pixel.h"
00026 #include "Manager_base.h"
00027 
00032 Agent_base::Agent_base(ThreadManager* MTHREAD_h, Manager_base* manager_h):OPT(MTHREAD_h, this){
00033     MTHREAD=MTHREAD_h;
00034     liquidity = 0;
00035     netProductionProfit = 0;
00036     manager = manager_h;
00037 }
00038 
00039 Agent_base::Agent_base(ThreadManager* MTHREAD_h, int uniqueID_h, Manager_base* manager_h):OPT(MTHREAD_h, this){
00040     MTHREAD=MTHREAD_h;
00041     liquidity = 0;
00042     netProductionProfit = 0;
00043     sunkCostsPaid = 0;
00044     agentUniqueID=uniqueID_h;
00045     if(MTHREAD->RD->getBoolSetting("agentsView")){
00046         MTHREAD->treeViewerAddAgent(agentUniqueID);
00047         MTHREAD->treeViewerAddAgentProperty(agentUniqueID, "liquidity");
00048         MTHREAD->treeViewerAddAgentProperty(agentUniqueID, "capital");
00049     }
00050     manager = manager_h;
00051 }
00052 
00053 Agent_base::~Agent_base(){
00054     if (MTHREAD->RD){ 
00055         if(MTHREAD->RD->getBoolSetting("agentsView")){
00056             MTHREAD->treeViewerRemoveAgent(agentUniqueID);
00057         }
00058     }
00059 }
00060 
00061 // **************************************************************************
00062 
00063 void
00064 Agent_base::acquireObject(ModelObject acquiredObject_h, int case_h){
00065     if(case_h==STAGE_INIT){
00066         acquiredObject_h.setRandomAge();
00067     }
00068     else {
00069         acquiredObject_h.setStartYear(MTHREAD->SCD->getYear());
00070     }
00071     acquiredObject_h.setOwner(this);
00072     myObjects.push_back(acquiredObject_h);
00073 }
00074 
00075 double
00076 Agent_base::getResource(string resourceName_h){
00077     RegResources resource = MTHREAD->RD->getResourceByName(resourceName_h);
00078     switch (resource.source){
00079     case RESSOURCE_ZERO:
00080         return 0;
00081         break;
00082     case RESSOURCE_FIXED:
00083         return getInitialResourceByName(resource.name);
00084         break;
00085     case RESSOURCE_CALCULATED:
00086         return getCalculatedResourceByName(resource.name);
00087         break;
00088     case RESSOURCE_OBJECTS:
00089         return getObjectResourceByName(resource.name);
00090         break;
00091     default:
00092         msgOut(MSG_ERROR,"Resource "+resource.name+" has an unexpected source ("+i2s(resource.source)+"), I don't know how to handle that! I left 0, please check that it has a sence!");
00093         return 0;
00094     }
00095     return 0;
00096 }
00097 
00098 double
00099 Agent_base::getInitialResourceByName(string resourceName_h){
00100     map<string, double>::iterator p;
00101     p=initialResources.find(resourceName_h);
00102     if(p != initialResources.end())
00103         return p->second;
00104     else 
00105         msgOut(MSG_ERROR, "Coud not find initial resource "+resourceName_h+". I returned 0.");
00106     return 0;
00107 }
00108 
00109 double
00110 Agent_base::getCalculatedResourceByName(string resourceName_h){
00111 
00112     if (resourceName_h == "liquidity"){
00113         return liquidity;
00114     }
00115     else if (resourceName_h == "debsLevel"){
00116         // owned capital / (owned capital+debs level) = minEqCShare
00117         // ==> debsLevel = owned capital * (1-minEqCShare) / minEqCShare;
00118         double minEqCShare = MTHREAD->RD->getDoubleSetting("minEC");
00119         return (this->getCapital() * (1-minEqCShare)/minEqCShare);
00120     }
00121     else {
00122         msgOut(MSG_ERROR,"I don't know how to calculate resource "+resourceName_h+". I return 0, please check that it has a sence!");
00123     }
00124     return 0;
00125 }
00126 
00127 double
00128 Agent_base::getObjectResourceByName(string resourceName_h){
00129     double resourceValue=0;
00130     vector <ModelObject*> objects = getAvailableObjects();
00131     for (uint i=0; i<objects.size();i++){
00132         resourceValue += -objects.at(i)->getResourceValue(resourceName_h);
00133     }
00134     return resourceValue;
00135 }
00136 
00137 double
00138 Agent_base::getCapital(bool endOfYear){
00139     double capital;
00140     capital = liquidity;
00141     vector <ModelObject*> objects = getOwnedObjects();
00142     for (uint i=0; i<objects.size();i++){
00143         capital += objects.at(i)->getCurrentValue(endOfYear);
00144     }
00145     capital += getLandCapital();
00146     return capital;
00147 }
00148 
00149 vector <ModelObject*>
00150 Agent_base::getOwnedObjects(){
00151     vector <ModelObject*> toReturn;
00152     for (uint i=0; i<myObjects.size();i++){
00153         toReturn.push_back(&myObjects.at(i));
00154     }
00155     Agent_space* spatialAgent = dynamic_cast<Agent_space*> (this);
00156     if(spatialAgent){
00157         vector<Pixel*> ownedPlots  = spatialAgent->getPlots(PLOTS_OWNED);
00158         vector<Pixel*> rentedPlots = spatialAgent->getPlots(PLOTS_RENTED);
00159         for(uint i=0;i<ownedPlots.size();i++){
00160             vector <ModelObject*> plotObjects = ownedPlots[i]->getIncludedObjects();
00161             for (uint j=0;j<plotObjects.size();j++){
00162                 Agent_base* objOwner = plotObjects[j]->getOwner();
00163                 if (objOwner && objOwner== this){
00164                     toReturn.push_back(plotObjects[j]);
00165                 }
00166             }
00167         }
00168         for(uint i=0;i<rentedPlots.size();i++){
00169             vector <ModelObject*> plotObjects = rentedPlots[i]->getIncludedObjects();
00170             for (uint j=0;j<plotObjects.size();j++){
00171                 Agent_base* objOwner = plotObjects[j]->getOwner();
00172                 if (objOwner && objOwner == this){
00173                     toReturn.push_back(plotObjects[j]);
00174                 }
00175             }
00176         }
00177     }
00178     return toReturn;
00179     //FIXME: if we allow farm2farm rental this function would need to be upgraded, as it would not catch objects owned but rented to an other farm
00180 }
00181 
00182 vector <ModelObject*>
00183 Agent_base::getAvailableObjects(){
00184     vector <ModelObject*> toReturn;
00185     for (uint i=0; i<myObjects.size();i++){
00186         toReturn.push_back(&myObjects.at(i));
00187     }
00188     Agent_space* spatialAgent = dynamic_cast<Agent_space*> (this);
00189     if(spatialAgent){
00190         vector<Pixel*> ownedPlots  = spatialAgent->getPlots(PLOTS_OWNED);
00191         vector<Pixel*> rentedPlots = spatialAgent->getPlots(PLOTS_RENTED);
00192         for(uint i=0;i<ownedPlots.size();i++){
00193             if(!ownedPlots[i]->getTenant() || ownedPlots[i]->getTenant() == this){     //if the owned plot is not rented to some other agent
00194                 vector <ModelObject*> plotObjects = ownedPlots[i]->getIncludedObjects();
00195                 for (uint j=0;j<plotObjects.size();j++){
00196                     toReturn.push_back(plotObjects[j]);
00197                 }
00198             }
00199         }
00200         for(uint i=0;i<rentedPlots.size();i++){
00201             vector <ModelObject*> plotObjects = rentedPlots[i]->getIncludedObjects();
00202             for (uint j=0;j<plotObjects.size();j++){
00203                 toReturn.push_back(plotObjects[j]);
00204             }
00205         }
00206     }
00207     return toReturn;
00208 }
00209 
00210 void
00211 Agent_base::withdraw(){
00212     double fixedMoneyToWithdraw = MTHREAD->RD->getDoubleSetting("perCapMinWithdrawal")* getResource("labour") / MTHREAD->RD->getDoubleSetting("AWU_h");
00213     double variableMoneyToWithDraw = max(((double)0),getOverallProfit())*MTHREAD->RD->getDoubleSetting("withdrawalProfitShare");
00214     liquidity -= (fixedMoneyToWithdraw+variableMoneyToWithDraw);
00215 }
00216 
00217 void
00218 Agent_base::answerStats(AgentSurvey &SURVEY){
00219     Agent_space*  spatialAgent=NULL;
00220     if( dynamic_cast<Agent_space*> (this) ){
00221         spatialAgent = ( (Agent_space*) this );
00222     }
00223 
00224     // PLOTS..
00225     vector <Pixel*> ownedPlots;
00226     vector <Pixel*> rentedPlots;
00227     vector <int> landTypes = MTHREAD->RD->getIntVectorSetting("landTypes");
00228     vector <int> ownedPlotsByAllTypes(landTypes.size(), 0);  // initialized with all 0 values
00229     vector <int> rentedPlotsByAllTypes(landTypes.size(), 0); // initialized with all 0 values
00230     if( spatialAgent ){
00231         ownedPlots = spatialAgent->getPlots(PLOTS_OWNED);
00232         rentedPlots = spatialAgent->getPlots(PLOTS_RENTED);
00233     }
00234     for(uint i=0;i<ownedPlots.size();i++){
00235         for(uint j=0;j<landTypes.size();j++){
00236             if(ownedPlots[i]->getDoubleValue("landUse") == landTypes[j]){
00237                 ownedPlotsByAllTypes.at(j)++;
00238                 break;
00239             }
00240         }
00241     }
00242     for(uint i=0;i<rentedPlots.size();i++){
00243         for(uint j=0;j<landTypes.size();j++){
00244             if(rentedPlots[i]->getDoubleValue("landUse") == landTypes[j]){
00245                 rentedPlotsByAllTypes.at(j)++;
00246                 break;
00247             }
00248         }
00249     }
00250 
00251     // OBJECTS..
00252     vector <ModelObject*> objTypes                     = MTHREAD->RD->getObjectsDefinitionVector();
00253     vector<int>           ownedObjectsByType           (objTypes.size(), 0);
00254     vector<int>           availableObjectsByType       (objTypes.size(), 0);
00255     vector<int>           newlyAvailableObjectsByType  (objTypes.size(), 0);
00256     vector <ModelObject*> ownedObjects                 = getOwnedObjects();
00257     vector <ModelObject*> availableObjects             = getAvailableObjects();
00258 
00259     for(uint i=0;i<ownedObjects.size();i++){
00260         for(uint j=0;j<objTypes.size();j++){
00261             if(ownedObjects[i]->getName() == objTypes[j]->getName()){
00262                 ownedObjectsByType.at(j)++;
00263                 break;
00264             }
00265         }
00266     }
00267     for(uint i=0;i<availableObjects.size();i++){
00268         for(uint j=0;j<objTypes.size();j++){
00269             if(availableObjects[i]->getName() == objTypes[j]->getName()){
00270                 availableObjectsByType.at(j)++;
00271                 if(availableObjects[i]->getAge() == 0){
00272                      newlyAvailableObjectsByType.at(j)++;
00273                 }
00274                 break;
00275             }
00276         }
00277     }
00278 
00279     // ACTIVITIES..
00280     vector<RegActivities*> actTypes = MTHREAD->RD->getRegActivities();
00281     vector<double>         activitiesByType (actTypes.size(), 0);
00282     vector<matrixActivities*> myActivities = OPT.getActs();
00283 
00284     // changed 24.nov.2007. It was missing to report the quantities of activities associated with the spatial new objects (that are coupled with their activities)
00285     for(uint i=0;i<myActivities.size();i++){
00286         string myActName = "";
00287         if (myActivities[i]->actMould) {myActName = myActivities[i]->actMould->getName();} // activity derive from a normal activity
00288         else if(myActivities[i]->objMould){myActName = myActivities[i]->objMould->getRequiredFor();} // activity derive from an object
00289         else {
00290             continue; // it is a normal, unspatial object
00291             //msgOut(MSG_CRITICAL_ERROR, "BOOM! We found an activity without any object or activity mould!");
00292          }
00293 
00294         for(uint j=0;j<actTypes.size();j++){
00295             if (actTypes[j]->getName() == myActName) {
00296                 activitiesByType.at(j) += myActivities[i]->q;
00297                 break;
00298             }
00299         }
00300     }
00301 
00302     // FILLING THE SURVEY....
00303     SURVEY.year                 = MTHREAD->SCD->getYear();
00304     SURVEY.agentType            = this->getCategory();
00305     if( spatialAgent){
00306         SURVEY.spatial          = true;
00307     }
00308     else {
00309         SURVEY.spatial          = false;
00310     }
00311     SURVEY.agentID              = this->getAgentUniqueID();
00312     SURVEY.agentMouldID         = this->getMouldLocalID();
00313     SURVEY.managerID            = this->manager->getManagerID();
00314     SURVEY.agent                = this;
00315     if(spatialAgent){
00316         SURVEY.hostPlotID       = spatialAgent->getHomePlot()->getID();
00317         SURVEY.hostPlotX        = spatialAgent->getHomePlot()->getX();
00318         SURVEY.hostPlotY        = spatialAgent->getHomePlot()->getY();
00319     }
00320     SURVEY.capital              = this->getCapital();
00321     SURVEY.landCapital          = spatialAgent->getLandCapital();
00322     SURVEY.labour               = this->getResource("labour");
00323     double objCapital=0;
00324     for (uint i=0; i<ownedObjects.size();i++){
00325         objCapital += ownedObjects[i]->getCurrentValue();
00326     }
00327     SURVEY.objectsCapital       = objCapital;
00328     SURVEY.liquidity            = liquidity;
00329 
00330     SURVEY.netProductionProfit  = netProductionProfit;
00331 
00332     if(getGrossCoupledPremiums()>0){
00333         SURVEY.coupledPremiums      = getGrossCoupledPremiums()  * getNetTotalPremium()/(getGrossCoupledPremiums() + getGrossDecoupledPayment());
00334     }
00335     else {
00336         SURVEY.coupledPremiums = 0;
00337     }
00338     if (getGrossDecoupledPayment()>0){
00339         SURVEY.decoupledPayment     = getGrossDecoupledPayment() * getNetTotalPremium()/(getGrossCoupledPremiums() + getGrossDecoupledPayment());
00340     }
00341     else {
00342         SURVEY.decoupledPayment     = 0;
00343     }
00344 
00345     SURVEY.lastSunkCostsPaid    = sunkCostsPaid;
00346 
00347     SURVEY.ownedPlotsByAllTypes        = ownedPlotsByAllTypes;
00348     SURVEY.rentedPlotsByAllTypes       = rentedPlotsByAllTypes;
00349     SURVEY.ownedObjectsByType          = ownedObjectsByType;
00350     SURVEY.availableObjectsByType      = availableObjectsByType;
00351     SURVEY.newlyAvailableObjectsByType = newlyAvailableObjectsByType;
00352     SURVEY.activitiesByType            = activitiesByType;
00353 }
00354 
00355 void
00356 Agent_base::pay(double amount_h, bool updateResourceValues){
00357     liquidity -= amount_h;
00358     if (updateResourceValues) OPT.updateResourceValues();
00359 }