时间管理器(python)

介绍

这款程序是我用来管理时间的。刚开始我尝试了很多软件比如calendar。他用来记录长期保持的事件是方便的,也是我刚开始认为的最好选择。但是作为一名高中学生,我发现由于假期的存在,和行程的不确定性,我可能总是需要编辑我的calendar,很麻烦,所以只能记录我放学后的兴趣班时间。我想要的效果是在学校那种上课就响上课铃,下课就响下课铃,快上课了会提醒,快下课了也会提醒,这样我就能很规律的学习。而且考虑到有时候会“迟到”,所以我还要让程序能够自动地根据课程设定来安排离我现在时间最近的一堂课。

import time
import datetime
import pygame
import sys
from pyecharts import options as opts
from pyecharts.charts import Pie
from turtle import *

print()
pygame.init()


class Schedule:
    @staticmethod
    def to_float(lcl_tm: str) -> float:  # convert string type time to float type
        lst = lcl_tm.split(":")
        return float(lst[0]) + round(float(lst[1]) / 60, 4)

    @staticmethod
    def to_string(lcl_tm: float) -> str:
        int_part = str(int(lcl_tm // 1))
        fl_part = str(round((lcl_tm % 1) * 60))

        if len(fl_part) <= 1:
            fl_part = "0" + fl_part

        if len(int_part) <= 1:
            int_part = "0" + int_part

        return int_part + ":" + fl_part

    def __init__(self, lessons, music_arr, start_tm="16:24"):
        assert len(  # format check for the argument
            start_tm.split(":")) == 2, "wrong format of start_time argument, should be hour:minute, eg 16:30"
        self.start_tm_nom = start_tm  # officially announced start time of studying
        self.start_plan = self.to_float(self.start_tm_nom)  # planned time, which will change if the user is late.

        cnt = 0
        for lesson in lessons:  # validation of argument 'lessons', due to the complexity of the program
            if not (isinstance(lesson[1], int) or isinstance(lesson[2], int)):
                raise TypeError("unable to utilise 'float' type in parameter 'lessons'")
            else:
                lesson.append(cnt)
                cnt += 1
        self.lessons = lessons  # declare and assign only when the argument is valid

        self.intv = 60  # to fetch state that determines whether it's time to start the program (unit: second)
        self.__uncertainty = round(self.intv / 2 / 60 / 60, 5)  # a range (unit:hour)

        # load music resources
        try:
            self.start_music = pygame.mixer.Sound(music_arr[0])
            self.over_music = pygame.mixer.Sound(music_arr[1])
            self.near_lesson = music_arr[2]
        except IndexError:
            print("not enough music files for this program!")
        except FileNotFoundError:
            print("name of the music file is not found!")

    @property
    def gap(self):  # encapsulation to prevent modification through undefined pathway 
        return self.__uncertainty

    def new_start(self, now_: float):
        cnt = 0
        # when it's too early
        if now_ <= self.start_plan + self.gap:
            return 0, ""

        for info in self.lessons:
            if now_ <= self.start_plan:
                return cnt, info[0]  # 1.new lesson index 2.lesson name
            self.start_plan += round((info[1] + info[2]) / 60, 5)
            cnt += 1

        print("you have missed all lessons today. make sure you attend them tomorrow on time!")
        sys.exit()

    def initialise(self) -> int:
        cnt = 0  # ensure statement is only executed once 
        is_exe = True  # same function as the one above
        info = [0, 0, 0]  # used to receive result
        self.start_plan = self.to_float(self.start_tm_nom)  # the initially planned start time
        tm_to_start = 0.1  # notice when 6 minutes towards the first lesson (unit:hour)

        while True:
            now_tm = datetime.datetime.now().strftime('%A %H:%M').split(" ")  # update the time now
            now_ = self.to_float(now_tm[1])

            # IF the now is later than planned starting time THEN
            if (now_ > self.start_plan + self.gap) and is_exe:  # execute once
                info = self.new_start(now_)
                print("late!\nlessons started at ", self.start_tm_nom)  # nominal start time of study
                print(f"attend the lesson <{info[1]}> started at ", self.to_string(self.start_plan))
                is_exe = False

            # IF now is earlier than planned starting time THEN
            elif now_ < self.start_plan - self.gap:
                if tm_to_start - self.gap <= self.start_plan - now_ <= tm_to_start + self.gap and cnt == 0:
                    print(f" {tm_to_start * 60} minutes towards the first lesson!")
                    cnt += 1
                time.sleep(self.intv)  # wait

            # time to activate the main program
            elif self.start_plan - self.gap <= now_ <= self.start_plan + self.gap:
                print("implement: lesson start")
                return info[0]  # return the starting index of lesson list

    # show time on console:None
    @staticmethod
    def show_time(total_tm: int):  # total_time is in minute
        sc = 60
        total_tm -= 1

        while total_tm >= 0:
            time.sleep(1)
            sc -= 1
            print(total_tm, ":", sc)

            if sc <= 0:
                total_tm -= 1
                sc = 60

    # show time on turtle screen:None
    @staticmethod
    def show_time_screen(total_min: int, lesson):  # parameter in minutes
        if total_min < 1:
            print(f"no time for {lesson}!")
            return

        tmp = total_min  # break time length
        total_min -= 1
        is_exe = True  # determine whether the lesson start notice should be executed
        sc = 60  # second
        sz = 160  # size of a character on the screen
        dev = 0  # deviation in counting

        # go to correct position
        speed(0)
        penup()
        goto(-sz * 2, -sz / 2)

        while total_min > -1:
            if dev < 1:
                intv = 1 - dev
            else:
                intv = 0  # set time slice to zero for deviation reduction
            time.sleep(intv)
            start = time.perf_counter()
            sc -= 1

            # effect:1:09 instead of 1:9
            if 0 <= sc < 10:
                str_sc = "0" + str(sc)
            else:
                str_sc = str(sc)

            # clear the screen
            clear()
            write(str(total_min) + ":" + str_sc, font=("arial", sz, "normal"))

            # reset second (one minute has passed)
            if sc <= 0:
                total_min -= 1
                sc = 60

            # lesson notice
            if (total_min + round(sc / 60, 5)) <= tmp / 2 and is_exe:  # execute only once
                print(f"{tmp / 2} minutes towards the {lesson}!")
                if lesson == "break time":  # only execute when it's class-over time
                    pygame.mixer.Sound(self.near_lesson).play()
                is_exe = False

            end = time.perf_counter()
            dev = round(end - start, 8)  # time taken for program to count (deviation)

    def execution(self):
        start_idx = self.initialise()

        for lesson_info in self.lessons:
            now_idx = lesson_info[3]

            if now_idx < start_idx:
                continue

            # class start
            print("\nlesson <{}> (duration: {} minutes) starts now".format(lesson_info[0], lesson_info[1]))
            self.start_music.play()
            self.show_time_screen(lesson_info[1], "break time")  # countdown

            # next lesson notice
            if now_idx < len(self.lessons) - 1:
                print(f"the next lesson {self.lessons[now_idx + 1][0]} started at",
                      self.to_string(self.start_plan))

            # class-over
            if lesson_info[2] > 0:  #
                print(f"class is over. break time for {lesson_info[2]} minutes")
                self.over_music.play()
                self.start_plan += round((lesson_info[1] + lesson_info[2]) / 60, 5)  # update next lesson's start time
                self.show_time_screen(lesson_info[2], "lesson")  # countdown

        print("one day hard work is over. disfrutas tu hora hoy y duermes bien! hasta manana!")

    def show_pie(self) -> None:
        data_pairs = [[pair[0], pair[1]] for pair in self.lessons]
        (
            Pie(init_opts=opts.InitOpts(bg_color="#2c343c"))

            .add(series_name="Pie chart",
                 center=["50%", "50%"],
                 radius="200",
                 data_pair=data_pairs,
                 )

            .set_colors(["blue", "yellow", "red", "orange", "purple"])

            .set_global_opts(  # set title format
                title_opts=opts.TitleOpts(
                    title="Pie",
                    pos_left="20%",
                    pos_top="50",
                    title_textstyle_opts=opts.TextStyleOpts(color="rgb(250,250,255)"),  # title color
                ),
                # is show legend
                legend_opts=opts.LegendOpts(
                    is_show=True,
                    pos_left="0%",
                    background_color="rgb(250,250,255)",
                    border_color="rgb(150,150,150)"
                ),
            )
            # set label format
            .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}", color="rgb(250,250,255)"))

            .render("study_time_pie.html")
        )


#模板
glb_lessons = [
    ["study", 60, 10],
    ["study", 60, 20],
    ["study", 60, 10],  # to 20:10
    ["study", 60, 10],
    ["study", 60, 10],  # 10:30
] #the second element of a sublist is lesson duration and the third is break time




glb_weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
glb_weekend = ["Saturday", "Sunday"]
#music_array=[class begin music,class over music, nearly class begin/over]
schedule = None

# use 24-hour system
glb_now = datetime.datetime.now().strftime('%A %H:%M').split(" ")

if glb_now[0] in glb_weekdays:
    if glb_now[0] == "Wednesday":
        glb_lessons.insert(2, ["English lesson", 60, 10])
    schedule = Schedule(glb_lessons, music_array, "16:00")

schedule.execution()
schedule.show_pie()
done()

执行效果:

计时器:

他还会在一天的学习后根据你在每个学习内容上花的时间画饼图。

程序思路懒得讲了,喜欢的朋友用就好。这个程序运行稳定而且容易使用。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值