Advertisement
FocusedWolf

EFT: Clock

Jul 26th, 2023 (edited)
968
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.61 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. # Version 28
  4.  
  5. # POSTED ONLINE: https://pastebin.com/BZV5c4a6
  6.  
  7. # SOURCE: https://tarkov-time.adam.id.au/
  8. # SOURCE: https://www.reddit.com/r/EscapefromTarkov/comments/u89ccn/i_made_a_physical_eft_clock_so_i_can_tell_when/i5kg22h/
  9. # SOURCE: https://escapefromtarkov.fandom.com/wiki/How_to_Play_Guide_for_Escape_from_Tarkov#IRL_time_vs_EFT_time
  10. # SOURCE: https://www.reddit.com/r/EscapefromTarkov/comments/ur05bc/at_what_time_of_the_raid_is_it_the_most_dark/
  11.  
  12. # -----
  13.  
  14. # Added text to prevent emoji replacement which tend to be smaller.
  15. CULTIST = '~&'
  16. #  CULTIST = "🗡\uFE0E"
  17. #  CULTIST = "🥷"
  18. #  CULTIST = "⛧\uFE0E"
  19. CULTIST = "🕯\uFE0E"
  20.  
  21. LEFT_ARROW = '<'
  22. LEFT_ARROW = "◀"
  23.  
  24. RIGHT_ARROW = '>'
  25. RIGHT_ARROW = "▶"
  26.  
  27. # -----
  28.  
  29. BLACK = '\033[30m'
  30. RED = '\033[31m'
  31. GREEN = '\033[32m'
  32. YELLOW = '\033[33m'
  33. BLUE = '\033[34m'
  34. MAGENTA = '\033[35m'
  35. CYAN = '\033[36m'
  36. WHITE = '\033[37m'
  37. BRIGHT_BLACK = '\033[90m'
  38. BRIGHT_RED = '\033[91m'
  39. BRIGHT_GREEN = '\033[92m'
  40. BRIGHT_YELLOW = '\033[93m'
  41. BRIGHT_BLUE = '\033[94m'
  42. BRIGHT_MAGENTA = '\033[95m'
  43. BRIGHT_CYAN = '\033[96m'
  44. BRIGHT_WHITE = '\033[97m'
  45. RESET = '\033[0m'
  46. BOLD = '\033[1m'
  47. HALF_BRIGHT = '\033[2m'
  48. ITALIC = '\033[3m'
  49. UNDERLINE = '\033[4m'
  50. REVERSED = '\033[7m'
  51.  
  52. # -----
  53.  
  54. DAY_BRIGHT = BRIGHT_YELLOW
  55. DAY_MORB = YELLOW
  56. NIGHT = BRIGHT_BLACK
  57. UI_CHEVRON = RED
  58. UI_CULTIST = RED
  59. UI_ETA = BRIGHT_WHITE #BRIGHT_CYAN
  60. UI_LABELS = CYAN
  61.  
  62. DAY_BRIGHT = WHITE
  63. DAY_MORB = YELLOW
  64. NIGHT = BRIGHT_BLACK
  65. UI_CHEVRON = RED
  66. UI_CULTIST = RED
  67. UI_ETA = CYAN
  68. UI_LABELS = RED #BRIGHT_MAGENTA #BRIGHT_GREEN
  69.  
  70. #
  71. #  DAY_BRIGHT = WHITE
  72. #  DAY_MORB = YELLOW
  73. #  NIGHT = BRIGHT_BLACK
  74. #  UI_CHEVRON = RED
  75. #  UI_CULTIST = RED
  76. #  UI_ETA = RED
  77. #  UI_LABELS = RED#MAGENTA #BRIGHT_MAGENTA #BRIGHT_GREEN
  78.  
  79. # -----
  80.  
  81. #  DAY_BRIGHT = BOLD + BRIGHT_CYAN
  82. #  DAY_MORB = BOLD + BRIGHT_BLUE
  83. #  NIGHT = BOLD + BRIGHT_GREEN
  84. #  UI_CHEVRON = BOLD + RED
  85. #  UI_ETA = BOLD + BRIGHT_BLACK
  86. #  UI_LABELS = BOLD + BRIGHT_BLACK
  87.  
  88. # -----
  89.  
  90. import datetime
  91.  
  92. TARKOV_SECONDS_PER_SECOND = 7 # Seven seconds in Tarkov is one second IRL.
  93. CHARLIE_TIMEZONE = datetime.timezone(datetime.timedelta(hours=3)) # Tarkov uses St. Petersburg - MSK (UTC+3) timezone.
  94. TWELVE_HOUR_SHIFT = datetime.timedelta(hours=12) # Right time is +12 hours ahead of left time.
  95. def get_tarkov_time():
  96.     utc_time = datetime.datetime.now(datetime.timezone.utc)
  97.     tarkov_left_time = datetime.datetime.fromtimestamp(utc_time.timestamp() * TARKOV_SECONDS_PER_SECOND, CHARLIE_TIMEZONE)
  98.     tarkov_right_time = tarkov_left_time + TWELVE_HOUR_SHIFT
  99.     return tarkov_left_time, tarkov_right_time
  100.  
  101. def convert_tarkov_timedelta_to_irl(tarkov_time_delta):
  102.     irl_time_delta = tarkov_time_delta / TARKOV_SECONDS_PER_SECOND
  103.     # Zero the microseconds created by the division because this is the easiest way to hide them.
  104.     irl_time_delta_without_microseconds = irl_time_delta - datetime.timedelta(microseconds=irl_time_delta.microseconds)
  105.     return irl_time_delta_without_microseconds
  106.  
  107. # -----
  108.  
  109. TIME_PERIODS = [
  110.     (0,  'Moonrise'),
  111.     (1,  'Low Moon'),
  112.     (2,  'Medium Moon'),
  113.     (3,  'High Moon'),
  114.     (4,  'No Moon'),
  115.     (5,  'Dawn'),
  116.  
  117.     (6,  'Sunrise'),
  118.     (7,  'Morning'),
  119.     (8,  'Early Day'),
  120.     (9,  'Mid Morning'),
  121.     (10, 'Late Morning'),
  122.     (11, 'Pre Noon'),
  123.  
  124.     (12, 'High Noon'),
  125.     (13, 'Post Meridiem'),
  126.     (14, 'Early Afternoon'),
  127.     (15, 'Mid Afternoon'),
  128.     (16, 'Late Afternoon'),
  129.     (17, 'Pre Dusk'),
  130.  
  131.     (18, 'Early Dusk'),
  132.     (19, 'Late Dusk'),
  133.     (20, 'Sunset'),
  134.     (21, 'Twilight'),
  135.     (22, 'Early Night'),
  136.     (23, 'Deep Night'),
  137. ]
  138.  
  139. MAX_TIME_PERIOD_WIDTH = max(len(time_period[1]) for time_period in TIME_PERIODS)
  140. def get_time_period_name(date_time):
  141.     for hour, time_period in sorted(TIME_PERIODS, reverse=True):
  142.         if date_time.hour >= hour:
  143.             return time_period
  144.  
  145. def format_time(date_time):
  146.     return date_time.strftime('%H:%M:%S')
  147.  
  148. def format_hour(date_time):
  149.     return date_time.strftime('%H')
  150.  
  151. def format_eta(time_delta):
  152.     total_seconds = int(time_delta.total_seconds())
  153.     days, remainder = divmod(total_seconds, 86400)
  154.     hours, remainder = divmod(remainder, 3600)
  155.     minutes, seconds = divmod(remainder, 60)
  156.     return f'T-{f"{days:02d}:" if days > 0 else ""}{hours:02d}:{minutes:02d}:{seconds:02d}'
  157.  
  158. # -----
  159.  
  160. def day_night_rotate_eta(date_time):
  161.     if is_any_daylight(date_time):
  162.         future_time = datetime.time(hour=DAYLIGHT_END, minute=0, second=0)
  163.     else:
  164.         future_time = datetime.time(hour=DAY_START, minute=0, second=0)
  165.     return eta(date_time, future_time)
  166.  
  167. # The left and right times are 12 hours apart.
  168. DAY_START = 6
  169. DAY_END = DAY_START + 12
  170. def is_day(date_time):
  171.     return DAY_START <= date_time.hour < DAY_END
  172.  
  173. # SOURCE: https://www.reddit.com/r/EscapefromTarkov/comments/7wwbmw/bsg_why_are_there_16_hours_of_daylight_in_this/
  174. DAYLIGHT_END = DAY_START + 16 # Dim daylight end time.
  175. def is_any_daylight(date_time):
  176.     return DAY_START <= date_time.hour < DAYLIGHT_END
  177.  
  178. BRIGHT_DAYLIGHT_START = 8 # Bright daylight start time.
  179. def is_bright_daylight(date_time):
  180.     # TODO: This was < DAY_END but apparently this hour its mostly bright except for last 2 minutes?
  181.     return BRIGHT_DAYLIGHT_START <= date_time.hour <= DAY_END
  182.  
  183. # SOURCE: ["Cultists appear between 22:00 and 7:00"] https://escapefromtarkov.fandom.com/wiki/Cultists
  184. # SOURCE: ["Between the times of 22:00 and 6:00"] https://youtu.be/pwIWGq6QACQ?si=fIPJFb-DrPObOzl_&t=269
  185. # SOURCE: ["So approximately 6:00 by Tarkov time they stand up and go into some place to despawn and just disappear. Their dead bodies do not disappear."] https://www.reddit.com/r/EscapefromTarkov/comments/14kan9b/i_always_was_wonder_how_when_and_does_cultists/
  186. # SOURCE: ["The Boss (Priest) spawns from 11PM to 6AM. After sunrise, the cultists disappear from the map."] https://tarkov.help/en/article/cultists
  187. # SOURCE: ["They absolutely despawn around 5:30 am"] https://www.reddit.com/r/EscapefromTarkov/comments/r14frs/cultist_despawn_at_daylight/
  188. # SOURCE: ["Cultists spawn from 23:00 (11 PM) to 5:00 (5 AM)"] https://www.reddit.com/r/EscapefromTarkov/comments/l69pvx/i_found_the_cultist_priest_on_day_time_woods/gkzxjpb/
  189. # SOURCE: ["I always thought they stopped spawning at 5 am not 7 am...22-5 you are correct."] https://www.reddit.com/r/EscapefromTarkov/comments/wvq6a4/how_do_cultist_spawns_really_work/
  190. # SOURCE: Cultist Spawn Locations: https://escapefromtarkov.fandom.com/wiki/Cultists
  191. #         Customs=1 priest + 4 warriors at scav base (ZB-013 extraction).
  192. #         Woods=1 priest + 4 warriors near their ritual places which are located west of sawmill and also at the dilapidated village in the north.
  193. #         Shoreline= 1 priest + 3 warriors at health resort and(rare)/or north-east of the swamp village.
  194. #         Night Factory=1 priest + 2 warriors.
  195. CULTIST_SPAWN_START = 22
  196. CULTIST_SPAWN_END = 7 # TODO: The wiki says 7 but a lot of sources say this should be 5, to represent 05:00 - 05:59, with 06:00 being when cultists despawn but need more info.
  197. def is_cultist_time(date_time):
  198.     return not (CULTIST_SPAWN_END < date_time.hour < CULTIST_SPAWN_START)
  199.  
  200. def eta(date_time, future_time):
  201.     future_date_time = date_time.replace(hour=future_time.hour, minute=future_time.minute, second=future_time.second)
  202.     if future_date_time < date_time:
  203.         future_date_time += datetime.timedelta(days=1)
  204.     remaining_time_delta = future_date_time - date_time
  205.     return remaining_time_delta, future_date_time
  206.  
  207. def color_hour(string, date_time):
  208.     return color(string, DAY_BRIGHT if is_bright_daylight(date_time) else DAY_MORB if is_any_daylight(date_time) else NIGHT)
  209.  
  210. def color(var, color):
  211.     return color + str(var) + RESET
  212.  
  213. def color_ljust(string, width, fillchar=' '):
  214.     if color_len(string) >= width:
  215.         return string
  216.     return string + fillchar * (width - color_len(string))
  217.  
  218. def color_rjust(string, width, fillchar=' '):
  219.     if color_len(string) >= width:
  220.         return string
  221.     return fillchar * (width - color_len(string)) + string
  222.  
  223. import re
  224. def color_len(string):
  225.     # Remove color codes to measure visible characters.
  226.     return len(re.sub(r'\033\[\d+m', '', string))
  227.  
  228. import os
  229. def clear():
  230.     os.system('cls' if os.name in ('nt', 'dos') else 'clear')
  231.  
  232. import time
  233. def sleep(milliseconds):
  234.     time.sleep(milliseconds / 1000)
  235.  
  236. ALIGN_LEFT = '<'
  237. ALIGN_RIGHT = '>'
  238. ALIGN_CENTER = '^'
  239.  
  240. # -----
  241.  
  242. def main():
  243.     while True:
  244.         clear() # Need to clear before color(...) can be used.
  245.         print()
  246.  
  247.         left_time, right_time = get_tarkov_time()
  248.         left_time_display = color_hour(f'{get_time_period_name(left_time)} {format_time(left_time)}', left_time)
  249.         right_time_display = color_hour(f'{get_time_period_name(right_time)} {format_time(right_time)}', right_time)
  250.  
  251.         left_day_night_rotate_eta, left_day_night_rotate_time = day_night_rotate_eta(left_time)
  252.         left_rotate_time_display = f'{color_hour(get_time_period_name(left_day_night_rotate_time), left_day_night_rotate_time)} {color(format_eta(convert_tarkov_timedelta_to_irl(left_day_night_rotate_eta)), UI_ETA)}'
  253.  
  254.         right_day_night_rotate_eta, right_day_night_rotate_time = day_night_rotate_eta(right_time)
  255.         right_rotate_time_display = f'{color_hour(get_time_period_name(right_day_night_rotate_time), right_day_night_rotate_time)} {color(format_eta(convert_tarkov_timedelta_to_irl(right_day_night_rotate_eta)), UI_ETA)}'
  256.  
  257.         # Measure length for alignment. Needs to be done without color(...) codes.
  258.         max_length_before_divider = max(color_len(left_time_display), color_len(left_rotate_time_display))
  259.         max_length_after_divider = max(color_len(right_time_display), color_len(right_rotate_time_display))
  260.  
  261.         # Print current tarkov server times.
  262.         L = color_rjust(left_time_display, max_length_before_divider)
  263.         R = color_ljust(right_time_display, max_length_after_divider)
  264.         print(f' {color(f" Tarkov Times:", UI_LABELS)} {L} {color("-", UI_LABELS)} {R}')
  265.  
  266.         # Print IRL ETA for when day/night switch.
  267.         L = color_rjust(left_rotate_time_display, max_length_before_divider)
  268.         R = color_ljust(right_rotate_time_display, max_length_after_divider)
  269.         print(f' {color(f" Rotate Times:", UI_LABELS)} {L} {color("-", UI_LABELS)} {R}')
  270.  
  271.         # -----
  272.  
  273.         # Print time-progressbar.
  274.         print()
  275.         print('  ', end='')
  276.         # For [0,24).
  277.         for h in range(24):
  278.             h_time = datetime.time(hour=h)
  279.             if is_cultist_time(h_time):
  280.                 print(color(f'{CULTIST} ', UI_CULTIST), end='')
  281.             else:
  282.                 print('   ', end='')
  283.         print()
  284.         print('  ', end='')
  285.         # For [0,24).
  286.         for h in range(24):
  287.             h_time = datetime.time(hour=h)
  288.             if h == left_time.hour or h == right_time.hour:
  289.                 print(color_hour(f'╳╳ ', h_time), end='')
  290.                 #  print(color_hour(f'◀▶ ', h_time), end='')
  291.             else:
  292.                 print(color_hour(f'██ ', h_time), end='')
  293.         print()
  294.         print('  ', end='')
  295.         # For [0,24).
  296.         for h in range(24):
  297.             h_time = datetime.time(hour=h)
  298.             print(color_hour(h_time.strftime('%H '), h_time), end='')
  299.         print()
  300.  
  301.         # -----
  302.  
  303.         # Print time-period names while indicating which slot we are in.
  304.         #  print()
  305.         #  for h in range(DAY_START, DAY_END):
  306.         #      h_time = datetime.datetime.now().replace(hour=h, minute=0, second=0)
  307.         #      if not is_day(left_time):
  308.         #          h_time -= TWELVE_HOUR_SHIFT
  309.         #      left_game_time = color_hour(f'{get_time_period_name(h_time):{ALIGN_RIGHT}{MAX_TIME_PERIOD_WIDTH}} {format_hour(h_time)}', h_time)
  310.         #      h_time += TWELVE_HOUR_SHIFT
  311.         #      right_game_time = color_hour(f'{format_hour(h_time)} {get_time_period_name(h_time)}', h_time)
  312.         #      on_time = left_time.hour == h or right_time.hour == h
  313.         #      left_bead = color(LEFT_ARROW if on_time else ' ', UI_CHEVRON)
  314.         #      closest_time_eta = min(eta(left_time, h_time)[0], eta(right_time, h_time)[0])
  315.         #      irl_time = color(format_eta(convert_tarkov_timedelta_to_irl(closest_time_eta)), UI_ETA)
  316.         #      right_bead = color(RIGHT_ARROW if on_time else ' ', UI_CHEVRON)
  317.         #      print(f' {left_game_time} {left_bead} {irl_time} {right_bead} {right_game_time}')
  318.  
  319.         # In this version the beads are matching the hour colors, but idk if i like this due to how hard they are to spot due to the different colors.
  320.         #
  321.         # Print time-period names while indicating which slot we are in.
  322.         print()
  323.         for h in range(DAY_START, DAY_END):
  324.             h_time = datetime.datetime.now().replace(hour=h, minute=0, second=0)
  325.             if not is_day(left_time):
  326.                 h_time -= TWELVE_HOUR_SHIFT
  327.             left_game_time = color_hour(f'{get_time_period_name(h_time):{ALIGN_RIGHT}{MAX_TIME_PERIOD_WIDTH}} {format_hour(h_time)} {LEFT_ARROW if left_time.hour == h_time.hour else " "}', h_time)
  328.             h_time += TWELVE_HOUR_SHIFT
  329.             right_game_time = color_hour(f'{RIGHT_ARROW if right_time.hour == h_time.hour else " "} {format_hour(h_time)} {get_time_period_name(h_time)}', h_time)
  330.             on_time = left_time.hour == h or right_time.hour == h
  331.             closest_time_eta = min(eta(left_time, h_time)[0], eta(right_time, h_time)[0])
  332.             irl_time = color(format_eta(convert_tarkov_timedelta_to_irl(closest_time_eta)), UI_ETA)
  333.             print(f' {left_game_time} {irl_time} {right_game_time}')
  334.  
  335.         sleep(1000)
  336.  
  337. if __name__ == '__main__':
  338.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement