from typing import Optional, Literal
from abc import ABC, abstractmethod


class Visitor(ABC):
    """
    A visitor.
    """

    @abstractmethod
    def visit(self, city_intersection: 'CityIntersection'):
        """
        Visit a city intersection.
        """


class City:
    """
    A city with a name, population, and typical traffic. The traffic is a
    float between 0 and 1 representing the percentage of the population that
    drives at any given time.
    """

    def __init__(self, name: str, population: int, traffic: float):
        self.name = name
        self.population = population
        self.traffic = traffic


IntersectionType = Literal[
    'FourWayIntersection',
    'TIntersection',
]


class CityIntersection:
    """
    An intersection between cities. It contains a city, and two intersections.
    """

    def __init__(
        self,
        intersection1: Optional['CityIntersection'],
        intersection2: Optional['CityIntersection'],
        city: City,
        type: IntersectionType,
    ):
        self.intersection1 = intersection1
        self.intersection2 = intersection2
        self.city = city
        self.type = type

    def accept(self, visitor: Visitor):
        """
        Accepts a visitor.
        """
        visitor.visit(self)


class TrafficAnalysisVisitor(Visitor):
    """
    A visitor that performs complex traffic analysis on city intersections.
    """

    def __init__(self):
        self.traffic_data = {}

    def visit(self, city_intersection: 'CityIntersection'):
        """
        Perform traffic analysis on a city intersection and its children.
        """
        if city_intersection.type == 'FourWayIntersection':
            self.analyze_four_way_intersection(city_intersection)
        elif city_intersection.type == 'TIntersection':
            self.analyze_t_intersection(city_intersection)

    def analyze_four_way_intersection(self, intersection: 'CityIntersection'):
        """
        Analyze traffic at a four-way intersection.
        """
        traffic_volume = intersection.city.population * intersection.city.traffic
        adjusted_traffic = traffic_volume * 1.2
        self.traffic_data[intersection.city.name] = {
            "type": intersection.type,
            "traffic_volume": adjusted_traffic
        }

    def analyze_t_intersection(self, intersection: 'CityIntersection'):
        """
        Analyze traffic at a T-intersection.
        """
        traffic_volume = intersection.city.population * intersection.city.traffic
        adjusted_traffic = traffic_volume * 1.1
        self.traffic_data[intersection.city.name] = {
            "type": intersection.type,
            "traffic_volume": adjusted_traffic
        }