Jt.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. from sys import flags
  2. from color_printing import ERROR, INFO, STATUS, WARNING, cstr, log_print
  3. import datetime
  4. import pickle
  5. import random
  6. import sys
  7. import time
  8. from hashlib import md5
  9. from os import listdir
  10. class Base:
  11. def __init__(self):
  12. self.create_time = time.time()
  13. self.create_date: datetime.datetime = datetime.datetime.utcfromtimestamp(
  14. self.create_time)
  15. self.str_time = time.strftime(
  16. "%Y%m%d%H%M%S", time.gmtime(self.create_time))
  17. self.__gene_id()
  18. def __gene_id(self):
  19. self.__id_seed: str = self.str_time + str(random.randint(10000, 99999))
  20. self.id: str = md5(self.__id_seed.encode("UTF-8")).hexdigest()
  21. class Entry(Base):
  22. def __init__(self, title: str = "未命名事项"):
  23. Base.__init__(self)
  24. if title == "未命名事项":
  25. self.title: str = title + self.str_time[4:8]
  26. else:
  27. self.title: str = title
  28. self.__content: str = "事项内容"
  29. self.set_priority()
  30. self.set_start_date()
  31. self.set_deadline(self.create_date + datetime.timedelta(days=7))
  32. self.time_total : datetime.timedelta = self.deadline-self.start_date
  33. self.time_left : datetime.timedelta = self.deadline - datetime.datetime.today()
  34. # self.sub_entries_dict: dict = {}
  35. def set_priority(self, priority: float = 0):
  36. if priority < -10:
  37. print("最低优先级为-10,已自动设置为-10")
  38. priority = -10.0
  39. elif priority > 10:
  40. print("最高优先级为10,已自动设置为10")
  41. priority = 10.0
  42. self.priority: float = priority
  43. def set_deadline(self, deadline_date: datetime.datetime):
  44. """This function will set the entry's deadline date
  45. Args:
  46. deadline_date (float): The deadline date must be datetime structure.
  47. Returns:
  48. bool : If successfully set the deadline will return 0, else 1.
  49. """
  50. if deadline_date < self.start_date:
  51. print("\033[1;31mERROR: Let it RIP if it's dead already\033[0m")
  52. return 1
  53. else:
  54. self.deadline = deadline_date
  55. return 0
  56. def set_start_date(self, start_date: datetime.datetime = datetime.datetime(1970, 1, 1, 0, 0, 0)):
  57. if start_date == datetime.datetime(1970, 1, 1, 0, 0, 0):
  58. self.start_date = self.create_date
  59. else:
  60. self.start_date = start_date
  61. def set_content(self, content: str):
  62. self.__content = content
  63. def timestamp_converter(self, time_in):
  64. """This function can convert timestamp to date string and do reversely.
  65. Args:
  66. time_in (float/ str): Timestamp as float or date string like "YYYY/mm/dd HH:MM".
  67. Returns:
  68. timestamp or date string.
  69. """
  70. try:
  71. _time_in = float(time_in)
  72. return datetime.datetime.utcfromtimestamp(_time_in)
  73. except ValueError:
  74. return time.mktime(time.strptime(time_in, "%Y/%m/%d %H:%M"))
  75. def str_to_date(self, date_in: str) -> datetime.datetime:
  76. """Convert date string like "%Y/%m/%d %H:%M" or "%Y/%m/%d %H:%M" to datetime structure
  77. Args:
  78. date_in (str): "%Y/%m/%d %H:%M", 2020/07/03 18:23
  79. Returns:
  80. datetime
  81. """
  82. try:
  83. date = datetime.datetime.strptime(date_in, "%Y/%m/%d")
  84. return date
  85. except ValueError:
  86. date = datetime.datetime.strptime(date_in, "%Y/%m/%d %H:%M")
  87. return date
  88. def date_input(self) -> datetime.datetime:
  89. while 1:
  90. try:
  91. str_in = input(
  92. cstr("Type in the date (%Y/%m/%d or %Y/%m/%d %H:%M): ", "g"))
  93. date :datetime.datetime = self.str_to_date(str_in)
  94. return date
  95. except:
  96. print("Care the correct date format.")
  97. class Coordinate(Base):
  98. def __init__(self):
  99. Base.__init__(self)
  100. self.name = "未命名坐标系" + self.str_time
  101. # Base.__gene_id(self)
  102. self.entries_dict = {}
  103. self.entries_num = 0
  104. def show_entries(self):
  105. print(self.entries_dict)
  106. def add_entry(self, entry_in: Entry):
  107. self.entries_dict[entry_in.id] = entry_in
  108. self.entries_num += 1
  109. def del_entry(self, entry_in: Entry):
  110. try:
  111. del self.entries_dict[entry_in.id]
  112. self.entries_num -= 1
  113. except KeyError:
  114. print("\033[1;31mERROR: Entry doesn't exist\033[0m")
  115. def save_coord(self):
  116. with open("coord/" + self.name + ".crd", "wb") as f:
  117. pickle.dump(self, f, pickle.HIGHEST_PROTOCOL)
  118. def __str__(self) -> str:
  119. return (
  120. "Title: "
  121. + self.name
  122. + "\nId: "
  123. + self.id
  124. + "\nEntries number: "
  125. + str(self.entries_num)
  126. )
  127. class Interface:
  128. def __init__(self):
  129. self.coordinate_dict: dict = {}
  130. self.exit: bool = False
  131. self.func_dict = {
  132. "exit": self.__exit,
  133. "open": self.__open_coord,
  134. "ls": self.__list_coord,
  135. "show": self.__show_now_coord,
  136. "entry": self.__new_entry,
  137. "chcrd": self.__coord_changer,
  138. }
  139. self.command_list: list = list(self.func_dict.keys())
  140. def start(self):
  141. try:
  142. print(
  143. "*******************************\n*Welcome to Jt mission manager*\n*******************************\n"
  144. )
  145. try:
  146. import completer
  147. completer.start_completer(self.command_list)
  148. log_print(STATUS, 'Auto complete: ON')
  149. # print("\033[1;32mAuto complete: ON\033[0m")
  150. except ModuleNotFoundError:
  151. log_print(WARNING, 'Auto complete: OFF. Module Not Found')
  152. # print("\033[1;31mWARNING: Auto complete: OFF. Module Not Found\033[0m")
  153. self.__coord_changer([])
  154. while not (self.exit):
  155. command = input("\033[1;32m> \033[0m").split()
  156. try:
  157. func_name = command[0]
  158. try:
  159. func = self.func_dict[func_name]
  160. func(command[1:])
  161. except KeyError:
  162. print("\033[1;31mERROR: Command not found\033[0m")
  163. except IndexError:
  164. pass
  165. except KeyboardInterrupt:
  166. self.__exit(1)
  167. def __open_coord(self, coord_file: str):
  168. with open(coord_file, "rb") as f:
  169. self.now_coord: Coordinate = pickle.load(f)
  170. def __list_coord(self, arg):
  171. """Detect the coord folder if there are any files.
  172. Args:
  173. arg (none): Meaningless, just give 1 or anything
  174. Returns:
  175. int: If multiple files exist, return 0, if empty, return -1, if only one, return 1.
  176. """
  177. self.files = listdir("coord")
  178. if len(self.files) == 1:
  179. print(cstr(f"Only one coordinate was found.\n{self.files}", 'y'))
  180. return 1
  181. if self.files:
  182. i = 0
  183. for f in self.files:
  184. print(i, f)
  185. i += 1
  186. return 0
  187. else:
  188. return -1
  189. def __coord_changer(self, arg: list):
  190. try:
  191. self.now_coord
  192. self.__save_now_coord()
  193. except AttributeError:
  194. pass
  195. list_result = self.__list_coord(0)
  196. if list_result==0:
  197. print("Select a coordinate to open:")
  198. coord_file = self.files[
  199. int(input("\033[1;32mType in the coordinate number:\033[0m"))
  200. ]
  201. self.__open_coord("coord/" + coord_file)
  202. elif list_result==1:
  203. print(cstr("Opening default coordinate.",'b'))
  204. self.__open_coord('coord/'+ self.files[0])
  205. elif list_result==-1:
  206. print(cstr('No coordinate exist','r'))
  207. def __save_now_coord(self, save_withou_asking:bool = False):
  208. if save_withou_asking:
  209. save_or_not = 'y'
  210. else:
  211. save_or_not: str = input("Save the opened coordinate? Y/n")
  212. if save_or_not in ["Y", "y", "1"]:
  213. self.now_coord.save_coord()
  214. return 0
  215. elif save_or_not in ["N", "n", "0"]:
  216. return 0
  217. else:
  218. self.__save_now_coord()
  219. def __new_entry(self, arg: list):
  220. e = Entry(arg[0])
  221. e.set_deadline(e.date_input())
  222. print(cstr("Input the content of this entry, use \"Ctrl+D\" to end.\n", 'g'))
  223. e.content = "\n".join(sys.stdin.readlines())
  224. print(e.content)
  225. print(e.time_left)
  226. def __new_coord(self, arg: list):
  227. c = Coordinate()
  228. c.name = arg[0]
  229. raise NotImplementedError
  230. def __show_now_coord(self, arg: list):
  231. print(self.now_coord)
  232. def __add_coordinate(self, c: Coordinate):
  233. if not c.id in self.coordinate_dict:
  234. self.coordinate_dict[c.id] = c
  235. else:
  236. print("\033[1;31mERROR: It's already in there\033[0m")
  237. def __exit(self, arg):
  238. log_print(WARNING, "Exiting...")
  239. self.__save_now_coord(True)
  240. log_print(INFO, "Coordinate saved.")
  241. self.exit = True
  242. def main():
  243. i = Interface()
  244. i.start()
  245. if __name__ == "__main__":
  246. main()