import sys
import time
import math
class CompetitionSystem(object):
def __init__(self):
self.assign_final_num_generator = 1
self.teams = {}#存储队伍的信息
self.graph = {}#存储地图信息
def start(self):
self.welcome()
all_teams = self.load_team_file()
for x in all_teams:
self.teams[x.team_num] = x
self.graph = self.load_place_graph()
def run(self):#菜单
print("=====================================")
while True:
print(
"请选择:\n 1: 管理参赛队基本信息\n 2: 根据参赛队编号查询\n 3: 根据学校查询参赛队\n 4: 根据类别查询参赛队\n 5: 决赛叫号\n 6: 赛场导游\n 7: 退出")
menu = self.user_input_number(lambda x: 1 <= x and x <= 7)
if menu == 1:
self.manage_teams()
elif menu == 2:
self.query_by_team_num()
elif menu == 3:
self.query_by_school()
elif menu == 4:
self.query_by_category()
elif menu == 5:
self.final_competition()
elif menu == 6:
self.navigation()
else:
print("谢谢使用!")
sys.exit(0)
def welcome(self):
print('========== 欢迎来到设计大赛 ==========\n')
print('系统正在启动,请稍后......')
def manage_teams(self):#管理参赛队基本信息
while True:
print('\n管理参赛队信息:\n 1: 新增参赛队\n 2: 删除参赛队\n 3: 修改参赛队\n 4: 回到上一级')
menu = self.user_input_number(lambda x: 1 <= x and x <= 4)
if menu == 1:
print(' 请输入要新增的参赛队编号:')
team_num = self.user_input_number()
if team_num in self.teams:
sys.stderr.write('新增失败: 参赛队{0}已经存在\n'.format(team_num))
else:
print(' 请输入作品名称:')
work_name = self.user_input()
print(' 请输入学校名称:')
school = self.user_input()
print(' 请输入赛事类别:')
category_word = self.user_input()
print(' 请输入参赛者:')
who = self.user_input()
print(' 请输入指导教师:')
teacher = self.user_input()
team = Team(team_num, work_name, school, self.to_category(category_word), category_word, who,
teacher, self.next_assign_final_room(), self.next_assign_final_num())
self.teams[team_num] = team
print('新增成功')
elif menu == 2:
print(' 请输入要删除的参赛队编号:')
del_team_num = self.user_input_number()
if del_team_num in self.teams:
self.teams[del_team_num] = None
print('删除成功')
else:
print('删除失败')
elif menu == 3:
print(' 请输入要修改的参赛队编号:')
team_num = self.user_input_number()
if team_num in self.teams:
t = self.teams[team_num]
print(' 请输入作品名称:')
t.work_name = self.user_input()
print(' 请输入学校名称:')
t.school = self.user_input()
print(' 请输入赛事类别:')
t.category_word = self.user_input()
print(' 请输入参赛者:')
t.who = self.user_input()
print(' 请输入指导教师:')
t.teacher = self.user_input()
print('修改成功')
else:
sys.stderr.write('修改失败: 参赛队{0}不存在\n'.format(team_num))
else:
return
def query_by_team_num(self):#根据参赛队编号查询
print(' 请输入查询的参赛队编号:')
team_num = self.user_input_number()
self.create_binary_tree(team_num)
def query_by_school(self):#根据学校查找参赛队
print(' 请输入学校名称:')
school = self.user_input()
ts = list(filter(lambda x: x.school == school, self.teams.values()))
ts.sort(key=lambda x: x.category)
for t in ts:
print(
'{0} # {1} # {2} # {3} # {4} # {5}\n'.format(str(t.team_num), t.work_name,
t.school, t.category_word,
t.who, t.teacher))
def query_by_category(self):#根据类别查找参赛队
print(' 请输入参赛类别:')
category_word = self.user_input()
category = self.to_category(category_word)
ts = list(filter(lambda x: x.category == category, self.teams.values()))
ts.sort(key=lambda t: t.team_num)#按照队伍编号进行排序
for t in ts:
print(
'{0} # {1} # {2} # {3} # {4} # {5}\n'.format(str(t.team_num), t.work_name,
t.school, t.category_word,
t.who, t.teacher))
def final_competition(self):#叫号系统
print(' 现在开始叫号......')
time.sleep(1)
for i in range(1, 10):
print('请决赛室是{0}号的同学依次进场:'.format(i))
ts = list(filter(lambda x: x.final_room == i, self.teams.values()))#筛选出该决赛室的所有参赛队伍
ts.sort(key=lambda t: t.final_num)
for t in ts:
print(' 决赛号为{0}的同学进入{1}号决赛室'.format(t.final_num, i))
time.sleep(0.1)
print('所有决赛室号为{0}的同学已经进入该决赛室,现在开始决赛.....'.format(i))
time.sleep(5)
print("叫号结束")
def navigation(self):
print(' 1行政大楼:学校办公的地方\n'
' 2海韵湖:学校的标志性景点\n'
' 3图书馆:大部分学生自习的地方\n'
' 4东苑食堂:靠近图书馆的学生可以去这吃饭,有三楼可供选择\n'
' 5东区操场:学生运动的地方,大部分外国人在这运动\n'
' 6南门:可以从该门出校\n'
' 7文体中心:体育课学生上课的地方,有大量体育活动室\n'
' 8西区操场:学生踢足球的地方,也是大量户外活动举办的场所\n'
' 9经世楼:学生上课的大楼之一\n'
' 10文理大楼:学校的标志性建筑,是学校的最高建筑,其中有许多面向专门课程的教室\n')
print('请输入起始地点编号:')
from_num = self.user_input_number(lambda x: 1 <= x and x <= len(self.graph.nodes)) - 1
print('请输入目的地点编号:')
to_num = self.user_input_number(lambda x: 1 <= x and x <= len(self.graph.nodes)) - 1
self.graph.cal_dis(from_num, to_num)#调用cal_dis方法
def create_binary_tree(self, team_num):#创建一个二叉树
all_teams = self.load_team_file()
binary_tree = BinaryTree(all_teams)
node = binary_tree.search_by_team_num(team_num)#用于根据参赛队伍编号查找对应的参赛队伍节点
if node != None:
t = node.team
print('平均查找长度 ASL:{0}'.format(binary_tree.ASL))
print(
'{0} # {1} # {2} # {3} # {4} # {5}\n'.format(str(t.team_num), t.work_name,
t.school, t.category_word,
t.who, t.teacher))
else:
print('查找失败')
def user_input_number(self, f=lambda x: True):#获取用户输入的数字
return int(self.user_input(lambda x: x.isdigit() and f(int(x))))#判断用户输入是否是否满足条件
def user_input(self, f=lambda x: len(x) > 0):#确保用户输入的内容符合要求
while True:
line = sys.stdin.readline().strip()
if not f(line):
sys.stderr.write('输入不合法,请重新输入\n')
else:
return line
def next_assign_final_room(self):
return (self.assign_final_num_generator % 9) + 1#计算下一轮应该召集的决赛室编号
def next_assign_final_num(self):
self.assign_final_num_generator += 1#计算下一个编号
return self.assign_final_num_generator - 1
def load_team_file(self):#从磁盘中读取文件,并将其转化为一组Team对象
all_teams = []
with open('team.txt', 'r', encoding='GBK') as f:
title = f.readline()
if not title or title.startswith('参赛队编号') == False or len(title.split(' # ')) != 6:
sys.stderr.write('team.txt 不合法!\n')
sys.exit(-1)
else:
line = f.readline()
while line:
line = line.strip()
if len(line) > 0:
one_team = line.split(' # ')
one_team = [word.strip() for word in one_team]
if len(one_team) != 6 or not one_team[0].isdigit():
sys.stderr.write('team.txt 内容不合法: "{0}"\n'.format(line))
sys.exit(-1)
all_teams.append(#添加到列表 all_teams
Team(int(one_team[0]), one_team[1], one_team[2], self.to_category(one_team[3]), one_team[3],
one_team[4], one_team[5], self.next_assign_final_room(), self.next_assign_final_num()))
line = f.readline()
return all_teams
def load_place_graph(self):#读取文件,构建Graph对象
graph = Graph()#创建新的Graph对象
with open('place.txt', 'r', encoding='GBK') as f:
self.until_read_line(f, lambda line: line == '#<places>')
f.readline()
line = f.readline().strip()
while line != '#<distances>':
parts = line.strip().split(' ')
place = {'num': int(parts[0].strip()), 'name': parts[1].strip(), 'intra': parts[2].strip()}
graph.nodes[place['num']] = place
line = f.readline().strip()
graph.init_edges()
line = f.readline().strip()
while line != '#<end>':
parts1 = line.split('<->')
parts2 = parts1[1].strip().split(':')
from_num = int(parts1[0].strip())
to_num = int(parts2[0].strip())
distance = int(parts2[1].strip())
graph.add_edge(from_num - 1, to_num - 1, distance)
line = f.readline().strip()
return graph
def until_read_line(self, f, func=lambda line: True):#用于读取的每一行将其传递给 func 函数进行判断
line = f.readline()
while line:
line = line.strip()
if func(line):
return
sys.stderr.write('文件不合法\n')
sys.exit(-1)
def to_category(self, category_word):#根据类别查询参赛队
# 2023年大赛分设11个大类,分别是:
# (1)软件应用与开发;
# (2)微课与教学辅助;
# (3)物联网应用;
# (4)大数据应用;
# (5)人工智能应用;
# (6)信息可视化设计;
# (7)数媒静态设计;
# (8)数媒动漫与短片;
# (9)数媒游戏与交互设计;
# (10)计算机音乐创作;
# (11)国际生“学汉语,写汉字”
if category_word.find('应用') >= 0 and category_word.find('开发') >= 0:
return 1
if category_word.find('微课') >= 0 or category_word.find('课程') >= 0 or category_word.find(
'在线') >= 0 or category_word.find('小学') >= 0:
return 2
if category_word.find('物联网') >= 0:
return 3
if category_word.find('大数据') >= 0:
return 4
if category_word.find('人工智能') >= 0 or category_word.find('AI') >= 0:
return 5
if category_word.find('可视化') >= 0:
return 6
if category_word.find('漫画') >= 0 or category_word.find('静态') >= 0 or category_word.find('平面设计') >= 0:
return 7
if category_word.find('动画') >= 0 or category_word.find('片') >= 0 or category_word.find('视频') >= 0:
return 8
if category_word.find('游戏') >= 0 or category_word.find('交互') >= 0:
return 9
if category_word.find('音乐') >= 0:
return 10
if category_word.find('汉字') >= 0 or category_word.find('汉语') >= 0:
return 11
else:
return 1
class Graph(object):
MAX = 99999999#用于表示两个节点间无连线
def __init__(self):
self.nodes = {}
self.edges = []
def init_edges(self):
self.edges = [[Graph.MAX for col in range(len(self.nodes))] for row in range(len(self.nodes))]
#edges列表中的所有元素初始化为一个较大的数,用于表示两个节点之间没有连线
def add_edge(self, from_num, to_num, distance):#添加边
self.edges[from_num][to_num] = distance
self.edges[to_num][from_num] = distance
def cal_dis(self, from_num, to_num):#计算最短路径,使用Dijkstra算法计算从起点到终点的最短路径
dis = self.edges[from_num].copy()
path = self.edges[from_num].copy()
for i in range(len(path)):
path[i] = from_num if self.edges[from_num][i] < Graph.MAX else -1
visited = [False for i in range(len(self.nodes))]
visited[from_num] = True#表示起点已经被访问
dis[from_num] = 0
for i in range(len(self.nodes)):#遍历所有节点,找到距离起点最近的节点u,并将该节点标记为visited
min = Graph.MAX
u = from_num
for j in range(len(self.nodes)):
if not visited[j] and dis[j] <= min:
min = dis[j]
u = j
visited[u] = True
for j in range(len(self.nodes)):#更新起点到其他节点的距离和路径信息
if not visited[j] and dis[j] > dis[u] + self.edges[u][j]:
dis[j] = dis[u] + self.edges[u][j]
path[j] = u
path_result = []
#使用深度优先算法to_path_result
self.to_path_result(from_num, to_num, path, path_result)#使用递归的方式
print('从{0}到{1}的最短路径计算结果:'.format(from_num + 1, to_num + 1))
print(' 最短路径长度{0}米'.format(dis[to_num]))
print(' 最短路径的节点编号依次是: {0}'.format(list(reversed(path_result))))
def to_path_result(self, from_num, to_num, path, path_result):#深度优先算法,算出起点到终点的路径该如何走
path_result.append(to_num + 1)
if from_num != to_num:
self.to_path_result(from_num, path[to_num], path, path_result)
class Team(object):#定义一个代表参赛队的类
def __init__(self, team_num, work_name, school, category, category_word, who, teacher, final_room, final_num):
self.team_num = team_num
self.work_name = work_name
self.school = school
self.category = category
self.category_word = category_word
self.who = who
self.teacher = teacher
self.final_room = final_room
self.final_num = final_num
def is_final_competition(self, final_room, final_num): # 判断是否被叫到
return final_room == self.final_room and final_num == self.final_num
class BinaryNode(object):#二叉树的结点
def __init__(self, team, parent=None):
self.team = team
self.parent = parent
self.left = None
self.right = None
def insert(self, team):#插入一个节点,用于接收一个参数team
if self.team.team_num > team.team_num:
if self.left == None:
self.left = BinaryNode(team, self)
else:
self.left.insert(team)
else:
if self.right == None:
self.right = BinaryNode(team, self)
else:
self.right.insert(team)
class BinaryNode(object):#二叉树的结点
def __init__(self, team, parent=None):
self.team = team
self.parent = parent
self.left = None
self.right = None
def insert(self, team):#插入一个节点,用于接收一个参数team
if self.team.team_num > team.team_num:
if self.left == None:
self.left = BinaryNode(team, self)
else:
self.left.insert(team)
else:
if self.right == None:
self.right = BinaryNode(team, self)
else:
self.right.insert(team)
class BinaryNode(object):#二叉树的结点
def __init__(self, team, parent=None):
self.team = team
self.parent = parent
self.left = None
self.right = None
def insert(self, team):#插入一个节点,用于接收一个参数team
if self.team.team_num > team.team_num:
if self.left == None:
self.left = BinaryNode(team, self)
else:
self.left.insert(team)
else:
if self.right == None:
self.right = BinaryNode(team, self)
else:
self.right.insert(team)
class BinaryNode(object):#二叉树的结点
def __init__(self, team, parent=None):
self.team = team
self.parent = parent
self.left = None
self.right = None
def insert(self, team):#插入一个节点,用于接收一个参数team
if self.team.team_num > team.team_num:
if self.left == None:
self.left = BinaryNode(team, self)
else:
self.left.insert(team)
else:
if self.right == None:
self.right = BinaryNode(team, self)
else:
self.right.insert(team)
class BinaryTree(object):#创建二叉树
def __init__(self, all_teams):
all_teams.sort(key=lambda t: t.team_num)
self.levels = [0 for i in range(int(math.log(len(all_teams) + 1, 2)) + 2)]#算出二叉树的深度
self.root_node = self.create(all_teams, 0, len(all_teams), 1)
self.ASL = 0
for i in range(len(self.levels)):
self.ASL += i * self.levels[i]
self.ASL = self.ASL / len(all_teams)
def search_by_team_num(self, team_num):#表示要查找的队伍编号
node = self.root_node
while node != None:
if node.team.team_num == team_num:
return node
elif node.team.team_num > team_num:
node = node.left
else:
node = node.right
return None
def insert(self, team):#表示要插入的队伍
self.root_node.insert(team)
def create(self, all_teams, low, high, level):
self.levels[level] += 1#当前节点所处的层数加1
mid = int((low + high) / 2)#根节点
node = BinaryNode(all_teams[mid])
node.left = None if mid == low else self.create(all_teams, low, mid, level + 1)#左子树为空
node.right = None if mid == high - 1 else self.create(all_teams, mid + 1, high, level + 1)
return node
if __name__ == "__main__":
cs = CompetitionSystem()
cs.start()
cs.run()
以上的按队伍编号查找求平均查找长度有错误,正确的可以看上一个发布的代码,那个是正确的