Переглянути джерело

Merge branch 'master' of http://local.beijingyongan.com:3000/linux-dev/ya-serv

zzj 5 роки тому
батько
коміт
b37c8fc43e
12 змінених файлів з 181 додано та 78 видалено
  1. 1 0
      ant.cpp
  2. 22 6
      bindmorecard.h
  3. 1 0
      card.cpp
  4. 2 2
      card.h
  5. 1 1
      cardMgr.cpp
  6. 8 2
      card_base.cpp
  7. 2 4
      card_car.cpp
  8. 2 4
      card_person.cpp
  9. 19 8
      event.cpp
  10. 108 28
      his_location.h
  11. 13 13
      main.cpp
  12. 2 10
      module_service/area_business_work_rate.cpp

+ 1 - 0
ant.cpp

@@ -389,6 +389,7 @@ void sit_list::read_ant_path(int id)
 
 	test_find_path(card_path::inst(),point(4727,-8.06),point(2200,-75));
 	test_find_path(card_path::inst(),point(4727,-8.06),point(2600,-100));
+	test_find_path(card_path::inst(),point(2768.50,-75.00),point(2768.50,-161.58));
 	test_find_path(card_path::inst(),point(4727,-8.06),point(5427.04,-304.02));
 	test_find_path(card_path::inst(),point(4714.70,-8.06),point(5427.04,-304.02));
 	test_find_path(card_path::inst(),point(4727,-75),point(2200,-75));

+ 22 - 6
bindmorecard.h

@@ -45,6 +45,10 @@ struct Data
 		m_totaldistance = 0;
 		m_flag = false;
 	}
+    bool empty()
+    {
+        return m_index==0;
+    }
 	void increase(const int index)
 	{
 		m_ct[index]++;
@@ -101,15 +105,15 @@ struct TcardInterface
 			}
 			else if(tsp>=tmp_tsp_max)
 			{
-				if(timeout())
+				if(timeout() && !empty_slop())//达到数量,而且最后一个slop是非空的则继续判断,否则,不判断。
 				{
 					auto tp = get();
 					stp = check(std::get<0>(tp),std::get<1>(tp));
 					skip(1);
 				}
 				grow(tsp);
-				tmp_tsp_min = back(0).m_timestamp;
-				tmp_tsp_max = back(0).m_timestamp + TIME_WIN_MILLISEC;
+				tmp_tsp_min = tsp;
+				tmp_tsp_max = tsp + TIME_WIN_MILLISEC;
 			}
             else
             {
@@ -140,14 +144,26 @@ struct TcardInterface
 	{
 		return m_arr.empty();
 	}
+    bool empty_slop()
+    {
+        return back(0).empty();
+    }
 	int size() 
 	{
 		return m_arr.size();
 	}
 	void  grow(uint64_t ct)
 	{
-		Data d(ct);
-		m_arr.push_back(d);
+        if(size()&&empty_slop())
+        {
+            back(0).reset();
+            back(0).m_timestamp=ct;
+        }
+        else
+        {
+		    Data d(ct);
+		    m_arr.push_back(d);
+        }
 	}
 	Data &back(int index)
 	{
@@ -163,7 +179,7 @@ struct TcardInterface
 	}
 	bool timeout()
 	{
-		return size() == SIZE;
+		return size()==SIZE;
 	}
 	std::string getInfo_1()
 	{

+ 1 - 0
card.cpp

@@ -18,6 +18,7 @@
 #include "mine_business.h"
 
 extern config_file config;
+int three_rates_flag=0;
 void card_list::init_staffer(const std::string & lszId64)
 {
     std::string strategy = config.get("person.strategy","PS_1");

+ 2 - 2
card.h

@@ -5,7 +5,7 @@
 
 #include "card_base.h"
 #include "write-copy.h"
-
+extern int three_rates_flag;
 struct card_list_visit:visitor<std::shared_ptr<card_location_base>>
 {
 	bool visit(std::shared_ptr<card_location_base> c);
@@ -28,4 +28,4 @@ struct card_list:single_base<card_list,uint64_t,std::shared_ptr<card_location_ba
     std::shared_ptr<card_location_base> get_card_by_cid(int cid);
     ~card_list(){}
 };
-#endif
+#endif

+ 1 - 1
cardMgr.cpp

@@ -36,7 +36,7 @@ void cardMgr::onMessage(const Msg &m)
 }
 void cardMgr::clear(uint64_t cardid)
 {
-	auto v = m_cgraph.getcard(cardid);
+	auto v = getcard(cardid);
 	for(const auto & cid:v)
 	{
         log_info("LemonHash_up_mine:%lu&%lu",cardid,cid);

+ 8 - 2
card_base.cpp

@@ -20,11 +20,11 @@
 #include "area.h"
 #include "cardMgr.h"
 extern config_file config;
-const static int three_rates_flag=config.get("service.three_rates_flag",0);
 card_location_base::card_location_base(const std::string&type,uint32_t id,uint16_t dis,int16_t t,int32_t deptid,int32_t level_id,uint32_t cid)
 	:card(id,dis,t,deptid,level_id,cid)
 {
     select_tool_manage::instance()->create_tool(type,m_sel_tool,m_smo_tool);
+	m_his_location_card.reset(new location_card(m_id,m_type,cid));
 }
 
 void card_location_base::do_status(int st)
@@ -81,6 +81,7 @@ void card_location_base::on_location(const std::vector<point>&vp,const std::vect
 {
 	loc_point pt = m_sel_tool->select_solution(vp,lm);
 	pt.y=-pt.y;
+	auto site_ptr=get_area_tool()->m_site;
 	if(pt.m_useless)
 	{
 		x = tool_other::round(pt.x,3);
@@ -93,12 +94,17 @@ void card_location_base::on_location(const std::vector<point>&vp,const std::vect
 		double acc = lm[0].m_acc;
         m_acc = lm[0].m_acc;
 		log_info("useful:type:%d,card_id:%d,ct:%d,timestamp:%llu, loc_point,x:%f,y:%f acc:%.2f",m_type,m_id,m_ct,m_time,x,y,acc);
+
+        int sid=0,mapid=0;
+        if(site_ptr){sid=site_ptr->m_area_id;mapid=site_ptr->m_map_id;}
+        //if(auto st=m_area_tool->m_site)sid=st->m_area_id;
+	    m_his_location_card->push(m_time,pt,sid,mapid);
+
 		do_business(lm.front().m_sit, pt, acc);
 	}
 	else
 	{
 		int sid=0;
-		auto site_ptr=get_area_tool()->m_site;
 
 		if(site_ptr)
 		{

+ 2 - 4
card_car.cpp

@@ -18,7 +18,7 @@ car::car(const std::string&type,uint32_t cardid,uint16_t needdisplay,int16_t t,i
 	 ,m_vehicle_type_id(type_id)
 {
 	m_message_handle.reset(new card_message_handle(this));
-	m_his_location_card.reset(new location_vehicle(m_id,m_type,cid));
+	//m_his_location_card.reset(new location_vehicle(m_id,m_type,cid));
 }
 
 car::~car(){}
@@ -95,9 +95,7 @@ void car::make_package()
 	cp.is_on_duty=on_duty;
     //log_info("%s,down_time:%f,today:%lu,duty:%u",tool_other::type_id_to_str(m_type,m_id).c_str(),cp.down_time,tool_time::morning_of_today_ms(),on_duty);
 	upt_card_pos(cp,pt);
-    int sid=0;
-    if(auto st=m_area_tool->m_site)sid=st->m_area_id;
-	m_his_location_card->push(pt.m_time,pt,sid,cp.map_id);
+    //int sid=0; if(auto st=m_area_tool->m_site)sid=st->m_area_id; m_his_location_card->push(pt.m_time,pt,sid,cp.map_id);
 
 	uint64_t _now=tool_time::now_to_ms();
 	uint64_t t=_now>m_timeval?_now-m_timeval:m_timeval-_now;

+ 2 - 4
card_person.cpp

@@ -29,7 +29,7 @@ person::person(const std::string &type,uint32_t cardid,uint16_t needdisplay,int1
 	,m_deptName(dname)
 {
 	m_message_handle.reset(new card_message_handle(this));
-	m_his_location_card.reset(new location_staff(m_id,m_type,cid));
+	//m_his_location_card.reset(new location_staff(m_id,m_type,cid));
 }
 
 person::~person()
@@ -139,9 +139,7 @@ void person::on_timer()
 	cp.is_on_duty= m_mine_tool->is_on_duty();
 	upt_card_pos(cp,pt);
 	log_info("on_timer here ...%d,%lld,%.2f,%.2f,%d,%d--%d",m_id,_time,pt.x,pt.y,cp.map_id,cp.area_info.size(),person::m_limit_detained_time);
-    int sid=0;
-    if(auto st=m_area_tool->m_site)sid=st->m_area_id;
-	m_his_location_card->push(_time,pt,sid,cp.map_id);
+    //int sid=0; if(auto st=m_area_tool->m_site)sid=st->m_area_id; m_his_location_card->push(_time,pt,sid,cp.map_id);
 
 	uint64_t _now=tool_time::now_to_ms();
 	uint64_t t=_now>m_timeval?_now-m_timeval:m_timeval-_now;

+ 19 - 8
event.cpp

@@ -103,7 +103,7 @@ void Event::handle_alarm_event(EVENT_TYPE et,uint64_t id,double limit_value,doub
         {
             uint64_t _id=id;
             log_info("Create_Event:desc[%s],id:%d,et:%d",desc.c_str(),id,et);
-            if(et == ET_VEHICLE_REAR_END&&!desc.empty())
+            if((et==ET_UWB_MORE_CARD||et == ET_VEHICLE_REAR_END)&&!desc.empty())//防追尾告警特殊处理
             {
                 std::string cardid = desc.substr(0,desc.find_first_of('&'));
                 _id = tool_other::card_id_to_u64(cardid);
@@ -115,11 +115,12 @@ void Event::handle_alarm_event(EVENT_TYPE et,uint64_t id,double limit_value,doub
                 ev_ptr->m_desc=desc;
                 ev_ptr->m_id=eid;
                 ev_ptr->m_dis_type=edt;
-                if(et==ET_UWB_MORE_CARD)
+                if(et==ET_UWB_MORE_CARD)//一人多卡特殊处理
                 {
                     ev_ptr->m_obj_id=desc;
                     ev_ptr->m_cur_time=std::chrono::system_clock::time_point(std::chrono::milliseconds((time_t)limit_value * 1000));
                 }
+                if(et == ET_VEHICLE_REAR_END)ev_ptr->m_obj_id=desc;
                 //保存告警信息
                 event_list::instance()->add(eid,ev_ptr);
             }
@@ -148,8 +149,20 @@ void Event::handle_alarm_event(EVENT_TYPE et,uint64_t id,double limit_value,doub
 std::shared_ptr<ya_event> mine_event::on_message(EVENT_TYPE et,uint64_t id,bool f)
 {
     std::shared_ptr<ya_event> event_ptr=nullptr;
-    if(f)
+    if(f){
         event_ptr=create_event(std::to_string(id), et);
+        auto card_ptr = card_list::instance()->get(id);
+        if(!card_ptr)
+        {
+            event_ptr->m_map_id=5;
+            return event_ptr;
+        }
+	    if(auto site_ptr=card_ptr->get_area_tool()->m_site)
+        {
+            event_ptr->m_area_id = site_ptr->m_area_id;
+            event_ptr->m_map_id = site_ptr->m_map_id;
+        }
+    }
     return event_ptr;
 }
 
@@ -208,12 +221,10 @@ std::shared_ptr<ya_event> card_event::on_message(EVENT_TYPE et,uint64_t id,bool
         event_ptr->y = card_ptr->y;
         //event_ptr->m_is_display = card_ptr->m_display;
 
-        auto area_info_map = card_ptr->get_area_tool()->m_area_info;
-        if(!area_info_map.empty())
+	    if(auto site_ptr=card_ptr->get_area_tool()->m_site)
         {
-            auto lm = area_info_map.begin()->second;
-            event_ptr->m_area_id = std::get<0>(lm);
-            event_ptr->m_map_id = card_ptr->get_area_tool()->get_mapid();
+            event_ptr->m_area_id = site_ptr->m_area_id;
+            event_ptr->m_map_id = site_ptr->m_map_id;
         }
     }
     return event_ptr;

+ 108 - 28
his_location.h

@@ -28,6 +28,7 @@ struct location_card
 	int 		m_mapid;//地图
 	uint64_t	m_timestamp;//入库后的时间
 	point		m_p;//入库后的点
+    int         m_direct_index;
 	struct mini_data
 	{
 		mini_data(const point &p,uint64_t t)
@@ -44,13 +45,15 @@ struct location_card
 		m_mapid=-1;
 		m_timestamp=0;
 		m_p.set(0,0);
-		init_att();
+		std::queue<mini_data> tmp;
+		m_d.swap(tmp);
+        m_direct_index=0;
 	}
-	void init_att()
+	void init_att(const point &pt,uint64_t time)
 	{
-		m_arg=0x12345678;
 		std::queue<mini_data> tmp;
 		m_d.swap(tmp);
+        m_d.emplace(pt,time);
 	}
 	void set_invalid()
 	{
@@ -69,21 +72,34 @@ struct location_card
 	{
 		m_timestamp=time;
 		m_p.set(pt);
+        init_att(pt,time);
 	}
-	bool line_changed(const point &pt)
+	bool line_changed(const point &pt,int &df)
 	{
 		if(!is_valid())
 		  return false;
-		point p=m_d.back().p;
+        point p;
+        if(m_d.empty())p=m_p;  else p=m_d.back().p;
 
 		if(point::eq(p.x,pt.x,0.2) && point::eq(p.y,pt.y,0.2)) return false;
         double dis1=m_p.dist(pt);
-        if(dis1<1.5)return false;
+        if(dis1<2)return false;
         double dis = p.dist(pt);
 		double arg = make_arg(pt,p);
-		log_info("his_location:line_changed:%d,%f,m_arg:%f,%s,%f,%f",m_cardid,arg,m_arg, (arg-m_arg > -1e-10 && arg-m_arg<1e-10)?"same":"not same",m_arg-arg,dis);
-        if(dis<0.5 && fabs(fabs(arg)+fabs(m_arg)-3.141593)< 0.000005)
-          return false;
+        //查看路径方向是否改变
+        bool change_flag=(arg-m_arg > -1e-10 && arg-m_arg<1e-10);
+        //change_flag为true,标识没有发生变化
+        if(change_flag)m_direct_index=0;
+		log_info("his_location:line_changed:%d,%f,m_arg:%f,%s,%f,%f",m_cardid,arg,m_arg, change_flag?"same":"not same",m_arg-arg,dis);
+        //if(dis<0.5 && fabs(fabs(arg)+fabs(m_arg)-3.141593)< 0.000005)
+        //判断5次反向才做下一步动作
+        if(fabs(fabs(arg)+fabs(m_arg)-3.141593)< 0.000005)
+        {
+            if(++m_direct_index<=10)
+            {
+                df=1;return false;
+            }
+        }
 		return !point::eq(arg,m_arg,1e-10);
 	}
 	bool is_speed_changed(const point& pt,uint64_t time)
@@ -138,7 +154,7 @@ struct location_card
 	}
 	void push(uint64_t timestamp,const point & p,int32_t areaid,int32_t mapid)
 	{
-		if(m_p.empty() || m_timestamp==0||m_areaid<=0||m_mapid<=0)	
+		if(m_p.empty() || m_timestamp==0||m_areaid<0||m_mapid<0)	
 		{
 		  set(p,timestamp);
 		  m_areaid=areaid;m_mapid=mapid;
@@ -148,18 +164,29 @@ struct location_card
 		
 		if(!is_valid())
 		{
-		  if(p==m_p)
-		  {
-			  init_att();set(p,timestamp);
-			  m_d.emplace(p,timestamp);
-			  return ;
-		  }
-		  m_arg=make_arg(p,m_p);
-		  log_info("his_location:%d arg:%f",m_cardid,m_arg);
-		  insert();
+            //if(p==m_p)
+		    if(point::eq(p.x,m_p.x,0.2) && point::eq(p.y,m_p.y,0.2))
+            {
+		        set(p,timestamp);
+			    return ;
+            }
+            auto v=find_path(m_p,p);
+            if(v.empty())
+		        m_arg=make_arg(p,m_p);
+            else
+            {
+                log_info("his_location:more_abnormal_point....%d,(%.2f,%.2f)---(%.2f,%.2f)",m_cardid,m_p.x,m_p.y,p.x,p.y);
+                handle_path(v,timestamp,true);
+                set_invalid();
+                return;
+            }
+		    log_info("his_location:%d arg:%f",m_cardid,m_arg);
+		    insert();
+            return;
 		}
 		bool flag=false;
 		bool iflag=false;
+        //判断是否路径发生了变化
 		flag=handle_message(p,timestamp);
 		//if(time_out(p,timestamp))
 		//	if(!flag)iflag=true;
@@ -177,34 +204,87 @@ struct location_card
 			insert();
 		}
 	}
-	virtual std::string getTabName()=0;
 	void insert()
 	{
-		std::string tabName=getTabName();
+		//std::string tabName=getTabName();
 		char nsql[512]={0};
 		const char * sql = "replace into his_location (obj_id,card_type_id,ident,begin_time,map_id,area_id,begin_pt,direction)"
 		                   "values(%d,%d,%d,'%s',%d,%d,'%.2f,%.2f',%f);";
 		snprintf(nsql,512,sql,m_objid,m_type,m_cardid,tool_time::to_str(m_timestamp/1000).c_str(),m_mapid,m_areaid,m_p.x,m_p.y,m_arg);
-		log_info("his_location[%d]:%s",m_cardid,nsql);
+		log_info("his_location[%d,%lu]:%s",m_cardid,m_timestamp,nsql);
 		sDBConnPool.PushAsync(nsql);
 	}
 	void update(const point &p,uint64_t timestamp)
 	{
-		std::string tabName=getTabName();
+		//std::string tabName=getTabName();
 		char nsql[512]={0};
 		const char * sql = "update his_location set last_time='%s',speed=%.2f where obj_id=%d and begin_time='%s' and last_time is null;";
 		double dist = m_p.dist(p);
-		double t	= timestamp - m_timestamp;
-		double avge_speed= dist/t*1000;
+		double t	= (timestamp - m_timestamp)/1000;
+		double avge_speed= dist/t;
 		if(std::isnan(avge_speed)|| std::isinf(avge_speed))avge_speed=0;
 
 		snprintf(nsql,512,sql,tool_time::to_str(timestamp/1000).c_str(),avge_speed,m_objid,tool_time::to_str(m_timestamp/1000).c_str());
-		log_info("his_location[%d]:%s",m_cardid,nsql);
+		log_info("his_location[%d]:%s[%lu,%lu]",m_cardid,nsql,timestamp,m_timestamp);
 		sDBConnPool.PushAsync(nsql);
 	}
+    std::vector<point> find_path(const point &p1,const point &p2)
+    {
+        std::vector<point> rc=card_path::inst().find_path(point(p1.x,-p1.y),point(p2.x,-p2.y));
+        return std::move(rc);
+    }
+	//virtual bool  handle_message(const point &p,uint64_t timestamp)=0;
+	bool  handle_message(const point &p,uint64_t timestamp)
+    {
+		bool flag = false;
+        int df=0;
+		if(line_changed(p,df))
+        {
+            flag = true;
+            std::vector<point> rc=find_path(m_d.back().p,p);
+            if(rc.empty())
+            {
+			    log_info("his_location:line_changed rc.empty() %d",m_cardid);
+			    update(m_d.back().p,m_d.back().time);
+			    set(m_d.back().p,m_d.back().time);
+            }
+            else
+            {
+                if(handle_path(rc,timestamp,false))
+                  return true;
+            }
+            //置m_arg非法
+            set_invalid();
+        }
+        if(df==1)flag=true;
+        return flag;
+    }
+    bool handle_path(std::vector<point> &rc,uint64_t timestamp,bool flag)
+    {
+        double dis=0;point _p=m_p;
+        std::for_each(rc.begin(),rc.end(),[&dis,&_p](point &pt){
+                    pt.y=-pt.y;dis+=_p.dist(pt);_p=pt;
+                    });
+		uint64_t t=timestamp/1000 - m_timestamp/1000;
+        if(t==0||dis<0.1)return true;
+		double avge_speed= dis/t;
+
+        for(const point & pp:rc)
+        {
+            if(flag){
+			    m_arg=make_arg(pp,m_p);insert();
+            }
+		    log_info("his_location:line_changed_x %d point(%.2f,%.2f)--circle point(%.2f,%.2f),speed:%.2f",m_cardid,m_p.x,m_p.y,pp.x,pp.y,avge_speed);
+            double dist=m_p.dist(pp);uint64_t tt=dist/avge_speed*1000;
+            uint64_t etime=m_timestamp+tt;
+			update(pp,etime);set(pp,etime);
+            flag=true;
+        }
+        return false;
+    }
 
-	virtual bool  handle_message(const point &p,uint64_t timestamp)=0;
 };
+#if 0
 struct location_staff:location_card
 {
 	location_staff(uint32_t id,uint64_t type,uint32_t objid)
@@ -228,7 +308,6 @@ struct location_staff:location_card
 			else
 			{
 				log_info("his_location:line_changed_find_path %d,(%.2f,%.2f)-->(%.2f,%.2f)-->(%.2f,%.2f)",m_cardid,m_p.x,m_p.y,m_d.back().p.x,m_d.back().p.y,p.x,p.y);
-				std::vector<point> rc=card_path::inst().find_path(point(m_d.back().p.x,-m_d.back().p.y),point(p.x,-p.y));
 				if(rc.empty())				
 				{
 					log_info("his_location:line_changed rc.empty() %d",m_cardid);
@@ -296,3 +375,4 @@ struct location_vehicle:location_card
 	}
 };
 #endif
+#endif

+ 13 - 13
main.cpp

@@ -25,10 +25,7 @@
 
 config_file config;
 void handlereader(uint32_t readerid,bool duration,uint32_t t)
-{
-
-}
-
+{}
 //三率模块中告警回调
 void Handle_ThreeRates_Event_Callback(const int evType, const int evId, uint64_t id
                                       , double limitVal, double curVal, bool bFalg)
@@ -44,6 +41,7 @@ struct Init_Setting
 {
     void init()
     {
+        three_rates_flag=config.get("service.three_rates_flag",0);
         YADB::_DB_POOL_SETTING_ DBSetting;
         DBSetting.Host = config.get("db.host","127.0.0.1");
         DBSetting.User = config.get("db.user","root");
@@ -88,15 +86,17 @@ struct Init_Setting
 		mine_business::inst()->load();
         event_list::instance()->load_his_data_from_db();
         card_list::instance()->load_his_card_postion_from_db();
-        db_para dp;	
-        dp.Host=DBSetting.Host;
-        dp.User=DBSetting.User;
-        dp.PWD=DBSetting.PWD ;
-        dp.DBName=DBSetting.DBName;
-        dp.CharSet=DBSetting.CharSet ;
-        dp.TimeOut=DBSetting.TimeOut;
-        dp.PoolSize=DBSetting.PoolSize;
-		init_three_rates(dp);
+        if(three_rates_flag){
+            db_para dp;	
+            dp.Host=DBSetting.Host;
+            dp.User=DBSetting.User;
+            dp.PWD=DBSetting.PWD ;
+            dp.DBName=DBSetting.DBName;
+            dp.CharSet=DBSetting.CharSet ;
+            dp.TimeOut=DBSetting.TimeOut;
+            dp.PoolSize=DBSetting.PoolSize;
+		    init_three_rates(dp);
+        }
 
 
         log_info("Init_Setting::init  Success. \n" );

+ 2 - 10
module_service/area_business_work_rate.cpp

@@ -8,9 +8,7 @@
 #include"struct_def.h"
 #include"three_rates.h"
 #include"area.h"
-#include"card.h"
 #include"tool_time.h"
-
 struct work_rate_data:business_data
 {
     work_rate_data()
@@ -27,10 +25,7 @@ void area_business_work_rate::on_load_his(const std::shared_ptr<area_hover>&area
 void area_business_work_rate::on_enter(const std::shared_ptr<area_hover>&area_hover_ptr,
                                        const std::shared_ptr<card_location_base>&card_ptr,std::shared_ptr<business_data>& ptr)
 {
-    if(!card_ptr->is_person())
-    {
-        return;
-    }
+    if(!card_ptr->is_person() || !three_rates_flag)return;
 
     auto card = std::make_shared<card_pos>();
     card->id = card_ptr->m_id;
@@ -55,10 +50,7 @@ void area_business_work_rate::on_hover(const std::shared_ptr<area_hover>&area_ho
 void area_business_work_rate::on_leave(const std::shared_ptr<area_hover>&area_hover_ptr,
                                        const std::shared_ptr<card_location_base>&card_ptr,std::shared_ptr<business_data> ptr)
 {
-    if(!card_ptr->is_person())
-    {
-        return;
-    }
+    if(!card_ptr->is_person() || !three_rates_flag)return;
 
     auto card = std::make_shared<card_pos>();
     card->id = card_ptr->m_id;