/// 대화 글자에 붙이는 업무 표시. 새 봉투 형식 없이 보통 대화로 오가고, 받는 쪽이 읽어서 업무 목록에 넣는다. /// /// 📌 업무 [김민수] 결제 API 정리 (마감 10/30) /// 🚨 긴급 호출: 서버가 멈췄어요 sealed class WorkNote { const WorkNote(); /// 대화 글자로. String encode(); /// 대화 글자에서 읽는다. 표시가 없으면 null. [now] 는 마감 연도를 정할 때 쓴다. static WorkNote? parse(String body, {DateTime? now}) { final t = body.trim(); if (t.startsWith(UrgentNote.prefix)) { final text = t.substring(UrgentNote.prefix.length).trim(); return UrgentNote(text); } if (t.startsWith(TaskNote.prefix)) return TaskNote._parse(t.substring(TaskNote.prefix.length).trim(), now: now); return null; } } /// 긴급 호출. class UrgentNote extends WorkNote { const UrgentNote(this.text); static const prefix = '🚨 긴급 호출:'; final String text; @override String encode() => text.isEmpty ? prefix : '$prefix $text'; } /// 업무 맡기기. [assignee] 는 이름(받는 쪽 기기에서 사람을 찾는 데 쓴다), [due] 는 마감 날짜. class TaskNote extends WorkNote { const TaskNote(this.title, {this.assignee, this.due}); static const prefix = '📌 업무'; final String title; final String? assignee; final DateTime? due; @override String encode() { final b = StringBuffer(prefix); if (assignee != null && assignee!.trim().isNotEmpty) b.write(' [${assignee!.trim().replaceAll(']', '')}]'); b.write(' ${title.trim()}'); if (due != null) b.write(' (마감 ${due!.month}/${due!.day})'); return b.toString(); } static final _who = RegExp(r'^\[([^\]]*)\]\s*'); static final _due = RegExp(r'\s*\(마감 (\d{1,2})/(\d{1,2})\)\s*$'); static TaskNote? _parse(String rest, {DateTime? now}) { var s = rest; String? who; final w = _who.firstMatch(s); if (w != null) { who = w.group(1)!.trim(); s = s.substring(w.end); } DateTime? due; final d = _due.firstMatch(s); if (d != null) { final m = int.parse(d.group(1)!), day = int.parse(d.group(2)!); if (m >= 1 && m <= 12 && day >= 1 && day <= 31) due = dueFrom(m, day, now ?? DateTime.now()); s = s.substring(0, d.start); } s = s.trim(); if (s.isEmpty) return null; return TaskNote(s, assignee: who == null || who.isEmpty ? null : who, due: due); } /// "10/30" 은 [now] 기준 가장 가까운 앞날 (지난 지 두 달이 넘었으면 내년). static DateTime dueFrom(int month, int day, DateTime now) { final thisYear = DateTime(now.year, month, day); return now.difference(thisYear).inDays > 60 ? DateTime(now.year + 1, month, day) : thisYear; } }