#include <string.h>
#include <map>
#include <stdio.h>
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
map<long,Number> num;
/**
* 用分隔符解析字符串
*/
void splitToArray(const std::string &src, const std::string &sep, std::vector<std::string> &destArray, bool filtEmpty = false)
{
if (src.empty())
{
return;
}
std::string::size_type posBegin = 0;
std::string::size_type posEnd = src.find(sep);
std::string value;
while (posEnd != std::string::npos)
{
value = src.substr(posBegin, posEnd - posBegin);
if (!(filtEmpty && value.empty()))
{
destArray.push_back(value);
}
posBegin = posEnd + 1;
posEnd = src.find(sep, posBegin);
}
value = src.substr(posBegin, src.size() - posBegin);
if (!(filtEmpty && value.empty()))
{
destArray.push_back(value);
}
}
/**
* 号码解析:把文件中读取到的一条号码记录解析成一个结构体
*/
RET_ERRORCODE parseNumber(const char* record, Number& number)
{
if ((NULL == record) || (strlen(record) == 0))
{
return E001;
}
std::string numberRecord(record);
std::vector<std::string> recordArray;
std::string::size_type posBegin = 0;
std::string::size_type posEnd = numberRecord.find("\r\n");
//去掉回车换行
if (posEnd != std::string::npos)
{
numberRecord = numberRecord.substr(0, posEnd);
}
else
{
//去掉换号
posEnd = numberRecord.find("\n");
if (posEnd != std::string::npos)
{
numberRecord = numberRecord.substr(0, posEnd);
}
}
//获取|分隔符分割的数据
splitToArray(numberRecord, "|", recordArray);
//合法数据只有6个字段
if (recordArray.size() != 6)
{
return E004;
}
strcpy_s(number.id, recordArray[0].c_str());
number.price = (float)atof(recordArray[1].c_str());
strcpy_s(number.brand, recordArray[2].c_str());
number.status = atoi(recordArray[3].c_str());
strcpy_s(number.customer, recordArray[4].c_str());
number.time = atoi(recordArray[5].c_str());
return E001;
}
long tolong(const char *p)
{
int i;
long r=0;
for (i = 0; i < 11; i++)
{
r += p[i] - 48;
r = r * 10;
}
return r;
}
/**
* 初始化:使用初始化指令让系统重新完成初始化,各条记录(如号码记录)清空,时间状态初始化等。
*/
RET_ERRORCODE initSys()
{
num.clear();
initTimeSeconds();
return E001;
}
/**
* 加载号码:读取numbers.txt格式的数据文件,加载所有号码信息到系统中。
*/
RET_ERRORCODE loadNumbers(const char* fileName)
{
if (fileName[0] == 0)
return E002;
ifstream infile(fileName);
RET_ERRORCODE ret;
if (!infile.is_open())
{
return E003;
}
Number tem;
string s;
while (getline(infile, s))
{
ret=parseNumber(s.data(),tem);
if (ret == E004)
{
infile.close();
return E004;
}
num[tolong(tem.id)] = tem;
}
infile.close(); //关闭文件输入流
return E001;
}
/**
* 查询:号码信息查询。
*/
RET_ERRORCODE queryNumber(const Number& number, Number numbers[], int& count)
{
int i = 0,j = 0;
int numsize = num.size();
int *tem=new int[numsize]();
map<long, Number>::iterator it;
if (number.id[0] == 0)
;
else
{
for (i = 0,it=num.begin(); i < numsize&&it!=num.end(); i++,it++)
if (strcmp(number.id, it->second.id) != 0)
tem[i] = 1;
}
if (number.price == 0)
;
else
{
for (i = 0, it = num.begin(); i < numsize&&it != num.end(); i++, it++)
if(number.price != it->second.price)
tem[i] = 1;
}
if (number.time == 0)
;
else
{
for (i = 0, it = num.begin(); i < numsize&&it != num.end(); i++, it++)
if (number.time != it->second.time)
tem[i] = 1;
}
if (number.status == 0)
;
else
{
for (i = 0, it = num.begin(); i < numsize&&it != num.end(); i++, it++)
if (number.status != it->second.status)
tem[i] = 1;
}
if (number.brand[0] == 0)
;
else
{
for (i = 0, it = num.begin(); i < numsize&&it != num.end(); i++, it++)
if (strcmp(number.brand, it->second.brand) != 0)
tem[i] = 1;
}
for (i = 0,it=num.begin(); i < numsize && j< count; i++,it++)
if (tem[i] == 0)
numbers[j++] = it->second;
count = j;
delete[] tem;
return E001;
}
/**
* 随机选号:根据品牌,随机选取未被预定的号码,供客户选择
*/
RET_ERRORCODE randomPick(const char* brand, const int randNumber, Number number[], int& count)
{
Number serch;
int j = 0;
serch.id[0] = 0;
serch.price = 0;
strcpy(serch.brand, brand);
serch.time = 0;
Number *tem=new Number[count];
queryNumber(serch, tem, count);
for (int i = 0; i < count && j<randNumber; i++)
{
if (tem[i].status == 0)
number[j++] = tem[i];
}
count = j;
delete[] tem;
return E001;
}
void findbra(const char* brand, Number number[], int& count)
{
int i = 0, j = 0;
int numsize = num.size();
int *tem = new int[numsize]();
map<long, Number>::iterator it;
for (i = 0, it = num.begin(); i < numsize&&it != num.end(); i++, it++)
if (strcmp(brand, it->second.brand) != 0)
tem[i] = 1;
for (i = 0, it = num.begin(); i < numsize && j < count; i++, it++)
if (tem[i] == 0)
number[j++] = it->second;
count = j;
delete[] tem;
}
/**
* 自助选号:根据选号表达式,返回满足条件的未被预定的号码列表
*/
RET_ERRORCODE selfServicePick(const char* brand, const char* expression1, const char* expression2, Number number[], int& count)
{
char s;
int i = 0, k = 0;
Number *t = new Number[num.size()];
findbra(brand, number, count);
if (expression1[0] == 0)
;
else
{
for (i = 0; i < count; i++)
for (k = 0; k < 11; k++)
if (expression1[k] != number[i].id[k] && expression1[k] != '*')
t[i] = number[i];
}
if (expression2[0] == 0)
;
else
{
std::string numberRecord(expression2);
std::vector<std::string> recordArray;
splitToArray(numberRecord, "!", recordArray, true);
for (int j = 0; j < recordArray.size(); j++)
{
s = recordArray[j][0];
for (i = 0; i < count; i++)
if (s == number[i].id[10])
t[i] = number[i];
}
}
for (k = 0,i = 0; i < count; i++)
if (t[i].id[0] == 0)
number[k++] = t[i];
count = k;
delete[] t;
return E001;
}
/**
* 锁定:根据号码信息,对号码资源进行锁定(预定)。
*/
RET_ERRORCODE lockNumber(const Number& number)
{
map<long, Number>::iterator it;
it = num.find(tolong(number.id));
if (it == num.end())
return E007;
if (it->second.status == 1)
return E005;
it->second.status = 1;
it->second.time = getCurrentTimeSeconds() + ONE_DAY_SECONDS;
return E001;
}
/**
* 解锁:根据时间对预定号码到期时间未处理的号码资源进行解锁,供其他客户选择。
*/
RET_ERRORCODE unLockNumber()
{
map<long, Number>::iterator it;
for (it = num.begin(); it != num.end(); it++)
if (it->second.time < getCurrentTimeSeconds())
{
it->second.customer[0] = 0;
it->second.status = 0;
it->second.time = 0;
}
return E001;
}
void selfServiceTerminal_TestCase()
{
//1 系统初始化
RET_ERRORCODE ret = initSys();
assert(ret == E001);
//2 正常号码加载
ret = loadNumbers("../output/template/numbers.txt");
assert(ret == E001);
//3 文件名校验
ret = loadNumbers("");
assert(ret == E002);
//4 号码格式校验
ret = loadNumbers("../output/template/numbers_err.txt");
assert(ret == E004);
ret = loadNumbers("../output/template/numbers_rep.txt");
assert(ret == E001);
//5 号码查询/重复检验
Number inNumber;
strcpy_s(inNumber.id, "13900000168");
Number number[10];
int numberCount = 10;
ret = queryNumber(inNumber, number, numberCount);
assert(ret == E001);
assert(numberCount == 1);
assert(number[0].price == 500);
//6 随机选号
int randNumber = 3;
Number selectNumber[10];
int selectNumberCount = 10;
ret = randomPick("2", randNumber, selectNumber, selectNumberCount);
assert(ret == E001);
assert(selectNumberCount == 3);
//7 自助选号规则
Number selfNumber[10];
int selfNumberCount = 10;
ret = selfServicePick("2", "", "", selfNumber, selfNumberCount);
assert(ret == E001);
assert(selfNumberCount == 4);
//8 自助选号规则
ret = selfServicePick("2", "**7********", "!3!4", selfNumber, selfNumberCount);
assert(ret == E001);
assert(selfNumberCount == 2);
//9 锁定号码
ret = lockNumber(inNumber);
assert(ret == E001);
numberCount = 10;
inNumber.status = 1;
ret = queryNumber(inNumber, number, numberCount);
assert(ret == E001);
assert(numberCount == 1);
assert(number[0].status == 1);
assert(number[0].time == ONE_DAY_SECONDS);
//10 解锁预约号码
ret = initSys();
assert(ret == E001);
ret = loadNumbers("../output/template/numbers_unlock.txt");
assert(ret == E001);
//系统时间调整
elapseTimeSeconds(86400);
ret = unLockNumber();
assert(ret == E001);
inNumber.id[0] = 0;
inNumber.status = 0;
inNumber.brand[0] = 0;
numberCount = 10;
ret = queryNumber(inNumber, number, numberCount);
assert(ret == E001);
assert(numberCount == 1);
for (int i = 0; i < numberCount; ++i)
{
assert(number[i].status == 0);
assert(number[i].time == 0);
}
}