123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- #pragma DISPATCH_USER_CLASS_H
- #include <time.h>
- #include <iostream>
- #include "../error_code/error_code.h"
- #include "database_controller.h"
- class User_class
- {
- const int MAX_SQL_COMMAND_SIZE = 512U; // 最大sql命令长度
- const int DAYS_MIN_TIMES = 4; // 判断用户类型的最小认定次数
- const int MAX_SAVE_DAYS = 10*24*60*60; // 保留数据库表单时限
- const int WORKER_IN_TIME[4] = {6, 7, 9, 10}; // 通勤入库时间函数变量
- const int WORKER_OUT_TIME[4] = {16, 17, 19, 20}; // 通勤出库时间函数变量
- const int WORKER_PARK_TIME[2] = {3, 4}; // 通勤停车时长函数变量
- const int RESIDENT_IN_TIME[4] = {17, 18, 23, 24}; // 居民入库时间函数变量
- const int RESIDENT_OUT_TIME[4] = {5, 6, 8, 9}; // 居民出库时间函数变量
- const int RESIDENT_PARK_TIME[2] = {4, 5}; // 居民停车时长函数变量
- enum USER_CLASS {
- USER_CLASS_UNKNOW = 0, // 临时用户
- USER_CLASS_WORKER, // 通勤用户
- USER_CLASS_RESIDENT, // 居民用户
- USER_CLASS_STUDY,
- USER_CLASS_MON_CARD, // 月卡用户
- USER_CLASS_NO_STUDY,
- };
- private:
- /* data */
- public:
- User_class();
- ~User_class();
- public:
- static void test();
- bool is_vip(const std::string& car_number);
- Error_manager add_vip(std::string& car_number, time_t& start_time, time_t& end_time);
- Error_manager delete_vip(std::string& car_number);
- Error_manager update_vip(std::string& car_number, time_t start_time, time_t end_time);
- Error_manager update_table();
- Error_manager update_table(int save_time);
- int type(const std::string& car_number);
- Error_manager type(const std::string& car_number, int& user_type);
- Error_manager creat_table(const time_t& in_time, const time_t& out_time, const std::string& car_number);
- private:
- int time_t_2_int(const time_t& time);
- Error_manager statistics_table();
- Error_manager get_user_type(const std::string& car_number, int& user_type);
- double fuzzy_model_I(double a, double b, double x);
- double fuzzy_model_II(double a, double b, double c, double d, double x);
- private:
- std::string m_car_number;
- };
- User_class::User_class() {}
- User_class::~User_class() {}
- bool User_class::is_vip(const std::string& car_number)
- {
- boost::shared_ptr<sql::ResultSet> result;
- std::string sql_command = "select * from vip where car_number = '" + car_number + "'";
- Error_manager ec = Database_controller::get_instance_pointer()->sql_query(sql_command, result);
- if(result->next()) {
- time_t t = time(NULL);
- if (result->getInt("end_time") > time_t_2_int(t))
- return true;
- }
- return false;
- }
- Error_manager User_class::add_vip(std::string& car_number, time_t& start_time, time_t& end_time)
- {
- if (!is_vip(car_number)) {
- char sql_command[MAX_SQL_COMMAND_SIZE] = "";
- sprintf(sql_command, "insert into vip (start_time, end_time, car_number) values (%d, %d, '%s')\n", time_t_2_int(start_time), time_t_2_int(end_time), car_number.c_str());
- Error_manager ec = Database_controller::get_instance_pointer()->sql_insert(sql_command);
- } else {
- return update_vip(car_number, start_time, end_time);
- }
- return SUCCESS;
- }
- Error_manager User_class::delete_vip(std::string& car_number)
- {
- std::string sql_command = "delete from vip where car_number = '" + car_number + "'";
- Error_manager ec = Database_controller::get_instance_pointer()->sql_delete(sql_command);
- return SUCCESS;
- }
- Error_manager User_class::update_vip(std::string& car_number, time_t start_time, time_t end_time)
- {
- char sql_command[MAX_SQL_COMMAND_SIZE] = "";
- sprintf(sql_command, "update vip set start_time = %d, end_time = %d where car_number = '%s'", time_t_2_int(start_time), time_t_2_int(end_time), car_number.c_str());
- Error_manager ec = Database_controller::get_instance_pointer()->sql_update(sql_command);
- return SUCCESS;
- }
- int User_class::time_t_2_int(const time_t& time) {
- tm* tt = localtime(&time);
- return (tt->tm_year + 1900)*10000 + (tt->tm_mon + 1)*100 + tt->tm_mday;
- }
- // 对存储的近期用户数据进行综合统计
- Error_manager User_class::statistics_table()
- {
- // 删除旧的统计结果
- boost::shared_ptr<sql::ResultSet> result;
- std::string sql_command = "delete from user_class where record_time = 99999999 "; // 特殊id,用作记录统计数据;
- Error_manager ec = Database_controller::get_instance_pointer()->sql_delete(sql_command);
- std::cout << "---Debug--- delete statistics ec = " << ec << std::endl;
- // 获取全部车牌号
- sql_command = "select distinct car_number from user_class";
- ec = Database_controller::get_instance_pointer()->sql_query(sql_command, result);
- std::cout << "---Debug--- ec = " << ec << std::endl;
- // 对每个车牌重新判断用户类型,并添加到数据库
- while (result->next())
- {
- int user_type = USER_CLASS_UNKNOW;
- get_user_type(result->getString("car_number"), user_type);
- sql_command = "insert into user_class (record_time, user_type, car_number) values (99999999, " + std::to_string(user_type) + ", '" + result->getString("car_number") + "')";
- Database_controller::get_instance_pointer()->sql_insert(sql_command);
- }
- // 从数据库获取vip车辆信息,判断是否过期
- time_t t = time(NULL);
- sql_command = "select * from vip where end_time > " + std::to_string(time_t_2_int(t));
- ec = Database_controller::get_instance_pointer()->sql_query(sql_command, result);
- std::cout << "---Debug--- ec = " << ec << std::endl;
- while (result->next())
- {
- int user_type = USER_CLASS_UNKNOW;
- sql_command = "insert into user_class (record_time, user_type, car_number) values (99999999, " + std::to_string(USER_CLASS_MON_CARD) + ", '" + result->getString("car_number") + "')";
- ec = Database_controller::get_instance_pointer()->sql_insert(sql_command);
- }
-
- return ec;
- }
- // 第一类点对点模糊模型 a、b、按照从小到大顺序输入
- double User_class::fuzzy_model_I(double a, double b, double x)
- {
- if (x > a && x <= b)
- return 1.00 * ((x - a)/(b - a));
- else if (x > b)
- return 1;
- else
- return 0;
- }
- // 第二类点对点模糊模型 a、b、c、d、按照从小到大顺序输入
- double User_class::fuzzy_model_II(double a, double b, double c, double d, double x)
- {
- if (x > a && x <= b)
- return 1.00 *((x - a)/(b - a));
- else if (x > b && x <= c)
- return 1;
- else if (x > c && x <= d)
- return 1.00 * ((d - x)/(d - c));
- else
- return 0;
- }
- int User_class::type(const std::string& car_number) {
- int user_type = 0;
- type(car_number, user_type);
- return user_type;
- }
- Error_manager User_class::type(const std::string& car_number, int& user_type)
- {
- boost::shared_ptr<sql::ResultSet> result;
- std::string sql_command = "select * from user_class where record_time = 99999999 and car_number = '" + car_number + "'";
- Error_manager ec = Database_controller::get_instance_pointer()->sql_query(sql_command, result);
- if (result->next())
- {
- user_type = result->getInt("user_type");
- }
- return ec;
- }
- // 从数据库获取用户历史停留信息,并跟据信息判断用户类型;
- Error_manager User_class::get_user_type(const std::string& car_number, int& user_type)
- {
- int worker = 0, resident = 0;
- boost::shared_ptr<sql::ResultSet> result;
- std::string sql_command = "select * from user_class where user_type > 0 and user_type < 3 and car_number = '" + car_number + "'";
- Error_manager ec = Database_controller::get_instance_pointer()->sql_query(sql_command, result);
- while (result->next())
- {
- if (USER_CLASS_WORKER == result->getInt("user_type"))
- {
- worker++;
- }
- else
- {
- resident++;
- }
- }
-
- if (worker >= DAYS_MIN_TIMES && worker >= resident)
- {
- user_type = USER_CLASS_WORKER;
- }
- else if (resident >= DAYS_MIN_TIMES)
- {
- user_type = USER_CLASS_RESIDENT;
- }
- else
- {
- user_type = USER_CLASS_UNKNOW;
- }
- return ec;
- }
- // 跟据今日时间信息,删除默认设置天数以前的表单数据,更新数据库。
- Error_manager User_class::update_table()
- {
- return update_table(MAX_SAVE_DAYS);
- }
- // 跟据今日时间信息,删除设置天数以前的表单数据,更新数据库。todo:数据库操作判断
- Error_manager User_class::update_table(int save_time)
- {
- printf("---Debug--- Begain update table.\n");
- time_t t_now = time(NULL) - save_time;
- std::string sql_command = "delete from user_class where record_time < " + std::to_string(time_t_2_int(t_now));
- Error_manager ec = Database_controller::get_instance_pointer()->sql_delete(sql_command);
- std::cout << "---Debug--- delete old ec = " << ec << std::endl;
- statistics_table();
- printf("---Debug--- update table over.\n");
- return ec;
- }
- // 通过传入的车辆入库、出库时间,计算隶属度,判断用户类型,然后存入到数据库;
- Error_manager User_class::creat_table(const time_t& in_time, const time_t& out_time, const std::string& car_number)
- {
- if(is_vip(car_number)) {
- return SUCCESS;
- }
- // 计算
- tm out = *localtime(&out_time);
- int user_type = USER_CLASS_UNKNOW;
- double parking_time = (out_time - in_time)/3600.00;
- double f_in = localtime(&in_time)->tm_hour + localtime(&in_time)->tm_min/60.00;
- double f_out = localtime(&out_time)->tm_hour + localtime(&out_time)->tm_min/60.00;
-
- // 根据入库时间计算隶属度
- double s_worker_in, s_worker_out, s_worker_park, s_resident_in, s_resident_out, s_resident_park;
- double s_worker, s_resident;
- s_worker_in = fuzzy_model_II(WORKER_IN_TIME[0], WORKER_IN_TIME[1], WORKER_IN_TIME[2], WORKER_IN_TIME[3], f_in);
- s_worker_out = fuzzy_model_II(WORKER_OUT_TIME[0], WORKER_OUT_TIME[1], WORKER_OUT_TIME[2], WORKER_OUT_TIME[3], f_out);
- s_worker_park = fuzzy_model_I(WORKER_PARK_TIME[0], WORKER_PARK_TIME[1], parking_time);
- s_resident_in = fuzzy_model_II(RESIDENT_IN_TIME[0], RESIDENT_IN_TIME[1], RESIDENT_IN_TIME[2], RESIDENT_IN_TIME[3], f_in);
- s_resident_out = fuzzy_model_II(RESIDENT_OUT_TIME[0], RESIDENT_OUT_TIME[1], RESIDENT_OUT_TIME[2], RESIDENT_OUT_TIME[3], f_out);
- s_resident_park = fuzzy_model_I(RESIDENT_PARK_TIME[0], RESIDENT_PARK_TIME[1], parking_time);
- s_worker = s_worker_in + s_worker_out + s_worker_park;
- s_resident = s_resident_in + s_resident_out + s_resident_park;
- // 根据隶属度判断用户类型
- if (s_worker >= s_resident && s_worker > 1.5)
- {
- user_type = USER_CLASS_WORKER;
- }
- else if (s_resident >= s_worker && s_resident > 1.5)
- {
- user_type = USER_CLASS_RESIDENT;
- }
- // 存储车牌、用户类型、日期、到sql
- char sql_command[MAX_SQL_COMMAND_SIZE] = "";
- sprintf(sql_command, "insert into user_class (car_number, record_time, user_type) values ('%s', %d, %d)",
- car_number.c_str(), time_t_2_int(out_time), user_type);
- Error_manager ec = Database_controller::get_instance_pointer()->sql_insert(sql_command);
- return SUCCESS;
- }
- void User_class::test()
- {
- User_class user_class;
- user_class.update_table();
- int times = 0;
- while (true && ++times)
- {
- printf("-----> No.%d start <-----\n", times);
- // 随机车牌、入场时间、停车时间
- time_t a = time(NULL);
- tm *tt = localtime(&a);
- tt->tm_sec = rand() % 61;
- tt->tm_min = rand() % 61;
- tt->tm_hour = rand() % 25;
- tt->tm_mday -= rand()%11 ; // 随机日期,最近十天
- time_t in = mktime(tt);
- time_t out = in + rand()%(24*60*60 + 1); // 最长停留一天
- // std::string car_number = "鄂A" + std::to_string(rand()%90000 + 10000); // 车牌
- std::string car_number = "鄂A900" + std::to_string(rand()%90 + 10); // 车牌
- // std::string car_number = "鄂A98829";
- // 添加记录到表格
- user_class.creat_table(in, out, car_number);
- // 获取该车牌类型
- int user_type = user_class.type(car_number);
- std::cout << "---Debug--- " << car_number << " check user_type " << user_type << std::endl;
- time_t end = in + 30*24*60*60;
- if (user_type < USER_CLASS_STUDY && user_type > USER_CLASS_UNKNOW) {
- user_class.add_vip(car_number, in, end);
- } else if (user_type == USER_CLASS_MON_CARD) {
- user_class.update_vip(car_number, in, end);
- }
- printf("-----> No.%d end <-----\n", times);
-
- sleep(1);
- }
- }
|