上一章+Excel數據分析實戰:軍事體能考核成績評定(三)男子引體向上計算成功實現了男子引體向上計算的功能,這一章我們實現女子單杠考試成績的計算計算年齡精確到秒的軟件,女子的單杠考核與男子的引體向上不同,為曲臂懸垂計時。
一、基本情況
通過分析女子單杠“成績計算標準表”,發現標準表也只是參照標準表,不是連續的全覆蓋,比如標準中24歲以下,只規定了曲臂懸垂1分10秒的成績為100分,1分6秒的成績為95分,那么中間的情況多少分呢?
女子單杠成績計算標準表
還是只能是我們根據公平原則去補充,在1分6秒、1分10秒之間去取平均分,數據量比較小,我也選擇手工計算,補充到成績計算標準表里,精確到小數點后一位。
女子單杠曲臂懸垂補充標準
當然根據標準,40歲以上組織俯臥撐考核替代曲臂懸垂考核。
女子俯臥撐補充標準
同樣,通過的模塊讀取補充成績計算標準表中的數據,制成 {原始單杠成績:分數} 格式的字典,以供主程序查詢出換算成績,再寫入成績表的對應位置中。
二、代碼實現
女子單杠考核原始成績統計表
這里在原始成績統計表中增加了“性別”這一項,在主程序中就要更改其它項目的相應序號。而且曲臂懸垂的原始成績為時間格式,輸入類似0:01:20的格式,這樣在程序中才能比較大小。
1.計算年齡作為復用頻率較高的函數,我把它放入單獨的模塊中,文件命名為.py。
# 根據出生日期計算年齡,精確到天
# born參數為datetime.datetime類型
import datetime as dt
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
復制
2.計算女子曲臂懸垂的模塊我命名為.py,首先是讀取出標準數據,制成 {原始曲臂懸垂時長:分數} 格式的字典。每一個字典是分年齡段的,字典“age24”指24歲以下的數據字典,“”指25~27歲的數據字典。
下面代碼中有一些注釋掉的語句,是為了中間測試,并且有大部分已經被刪除了,因為實際編程過程中,都是每一小段代碼都要測試的,成功了才能繼續下步,就像大樓一層一層的建起來。
# 女性單杠曲臂懸垂的成績計算,40歲及以上計算俯臥撐個數
# 從工作表“女子單桿曲臂懸垂標準”中讀取數據
import openpyxl
import datetime as dt
class Flex_arm_hang_standard_data():
wb=openpyxl.load_workbook('通用訓練課目考核成績計算.xlsx')
ws_flex_arm_hang = wb['女子單桿曲臂懸垂標準']

age24={} # 24歲以下,{原始懸垂時間:分數}
age25_27={} # 25~27歲,{原始懸垂時間:分數}
age28_30={}
age31_33={}
age34_36={}
age37_39={}
rngs1 = ws_flex_arm_hang.iter_rows(min_row=3,max_row=43,min_col=1,max_col=8)
# 生成{原始懸垂時間:分數}的字典
for row in rngs1:
#print([c.value for c in row])
age24[row[1].value]=row[0].value
age25_27[row[3].value]=row[2].value
age28_30[row[4].value]=row[2].value
age31_33[row[5].value]=row[2].value
age34_36[row[6].value]=row[2].value
age37_39[row[7].value] = row[2].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_flex_arm_hang.iter_rows(min_row=49,max_row=69,min_col=1,max_col=14)
# 生成{原始俯臥撐個數:分數}的字典
for row in rngs2:
#print([c.value for c in row])
age40_42[row[1].value]=row[0].value
age43_45[row[3].value]=row[2].value
age46_48[row[5].value]=row[4].value
age49_51[row[7].value]=row[6].value
age52_54[row[9].value]=row[8].value
age55_57[row[11].value] = row[10].value
age58_59[row[13].value] = row[12].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)
復制
3.設計曲臂懸垂的計算函數(),首先IF語句判定年齡;再判定是否小于55分的曲臂懸垂時長或者俯臥撐個數,是則返回0分;再判定是否大于100分的曲臂懸垂時長或者俯臥撐個數,是則按超出100分的方法計算;最后55分~100分的情況,查詢字典,返回對應分數。對于一類人員65分及格、二類人員60分及格的情況,后期在主程序里考慮。
def flex_arm_hang_performance_computing(self,age,original_amount):
'''根據年齡,實際單杠曲臂懸垂時間,計算所得分數'''
if age <= 24:
# 判定是否小于55分的曲臂懸垂時長,是則返回0分
if original_amount < dt.time(0,0,30):
return 0
# 判定是否大于100分的曲臂懸垂時長,是則按照引體向上超出100分計算,每遞增5秒加一分
elif original_amount > dt.time(0,1,10):
return 100+((original_amount.hour-0)*3600+(original_amount.minute-1)*60+original_amount.second-10)/5
elif dt.time(0,0,30) <= original_amount <= dt.time(0,1,10) :

return self.age24[original_amount]
elif 25 <= age <= 27:
if original_amount < dt.time(0,0,29):
return 0
elif original_amount > dt.time(0,1,5):
return 100+((original_amount.hour-0)*3600+(original_amount.minute-1)*60+original_amount.second-5)/5
elif dt.time(0,0,29) <= original_amount <= dt.time(0,1,5) :
return self.age25_27[original_amount]
elif 28 <= age <= 30:
if original_amount < dt.time(0,0,27):
return 0
elif original_amount > dt.time(0,1,3):
return 100+((original_amount.hour-0)*3600+(original_amount.minute-1)*60+original_amount.second-3)/5
elif dt.time(0,0,27) <= original_amount <= dt.time(0,1,3) :
return self.age28_30[original_amount]
elif 31 <= age <= 33:
if original_amount < dt.time(0,0,24):
return 0
elif original_amount > dt.time(0,1,0):
return 100+((original_amount.hour-0)*3600+(original_amount.minute-1)*60+original_amount.second-0)/5
elif dt.time(0,0,24) <= original_amount <= dt.time(0,1,00) :
return self.age31_33[original_amount]
elif 34 <= age <= 36:
if original_amount < dt.time(0,0,21):
return 0
elif original_amount > dt.time(0,0,57):
return 100+((original_amount.hour-0)*3600+(original_amount.minute-0)*60+original_amount.second-57)/5
elif dt.time(0,0,21) <= original_amount <= dt.time(0,0,57) :
return self.age34_36[original_amount]
elif 37 <= age <= 39:
if original_amount < dt.time(0,0,18):
return 0
elif original_amount > dt.time(0,0,54):
return 100+((original_amount.hour-0)*3600+(original_amount.minute-0)*60+original_amount.second-54)/5
elif dt.time(0,0,18) <= original_amount <= dt.time(0,0,54) :
return self.age37_39[original_amount]
# 大于40歲時計算俯臥撐
elif 40 <= age <= 42:
if original_amount < 13:
return 0
elif original_amount > 30:
return 100 + (original_amount-30)*0.5
elif 13 <= original_amount <= 30 :
return self.age40_42[original_amount]
elif 43 <= age <= 45:

if original_amount < 11:
return 0
elif original_amount > 27:
return 100 + (original_amount-27)*0.5
elif 11 <= original_amount <= 27 :
return self.age43_45[original_amount]
elif 46 <= age <= 48:
if original_amount < 11:
return 0
elif original_amount > 24:
return 100 + (original_amount-24)*0.5
elif 11 <= original_amount <= 24 :
return self.age46_48[original_amount]
elif 49 <= age <= 51:
if original_amount < 9:
return 0
elif original_amount > 21:
return 100 + (original_amount-21)*0.5
elif 9 <= original_amount <= 21 :
return self.age49_51[original_amount]
elif 52 <= age <= 54:
if original_amount < 8:
return 0
elif original_amount > 19:
return 100 + (original_amount-19)*0.5
elif 8 <= original_amount <= 19 :
return self.age52_54[original_amount]
elif 55 <= age <= 57:
if original_amount < 7:
return 0
elif original_amount > 17:
return 100 + (original_amount-17)*0.5
elif 7 <= original_amount <= 17 :
return self.age55_57[original_amount]
elif 58 <= age <= 59:
if original_amount < 3:
return 0
elif original_amount > 16:
return 100 + (original_amount-16)*0.5
elif 3 <= original_amount <= 16 :
return self.age58_59[original_amount]
if __name__ == "__main__": #本模塊測試
flex_arm_hang_std_data = Flex_arm_hang_standard_data()
result = flex_arm_hang_std_data.flex_arm_hang_performance_computing(59,15)

#print(type(dt.time(0, 1, 10).second))
print(result)
復制
4.對主程序.py進行修改,如果原始成績不為空,則進行分數計算,再將分數寫入表中換算成績的相應位置。這里增加了出生日期格式異常檢測,性別判斷。如果性別為“男”,則進行男子引體向上或俯臥撐成績計算;如果性別為“女”,則進行女子曲臂懸垂或俯臥撐成績計算
import openpyxl
import datetime as dt
from calculate_age import calculate_age # 導入年齡計算模塊
from pullup_standard_data import Pullup_standard_data # 導入男子引體向上成績計算模塊
from flex_arm_hang import Flex_arm_hang_standard_data # 導入女子單杠曲臂懸垂的成績計算模塊
wb=openpyxl.load_workbook('通用訓練課目考核成績計算.xlsx')
ws_training_performance = wb['體能考核成績']
pullup_sd = Pullup_standard_data() #實例化男子引體向上成績計算
flexarmhang_sd = Flex_arm_hang_standard_data() #實例化女子單杠曲臂懸垂成績計算
rngs = ws_training_performance.iter_rows(min_row=6)
for row in rngs:
gender = row[4].value # 性別
pullup = row[11].value # 單杠原始數量
if row[5].value:
if not type(row[5].value) is dt.datetime: # 核查日期格式
print('序號%d %s 的出生日期格式不對'%(row[0].value,row[1].value))
# print(row[5].value)
else:
age = calculate_age(row[5].value) # 由出生日期計算年齡,精確到天
row[6].value = age
if gender == '男' : # 男子引體向上或俯臥撐成績計算
if row[6].value != None:
row[12].value = pullup_sd.pullup_performance_computing(age, pullup)
print(row[0].value,pullup,row[12].value)
elif gender == '女': # 女子曲臂懸垂或俯臥撐成績計算
if row[6].value != None:
row[12].value = flexarmhang_sd.flex_arm_hang_performance_computing(age, pullup)
print(row[0].value,pullup, row[12].value)
else: #核查性別
print('序號%d %s 的性別填寫錯誤'%(row[0].value,row[1].value))
wb.save('計算結果.xlsx')
復制
運行后,生成文件“計算結果.xlsx”如下:
女子單杠考核計算結果
到此計算年齡精確到秒的軟件,我們成功實現了女子單杠考核成績計算的功能。
原創不易,有償下載,請多支持: 軍事體能考核成績評定系統下載
軍事體能考核成績評定系統全套源碼下載