示例#1
0
 def __init__(self, date, config):
     self.today = date
     self.num_reg = re.compile('^-?\d+$')
     self.infstr = config['Journal']['INFSTR']
     self.template = Regexplate(config['Journal']['DATE'])
     super().__init__()
     return
示例#2
0
 def __init__(self, date, config):
     t00 = datetime.datetime(date.year, date.month, date.day, 0, 0, 0)
     t24 = t00 + datetime.timedelta(1)
     self.t00 = int(t00.timestamp())
     self.t24 = int(t24.timestamp())
     self.template = Regexplate(config['Journal']['TIME'])
     self.delim = config['Journal']['DELIM']
     super().__init__()
示例#3
0
 def __init__(self, date, config):
     self.year = date.year
     self.month = date.month
     self.day = date.day
     self.template = Regexplate(config['Journal']['TIME'])
     self.delim = config['Journal']['DELIM']
     super().__init__()
     return
示例#4
0
class MemoParser(Logger):
    """メモ解析器"""
    def __init__(self, config):
        self.root = config['Main']['ROOT']
        self.template = Regexplate(config['Journal']['MEMOTITLE'])
        super().__init__()
        return

    @Logger.logging
    def parse(self, string):
        texts = self.template.split(string)[1:]
        titles = self.template.findall(string)
        paths = [self.root + self.template.parse(s)['PATH'] for s in titles]
        return [{'PATH': p, 'TEXT': t} for p, t in zip(paths, texts)]
class TaskLineBuilder(Logger):
    """"""

    def __init__(self, date, config):
        self.root = config['Main']['ROOT']
        self.dlb = DeadLineBuilder(date, config)
        self.ttb = TimeTableBuilder(date, config)
        self.template = Regexplate(config['Journal']['TASKLINE'])
        super().__init__()

    @Logger.logging
    def build(self, task):
        return self.template.substitute(self.task_map(task))

    @Logger.logging
    def task_map(self, task):
        return {
                'PATH': self.short_path(task.path),
                'DEADLINE': self.dlb.build(task.deadline),
                'TIMETABLE': self.ttb.build(task.timetable),
                }

    @Logger.logging
    def short_path(self, path):
        if self.root not in path or path.index(self.root) != 0:
            return path
        else:
            return path.replace(self.root, '')
示例#6
0
class Memo(Logger):

    stamp = Regexplate('## Written at %Y/%m/%d %H:%M')

    head_blank_reg = re.compile(r'^\n*')
    tail_blank_reg = re.compile(r'\n*$')
    body_blank_reg = re.compile(r'\n{3,}')

    # コンストラクタ
    def __init__(self, dirpath, filename):
        self.dirpath = dirpath
        self.filepath = os.path.join(dirpath, filename)
        super().__init__()

    # メモ取得
    @Logger.logging
    def get(self):
        # ファイルが無ければ空リストを返す
        if not os.path.isdir(self.dirpath):
            return []
        if not os.path.isfile(self.filepath):
            return []

        # ファイルを読み込んでテキストリストにして返す
        with open(self.filepath, 'r', encoding='utf-8-sig') as f:
            text = f.read()
        return [s for _, s in type(self).parse(text, type(self).stamp)]

    # メモ追記
    @Logger.logging
    def put(self, timestamp, text):
        # ディレクトリが無ければ作成する
        if not os.path.isdir(self.dirpath):
            os.makedirs(self.dirpath)
        # 余計な空白行を削除する
        text = type(self).trim(text)
        # 既に記載されていれば無視する
        if text in self.get():
            return False
        # 追記する
        with open(self.filepath, 'a', encoding='utf-8') as f:
            f.write("{}\n\n{}\n\n".format(
                timestamp.strftime(type(self).stamp.template), text))
        return True

    # 補助メソッド
    @classmethod
    @Logger.logging
    def parse(cls, text, template):
        titles = template.findall(text)
        texts = [cls.trim(s) for s in template.split(text)[1:]]
        return list(zip(titles, texts))

    @classmethod
    @Logger.logging
    def trim(cls, string):
        string = Memo.head_blank_reg.sub('', string)
        string = Memo.tail_blank_reg.sub('', string)
        string = Memo.body_blank_reg.sub(r'\n\n', string)
        return string
示例#7
0
class TimeTableParser(Logger):
    """タイムテーブル解析器"""
    def __init__(self, date, config):
        self.year = date.year
        self.month = date.month
        self.day = date.day
        self.template = Regexplate(config['Journal']['TIME'])
        self.delim = config['Journal']['DELIM']
        super().__init__()
        return

    @Logger.logging
    def parse(self, string):
        phrases = [t for t in string.replace(' ', '').split(self.delim) if t]
        terms = [self.template.parse(p) for p in phrases]
        return [self.timetuple(t) for t in terms]

    @Logger.logging
    def timetuple(self, term):
        s = self.timestamp(term['SHOUR'], term['SMIN'])
        e = self.timestamp(term['EHOUR'], term['EMIN'])
        return (s, e - s)

    @Logger.logging
    def timestamp(self, hour, minute):
        return int(
            datetime.datetime(self.year, self.month, self.day, int(hour),
                              int(minute), 0).timestamp())
class TaskLineBuilder(Logger):
    """"""
    def __init__(self, date, config):
        self.root = config['Main']['ROOT']
        self.dlb = DeadLineBuilder(date, config)
        self.ttb = TimeTableBuilder(date, config)
        self.template = Regexplate(config['Journal']['TASKLINE'])
        super().__init__()

    @Logger.logging
    def build(self, task):
        return self.template.substitute(self.task_map(task))

    @Logger.logging
    def task_map(self, task):
        return {
            'PATH': self.short_path(task.path),
            'DEADLINE': self.dlb.build(task.deadline),
            'TIMETABLE': self.ttb.build(task.timetable),
        }

    @Logger.logging
    def short_path(self, path):
        if self.root not in path or path.index(self.root) != 0:
            return path
        else:
            return path.replace(self.root, '')
示例#9
0
class TimeTableBuilder(Logger):
    def __init__(self, date, config):
        t00 = datetime.datetime(date.year, date.month, date.day, 0, 0, 0)
        t24 = t00 + datetime.timedelta(1)
        self.t00 = int(t00.timestamp())
        self.t24 = int(t24.timestamp())
        self.template = Regexplate(config['Journal']['TIME'])
        self.delim = config['Journal']['DELIM']
        super().__init__()

    @Logger.logging
    def build(self, timetable):
        maps = [
            self.time_map(s, s + t) for s, t in timetable if self.at_date(s)
        ]
        return self.delim.join([self.template.substitute(m) for m in maps])

    @Logger.logging
    def at_date(self, ts):
        return self.t00 <= ts and ts < self.t24

    @Logger.logging
    def time_map(self, s, e):
        start = datetime.datetime.fromtimestamp(s)
        end = datetime.datetime.fromtimestamp(e)
        return {
            'SHOUR': start.hour,
            'SMIN': '{:02}'.format(start.minute),
            'EHOUR': end.hour,
            'EMIN': '{:02}'.format(end.minute)
        }
示例#10
0
 def __init__(self, date, config):
     self.today = date
     self.num_reg = re.compile('^-?\d+$')
     self.infstr = config['Journal']['INFSTR']
     self.template = Regexplate(config['Journal']['DATE'])
     super().__init__()
     return
示例#11
0
class JournalBuilder(Logger):
    def __init__(self, tmpl, config):
        self.template = Regexplate(tmpl)
        self.config = config
        super().__init__()

    @Logger.logging
    def build(self, date, tasks, memo):
        self.tcb = TaskChunkBuilder(date, self.config)
        return self.template.substitute({
            'YEAR':
            date.year,
            'MONTH':
            date.month,
            'DAY':
            date.day,
            'OPENCHUNK':
            self.tcb.build([t for t in tasks if t.status == Tasktory.OPEN]),
            'WAITCHUNK':
            self.tcb.build([t for t in tasks if t.status == Tasktory.WAIT]),
            'CLOSECHUNK':
            self.tcb.build([t for t in tasks if t.status == Tasktory.CLOSE]),
            'MEMO':
            memo,
        })
示例#12
0
class TimeTableParser(Logger):
    """タイムテーブル解析器"""

    def __init__(self, date, config):
        self.year = date.year
        self.month = date.month
        self.day = date.day
        self.template = Regexplate(config['Journal']['TIME'])
        self.delim = config['Journal']['DELIM']
        super().__init__()
        return

    @Logger.logging
    def parse(self, string):
        phrases = [t for t in string.replace(' ', '').split(self.delim) if t]
        terms = [self.template.parse(p) for p in phrases]
        return [self.timetuple(t) for t in terms]

    @Logger.logging
    def timetuple(self, term):
        s = self.timestamp(term['SHOUR'], term['SMIN'])
        e = self.timestamp(term['EHOUR'], term['EMIN'])
        return (s, e-s)

    @Logger.logging
    def timestamp(self, hour, minute):
        return int(datetime.datetime(
            self.year, self.month, self.day, int(hour), int(minute), 0
            ).timestamp())
示例#13
0
class TimeTableBuilder(Logger):

    def __init__(self, date, config):
        t00 = datetime.datetime(date.year, date.month, date.day, 0, 0, 0)
        t24 = t00 + datetime.timedelta(1)
        self.t00 = int(t00.timestamp())
        self.t24 = int(t24.timestamp())
        self.template = Regexplate(config['Journal']['TIME'])
        self.delim = config['Journal']['DELIM']
        super().__init__()

    @Logger.logging
    def build(self, timetable):
        maps = [self.time_map(s, s+t) for s, t in timetable if self.at_date(s)]
        return self.delim.join([self.template.substitute(m) for m in maps])

    @Logger.logging
    def at_date(self, ts):
        return self.t00 <= ts and ts < self.t24

    @Logger.logging
    def time_map(self, s, e):
        start = datetime.datetime.fromtimestamp(s)
        end = datetime.datetime.fromtimestamp(e)
        return {'SHOUR': start.hour, 'SMIN': '{:02}'.format(start.minute),
                'EHOUR': end.hour, 'EMIN': '{:02}'.format(end.minute)}
示例#14
0
 def __init__(self, date, config):
     self.year = date.year
     self.month = date.month
     self.day = date.day
     self.template = Regexplate(config['Journal']['TIME'])
     self.delim = config['Journal']['DELIM']
     super().__init__()
     return
示例#15
0
 def __init__(self, date, config):
     t00 = datetime.datetime(date.year, date.month, date.day, 0, 0, 0)
     t24 = t00 + datetime.timedelta(1)
     self.t00 = int(t00.timestamp())
     self.t24 = int(t24.timestamp())
     self.template = Regexplate(config['Journal']['TIME'])
     self.delim = config['Journal']['DELIM']
     super().__init__()
示例#16
0
class TaskLineParser(Logger):
    """タスクライン解析器"""

    def __init__(self, date, config):
        self.dlp = DeadLineParser(date, config)
        self.ttp = TimeTableParser(date, config)
        self.template = Regexplate(config['Journal']['TASKLINE'])
        super().__init__()
        return

    @Logger.logging
    def parse(self, string):
        attrs = self.template.parse(string)
        return {'PATH': attrs['PATH'],
                'DEADLINE': self.dlp.parse(attrs['DEADLINE']),
                'TIMETABLE': self.ttp.parse(attrs['TIMETABLE'])}

    @Logger.logging
    def match(self, string):
        return self.template.match(string)
示例#17
0
class TaskLineParser(Logger):
    """タスクライン解析器"""
    def __init__(self, date, config):
        self.dlp = DeadLineParser(date, config)
        self.ttp = TimeTableParser(date, config)
        self.template = Regexplate(config['Journal']['TASKLINE'])
        super().__init__()
        return

    @Logger.logging
    def parse(self, string):
        attrs = self.template.parse(string)
        return {
            'PATH': attrs['PATH'],
            'DEADLINE': self.dlp.parse(attrs['DEADLINE']),
            'TIMETABLE': self.ttp.parse(attrs['TIMETABLE'])
        }

    @Logger.logging
    def match(self, string):
        return self.template.match(string)
示例#18
0
class DeadLineParser(Logger):
    """期日解析器"""

    def __init__(self, date, config):
        self.today = date
        self.num_reg = re.compile('^-?\d+$')
        self.infstr = config['Journal']['INFSTR']
        self.template = Regexplate(config['Journal']['DATE'])
        super().__init__()
        return

    @Logger.logging
    def parse(self, string):
        # @
        if string == '':
            return None

        # @@
        if string == self.infstr:
            return float('inf')

        # @d
        m = self.num_reg.match(string)
        if m:
            return self.today.toordinal() + int(m.group())

        date = self.template.parse(string)
        year = date['YEAR']
        month = int(date['MONTH'])
        day = int(date['DAY'])

        # @mm/dd
        if year is None:
            tmp_date = datetime.date(self.today.year, month, day)
            year = self.today.year + (0 if tmp_date >= self.today else 1)

        # @yy/mm/dd
        elif len(year) == 2:
            year = int(year) + self.today.year // 100 * 100
            tmp_date = datetime.date(year, month, day)
            year += 0 if tmp_date >= self.today else 100

        # YYYY/mm/dd
        else:
            year = int(year)

        return datetime.date(year, month, day).toordinal()
示例#19
0
class DeadLineParser(Logger):
    """期日解析器"""
    def __init__(self, date, config):
        self.today = date
        self.num_reg = re.compile('^-?\d+$')
        self.infstr = config['Journal']['INFSTR']
        self.template = Regexplate(config['Journal']['DATE'])
        super().__init__()
        return

    @Logger.logging
    def parse(self, string):
        # @
        if string == '':
            return None

        # @@
        if string == self.infstr:
            return float('inf')

        # @d
        m = self.num_reg.match(string)
        if m:
            return self.today.toordinal() + int(m.group())

        date = self.template.parse(string)
        year = date['YEAR']
        month = int(date['MONTH'])
        day = int(date['DAY'])

        # @mm/dd
        if year is None:
            tmp_date = datetime.date(self.today.year, month, day)
            year = self.today.year + (0 if tmp_date >= self.today else 1)

        # @yy/mm/dd
        elif len(year) == 2:
            year = int(year) + self.today.year // 100 * 100
            tmp_date = datetime.date(year, month, day)
            year += 0 if tmp_date >= self.today else 100

        # YYYY/mm/dd
        else:
            year = int(year)

        return datetime.date(year, month, day).toordinal()
示例#20
0
class JournalBuilder(Logger):

    def __init__(self, tmpl, config):
        self.template = Regexplate(tmpl)
        self.config = config
        super().__init__()

    @Logger.logging
    def build(self, date, tasks, memo):
        self.tcb = TaskChunkBuilder(date, self.config)
        return self.template.substitute({
            'YEAR': date.year, 'MONTH': date.month, 'DAY': date.day,
            'OPENCHUNK': self.tcb.build(
                [t for t in tasks if t.status == Tasktory.OPEN]),
            'WAITCHUNK': self.tcb.build(
                [t for t in tasks if t.status == Tasktory.WAIT]),
            'CLOSECHUNK': self.tcb.build(
                [t for t in tasks if t.status == Tasktory.CLOSE]),
            'MEMO': memo,
            })
示例#21
0
 def __init__(self, date, config):
     self.root = config['Main']['ROOT']
     self.dlb = DeadLineBuilder(date, config)
     self.ttb = TimeTableBuilder(date, config)
     self.template = Regexplate(config['Journal']['TASKLINE'])
     super().__init__()
示例#22
0
class JournalParser(Logger):
    """ジャーナル解析器"""
    def __init__(self, tmpl, config):
        self.template = Regexplate(tmpl)
        self.config = config
        self.mp = MemoParser(config)
        super().__init__()
        return

    @Logger.logging
    def parse(self, text):
        # ジャーナルをパース
        if not self.template.match(text):
            raise JournalParserNoMatchTemplateError()
        attrs = self.template.parse(text)

        # 日付を取得
        date = datetime.date(int(attrs['YEAR']), int(attrs['MONTH']),
                             int(attrs['DAY']))

        # 各タスクチャンクをパース
        tcp = TaskChunkParser(date, self.config)
        tasks = [
            self.ps(d, Tasktory.OPEN) for d in tcp.parse(attrs['OPENCHUNK'])
        ]
        tasks += [
            self.ps(d, Tasktory.WAIT) for d in tcp.parse(attrs['WAITCHUNK'])
        ]
        tasks += [
            self.ps(d, Tasktory.CLOSE) for d in tcp.parse(attrs['CLOSECHUNK'])
        ]

        # タスクの重複チェック
        if self.duplicate_task(tasks):
            raise JournalParserDuplicateTaskError()

        # 作業時間の重複チェック
        if self.duplicate_timetable(tasks):
            raise JournalParserOverlapTimeTableError()

        # メモを取得
        memo = self.mp.parse(attrs['MEMO'])

        return date, tasks, memo, attrs["MEMO"]

    @staticmethod
    def duplicate_task(tasks):
        """同じタスクが複数存在する場合Trueを返す"""
        return len(tasks) != len(set([t['PATH'] for t in tasks]))

    @staticmethod
    def duplicate_timetable(tasks):
        """作業時間に重複があればTrueを返す"""
        tbl = sorted(sum([t['TIMETABLE'] for t in tasks], []),
                     key=lambda t: t[0])
        return not all(convolute(lambda v, a: (sum(a) <= v[0], v), tbl,
                                 (0, 0)))

    @staticmethod
    def ps(d, s):
        d['STATUS'] = s
        return d
示例#23
0
 def __init__(self, tmpl, config):
     self.template = Regexplate(tmpl)
     self.config = config
     super().__init__()
示例#24
0
 def __init__(self, tmpl, config):
     self.template = Regexplate(tmpl)
     self.config = config
     super().__init__()
示例#25
0
 def __init__(self, date, config):
     self.dlp = DeadLineParser(date, config)
     self.ttp = TimeTableParser(date, config)
     self.template = Regexplate(config['Journal']['TASKLINE'])
     super().__init__()
     return
示例#26
0
 def __init__(self, tmpl, config):
     self.template = Regexplate(tmpl)
     self.config = config
     self.mp = MemoParser(config)
     super().__init__()
     return
示例#27
0
 def __init__(self, date, config):
     self.root = config['Main']['ROOT']
     self.dlb = DeadLineBuilder(date, config)
     self.ttb = TimeTableBuilder(date, config)
     self.template = Regexplate(config['Journal']['TASKLINE'])
     super().__init__()
示例#28
0
class JournalParser(Logger):
    """ジャーナル解析器"""

    def __init__(self, tmpl, config):
        self.template = Regexplate(tmpl)
        self.config = config
        self.mp = MemoParser(config)
        super().__init__()
        return

    @Logger.logging
    def parse(self, text):
        # ジャーナルをパース
        if not self.template.match(text):
            raise JournalParserNoMatchTemplateError()
        attrs = self.template.parse(text)

        # 日付を取得
        date = datetime.date(
                int(attrs['YEAR']), int(attrs['MONTH']), int(attrs['DAY']))

        # 各タスクチャンクをパース
        tcp = TaskChunkParser(date, self.config)
        tasks = [
                self.ps(d, Tasktory.OPEN)
                for d in tcp.parse(attrs['OPENCHUNK'])]
        tasks += [
                self.ps(d, Tasktory.WAIT)
                for d in tcp.parse(attrs['WAITCHUNK'])]
        tasks += [
                self.ps(d, Tasktory.CLOSE)
                for d in tcp.parse(attrs['CLOSECHUNK'])]

        # タスクの重複チェック
        if self.duplicate_task(tasks):
            raise JournalParserDuplicateTaskError()

        # 作業時間の重複チェック
        if self.duplicate_timetable(tasks):
            raise JournalParserOverlapTimeTableError()

        # メモを取得
        memo = self.mp.parse(attrs['MEMO'])

        return date, tasks, memo, attrs["MEMO"]

    @staticmethod
    def duplicate_task(tasks):
        """同じタスクが複数存在する場合Trueを返す"""
        return len(tasks) != len(set([t['PATH'] for t in tasks]))

    @staticmethod
    def duplicate_timetable(tasks):
        """作業時間に重複があればTrueを返す"""
        tbl = sorted(
                sum([t['TIMETABLE'] for t in tasks], []),
                key=lambda t: t[0])
        return not all(convolute(
            lambda v, a: (sum(a) <= v[0], v), tbl, (0, 0)
            ))

    @staticmethod
    def ps(d, s):
        d['STATUS'] = s
        return d
示例#29
0
 def __init__(self, config):
     self.root = config['Main']['ROOT']
     self.template = Regexplate(config['Journal']['MEMOTITLE'])
     super().__init__()
     return
示例#30
0
 def __init__(self, date, config):
     self.dlp = DeadLineParser(date, config)
     self.ttp = TimeTableParser(date, config)
     self.template = Regexplate(config['Journal']['TASKLINE'])
     super().__init__()
     return
示例#31
0
 def __init__(self, tmpl, config):
     self.template = Regexplate(tmpl)
     self.config = config
     self.mp = MemoParser(config)
     super().__init__()
     return