def std_class_taken(self, weekday=[6], display='print_list', format='only_clsname'): wds = [] for wkdy in weekday: wds.append(days_calculate.num_to_ch(wkdy)) cls = [] fn_dir = os.path.join(self.std_info_dir, '学生信息表') for xls in os.listdir(fn_dir): if re.match(r'\d\d\d\d\w{1}-.*.xlsx$', xls) and xls[-8:-6] != '体验': for wd in wds: if xls[-7:-6] == wd: fn = os.path.join(fn_dir, xls) info_taken = WashData.class_taken(fn) cls.extend(info_taken['cls_taken']) cls_only_name = [item[9:] for item in cls] if format == 'only_clsname': cls = cls_only_name if display == 'print_list': for line in cls: print(line) return cls
def read_sig(self, weekday): # if weekday==2: # sigFile='2020乐高课程签到表(周二).xlsx' # elif weekday==6: # sigFile='2020乐高课程签到表(周六).xlsx' wd = days_calculate.num_to_ch(str(self.weekday)) if self.mode == 'tiyan': sigFile = os.path.join(self.std_sig_dir, self.place, '学生信息表', self.term + '-学生信息表(体验).xlsx') else: sigFile = os.path.join(self.std_sig_dir, self.place, '学生信息表', self.term + '-学生信息表(周' + wd + ').xlsx') stdInfo = pd.read_excel(os.path.join(self.stu_sigDir, sigFile), sheet_name='学生上课签到表', skiprows=1) stdInfo.rename(columns={'Unnamed: 0':'ID','Unnamed: 1':'机构','Unnamed: 2':'班级','Unnamed: 3':'姓名首拼', \ 'Unnamed: 4':'学生姓名','Unnamed: 5':'昵称','Unnamed: 6':'性别', \ 'Unnamed: 7':'上期课时结余','Unnamed: 8':'购买课时','Unnamed: 9':'目前剩余课时','Unnamed: 10':'上课数量统计汇总'},inplace=True) stdName = stdInfo['学生姓名'].tolist() stdPY = stdInfo['姓名首拼'].tolist() dictPY = {} for i, v in enumerate(stdName): dictPY[v] = stdPY[i] return [dictPY, stdName]
def draw_std_term_crs(self, std_name='韦宇浠', start_date='20200930', end_date='20210121', weekday='2'): std_name = std_name.strip() xls_name = os.path.join( self.std_dir, '2020乐高课程签到表(周' + days_calculate.num_to_ch(weekday) + ').xlsx') std_term_crs = WashData.std_term_crs(std_name=std_name, start_date=start_date, end_date=end_date, xls=xls_name) return std_term_crs
def read_scores(place_input,term,weekday): print('正在读取积分信息……',end='') wd=days_calculate.num_to_ch(str(weekday)) if self.mode=='tiyan': xls_this=os.path.join(self.std_sig_dir,self.place_input,'学生信息表',term+'-学生信息表(体验).xlsx') else: xls_this=os.path.join(self.std_sig_dir,self.place_input,'学生信息表',term+'-学生信息表(周'+wd+').xlsx') this_crs_score_info=WashData.std_score_this_crs(xls_this) df_this_crs_score,df_this_medals=this_crs_score_info['std_this_scores'],this_crs_score_info['medals_this_class'] place_dir=os.path.join(self.std_sig_dir,self.place_input) df_all_scores=WashData.std_all_scores(place_dir,plus_tiyan='no') print('完成') return {'this_score':df_this_crs_score,'this_medals':df_this_medals,'all_scores':df_all_scores}
def read_scores(place_input, term, weekday): print('正在读取积分信息……', end='') wd = days_calculate.num_to_ch(str(weekday)) xls_this = os.path.join(self.std_sig_dir, self.place_input, '学生信息表', term + '-学生信息表(周' + wd + ').xlsx') df_this_crs_score = WashData.std_score_this_crs(xls_this) place_dir = os.path.join(self.std_sig_dir, self.place_input) df_all_scores = WashData.std_all_scores(place_dir) print('完成') return { 'this_score': df_this_crs_score, 'all_scores': df_all_scores }
def __init__(self,weekday=2,term='2021春',place_input='001-超智幼儿园',mode=''): with open(os.path.join(os.path.dirname(os.path.realpath(__file__)),'LegoPosterAfterClass.config'),'r',encoding='utf-8') as f: lines=f.readlines() _line='' for line in lines: newLine=line.strip('\n') _line=_line+newLine config=json.loads(_line) self.mode=mode self.bg=config['导出文件夹'] self.bg=self.bg.replace('$',place_input) self.font_dir=config['字体文件夹'] self.default_font=config['默认字体'] self.crsList=config['课程信息表'] self.weekday=weekday self.term=term self.place_input=place_input self.std_sig_dir=config['学生签到表文件夹'] self.feedback_dir=config['课后照片及反馈文件夹'] wd=days_calculate.num_to_ch(str(weekday)) # self.eachStd=config['个别学员评语表'] # 个别学员评语表":"E:\\WXWork\\1688852895928129\\WeDrive\\大智小超科学实验室\\001-超智幼儿园\\每周课程反馈\\学员课堂学习情况反馈表.xlsx", cmt_table_dir=config['老师评语表文件夹'] if mode=='tiyan': self.eachStd=os.path.join(cmt_table_dir,place_input,'每周课程反馈',term+'-学生课堂学习情况反馈表(体验).xlsx') self.crsStudent=os.path.join(self.std_sig_dir,place_input,'学生信息表',term+'-学生信息表(体验).xlsx') else: self.eachStd=os.path.join(cmt_table_dir,place_input,'每周课程反馈',term+'-学生课堂学习情况反馈表(周'+wd+').xlsx') self.crsStudent=os.path.join(self.std_sig_dir,place_input,'学生信息表',term+'-学生信息表(周'+wd+').xlsx') self.picTitleDir=config['课程标题照片文件夹'] self.picTitleDir=self.picTitleDir.replace('$',place_input) self.picStdDir=config['学生照片文件夹'] self.picStdDir=self.picStdDir.replace('$',place_input) self.ConsDir=config['乐高图纸文件夹'] self.public_pic_dir=config['公共素材'] # if weekday==2: # self.crsStudent=config['学员签到表w2'] # elif weekday==6: # self.crsStudent=config['学员签到表w6'] self.PraiseTxt=['#同学在课堂上的表现非常棒!下次课加油!','下节课继续加油哦!','这节课很有收获,期待你下节课能有更大进步!','#同学的课堂表现非常棒,老师给你点个赞!'] self.picWid=425 #默认照片 self.comment_dis_line=25 #老师评论的行间距 self.comment_font_size=36 #老师评论的字体大小
def get_std_term_crs(self, std_name='韦宇浠', tb_list=[['2020秋', 'w2'], ['2021春', 'w4']], start_date='20200901', end_date='20210521'): print(' 正在读取 {} 的数据……'.format(std_name), end='') std_name = std_name.strip() std_term_crs = [] for tb in tb_list: term, weekday = tb[0], tb[1][-1] xls_name = os.path.join( self.std_dir, '学生信息表', term + '-学生信息表(周' + days_calculate.num_to_ch(weekday) + ').xlsx') std_term_crs_pre = WashData.std_term_crs(std_name=std_name, start_date=start_date, end_date=end_date, xls=xls_name) std_term_crs.append(std_term_crs_pre) # print(std_term_crs_pre) df_std_crss = [] df_total_crss = [] for df_std_term_crs in std_term_crs: df_std_crss.append(df_std_term_crs['std_crs']) df_total_crss.append(df_std_term_crs['total_crs']) df_std_crs = pd.concat(df_std_crss) df_std_crs.dropna(axis=0, inplace=True) df_std_crs.reset_index(inplace=True) df_total_crs = pd.concat(df_total_crss, ignore_index=True) df_std_crs.drop(df_std_crs[df_std_crs['课程名称'] == '请假'].index, inplace=True) # print(df_std_crs,'\n',df_total_crs) # print(df_total_crs) res_std_term_crs = { 'total_crs': df_total_crs, 'std_crs': df_std_crs, 'std_info': std_term_crs[0]['std_info'] } print('完成') return res_std_term_crs
def put(self,term='2021春',weekdays=[1,4],start_date='20210103',end_date='20210506'): xlsxs=[] print('\n正在生成学员列表……',end='') for wd in weekdays: wd=days_calculate.num_to_ch(wd) fn=term+'-'+'学生信息表(周'+wd+').xlsx' xls=os.path.join(self.sig_table_dir,self.place_input,'学生信息表',fn) xlsxs.append(xls) std_list=[] for xlsx in xlsxs: df=pd.read_excel(xlsx,sheet_name='学生档案表') std_name_pre=df['姓名首拼'].str.cat(df['学生姓名']) std_name=std_name_pre.to_list() std_list.extend(std_name) # print(std_list) print('完成\n') self.put_simple_marks(std_name_list=std_list,start_date=start_date,end_date=end_date) print('完成')
def read_excel(): crsFile=['课程信息表.xlsx','课程信息'] # if weekday==2: # stdFile=['2020乐高课程签到表(周二).xlsx','学生上课签到表'] # elif weekday==6: # stdFile=['2020乐高课程签到表(周六).xlsx','学生上课签到表'] wd=days_calculate.num_to_ch(weekday) stdFile=[term+'-'+'学生信息表(周'+wd+').xlsx','学生上课签到表'] # stdFile=['2019科学实验课学员档案2.xlsx','学员名单'] crs=pd.read_excel(os.path.join(self.CrsInfoDir,crsFile[0]),skiprows=0,sheet_name=crsFile[1]) stds=pd.read_excel(os.path.join(self.StdInfoDir,stdFile[0]),skiprows=1,sheet_name=stdFile[1]) stds.rename(columns={'Unnamed: 0':'ID','Unnamed: 1':'机构','Unnamed: 2':'班级','Unnamed: 3':'姓名首拼','Unnamed: 4':'学生姓名', \ 'Unnamed: 5':'昵称','Unnamed: 6':'性别','Unnamed: 7':'上期课时结余','Unnamed: 8':'购买课时','Unnamed: 9':'目前剩余课时', \ 'Unnamed: 10':'上课数量统计汇总'},inplace=True) # print(stds) # std=stds[stds['学生姓名']==stdName] # std_basic=std[['姓名首拼','学生姓名']] # std_crs=std[std.iloc[:,:]=='√'].dropna(axis=1) # std_res=pd.concat([std_basic,std_crs],axis=1) # print(crs) return [crs,stds]
def check_duplicate(self, term='2021秋', weekday=5, crs_name='L103摩托车骑士', show='show'): wd = days_calculate.num_to_ch(weekday) fn_dir = os.path.join(self.std_info_dir, '学生信息表') fn = os.path.join(fn_dir, term + '-学生信息表(周' + wd + ').xlsx') df_current = pd.read_excel(fn, skiprows=1) std_list = [ item[0] for item in df_current.iloc[:, 4:5].values.tolist() ] info_current = [crs_name, std_list] rpt = 0 rpt_info = [] for xls in os.listdir(fn_dir): if re.match(r'\d\d\d\d\w{1}-.*.xlsx$', xls) and xls[-8:-6] != '体验': fn_ever = os.path.join(fn_dir, xls) info_taken = WashData.class_taken(fn_ever) cls_taken_get = [cls[9:] for cls in info_taken['cls_taken']] #输入的课程名单是否在既往的课程中 if crs_name in cls_taken_get: #当前学期的学生姓名是否在过去的名单中 for std in std_list: if std in info_taken['std_names']: rpt_info.append( [std, crs_name, xls[:5], xls[-8:-6]]) rpt += 1 if show == 'show': if rpt > 0: print('\n在 {} 学期 星期{} 的学生课程 {} 中检测到以下重复\n'.format( term, wd, crs_name)) for info in rpt_info: print(info) else: print('未检测到重复值') return [rpt_info, rpt]
def check_conflict(self, term='2021秋', weekday=5, fn='c:/Users/jack/desktop/w5待排课程.txt', show_res='yes', write_file='yes'): with open(fn, 'r', encoding='utf-8') as f: lines = f.readlines() to_arrange = [itm.strip() for itm in lines] res = [] rpt = 0 for crs in to_arrange: res_dup = self.check_duplicate(term=term, weekday=weekday, crs_name=crs, show='no') rpt = rpt + res_dup[1] check_res = res_dup[0] _res = [] for _check_res in check_res: _res.append([_check_res[0], _check_res[2], _check_res[3]]) res.append([crs, _res]) # print(res) if show_res == 'yes': if rpt > 0: print('\n在 {} 学期 星期{} 的班级课程中检测到以下重复值:'.format( term, days_calculate.num_to_ch(weekday))) res_no_dups = [] for conf in res: if conf[1]: if conf[0] != '': print('\n' + conf[0] + '---->') for conff in conf[1]: print(conff[0] + ' ' + conff[1] + ' ' + conff[2]) else: if conf[0] != '': res_no_dups.append(conf[0]) if res_no_dups: print('\n=========分==隔==线===========\n') for res_no_dup in res_no_dups: print(res_no_dup) print( '-------------------------------->\n在 {} 学期 星期{} 的班级课程中未检测到重复值。\n' .format(term, days_calculate.num_to_ch(weekday))) print('\n') else: print('\n') for conf in res: if conf[0] != '': print(conf[0]) print('----------------------------------------->') print('\n以上在 {} 学期 星期{} 的班级课程中未检测到重复值。\n'.format( term, days_calculate.num_to_ch(weekday))) if write_file == 'yes': res_fn = 'c:/Users/jack/desktop/crs_conflict_result.txt' if rpt > 0: with open(res_fn, 'w', encoding='utf-8') as fw: fw.write('\n在 {} 学期 星期{} 的班级课程中检测到以下重复值:\n'.format( term, days_calculate.num_to_ch(weekday))) res_no_dup_w = [] for conf in res: if conf[1]: fw.write('\n' + conf[0] + '---->' + '\n') for conff in conf[1]: fw.write(conff[0] + ' ' + conff[1] + ' ' + conff[2] + '\n') else: if conf[0] != '': res_no_dup_w.append(conf[0]) if res_no_dup_w: fw.write('\n=========分==隔==线===========\n\n') for res_no_dup in res_no_dups: fw.write(res_no_dup + '\n') fw.write( '------------------------------->\n在 {} 学期 星期{} 的班级课程中未检测到重复值。\n' .format(term, days_calculate.num_to_ch(weekday))) fw.write('\n') print('\n文件写入完成') else: with open(res_fn, 'w', encoding='utf-8') as fw: fw.write('\n') for conf in res: if conf[0] != '': fw.write(conf[0] + '\n') fw.write('----------------------------------->' + '\n') fw.write('\n在 {} 学期 星期{} 的班级课程中未检测到重复值。\n'.format( term, days_calculate.num_to_ch(weekday))) # print(res) return res
def exp_poster(self,std_name='韦宇浠',start_date='20200930',end_date='20210121',cmt_date='20210407', \ tb_list=[['2020秋','w2'],['2021春','w4']],tch_name='阿晓老师',mode='all',k=1): print('正在处理……') info = self.get_std_term_crs(std_name=std_name, tb_list=tb_list, start_date=start_date, end_date=end_date) total_crs = info['total_crs'] total_crs.dropna(inplace=True) std_crs = info['std_crs'] std_crs.dropna(inplace=True) std_info = info['std_info'] #学期课程总数 total_crs_num = total_crs.shape[0] #格子的行数 if total_crs_num / 4 == total_crs_num // 4: crs_lines = total_crs_num // 4 else: crs_lines = total_crs_num // 4 + 1 #所有课程格子的总高度 ht_crs = int((170 * k + 14 * k) * crs_lines) #学生基本信息 std_school = std_info['机构'].values[0] std_class = std_info['班级'].values[0] #学生学期末评语 term, weekday = tb_list[-1][0], tb_list[-1][1][1] wd = days_calculate.num_to_ch(weekday) xls = os.path.join(self.feedback_dir, term + '-学生课堂学习情况反馈表(周' + wd + ').xlsx') comments = WashData.std_feedback(std_name=std_name, xls=xls)['df_term_comment'] comments_for_std = comments[comments['学生姓名'] == std_name][ term + '学期总结-' + str(cmt_date)].values.tolist()[0].replace( '#', std_name) std_crs_num = std_crs.shape[0] if mode == 'part': if total_crs_num == std_crs_num: std_crs_num_txt = '{0}同学在上一阶段的{1} 节科学机器人课中,完成了全部课程的学习!'.format( std_name, total_crs_num) else: std_crs_num_txt = '{0}同学在上一阶段的{1} 节科学机器人课中,完成了{2} 节课的学习,请假{3} 节。'.format( std_name, total_crs_num, std_crs_num, total_crs_num - std_crs_num) elif mode == 'all': # if total_crs_num==std_crs_num: std_crs_num_txt = '{0}已经完成了{1} 节科学机器人课程的学习!'.format( std_name, total_crs_num) # else: # std_crs_num_txt='{0}同学在上一阶段的{1} 节科学机器人课中,完成了{2} 节课的学习,请假{3} 节。'.format(std_name,total_crs_num,std_crs_num,total_crs_num-std_crs_num) comments_for_std = std_crs_num_txt + '\n' + comments_for_std font_size_cmt = int(30 * k) prgh_nums = composing.split_txt_Chn_eng(wid=int(636 * k), font_size=font_size_cmt, txt_input=comments_for_std)[1] #评语标题高度 ht_cmt_title = int(60 * k) #评语高度 ht_prgh = int(font_size_cmt * 1.5 * (prgh_nums + 4)) ht_title = int(110 * k) ht_std = int(100 * k) ht_bottom = int(210) gap_0 = int(12 * k) gap_1 = int(13 * k) y_std_1 = int(120 * k) y_std_2 = int((y_std_1 + 100)) blocks = [ht_title, ht_std, ht_crs, ht_cmt_title, ht_prgh, ht_bottom] #计算总的高度 ht_total_bg = int((sum(blocks) + gap_0 * 4 + gap_1 * (prgh_nums - 1))) #课程标题坐标 y_crs_title = int((y_std_2 + gap_0 + 80)) #课程格最左上角坐标 y_left_up = int((y_crs_title + gap_0)) #评语绿底右下坐标 y_cmt_bg = y_left_up + ht_crs + gap_0 + ht_cmt_title + ht_prgh + 30 # draw.rectangle([(int(36*k),y_left_up+gap_0+ht_cmt_title+10),(int(684*k),y_cmt_bg)],fill='#F3F3E4') def draw_bg(): bg = Image.new('RGBA', (int(720 * k), ht_total_bg), '#F3F9E4') draw = ImageDraw.Draw(bg) #白底 draw.rectangle([(int(13 * k), int(110 * k)), (int(707 * k), ht_total_bg - 25)], fill='#FFFFFF') #名字绿底 draw.rectangle([(int(36), y_std_1), (int(250 * k), y_std_2)], fill='#F3F9E4') draw.rectangle([(int(36), y_std_2), (int(684 * k), y_std_2 + 2)], fill='#F3F9E4') return bg def crs_pic(total_crs=total_crs, std_crs=std_crs, odr=0): wid_crs, ht_crs = int(150 * k), int(170 * k) #学生上过的课程和总课程的差集 sub_set = total_crs.copy() sub_set = sub_set.append(std_crs) sub_set = sub_set.append(std_crs) sub_set.drop_duplicates(subset=['课程名称'], keep=False, inplace=True) crs_bg = Image.new('RGB', (wid_crs, ht_crs), '#F3F3E4') crs_name = total_crs.iloc[odr, :]['课程名称'] crs_date = total_crs.iloc[odr, :]['上课日期'] crs_pic = Image.open( os.path.join(self.design_dir, crs_name, crs_name[4:] + '.jpg')) crs_pic = crs_pic.crop((560, 0, 1280, 720)).resize( (int(110 * k), int(110 * k))) crs_bg.paste(crs_pic, (int(20 * k), int(6 * k))) draw = ImageDraw.Draw(crs_bg) ft_size = int(19 * k) x_txt = int(((150 * k - len(crs_name[4:]) * ft_size) / 2 + 3)) draw.text((x_txt, int(122 * k)), crs_name[4:], fill='#8fc31f', font=self.font('方正韵动粗黑简', ft_size)) #课程名称 #判断是否有不上的课,如有,变灰 if crs_name not in sub_set['课程名称'].values: draw.text((int(35 * k), int(148 * k)), str(crs_date)[:11], fill='#8fc31f', font=self.font('方正韵动粗黑简', int(12 * k))) #课程日期 else: draw.text((int(35 * k), int(148 * k)), '---------', fill='#8fc31f', font=self.font('方正韵动粗黑简', int(12 * k))) #课程日期 crs_bg = ImageEnhance.Brightness(crs_bg).enhance(1.4) crs_bg = crs_bg.convert('L') # crs_bg.show() return crs_bg def draw_crs(): print('正在生成图片……', end='') #使用并改变母函数的变量 nonlocal y_left_up bg = draw_bg() wid_crs, ht_crs = int(150 * k), int(170 * k) draw = ImageDraw.Draw(bg) #分隔线 draw.rectangle([(int(36 * k), y_crs_title), (int(684 * k), y_crs_title + 2 * k)], fill='#F3F3E4') cnt = 0 for i in range(crs_lines): x_begin = int(40 * k) for j in range(4): if cnt < total_crs_num: crs_block = crs_pic(total_crs=total_crs, std_crs=std_crs, odr=cnt) bg.paste(crs_block, (x_begin, y_left_up)) x_begin = x_begin + wid_crs + int(13 * k) cnt += 1 y_left_up = y_left_up + ht_crs + gap_1 #分隔线 draw.rectangle([(int(36 * k), y_left_up + gap_0), (int(684 * k), y_left_up + gap_0 + 2)], fill='#F3F3E4') #评语绿底 # y_cmt_bg=y_left_up+gap_0+ht_cmt_title+ht_prgh draw.rectangle( [(int(36 * k), y_left_up + gap_0 + ht_cmt_title + 10), (int(684 * k), y_cmt_bg)], fill='#F3F3E4') #二维码,logo _pic_logo = Image.open( 'I:\\大智小超\\公共素材\\图片类\\大智小超新logo.png').convert('RGBA') pic_logo = _pic_logo.resize((int(210 * k), int(210 * k / 2.76))) r, g, b, a = pic_logo.split() y_logo = int((ht_total_bg - 140)) _pic_qrcode = Image.open('I:\\大智小超\\公共素材\\图片类\\大智小超视频号二维码2.png') pic_qrcode = _pic_qrcode.resize((int(100 * k), int(100 * k))) bg.paste(pic_logo, (int(40 * k), int(y_logo + 10)), mask=a) bg.paste(pic_qrcode, (int(580 * k), int(y_logo - 10))) #文字部分 #标题 draw.text((int(130 * k), int(5 * k)), '科学机器人课', fill='#8fc31f', font=self.font('汉仪超级战甲', int(78 * k))) #姓名班级 draw.text((int(60 * k * 0.9), int(142 * k * 0.9)), std_name, fill='#F8B62D', font=self.font('汉仪字酷堂义山楷w', int(60 * k))) draw.text((int(400 * k * 0.9), int(182 * k * 0.9)), std_school + ' ' + std_class, fill='#6C8466', font=self.font('汉仪字酷堂义山楷w', int(30 * k))) draw.text((int(45), int((y_crs_title - 52))), '点亮的课程', fill='#8fc31f', font=self.font('鸿蒙印品', int(35 * k))) draw.text((int(45), int((y_left_up + gap_0 + 20))), '学期评语', fill='#8fc31f', font=self.font('鸿蒙印品', int(35 * k))) #评语 composing.put_txt_img(draw=draw,tt=comments_for_std,total_dis=int(628*k*0.95), \ xy=[int(58),int((y_left_up+gap_0+110))],dis_line=int(20*k),fill='#595757', \ font_name='丁永康硬笔楷书',font_size=font_size_cmt,addSPC="add_2spaces") draw.text((int(520 * k), int((y_cmt_bg - 46))), tch_name, fill='#595757', font=self.font('丁永康硬笔楷书', 35)) draw.text((int(380 * k), int((y_logo + 10))), '长按二维码 → \n关注视频号 →', fill='#8E9184', font=self.font('微软雅黑', 25)) bg = bg.convert('RGB') savename = os.path.join( self.term_pic_dir, std_name + '-' + cmt_date + '-' + term + '阶段小结.jpg') bg.save(savename, quality=90, subsampling=0) # bg.show() print('图片保存完成,保存路径:{}'.format(savename)) draw_crs()
def exp_a4_16(self,std_name='韦宇浠',start_date='20200930',end_date='20210121',cmt_date='20210407', \ tb_list=[['2020秋','w2'],['2021春','w4']],tch_name='阿晓老师',mode='only16',k=1): print('正在处理……') info = self.get_std_term_crs(std_name=std_name, tb_list=tb_list, start_date=start_date, end_date=end_date) total_crs = info['total_crs'] total_crs.dropna(inplace=True) std_crs = info['std_crs'] std_crs.dropna(inplace=True) std_info = info['std_info'] if mode == 'only16': # if len(std_crs)<16: # print('{} 在{} - {} 期间总共上了{}节课,未上满16节。未生成报告。'.format(std_name,start_date,end_date,len(std_crs))) # exit(0) total_crs = std_crs #学期课程总数 total_crs_num = 16 crs_lines = 2 else: #学期课程总数 total_crs_num = total_crs.shape[0] # 格子的行数 if total_crs_num / 8 == total_crs_num // 8: crs_lines = total_crs_num // 8 else: crs_lines = total_crs_num // 8 + 1 #所有课程格子的总高度 ht_crs = int((316 + 30) * crs_lines) #学生基本信息 std_school = std_info['机构'].values[0] std_class = std_info['班级'].values[0] #学生学期末评语 term, weekday = tb_list[-1][0], tb_list[-1][1][1] wd = days_calculate.num_to_ch(weekday) xls = os.path.join(self.feedback_dir, term + '-学生课堂学习情况反馈表(周' + wd + ').xlsx') comments = WashData.std_feedback(std_name=std_name, xls=xls)['df_term_comment'] comments_for_std = comments[comments['学生姓名'] == std_name][ term + '学期总结-能力-' + str(cmt_date)].values.tolist()[0].replace( '#', std_name) comments_for_std_psycho = comments[comments['学生姓名'] == std_name][ term + '学期总结-心理-' + str(cmt_date)].values.tolist()[0].replace( '#', std_name) # print(std_crs) std_crs_num = std_crs.shape[0] # if mode=='only16': # if total_crs_num==std_crs_num: # std_crs_num_txt='{0}同学在上一阶段的{1} 节科学机器人课中,完成了全部课程的学习!'.format(std_name,total_crs_num) # else: # std_crs_num_txt='{0}同学在上一阶段的{1} 节科学机器人课中,完成了{2} 节课的学习,请假{3} 节。'.format(std_name,total_crs_num,std_crs_num,total_crs_num-std_crs_num) # elif mode=='all': # # if total_crs_num==std_crs_num: # std_crs_num_txt='{0}已经完成了{1} 节科学机器人课程的学习!'.format(std_name,total_crs_num) # else: # std_crs_num_txt='{0}同学在上一阶段的{1} 节科学机器人课中,完成了{2} 节课的学习,请假{3} 节。'.format(std_name,total_crs_num,std_crs_num,total_crs_num-std_crs_num) # comments_for_std=std_crs_num_txt+'\n'+comments_for_std font_size_cmt = int(50 * k) prgh_nums = composing.split_txt_Chn_eng(wid=int(636 * k), font_size=font_size_cmt, txt_input=comments_for_std)[1] #评语标题高度 ht_cmt_title = int(60 * k) #评语高度 ht_prgh = int(font_size_cmt * 1.5 * (prgh_nums + 4)) ht_title = int(110 * k) ht_std = int(100 * k) ht_bottom = int(210) gap_0 = int(12 * k) gap_1 = int(13 * k) y_std_1 = int(120 * k) y_std_2 = int((y_std_1 + 100)) blocks = [ht_title, ht_std, ht_crs, ht_cmt_title, ht_prgh, ht_bottom] #计算总的高度 # ht_total_bg=int((sum(blocks)+gap_0*4+gap_1*(prgh_nums-1))) ht_total_bg = 3508 #课程标题坐标 y_crs_title = int((y_std_2 + gap_0 + 80)) # y_crs_title= #课程格最左上角坐标 y_left_up = 800 #评语绿底右下坐标 y_cmt_bg = y_left_up + ht_crs + gap_0 + ht_cmt_title + ht_prgh + 30 # draw.rectangle([(int(36*k),y_left_up+gap_0+ht_cmt_title+10),(int(684*k),y_cmt_bg)],fill='#F3F3E4') def draw_bg(): bg = Image.new('RGBA', (2481, 3508), '#7197b4') draw = ImageDraw.Draw(bg) #白底 draw.rectangle([(50, 54), (2431, 3454)], fill='#FFFFFF') #评论大框 draw.rectangle([(166, 1720), (2315, 3202)], fill='#FFFFFF', outline='#7197b4', width=2) #玫瑰图底色 # draw.rectangle([(1595,1936),(2295,3155)],fill='#f0f8fb') # draw.rectangle([(1635,2695),(2255,2855)],fill='#ffffff') # draw.rectangle([(1635,2975),(2255,3125)],fill='#ffffff') #左边能力底色 draw.rectangle([(206, 1740), (1246, 3182)], fill='#f0f8fb') draw.rectangle([(226, 2537), (1226, 3162)], fill='#ffffff') #右边心理底色 draw.rectangle([(1275, 1740), (2295, 3182)], fill='#f0f8fb') draw.rectangle([(1295, 2537), (2275, 3162)], fill='#ffffff') return bg def crs_pic(total_crs=total_crs, std_crs=std_crs, odr=0): wid_crs, ht_crs = int(270 * k), int(351 * k) #学生上过的课程和总课程的差集 sub_set = total_crs.copy() sub_set = sub_set.append(std_crs) sub_set = sub_set.append(std_crs) sub_set.drop_duplicates(subset=['课程名称'], keep=False, inplace=True) crs_bg = Image.new('RGB', (wid_crs, ht_crs), '#7197b4') crs_name = total_crs.iloc[odr, :]['课程名称'] crs_date = total_crs.iloc[odr, :]['上课日期'] crs_pic = Image.open( os.path.join(self.design_dir, crs_name, crs_name[4:] + '.jpg')) crs_pic = crs_pic.crop((560, 0, 1280, 720)).resize( (int(230 * k), int(230 * k))) crs_bg.paste(crs_pic, (int(20 * k), int(20 * k))) draw = ImageDraw.Draw(crs_bg) ft_size = int(30 * k) x_txt = int(((270 * k - len(crs_name[4:]) * ft_size) / 2 + 3)) draw.text((x_txt, int(270 * k)), crs_name[4:], fill='#ffffff', font=self.font('方正韵动粗黑简', ft_size)) #课程名称 # draw.text((int(55*k),int(310*k)),str(crs_date)[:11],fill='#ffffff',font=self.font('方正韵动粗黑简',int(24*k))) #课程日期 #判断是否有不上的课,如有,变灰 if crs_name not in sub_set['课程名称'].values: draw.text((int(55 * k), int(310 * k)), str(crs_date)[:11], fill='#ffffff', font=self.font('方正韵动粗黑简', int(24 * k))) #课程日期 else: draw.text((int(55 * k), int(310 * k)), '---------', fill='#ffffff', font=self.font('方正韵动粗黑简', int(24 * k))) #课程日期 crs_bg = ImageEnhance.Brightness(crs_bg).enhance(1.4) crs_bg = crs_bg.convert('L') # crs_bg.show() return crs_bg def draw_crs(): print('正在生成图片……', end='') #使用并改变母函数的变量 nonlocal y_left_up bg = draw_bg() wid_crs, ht_crs = int(270 * k), int(351 * k) draw = ImageDraw.Draw(bg) #分隔线 # draw.rectangle([(int(36*k),y_crs_title),(int(684*k),y_crs_title+2*k)],fill='#F3F3E4') cnt = 0 for i in range(crs_lines): x_begin = int(80 * k) for j in range(8): if cnt < total_crs_num: try: crs_block = crs_pic(total_crs=total_crs, std_crs=std_crs, odr=cnt) bg.paste(crs_block, (x_begin, y_left_up)) x_begin = x_begin + wid_crs + int(23 * k) cnt += 1 except Exception as e: pass continue y_left_up = y_left_up + ht_crs + gap_1 #分隔线 # draw.rectangle([(int(36*k),y_left_up+gap_0),(int(684*k),y_left_up+gap_0+2)],fill='#F3F3E4') #评语绿底 # y_cmt_bg=y_left_up+gap_0+ht_cmt_title+ht_prgh # draw.rectangle([(int(36*k),y_left_up+gap_0+ht_cmt_title+10),(int(684*k),y_cmt_bg)],fill='#F3F3E4') #二维码,logo _pic_logo = Image.open( os.path.join(self.public_dir, '图片类', '大智小超新logo.png')).convert('RGBA') pic_logo = _pic_logo.resize((int(330 * k), int(330 * k / 2.76))) r, g, b, a = pic_logo.split() y_logo = int((ht_total_bg - 240)) _pic_qrcode = Image.open( os.path.join(self.public_dir, '图片类', '大智小超视频号二维码2.png')) pic_qrcode = _pic_qrcode.resize((int(210 * k), int(210 * k))) bg.paste(pic_logo, (int(130 * k), int(y_logo + 10)), mask=a) bg.paste(pic_qrcode, (int(2190 * k), int(y_logo - 40))) #玫瑰图 rose_and_bar = self.rose_and_bar(std_name=std_name, xls=xls) rose_mat = rose_and_bar['res_rose']['chart'] rose_pic = pic_transfer.mat_to_pil_img(rose_mat) rose_pic = rose_pic.resize( (640, 640 * rose_pic.size[1] // rose_pic.size[0])) rose_pic = rose_pic.crop((0, 0, 620, 640)) bg.paste(rose_pic, (421, 1890)) rose_data = rose_and_bar['res_rose']['data'] #柱形图 # bar_mat=rose_and_bar['res_bar']['chart'] # bar_pic=pic_transfer.mat_to_pil_img(bar_mat) # bar_pic=bar_pic.resize((640,640*rose_pic.size[1]//rose_pic.size[0])) # bar_pic=bar_pic.crop((0,0,620,640)) # bg.paste(bar_pic,(1460,1890)) #雷达图 radar_mat = rose_and_bar['res_radar']['chart'] radar_pic = pic_transfer.mat_to_pil_img(radar_mat) radar_pic = radar_pic.resize( (640, 640 * radar_pic.size[1] // radar_pic.size[0])) # radar_pic=radar_pic.crop((0,0,620,640)) bg.paste(radar_pic, (1460, 1890)) #签名(图片) tch_sig_txt = [] for m, tch_n in enumerate(tch_name): try: pic_tch_sig = Image.open( os.path.join(self.tch_sig_pic_dir, tch_n + '.png')) pic_tch_sig = pic_tch_sig.resize( (200, 200 * pic_tch_sig.size[1] // pic_tch_sig.size[0])) r_sig, g_sig, b_sib, a_sig = pic_tch_sig.split() bg.paste(pic_tch_sig, (950 + m * 1000, 3015), mask=pic_tch_sig) except FileNotFoundError as e: tch_sig_txt.append([m, tch_n]) # print(tch_n,e) #最高和高低的两个能力名称 abl_btm = [rose_data[0][0], rose_data[1][0]] abl_top = [rose_data[3][0], rose_data[4][0]] #文字部分 #标题 draw.text((int(1020 * k), int(101 * k)), '科学机器人课', fill='#7197b4', font=self.font('方正韵动粗黑简', int(78 * k))) draw.text((int(890 * k), int(220 * k)), '课程学习报告', fill='#7197b4', font=self.font('方正韵动粗黑简', int(120 * k))) #姓名班级 ftsz_name = 120 x_name = (2481 - ftsz_name * len(std_name)) // 2 draw.text((int(x_name), int(421 * k)), std_name, fill='#3e3a39', font=self.font('汉仪字酷堂义山楷w', int(ftsz_name * k))) # draw.text((int(400*k*0.9),int(182*k*0.9)),std_school+' '+std_class,fill='#6C8466',font=self.font('汉仪字酷堂义山楷w',int(30*k))) #课程信息 # print(total_crs) prd = total_crs['上课日期'].apply( lambda x: x.strftime('%Y-%m-%d')).tolist() mth_start = prd[0].split('-')[0] + '年' + prd[0].split('-')[1] + '月' mth_end = prd[-1].split('-')[0] + '年' + prd[-1].split('-')[1] + '月' prd_txt = '{}-{}'.format(mth_start, mth_end) std_crs_finish_number = len(std_crs) if len(std_crs) <= 16 else 16 draw.text((930, 580), prd_txt, fill='#7197b4', font=self.font('方正韵动粗黑简', int(50 * k))) # draw.text((820,730),'在大智小超科学实验室学习',fill='#7197b4',font=self.font('方正韵动粗黑简',int(50*k))) draw.text((700, 670), '完成了{}节科学机器人课程的学习'.format(std_crs_finish_number), fill='#7197b4', font=self.font('方正韵动粗黑简', int(72 * k))) draw.text((980, 1594), '学习情况总结', fill='#7197b4', font=self.font('优设标题', int(90 * k))) #能力描述 # format(abl_top[0],abl_top[1],abl_btm[0],abl_btm[1]) # draw.text((1790,2625),'你现在最棒的能力',fill='#9f9c9c',font=self.font('优设标题',int(50*k))) # draw.text((1750,2905),'还可以再提升的能力',fill='#9f9c9c',font=self.font('优设标题',int(50*k))) # draw.text((1750,2715),'• '+abl_top[1],fill=rose_data[-1][2],font=self.font('微软雅黑',int(70*k))) # draw.text((1750,2995),'• '+abl_btm[0],fill=rose_data[0][2],font=self.font('微软雅黑',int(70*k))) # composing.put_txt_img(draw=draw,tt='• '+abl_top[0]+'\n'+'• '+abl_top[1],total_dis=int(800*k*0.95), \ # xy=[1750,2705],dis_line=int(23*k),fill='#7197b4', \ # font_name='微软雅黑',font_size=40,addSPC="add_2spaces") # composing.put_txt_img(draw=draw,tt='• '+abl_btm[0]+'\n'+'• '+abl_btm[1],total_dis=int(800*k*0.95), \ # xy=[1750,2995],dis_line=int(23*k),fill='#7197b4', \ # font_name='微软雅黑',font_size=40,addSPC="add_2spaces") #评语 #左右标题 draw.text((608, 1764), '技能成长', fill='#7197b4', font=self.font('优设标题', int(80 * k))) draw.text((1598, 1764), '社会能力成长', fill='#7197b4', font=self.font('优设标题', int(80 * k))) draw.text((698, 3034), '上课老师:', fill='#7197b4', font=self.font('优设标题', int(50 * k))) draw.text((1618, 3034), '特约心理老师:', fill='#7197b4', font=self.font('优设标题', int(50 * k))) composing.put_txt_img(draw=draw,tt=comments_for_std,total_dis=int(980*k*0.95), \ xy=[248,2607],dis_line=int(23*k),fill='#3e3a39', \ font_name='丁永康硬笔楷书',font_size=font_size_cmt,addSPC="add_2spaces") composing.put_txt_img(draw=draw,tt=comments_for_std_psycho,total_dis=int(980*k*0.95), \ xy=[1313,2607],dis_line=int(23*k),fill='#3e3a39', \ font_name='丁永康硬笔楷书',font_size=font_size_cmt,addSPC="add_2spaces") #签名(如无图片,则用文字) #上课 # draw.text((950,3035),tch_name[0]+'老师',fill='#3e3a39',font=self.font('丁永康硬笔楷书',int(50*k))) draw.text((950, 3100), cmt_date[0:4] + '.' + cmt_date[4:6] + '.' + cmt_date[6:], fill='#3e3a39', font=self.font('丁永康硬笔楷书', int(40 * k))) #心理 # draw.text((1950,3035),tch_name[1]+'老师',fill='#3e3a39',font=self.font('丁永康硬笔楷书',int(50*k))) draw.text((1950, 3100), cmt_date[0:4] + '.' + cmt_date[4:6] + '.' + cmt_date[6:], fill='#3e3a39', font=self.font('丁永康硬笔楷书', int(40 * k))) if tch_sig_txt: for tch_sig_t in tch_sig_txt: if tch_sig_t[0] == 0: draw.text((950, 3035), tch_sig_t[1] + '老师', fill='#3e3a39', font=self.font('丁永康硬笔楷书', int(50 * k))) elif tch_sig_t[0] == 1: draw.text((1950, 3035), tch_sig_t[1] + '老师', fill='#3e3a39', font=self.font('丁永康硬笔楷书', int(50 * k))) else: print('没有该老师签名,请检查。') #slogan draw.text((600, 3300), '让孩子从小玩科学,爱科学,学科学。', fill='#c23030', font=self.font('楷体', int(82 * k))) # draw.text((int(380*k),int((y_logo+10))), '长按二维码 → \n关注视频号 →', fill = '#8E9184',font=self.font('微软雅黑',25)) bg = bg.convert('RGB') savename = os.path.join( self.term_pic_dir, std_name + '-' + cmt_date + '-' + term + '-课程学习报告.jpg') if not os.path.exists(self.term_pic_dir): os.makedirs(self.term_pic_dir) # savename=os.path.join('e:/temp/',std_name+'.jpg') bg.save(savename, quality=90, subsampling=0) # bg.save(savename,quality=95,dpi=(300,300)) # bg.show() print('图片保存完成,保存路径:{}'.format(savename)) draw_crs()