for t in time_points: for start, end, rate in time_ranges: if start <= t < end: arrivals.append(np.random.poisson(rate)) break else: arrivals.append(0) # 不在任何时间段内的情况
from collections import OrderedDict import random total_seconds=120*60# 7200秒 second_dict=OrderedDict([(second,0) for second inrange(total_seconds)])
# 随机分配人数到各秒 for minute inrange(120): minute_people=arrivals[minute] start_second=minute * 60
# 为每个人随机分配秒数(0-59,对应start_second到start_second+59) for _ inrange(minute_people): random_second=random.randint(0, 59) total_second=start_second+random_second second_dict[total_second]+=1 for i inrange(7200,7260):#为了保证全部学生都能取到菜,将食堂开放时间延长一分钟 second_dict[i]=0
options=["快餐","面食","特色菜"] weights=[0.2,0.3,0.5] defchoose_window(student,windows_list,students_list): choice=random.choices(options,weights=weights,k=1)[0]#按照权重随机选择一个 student.chosen_dish=choice window_signs=[]#提供这个菜品的窗口 window_queue_num=[]#对应排队人数 change_flag=0#是否改变选择的标志 for window in windows_list: if window.open==False:#如果没开门不管他 continue if window.dish==choice:#如果提供对应菜品 window_signs.append(window.sign)#记录对应的窗口号与队列人数 window_queue_num.append(len(window.queue)) iflen(window_signs)==0: change_flag=1 student.chosen_times+=1 iflen(window_signs)!=0:#如果存在卖他的窗口 queue_num_min=min(window_queue_num)#找到排队人数最少的窗口号 sign_min=window_signs[window_queue_num.index(queue_num_min)] if queue_num_min<10:#如果最小值小于10,就排这一条 student.chosen_window=sign_min windows_list[sign_min-1].queue.append(student) windows_list[sign_min-1].queue_num+=1 if queue_num_min==10:#如果最小值为10,说明全部排满了 change_flag=1 student.chosen_times+=1
if change_flag==1:#如果确实发生了第二次选择 change_flag=0 options_tool=["快餐","面食","特色菜"] weights_tool=[0.2,0.3,0.5] index_tool=options_tool.index(choice)#在剩下的两个菜中选 del options_tool[index_tool] del weights_tool[index_tool] choice=random.choices(options_tool,weights=weights_tool,k=1)[0] student.chosen_dish=choice window_signs=[]#提供这个菜品的窗口 window_queue_num=[]#对应排队人数 for window in windows_list: if window.open==False:#如果没开门不管他 continue if window.dish==choice:#如果提供对应菜品 window_signs.append(window.sign)#记录对应的窗口号与队列人数 window_queue_num.append(len(window.queue)) iflen(window_signs)==0: change_flag=2 student.chosen_times+=1 iflen(window_signs)!=0:#如果存在卖他的窗口 queue_num_min=min(window_queue_num)#找到排队人数最少的窗口号 sign_min=window_signs[window_queue_num.index(queue_num_min)] if queue_num_min<10:#如果最小值小于10,就排这一条 student.chosen_window=sign_min windows_list[sign_min-1].queue.append(student) windows_list[sign_min-1].queue_num+=1 if queue_num_min==10:#如果最小值为10,说明全部排满了 change_flag=2 student.chosen_times+=1
if change_flag==2:#如果发生了第三次选择 change_flag=0 index_tool=options_tool.index(choice)#在剩下的两个菜中选 del options_tool[index_tool] del weights_tool[index_tool] choice=options_tool[0] student.chosen_dish=choice window_signs=[]#提供这个菜品的窗口 window_queue_num=[]#对应排队人数 for window in windows_list: if window.open==False:#如果没开门不管他 continue if window.dish==choice:#如果提供对应菜品 window_signs.append(window.sign)#记录对应的窗口号与队列人数 window_queue_num.append(len(window.queue)) iflen(window_signs)==0: change_flag=3 student.chosen_times+=1 iflen(window_signs)!=0:#如果存在卖他的窗口 queue_num_min=min(window_queue_num)#找到排队人数最少的窗口号 sign_min=window_signs[window_queue_num.index(queue_num_min)] if queue_num_min<10:#如果最小值小于10,就排这一条 student.chosen_window=sign_min windows_list[sign_min-1].queue.append(student) windows_list[sign_min-1].queue_num+=1 if queue_num_min==10:#如果最小值为10,说明全部排满了 change_flag=3 student.chosen_times+=1
if change_flag==3:#如果第三次仍然没有选择 student.is_angry=True students_list.append(student)
windows_set=[ [(True,"快餐"),(True,"快餐"),(True,"快餐"),(True,"快餐"),(True,"面食"),(True,"面食"),(True,"特色菜"),(True,"特色菜"),(False,""),(False,"")], [(True,"快餐"),(True,"快餐"),(True,"快餐"),(True,"快餐"),(True,"面食"),(True,"面食"),(True,"特色菜"),(True,"特色菜"),(True,"快餐"),(True,"特色菜")], [(True,"快餐"),(True,"快餐"),(True,"快餐"),(False,""),(True,"面食"),(True,"面食"),(True,"面食"),(False,""),(False,""),(False,"")]]#代入理论值结果 windows_list=[]#初始化 students_list=[] for i inrange(10): window=Window(windows_set[0][i][0],windows_set[0][i][1],i+1) windows_list.append(window) print(windows_list)
import matplotlib matplotlib.use('QtAgg') from matplotlib import pyplot as plt import numpy as np %matplotlib qt5 x2=[] y2=[] plt.ion() for i inrange(7260): '''首先更新所有窗口的状态''' for window in windows_list: if i==1800: window.change_flag=1 if i==5400: window.change_flag=2 if (not window.iscooking):#对于没有在做菜的窗口 if window.change_flag!=0:#如果到了改菜品的时候 window.change(windows_set[window.change_flag][window.sign-1][0],windows_set[window.change_flag][window.sign-1][1])#更改的菜品以及窗口开关 if (window.dish=="特色菜"and special_dish_store==0):#仅针对换菜事件,如果换的是特色菜但是没库存了,关闭窗口 window.open=False window.iscooking=False window.queue_num=0 if window.iscooking:#做菜的窗口,菜的剩余时间-1 window.cooktimeleft-=1 if window.cooktimeleft==0:#如果时间剩余0,即完成了菜,那么队列排队人数-1 student_tool=window.queue.pop(0) window.queue_num-=1 student_tool.over_time=i#队首的学生记录结束时间 student_tool.chosen_dish=window.dish#记录最后拿到的菜品是window此时正在卖的菜品 students_list.append(student_tool)#完成的学生存入另一个列表中用于计算满意度
if window.change_flag!=0:#如果完成后到了改菜品的时候了 window.change(windows_set[window.change_flag][window.sign-1][0],windows_set[window.change_flag][window.sign-1][1])#更改的菜品以及窗口开关 if (window.dish=="特色菜"and special_dish_store==0):#仅针对换菜事件,如果换的是特色菜但是没库存了,关闭窗口 window.open=False window.iscooking=False window.queue_num=0 if window.open==False:#如果关窗口了 for student in window.queue:#原队列所有人重新选择 choose_window(student,windows_list,students_list) window.queue=[]
iflen(window.queue)==0:#检查走后是否还剩下人 window.iscooking=False else: if window.dish=="特色菜":#检查窗口是否提供特色菜 if special_dish_store!=0:#如果是而且库存没空 window.cooktimeleft=dishes[window.dish][1]#重置做饭时间 special_dish_store-=1#减一份库存 if special_dish_store==0:#如果库存空了 window.open=False window.iscooking=False window.queue_num=0#关窗口 for student in window.queue: choose_window(student,windows_list,students_list) window.queue=[] if window.dish!="特色菜":#非特色菜 window.cooktimeleft=dishes[window.dish][1]#重置做饭时间 '''再更新新学生''' if second_dict[i]==0: print(f"第{int(i/60)}分{i%60}秒,有0个学生") if second_dict[i]!=0:#如果有新客人来 print(f"第{int(i/60)}分{i%60}秒,有{second_dict[i]}个学生") for _ inrange(second_dict[i]): student=Student(i) choose_window(student,windows_list,students_list) if student.is_angry: print(" 有一位学生感到愤怒!") print(f" 有一位同学去了{student.chosen_window}窗口,选择的菜品是{student.chosen_dish}")
x1=[1,2,3,4,5,6,7,8,9,10] y1=[] for window in windows_list: y1.append(len(window.queue))
for window in windows_list:#针对新上人的窗口 if window.open: if (not window.iscooking andlen(window.queue)!=0): window.iscooking=True if window.dish=="特色菜":#对特色菜窗口 if special_dish_store==0:#如果库存为0关门,队伍重新选窗口 window.open=False window.iscooking=False window.queue_num=0 for j inrange(len(window.queue)): choose_window(window.queue[j],windows_list,students_list) window.queue=[] if special_dish_store!=0: special_dish_store-=1 window.cooktimeleft=dishes[window.dish][1]#重置做饭时间 else: window.cooktimeleft=dishes[window.dish][1]#重置做饭时间 c=0 for student in students_list: if student.is_angry: c-=dishes[student.chosen_dish][0] else: c+=dishes[student.chosen_dish][0]*60/(student.over_time-student.arrive_time) x2.append(i) y2.append(c) plt.subplot(1,2,2) plt.clf() # 清除之前画的图 plt.plot(x2,y2) #画出当前x列表和y列表中的值的图形 plt.pause(0.001) #暂停一段时间,不然画的太快会卡住显示不出来
(↑这两段纯手搓,我都不知道当时怎么有这么大的耐心)最后输出一下满意度和特色菜库存
1 2 3 4 5 6 7 8 9
c=0 plt.plot(x2,y2) for student in students_list: if student.is_angry: c-=dishes[student.chosen_dish][0] else: c+=dishes[student.chosen_dish][0]*60/(student.over_time-student.arrive_time) print(c) print(special_dish_store)