#include <cmath>
#include <sstream>
#include <vector>
#include <list>
#include <array>
#include <map>
#include "mine_business.h"
#include "log.h"
#include "point.h"
#include "db/db_api/CDBSingletonDefine.h"
#include "db/db_tool.h"
#include "common_tool.h"
#include "ant.h"
#include "ya_setting.h"
#include "card_path.h"
#include "card.h"
#include "area.h"
#include "event.h"
struct card_sensor
{
    card_sensor(int32_t wid,const point &p,const std::string &cid)
        :card_id(cid)
         ,sid(0)
         ,id(wid)
         ,bigger(-1),count(0),sum(0),ct(-1),stime(0),flag(false),is_alarm(false)
    {
        base_point=p;
    }
    std::string         card_id;
    int32_t             sid;
    int32_t             id;
    std::vector<int>    sensorId_list;
    point               base_point; 
    std::array<point,2> ant;
    int8_t bigger;
    uint32_t count,sum;
    uint16_t ct;
    uint64_t stime;
    bool flag,is_alarm;
    std::list<double> his_data;
    std::array<uint64_t,2> dist;
    void clear()
    {
        count=sum=0;stime=0;flag=false;
    }
    bool timeout()
    {
        time_t t=time(NULL);
        return flag && t-stime>10*60;
    }
    bool check_location_reversal(std::string & str)
    {
        time_t t=time(NULL);
        time_t tval= t-stime;
        bool f=false;
        if (tval !=0 && sum*1.0/tval > 0.8 && count*1.0/sum <0.2)
          f=true;
        char buf[1024]={0};
        sprintf(buf,"[reverse_alarm_checking]%s,count:%d,sum:%d,val:%ld,s:%.2f,v:%.2f,alarm:%d",
                    card_id.c_str(),count,sum,tval,(sum*1.0/tval),(count*1.0/sum),f);
        str=buf;
        return f;
    }
    void make_reverse_condition(int16_t antid,uint16_t ct,double d)
    {
        dist[antid]=d;
        if(this->ct == ct){
            sum++;
            int b=-1;
            if (dist[0]>dist[1]) b=0 ;else b =1;
            if(b==bigger) count++; //合格的点
        }
        this->ct = ct;
    }
    void set(const point &p0,const point &p1,int id)
    {
        int8_t b=0;
        ant[0].set(p0);ant[1].set(p1);
        double d0=base_point.dist(p0);double d1=base_point.dist(p1);
        if(d0>d1)b=1;else b=0;
        if (bigger!=-1 && b!=bigger){
            count=sum=0;stime=time(0);
        }
        bigger=b;sid=id;
    }
    bool push(double d){
        bool f=true;
        his_data.push_back(d);
        if (his_data.size()==3){
            double da=0;
            for (const auto &d:his_data){
                if(da>d || d-da<0.004){f=false;break;}
                da=d;
            }
            his_data.pop_front();
        }
        else f=false;
        return f;
    }
    point &operator[](int i){return ant[i];}
    const point &operator[](int i)const {return ant[i];}
    void set_true(){flag=true;stime=time(NULL);}
    bool warning(){return flag;}
    bool empty(){return his_data.empty();}
    double back(){return his_data.back();}
    void clear_sensor(){clear();}
    int reader_id(){return sid;}
    void push_back(int32_t sensor_id){sensorId_list.push_back(sensor_id);}
};
struct card_sensor_mgr
{
    void push(int32_t wid,int32_t sid,const point &p,const std::string & cardid)
    {
        std::shared_ptr<card_sensor> cs=nullptr;
        auto it=m_mgr.find(wid);
        if(it!=m_mgr.end())
          cs=it->second;
        else
        {
            cs=std::make_shared<card_sensor>(wid,p,cardid);
            m_mgr.insert({wid,cs});
        }
        cs->push_back(sid);
    }
    void for_each();
    void make_condition(int32_t antid,uint32_t ct,uint64_t tof,uint32_t sid);
    std::map<int32_t,std::shared_ptr<card_sensor>> m_mgr;
};

struct staffer_num_business
{
	void record_staffer_num();
	void fetch_add(bool f)
    {
        if(f)
            m_staff_num++;
		m_staff_num_real++;
        
    }
	staffer_num_business()
	{
        reset();
		m_record_staffer_timeval = 0;
	}
	private:
	void reset(){m_staff_num=0;m_staff_num_real=0;}
	std::atomic<uint32_t> m_staff_num,m_staff_num_real;
	std::time_t m_record_staffer_timeval;
};

struct reverse_alarm_business
{
    void load_sensor(); 
    void run_sensor();
    void make_condition(uint64_t type,uint32_t id,int32_t antid,uint32_t ct,uint64_t tof,uint32_t sid);
    private:
    std::map<uint64_t,std::shared_ptr<card_sensor_mgr>> m_sensor_mgr;
};
struct rear_end_collision_prevented_business
{
    rear_end_collision_prevented_business()
    {
        _time=0;m_v.clear();
    }
    void clear(){m_v.clear();}
    void put(const std::shared_ptr<card_location_base>&c)
    {
        m_v.push_back(c);
    }
    bool rear_end_arg_algo(uint64_t u1,uint64_t u2);
    void handle_message();
    double get_absolute_distance(uint64_t c1,uint64_t c2);
    struct car_data
    {
        car_data()
            :_t(0),_arg(0x12345678)
        {}
        void push(uint64_t cid,const point &p,uint64_t t)
        {
            last_p=_p;_p=p;
            if (last_p.empty() || _p.empty())
              return;
            if (_p.dist(last_p)<0.5)
              return;

            if ( t-_t<5*1000)
            {
                _arg = std::arg(std::complex<double>(_p.x,_p.y)-std::complex<double>(last_p.x,last_p.y));
                line_v l(last_p,_p);_line=l;
                std::string card_id = tool_other::get_string_cardid(cid);
                log_info("[vehicle_alarm_arg ] %s,arg:%f (%.2f,%.2f)--(%.2f,%.2f)",card_id.c_str(),_arg,last_p.x,last_p.y,p.x,p.y);
            }
            _t=t;
        }

        point last_p,_p;
        line_v _line;
        uint64_t _t;
        double _arg;
    };
    struct vInfo
    {
        vInfo()
        {
            is_alarm=false;
            real_end_start_time=0;
            backfired_start_time=0;
        }
        void push(const std::string & c1, const std::string &c2)
        {
            m_cid[0]=c1;
            m_cid[1]=c2;
            std::sort(m_cid.begin(),m_cid.end());
        }
        std::string getKey() const
        {
            return m_cid[0]+"&"+m_cid[1];
        }
        bool is_alarm;
        std::array<std::string,2> m_cid;
        time_t real_end_start_time ;
        time_t backfired_start_time;
    };
    void make_arg(uint64_t cid, const point &p,uint64_t t)
    {
        m_map[cid].push(cid,p,t);
    }
    private:
    bool invalid_card(const std::shared_ptr<card_location_base> &c);
    time_t _time;
    std::vector<std::shared_ptr<card_location_base>> m_v;
    std::map<uint64_t,car_data> m_map;
    std::map<std::string,vInfo> m_CloserVehicle;
};
mine_business::mine_business()
{
    m_staffer_num_ptr.reset(new staffer_num_business);
    m_reverse_alarm_ptr.reset(new reverse_alarm_business);
    m_rear_ended_ptr.reset(new rear_end_collision_prevented_business);
}
mine_business* mine_business::inst()
{
    static mine_business mb;
    return &mb;
}
void mine_business::run_business()
{
    record_staffer_num();
    handle_reverse_alarm();
    handle_rear_end();
}
void mine_business::fetch_add(bool f)
{
    m_staffer_num_ptr->fetch_add(f);
}
void mine_business::record_staffer_num()
{
    m_staffer_num_ptr->record_staffer_num();
}
void mine_business::load()
{
    m_reverse_alarm_ptr->load_sensor(); 
}
void mine_business::handle_reverse_alarm()
{
    m_reverse_alarm_ptr->run_sensor();
}
void mine_business::make_reverse_condition(uint64_t type,uint32_t id,int32_t antid,uint32_t ct,uint64_t tof,uint32_t sid)
{
    m_reverse_alarm_ptr->make_condition(type,id,antid,ct,tof,sid);
}
///rear ended  collision...
void mine_business::put(const std::shared_ptr<card_location_base> &c)
{
    m_rear_ended_ptr->put(c);
}
void mine_business::make_arg(uint64_t cid,const point &p,uint64_t t)
{
    m_rear_ended_ptr->make_arg(cid,p,t);
}
void mine_business::handle_rear_end()
{
    m_rear_ended_ptr->handle_message();
}
void mine_business::clear_vehicle()
{
    m_rear_ended_ptr->clear();
}
///////staffer_num_business
/**********************************
//每两分钟把人员数量入库。
//不往前端推送的人员,不算在数量范围内
 *********************************/
void staffer_num_business::record_staffer_num()
{
    static uint32_t min_num=0,max_num=0,min_num_real=0,max_num_real=0;
    std::time_t t = time(NULL);
    char ti[64] = { 0 };
    strftime(ti,sizeof(ti),"%Y/%m/%d %H:%M:%S",localtime(&t));
    std::string sti(ti);
    int minute = atoi(sti.substr(sti.find_first_of(':')+1,2).c_str());
    uint32_t a=m_staff_num.load();
    uint32_t ar=m_staff_num_real.load();
    if(m_record_staffer_timeval==0)
    {
        min_num=max_num=a;
        min_num_real=max_num_real=ar;
        m_record_staffer_timeval = t;
    }
    if(t-m_record_staffer_timeval>=120 && minute%2 == 0)
    {
        std::stringstream ss;
        ss<< "INSERT INTO his_staff_number(max_num,min_num,ave_num,max_num_real,min_num_real,ave_num_real) VALUES("
            <<max_num<<','<<min_num<<','<<std::lround((max_num+min_num)/2)<<','
            <<max_num_real<<','<<min_num_real<<','<<std::lround((max_num_real+min_num_real)/2)<<");";
        db_tool::PushAsync(ss.str().c_str());

        min_num=max_num=a;
        min_num_real=max_num_real=ar;
        m_record_staffer_timeval = t;
    }
    else
    {
        if (min_num>a)min_num = a;
        if (max_num<a)max_num = a;
        if (min_num_real>ar)min_num_real = ar;
        if (max_num_real<ar)max_num_real = ar;
    }
    reset();
    return;
}
//前端修改数据库表,dat_sensor dat_drivingface,dat_drivingface_vehicle的时候,需要加载.
void reverse_alarm_business::load_sensor()
{
    std::string sql = "SELECT sensor_id,data_source,work_face_id,v.vehicle_id,ve.card_id,d.base_point_x,d.base_point_y FROM dat_sensor ,dat_drivingface_vehicle v,dat_drivingface d,dat_vehicle_extend ve WHERE sensor_type_id = 1 AND work_face_id = v.drivingface_id AND work_face_id = d.drivingface_id AND ve.vehicle_id = v.vehicle_id;";

    std::string Error;
    YADB::CDBResultSet DBRes;
    sDBConnPool.Query(sql.c_str(),DBRes,Error);
    int nCount = DBRes.GetRecordCount( Error );
    if (nCount < 1)
      log_error("init_sensor..failed[%s]", sql.c_str());

    while ( DBRes.GetNextRecod(Error) )
    {
        int32_t sensor_id  = 0;
        DBRes.GetField( "sensor_id",sensor_id, Error );

        int32_t data  = 0;
        DBRes.GetField( "data_source",data, Error );

        int32_t workfaceid  = 0;
        DBRes.GetField( "work_face_id",workfaceid, Error );

        std::string card_id;
        DBRes.GetField( "card_id",card_id, Error );
        double bx,by;
        DBRes.GetField( "base_point_x",bx, Error );
        DBRes.GetField( "base_point_y",by, Error );

        log_info("init sensor :workfaceid:%d,sensor_id:%d,data:%d,card:%s,(%.2f,%.2f)",workfaceid,sensor_id,data,card_id.c_str(),bx,by);
        if(data <= 0) continue;
        uint64_t cid = tool_other::card_id_to_u64(card_id);

        std::shared_ptr<card_sensor_mgr> tm=nullptr;
        auto iter = m_sensor_mgr.find(cid);
        if(iter != m_sensor_mgr.end())
          tm=iter->second;
        else
        {
            tm = std::make_shared<card_sensor_mgr>();
            m_sensor_mgr.insert({cid,tm});
        }
        point p(bx,by);
        tm->push(workfaceid,sensor_id,p,card_id);
    }
}
/************************************
//获取传感器数据,从数据库中
//每三分钟获取一次,判断其是否上升趋势。
//如果上升趋势,则标识正在掘进中。开始判断反向
 ************************************/
void reverse_alarm_business::run_sensor()
{
    static time_t time_interval=0;
    time_t t = time(NULL);
    if (t-time_interval>3*60)
    {
        time_interval =t;
        for(const auto &x:m_sensor_mgr)
          x.second->for_each();
    }
}

void card_sensor_mgr::for_each()
{
    for(const auto & cst:m_mgr)
    {
        auto cs = cst.second;
        if(cs->sensorId_list.empty())
          continue;
        char strsql[512]={0};
        snprintf(strsql,512, "SELECT data_value FROM his_sensor_data WHERE WHERE write_time > DATE_SUB(NOW(),INTERVAL 10 MINUTE) and sensor_id = %d ORDER BY write_time DESC LIMIT 3;",cs->sensorId_list[0]);
        std::string Error;
        YADB::CDBResultSet DBRes;
        sDBConnPool.Query(strsql,DBRes,Error);
        int nCount = DBRes.GetRecordCount( Error );
        if (nCount < 1)
        {
            log_warn("load_sensor_data..failed[%s]", strsql);
            continue;
        }

        double prenum=-1;
        double nrow=0;double sum=0;bool f=false;
        while ( DBRes.GetNextRecod(Error) )
        {
            double num  = 0;
            DBRes.GetField( "data_value",num, Error );

            if (point::eq(num,0,1e-10))continue; //0异常数据抛掉
            if(point::eq(prenum,-1,1e-10)){ //如果没有参考数据,则判断,如果有历史数据,用历史,没有则用第一个数据。
                if(cs->empty()) prenum=num; else prenum=cs->back();
            }
            if (prenum-num>0.1){ //异常数据 如果之前存在正常数据则继续,如果没有则本次不作参考。0.1暂定
                if(cs->empty()){
                    f=true;break;
                }
                else continue;
            }
            nrow++;sum+=num;        
        }
        if (!f && nrow!=0){
            double result=sum/nrow;
            log_info("reverse_alarm_push %s,%.3f",cs->card_id.c_str(),result);
            if(cs->push(result)){//满足三个并且呈现上升趋势
                log_info("reverse_alarm_up %s",cs->card_id.c_str());
                if (!cs->warning())
                  cs->set_true();//置true,主进程开始抓取数据。
            }
        }
        if (cs->timeout()){//时间满足,判断是否告警
            auto reader_it = sit_list::instance()->get(cs->reader_id());
            if (!reader_it){
                cs->clear_sensor();
                continue;
            }
            std::string msg;
            if(cs->check_location_reversal(msg) )//满足告警条件,查看是否已经存在告警,没有产生告警
            {
                log_info("reverse_alarm_create:%s",cs->card_id.c_str());
                //产生告警。
                //deal_readers_event(ET_READER_LOCATION_REVERSAL,true,reader_it->second);
                if(!cs->is_alarm)
                    event_tool::instance()->handle_event(OT_DEVICE_READER,ET_READER_LOCATION_REVERSAL,cs->reader_id(),cs->count,cs->sum,cs->is_alarm=true);
            }
            else  //不满足告警条件,查看是否已经存在告警,存在则取消告警。
            {
                log_info("reverse_alarm_delete:%s",cs->card_id.c_str());
                if(cs->is_alarm)
                    event_tool::instance()->handle_event(OT_DEVICE_READER,ET_READER_LOCATION_REVERSAL,cs->reader_id(),cs->count,cs->sum,cs->is_alarm=false);
                //补
                //deal_readers_event(ET_READER_LOCATION_REVERSAL,false,reader_it->second);
            }
            log_info("%s",msg.c_str());
            cs->clear_sensor();//清除数据,重新判断
        }
    }
}
/*****************************************
//当判断为反向后,则开始手机数据。
//在规定的时间内,记录反向的数量以及双天线数量。
//正常的数量n 总数量s 时长m(秒)
//n/s<0.2 && s/m>0.8则标识天线反向
 ****************************************/
void reverse_alarm_business::make_condition(uint64_t type,uint32_t id,int32_t antid,uint32_t ct,uint64_t tof,uint32_t sid)
{
    uint64_t cid = tool_other::type_id_to_u64(type,id);
    auto it = m_sensor_mgr.find(cid);
    if(it != m_sensor_mgr.end())
      it->second->make_condition(antid,ct,tof,sid);
}
void card_sensor_mgr::make_condition(int32_t antid,uint32_t ct,uint64_t tof,uint32_t sid)
{
    for(const auto x:m_mgr)
    {
        auto pdc =x.second;
        if (pdc->warning()){
            auto sit = sit_list::instance()->get(sid);
            point p0=(*sit)[0];point p1=(*sit)[1];
            if (!((*pdc)[0]==p0 && (*pdc)[1]==p1)){
                pdc->set(p0,p1,sid); 
                log_info("[reverse_alarm_start]%s,bigger:%d",pdc->card_id.c_str(),pdc->bigger);
            }
            log_info("[reverse_alarm_working]%s,ct:%d,antid:%d,dist:%.2f",pdc->card_id.c_str(),ct,antid,tof);
            pdc->make_reverse_condition(antid,ct,tof);
        }
    }
}
bool rear_end_collision_prevented_business::invalid_card(const std::shared_ptr<card_location_base> &c)
{
     bool f=false;
     uint64_t _now=time(0)*1000;
     uint64_t ti=c->time_();
     uint64_t t=_now>ti?_now-ti:ti-_now;
     if(t<45*1000 && !c->empty())
        f=true;
     return f;
}
void rear_end_collision_prevented_business::handle_message()
{
    time_t now = time(0);
    if(now-_time>3)
        _time=now;
    else
      return;
    auto it=m_v.cbegin();
    for (;it!=m_v.cend();it++)
    {
        auto c=*it;
        if(!invalid_card(c))continue;
        double map_scale = c->get_area_tool()->m_scale;
        for (auto prv_it=std::next(it);prv_it!=m_v.cend();++prv_it)
        {
            auto c2=*prv_it;
            if(!invalid_card(c2))continue;
            double dis = (*c).dist(*c2)*map_scale;
            log_info("vehicle_alarm stpe3 : cid1:%d,cid2:%d (%.2f,%.2f),(%.2f,%.2f) %.2f,%f",c->m_id,c2->m_id,c->x,c->y,c2->x,c2->y,dis,map_scale);
            if(dis>CYaSetting::m_sys_setting.rear_end_d)
              continue;
            //判断反向行驶,平行行驶,背离行驶的车辆
            uint64_t u1=tool_other::type_id_to_u64(c->m_type,c->m_id);uint64_t u2=tool_other::type_id_to_u64(c2->m_type,c2->m_id);
            if (!rear_end_arg_algo(u1,u2))
              continue;
            //
            std::string card1=tool_other::type_id_to_str(c->m_type,c->m_id);std::string card2=tool_other::type_id_to_str(c2->m_type,c2->m_id);
            vInfo v;
            v.push(card1,card2);
            std::string cardid=v.getKey();
            if(m_CloserVehicle.find(cardid) == m_CloserVehicle.end())
            {
                m_CloserVehicle.insert(std::make_pair(cardid,v));
                log_info("vehicle_alarm_insert %s",cardid.c_str());
            }
        }
    }
    auto it_cv=m_CloserVehicle.begin();
    for (;it_cv != m_CloserVehicle.end();)
    {
        vInfo & vinfo = it_cv->second;
        std::string vvid = it_cv->first;
        uint64_t u1=tool_other::card_id_to_u64(vinfo.m_cid[0]);
        uint64_t u2=tool_other::card_id_to_u64(vinfo.m_cid[1]);
        uint64_t t=now*1000;
        uint64_t ct=m_map[u1]._t ;uint64_t rt = t>ct?t-ct:ct-t;
        uint64_t ct_=m_map[u2]._t; uint64_t rt_ = t>ct_?t-ct_:ct_-t;
        std::hash<std::string> hsh;
        uint32_t id = hsh(vvid);
        if (rt>45*1000 || rt_>45*1000 )
        {
            log_info("vehicle_alarm_time_ %s,%u",vvid.c_str(),id);
            if (vinfo.is_alarm){
                event_tool::instance()->handle_event(OT_CARD,ET_VEHICLE_REAR_END,id,0,0,false,DT_COMMON,vvid);
            }
            it_cv = m_CloserVehicle.erase(it_cv);
            continue;
        }
        auto c=card_list::instance()->get(u1);
        if(!c) continue;
        double map_scale = c->get_area_tool()->m_scale;
        double dis = get_absolute_distance(u1,u2)*map_scale;
        log_info("vehicle_alarm_distance %s %f",vvid.c_str(),dis);

        time_t tt = time(0);
        if (dis>CYaSetting::m_sys_setting.rear_end_d ||!rear_end_arg_algo(u1,u2))
        {
            if (vinfo.backfired_start_time==0)
              vinfo.backfired_start_time=tt;
            vinfo.real_end_start_time=0;
            if (tt-vinfo.backfired_start_time>CYaSetting::m_sys_setting.rear_end_t)
            {
                log_info("vehicle_alarm_backfired_timeout %s,%u",vvid.c_str(),id);
                if(vinfo.is_alarm){
                    event_tool::instance()->handle_event(OT_CARD,ET_VEHICLE_REAR_END,id,CYaSetting::m_sys_setting.rear_end_d,dis,false,DT_COMMON,vvid);
                }
                it_cv = m_CloserVehicle.erase(it_cv);
                continue;
            }
        }
        else
        {
            vinfo.backfired_start_time =0;
            if (vinfo.real_end_start_time==0)
              vinfo.real_end_start_time=tt;
            if (tt-vinfo.real_end_start_time>CYaSetting::m_sys_setting.rear_end_t)
            {
                //  debug_print_syslog(0,"vehicle_alarm_real_end_timeout %s",vvid.c_str());
                if (!vinfo.is_alarm)
                {
                    log_info("vehicle_alarm_real_end_timeout_exec %s,%u",vvid.c_str(),id);
                    event_tool::instance()->handle_event(OT_CARD,ET_VEHICLE_REAR_END,id,CYaSetting::m_sys_setting.rear_end_d,dis,true,DT_COMMON,vvid);
                    vinfo.is_alarm = true;
                }
            }
        }
        ++it_cv;
    }

}
double rear_end_collision_prevented_business::get_absolute_distance(uint64_t c1,uint64_t c2)
{
    point pp1=m_map[c1]._p;point pp2=m_map[c2]._p;
    double arg1=m_map[c1]._arg;double arg2=m_map[c2]._arg;
    point p1(pp1.x,-pp1.y);
    point p2(pp2.x,-pp2.y);

    if (fabs(arg1-arg2)<1e-10)
      return p1.dist(p2);
    std::stringstream ss;
    std::vector<point> v = card_path::inst().find_path(p1,p2);
    point pt = p1;double dis = 0;
    for (const auto & p:v)
    {
        dis += pt.dist(p);
        pt=p;
    }
    dis += pt.dist(p2);
    return dis;
}
bool rear_end_collision_prevented_business::rear_end_arg_algo(uint64_t u1,uint64_t u2)
{
    point p_1=m_map[u1].last_p;point p_2=m_map[u2].last_p;
    double arg_1=m_map[u1]._arg;double arg_2=m_map[u2]._arg;
    line_v l_1=m_map[u1]._line;line_v l_2=m_map[u2]._line;
    std::string card1=tool_other::get_string_cardid(u1);std::string card2=tool_other::get_string_cardid(u2);
    if(p_1.empty() || p_2.empty())
      return false;
    log_info("[vehicle_alarm_begin_algo]%s&%s %f,%f (%s)(%s)--(%.2f,%.2f)(%.2f,%.2f)",card1.c_str(),card2.c_str(),arg_1,arg_2,l_1.to_string().c_str(),l_2.to_string().c_str(),p_1.x,p_1.y,p_2.x,p_2.y);
    if (point::eq(arg_1,0x12345678,1e-10) || point::eq(arg_2,0x12345678,1e-10))
    {
        log_info("[vehicle_alarm_invalid]%s&%s  %f,%f",card1.c_str(),card2.c_str(),arg_1,arg_2);
        return false;
    }
    if (!point::eq(arg_1,0,1e-10))
      if (fabs(fabs(arg_1-arg_2)-3.141593)< 0.000005)
      {
          log_info("[vehicle_alarm_opposite]%s&%s",card1.c_str(),card2.c_str());
          return false;
      }
    if (point::eq(arg_1,arg_2,1e-10))
    {
        double arg = std::arg(std::complex<double>(p_1.x,p_1.y)-std::complex<double>(p_2.x,p_2.y));
        if (!(fabs(fabs(arg)-fabs(arg_1))<1e-10 || fabs(fabs(arg)+fabs(arg_2)-3.141593)< 0.000005))
        {
            log_info("[vehicle_alarm_parallel]%s&%s  %f,%f()",card1.c_str(),card2.c_str(),arg,arg_1);
            return false;
        }
    }
    if(!point::eq(arg_1,arg_2,1e-10))
    {
        point p = l_1.line::crossing(l_2);
        if (p==l_1[1] || p==l_2[1])
        {
            log_info("[vehicle_alarm_point]%s&%s",card1.c_str(),card2.c_str());
            return true;
        }
        double arg1 = std::arg(std::complex<double>(p.x,p.y)-std::complex<double>(l_1[1].x,l_1[1].y));
        double arg2 = std::arg(std::complex<double>(p.x,p.y)-std::complex<double>(l_2[1].x,l_2[1].y));
        if (fabs(fabs(arg1-arg_1)-3.141593)<0.000005 && fabs(fabs(arg2-arg_2)-3.141593)<0.000005)
        {
            log_info(0,"[vehicle_alarm_backfired]%s&%s",card1.c_str(),card2.c_str());
            return false;
        }
    }
    log_info("[vehicle_alarm_end]%s&%s  %f,%f",card1.c_str(),card2.c_str(),arg_1,arg_2);
    return true;
}