/*********************************************************************
程序名: 银行业务模拟
版权: java.KFC.CrazyThursday.BalanceNotEnoughException:
at function getWechatBalance(), getAlipayBalance();
作者: 筱鸣@1522
日期: 2022-10-29 17:03
说明: 模拟简单的银行业务
*********************************************************************/
#include <bits/stdc++.h>
using namespace std;
class Customer {
private:
int id;//没用到
int enterTime;//从9点开始以秒计算的客户进入时间
//比如10:00:00进入就是3600,09:10:05就是605
public:
Customer() {
}
Customer(int id, int enterTime) {
this->id = id;
this->enterTime = enterTime;
}
int getId() {
return this->id;
}
int getEnterTime() {
return this->enterTime;
}
} c[105];
class Staff {
public:
int remainTime = -1;//每个员工对于当前业务的处理时间
int count = 0;//经手多少人
queue<Customer> q;//员工面前的队伍
} s[5];
void timePrint(int seconds) {//以秒数直接计算当前时间并输出
int h = 0;
int m = 0;
int s = 0;
m = seconds / 60;
s = seconds % 60;
h = m / 60;
m %= 60;
printf("[%02d:%02d:%02d]:", h + 9, m, s);
}
void timeFilePrint(int seconds, FILE *stream) {//同上,往文件里输出的版本
int h = 0;
int m = 0;
int s = 0;
m = seconds / 60;
s = seconds % 60;
h = m / 60;
m %= 60;
fprintf(stream, "[%02d:%02d:%02d]:", h + 9, m, s);
}
bool cmp(Customer a, Customer b) {//使用STL的sort给客户进门的时间不降序排列
return a.getEnterTime() < b.getEnterTime();
}
void createConditions() {
for (int i = 1; i <= 100; i++) {
srand(c[i - 1].getEnterTime() + time(0));
//种子越怪越好
c[i] = Customer(i, rand() % 28801);
//rand()生成的数字最大为65536 让客户在自09:00:00起28800秒,即17:00:00内进来
}
sort(c + 1, c + 101, cmp);
}
pair<int, int> scanQueue() {
int lowValue = 114514;//跑完循环后出现最少排队人数
int window = -1;//客户选择的窗口
//经过测试,生成进入时间时,基本上不会出现"客户蜂拥而至"且"某时段员工处理能力极快"导致某队伍极长且存在窗口空置的情况
for (int i = 1; i <= 4; i++) {
if (s[i].q.size() < lowValue) {
lowValue = s[i].q.size();
window = i;
}
}
pair<int, int>p(window, lowValue);//返回一个为要选择的窗口,另一个是当前选择的窗口的人数
return p;
}
//17:00:00为28800秒
int main() {
FILE *stream;
//打开文件
stream = fopen("RECORD.txt", "w");//在该cpp文件所在的位置生成结果
if (stream != NULL) {
int total = 0;
double waitSecond = 0;//总客户等待时间,用于程序末尾的统计
double staySecond = 0;//总客户逗留时间,用于程序末尾的统计
createConditions();//创造条件
int currentCustomer = 1;//指向客户列表的当前客户
for (int i = 0; i <= 30000 || currentCustomer < 101; i++) {
//时间宽裕至3w秒 一旦客户列表读完(100人)就跳出循环
//每秒可能有三种操作:一种是有人进来;一种是有人出去;一种是啥也没发生
for (int j = 1; j <= 4; j++) { //有人离开
if (s[j].remainTime == 0) {//员工处理完了
timePrint(i);
printf("%02d 号客户在 %d 号窗口办理完成\n", s[j].q.front().getId(), j);
//s[j]是员工列表,每个员工有一个队列q,q的第一个元素的id是正在办理的客户的id;
timeFilePrint(i, stream);
fprintf(stream, "%02d 号客户在 %d 号窗口办理完成\n", s[j].q.front().getId(), j);
s[j].count++;//经手一个人
s[j].q.pop();//当前客户离开
if (s[j].q.size()) {//如果现在的队列里还有人那就上来办业务
timePrint(i);
printf("%02d 号客户在 %d 号窗口开始办理\n", s[j].q.front().getId(), j);
timeFilePrint(i, stream);
fprintf(stream, "%02d 号客户在 %d 号窗口开始办理\n", s[j].q.front().getId(), j);
srand( time(0) + s[j].q.front().getEnterTime());
s[j].remainTime = rand() % (20 * 60 + 1);//给当前的顾客决定一个avg=10min的处理时间
}
}
}
while (i == c[currentCustomer].getEnterTime()) { //当前时间正好和列表中第一个客户的时间相等,就放他进来
pair<int, int> choice = scanQueue();//找到客户想去的队伍和他目标队伍的人数
if (choice.second == 0) { //无需排队直接办理
//s[选择的窗口].q.push(这一名客户)
s[choice.first].q.push(c[currentCustomer]);
timePrint(i);
printf("%02d 号客户在 %d 号窗口开始办理\n", s[choice.first].q.front().getId(), choice.first);
timeFilePrint(i, stream);
fprintf(stream, "%02d 号客户在 %d 号窗口开始办理\n", s[choice.first].q.front().getId(), choice.first);
srand(time(0) + c[currentCustomer].getEnterTime());
s[choice.first].remainTime = rand() % (20 * 60 + 1);//给当前的顾客决定一个avg=10min的处理时间
} else { //排队
s[choice.first].q.push(c[currentCustomer]);
timePrint(i);
printf("%02d 号客户在 %d 号窗口排队\n", c[currentCustomer].getId(), choice.first);
timeFilePrint(i, stream);
fprintf(stream, "%02d 号客户在 %d 号窗口排队\n", c[currentCustomer].getId(), choice.first);
}
currentCustomer++;//这个客户进来了,换下一个客户急
}
for (int j = 1; j <= 4; j++) {//无事发生
s[j].remainTime--;//每个窗口剩余处理秒数减少1
if (s[j].q.size() > 1) {
waitSecond += (s[j].q.size() - 1);
staySecond += s[j].q.size();
}
}
}
for (int i = 1; i <= 4; i++) {
total += s[i].count;
// cout << s[i].remainTime << endl;
}
printf("今日共办理%d件业务\n", total);
fprintf(stream, "今日共办理%d件业务\n", total);
for (int i = 1; i <= 4; i++) {
printf("%d号窗口办理%d件\n", i, s[i].count);
fprintf(stream, "%d号窗口办理%d件\n", i, s[i].count);
}
printf("客户平均等待%.2lfmin\n", waitSecond / (60 * 100));
fprintf(stream, "客户平均等待%.2lfmin\n", waitSecond / (60 * 100));
printf("客户平均逗留%.2lfmin\n", staySecond / (60 * 100));
fprintf(stream, "客户平均逗留%.2lfmin\n", staySecond / (60 * 100));
}
fclose(stream);
return 0;
}
调试记录:
好家伙你们这是只排队不办事啊;
自9时起199小时...