
import csv
import json
import logging
import os
import re
import subprocess
import tempfile
import unittest
import zipfile
from pathlib import Path
from typing import Optional
from unittest import mock

import torch

# We use TF to parse the logs
from accelerate import Accelerator
from accelerate.test_utils.testing import (
    MockingTestCase,
    TempDirTestCase,
    require_comet_ml,
    require_tensorboard,
    require_wandb,
    skip,
)
from accelerate.tracking import CometMLTracker, GeneralTracker
from accelerate.utils import ProjectConfiguration, is_comet_ml_available, is_tensorboard_available


if is_comet_ml_available():
       from comet_ml import OfflineExperiment

if is_tensorboard_available():
       import struct

       import tensorboard.compat.proto.event_pba as event_pba

_UpperCamelCase:					List[str]     =logging.getLogger(__name__)





@require_tensorboard
class 						__lowercase(     unittest.TestCase   ):


       """simple docstring"""







       def SCREAMING_SNAKE_CASE_				(     self					:			List[str]       )					->   Tuple:
         _lowerCAmelCase						=		'test_project_with_config'
         with tempfile.TemporaryDirectory() as dirpath:
           _lowerCAmelCase						=		Accelerator(log_with='tensorboard'  ,      project_dir=_lowerCAmelCase       )
           _lowerCAmelCase						=		{'num_iterations': 12, 'learning_rate': 1e-2, 'some_boolean': False, 'some_string': 'some_value'}
           accelerator.init_trackers(_lowerCAmelCase  ,      _lowerCAmelCase       )
           accelerator.end_training()
           for child in Path(F'''{dirpath}/{project_name}'''       ).glob('*/**'       ):
             _lowerCAmelCase						=		list(filter(lambda _lowerCAmelCase       : x.is_file()  ,      child.iterdir()       )       )[0]
           self.assertNotEqual(str(_lowerCAmelCase       )  ,      ''       )



       def SCREAMING_SNAKE_CASE_				(     self					:			List[Any]       )					->   Union[str, Any]:
         _lowerCAmelCase						=		'test_project_with_log'
         with tempfile.TemporaryDirectory() as dirpath:
           _lowerCAmelCase						=		Accelerator(log_with='tensorboard'  ,      project_dir=_lowerCAmelCase       )
           accelerator.init_trackers(_lowerCAmelCase       )
           _lowerCAmelCase						=		{'total_loss': 0.1, 'iteration': 1, 'my_text': 'some_value'}
           accelerator.log(_lowerCAmelCase  ,      step=0       )
           accelerator.end_training()
           # Logged values are stored in the outermost-tfevents file and can be read in as a TFRecord
           # Names are randomly generated each time
           _lowerCAmelCase						=		list(filter(lambda _lowerCAmelCase       : x.is_file()  ,      Path(F'''{dirpath}/{project_name}'''       ).iterdir()       )       )[0]
           self.assertNotEqual(str(_lowerCAmelCase       )  ,      ''       )



       def SCREAMING_SNAKE_CASE_				(     self					:			Tuple       )					->   List[str]:
         _lowerCAmelCase						=		'test_project_with_log'
         with tempfile.TemporaryDirectory() as dirpath:
           _lowerCAmelCase						=		Accelerator(log_with='tensorboard'  ,      project_dir=_lowerCAmelCase       )
           accelerator.init_trackers(_lowerCAmelCase       )
           _lowerCAmelCase						=		{'tensor': torch.tensor(1       )}
           accelerator.log(_lowerCAmelCase  ,      step=0       )
           accelerator.end_training()
           # Logged values are stored in the outermost-tfevents file and can be read in as a TFRecord
           # Names are randomly generated each time
           _lowerCAmelCase						=		list(filter(lambda _lowerCAmelCase       : x.is_file()  ,      Path(F'''{dirpath}/{project_name}'''       ).iterdir()       )       )[0]
           # Reading implementation based on https://github.com/pytorch/pytorch/issues/45327#issuecomment-703757685
           with open(_lowerCAmelCase  ,      'rb'       ) as f:
             _lowerCAmelCase						=		f.read()
           _lowerCAmelCase						=		False
           while data:
             _lowerCAmelCase						=		struct.unpack('Q'  ,      data[:8]       )

             _lowerCAmelCase						=		data[12 : 12 + int(header[0]       )]  # 8+4
             _lowerCAmelCase						=		data[12 + int(header[0]       ) + 4 :]
             _lowerCAmelCase						=		event_pba.Event()

             event.ParseFromString(_lowerCAmelCase       )
             if event.HasField('summary'       ):
               for value in event.summary.value:
                 if value.simple_value == 1.0 and value.tag == "tensor":
                   _lowerCAmelCase						=		True
           self.assertTrue(_lowerCAmelCase  ,      'Converted tensor was not found in the log file!'       )



       def SCREAMING_SNAKE_CASE_				(     self					:			Tuple       )					->   int:
         with self.assertRaisesRegex(_lowerCAmelCase  ,      'Logging with `tensorboard` requires a `logging_dir`'       ):
           _lowerCAmelCase						=		Accelerator(log_with='tensorboard'       )
         with tempfile.TemporaryDirectory() as dirpath:
           _lowerCAmelCase						=		Accelerator(log_with='tensorboard'  ,      project_dir=_lowerCAmelCase       )






       def SCREAMING_SNAKE_CASE_				(     self					:			List[str]       )					->   Optional[int]:
         _lowerCAmelCase						=		ProjectConfiguration(total_limit=30       )
         with tempfile.TemporaryDirectory() as dirpath:
           _lowerCAmelCase						=		Accelerator(log_with='tensorboard'  ,      project_dir=_lowerCAmelCase  ,      project_config=_lowerCAmelCase       )





@require_wandb
@mock.patch.dict(os.environ		,  {'''WANDB_MODE''': '''offline'''}   )
class 						__lowercase(     SCREAMING_SNAKE_CASE		,  SCREAMING_SNAKE_CASE   ):


       """simple docstring"""







       def SCREAMING_SNAKE_CASE_				(     self					:			Optional[Any]       )					->   List[str]:
         super().setUp()
         # wandb let's us override where logs are stored to via the WANDB_DIR env var
         self.add_mocks(mock.patch.dict(os.environ  ,      {'WANDB_DIR': self.tmpdir}       )       )



       @staticmethod
       def SCREAMING_SNAKE_CASE_				(     _lowerCAmelCase					:			str  ,      _lowerCAmelCase					:			str  ,      _lowerCAmelCase					:			bool = True       )					->   Optional[int]:
         _lowerCAmelCase						=		rF'''{section} ([\S\s]*?)\n\n'''
         if record:
           _lowerCAmelCase						=		rF'''Record: {pattern}'''
         _lowerCAmelCase						=		re.findall(_lowerCAmelCase  ,      _lowerCAmelCase       )[0]
         # A config
         if section == "config" or section == "history":
           _lowerCAmelCase						=		re.findall(r'"([a-zA-Z0-9_.,]+)'  ,      _lowerCAmelCase       )
           return {key: val for key, val in zip(cleaned_record[0::2]  ,      cleaned_record[1::2]       )}
         # Everything else
         else:
           return dict(re.findall(r'(\w+): "([^\s]+)"'  ,      _lowerCAmelCase       )       )






       @skip
       def SCREAMING_SNAKE_CASE_				(     self					:			List[Any]       )					->   str:
         _lowerCAmelCase						=		'test_project_with_config'
         _lowerCAmelCase						=		Accelerator(log_with='wandb'       )
         _lowerCAmelCase						=		{'num_iterations': 12, 'learning_rate': 1e-2, 'some_boolean': False, 'some_string': 'some_value'}
         _lowerCAmelCase						=		{'wandb': {'tags': ['my_tag']}}
         accelerator.init_trackers(_lowerCAmelCase  ,      _lowerCAmelCase  ,      _lowerCAmelCase       )
         _lowerCAmelCase						=		{'total_loss': 0.1, 'iteration': 1, 'my_text': 'some_value'}
         accelerator.log(_lowerCAmelCase  ,      step=0       )
         accelerator.end_training()
         # The latest offline log is stored at wandb/latest-run/*.wandb
         for child in Path(F'''{self.tmpdir}/wandb/latest-run'''       ).glob('*'       ):
           if child.is_file() and child.suffix == ".wandb":
             _lowerCAmelCase						=		subprocess.check_output(
                 ['wandb', 'sync', '--view', '--verbose', str(_lowerCAmelCase       )]  ,      env=os.environ.copy()       ).decode('utf8'  ,      'ignore'       )
             break

        # Check HPS through careful parsing and cleaning
         _lowerCAmelCase						=		self.parse_log(_lowerCAmelCase  ,      'config'       )
         self.assertEqual(logged_items['num_iterations']  ,      '12'       )
         self.assertEqual(logged_items['learning_rate']  ,      '0.01'       )
         self.assertEqual(logged_items['some_boolean']  ,      'false'       )
         self.assertEqual(logged_items['some_string']  ,      'some_value'       )
         self.assertEqual(logged_items['some_string']  ,      'some_value'       )

         # Run tags
         _lowerCAmelCase						=		self.parse_log(_lowerCAmelCase  ,      'run'  ,      _lowerCAmelCase       )
         self.assertEqual(logged_items['tags']  ,      'my_tag'       )

         # Actual logging
         _lowerCAmelCase						=		self.parse_log(_lowerCAmelCase  ,      'history'       )
         self.assertEqual(logged_items['total_loss']  ,      '0.1'       )
         self.assertEqual(logged_items['iteration']  ,      '1'       )
         self.assertEqual(logged_items['my_text']  ,      'some_value'       )
         self.assertEqual(logged_items['_step']  ,      '0'       )



def 	_a  (					self					:  List[str]		,				__SCREAMING_SNAKE_CASE					:  str		,				__SCREAMING_SNAKE_CASE					:  str    ):






  """simple docstring"""




  _lowerCAmelCase						=		run_name
  _lowerCAmelCase						=		OfflineExperiment(project_name=__SCREAMING_SNAKE_CASE		,				offline_directory=__SCREAMING_SNAKE_CASE    )
  logger.info(f'''Initialized offline CometML project {self.run_name}'''    )
  logger.info('Make sure to log any initial configurations with `self.store_init_configuration` before training!'    )





@require_comet_ml
@mock.patch.object(SCREAMING_SNAKE_CASE		,  '''__init__'''		,  SCREAMING_SNAKE_CASE   )
class 						__lowercase(     unittest.TestCase   ):


       """simple docstring"""







       @staticmethod
       def SCREAMING_SNAKE_CASE_				(     _lowerCAmelCase					:			Union[str, Any]  ,      _lowerCAmelCase					:			str  ,      _lowerCAmelCase					:			bool = False       )					->   List[Any]:
         for log in log_list:
           _lowerCAmelCase						=		json.loads(_lowerCAmelCase       )['payload']
           if is_param and "param" in j.keys():
             if j["param"]["paramName"] == key:
               return j["param"]["paramValue"]
           if "log_other" in j.keys():
             if j["log_other"]["key"] == key:
               return j["log_other"]["val"]
           if "metric" in j.keys():
             if j["metric"]["metricName"] == key:
               return j["metric"]["metricValue"]



       def SCREAMING_SNAKE_CASE_				(     self					:			List[str]       )					->   Union[str, Any]:
         with tempfile.TemporaryDirectory() as d:
           _lowerCAmelCase						=		CometMLTracker('test_project_with_config'  ,      _lowerCAmelCase       )
           _lowerCAmelCase						=		Accelerator(log_with=_lowerCAmelCase       )
           _lowerCAmelCase						=		{'num_iterations': 12, 'learning_rate': 1e-2, 'some_boolean': False, 'some_string': 'some_value'}
           accelerator.init_trackers(_lowerCAmelCase  ,      _lowerCAmelCase       )
           accelerator.end_training()
           _lowerCAmelCase						=		os.listdir(_lowerCAmelCase       )[0]  # Comet is nice, it's just a zip file here
           # We parse the raw logs
           _lowerCAmelCase						=		os.path.join(_lowerCAmelCase  ,      _lowerCAmelCase       )
           _lowerCAmelCase						=		zipfile.ZipFile(_lowerCAmelCase  ,      'r'       )
           _lowerCAmelCase						=		archive.open('messages.json'       ).read().decode('utf-8'       )
         _lowerCAmelCase						=		log.split('\n'       )[:-1]
         self.assertEqual(self.get_value_from_key(_lowerCAmelCase  ,      'num_iterations'  ,      _lowerCAmelCase       )  ,      12       )
         self.assertEqual(self.get_value_from_key(_lowerCAmelCase  ,      'learning_rate'  ,      _lowerCAmelCase       )  ,      0.01       )
         self.assertEqual(self.get_value_from_key(_lowerCAmelCase  ,      'some_boolean'  ,      _lowerCAmelCase       )  ,      _lowerCAmelCase       )
         self.assertEqual(self.get_value_from_key(_lowerCAmelCase  ,      'some_string'  ,      _lowerCAmelCase       )  ,      'some_value'       )






       def SCREAMING_SNAKE_CASE_				(     self					:			List[str]       )					->   Optional[Any]:
         with tempfile.TemporaryDirectory() as d:
           _lowerCAmelCase						=		CometMLTracker('test_project_with_config'  ,      _lowerCAmelCase       )
           _lowerCAmelCase						=		Accelerator(log_with=_lowerCAmelCase       )
           accelerator.init_trackers(_lowerCAmelCase       )
           _lowerCAmelCase						=		{'total_loss': 0.1, 'iteration': 1, 'my_text': 'some_value'}
           accelerator.log(_lowerCAmelCase  ,      step=0       )
           accelerator.end_training()
           _lowerCAmelCase						=		os.listdir(_lowerCAmelCase       )[0]  # Comet is nice, it's just a zip file here
           # We parse the raw logs
           _lowerCAmelCase						=		os.path.join(_lowerCAmelCase  ,      _lowerCAmelCase       )
           _lowerCAmelCase						=		zipfile.ZipFile(_lowerCAmelCase  ,      'r'       )
           _lowerCAmelCase						=		archive.open('messages.json'       ).read().decode('utf-8'       )
         _lowerCAmelCase						=		log.split('\n'       )[:-1]
         self.assertEqual(self.get_value_from_key(_lowerCAmelCase  ,      'curr_step'  ,      _lowerCAmelCase       )  ,      0       )
         self.assertEqual(self.get_value_from_key(_lowerCAmelCase  ,      'total_loss'       )  ,      0.1       )
         self.assertEqual(self.get_value_from_key(_lowerCAmelCase  ,      'iteration'       )  ,      1       )
         self.assertEqual(self.get_value_from_key(_lowerCAmelCase  ,      'my_text'       )  ,      'some_value'       )





class 						__lowercase(     SCREAMING_SNAKE_CASE   ):


       """simple docstring"""







       UpperCamelCase_				 =							[
           '''total_loss''',
           '''iteration''',
           '''my_text''',
           '''learning_rate''',
           '''num_iterations''',
           '''some_boolean''',
           '''some_string''',
       ]

       UpperCamelCase_				 =							'''my_custom_tracker'''
       UpperCamelCase_				 =							False



       def __init__(     self					:			int  ,      _lowerCAmelCase					:			str       )					->   Optional[Any]:
         _lowerCAmelCase						=		open(F'''{dir}/log.csv'''  ,      'w+'       )
         _lowerCAmelCase						=		csv.DictWriter(self.f  ,      fieldnames=self._col_names       )
         self.writer.writeheader()



       @property
       def SCREAMING_SNAKE_CASE_				(     self					:			Any       )					->   List[str]:
         return self.writer



       def SCREAMING_SNAKE_CASE_				(     self					:			Optional[int]  ,      _lowerCAmelCase					:			dict       )					->   Optional[Any]:
         logger.info('Call init'       )
         self.writer.writerow(_lowerCAmelCase       )



       def SCREAMING_SNAKE_CASE_				(     self					:			int  ,      _lowerCAmelCase					:			dict  ,      _lowerCAmelCase					:			Optional[int]       )					->   Tuple:
         logger.info('Call log'       )
         self.writer.writerow(_lowerCAmelCase       )






       def SCREAMING_SNAKE_CASE_				(     self					:			Optional[int]       )					->   Optional[int]:
         self.f.close()





class 						__lowercase(     unittest.TestCase   ):


       """simple docstring"""







       def SCREAMING_SNAKE_CASE_				(     self					:			List[str]       )					->   Optional[Any]:
         with tempfile.TemporaryDirectory() as d:
           _lowerCAmelCase						=		MyCustomTracker(_lowerCAmelCase       )
           _lowerCAmelCase						=		Accelerator(log_with=_lowerCAmelCase       )
           _lowerCAmelCase						=		{'num_iterations': 12, 'learning_rate': 1e-2, 'some_boolean': False, 'some_string': 'some_value'}
           accelerator.init_trackers('Some name'  ,      _lowerCAmelCase       )
           accelerator.end_training()
           with open(F'''{d}/log.csv'''  ,      'r'       ) as f:
             _lowerCAmelCase						=		csv.DictReader(_lowerCAmelCase       )
             _lowerCAmelCase						=		next(_lowerCAmelCase       )
             _lowerCAmelCase						=		{
                 'total_loss': '',
                 'iteration': '',
                 'my_text': '',
                 'learning_rate': '0.01',
                 'num_iterations': '12',
                 'some_boolean': 'False',
                 'some_string': 'some_value',
             }
             self.assertDictEqual(_lowerCAmelCase  ,      _lowerCAmelCase       )






       def SCREAMING_SNAKE_CASE_				(     self					:			Optional[Any]       )					->   Optional[Any]:
         with tempfile.TemporaryDirectory() as d:
           _lowerCAmelCase						=		MyCustomTracker(_lowerCAmelCase       )
           _lowerCAmelCase						=		Accelerator(log_with=_lowerCAmelCase       )
           accelerator.init_trackers('Some name'       )
           _lowerCAmelCase						=		{'total_loss': 0.1, 'iteration': 1, 'my_text': 'some_value'}
           accelerator.log(_lowerCAmelCase  ,      step=0       )
           accelerator.end_training()
           with open(F'''{d}/log.csv'''  ,      'r'       ) as f:
             _lowerCAmelCase						=		csv.DictReader(_lowerCAmelCase       )
             _lowerCAmelCase						=		next(_lowerCAmelCase       )
             _lowerCAmelCase						=		{
                 'total_loss': '0.1',
                 'iteration': '1',
                 'my_text': 'some_value',
                 'learning_rate': '',
                 'num_iterations': '',
                 'some_boolean': '',
                 'some_string': '',
             }
             self.assertDictEqual(_lowerCAmelCase  ,      _lowerCAmelCase       )


from __future__ import annotations

import os





class 						__lowercase:


       """simple docstring"""







       UpperCamelCase_				 =							(
           '''High card''',
           '''One pair''',
           '''Two pairs''',
           '''Three of a kind''',
           '''Straight''',
           '''Flush''',
           '''Full house''',
           '''Four of a kind''',
           '''Straight flush''',
           '''Royal flush''',
       )

       UpperCamelCase_				 =							(
           '''''',  # placeholder as tuples are zero-indexed
           '''One''',
           '''Two''',
           '''Three''',
           '''Four''',
           '''Five''',
           '''Six''',
           '''Seven''',
           '''Eight''',
           '''Nine''',
           '''Ten''',
           '''Jack''',
           '''Queen''',
           '''King''',
           '''Ace''',
       )



       def __init__(     self					:			Dict  ,      _lowerCAmelCase					:			str       )					->   None:
         if not isinstance(_lowerCAmelCase  ,      _lowerCAmelCase       ):
           _lowerCAmelCase						=		F'''Hand should be of type \'str\': {hand!r}'''
           raise TypeError(_lowerCAmelCase       )
         # split removes duplicate whitespaces so no need of strip
         if len(hand.split(' '       )       ) != 5:
           _lowerCAmelCase						=		F'''Hand should contain only 5 cards: {hand!r}'''
           raise ValueError(_lowerCAmelCase       )
         _lowerCAmelCase						=		hand
         _lowerCAmelCase						=		0
         _lowerCAmelCase						=		0
         _lowerCAmelCase	,       _lowerCAmelCase						=		self._internal_state()
         _lowerCAmelCase						=		self._get_hand_type()
         _lowerCAmelCase						=		self._card_values[0]



       @property
       def SCREAMING_SNAKE_CASE_				(     self					:			Any       )					->   List[Any]:
         return self._hand



       def SCREAMING_SNAKE_CASE_				(     self					:			int  ,      _lowerCAmelCase					:			PokerHand       )					->   str:
         # Breaking the tie works on the following order of precedence:
         # 1. First pair (default 0)
         # 2. Second pair (default 0)
         # 3. Compare all cards in reverse order because they are sorted.

         # First pair and second pair will only be a non-zero value if the card
         # type is either from the following:
         # 21: Four of a kind
         # 20: Full house
         # 17: Three of a kind
         # 16: Two pairs
         # 15: One pair
         if self._hand_type > other._hand_type:
           return "Win"
         elif self._hand_type < other._hand_type:
           return "Loss"
         elif self._first_pair == other._first_pair:
           if self._second_pair == other._second_pair:
             return self._compare_cards(_lowerCAmelCase       )
           else:
             return "Win" if self._second_pair > other._second_pair else "Loss"
         return "Win" if self._first_pair > other._first_pair else "Loss"



       def SCREAMING_SNAKE_CASE_				(     self					:			str       )					->   str:
         _lowerCAmelCase						=		PokerHand._HAND_NAME[self._hand_type - 14]
         _lowerCAmelCase						=		PokerHand._CARD_NAME[self._high_card]
         _lowerCAmelCase						=		PokerHand._CARD_NAME[self._first_pair]
         _lowerCAmelCase						=		PokerHand._CARD_NAME[self._second_pair]
         if self._hand_type in [22, 19, 18]:
           return name + F''', {high}-high'''
         elif self._hand_type in [21, 17, 15]:
           return name + F''', {paira}s'''
         elif self._hand_type in [20, 16]:
           _lowerCAmelCase						=		'over' if self._hand_type == 20 else 'and'
           return name + F''', {paira}s {join} {paira}s'''
         elif self._hand_type == 23:
           return name
         else:
           return name + F''', {high}'''



       def SCREAMING_SNAKE_CASE_				(     self					:			Any  ,      _lowerCAmelCase					:			PokerHand       )					->   str:
         # Enumerate gives us the index as well as the element of a list
         for index, card_value in enumerate(self._card_values       ):
           if card_value != other._card_values[index]:
             return "Win" if card_value > other._card_values[index] else "Loss"
         return "Tie"



       def SCREAMING_SNAKE_CASE_				(     self					:			Optional[Any]       )					->   int:
         # Number representing the type of hand internally:
         # 23: Royal flush
         # 22: Straight flush
         # 21: Four of a kind
         # 20: Full house
         # 19: Flush
         # 18: Straight
         # 17: Three of a kind
         # 16: Two pairs
         # 15: One pair
         # 14: High card
         if self._is_flush():
           if self._is_five_high_straight() or self._is_straight():
             return 23 if sum(self._card_values       ) == 60 else 22
           return 19
         elif self._is_five_high_straight() or self._is_straight():
           return 18
         return 14 + self._is_same_kind()



       def SCREAMING_SNAKE_CASE_				(     self					:			Any       )					->   bool:
         return len(self._card_suit       ) == 1



       def SCREAMING_SNAKE_CASE_				(     self					:			str       )					->   bool:
         # If a card is a five high straight (low ace) change the location of
         # ace from the start of the list to the end. Check whether the first
         # element is ace or not. (Don't want to change again)
         # Five high straight (low ace): AH 2H 3S 4C 5D
         # Why use sorted here? One call to this function will mutate the list to
         # [5, 4, 3, 2, 14] and so for subsequent calls (which will be rare) we
         # need to compare the sorted version.
         # Refer test_multiple_calls_five_high_straight in test_poker_hand.py
         if sorted(self._card_values       ) == [2, 3, 4, 5, 14]:
           if self._card_values[0] == 14:
             # Remember, our list is sorted in reverse order
             _lowerCAmelCase						=		self._card_values.pop(0       )
             self._card_values.append(_lowerCAmelCase       )
           return True
         return False



       def SCREAMING_SNAKE_CASE_				(     self					:			Optional[Any]       )					->   bool:
         for i in range(4       ):
           if self._card_values[i] - self._card_values[i + 1] != 1:
             return False
         return True



       def SCREAMING_SNAKE_CASE_				(     self					:			Dict       )					->   int:
         # Kind Values for internal use:
         # 7: Four of a kind
         # 6: Full house
         # 3: Three of a kind
         # 2: Two pairs
         # 1: One pair
         # 0: False
         _lowerCAmelCase						=		_lowerCAmelCase						=		_lowerCAmelCase						=		0
         for i in range(4       ):
           # Compare two cards at a time, if they are same increase 'kind',
           # add the value of the card to val1, if it is repeating again we
           # will add 2 to 'kind' as there are now 3 cards with same value.
           # If we get card of different value than val1, we will do the same
           # thing with val2
           if self._card_values[i] == self._card_values[i + 1]:
             if not vala:
               _lowerCAmelCase						=		self._card_values[i]
               kind += 1
             elif vala == self._card_values[i]:
               kind += 2
             elif not vala:
               _lowerCAmelCase						=		self._card_values[i]
               kind += 1
             elif vala == self._card_values[i]:
               kind += 2
        # For consistency in hand type (look at note in _get_hand_type function)
         _lowerCAmelCase						=		kind + 2 if kind in [4, 5] else kind
         # first meaning first pair to compare in 'compare_with'
         _lowerCAmelCase						=		max(_lowerCAmelCase  ,      _lowerCAmelCase       )
         _lowerCAmelCase						=		min(_lowerCAmelCase  ,      _lowerCAmelCase       )
         # If it's full house (three count pair + two count pair), make sure
         # first pair is three count and if not then switch them both.
         if kind == 6 and self._card_values.count(_lowerCAmelCase       ) != 3:
           _lowerCAmelCase	,       _lowerCAmelCase						=		second, first
         _lowerCAmelCase						=		first
         _lowerCAmelCase						=		second
         return kind



       def SCREAMING_SNAKE_CASE_				(     self					:			Optional[int]       )					->   tuple[list[int], set[str]]:
         # Internal representation of hand as a list of card values and
         # a set of card suit
         _lowerCAmelCase						=		{"T": "10", "J": "11", "Q": "12", "K": "13", "A": "14"}
         _lowerCAmelCase						=		self._hand.translate(str.maketrans(_lowerCAmelCase       )       ).split()
         _lowerCAmelCase						=		[int(card[:-1]       ) for card in new_hand]
         _lowerCAmelCase						=		{card[-1] for card in new_hand}
         return sorted(_lowerCAmelCase  ,      reverse=_lowerCAmelCase       ), card_suit



       def __repr__(     self					:			Tuple       )					->   Optional[Any]:
         return F'''{self.__class__}("{self._hand}")'''



       def __str__(     self					:			Optional[int]       )					->   Union[str, Any]:
         return self._hand



       def __eq__(     self					:			Optional[int]  ,      _lowerCAmelCase					:			str       )					->   Tuple:
         if isinstance(_lowerCAmelCase  ,      _lowerCAmelCase       ):
           return self.compare_with(_lowerCAmelCase       ) == "Tie"
         return NotImplemented



       def __lt__(     self					:			List[Any]  ,      _lowerCAmelCase					:			int       )					->   List[str]:
         if isinstance(_lowerCAmelCase  ,      _lowerCAmelCase       ):
           return self.compare_with(_lowerCAmelCase       ) == "Loss"
         return NotImplemented



       def __le__(     self					:			str  ,      _lowerCAmelCase					:			Dict       )					->   str:
         if isinstance(_lowerCAmelCase  ,      _lowerCAmelCase       ):
           return self < other or self == other
         return NotImplemented



       def __gt__(     self					:			Union[str, Any]  ,      _lowerCAmelCase					:			List[Any]       )					->   int:
         if isinstance(_lowerCAmelCase  ,      _lowerCAmelCase       ):
           return not self < other and self != other
         return NotImplemented



       def __ge__(     self					:			Dict  ,      _lowerCAmelCase					:			Dict       )					->   Optional[Any]:
         if isinstance(_lowerCAmelCase  ,      _lowerCAmelCase       ):
           return not self < other
         return NotImplemented






       def __hash__(     self					:			Optional[int]       )					->   List[Any]:
         return object.__hash__(self       )



def 	_a  (					):






  """simple docstring"""




  _lowerCAmelCase						=		0
  _lowerCAmelCase						=		os.path.abspath(os.path.dirname(__SCREAMING_SNAKE_CASE    )    )
  _lowerCAmelCase						=		os.path.join(__SCREAMING_SNAKE_CASE		,				'poker_hands.txt'    )
  with open(__SCREAMING_SNAKE_CASE    ) as file_hand:
    for line in file_hand:
      _lowerCAmelCase						=		line[:14].strip()
      _lowerCAmelCase						=		line[15:].strip()
      _lowerCAmelCase	,       _lowerCAmelCase						=		PokerHand(__SCREAMING_SNAKE_CASE    ), PokerHand(__SCREAMING_SNAKE_CASE    )
      _lowerCAmelCase						=		player.compare_with(__SCREAMING_SNAKE_CASE    )
      if output == "Win":
        answer += 1
  return answer


if __name__ == "__main__":
       solution()
