





import builtins
import sys

from ...utils.imports import _is_package_available
from . import cursor, input
from .helpers import Direction, clear_line, forceWrite, linebreak, move_cursor, reset_cursor, writeColor
from .keymap import KEYMAP


_SCREAMING_SNAKE_CASE      	=		False
try:
						_SCREAMING_SNAKE_CASE      	=		_is_package_available("""google.colab""")
except ModuleNotFoundError:
						pass
@input.register
class SCREAMING_SNAKE_CASE_						:






						def __init__(      self      :      Optional[int]		,   _A      :      str = None		,   _A      :      list = []	)							->    Optional[Any]:







							"""simple docstring"""


							snake_case_		:			Tuple											=	0
							snake_case_		:			Optional[int]											=	choices
							snake_case_		:			Union[str, Any]											=	prompt
							if sys.platform == "win32":
								snake_case_		:			Optional[int]											=	"*"
							else:
								snake_case_		:			Union[str, Any]											=	"➔ "






						def UpperCAmelCase_				(      self      :      int		,   _A      :      int		,   _A      :      str = ""	)							->    Union[str, Any]:







							"""simple docstring"""


							if sys.platform != "win32":
								writeColor(self.choices[index]		,   32		,   __lowerCamelCase	)
							else:
								forceWrite(self.choices[index]		,   __lowerCamelCase	)






						def UpperCAmelCase_				(      self      :      Dict		,   _A      :      int	)							->    str:







							"""simple docstring"""


							if index == self.position:
								forceWrite(F""" {self.arrow_char} """	)
								self.write_choice(__lowerCamelCase	)
							else:
								forceWrite(F"""    {self.choices[index]}"""	)
							reset_cursor()






						def UpperCAmelCase_				(      self      :      Any		,   _A      :      Direction		,   _A      :      int = 1	)							->    Tuple:







							"""simple docstring"""


							snake_case_		:			Optional[int]											=	self.position
							if direction == Direction.DOWN:
								if self.position + 1 >= len(self.choices	):
									return
								self.position += num_spaces
							else:
								if self.position - 1 < 0:
									return
								self.position -= num_spaces
							clear_line()
							self.print_choice(__lowerCamelCase	)
							move_cursor(__lowerCamelCase		,   direction.name	)
							self.print_choice(self.position	)






						@input.mark(KEYMAP['up']	)
						def UpperCAmelCase_				(      self      :      Optional[int]	)							->    Union[str, Any]:







							"""simple docstring"""


							self.move_direction(Direction.UP	)






						@input.mark(KEYMAP['down']	)
						def UpperCAmelCase_				(      self      :      Optional[Any]	)							->    Tuple:







							"""simple docstring"""


							self.move_direction(Direction.DOWN	)






						@input.mark(KEYMAP['newline']	)
						def UpperCAmelCase_				(      self      :      str	)							->    Any:







							"""simple docstring"""


							move_cursor(len(self.choices	) - self.position		,   'DOWN'	)
							return self.position






						@input.mark(KEYMAP['interrupt']	)
						def UpperCAmelCase_				(      self      :      Tuple	)							->    Any:







							"""simple docstring"""


							move_cursor(len(self.choices	) - self.position		,   'DOWN'	)
							raise KeyboardInterrupt






						@input.mark_multiple(*[KEYMAP[str(__lowerCamelCase	)] for number in range(10	)]	)
						def UpperCAmelCase_				(      self      :      str	)							->    Any:







							"""simple docstring"""


							snake_case_		:			List[Any]											=	int(chr(self.current_selection	)	)
							snake_case_		:			Union[str, Any]											=	index - self.position
							if index == self.position:
								return
							if index < len(self.choices	):
								if self.position > index:
									self.move_direction(Direction.UP		,   -movement	)
								elif self.position < index:
									self.move_direction(Direction.DOWN		,   __lowerCamelCase	)
								else:
									return
							else:
								return






						def UpperCAmelCase_				(      self      :      List[str]		,   _A      :      int = 0	)							->    List[str]:







							"""simple docstring"""


							if self.prompt:
								linebreak()
								forceWrite(self.prompt		,   '\n'	)
								if in_colab:
									forceWrite('Please input a choice index (starting from 0), and press enter'		,   '\n'	)
								else:
									forceWrite('Please select a choice using the arrow or number keys, and selecting with enter'		,   '\n'	)
							snake_case_		:			Optional[Any]											=	default_choice
							for i in range(len(self.choices	)	):
								self.print_choice(__lowerCamelCase	)
								forceWrite('\n'	)
							move_cursor(len(self.choices	) - self.position		,   'UP'	)
							with cursor.hide():
								while True:
									if in_colab:
										try:
											snake_case_		:			int											=	int(builtins.input()	)
										except ValueError:
											snake_case_		:			Any											=	default_choice
									else:
										snake_case_		:			int											=	self.handle_input()
									if choice is not None:
										reset_cursor()
										for _ in range(len(self.choices	) + 1	):
											move_cursor(1		,   'UP'	)
											clear_line()
										self.write_choice(__lowerCamelCase		,   '\n'	)
										return choice








from __future__ import annotations


def 							SCREAMING_SNAKE_CASE__						(    __a   , __a = None   , __a = None   , __a = False   , ):
	snake_case_		:			int											=	cipher_alphabet or [chr(__a   ) for i in range(97   , 1_23   )]

	# If the argument is None or the user provided an empty dictionary
	if not frequencies_dict:
		# Frequencies of letters in the english language (how much they show up)
		snake_case_		:			Dict											=	{
		    'a': 0.08497,
		    'b': 0.01492,
		    'c': 0.02202,
		    'd': 0.04253,
		    'e': 0.11162,
		    'f': 0.02228,
		    'g': 0.02015,
		    'h': 0.06094,
		    'i': 0.07546,
		    'j': 0.00153,
		    'k': 0.01292,
		    'l': 0.04025,
		    'm': 0.02406,
		    'n': 0.06749,
		    'o': 0.07507,
		    'p': 0.01929,
		    'q': 0.00095,
		    'r': 0.07587,
		    's': 0.06327,
		    't': 0.09356,
		    'u': 0.02758,
		    'v': 0.00978,
		    'w': 0.02560,
		    'x': 0.00150,
		    'y': 0.01994,
		    'z': 0.00077,
		}
	else:
		# Custom frequencies dictionary
		snake_case_		:			int											=	frequencies_dict

	if not case_sensitive:
		snake_case_		:			Optional[Any]											=	ciphertext.lower()

	# Chi squared statistic values
	snake_case_		:			dict[int, tuple[float, str]]											=	{}

	# cycle through all of the shifts
	for shift in range(len(__a   )   ):
		snake_case_		:			int											=	''

		# decrypt the message with the shift
		for letter in ciphertext:
			try:
				# Try to index the letter in the alphabet
				snake_case_		:			List[Any]											=	(alphabet_letters.index(letter.lower()   ) - shift) % len(
				    __a   )
				decrypted_with_shift += (
				    alphabet_letters[new_key].upper()
				    if case_sensitive and letter.isupper()
				    else alphabet_letters[new_key]
				)
			except ValueError:
				# Append the character if it isn't in the alphabet
				decrypted_with_shift += letter

		snake_case_		:			Union[str, Any]											=	0.0

		# Loop through each letter in the decoded message with the shift
		for letter in decrypted_with_shift:
			if case_sensitive:
				snake_case_		:			List[Any]											=	letter.lower()
				if letter in frequencies:
					# Get the amount of times the letter occurs in the message
					snake_case_		:			Optional[Any]											=	decrypted_with_shift.lower().count(__a   )

					# Get the excepcted amount of times the letter should appear based
					# on letter frequencies
					snake_case_		:			Tuple											=	frequencies[letter] * occurrences

					# Complete the chi squared statistic formula
					snake_case_		:			Optional[int]											=	((occurrences - expected) ** 2) / expected

					# Add the margin of error to the total chi squared statistic
					chi_squared_statistic += chi_letter_value
			else:
				if letter.lower() in frequencies:
					# Get the amount of times the letter occurs in the message
					snake_case_		:			Any											=	decrypted_with_shift.count(__a   )

					# Get the excepcted amount of times the letter should appear based
					# on letter frequencies
					snake_case_		:			List[str]											=	frequencies[letter] * occurrences

					# Complete the chi squared statistic formula
					snake_case_		:			Optional[Any]											=	((occurrences - expected) ** 2) / expected

					# Add the margin of error to the total chi squared statistic
					chi_squared_statistic += chi_letter_value

        # Add the data to the chi_squared_statistic_values dictionary
		snake_case_		:			Any											=	(
		    chi_squared_statistic,
		    decrypted_with_shift,
		)

	# Get the most likely cipher by finding the cipher with the smallest chi squared
	# statistic
	def chi_squared_statistic_values_sorting_key(__a   ) -> tuple[float, str]:
		return chi_squared_statistic_values[key]

	snake_case_		:			int											=	min(
	    __a   , key=__a   , )

	# Get all the data from the most likely cipher (key, decoded message)
	(
	    (
	    snake_case_
	)						,(
	    snake_case_
	)						,
	)		:			str											=	chi_squared_statistic_values[most_likely_cipher]

	# Return the data on the most likely shift
	return (
	    most_likely_cipher,
	    most_likely_cipher_chi_squared_value,
	    decoded_most_likely_cipher,
	)

