FocusedWolf

EFT: Clock

Jul 26th, 2023 (edited)
1,355
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.98 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. # Version 39 - A reddit moderator permanently banned me for saying this so i feel obligated to repost it: "Don't play Arenas. That's the sink for autist cheaters. Every game has someone that walks around like a bot with a crosshair locked on your forehead".
  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. # ----- Colors -----
  13. def ansi(code):
  14.     return f"\033[{code}m"
  15.  
  16. def rgb(r, g, b):
  17.     return ansi(f"38;2;{r};{g};{b}")
  18.  
  19. PURPLE = rgb(177, 72, 198) # Mingw64 purple.
  20. #  PURPLE = rgb(128, 0, 128) # True purple.
  21. BLACK = ansi(30)
  22. RED = ansi(31)
  23. GREEN = ansi(32)
  24. YELLOW = ansi(33)
  25. BLUE = ansi(34)
  26. MAGENTA = ansi(35)
  27. CYAN = ansi(36)
  28. WHITE = ansi(37)
  29. BRIGHT_BLACK = ansi(90)
  30. BRIGHT_RED = ansi(91)
  31. BRIGHT_GREEN = ansi(92)
  32. BRIGHT_YELLOW = ansi(93)
  33. BRIGHT_BLUE = ansi(94)
  34. BRIGHT_MAGENTA = ansi(95)
  35. BRIGHT_CYAN = ansi(96)
  36. BRIGHT_WHITE = ansi(97)
  37.  
  38. # ----- Styles -----
  39. RESET = ansi(0) # Reset all styles.
  40. BOLD = ansi(1)
  41. HALF_BRIGHT = ansi(2)
  42. ITALIC = ansi(3)
  43. UNDERLINE = ansi(4)
  44. REVERSED = ansi(7) # Reverse foreground and background colors.
  45.  
  46. # ----- Color Helpers -----
  47. def color(text, *codes):
  48.     return "".join(codes) + str(text) + RESET
  49.  
  50. # Use these in situations where you can't use alignment formatting codes and padding, because you have two different colored strings in a row.
  51. # In this situation the padding added will be too little because the colored string will appear longer then it appears because len() includes the invisible formatting tags in the total length of the string.
  52. # By applying coloring tags AFTER padding the strings, you can avoid needing these functions.
  53. #
  54. # NOTE: These functions are based on string.ljust and string.rjust.
  55. def color_ljust(string, width, fillchar=' '):
  56.     if color_len(string) >= width:
  57.         return string
  58.     return string + fillchar * (width - color_len(string))
  59.  
  60. def color_rjust(string, width, fillchar=' '):
  61.     if color_len(string) >= width:
  62.         return string
  63.     return fillchar * (width - color_len(string)) + string
  64.  
  65. import re
  66. def color_len(string):
  67.     # Remove formatting using regular expressions.
  68.     string = re.sub(r'\033\[[0-9;]*m', '', string)
  69.     return len(string)
  70.  
  71. # -----
  72.  
  73. import os
  74. def clear():
  75.     os.system('cls' if os.name in ('nt', 'dos') else 'clear')
  76. clear() # Need to clear before color(...) can be used.
  77.  
  78. # -----
  79.  
  80. DAY_BRIGHT = WHITE
  81. DAY_MORB = YELLOW
  82. NIGHT = BRIGHT_BLACK
  83. UI_CHEVRON = PURPLE #RED
  84. UI_CULTIST = PURPLE #BRIGHT_MAGENTA
  85. UI_ETA = CYAN
  86. UI_LABELS = BRIGHT_GREEN #RED #BRIGHT_MAGENTA
  87.  
  88. # -----
  89.  
  90. # Added text to prevent emoji replacement which tend to be smaller.
  91. CULTIST = '~&' # Cultist with a poison knife.
  92. #  CULTIST = "🗡\uFE0E"
  93. #  CULTIST = "🥷"
  94. #  CULTIST = "â›§\uFE0E"
  95. #  CULTIST = "🕯\uFE0E" # Only Windows 11 terminal can show this emoji.
  96. CULTIST = "🕯 " # Only Windows 11 terminal can show this emoji. Suddenly now i need to replace \uFE0E with space to fix alignment issue?
  97.  
  98. LEFT_ARROW = '<'
  99. LEFT_ARROW = "â—€"
  100.  
  101. RIGHT_ARROW = '>'
  102. RIGHT_ARROW = "â–¶"
  103.  
  104. # -----
  105.  
  106. import datetime
  107.  
  108. TARKOV_SECONDS_PER_SECOND = 7 # Seven seconds in Tarkov is one second IRL.
  109. CHARLIE_TIMEZONE = datetime.timezone(datetime.timedelta(hours=3)) # Tarkov uses St. Petersburg - MSK (UTC+3) timezone.
  110. TWELVE_HOUR_SHIFT = datetime.timedelta(hours=12) # Right time is +12 hours ahead of left time.
  111. def get_tarkov_time():
  112.     utc_time = datetime.datetime.now(datetime.timezone.utc)
  113.     tarkov_left_time = datetime.datetime.fromtimestamp(utc_time.timestamp() * TARKOV_SECONDS_PER_SECOND, CHARLIE_TIMEZONE)
  114.     tarkov_right_time = tarkov_left_time + TWELVE_HOUR_SHIFT
  115.     return tarkov_left_time, tarkov_right_time
  116.  
  117. def convert_tarkov_timedelta_to_irl(tarkov_time_delta):
  118.     irl_time_delta = tarkov_time_delta / TARKOV_SECONDS_PER_SECOND
  119.     # Zero the microseconds created by the division because this is the easiest way to hide them.
  120.     irl_time_delta_without_microseconds = irl_time_delta - datetime.timedelta(microseconds=irl_time_delta.microseconds)
  121.     return irl_time_delta_without_microseconds
  122.  
  123. def edit_time(dt, hour=None, minute=None, second=None, microsecond=None):
  124.     return datetime.datetime(
  125.         dt.year,
  126.         dt.month,
  127.         dt.day,
  128.         hour if hour is not None else dt.hour,
  129.         minute if minute is not None else dt.minute,
  130.         second if second is not None else dt.second,
  131.         microsecond if microsecond is not None else dt.microsecond,
  132.         tzinfo=dt.tzinfo
  133.     )
  134.  
  135. # -----
  136.  
  137. TIME_PERIODS = [
  138.     (0,  'Moonrise'),
  139.     (1,  'Low Moon'),
  140.     (2,  'Mid Moon'),
  141.     (3,  'High Moon'),
  142.     (4,  'No Moon'),
  143.     (5,  'Dawn'),
  144.  
  145.     (6,  'Sunrise'),
  146.     (7,  'Early Morning'),
  147.     (8,  'Mid Morning'),
  148.     (9,  'Late Morning'),
  149.     (10, 'Early Day'),
  150.     (11, 'Late Day'),
  151.  
  152.     (12, 'High Noon'),
  153.     (13, 'Early Afternoon'),
  154.     (14, 'Mid Afternoon'),
  155.     (15, 'Late Afternoon'),
  156.     (16, 'Early Evening'),
  157.     (17, 'Mid Evening'),
  158.  
  159.     (18, 'Late Evening'),
  160.     (19, 'Pre Sunset'),
  161.     (20, 'Sunset'),
  162.     (21, 'Twilight'),
  163.     (22, 'Early Night'),
  164.     (23, 'Deep Night'),
  165. ]
  166.  
  167. MAX_TIME_PERIOD_WIDTH = max(len(time_period[1]) for time_period in TIME_PERIODS)
  168. def get_time_period_name(dt):
  169.     for hour, time_period in sorted(TIME_PERIODS, reverse=True):
  170.         if dt.hour >= hour:
  171.             return time_period
  172.  
  173. def format_time(dt):
  174.     return dt.strftime('%H:%M:%S')
  175.  
  176. def format_hour(dt):
  177.     return dt.strftime('%H')
  178.  
  179. def format_eta(time_delta):
  180.     total_seconds = int(time_delta.total_seconds())
  181.     days, remainder = divmod(total_seconds, 86400)
  182.     hours, remainder = divmod(remainder, 3600)
  183.     minutes, seconds = divmod(remainder, 60)
  184.     return f'T-{f"{days:02d}:" if days > 0 else ""}{hours:02d}:{minutes:02d}:{seconds:02d}'
  185.  
  186. # -----
  187.  
  188. def day_night_rotate_eta(dt):
  189.     if is_bright_daylight(dt):
  190.         future_time = datetime.time(hour=BRIGHT_DAYLIGHT_END, minute=0, second=0)
  191.     else:
  192.         future_time = datetime.time(hour=BRIGHT_DAYLIGHT_START, minute=0, second=0)
  193.     return eta(dt, future_time)
  194.  
  195. # The left and right times are 12 hours apart.
  196. DAY_START = 6
  197. DAY_END = DAY_START + 12
  198. def is_day(dt):
  199.     return DAY_START <= dt.hour < DAY_END
  200.  
  201. # SOURCE: https://www.reddit.com/r/EscapefromTarkov/comments/7wwbmw/bsg_why_are_there_16_hours_of_daylight_in_this/
  202. DAYLIGHT_END = DAY_START + 16 # Dim daylight end time.
  203. def is_any_daylight(dt):
  204.     return DAY_START <= dt.hour < DAYLIGHT_END
  205.  
  206. BRIGHT_DAYLIGHT_START = DAY_START + 2 # Bright daylight start time.
  207. BRIGHT_DAYLIGHT_END = DAY_END + 2 # Sun is setting.
  208. def is_bright_daylight(dt):
  209.     return BRIGHT_DAYLIGHT_START <= dt.hour < BRIGHT_DAYLIGHT_END
  210.  
  211. # SOURCE: ["Cultists appear between 22:00 and 7:00"] https://escapefromtarkov.fandom.com/wiki/Cultists
  212. # SOURCE: ["Between the times of 22:00 and 6:00"] https://youtu.be/pwIWGq6QACQ?si=fIPJFb-DrPObOzl_&t=269
  213. # 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/
  214. # SOURCE: ["The Boss (Priest) spawns from 11PM to 6AM. After sunrise, the cultists disappear from the map."] https://tarkov.help/en/article/cultists
  215. # SOURCE: ["They absolutely despawn around 5:30 am"] https://www.reddit.com/r/EscapefromTarkov/comments/r14frs/cultist_despawn_at_daylight/
  216. # 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/
  217. # 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/
  218. # SOURCE: Cultist Spawn Locations: https://escapefromtarkov.fandom.com/wiki/Cultists
  219. #         Customs=1 priest + 4 warriors at scav base (ZB-013 extraction).
  220. #         Woods=1 priest + 4 warriors near their ritual places which are located west of sawmill and also at the dilapidated village in the north.
  221. #         Shoreline= 1 priest + 3 warriors at health resort and(rare)/or north-east of the swamp village.
  222. #         Night Factory=1 priest + 2 warriors.
  223. CULTIST_SPAWN_START = 22
  224. # CULTIST_SPAWN_END = 5 # 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.
  225. CULTIST_SPAWN_END = 7 # This guy says 7 AM but probably just quoting wiki. https://www.reddit.com/r/EscapefromTarkov/comments/1eq4n55/discussion_cultist_dagger_farming_for_night_sweep/
  226. def is_cultist_time(dt):
  227.     h = dt.hour
  228.     return h >= CULTIST_SPAWN_START or h <= CULTIST_SPAWN_END
  229.  
  230. def eta(dt, future_time):
  231.     future_dt = dt.replace(hour=future_time.hour, minute=future_time.minute, second=future_time.second)
  232.     if future_dt < dt:
  233.         future_dt += datetime.timedelta(days=1)
  234.     remaining_time_delta = future_dt - dt
  235.     return remaining_time_delta, future_dt
  236.  
  237. def color_hour(string, dt):
  238.     return color(string, DAY_BRIGHT if is_bright_daylight(dt) else DAY_MORB if is_any_daylight(dt) else NIGHT)
  239.  
  240. ALIGN_LEFT = '<'
  241. ALIGN_RIGHT = '>'
  242. ALIGN_CENTER = '^'
  243.  
  244. # -----
  245.  
  246. import time
  247.  
  248. def main():
  249.     while True:
  250.         print()
  251.         left_time, right_time = get_tarkov_time()
  252.         left_cultist = color(f'{" " + CULTIST if is_cultist_time(left_time) else ""}', UI_CULTIST)
  253.         right_cultist = color(f'{CULTIST + " " if is_cultist_time(right_time) else ""}', UI_CULTIST)
  254.         left_time_display = color_hour(f'{get_time_period_name(left_time)} {format_time(left_time)}', left_time) + left_cultist
  255.         right_time_display = right_cultist + color_hour(f'{format_time(right_time)} {get_time_period_name(right_time)}', right_time)
  256.  
  257.         day_night_composition = 'â–›' if is_day(left_time) else 'â–œ'
  258.         bright_daylight_eta, left_day_night_sector_time = day_night_rotate_eta(left_time)
  259.         #  print(f' {color(f" Tarkov Times:", UI_LABELS)} {color("[", UI_LABELS)} {left_time_display} {color("-", UI_LABELS)} {right_time_display} {color("]", UI_LABELS)} {color(day_night_composition, DAY_MORB)} {color(format_eta(convert_tarkov_timedelta_to_irl(bright_daylight_eta)), UI_ETA)}')
  260.         print(f' {color(f" Tarkov Times:", UI_LABELS)} {color("[", UI_LABELS)} {left_time_display} {color("-", UI_LABELS)} {right_time_display} {color("]", UI_LABELS)} {color(day_night_composition, DAY_BRIGHT)} {color(format_eta(convert_tarkov_timedelta_to_irl(bright_daylight_eta)), UI_ETA)}')
  261.  
  262.         # ----- Print horizontal time-progressbar -----
  263.  
  264.         # NOTE: Its kinda redundant to show this because cultist indicators are already visible on the vertical time list.
  265.         #       That's why i have it commented out.
  266.         #       It looks cool though.
  267.  
  268.         #  print()
  269.         #  print('  ', end='')
  270.         #  # For [0,24).
  271.         #  for h in range(24):
  272.         #      h_time = datetime.time(hour=h)
  273.         #      if is_cultist_time(h_time):
  274.         #          print(color(f'{CULTIST} ', UI_CULTIST), end='')
  275.         #      else:
  276.         #          print('   ', end='')
  277.         #  print()
  278.         #  print('  ', end='')
  279.         #  # For [0,24).
  280.         #  for h in range(24):
  281.         #      h_time = datetime.time(hour=h)
  282.         #      if h == left_time.hour or h == right_time.hour:
  283.         #          print(color_hour(f'╳╳ ', h_time), end='')
  284.         #          #  print(color_hour(f'◀▶ ', h_time), end='')
  285.         #      else:
  286.         #          print(color_hour(f'██ ', h_time), end='')
  287.         #  print()
  288.         #  print('  ', end='')
  289.         #  # For [0,24).
  290.         #  for h in range(24):
  291.         #      h_time = datetime.time(hour=h)
  292.         #      print(color_hour(h_time.strftime('%H '), h_time), end='')
  293.         #  print()
  294.  
  295.         # ----- Print time-period names while indicating what slot we are on -----
  296.  
  297.         # Cultist-spawn indicators and arrows are colored UI_CHEVRON.
  298.         #  print()
  299.         #  for h in range(DAY_START, DAY_END):
  300.         #      h_time = edit_time(left_time, hour=h, minute=0, second=0)
  301.         #      if not is_day(left_time):
  302.         #          h_time -= TWELVE_HOUR_SHIFT
  303.         #      left_game_time = color_hour(f'{get_time_period_name(h_time):{ALIGN_RIGHT}{MAX_TIME_PERIOD_WIDTH}} {format_hour(h_time)}', h_time)
  304.         #      left_cultist = color(f'{CULTIST if is_cultist_time(h_time) else "  "}', UI_CULTIST)
  305.         #      on_time = left_time.hour == h or right_time.hour == h
  306.         #      left_arrow = color(LEFT_ARROW if on_time else ' ', UI_CHEVRON)
  307.         #      h_time += TWELVE_HOUR_SHIFT
  308.         #      right_arrow = color(RIGHT_ARROW if on_time else ' ', UI_CHEVRON)
  309.         #      right_cultist = color(f'{CULTIST if is_cultist_time(h_time) else "  "}', UI_CULTIST)
  310.         #      right_game_time = color_hour(f'{format_hour(h_time)} {get_time_period_name(h_time)}', h_time)
  311.         #      closest_time_eta = min(eta(left_time, h_time)[0], eta(right_time, h_time)[0])
  312.         #      irl_time = color(format_eta(convert_tarkov_timedelta_to_irl(closest_time_eta)), UI_ETA)
  313.         #      print(f' {left_game_time} {left_cultist} {left_arrow} {irl_time} {right_arrow} {right_cultist} {right_game_time}')
  314.  
  315.         # Cultist-spawn indicators and arrows are colored based on the hour.
  316.         print()
  317.         for h in range(DAY_START, DAY_END):
  318.             h_time = edit_time(left_time, hour=h, minute=0, second=0)
  319.             if not is_day(left_time):
  320.                 h_time -= TWELVE_HOUR_SHIFT
  321.             left_game_time = color_hour(f'{get_time_period_name(h_time):{ALIGN_RIGHT}{MAX_TIME_PERIOD_WIDTH}} {format_hour(h_time)}', h_time)
  322.             left_cultist = color(f'{CULTIST if is_cultist_time(h_time) else "  "}', UI_CULTIST)
  323.             left_arrow = color_hour(f'{LEFT_ARROW if left_time.hour == h_time.hour else " "}', h_time)
  324.             h_time += TWELVE_HOUR_SHIFT
  325.             right_arrow = color_hour(f'{RIGHT_ARROW if right_time.hour == h_time.hour else " "}', h_time)
  326.             right_cultist = color(f'{CULTIST if is_cultist_time(h_time) else "  "}', UI_CULTIST)
  327.             right_game_time = color_hour(f'{format_hour(h_time)} {get_time_period_name(h_time)}', h_time)
  328.             closest_time_eta = min(eta(left_time, h_time)[0], eta(right_time, h_time)[0])
  329.             irl_time = color(format_eta(convert_tarkov_timedelta_to_irl(closest_time_eta)), UI_ETA)
  330.             print(f' {left_game_time} {left_cultist} {left_arrow} {irl_time} {right_arrow} {right_cultist} {right_game_time}')
  331.  
  332.         # No cultist-spawn indicators and arrows are colored UI_CHEVRON.
  333.         #  print()
  334.         #  for h in range(DAY_START, DAY_END):
  335.         #      h_time = edit_time(left_time, hour=h, minute=0, second=0)
  336.         #      if not is_day(left_time):
  337.         #          h_time -= TWELVE_HOUR_SHIFT
  338.         #      left_game_time = color_hour(f'{get_time_period_name(h_time):{ALIGN_RIGHT}{MAX_TIME_PERIOD_WIDTH}} {format_hour(h_time)}', h_time)
  339.         #      h_time += TWELVE_HOUR_SHIFT
  340.         #      right_game_time = color_hour(f'{format_hour(h_time)} {get_time_period_name(h_time)}', h_time)
  341.         #      on_time = left_time.hour == h or right_time.hour == h
  342.         #      left_arrow = color(LEFT_ARROW if on_time else ' ', UI_CHEVRON)
  343.         #      closest_time_eta = min(eta(left_time, h_time)[0], eta(right_time, h_time)[0])
  344.         #      irl_time = color(format_eta(convert_tarkov_timedelta_to_irl(closest_time_eta)), UI_ETA)
  345.         #      right_arrow = color(RIGHT_ARROW if on_time else ' ', UI_CHEVRON)
  346.         #      print(f' {left_game_time} {left_arrow} {irl_time} {right_arrow} {right_game_time}')
  347.  
  348.         # No cultist-spawn indicators and arrows are colored based on the hour.
  349.         #  print()
  350.         #  for h in range(DAY_START, DAY_END):
  351.         #      h_time = edit_time(left_time, hour=h, minute=0, second=0)
  352.         #      if not is_day(left_time):
  353.         #          h_time -= TWELVE_HOUR_SHIFT
  354.         #      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)
  355.         #      h_time += TWELVE_HOUR_SHIFT
  356.         #      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)
  357.         #      closest_time_eta = min(eta(left_time, h_time)[0], eta(right_time, h_time)[0])
  358.         #      irl_time = color(format_eta(convert_tarkov_timedelta_to_irl(closest_time_eta)), UI_ETA)
  359.         #      print(f' {left_game_time} {irl_time} {right_game_time}')
  360.  
  361.         time.sleep(1)
  362.         clear()
  363.  
  364. if __name__ == '__main__':
  365.     main()
Advertisement
Add Comment
Please, Sign In to add comment