前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python+Excel数据分析实战:军事体能考核成绩评定(三)男子引体向上计算

Python+Excel数据分析实战:军事体能考核成绩评定(三)男子引体向上计算

原创
作者头像
张国平
修改2021-02-14 15:15:38
1.6K0
修改2021-02-14 15:15:38
举报
文章被收录于专栏:张国平_玩转树莓派

一、基本情况

通过分析男子引体向上“成绩计算标准表”,发现标准表只是参照标准表,不是连续的全覆盖,比如标准中24岁以下,只规定了单杆30个100分,27个95分,那么28/29个的情况多少分呢?

男子引体向上成绩计算标准表
男子引体向上成绩计算标准表

只能是我们根据公平原则去补充,在30/27之间去取平均分,数据量比较小,为加快程序运行速度,我选择手工计算,补充到成绩计算标准表里,精确到小数点后一位。

男子单杠补充标准表
男子单杠补充标准表

当然根据标准,40岁以上组织俯卧撑考核替代引体向上考核。

男子俯卧撑补充标准表
男子俯卧撑补充标准表

按照上一章Python+Excel数据分析实战:军事体能考核成绩评定(二)基本框架和年龄计算中的算法思路,制作完成绩计算标准表后,通过Python的openpyxl模块读取补充成绩计算标准表中的数据,制成 {原始单杠个数:分数} 格式的字典,以供主程序查询出换算成绩,再写入成绩表的对应位置中。

为什么要选择字典类型呢?这也是为什么选择Python语言的原因:

Python具有语法简洁、简单易学、代码高效、功能强大的特点,我个人认为,这要归功于列表(list)、字典(dict)、元组(tuple)和集合(set)这“四大金刚”。尽管整型(int)、浮点型(float)和字符串(str)也很重要,但这三种对象相对于其他编程语言来说,差异并不像“四大金刚”那样明显。可以毫不夸张地说,列表、字典、元组和集合代表了Python语言的核心和基础,同时也是Python的精髓所在。学会使用列表、字典、元组和集合,就意味着掌握了Python这门编程语言。

字典(dict)是Python用于存放具有映射关系的数据,相当于保存了两组数据,其中一组数据是关键数据,被称为 key;另一组数据可通过 key 来访问,被称为 value。列表是根据偏移量来读取的,而字典是根据键的Hash来读取的,字典的索引效率要远远大于列表。

从Python 3.6开始,字典是变成有顺序的了。你先插入键值对A,后插入键值对B,那么当你打印Keys列表的时候,你就会发现B在A的后面。这样使得索引的效率更高,而且后面计算3000米跑时,因数据太多不能手动补充标准数据时,要利用这个有序的特性,进行计算。

所以我设计了{原始单杠个数(key):分数(value)} 这样的字典格式来查询对应的分数。

二、代码实现

男子引体向上原始表
男子引体向上原始表

1.计算男子引体向上的模块我命名为pullup_standard_data.py,首先是读取出标准数据,制成 {原始单杠个数:分数} 格式的字典。每一个字典是分年龄段的,字典“age24”指24岁以下的{原始单杠个数:分数}字典,“age25_27”指25~27岁的{原始单杠个数:分数}字典。

下面代码中有一些注释掉的语句,是为了中间测试,并且有大部分已经被删除了,因为实际编程过程中,都是每一小段代码都要测试的,成功了才能继续下步,就像大楼一层一层的建起来。

代码语言:txt
复制
# 男性单杠引体向上的成绩计算,40岁及以上计算俯卧撑个数
# 从工作表“男子引体向上标准”中读取数据
import openpyxl
class Pullup_standard_data():
    wb=openpyxl.load_workbook('通用训练课目考核成绩计算.xlsx')
    ws_pullup = wb['男子引体向上标准']

    age24 = {}     # 24岁以下,{原始单杠个数:分数}
    age25_27 = {}  # 25~27岁,{原始单杠个数:分数}
    age28_30 = {}
    age31_33 = {}
    age34_36 = {}
    age37_39 = {}

    rngs1 = ws_pullup.iter_rows(min_row=3,max_row=23,min_col=1,max_col=9)
    # 生成{原始单杠个数:分数}的字典
    for row in rngs1:
        # print([c.value for c in row]) # 打印查看
        age24[row[1].value] = row[0].value  # row[0].value为分数,row[1].value为24岁以下单杠个数
        age25_27[row[2].value] = row[0].value
        age28_30[row[3].value] = row[0].value
        age31_33[row[4].value] = row[0].value
        age34_36[row[6].value] = row[5].value
        age37_39[row[8].value] = row[7].value
    # print('-----age24-----') # 打印数据以便检查
    # for m in age24.items():
    #     print(m)
    # print('-----age25_27-----')
    # for m in age25_27.items():
    #     print(m)
    # print('-----age28_30-----')
    # for m in age28_30.items():
    #     print(m)
    # print('-----age31_33-----')
    # for m in age31_33.items():
    #     print(m)
    # print('-----age34_36-----')
    # for m in age34_36.items():
    #     print(m)
    # print('-----age37_39-----')
    # for m in age37_39.items():
    #     print(m)

    age40_42 = {}  # 40岁以上,{原始俯卧撑个数:分数}
    age43_45 = {}  # 43~45岁,{原始俯卧撑个数:分数}
    age46_48 = {}
    age49_51 = {}
    age52_54 = {}
    age55_57 = {}
    age58_59 = {}

    rngs2 = ws_pullup.iter_rows(min_row=29,max_row=78,min_col=1,max_col=13)
    # 生成{原始俯卧撑个数:分数}的字典
    for row in rngs2:
        # print([c.value for c in row])
        age40_42[row[1].value] = row[0].value  # row[0].value为俯卧撑分数,row[1].value为俯卧撑个数
        age43_45[row[3].value] = row[2].value
        age46_48[row[5].value] = row[4].value
        age49_51[row[6].value] = row[4].value
        age52_54[row[8].value] = row[7].value
        age55_57[row[10].value] = row[9].value
        age58_59[row[12].value] = row[11].value

    # print('-----age40_42-----') # 打印数据以便检查
    # for m in age40_42.items():
    #     print(m)
    # print('-----age43_45-----')
    # for m in age43_45.items():
    #     print(m)
    # print('-----age46_48-----')
    # for m in age46_48.items():
    #     print(m)
    # print('-----age49_51-----')
    # for m in age49_51.items():
    #     print(m)
    # print('-----age52_54-----')
    # for m in age52_54.items():
    #     print(m)
    # print('-----age55_57-----')
    # for m in age55_57.items():
    #     print(m)
    # print('-----age58_59-----')
    # for m in age58_59.items():
    #     print(m)

2.设计计算函数pullup_performance_computing(),首先IF语句判定年龄;再判定是否小于55分的引体向上个数,是则返回0分;再判定是否大于100分的引体向上个数,是则按照引体向上超出100分,每递增一次增加1分计算;最后55分~100分的情况,查询字典,返回对应分数。对于一类人员65分及格、二类人员60分及格的情况,后期在主程序里考虑。

代码语言:txt
复制
#函数的参数,age是年龄,original_amount是原始引体向上的个数
    def pullup_performance_computing(self,age,original_amount):
        '''根据年龄,实际单杠个数,计算所得分数'''
        if age <= 24:  # 判定年龄
            if original_amount < 10:  # 判定是否小于55分的引体向上个数,是则返回0分
                return 0
            elif original_amount > 30:  # 判定是否大于100分的引体向上个数,是则按照引体向上超出100分计算
                return 100+original_amount-30
            elif 10 <= original_amount <= 30:  # 查询字典,返回对应分数
                return self.age24[original_amount]
        elif 25 <= age <= 27:
            if original_amount < 9:
                return 0
            elif original_amount > 28:
                return 100+original_amount-28
            elif 9 <= original_amount <= 28:
                return self.age25_27[original_amount]
        elif 28 <= age <= 30:
            if original_amount < 8:
                return 0
            elif original_amount > 26:
                return 100+original_amount-26
            elif 8 <= original_amount <= 26:
                return self.age28_30[original_amount]
        elif 31 <= age <= 33:
            if original_amount < 7:
                return 0
            elif original_amount > 23:
                return 100+original_amount-23
            elif 7 <= original_amount <= 23:
                return self.age31_33[original_amount]
        elif 34 <= age <= 36:
            if original_amount < 6:
                return 0
            elif original_amount > 20:
                return 100+original_amount-20
            elif 6 <= original_amount <= 20:
                return self.age34_36[original_amount]
        elif 37 <= age <= 39:
            if original_amount < 5:
                return 0
            elif original_amount > 17:
                return 100+original_amount-17
            elif 5 <= original_amount <= 17:
                return self.age37_39[original_amount]

        # 计算俯卧撑
        elif 40 <= age <= 42:
            if original_amount < 27:
                return 0
            elif original_amount > 73:
                return 100 + (original_amount - 73) * 0.5
            elif 27 <= original_amount <= 73:
                return self.age40_42[original_amount]
        elif 43 <= age <= 45:
            if original_amount < 26:
                return 0
            elif original_amount > 69:
                return 100 + (original_amount - 69) * 0.5
            elif 26 <= original_amount <= 69:
                return self.age43_45[original_amount]
        elif 46 <= age <= 48:
            if original_amount < 23:
                return 0
            elif original_amount > 68:
                return 100 + (original_amount - 68) * 0.5
            elif 23 <= original_amount <= 68:
                return self.age46_48[original_amount]
        elif 49 <= age <= 51:
            if original_amount < 21:
                return 0
            elif original_amount > 66:
                return 100 + (original_amount - 66) * 0.5
            elif 21 <= original_amount <= 66:
                return self.age49_51[original_amount]
        elif 52 <= age <= 54:
            if original_amount < 18:
                return 0
            elif original_amount > 65:
                return 100 + (original_amount - 65) * 0.5
            elif 18 <= original_amount <= 65:
                return self.age52_54[original_amount]
        elif 55 <= age <= 57:
            if original_amount < 16:
                return 0
            elif original_amount > 62:
                return 100 + (original_amount - 62) * 0.5
            elif 16 <= original_amount <= 62:
                return self.age55_57[original_amount]
        elif 58 <= age <= 59:
            if original_amount < 10:
                return 0
            elif original_amount > 44:
                return 100 + (original_amount - 44) * 0.5
            elif 10 <= original_amount <= 44:
                return self.age58_59[original_amount]

3.测试模块计算是否正确。

代码语言:txt
复制
if __name__ == "__main__":
    pup_std_data = Pullup_standard_data()
    result = pup_std_data.pullup_performance_computing(49,68) # 修改这里的参数即可测试不同情况
    print(result)

4.对主程序training_performance.py进行修改,如果引体向上的原始成绩不为空,则进行计算分数,再将分数写入表中引体向上的换算成绩的位置。

代码语言:txt
复制
import openpyxl
import datetime as dt
from pullup_standard_data import Pullup_standard_data

wb=openpyxl.load_workbook('通用训练课目考核成绩计算.xlsx')
ws_training_performance = wb['体能考核成绩']

pullup_sd = Pullup_standard_data()

def calculate_age(born):
    '''由出生日期计算年龄,精确到天'''
    today =dt.datetime.today()
    # today = today.replace(year=2020)
    # print(born)
    try:
        birthday = born.replace(year = today.year)
    except ValueError:
        # 出生日期是2月29日但若今年不是润年时,29要减1天为28天
        birthday = born.replace(year=today.year, day=born.day-1)
    # print(birthday)
    if birthday > today:
        return today.year - born.year - 1
    else:
        return today.year - born.year

rngs = ws_training_performance.iter_rows(min_row=6,min_col=2)
for row in rngs:
    if row[3].value:
        # print(row[3].value)
        age = calculate_age(row[3].value)    # 由出生日期计算年龄,精确到天
        row[4].value = age
        if row[9].value:  #如果引体向上的原始成绩不为空
            row[10].value = pullup_sd.pullup_performance_computing(row[4].value, row[9].value)
            print(row[9].value,row[10].value)

wb.save('计算结果.xlsx')

运行后,生成文件“计算结果.xlsx”如下:

男子引体向上计算结果
男子引体向上计算结果

到此,我们成功实现了男子引体向上计算的功能。

原创不易,有偿下载,请多支持:

军事体能考核成绩评定系统下载

军事体能考核成绩评定系统全套Python源码下载

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、基本情况
  • 二、代码实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档