from uuid import uuid4, UUID

# from matplotlib.pylab import f
from ulid import ULID

from typing import (
    List,
    Set,
    Union,
    TypeAlias,
    Optional,
    Self,
    Tuple,
    Dict,
    Literal,
    Any,
)

from collections import Counter
from collections.abc import Iterable

# from matplotlib.rcsetup import all_backends
import networkx as nx
from networkx import Graph
import sympy as sy
from pprint import pprint

import matplotlib

matplotlib.use("Qt5Agg")
# matplotlib.use("TkAgg")

import matplotlib.pyplot as plt
# * from mpl_toolkits.mplot3d import Axes3D

from colorama import Back

from . import components
from . import current as current
from . import solvers as solvers
from .geom_handler import base_geom_objects as bgo
from .errors import ConduitForgeError
from .data import numerical_constants as nc


Equation: TypeAlias = sy.Eq

Part: TypeAlias = UUID | tuple[UUID]
Joint: TypeAlias = list[Part]


class Mosaic:
    """
    This class will be used to monitor and arrange a group of pipes and acessories created by the user.

    The essential information it will store is the joints between the ports of the individual components and currents.
    Those joints will be stored as a list that holds a pair of the objects being joined.
    The list of joints will be used to solve the fluid mechanics equations for the piping systems created by the user.
    Each piping system will be called a "Mosaic", because each one of the objects of this class will store the data for a single mosaic.
    The user will print the mosaic atributes by calling a speciffic method from this class withe the name of the wanted propperty.

    i.e. : pressure_loss = m_1.pressure_loss()
    """

    # Class variable to keep track of all the mosaic objects created
    mosaic_objects: list[Self] = []

    def __init__(self, joints_list: List[Joint] = []) -> None:
        self.id: UUID = uuid4()

        self.graph: Optional[nx.Graph] = nx.DiGraph()

        """
        The joints_list could register the joints in some different ways:
            The first would be in the order that the components and currents objects are being added one to another and to the mosaic.
            The second would be harder than the forst, and would be to organize the joints_list to aglomerate joints from the same
            object in neigbouring cells of the list. (this method could serve to help the solver, but it can make the code bigger with adding
            little to no value to it)
        """

        self.joints_list: List[Joint] = joints_list

        self.global_inlet_currents: List[UUID] = []
        self.global_outlet_currents: List[UUID] = []

        self.all_eq_variables: set = set()

        # // This equation dict maps all the equations of a Mosaic object, and assign an ULID to it
        self.equations_dict: dict[ULID, sy.Basic] = {}

        # this must be the last command inside the Mosaic class __init__, read the Port __init__ documentation to know more.
        Mosaic.mosaic_objects.append(self)

    def category_identifier(self):
        """
        This method will be used to evaluete in what category/shape/complexity the Mosaic is.
        The shapes that this method identifies will help the solver to use the correct methods to solve the system
            The first shape would be the "one branch of piping and accessories
            The second shape
        """
        raise NotImplementedError

    def geometry_check(self):
        # This method will check if the two ports in some part of the mosaic have the same cross section geometry
        # If the cross sectional geometries aren't compatible, this method should raise an error
        raise NotImplementedError

    def size_check(self):
        # This method will check if the size of the fittings are compatible
        raise NotImplementedError

    def fitting_type_check(self):
        # This method will check if the fitting types are compatbile between both ports of a joint between Components
        raise NotImplementedError

    def rearrange_components(self, other):
        """
        This method will be used if the mosaic needs to rearage one or more components in the mosaic,
        for the mosaic to be coherent to the real life or for it to be coherent to be fed into a
        solver class instance.
        """
        raise NotImplementedError

    def __add__(self, other):
        """
        After some thougth, i had the ideia to make the __add__ and __radd__ methods
        return a joint, a register it in the self.joints_list
        """

        """
        !Test Implementation!
        """
        match isinstance(other, Mosaic):
            case True:
                # I still have to define what happens when two Mosaic instances are being added, i don't know yet
                raise NotImplementedError

            case False if (isinstance(other, current.Current)) == True:
                """
                I have to check if this case is right !
                This part should be stating that if the other object isn't an instance of Mosaic class
                and the other object is an instance of the Current class something must happen

                I have to code what happen in this case, i don't know right now
                """
                raise NotImplementedError

            case False if (isinstance(other, components.Component)) == True:
                """
                This part should be stating that if the other object isn't an instance of Mosaic class
                and the other object is an instance of the Component class something must happen.

                I have to make the add method create a joint list with the output of the last element of the mosaic (the one
                from the right side extremity).
                    To make this, i have to understand how i could tell the mosaic class wich element is the one from the right side
                    "tip" of the Mosaic.
                """

                # self.joints_list.append(,)
                raise NotImplementedError

            case _:
                raise NotImplementedError

    def __radd__(self, other):
        raise NotImplementedError

    def joint(self, arg_1, arg_2) -> None:
        # print(f'\nBeginning of the Joint method')

        # print(f'\n{arg_1 = }')
        # print(f'\n{arg_2 = }')

        comp_1_r_status: str = ""
        comp_1: Optional[components.Component] = None
        port_1: Optional[components.Port] = None

        comp_2_r_status: str = ""
        comp_2: Optional[components.Component] = None
        port_2: Optional[components.Port] = None

        for port in components.Port.port_objects:
            # Esse if não entrou nenhuma vez, então o probllema deve estar em uma dessas condições, ou em mais de uma delas
            if (port.id == arg_1) and (
                port.location is not None
            ):  # and (port != None)):
                port_1 = port

                for component in components.Component.component_objects:
                    assert port_1 is not None

                    if (component is not None) and component.id == port_1.location:
                        comp_1 = component

        for port in components.Port.port_objects:
            if (port.id == arg_2) and (port.location is not None):
                port_2 = port

                for component in components.Component.component_objects:
                    assert port_2 is not None

                    if (component is not None) and component.id == port_2.location:
                        comp_2 = component

        from . import current as current

        if comp_1 is None:
            for cur in current.Current.current_objects:
                if (cur.id == arg_1) and (cur is not None):
                    comp_1 = cur

                    if (comp_2 is not None) and (len(self.joints_list) == 0):
                        # * if comp_1.relational_status == 'unfixed':

                        comp_2.component_ports[0].spacial_position = bgo.Point(0, 0, 0)

                        comp_2.position_solver()

                    self.graph.add_node(
                        comp_1.component_ports[0].id,
                        pos=comp_1.component_ports[0].spacial_position.coords,
                    )

                    # *print(f'\nArg_2 is a current, None is returned, so that the control flow exits the joint method')
                    assert comp_2 is not None
                    for port in comp_2.component_ports:
                        if (port.id != comp_2.component_ports[0]) and (
                            self.graph is not None
                        ):
                            if self.graph.has_node(port.id) == False:
                                self.graph.add_node(
                                    port.id, pos=port.spacial_position.coords
                                )

                            if self.graph.has_edge(
                                comp_2.component_ports[0].id, port.id
                            ):
                                self.graph.add_edge(
                                    comp_2.component_ports[0].id, port.id
                                )

                    self.joints_list.append((arg_1, arg_2))
                    return None

                raise ValueError(
                    "\n comp_1 is not a current, nor a component, because it was not found inside none of those classes"
                )

        from . import current as current

        current_uuid_map: dict[UUID, current.Current] = {
            cur.id: cur for cur in current.Current.current_objects
        }

        if comp_2 == None:
            for cur in current.Current.current_objects:
                if cur.id == arg_2:
                    comp_2 = cur  # type: ignore

                    if (comp_1 is not None) and (len(self.joints_list) == 0):
                        # * if comp_1.relational_status == 'unfixed':

                        comp_1.component_ports[0].spacial_position = bgo.Point(0, 0, 0)

                        comp_1.position_solver()

                    if self.graph.has_node(comp_1.component_ports[0].id) == False:
                        self.graph.add_node(
                            comp_1.component_ports[0].id,
                            pos=comp_1.component_ports[0].spacial_position.coords,
                        )

                    for port in comp_1.component_ports:
                        if (port.id != comp_1.component_ports[0].id) and (
                            self.graph is not None
                        ):
                            if self.graph.has_node(port.id) == False:
                                self.graph.add_node(
                                    port.id, pos=port.spacial_position.coords
                                )

                            if self.graph.has_edge(
                                comp_1.component_ports[0].id, port.id
                            ):
                                self.graph.add_edge(
                                    comp_1.component_ports[0].id, port.id
                                )

                    self.joints_list.append((arg_1, arg_2))

                    # * Arg_2 is a current, None is returned, so that the control flow exits the joint method
                    return None

                print(f"\n{cur.id == arg_2 = }")
                print(f"\n{(comp_1 is not None) and (len(self.joints_list) == 0) = }")
                print(
                    f"\n{self.graph.has_node(comp_1.component_ports[0].id) == False = }"
                )
                print(
                    f"\n{(port.id != comp_1.component_ports[0].id) and (
                            self.graph is not None
                        ) = }"
                )
                print(f"\n{self.graph.has_node(port.id) == False = }")
                print(f"\n{self.graph.has_node(port.id) == False = }")
                print(
                    f"\n{self.graph.has_edge(
                                comp_1.component_ports[0].id, port.id
                            ) = }"
                )
                # else:
                raise ValueError(
                    f"\n{arg_1 = }, {arg_2 = }\n{comp_1 = }\n{comp_2 = } is not a current, nor a component, because it was not found inside none of those classes"
                )

        # assert comp_1 != None
        # assert comp_2 != None
        # assert port_1 != None
        # assert port_2 != None

        match comp_1, comp_1.relational_status(), comp_2, comp_2.relational_status():
            case (
                x,
                "unfixed",
                y,
                "unfixed",
            ) if (x != None) and (y != None):
                # * In this case, the joint created must be the first one inside the code running, or the first joint of a new
                # mosaic
                comp_1.component_ports[0] = comp_1.component_ports[0]
                comp_1.component_ports[0].spacial_position = bgo.Point(0, 0, 0)

                # // This part comes from the 'c1-fixed, c2-unfixed case', and it considers the c1_component_ports[0].spacial_position= bgo.Point(0,0,0)

                if len(comp_1.component_ports) == 2:
                    if comp_1.component_ports[0].spacial_position != None:
                        comp_1.position_solver()

                        pass

                elif len(comp_1.component_ports) > 2:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_2.spacial_position = port_1.spacial_position

                    comp_2.component_ports[0].spacial_position = port_2.spacial_position

                    comp_2.position_solver()

                    pass

                if len(comp_2.component_ports) == 2:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_2.spacial_position = port_1.spacial_position

                    # //comp_2.component_ports[0] = comp_2.component_ports[0]
                    comp_2.component_ports[0].spacial_position = port_2.spacial_position

                    comp_2.position_solver()

                    pass

                elif len(comp_2.component_ports) > 2:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_2.spacial_position = port_1.spacial_position

                    # //comp_2.component_ports[0] = comp_2.component_ports[0]
                    comp_2.component_ports[0].spacial_position = port_2.spacial_position

                    comp_2.position_solver()

                    pass

            case (
                x,
                "fixed",
                y,
                "unfixed",
            ) if (x != None) and (y != None):
                if len(comp_1.component_ports) == 2:
                    if comp_1.component_ports[0].spacial_position != None:
                        comp_1.position_solver()

                        pass

                elif len(comp_1.component_ports) > 2:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_2.spacial_position = port_1.spacial_position

                    # //comp_2.component_ports[0] = comp_2.component_ports[0]
                    comp_2.component_ports[0].spacial_position = port_2.spacial_position

                    comp_2.position_solver()

                    pass

                if len(comp_2.component_ports) == 2:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_2.spacial_position = port_1.spacial_position

                    comp_2.component_ports[0].spacial_position = port_2.spacial_position

                    comp_2.position_solver()

                    pass

                elif len(comp_2.component_ports) > 2:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_2.spacial_position = port_1.spacial_position

                    comp_2.component_ports[0].spacial_position = port_2.spacial_position

                    comp_2.position_solver()

                    pass

            case (
                x,
                "unfixed",
                y,
                "fixed",
            ) if (x != None) and (y != None):
                if len(comp_2.component_ports) == 2:
                    if comp_2.component_ports[0].spacial_position != None:
                        comp_2.position_solver()

                        pass

                elif len(comp_2.component_ports) > 2:
                    assert port_2 is not None
                    assert port_1 is not None

                    port_1.spacial_position = port_2.spacial_position

                    comp_1.component_ports[0].spacial_position = port_1.spacial_position

                    comp_1.position_solver()
                    pass

                if len(comp_1.component_ports) == 2:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_1.spacial_position = port_2.spacial_position

                    comp_1.component_ports[0].spacial_position = port_1.spacial_position

                    comp_1.position_solver()

                    pass

                elif len(comp_1.component_ports) > 2:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_1.spacial_position = port_2.spacial_position

                    comp_1.component_ports[0].spacial_position = port_1.spacial_position

                    comp_1.position_solver()

                    pass

            case x, "fixed", y, "fixed":
                """
                This is where the 'snap' optin between two ports could happen but its an optional feature


                // Nesse caso, eu pensei em usar dois criterios para fazer o 'snap' entre as duas portas
                // O primeiro cirterio seria verificar qual dos dois componentes tem mais componentes ou correntes
                // conectadas a ele. O componente com o maior numer o de correntes ou componentes conectados a ele
                // deverá permanecer com a sua porta fixa, enquanto o segundo componente terá a porta 'dobrada' na
                // direção da primeira porta. e essa porta que vai ser dobrada no espaço é a que vai sofrer o snap, mas a
                // primeira porta vai permanecer fixa

                // Se o primeiro critério empatar, o segundo critério vai desempatar a disputa pelo 'snap'

                // A segunda opção seria verificar qual dos dois componentes é mais antigo dentro do mosaico.
                // Isso significa que eu precisaria verificar qual dos componentes teve uma junta registrada mais cedo
                // dentro da lista de juntas do mosaico antes do outro
                // Uma forma de fazer isso seria verificar qual é o index da primeira junta de cada um dos componentes
                // dentro do mosaico. O menor index Vence a disputa, e o componente com o maior index deve sofrer o 'snap'
                // e a sua porta que está sendo unida à outra deve ser dobrada na direção do componente 'mais velho'

                //   O que eu preciso descobrir é como encontrar a primeira junta que um componente realizou no mosaico.
                """

                # Detector of the index of the first joint created by a component inside the mosaic
                def find_oldest_comp_in_mosaic():
                    comp_1_oldest_joint_index: Union[int, None] = None
                    comp_2_oldest_joint_index: Union[int, None] = None

                    for joint_index, joint in enumerate(self.joints_list):
                        for obj in joint:
                            for port in components.Port.port_objects:
                                if port.id == obj:
                                    for (
                                        component
                                    ) in components.Component.component_objects:
                                        if component.id == port.location:
                                            if component.id == comp_1.id:
                                                comp_1_oldest_joint_index = joint_index
                                                pass

                                            if component.id == comp_2.id:
                                                comp_2_oldest_joint_index = joint_index
                                                pass

                    if (comp_1_oldest_joint_index != None) and (
                        comp_2_oldest_joint_index != None
                    ):
                        if comp_1_oldest_joint_index < comp_2_oldest_joint_index:
                            return comp_1

                        elif comp_2_oldest_joint_index < comp_1_oldest_joint_index:
                            return comp_2

                        elif comp_1_oldest_joint_index == comp_2_oldest_joint_index:
                            raise ValueError("\n\nThis should be impossible")

                        else:
                            raise ConduitForgeError(
                                "\n\nThere should be no possibility of those numbers to be something different than the other if and elif blocks"
                            )

                    else:
                        # * This else block after the for loop means that if all iterations run without a return statement,
                        # * this error should automatically run

                        raise ConduitForgeError(
                            f"Neither {comp_1 = } nor {comp_2 = } where found during the search"
                        )

                oldest_comp = find_oldest_comp_in_mosaic()

                if oldest_comp.id == comp_1.id:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_2.spacial_position = port_1.spacial_position
                    pass

                elif oldest_comp.id == comp_2.id:
                    assert port_1 is not None
                    assert port_2 is not None

                    port_1.spacial_position = port_2.spacial_position
                    pass

                """
                Uma outra forma de fazer isso poderia ser pegando qual é a porta de index 0 de comp1 e comp2, já que a
                primeira junta de ada componente é feita na porta 0, e a segunda na porta 1, e assim por diante.

                Dessa forma, teoricamente, eu só precisaria pricurar uma junta dentro do mosaico que contenha o id da
                porta 0 de cada um dos componentes, e verificar qual é o index dessas duas juntas.

                O problema com essa abordagem é que, apesar de ser direta, ela pode falhar por proble4mas inviziveis no meu
                codigo, que agora eu não tenho tempo para resolver ou analizar, então eu vou ficar com o método mais
                robusto por enquanto e, depois de tudo acabar, essa é uma melhoria que ue posso fazer no codigo, se eu
                tiver tempo
                """

                # raise NotImplementedError

            case (
                None,
                x,
                y,
                z,
            ) if y != None:
                raise ValueError("\ncomp_1 == None")

            case (
                x,
                y,
                None,
                z,
            ) if x != None:
                raise ValueError("\ncomp_2 == None")

            case None, x, None, y:
                raise ValueError("\ncomp_1 and comp_2 == None")

            case _:
                raise ValueError("\nSomething wrong happened")

        # // for port in comp_1.component_ports:
        # //    if self.graph.has_node(port.id) == False:
        # //        self.graph.add_node(port.id, pos = port.spacial_position.coords)

        # //         raise ConduitForgeError(f'\n\nThis part maybe creating the nodes that have no edge conected to them')

        # // for port in comp_2.component_ports:
        # //     if self.graph.has_node(port.id) == False:
        # //         self.graph.add_node(port.id, pos = port.spacial_position.coords)

        # //         raise ConduitForgeError(f'\n\nThis part maybe creating the nodes that have no edge conected to them')

        # // if ((self.graph.has_edge(arg_1, arg_2) == False) and (self.graph.has_edge(arg_2, arg_1 == False))):
        # //     self.graph.add_edge(arg_1, arg_2)

        # //     raise ConduitForgeError(f'\n\nThis part maybe creating the nodes that have no edge conected to them')

        print(f"\n\n{arg_1, arg_2 = }\n\n")

        # // In this section, the compositions inside all the mosaic will be
        # // setted to be homogenous (all equal, with equal T)
        comp_uuid_map = {
            comp.id: comp for comp in components.Component.component_objects
        }

        curr_uuid_map = {cur.id: cur for cur in current.Current.current_objects}

        currs_inside_self: list[UUID] = []

        comps_inside_self: list[UUID] = []

        # // finding the comps and currents in self

        if False:
            for j in self.joints_list:
                for some_obj in j:
                    if isinstance(some_obj, Iterable):
                        raise ValueError(
                            "i dont remeber if this is possible and allowed to happen"
                        )

                    if some_obj in curr_uuid_map.keys():
                        # * Search for another original current inside the self mosaic
                        currs_inside_self.append(some_obj)

                    if some_obj in comp_uuid_map.keys():
                        # * Search for another original current inside the self mosaic
                        comps_inside_self.append(some_obj)

            for curr_id in currs_inside_self:
                for some_orig_self_curr_id in currs_inside_self:
                    if curr_id != some_orig_self_curr_id:
                        try:
                            assert (
                                curr_uuid_map[curr_id].composition.T
                                == curr_uuid_map[some_orig_self_curr_id].composition.T
                            )

                            assert (
                                curr_uuid_map[curr_id].composition.P
                                == curr_uuid_map[some_orig_self_curr_id].composition.P
                            )

                            assert (
                                curr_uuid_map[curr_id].composition.ID
                                == curr_uuid_map[some_orig_self_curr_id].composition.ID
                            )

                        except:
                            if (curr_uuid_map[curr_id].composition.ID == "water") and (
                                curr_uuid_map[some_orig_self_curr_id].composition.ID
                                != "water"
                            ):
                                curr_uuid_map[curr_id].composition = curr_uuid_map[
                                    some_orig_self_curr_id
                                ].composition

                                # curr_uuid_map[curr_id].composition.ID = curr_uuid_map[
                                #     some_orig_self_curr_id
                                # ].composition.ID

                                # curr_uuid_map[curr_id].composition.T = curr_uuid_map[
                                #     some_orig_self_curr_id
                                # ].composition.T

                                # curr_uuid_map[curr_id].composition.P = curr_uuid_map[
                                #     some_orig_self_curr_id
                                # ].composition.P

                            elif (
                                curr_uuid_map[some_orig_self_curr_id].composition.ID
                                == "water"
                            ) and (curr_uuid_map[curr_id].composition.ID != "water"):
                                curr_uuid_map[
                                    some_orig_self_curr_id
                                ].composition = curr_uuid_map[curr_id].composition

                                # curr_uuid_map[
                                #     some_orig_self_curr_id
                                # ].composition.ID = curr_uuid_map[curr_id].composition.ID

                                # curr_uuid_map[
                                #     some_orig_self_curr_id
                                # ].composition.T = curr_uuid_map[curr_id].composition.T

                                # curr_uuid_map[
                                #     some_orig_self_curr_id
                                # ].composition.P = curr_uuid_map[curr_id].composition.P

                            elif (
                                curr_uuid_map[curr_id].composition.ID == "water"
                            ) and (
                                curr_uuid_map[some_orig_self_curr_id].composition.ID
                                == "water"
                            ):
                                evaluated_curr_pair: list[UUID] = [
                                    curr_id,
                                    some_orig_self_curr_id,
                                ]
                                standard_composition = nc.pure_water

                                if (
                                    curr_uuid_map[curr_id].composition.T
                                    == curr_uuid_map[
                                        some_orig_self_curr_id
                                    ].composition.T
                                ):
                                    for c_uuid in evaluated_curr_pair:
                                        if (
                                            curr_uuid_map[c_uuid].composition.T
                                            != standard_composition.T
                                        ):
                                            curr_uuid_map[
                                                evaluated_curr_pair[
                                                    1
                                                    - evaluated_curr_pair.index(c_uuid)
                                                ]
                                            ].composition = curr_uuid_map[
                                                c_uuid
                                            ].composition

                                            # curr_uuid_map[
                                            #     evaluated_curr_pair[
                                            #         1 - evaluated_curr_pair.index(c_uuid)
                                            #     ]
                                            # ].composition.ID = curr_uuid_map[
                                            #     c_uuid
                                            # ].composition.ID

                                            # curr_uuid_map[
                                            #     evaluated_curr_pair[
                                            #         1 - evaluated_curr_pair.index(c_uuid)
                                            #     ]
                                            # ].composition.P = curr_uuid_map[
                                            #     c_uuid
                                            # ].composition.P

                                        elif (
                                            curr_uuid_map[
                                                evaluated_curr_pair[
                                                    1
                                                    - evaluated_curr_pair.index(c_uuid)
                                                ]
                                            ].composition.T
                                            != standard_composition.T
                                        ):
                                            curr_uuid_map[
                                                c_uuid
                                            ].composition = curr_uuid_map[
                                                evaluated_curr_pair[
                                                    1
                                                    - evaluated_curr_pair.index(c_uuid)
                                                ]
                                            ].composition

                                            # curr_uuid_map[
                                            #     c_uuid
                                            # ].composition.ID = curr_uuid_map[
                                            #     evaluated_curr_pair[
                                            #         1 - evaluated_curr_pair.index(c_uuid)
                                            #     ]
                                            # ].composition.ID

                                            # curr_uuid_map[
                                            #     c_uuid
                                            # ].composition.T = curr_uuid_map[
                                            #     evaluated_curr_pair[
                                            #         1 - evaluated_curr_pair.index(c_uuid)
                                            #     ]
                                            # ].composition.T

                                elif (
                                    curr_uuid_map[curr_id].composition.P
                                    == curr_uuid_map[
                                        some_orig_self_curr_id
                                    ].composition.P
                                ):
                                    for c_uuid in evaluated_curr_pair:
                                        if (
                                            curr_uuid_map[c_uuid].composition.P
                                            != standard_composition.P
                                        ):
                                            curr_uuid_map[
                                                evaluated_curr_pair[
                                                    1
                                                    - evaluated_curr_pair.index(c_uuid)
                                                ]
                                            ].composition = curr_uuid_map[
                                                c_uuid
                                            ].composition

                                            # curr_uuid_map[
                                            #     evaluated_curr_pair[
                                            #         1 - evaluated_curr_pair.index(c_uuid)
                                            #     ]
                                            # ].composition.ID = curr_uuid_map[
                                            #     c_uuid
                                            # ].composition.ID

                                            # curr_uuid_map[
                                            #     evaluated_curr_pair[
                                            #         1 - evaluated_curr_pair.index(c_uuid)
                                            #     ]
                                            # ].composition.T = curr_uuid_map[
                                            #     c_uuid
                                            # ].composition.T

                                        elif (
                                            curr_uuid_map[
                                                evaluated_curr_pair[
                                                    1
                                                    - evaluated_curr_pair.index(c_uuid)
                                                ]
                                            ].composition.P
                                            != standard_composition.P
                                        ):
                                            curr_uuid_map[
                                                c_uuid
                                            ].composition = curr_uuid_map[
                                                evaluated_curr_pair[
                                                    1
                                                    - evaluated_curr_pair.index(c_uuid)
                                                ]
                                            ].composition

                                            # curr_uuid_map[
                                            #     c_uuid
                                            # ].composition.ID = curr_uuid_map[
                                            #     evaluated_curr_pair[
                                            #         1 - evaluated_curr_pair.index(c_uuid)
                                            #     ]
                                            # ].composition.ID

                                            # curr_uuid_map[
                                            #     c_uuid
                                            # ].composition.T = curr_uuid_map[
                                            #     evaluated_curr_pair[
                                            #         1 - evaluated_curr_pair.index(c_uuid)
                                            #     ]
                                            # ].composition.T

                            else:
                                raise ValueError(
                                    r"\nThis is a scenario that wasnt planned,"
                                )

            # raise ValueError(r"""It seems that the benzen composition is recieving the temperature
            #     from the standard composition (pure_water) from the numerical constants
            #     module""")

            for self_comp in comps_inside_self:
                for port in comp_uuid_map[self_comp].component_ports:
                    port.local_current.composition = curr_uuid_map[
                        currs_inside_self[0]
                    ].composition

        self.joints_list.append((arg_1, arg_2))

        print(f"\n{self.joints_list = }")

    def create_graph(self) -> None:
        """
        This method is the one responsible for creating the direct graph that represents the Components connections
        between each other inside the Mosaic.
        """

        assert self.graph is not None

        for some_comp in components.Component.component_objects:
            if some_comp.location == self.id:
                for some_port in some_comp.component_ports:
                    back_color = Back.YELLOW
                    self.graph.add_node(
                        some_port.id, pos=some_port.spacial_position.coords
                    )
                    # print(f'\n\n{Fore.BLACK + back_color}{some_comp.id = }\n{some_port.id = }\n{some_port.spacial_position = }{Style.RESET_ALL}')

            elif some_comp.location != self.id:
                pass

            else:
                raise TypeError

        """
        The next step is to check to what compnent each point belongs. After this checking, if the components are pipes,
        the two nodes will be used to create an edge.
        """
        # nodes_list = list(self.graph.nodes()) #//data = True

        current_uuid_map: dict[UUID, current.Current] = {
            cur.id: cur for cur in current.Current.current_objects
        }

        port_uuid_map: dict[UUID, components.Port] = {
            port.id: port for port in components.Port.port_objects
        }

        component_uuid_map: dict[UUID, components.Component] = {
            comp.id: comp for comp in components.Component.component_objects
        }

        edges: list[tuple[UUID, UUID]] = []

        for comp in components.Component.component_objects:
            if comp.location == self.id:
                # This part means that all the components that have the self mosaic as their location, will be used
                # to create the edges of the graph

                component_root_node: UUID = comp.component_ports[-1].id
                port_node: None | UUID = None
                other_port_node: None | UUID = None

                for port in comp.component_ports:
                    if (
                        (comp.component_ports[0].spacial_position != None)
                        and (port.id != comp.component_ports[-1].id)
                        and (len(comp.component_ports) == 2)
                    ):
                        # and (self.graph.has_edge(port.id, comp.component_ports[0].spacial_position.id) == True)

                        port_node = port.id

                        # for element in self.graph.nodes():
                        #     if element == port.id:
                        #         port_node = element

                        for p in comp.component_ports:
                            if p.id != port_node:
                                other_port_node = p.id

                        # Se o nó tiver o mesmo uuid que o ponto raiz, esse nó vai ser chamado de nó raiz
                        if (
                            (
                                self.graph.has_node(comp.component_ports[1].id)  # noqa: E712
                            )
                            and (comp.port_quantity == len(comp.component_ports))
                            and (not isinstance(comp, components.T_connector))
                            and (
                                (not self.graph.has_edge(other_port_node, port_node))
                                and (
                                    not self.graph.has_edge(port_node, other_port_node)
                                )
                            )
                        ):
                            # port_node = port_uuid_map[port].id

                            # # for element in self.graph.nodes():
                            # #     if element == port.id:
                            # #         port_node = element

                            # for p in comp.component_ports:
                            #     if p.id != port_node:
                            #         other_port_node = p.id

                            assert port_node != None
                            assert other_port_node != None

                            edges.append((other_port_node, port_node))

                        elif comp.port_quantity != len(comp.component_ports):
                            # for element in self.graph.nodes():
                            #     if element == port.id:
                            #         port_node = element

                            comp_root_port = comp.component_ports[-1].id

                            assert port_node != None
                            assert comp_root_port != None

                            if (
                                (
                                    (not self.graph.has_edge(comp_root_port, port_node))
                                    and (
                                        not self.graph.has_edge(
                                            port_node, comp_root_port
                                        )
                                    )
                                )
                                and (self.graph.has_node(comp_root_port))
                                and (self.graph.has_node(port_node))
                            ):
                                edges.append((comp_root_port, port_node))

                        elif (
                            (
                                self.graph.has_node(comp.component_ports[-1].id)  # noqa: E712
                            )
                            and (comp.port_quantity != len(comp.component_ports))
                            and isinstance(comp, components.T_connector)
                        ):
                            # // if the component is not an instance of the T_connector class,
                            # // It should be impossible to have the port quantity != len(comp_ports)

                            raise ConduitForgeError(
                                """\n\n if the component is not an instance of the T_connector class,
                                It should be impossible to have the port quantity != len(comp_ports),
                                at least by how the project is now (31/12/2024)"""
                            )

                        elif self.graph.has_node(comp.component_ports[0].id) == False:  # noqa: E712
                            self.graph.add_node(comp.component_ports[0].id)

                    #! I need to code this part specially for components with 3 or more ports

                    elif (
                        (comp.component_ports[-1].spacial_position != None)
                        and (port.id != comp.component_ports[-1].id)
                        and (len(comp.component_ports) == 3)
                        and (comp.component_ports[0].spacial_position != None)
                        and (port.id != comp.component_ports[0].id)
                    ):
                        # and (self.graph.has_edge(port.id, comp.component_ports[0].spacial_position.id) == True)

                        # Se o nó tiver o mesmo uuid que o ponto raiz, esse nó vai ser chamado de nó raiz
                        if (
                            (self.graph.has_node(comp.component_ports[-1].id))
                            and (self.graph.has_node(port_node))
                            and (
                                (
                                    not self.graph.has_edge(
                                        component_root_node, port_node
                                    )
                                )
                                and (
                                    not self.graph.has_edge(
                                        port_node, component_root_node
                                    )
                                )
                            )
                        ):
                            # for element in self.graph.nodes():
                            #     if element == port.id:
                            #         port_node = element

                            assert port_node is not None

                            edges.append((component_root_node, port_node))

                        elif not self.graph.has_node(comp.component_ports[-1].id):
                            self.graph.add_node(comp.component_ports[0].id)

                    elif (len(comp.component_ports) == comp.port_quantity + 1) and (
                        isinstance(comp, components.MinorLossComponent)
                    ):
                        for port_ml_comp_index, port_from_minor_loss_comp in enumerate(
                            comp.component_ports
                        ):
                            comp_central_port = comp.component_ports[-1]

                            if (
                                (
                                    port_from_minor_loss_comp.id
                                    is not comp_central_port.id
                                )
                                and (
                                    not self.graph.has_edge(
                                        port_from_minor_loss_comp.id,
                                        comp_central_port.id,
                                    )
                                )
                                and (
                                    not self.graph.has_edge(
                                        comp_central_port.id,
                                        port_from_minor_loss_comp.id,
                                    )
                                )
                            ):
                                assert port_from_minor_loss_comp is not None

                                if not self.graph.has_node(comp_central_port):
                                    self.graph.add_node(
                                        comp.component_ports[port_ml_comp_index].id
                                    )

                                edges.append(
                                    (port_from_minor_loss_comp.id, comp_central_port.id)
                                )

                        # raise NotImplementedError(
                        #     "\n\n I need to code this part specially for components with 3 or more ports"
                        # )

                    elif comp.component_ports[-1].spacial_position is None:
                        raise ValueError(
                            f"the {comp.component_ports[-1].id = } has {comp.component_ports[-1].spacial_position = }"
                        )

                    elif (
                        comp.component_ports[-1].spacial_position.has_none_coord()
                    ) and (comp.component_ports[-1].spacial_position is None):
                        raise ValueError

                    elif comp.component_ports[-1].spacial_position.has_none_coord():
                        raise ValueError

                    elif (
                        not comp.component_ports[-1].spacial_position.has_none_coord()
                    ) and (comp.component_ports[-1].spacial_position is not None):
                        pass  # continue

                    else:
                        print(
                            f"\n\n{comp.component_ports[-1].spacial_position.has_none_coord() = }"
                        )
                        print(f"\n\n{comp.component_ports[-1].spacial_position = }")
                        print(f"\n\n{port.id = }")
                        raise TypeError(
                            "The comp.component_ports[0].spacial_position.has_none_coord should be a bool!"
                        )

        # * This part adds the nodes from the joints list (only if they are not already inside the graph)
        # * This part will create endges based in the joints list (only if those edges aren't already inside the graph)

        for joint in self.joints_list:
            for obj in joint:
                if (self.graph.has_node(obj) == False) and (
                    obj in current_uuid_map.keys()
                ):
                    self.graph.add_node(obj)

            if (
                (self.graph.has_edge(joint[0], joint[1]) == False)
                and (self.graph.has_edge(joint[1], joint[0]) == False)
                and (
                    (joint[0] not in current_uuid_map.keys())
                    or (joint[1] not in current_uuid_map.keys())
                )
            ):
                self.graph.add_edge(joint[0], joint[1])

            if (
                (self.graph.has_edge(joint[1], joint[0]) == False)
                and (self.graph.has_edge(joint[0], joint[1]) == False)
                and (
                    (joint[0] not in current_uuid_map.keys())
                    or (joint[1] not in current_uuid_map.keys())
                )
            ):
                self.graph.add_edge(joint[1], joint[0])

        self.graph.add_edges_from(edges)

        self_loops = list(nx.selfloop_edges(self.graph))

        # print(f'\n{self_loops = }')

        self.graph.remove_edges_from((self_loops))

        #! Sanity check

        for node in self.graph.nodes():
            n_in_deg = node.in_degree()
            n_out_deg = node.out_degree()

            assert n_in_deg + n_out_deg <= 3
        else:
            print(f"\n\nin_deg and out_deg OK for all nodes!")

        for comp in components.Component.component_objects:
            if comp.location == self.id:
                if (comp.port_quantity == len(comp.component_ports)) and (
                    len(comp.component_ports) == 2
                ):
                    first_node = comp.component_ports[0].id
                    second_node = comp.component_ports[1].id

                    assert self.graph.has_node(first_node)
                    assert self.graph.has_node(second_node)

                    assert (self.graph.has_edge(first_node, second_node)) or (
                        self.graph.has_edge(second_node, first_node)
                    )

                elif (comp.port_quantity != len(comp.component_ports)) and len(
                    comp.component_ports == 4
                ):
                    for cp_index, comp_port in enumerate(comp.component_ports):
                        root_node = comp.component_ports[-1].id
                        some_node: UUID | None = None

                        for some_port in comp.component_ports:
                            if (some_port.id != root_node) and (
                                some_port.id != comp.component_ports[cp_index - 1]
                            ):
                                some_node = some_port.id
                                break

                        assert some_node != None
                        assert root_node != None

                        assert self.graph.has_node(root_node)
                        assert self.graph.has_node(some_node)

                        assert (self.graph.has_edge(root_node, some_node)) or (
                            self.graph.has_edge(some_node, root_node)
                        )

                else:
                    raise NotImplementedError("""\nThe component graph generation needs to be coded
                        for said component""")

    def create_graph_2(self):
        current_uuid_map: dict[UUID, current.Current] = {
            cur.id: cur for cur in current.Current.current_objects
        }

        port_uuid_map: dict[UUID, components.Port] = {
            port.id: port for port in components.Port.port_objects
        }

        component_uuid_map: dict[UUID, components.Component] = {
            comp.id: comp for comp in components.Component.component_objects
        }

        # // Creation of the nodes for the component_ports
        for comp in components.Component.component_objects:
            if comp.location == self.id:
                for port in comp.component_ports:
                    if not self.graph.has_node(port.id):
                        # print(f"\n{port.id = }")
                        # print(f"\n{list(self.graph.nodes()) = }")
                        self.graph.add_node(port.id, pos=port.spacial_position.coords)

        # // Creation of the joint edges
        for joint in self.joints_list:
            for obj in joint:
                other_obj: None | UUID = None

                for some_id in joint:
                    if some_id != obj:
                        other_obj = some_id

                if (
                    (not self.graph.has_edge(obj, other_obj))
                    and (not self.graph.has_edge(other_obj, obj))
                    # and (self.graph.has_node(obj))
                    # and (self.graph.has_node(other_obj))
                ):
                    if obj in current_uuid_map.keys():
                        # // There should not exist joints with two currents
                        assert other_obj in port_uuid_map.keys()

                        if self.graph.has_node(obj):
                            self.graph.add_node(
                                obj, pos=port_uuid_map[obj].spacial_position.coords
                            )

                        elif self.graph.has_node(obj) and (
                            not self.graph.has_node(other_obj)
                        ):
                            self.graph.add_node(
                                other_obj,
                                pos=port_uuid_map[other_obj].spacial_position.coords,
                            )

                        self.graph.add_edge(obj, other_obj)
                        continue

                    elif obj in port_uuid_map.keys():
                        assert (other_obj in port_uuid_map.keys()) or (
                            other_obj in current_uuid_map.keys()
                        )

                        if not self.graph.has_node(obj):
                            self.graph.add_node(
                                obj,
                                pos=port_uuid_map[other_obj].spacial_position.coords,
                            )

                        elif (
                            (self.graph.has_node(obj))
                            and (not self.graph.has_node(other_obj))
                            and (other_obj in port_uuid_map.keys())
                        ):
                            self.graph.add_node(
                                other_obj,
                                pos=port_uuid_map[other_obj].spacial_position.coords,
                            )

                        elif (
                            (self.graph.has_node(other_obj))
                            and (not self.graph.has_node(obj))
                            and (obj in current_uuid_map.keys())
                        ):
                            self.graph.add_node(
                                obj,
                                pos=port_uuid_map[obj].spacial_position.coords,
                            )

                        self.graph.add_edge(obj, other_obj)
                        continue

                    elif obj in component_uuid_map.keys():
                        raise TypeError(f"""There should be no component id inside the
                            joints_list, the id is :{obj}""")

                    else:
                        raise TypeError("""The obj and other obj should be inside
                            the current_uuid_map.keys() or port_uuid_map.keys()""")

                else:
                    continue

        # // Creation of the internal edges of the components
        for comp in components.Component.component_objects:
            if comp.location == self.id:
                for port in comp.component_ports:
                    # // Those should be comps like Pipe, Pump or Straight_Fitting
                    if (comp.port_quantity == len(comp.component_ports)) and (
                        comp.port_quantity == 2
                    ):
                        other_port: components.Port | None = None

                        for p in comp.component_ports:
                            if p.id != port.id:
                                other_port = p

                        assert other_port is not None

                        if (
                            (not self.graph.has_edge(port.id, other_port.id))
                            and (not self.graph.has_edge(other_port.id, port.id))
                            and (port.location == comp.id)
                            and (port.location == other_port.location)
                            # and (self.graph.has_node(port.id))
                            # and (self.graph.has_node(other_port.id))
                        ):
                            if not self.graph.has_node(port.id):
                                self.graph.add_node(
                                    port.id, pos=port.spacial_position.coords
                                )

                            if not self.graph.has_node(other_port.id):
                                self.graph.add_node(
                                    other_port.id,
                                    pos=other_port.spacial_position.coords,
                                )

                            self.graph.add_edge(port.id, other_port.id)

                    # // Those should be components like the T_connector

                    elif (
                        comp.port_quantity != len(comp.component_ports)
                        # and (len(comp.component_ports) == 4)
                        # and (self.graph.has_node(port.id))
                        # and (self.graph.has_node(comp.component_ports[-1].id))
                    ):
                        for another_port in comp.component_ports:
                            comp_root_port = comp.component_ports[-1]

                            # // root_port cartesian position
                            rp_cartesian_position = (
                                comp_root_port.spacial_position.coords
                            )

                            if self.graph.has_node(comp_root_port.id) is False:
                                self.graph.add_node(
                                    comp_root_port.id, pos=rp_cartesian_position
                                )

                            if self.graph.has_node(another_port.id) is False:
                                self.graph.add_node(
                                    another_port.id, pos=port.spacial_position.coords
                                )

                            if (
                                (
                                    self.graph.has_edge(
                                        another_port.id, comp_root_port.id
                                    )
                                    is False
                                )
                                and (
                                    self.graph.has_edge(
                                        comp_root_port.id, another_port.id
                                    )
                                    is False
                                )
                                and (another_port.id != comp.component_ports[-1].id)
                                # and (another_port.location == comp.id)
                                # and (another_port.location == other_port.location)
                            ):
                                self.graph.add_edge(another_port.id, comp_root_port.id)

                    elif (comp.port_quantity != len(comp.component_ports)) and (
                        len(comp.component_ports) != 4
                    ):
                        raise NotImplementedError(f"""the {comp = } is not an
                            objectfrom the classes existent in the moment""")

        # // exclusion of self loops (edges between one point and itself)
        self_loops = list(nx.selfloop_edges(self.graph))

        self.graph.remove_edges_from(self_loops)

        #! Exclusion of reciprocal edges (two edges that one is the inverse of the other,
        #! and those edges exist between the same two nodes)

        for edge in list(self.graph.edges()):
            # reverse_edge = (edge[1], edge[0])
            assert not self.graph.has_edge(edge[1], edge[0])
        else:
            print("\n\nNo reciprocal edges!\n\n")

        # // Sanity check

        for node in self.graph.nodes():
            n_in_deg = self.graph.in_degree(node)
            n_out_deg = self.graph.out_degree(node)

            try:
                assert n_in_deg + n_out_deg <= 3
            except:
                print(f"\n{node = }\n")

                print(f"\n{n_in_deg = }\n")
                print(f"\n{n_out_deg = }\n")

                print(f"\n{(node in port_uuid_map) = }\n")
                print(f"\n{(node in current_uuid_map) = }\n")

                if node in port_uuid_map:
                    print(f"\n{(node in port_uuid_map) = }\n")
                    node_port = port_uuid_map[node]

                    print(f"\n{node_port.location = }\n")

                elif node in current_uuid_map:
                    print(f"\n{(node in current_uuid_map) = }\n")
                    node_cur = current_uuid_map[node]

                    # print(f"{node_cur.location = }")

                #!  raise AssertionError
        else:
            print(f"\n\nin_deg and out_deg OK for all nodes!")

        for comp in components.Component.component_objects:
            if comp.location == self.id:
                if (comp.port_quantity == len(comp.component_ports)) and (
                    len(comp.component_ports) == 2
                ):
                    for node in self.graph.nodes():
                        # print(f"\n{node = }\n")
                        first_node = comp.component_ports[0].id
                        second_node = comp.component_ports[1].id

                        assert self.graph.has_node(first_node) is True
                        assert self.graph.has_node(second_node) is True

                        # assert (
                        #     first_node in self.graph
                        # )

                        # assert (
                        #     second_node in self.graph
                        # )

                        assert (self.graph.has_edge(first_node, second_node)) or (
                            self.graph.has_edge(second_node, first_node)
                        )

                elif (comp.port_quantity != len(comp.component_ports)) and (
                    len(comp.component_ports) == 4
                ):
                    for cp_index, comp_port in enumerate(comp.component_ports):
                        root_node = comp.component_ports[-1].id
                        some_node: UUID | None = None

                        for some_port in comp.component_ports:
                            if some_port.id == root_node:
                                continue

                            if (some_port.id != root_node) and (
                                some_port.id != comp.component_ports[cp_index - 1]
                            ):
                                some_node = some_port.id

                                assert some_node != None
                                assert root_node != None

                                assert self.graph.has_node(root_node)
                                assert self.graph.has_node(some_node)

                                assert (self.graph.has_edge(root_node, some_node)) or (
                                    self.graph.has_edge(some_node, root_node)
                                )

                else:
                    raise NotImplementedError("""\nThe component graph generation needs to be coded
                        for said component""")

    def cycle_and_branch_identifier(self) -> None:
        """
        This method will be used to identify cicles and branches, and return them to the other methods

        The branch detection will be made by detecting the 'leaf' nodes of the graph. Thos enodes are the ones that there is
        just one inlet, but no outlet (inside the grapf representation).

        After detecting the leaf nodes, the code must track back from this node, detecting all the edges that forma a
        branch.

        In this case, The branches can have branches.
        """

        assert self.graph is not None

        # This function converts the graph to an undirected version
        # I had to use this function because the simple_cicles function is afected by the direction of the edges
        # and this can cause some cicles to be undetected.
        self.undirected_graph: Graph = self.graph.to_undirected()

        unsorted_simple_cycles_as_nodes: List[List[UUID]] = list(
            nx.simple_cycles(self.undirected_graph)
        )
        self.simple_cycles_as_nodes: List[List[UUID]] = unsorted_simple_cycles_as_nodes

        for obj_index, obj in enumerate(unsorted_simple_cycles_as_nodes):
            if len(obj) <= 2:
                del self.simple_cycles_as_nodes[obj_index]

                raise Warning(f"\n\n{self.simple_cycles_as_nodes[obj_index] = }")

        self.unsorted_branches: List = []

        self.sorted_branches: list = []

        self.leaf_nodes: List = [
            n for n, out_degree in self.graph.out_degree() if out_degree == 0
        ]

        # * Essa é uma idea de como encontrar todos os ramos, só que ela usa a exclusão dos ciclos do gráfico.

        # This part finds the edges that are in cycles
        edges_to_remove: List[Any] = []
        for cycle in self.simple_cycles_as_nodes:
            # Transformar o ciclo em pares de arestas e adicionar à lista
            edges_to_remove.extend(
                [(cycle[i], cycle[(i + 1) % len(cycle)]) for i in range(len(cycle))]
            )

        # This part creates the subgraph that doesn't contain any cycles
        self.acyclic_graph = self.undirected_graph.copy()
        self.acyclic_graph.remove_edges_from(edges_to_remove)

        self.unsorted_branches = list(self.acyclic_graph.edges)

        """
        Essa lista vai conter diferentes listas dentro dela. cada uma das listas vai conter um ramo.

        Para detectar um ramo, o codigo deve começar com as 'folhas' do gráfico, e seguir as arestas até uma outra folha.

        Com isso, o resultado final deve ser todos os ramos, sem que haja ramos diferentes com multiplas arestas iguais.
        """

        #! Essa parte precisa de revisão, e não deve ser usada antes de eu refatorar ela.

        all_branches = []

        # This part finds all the symple branches between two nodes
        for source in self.acyclic_graph.nodes():
            for target in self.acyclic_graph.nodes():
                if source != target:
                    for path in nx.all_simple_paths(
                        self.acyclic_graph, source=source, target=target
                    ):
                        all_branches.append(path)

        # This part sortds them so that only the unique ones remain in the final list

        for branch in all_branches:
            # This part verifies if the branch is not contained in a bigger branch
            if not any(
                set(branch).issubset(set(other_branch)) and branch != other_branch
                for other_branch in self.sorted_branches
            ):
                self.sorted_branches.append(branch)

        # * self.sorted_branches

        #! Essa parte precisa de revisão, e não deve ser usada antes de eu refatorar ela.

    def first_mass_flow_guess(self) -> None:
        """
        Essa função vai servir para 'chutar' um valor inicial para cada corrente dentro de cada porta de um component.

        Esse chute é importante, por que o método de Newton-Raphson só funciona quando as variáveis
        incógnitas já tem algum valor antes de realizar a primeira iteração. Além disso, vale lembrar
        que o método de N-R permite que, tanto os valores de entrada quanto de saída sejam positivos
        ou negativos. Se a vazão for positiva, o fluxo está ocorrendo na direção esperada pelo código.

        Se a vazão for negativa, o fluxo está ocorrendo na diração contrária à setada pelo código.

        EU pensei em, antes de chutar os valores, detectar quais são as portas de saída do mosaico.

        Depois disso,eu pensei em determinar que, a soma das vazões de saida deve ser igual à soma das vazões de
        entrada.

        Por fim, eu pensei em usar o gráfico para preencher os valores de vazão mássica a partir das
        correntes de entrada. Dessa forma, os valores seriam setados na ordem aproximada na qual
        o fluido deve escoar.

        Além disso, eu pensei em conferir se, para cada um dos componentes, a vazão chutada, obedece
        a conservação de massa local, no prorio componente.
        """

        # // Primeiro passo: Detectar quais são as correntes de entrada no mosaico.
        # * Eu pensei em fazer essa detecção pelas juntas do mosaico.

        # *(Correntes de Entrada)Ler joints_List, e procurar juntas que contenham UUIDs de correntes e portas.
        # *Isso deve funcionar por que uma junta entre uma corrente e uma porta só pode acontecer entre correntes
        # *que 'vivem' fora de uma porta (que são correntes originais)

        # self.global_inlet_currents: List[current.Current] = []

        port_uuid_map: dict[UUID, components.Port] = {
            port.id: port for port in components.Port.port_objects
        }
        current_uuid_map: dict[UUID, current.Current] = {
            cur.id: cur for cur in current.Current.current_objects
        }

        component_uuid_map: dict[UUID, components.Component] = {
            comp.id: comp for comp in components.Component.component_objects
        }
        for joint in self.joints_list:
            for obj_index, obj in enumerate(joint):
                # print(f'\n{obj = }')

                for cur in current.Current.current_objects:
                    assert cur is not None

                    # print(f'\n{obj = }')

                    if (
                        obj == cur.id
                    ):  # // and (obj not in self.global_inlet_currents)):
                        if cur.mass_flow is None:
                            cur.mass_flow = 10  # * kg/s ou m^3/s
                            cur.volume_flow = (cur.mass_flow) / (cur.density())

                            if isinstance(cur.location, tuple) or (
                                isinstance(cur.location, list)
                            ):
                                cur.velocity = (cur.mass_flow) / (
                                    cur.density()
                                    * port_uuid_map[cur.location[1]].cross_sect_area()
                                )

                            else:
                                cur.velocity = (cur.mass_flow) / (
                                    cur.density()
                                    * port_uuid_map[cur.location].cross_sect_area()
                                )

                            assert cur.mass_flow is not None
                            assert cur.volume_flow is not None
                            assert cur.velocity is not None
                        else:
                            pass

                        # print(f'\n************* {cur.id = } Selected *************')

                        self.global_inlet_currents.append(cur.id)

        # // passo 1b: definir que todas as correntes dentro dos componentes tenham composições e
        # // temperaturas iguais às das correntes de entrada globais do mosaico

        reference_orig_cur: current.Current | None = None
        for orig_cur_id in self.global_inlet_currents:
            orig_cur = current_uuid_map[orig_cur_id]
            for some_orig_cur in self.global_inlet_currents:
                assert (
                    orig_cur.composition.ID
                    == current_uuid_map[some_orig_cur].composition.ID
                )
                assert (
                    orig_cur.composition.T
                    == current_uuid_map[some_orig_cur].composition.T
                )
                assert (
                    orig_cur.temperature == current_uuid_map[some_orig_cur].temperature
                )
            else:
                reference_orig_cur = current_uuid_map[self.global_inlet_currents[0]]

        assert reference_orig_cur is not None

        for cp in components.Component.component_objects:
            if cp.location == self.id:
                for prt in cp.component_ports:
                    prt.local_current.composition = reference_orig_cur.composition
                    prt.local_current.temperature = reference_orig_cur.temperature

        # // Segundo passo: Detectar quais são as correntes de saída no mosaico.
        # *(Correntes de Saída) Ler  Joints list, e criar uma lista de todas as postas do mosaico.
        # *Essa lista de UUIDs de portas vai ser lida, e vai ser transformada em uma lista de portas.
        # *A lista de portas vai ser lida, e vai ser transformada em uma lista de componentes.
        # *(A lista de componentes não pode ter componentes repetidos).
        # *Essa lista de componentes vai ser lida, e transformada em uma lista temporaria de portas do componente.
        # *Essa lista de todas as portas do componente vai ser comparada com a lista de portas do mosaico.
        # * Nessa comparação, será criada uma nova lista, contendo somente as portas que NÃO aparecem em nenhuma
        # *do mosaico.
        # *A lista dessas portas é a lista de portas de saída.
        # * Por fim, esta lista de portas será lida, e uma nova lista contendo as correntes locais dessas
        # *portas será criada.
        # *Essa lista será lida, e cada uma das portas terá a sua pressão setada = 0
        self.global_mosaic_ports: list[components.Port] = []

        # Selection of all the ports inside the self Mosaic
        for joint in self.joints_list:
            for obj in joint:
                for port in components.Port.port_objects:
                    if (obj == port.id) and (port not in self.global_mosaic_ports):
                        # print(f'\n{port = }')
                        self.global_mosaic_ports.append(port)

        assert len(self.global_mosaic_ports) <= len(components.Port.port_objects)

        self.global_mosaic_components_as_uuids: list[UUID] = []

        # Selection of the components UUIDs inside the self MOsaic
        for port in self.global_mosaic_ports:
            if port.location not in self.global_mosaic_components_as_uuids:
                self.global_mosaic_components_as_uuids.append(port.location)

        self.global_mosaic_components_as_components: list[components.Component] = []
        #

        for comp in components.Component.component_objects:
            if comp not in self.global_mosaic_components_as_components:
                self.global_mosaic_components_as_components.append(comp)

        assert self.graph is not None

        for comp in self.global_mosaic_components_as_components:
            for port in comp.component_ports:
                assert port is not None

                if (port not in self.global_mosaic_ports) and (
                    port.id in self.graph.nodes()
                ):
                    self.global_outlet_currents.append(port.local_current.id)

        # // Terceiro passo: Setar as pressões das correntes de saída do mosaico = 0 Pa
        # // Quarto passo: Traçar os simple paths que vão desde as portas de entrada até as portas de
        # //saída. (de forma que dois simple paths possam até compartilhar algumas portas, mas nunca
        # // um componente inteiro)

        #! Eu não sei se, quando eu setar a pressão da corrente = 0, cada corrente de saída dentro das
        #!portas de um componente vão ter a sua pressão atualizada

        for cur in current.Current.current_objects:
            for mosaic_cur_id in self.global_outlet_currents:
                if (cur.id == mosaic_cur_id) and (cur.pressure is None):
                    cur.pressure = 0  # * Pa

                    # print(f'\n{cur.pressure = }')

                    # * Todos os passos do loop abaixo são somente para checagem e prevenção de erros
                    # *na setagem da pressão das correntes de saída para pressure = 0
                    for comp in self.global_mosaic_components_as_components:
                        for port in comp.component_ports:
                            assert port is not None

                            if port.local_current.id == cur.id:
                                # print(f'\n{port.local_current.pressure = }')
                                # print(f'\n{cur.pressure = }')

                                assert port.local_current.pressure == cur.pressure

                                # print(f'\n{port.local_current.pressure = }')
                                # print(f'\n{cur.pressure = }')

        # // quarto passo(b): Eu preciso calcular a conservação de massa global do mosaico, e setar as
        # //vazões mássicas das entradas e saídas respeitando essa conservação global.
        # //Eu preciso chutar vazões para as correntes de entrada, e usar esses valores pra chutar as
        # //vazões das correntes de saída.
        # * Eu pensei em falar que cada uma das correntes de saída tem vazão de entrada = 10 Kg/s

        for cur_uuid in self.global_inlet_currents:
            for cur in current.Current.current_objects:
                if (cur.id == cur_uuid) and (cur.mass_flow is None):
                    cur.mass_flow = 10  # * kg/s

                    # print(f'\n{cur.mass_flow = }')

                    # * Todos os passos do loop abaixo são somente para checagem e prevenção de erros
                    # *na setagem da vazão mássica das correntes de entrada mass_flow = 1kg/s
                    for comp in self.global_mosaic_components_as_components:
                        for port in comp.component_ports:
                            assert port is not None

                            if port.local_current.id == cur.id:
                                # print(f'\n{port.local_current.mass_flow = }')
                                # print(f'\n{cur.mass_flow = }')

                                assert port.local_current.mass_flow == cur.mass_flow

                                # print(f'\n{port.local_current.mass_flow = }')
                                # print(f'\n{cur.mass_flow = }')

        # // Quinto passo(a): Setar as vazões de cada corrente seguindo os simple paths encontrados
        # // Quinto passo(b): Na setagem das vazões, calcular valores que estejam de acordo com a
        # //conservação de massa local (em cada um dos componentes).
        #! Somente as correntes que tiverem vazões mássicas = None poderão ter as vazões alteradas

        global_inlet_mass_flow: Union[int, float] = 0

        # print(f'\n{self.global_inlet_currents = }')

        for cur_uuid in self.global_inlet_currents:
            global_inlet_mass_flow += 1

        individual_outlet_mass_flow: Union[int, float] = global_inlet_mass_flow / len(
            self.global_outlet_currents
        )

        # print(f'\n\n{individual_outlet_mass_flow = }')
        # print(f'\n\n{global_inlet_mass_flow = }')

        for cur_uuid in self.global_outlet_currents:
            for cur in current.Current.current_objects:
                if cur.id == cur_uuid:
                    cur.mass_flow = individual_outlet_mass_flow

        assert (
            individual_outlet_mass_flow * len(self.global_outlet_currents)
        ) == global_inlet_mass_flow

        # // Um outro passo: Definir que a corrente local das portas que estão em uma junta com uma
        # //corrente devem ter a velocidade calculada/chutada, já que a vazão mássica e/ou a vazão
        # // volumétrica são 'chutadas' neste método.

        # main_port
        # sidekick_port

        for port in components.Port.port_objects:
            for comp in components.Component.component_objects:
                # // This block skips the root ports
                if (comp.port_quantity != len(comp.component_ports)) and (
                    port == comp.component_ports[-1]
                ):
                    pass

    def symple_q_p_guess(self, volume_flow_guess=5, pressure_guess=200_000) -> None:
        """
        Recreation of the method to set all the pressures, and volume_flows (Q)
        inside each and every current that belongs to the self mosaic
        """

        current_uuid_map: dict[UUID, current.Current] = {
            cur.id: cur for cur in current.Current.current_objects
        }

        port_uuid_map: dict[UUID, components.Port] = {
            port.id: port for port in components.Port.port_objects
        }

        component_uuid_map: dict[UUID, components.Component] = {
            comp.id: comp for comp in components.Component.component_objects
        }

        self.all_orig_currents: list[current.Current] = []

        for joint in self.joints_list:
            for obj in joint:
                if obj in current_uuid_map.keys():
                    # In this case, the obj is an UUID from an original current

                    #! The location of the current must be a tuple with two UUIDS
                    #! It should not be a simple UUID, nor a tuple with just one
                    #! UUID inside
                    assert isinstance(
                        current_uuid_map[obj].location, tuple
                    ) or isinstance(current_uuid_map[obj].location, list)

                    assert len(current_uuid_map[obj].location) == 2

                    print(f"\n{current_uuid_map[obj] = }\n")

                    self.all_orig_currents.append(current_uuid_map[obj])

        # print(f"\n{self.all_orig_currents[0].id}\n")
        # print(f"\n{self.all_orig_currents[0].composition.P = }\n")
        # print(f"\n{self.all_orig_currents[0].pressure = }\n")

        # // Sanity check
        for cur in self.all_orig_currents:
            assert cur.composition.P == cur.pressure
            assert cur.composition.T == cur.temperature

            if len(self.all_orig_currents) > 1:
                for other_cur in self.all_orig_currents:
                    if other_cur != cur:
                        assert cur.composition.P == other_cur.composition.P
                        assert cur.composition.T == other_cur.composition.T
                        assert cur.composition.ID == other_cur.composition.ID

            for comp in components.Component.component_objects:
                if comp.location == self.id:
                    for comp_port in comp.component_ports:
                        # l_cur = comp_port.local_current

                        # assert l_cur.id != cur.id
                        # assert l_cur != cur

                        assert comp_port.local_current.id != cur.id
                        assert comp_port.local_current != cur

        # print(f"\n{self.all_orig_currents[0].id}\n")
        # print(f"\n{self.all_orig_currents[0].composition.P = }\n")
        # print(f"\n{self.all_orig_currents[0].pressure = }\n")

        standard_volume_flow = (
            volume_flow_guess  # 5  # that is the first guess, in m^3 / s
        )
        standard_pressure = pressure_guess  # 200_000  # self.all_orig_currents[0].composition.P  # that is the other guess

        self.standard_pressure = standard_pressure
        self.standard_volume_flow = standard_volume_flow

        assert standard_pressure != 0

        # // Setting the volume_flow and pressure value for all original_currents
        for orig_cur in self.all_orig_currents:
            # // An original current must have the pressure != None or volume_flow != None
            assert not ((orig_cur.pressure == None) and (orig_cur.volume_flow == None))

            if orig_cur.volume_flow == None:
                orig_cur.volume_flow = standard_volume_flow

            elif (orig_cur.pressure == None) and (orig_cur.composition.P == None):
                orig_cur.pressure = standard_pressure
                orig_cur.composition.P = standard_pressure

            elif (orig_cur.pressure == None) or (orig_cur.composition.P == None):
                raise ValueError(
                    "\nBoth pressures should have equal values inside every current"
                )

            elif (
                (orig_cur.pressure == None)
                and (orig_cur.composition.P == None)
                and orig_cur.volume_flow == None
            ):
                raise ValueError(
                    """\nBetween the pressures and the volume flow, at least
                    one of those must be != None"""
                )

        # // Sanity check, checking if cur.composition.P = cur.pressure
        # // and cur.composition.T == cur.temperature
        for in_cur in self.all_orig_currents:
            try:
                assert in_cur.composition.P == in_cur.pressure
                assert in_cur.composition.T == in_cur.temperature
            except:
                print(f"\n{in_cur.id = }")
                print(f"\n{in_cur.location = }")
                print(f"\n{in_cur.composition.ID = }")
                print(f"\n{in_cur.composition.P = }")
                print(f"\n{in_cur.pressure = }")
                print(f"\n{in_cur.composition.T = }")
                print(f"\n{in_cur.temperature = }")

                raise ValueError
        # * if this pressure is = 0, the thermo.chemical raises an error
        # * if the user wants to set this pressure = 0, the pressure should
        # * be slightly different than zero, but not zero, something like 0.1 Pa
        # * or 3 Pa.

        for comp in components.Component.component_objects:
            if comp.location == self.id:
                print(f"\nsymple_q_p_guess: {comp.id = }\n")

                for p in comp.component_ports:
                    # print(f"\nsymple_q_p_guess: {p.id = }\n")
                    # print(f"\nsymple_q_p_guess: {p.local_current.composition.T = }\n")
                    # print(f"\nsymple_q_p_guess: {p.local_current.composition.P = }\n")
                    assert self.all_orig_currents[0].id != p.local_current.id
                    assert self.all_orig_currents[0] is not p.local_current

                    orig_cur_id = str(self.all_orig_currents[0].composition.ID)
                    orig_cur_T = float(self.all_orig_currents[0].composition.T)
                    # * orig_cur_pressure = float(self.all_orig_currents[0].composition.P)

                    # * p.local_current.composition.ID = orig_cur_id
                    # * p.local_current.composition.T = orig_cur_T

                    # print(f"\n{p.id = }")
                    # print(f"\n{p.location = }")
                    # print(f"\n{p.local_current.id = }")
                    # print(f"\n{p.local_current.composition = }")
                    # print(f"\n{p.local_current.composition.ID = }")
                    # print(f"\n{p.local_current.composition.T = }")
                    # print(f"\n{p.local_current.composition.P = }")
                    # print(f"\n{p.local_current.density() = }")

                    p.local_current.composition.ID = orig_cur_id
                    p.local_current.composition.T = orig_cur_T

                    # print(f"\n{p.id = }")
                    # print(f"\n{p.location = }")
                    # print(f"\n{p.local_current.id = }")
                    # print(f"\n{p.local_current.composition = }")
                    # print(f"\n{p.local_current.composition.ID = }")
                    # print(f"\n{p.local_current.composition.T = }")
                    # print(f"\n{p.local_current.composition.P = }")
                    # print(f"\n{p.local_current.density() = }")

                    # p.local_current.composition.P = standard_pressure

                    # * p.local_current.temperature = orig_cur_T
                    # * p.local_current.pressure = standard_pressure

                    p.local_current.temperature = orig_cur_T
                    p.local_current.pressure = standard_pressure
                    p.local_current.composition.P = standard_pressure
                    # p.local_current.pressure = orig_cur_pressure

                    # print(f"\n{p.id = }")
                    # print(f"\n{p.location = }")
                    # print(f"\n{p.local_current.id = }")
                    # print(f"\n{p.local_current.composition = }")
                    # print(f"\n{p.local_current.composition.ID = }")
                    # print(f"\n{p.local_current.composition.T = }")
                    # print(f"\n{p.local_current.composition.P = }")
                    # print(f"\n{p.local_current.density() = }")

                    p.local_current.volume_flow = standard_volume_flow

                    # print(f"\n{p.id = }")
                    # print(f"\n{p.location = }")
                    # print(f"\n{p.local_current.id = }")
                    # print(f"\n{p.local_current.composition = }")
                    # print(f"\n{p.local_current.composition.ID = }")
                    # print(f"\n{p.local_current.composition.T = }")
                    # print(f"\n{p.local_current.composition.P = }")
                    # print(f"\n{p.local_current.density() = }")

                    # print(f"\nsymple_q_p_guess: {p.local_current.composition.T = }\n")
                    # print(f"\nsymple_q_p_guess: {p.local_current.composition.P = }\n")

                    # print(f"\nsymple_q_p_guess: {p.local_current.temperature = }\n")
                    # print(f"\nsymple_q_p_guess: {p.local_current.pressure = }\n")

        # print(f"\n{self.all_orig_currents[0].id}\n")
        # print(f"\n{self.all_orig_currents[0].composition.P = }\n")
        # print(f"\n{self.all_orig_currents[0].pressure = }\n")

    def cycle_analyzer(self) -> None:
        """
        THis method will define the clockwise and anti-clockwise directions inside all the cycles found.
        After this, the method will create a dictionary of all the edges, and if its direction os clockwise or
        anti-clockwise
        """

        def edge_direction_detector(cicle, graph) -> Dict[Tuple[UUID, UUID], int]:
            clock_wise_edges: List[Tuple[UUID, UUID]] = []
            anti_clock_wise_edges: List[Tuple[UUID, UUID]] = []

            edge_directions: Dict[Tuple[UUID, UUID], int] = {}

            # Comparar cada aresta do ciclo com o sentido do ciclo (como ele foi percorrido)
            for i in range(len(cicle)):
                u: UUID = cicle[i]
                v: UUID = cicle[(i + 1) % len(cicle)]  # próximo nó no ciclo

                # Verificar se a aresta está no sentido original ou invertido
                if graph.has_edge(u, v):
                    clock_wise_edges.append((u, v))  # Segue o sentido do ciclo

                    edge_directions[(u, v)] = 1

                elif graph.has_edge(v, u):
                    anti_clock_wise_edges.append((u, v))  # Sentido inverso

                    edge_directions[(u, v)] = -1

            return edge_directions

        self.final_directed_cycles: List[Dict[Tuple[UUID, UUID], int]] = list(
            map(
                lambda cicle: edge_direction_detector(cicle, self.graph),
                self.simple_cycles_as_nodes,
            )
        )

        self.simple_cycles_as_edges: List[List[Tuple[UUID, UUID]]] = []

        edges: List[Tuple[UUID, UUID]] = []

        # print(f'\n\n{ self.final_directed_cycles = }')

        for cycle in self.simple_cycles_as_nodes:
            # Transformar ciclo de nós em ciclo de arestas
            edges = [(cycle[j], cycle[(j + 1) % len(cycle)]) for j in range(len(cycle))]
            self.simple_cycles_as_edges.append(edges)

    @staticmethod
    def equation_comparator(given_eq: sy.Basic, target_eq: sy.Basic) -> bool:
        """
        This method will be used to check if, equation given is already inside the target equation

        In this case, the equation given is the equation from the Component class method, and the
        target equation is the equation that already exists, or is being created inside the equations
        list of the mosaic.

        THis method will compare the variables inside both equations, and see if the target equation
        already has one or more variables of the given equations. if the answer is True, the given
        equation will not be added to the target equation, and the current iteration will be skipped
        . if the answer is False, the given equation will be used inside the target equation, and
        the controol flow will continue normally

        The method returns True, if the further operation of using the given eq to compose the
        Target Equation is allowed.

        The method returns True, if the further operation of using the given eq to compose the
        Target Equation isn't allowed
        """

        given_variables: set = given_eq.free_symbols

        if isinstance(target_eq, int) == True:
            # * In this case, the function returns True, because the single_cicle_eq is only an integer
            # * and it didn't have time to turn into an equation, and in this scenario it is impossible
            # * That the given equation was used in the past iterations to compose the left side of the
            # * single_cicle_equation

            return True

        target_variables: set = target_eq.free_symbols
        for g_var in given_variables:
            for t_var in target_variables:
                if (g_var in target_variables) or (t_var in given_variables):
                    return False
                    # raise ValueError (f'\n\nThe g_var already is inside the t_eq')

        else:
            return True

    def composition_homogenizer(self):
        """
        This method will search for local currents that have a composition that
        is wrong, and make it the correct chemical species and properties (P and T)

        This method should run before the eq_gathering method, so that density errors
        never get to happen inside the energy_conservation_of the components
        """

        cur_uuid_map: dict[UUID, current.Current] = {
            cur.id: cur for cur in current.Current.current_objects
        }

        comp_uuid_map: dict[UUID, components.Component] = {
            comp.id: comp for comp in components.Component.component_objects
        }

        port_uuid_map: dict[UUID, components.Port] = {
            port.id: port for port in components.Port.port_objects
        }

        self.orig_curs_in_self_mosaic: list[Current] = []

        # // This holds the compositions as tuples, and will be used to compare
        # // and count differente compositions.
        # // If the set has 3 different comps, the code must return an error
        self.dif_compositions_inside_self: set[tuple] = {}

        """
        examle:
        
        composition = [id: 'water', T = 303, P = 100_000]
        
        tuple_comp = ('water', 303, 100_000)
        """

        # // Filtering of all the original currents inside the self mosaic
        for j in self.joints_list:
            for obj in j:
                if isinstance(obj, Iterable):
                    raise TypeError(f"Maybe this case shouldnt exist, but im not shure")
                else:
                    if obj in cur_uuid_map.keys():
                        self.dif_compositions_inside_self.add(
                            (
                                cur_uuid_map[obj].composition.ID,
                                cur_uuid_map[obj].composition.T,
                                cur_uuid_map[obj].composition.P,
                                cur_uuid_map[obj].composition,
                            )
                        )

                        self.orig_curs_in_self_mosaic.append(cur_uuid_map[obj])
                        cur_uuid_map[obj]

                    elif obj in comp_uuid_map.keys():
                        ...
                    elif obj in port_uuid_map.keys():
                        ...
                    else:
                        raise ValueError(
                            "\n\nThere should never be a case in witch some UUID from the self.joints_list does not belong into one of those three dict key list"
                        )

        try:
            assert len(self.dif_compositions_inside_self) <= 2
            assert len(self.dif_compositions_inside_self) >= 1
        except:
            raise ValueError

        nc_pure_water_tuple = (
            nc.pure_water.ID,
            nc.pure_water.T,
            nc.pure_water.P,
            nc.pure_water,
        )

        self.generic_orig_self_curs: list[Current] = []

        # // Homogenization of the original currents inside self mosaic
        if len(self.dif_compositions_inside_self) == 2:
            assert nc_pure_water_tuple in self.dif_compositions_inside_self

            a, b = self.dif_compositions_inside_self
            dif_comp = b if nc_pure_water_tuple == a else a

            for orig_cur in self.orig_curs_in_self_mosaic:
                if (
                    (orig_cur.composition.ID == nc.pure_water.ID)
                    and (orig_cur.composition.T == nc.pure_water.T)
                    and (orig_cur.composition.P == nc.pure_water.P)
                ):
                    orig_cur.composition = dif_comp[3]

        if False:
            # // Homogenization of the original currents inside self mosaic
            for o_cur in self.orig_curs_in_self_mosaic:
                for other_o_cur in self.orig_curs_in_self_mosaic:
                    if o_cur.id != other_o_cur.id:
                        #! Será que essa comparação faz mesmo sentido?
                        #! Acho que não, mas não tenho ctz, talvez ela possa levantar uma erro desnecessário
                        # * assert o_cur.composition == other_o_cur.composition

                        assert o_cur.composition.ID == other_o_cur.composition.ID
                        assert o_cur.composition.T == other_o_cur.composition.T
                        assert o_cur.composition.P == other_o_cur.composition.P

                        if o_cur.composition.ID != other_o_cur.composition.ID:
                            # for another_o_cur in self
                            ...
                            if o_cur.composition.ID == other_o_cur.composition.ID:
                                ...

    def equation_gathering_from_graph(self, verify=False) -> None:
        """
        This method will declare the SymPy variables, create the equations based on the graph, and pass all of this equations
        foward to the next method.

        This method should have a try block in the middle of it, to detect if there is the same number of equations and
        unknows. If the equations number is less than the unknowns, this method should raise an error.
        """
        #! for cur in self.all_orig_currents
        #!     self.symple_q_p_guess()

        self.equation_list: list = []

        current_uuid_map: dict[UUID, current.Current] = {
            cur.id: cur for cur in current.Current.current_objects
        }

        port_uuid_map: dict[UUID, components.Port] = {
            port.id: port for port in components.Port.port_objects
        }

        component_uuid_map: dict[UUID, components.Component] = {
            comp.id: comp for comp in components.Component.component_objects
        }

        # mosaic_uuid_map: dict[UUID, Mosaic] = {
        #     mos.id: mos for mos in Mosaic.mosaic_objects
        # }

        # Selecionar todos os nós com a soma de numero de entradas com o saidas > 2

        local_error_message: str = """There is a problem when the component has a root_port,
        because the root_port UUID is being added to the self.equations_list, directly from the
        component method -> component.mass_conservation()
        """
        #! I need to refactorate the mass_conservation, so that if the component has a root_port,
        #! it does not show inside the mass_conservation equation.

        # // First part: Mass conservation inside each Component from the self mosaic
        for joint in self.joints_list:
            for id in joint:
                for port in components.Port.port_objects:
                    if port.id == id:
                        for component in components.Component.component_objects:
                            if (
                                (component.id == port.location)
                                and (
                                    component.mass_conservation()
                                    not in self.equation_list
                                )
                                and (
                                    component.mass_conservation()
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        component.mass_conservation().free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                )
                            ):
                                self.equations_dict[ULID()] = (
                                    component.mass_conservation()
                                )
                                self.equation_list.append(component.mass_conservation())

                            if (
                                (component.id == port.location)
                                and (
                                    component.mass_conservation()
                                    not in self.equation_list
                                )
                                and (
                                    component.mass_conservation()
                                    not in self.equations_dict.values()
                                )
                                and (
                                    any(
                                        component.mass_conservation().free_symbols
                                        == eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                )
                            ):
                                other_eq: sy.Basic | None = None
                                other_eqs: list[sy.Basic] = []

                                for eq in self.equations_dict.values():
                                    if (
                                        eq.free_symbols
                                        == component.mass_conservation().free_symbols
                                    ):
                                        other_eqs = (
                                            other_eqs.remove(None)
                                            if (None in other_eqs)
                                            else other_eqs
                                        )  # type: ignore
                                        other_eqs.append(eq)

                                if len(other_eqs) == 1:
                                    other_eq = other_eqs[0]

                                # print(
                                #     f"\n{(all(item is not None for item in other_eqs)) = }\n"
                                # )

                                # print(
                                #     f"\n{(any(item is None for item in other_eqs)) = }\n"
                                # )

                                # print(f"\n{(other_eq is not None) = }\n")

                                # print(
                                #     f"\n{any(
                                #             component.mass_conservation().free_symbols
                                #             == eq.free_symbols
                                #             for eq in self.equations_dict.values()) = }\n"
                                # )

                                # print(f"\n{other_eq = }\n")

                                assert (
                                    (all(item is not None for item in other_eqs))
                                    or (any(item is not None for item in other_eqs))
                                ) or (other_eq is not None)

                                c_mc_e_var_list = list(
                                    component.mass_conservation().free_symbols
                                )

                                flag = False

                                for eq in other_eqs:
                                    for some_var in c_mc_e_var_list:
                                        solved_c_mc_e = sy.solve(
                                            component.mass_conservation(), some_var
                                        )

                                        solved_eq = sy.solve(eq, some_var)

                                        if (
                                            (eq.lhs in solved_c_mc_e)
                                            or (eq.rhs in solved_c_mc_e)
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    component.mass_conservation().rhs,
                                                )
                                                in solved_c_mc_e
                                            )
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    component.mass_conservation().lhs,
                                                )
                                                in solved_c_mc_e
                                            )
                                            or (
                                                component.mass_conservation().subs(
                                                    some_var, eq.rhs
                                                )
                                                in solved_c_mc_e
                                            )
                                            or (
                                                component.mass_conservation().subs(
                                                    some_var, eq.lhs
                                                )
                                                in solved_c_mc_e
                                            )
                                            or (
                                                component.mass_conservation().lhs
                                                in solved_eq
                                            )
                                            or (
                                                component.mass_conservation().rhs
                                                in solved_eq
                                            )
                                        ):
                                            flag = True

                                    if flag:
                                        break
                                    else:
                                        self.equations_dict[ULID()] = (
                                            component.mass_conservation()
                                        )
                                        self.equation_list.append(
                                            component.mass_conservation()
                                        )

                                NIE_msg: str = """
                                This part needs to have precise verification of the equation comparison,
                                in a way that the equations are also compared algebraically, and not only
                                in an Object perspective
                                """

                                #! raise NotImplementedError(NIE_msg)

                                print(f"\n{component.id = }")
                                print(f"\n{component.mass_conservation() = }\n")

                                #! This equation needs to be revised and checked before it's added
                                #! to the self.equations_list

                                # raise NotImplementedError
                                # self.equations_dict[ULID()] = (
                                #     component.mass_conservation()
                                # )
                                # self.equation_list.append(component.mass_conservation())

                                # raise ValueError(local_error_message)

        # // Second part: Mass and energy Conservation equations for joints
        for joint in self.joints_list:
            for uuid_index, uu_id in enumerate(joint):
                assert len(joint) == 2

                for obj in joint:
                    assert isinstance(obj, UUID)

                first_uuid = joint[0]
                second_uuid = joint[1]

                if (
                    (first_uuid in port_uuid_map)
                    and (second_uuid in port_uuid_map)
                    and (
                        port_uuid_map[first_uuid].location  # type: ignore
                        != port_uuid_map[second_uuid].location  # type: ignore
                    )  # type: ignore
                ):
                    first_port = port_uuid_map[first_uuid]  # type: ignore
                    second_port = port_uuid_map[second_uuid]

                    first_comp = component_uuid_map[first_port.location]
                    second_comp = component_uuid_map[second_port.location]

                    assert first_port is not None
                    assert second_port is not None

                    assert first_comp is not None
                    assert second_comp is not None

                    # // This is the case where the mass conservation equations must be created
                    # // for each joint between ports from two differente components

                    # // I could use this selection to also create the energy conservation equation
                    # // for each joint between ports from different components

                    first_port_id = sy.symbols(str(first_port.id))
                    second_port_id = sy.symbols(str(second_port.id))

                    first_cur_pressure: sy.Symbol = sy.symbols(
                        str(first_port.local_current.pressure_name)
                    )
                    second_cur_pressure: sy.Symbol = sy.symbols(
                        str(second_port.local_current.pressure_name)
                    )

                    pp_joint_mass_cons_eq: sy.Basic = sy.Eq(
                        first_port_id, -second_port_id
                    )

                    pp_joint_energy_cons_eq: sy.Basic = sy.Eq(
                        (
                            (first_cur_pressure)
                            / (first_port.local_current.density() * nc.g)
                        )  # type: ignore
                        + (first_comp.E_constant(first_port.id) * (first_port_id**2)),  # type: ignore
                        (
                            (second_cur_pressure)
                            / (second_port.local_current.density() * nc.g)
                        )  # type: ignore
                        + (
                            second_comp.E_constant(second_port.id) * (second_port_id**2)
                        ),
                    )  # type: ignore

                    if (pp_joint_mass_cons_eq not in self.equations_dict.values()) and (
                        all(
                            pp_joint_mass_cons_eq.free_symbols != eq.free_symbols
                            for eq in self.equations_dict.values()
                        )
                    ):
                        NIE_msg: str = """
                        This part needs to have precise verification of the equation comparison,
                        in a way that the equations are also compared algebraically, and not only
                        in an Object perspective
                        """

                        #! raise NotImplementedError(NIE_msg)

                        self.equations_dict[ULID()] = pp_joint_mass_cons_eq
                        self.equation_list.append(pp_joint_mass_cons_eq)

                    elif (
                        pp_joint_mass_cons_eq not in self.equations_dict.values()
                    ) and (
                        any(
                            pp_joint_mass_cons_eq.free_symbols == eq.free_symbols
                            for eq in self.equations_dict.values()
                        )
                    ):
                        other_eq: sy.Basic | None = None
                        other_eqs: list[sy.Basic] = []

                        for eq in self.equations_dict.values():
                            if eq.free_symbols == pp_joint_mass_cons_eq.free_symbols:
                                other_eqs = (
                                    other_eqs.remove(None)
                                    if (None in other_eqs)
                                    else other_eqs
                                )  # type: ignore
                                other_eqs.append(eq)

                        if len(other_eqs) == 1:
                            other_eq = other_eqs[0]

                        assert (other_eq is not None) or (
                            (all(item is not None for item in other_eqs))
                            or (any(item is not None for item in other_eqs))
                        )

                        pp_j_mc_e_var_list = list(pp_joint_mass_cons_eq.free_symbols)

                        flag = False

                        for eq in other_eqs:
                            for some_var in pp_j_mc_e_var_list:
                                solved_ppjmce = sy.solve(
                                    pp_joint_mass_cons_eq, some_var
                                )

                                solved_eq = sy.solve(eq, some_var)

                                if (
                                    (eq.lhs in solved_ppjmce)
                                    or (eq.rhs in solved_ppjmce)
                                    or (eq.subs(some_var, pp_joint_mass_cons_eq.rhs))
                                    or (eq.subs(some_var, pp_joint_mass_cons_eq.lhs))
                                    or (pp_joint_mass_cons_eq.subs(some_var, eq.rhs))
                                    or (pp_joint_mass_cons_eq.subs(some_var, eq.lhs))
                                    or (pp_joint_mass_cons_eq.lhs in solved_eq)
                                    or (pp_joint_mass_cons_eq.rhs in solved_eq)
                                ):
                                    flag = True

                            if flag:
                                break
                            else:
                                self.equations_dict[ULID()] = pp_joint_mass_cons_eq
                                self.equation_list.append(pp_joint_mass_cons_eq)

                        NIE_msg: str = """
                        This part needs to have precise verification of the equation comparison,
                        in a way that the equations are also compared algebraically, and not only
                        in an Object perspective
                        """

                        #! raise NotImplementedError(NIE_msg)

                    else:
                        # // This part will only be used to know if the equation composed is being
                        # // repeated.
                        # print(f"\n{joint = }\n")
                        # print(f"\n{first_comp.id = }\n")
                        # print(f"\n{second_comp.id = }\n")
                        # raise NotImplementedError
                        pass

                    if (
                        (pp_joint_energy_cons_eq not in self.equations_dict.values())
                        and (
                            all(
                                pp_joint_energy_cons_eq.free_symbols != eq.free_symbols
                                for eq in self.equations_dict.values()
                            )
                        )
                    ) and (all):
                        NIE_msg: str = """
                        This part needs to have precise verification of the equation comparison,
                        in a way that the equations are also compared algebraically, and not only
                        in an Object perspective
                        """

                        #! raise NotImplementedError(NIE_msg)

                        self.equations_dict[ULID()] = pp_joint_energy_cons_eq
                        self.equation_list.append(pp_joint_energy_cons_eq)

                    elif (
                        pp_joint_energy_cons_eq not in self.equations_dict.values()
                    ) and (
                        any(
                            pp_joint_energy_cons_eq.free_symbols == eq.free_symbols
                            for eq in self.equations_dict.values()
                        )
                    ):
                        other_eq: sy.Basic | None = None
                        other_eqs: list[sy.Basic] = []

                        for eq in self.equations_dict.values():
                            if eq.free_symbols == pp_joint_energy_cons_eq.free_symbols:
                                other_eqs = (
                                    other_eqs.remove(None)
                                    if (None in other_eqs)
                                    else other_eqs
                                )  # type: ignore
                                other_eqs.append(eq)

                        if len(other_eqs) == 1:
                            other_eq = other_eqs[0]

                        assert (other_eq is not None) or (
                            (all(item is not None for item in other_eqs))
                            or (any(item is not None for item in other_eqs))
                        )

                        pp_j_ec_e_var_list = list(pp_joint_energy_cons_eq.free_symbols)

                        flag = False

                        for eq in other_eqs:
                            for some_var in pp_j_ec_e_var_list:
                                solved_ppjece = sy.solve(
                                    pp_joint_energy_cons_eq, some_var
                                )

                                solved_eq = sy.solve(eq, some_var)

                                if (
                                    (eq.lhs in solved_ppjece)
                                    or (eq.rhs in solved_ppjece)
                                    or (
                                        eq.subs(some_var, pp_joint_energy_cons_eq.rhs)
                                        in solved_ppjece
                                    )
                                    or (
                                        eq.subs(some_var, pp_joint_energy_cons_eq.lhs)
                                        in solved_ppjece
                                    )
                                    or (
                                        pp_joint_energy_cons_eq.subs(some_var, eq.rhs)
                                        in solved_eq
                                    )
                                    or (
                                        pp_joint_energy_cons_eq.subs(some_var, eq.lhs)
                                        in solved_eq
                                    )
                                    or (pp_joint_energy_cons_eq.lhs in solved_eq)
                                    or (pp_joint_energy_cons_eq.rhs in solved_eq)
                                ):
                                    flag = True

                            if flag:
                                break
                            else:
                                self.equations_dict[ULID()] = pp_joint_energy_cons_eq
                                self.equation_list.append(pp_joint_energy_cons_eq)

                        NIE_msg: str = """
                        This part needs to have precise verification of the equation comparison,
                        in a way that the equations are also compared algebraically, and not only
                        in an Object perspective
                        """

                        #! raise NotImplementedError(NIE_msg)

                    else:
                        # // THis part will only be used to know if the equation composed is being
                        # // repeted.
                        # print(f"\n{joint = }\n")
                        # print(f"\n{first_comp.id = }\n")
                        # print(f"\n{second_comp.id = }\n")
                        # raise NotImplementedError

                        pass

                # // This is the case where there is a joint between a current and a port
                # // The mass conservation eq and the energy conservation eq must be created here
                if (first_uuid in current_uuid_map) or (
                    second_uuid in current_uuid_map
                ):
                    cur: current.Current | None = None
                    port: components.Port | None = None
                    comp: components.Component | None = None

                    if first_uuid in current_uuid_map:
                        cur = current_uuid_map[first_uuid]
                        port = port_uuid_map[second_uuid]

                    if second_uuid in current_uuid_map:
                        cur = current_uuid_map[second_uuid]
                        port = port_uuid_map[first_uuid]

                    comp = component_uuid_map[port.location]

                    assert cur is not None
                    assert port is not None
                    assert comp is not None

                    cur_volume_flow: sy.Symbol = sy.symbols(str(cur.id))
                    cur_pressure: sy.Symbol = sy.symbols(str(cur.pressure_name))
                    port_id: sy.Symbol = sy.symbols(str(port.id))
                    port_pressure: sy.Symbol = sy.symbols(
                        str(port.local_current.pressure_name)
                    )

                    cp_joint_mass_cons_eq: sy.Basic = sy.Eq(cur_volume_flow, port_id)

                    # // This part is temporarely deactivated because the pressures were a little bit
                    # // off
                    # cp_joint_energy_cons_eq: sy.Basic = sy.Eq(
                    #     (cur_pressure) / (cur.density() * nc.g),  # type: ignore
                    #     ((port_pressure) / (port.local_current.density() * nc.g)),  # type: ignore
                    # )

                    # // This part is being used instead of the one above, for numerical precision
                    cp_joint_energy_cons_eq: sy.Basic = sy.Eq(
                        (cur_pressure),  # type: ignore
                        (port_pressure),
                    )

                    if (
                        (cp_joint_mass_cons_eq not in self.equations_dict.values())
                        and (
                            all(
                                cp_joint_mass_cons_eq.free_symbols != eq.free_symbols
                                for eq in self.equations_dict.values()
                            )
                        )
                    ) and (all):
                        NIE_msg: str = """
                        This part needs to have precise verification of the equation comparison,
                        in a way that the equations are also compared algebraically, and not only
                        in an Object perspective
                        """

                        #! raise NotImplementedError(NIE_msg)

                        self.equations_dict[ULID()] = cp_joint_mass_cons_eq
                        self.equation_list.append(cp_joint_mass_cons_eq)

                    elif (
                        cp_joint_mass_cons_eq not in self.equations_dict.values()
                    ) and (
                        all(
                            cp_joint_mass_cons_eq.free_symbols != eq.free_symbols
                            for eq in self.equations_dict.values()
                        )
                    ):
                        other_eq: sy.Basic | None = None
                        other_eqs: list[sy.Basic] = []

                        for eq in self.equations_dict.values():
                            if eq.free_symbols == cp_joint_mass_cons_eq.free_symbols:
                                other_eqs = (
                                    other_eqs.remove(None)
                                    if (None in other_eqs)
                                    else other_eqs
                                )  # type: ignore
                                other_eqs.append(eq)

                        if len(other_eqs) == 1:
                            other_eq = other_eqs[0]

                        assert (other_eq is not None) or (
                            (all(item is not None for item in other_eqs))
                            or (any(item is not None for item in other_eqs))
                        )

                        cp_j_mc_e_var_list = list(cp_joint_mass_cons_eq.free_symbols)

                        flag = False

                        for eq in other_eqs:
                            for some_var in cp_j_mc_e_var_list:
                                solved_cpjmce = sy.solve(
                                    cp_joint_mass_cons_eq, some_var
                                )

                                solved_eq = sy.solve(eq, some_var)

                                if (
                                    (eq.lhs in solved_cpjmce)
                                    or (eq.rhs in solved_cpjmce)
                                    or (
                                        eq.subs(some_var, cp_joint_mass_cons_eq.rhs)
                                        in solved_cpjmce
                                    )
                                    or (
                                        eq.subs(some_var, cp_joint_mass_cons_eq.lhs)
                                        in solved_cpjmce
                                    )
                                    or (
                                        cp_joint_mass_cons_eq.subs(some_var, eq.rhs)
                                        in solved_cpjmce
                                    )
                                    or (
                                        cp_joint_mass_cons_eq.subs(some_var, eq.lhs)
                                        in solved_cpjmce
                                    )
                                    or (cp_joint_mass_cons_eq.lhs in solved_eq)
                                    or (cp_joint_mass_cons_eq.rhs in solved_eq)
                                ):
                                    flag = True

                            if flag:
                                break
                            else:
                                self.equations_dict[ULID()] = cp_joint_mass_cons_eq
                                self.equation_list.append(cp_joint_mass_cons_eq)

                        NIE_msg: str = """
                        This part needs to have precise verification of the equation comparison,
                        in a way that the equations are also compared algebraically, and not only
                        in an Object perspective
                        """

                        #! raise NotImplementedError(NIE_msg)

                    else:
                        # // THis part will only be used to know if the equation composed is being
                        # // repeted.
                        # print(f"\n{joint = }\n")
                        # print(f"\n{cur.id = }\n")
                        # print(f"\n{port.id = }\n")
                        # raise NotImplementedError
                        pass

                    if (
                        (cp_joint_energy_cons_eq not in self.equations_dict.values())
                        and (
                            all(
                                cp_joint_energy_cons_eq.free_symbols != eq.free_symbols
                                for eq in self.equations_dict.values()
                            )
                        )
                    ) and (all):
                        NIE_msg: str = """
                        This part needs to have precise verification of the equation comparison,
                        in a way that the equations are also compared algebraically, and not only
                        in an Object perspective
                        """

                        #! raise NotImplementedError(NIE_msg)

                        self.equations_dict[ULID()] = cp_joint_energy_cons_eq
                        self.equation_list.append(cp_joint_energy_cons_eq)

                    elif (
                        cp_joint_energy_cons_eq not in self.equations_dict.values()
                    ) and (
                        all(
                            cp_joint_energy_cons_eq.free_symbols != eq.free_symbols
                            for eq in self.equations_dict.values()
                        )
                    ):
                        other_eq: sy.Basic | None = None
                        other_eqs: list[sy.Basic] = []

                        for eq in self.equations_dict.values():
                            if eq.free_symbols == cp_joint_energy_cons_eq.free_symbols:
                                other_eqs = (
                                    other_eqs.remove(None)
                                    if (None in other_eqs)
                                    else other_eqs
                                )  # type: ignore
                                other_eqs.append(eq)

                        if len(other_eqs) == 1:
                            other_eq = other_eqs[0]

                        assert (other_eq is not None) or (
                            (all(item is not None for item in other_eqs))
                            or (any(item is not None for item in other_eqs))
                        )

                        cp_j_ec_e_var_list = list(cp_joint_energy_cons_eq.free_symbols)

                        flag = False

                        for eq in other_eqs:
                            for some_var in cp_j_ec_e_var_list:
                                solved_cpjece = sy.solve(
                                    cp_joint_energy_cons_eq, some_var
                                )

                                solved_eq = sy.solve(eq, some_var)

                                if (
                                    (eq.lhs in solved_cpjece)
                                    or (eq.rhs in solved_cpjece)
                                    or (
                                        eq.subs(some_var, cp_joint_energy_cons_eq.rhs)
                                        in solved_cpjece
                                    )
                                    or (
                                        eq.subs(some_var, cp_joint_energy_cons_eq.lhs)
                                        in solved_cpjece
                                    )
                                    or (
                                        cp_joint_energy_cons_eq.subs(some_var, eq.rhs)
                                        in solved_cpjece
                                    )
                                    or (
                                        cp_joint_energy_cons_eq.subs(some_var, eq.lhs)
                                        in solved_cpjece
                                    )
                                    or (cp_joint_energy_cons_eq.lhs in solved_eq)
                                    or (cp_joint_energy_cons_eq.rhs in solved_eq)
                                ):
                                    flag = True

                            if flag:
                                break
                            else:
                                self.equations_dict[ULID()] = cp_joint_energy_cons_eq
                                self.equation_list.append(cp_joint_energy_cons_eq)

                        NIE_msg: str = """
                        This part needs to have precise verification of the equation comparison,
                        in a way that the equations are also compared algebraically, and not only
                        in an Object perspective
                        """

                        #! raise NotImplementedError(NIE_msg)

                    else:
                        # // THis part will only be used to know if the equation composed is being
                        # // repeted.
                        # print(f"\n{joint = }\n")
                        # print(f"\n{cur.id = }\n")
                        # print(f"\n{port.id = }\n")

                        pass
                        # raise NotImplementedError

                # if ((uu_id in port_uuid_map)\
                #     and (isinstance(uu_id, UUID))\
                #     and (uu_id != joint[-1])):

                # if ((uu_id in port_uuid_map)\
                #     and (isinstance(uu_id, UUID))\
                #     and (uu_id == joint[-1])):

        # // The second part is calling the energy conservation equation for each and every component
        # // from the self.mosaic

        assert self.graph is not None

        # // These ports have joints (or the ports themselves store the currents inside its
        # //local_current list) with original root or leaf currents
        # // Only the root currents show up inside the joints list
        # // All leaf currents does not show up in any joint inside the joints list

        inlet_original_ports: list = []

        outlet_ports: list = []

        original_inlet_currents: list = []

        # // Third part: Energy conservation equations inside each edge inside a Component

        for edge_index, edge in enumerate(self.graph.to_undirected().edges):
            for some_id_index, some_id in enumerate(edge):
                other_id: UUID | None = None

                assert len(edge) == 2

                for edge_id in edge:
                    if edge_id != some_id:
                        other_id = edge_id

                assert other_id is not None

                if (some_id not in port_uuid_map.keys()) or (
                    other_id not in port_uuid_map.keys()
                ):
                    continue

                for some_component in components.Component.component_objects:
                    if (
                        (some_component.location == self.id)
                        and (port_uuid_map[some_id] in some_component.component_ports)
                        and (port_uuid_map[other_id] in some_component.component_ports)
                        and (port_uuid_map[some_id].location == some_component.id)
                        and (port_uuid_map[other_id].location == some_component.id)
                    ):
                        print(f"\n{len(self.equation_list) = }\n")

                        if len(self.equation_list) <= len(self.all_eq_variables):
                            print(f"\n{len(self.equation_list) = }")
                            print(f"\n{self.equation_list = }")

                            print(f"\n{len(self.all_eq_variables) = }")
                            print(f"\n{self.all_eq_variables = }")

                            raise ValueError
                        # print(f"\n + {some_id = }\n")
                        # print(f"\n + {other_id = }\n")

                        # print(f"\n * {port_uuid_map[some_id]= }\n")
                        # print(f"\n * {port_uuid_map[some_id]= }\n")

                        if (
                            isinstance(some_component, components.MajorLossComponent)
                        ) or (
                            isinstance(
                                some_component, components.MechanicalPowerInputComponent
                            )
                        ):
                            if (
                                (
                                    some_component.energy_conservation(some_id)
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(some_id)
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            some_id
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                )
                                and (
                                    port_uuid_map[some_id].location == some_component.id
                                )
                                and (
                                    port_uuid_map[other_id].location
                                    == some_component.id
                                )
                            ):
                                self.equations_dict[ULID()] = (
                                    some_component.energy_conservation(some_id)
                                )
                                self.equation_list.append(
                                    some_component.energy_conservation(some_id)
                                )

                                continue

                            elif (
                                (some_component.id == port.location)
                                and (
                                    some_component.energy_conservation(some_id)
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(some_id)
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            some_id
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                    # any(
                                    #     some_component.energy_conservation(
                                    #         some_id
                                    #     ).free_symbols
                                    #     == eq.free_symbols
                                    #     for eq in self.equations_dict.values()
                                    # )
                                )
                                and (
                                    port_uuid_map[some_id].location == some_component.id
                                )
                                and (
                                    port_uuid_map[other_id].location
                                    == some_component.id
                                )
                            ):
                                other_eq: sy.Basic | None = None
                                other_eqs: list[sy.Basic] = []

                                for eq in self.equations_dict.values():
                                    if (
                                        eq.free_symbols
                                        == some_component.energy_conservation(
                                            some_id
                                        ).free_symbols
                                    ):
                                        other_eqs = (
                                            other_eqs.remove(None)
                                            if (None in other_eqs)
                                            else other_eqs
                                        )  # type: ignore
                                        other_eqs.append(eq)

                                if len(other_eqs) == 1:
                                    other_eq = other_eqs[0]

                                # print(
                                #     f"\n{(all(item is not None for item in other_eqs)) = }\n"
                                # )

                                # print(
                                #     f"\n{(any(item is not None for item in other_eqs)) = }\n"
                                # )

                                # print(f"\n{(other_eq is not None) = }\n")

                                # print(
                                #     f"\n{any(
                                #             some_component.energy_conservation(some_id).free_symbols
                                #             == eq.free_symbols
                                #             for eq in self.equations_dict.values()) = }\n"
                                # )

                                # print(f"\n{other_eq = }\n")

                                assert (
                                    (all(item is not None for item in other_eqs))
                                    or (any(item is not None for item in other_eqs))
                                ) or (other_eq is not None)

                                c_ec_e_var_list = list(
                                    some_component.energy_conservation(
                                        some_id
                                    ).free_symbols
                                )

                                flag = False

                                for eq in other_eqs:
                                    for some_var in c_ec_e_var_list:
                                        solved_c_ec_e = sy.solve(
                                            some_component.energy_conservation(some_id),
                                            some_var,
                                        )

                                        solved_eq = sy.solve(eq, some_var)

                                        if (
                                            (eq.lhs in solved_c_ec_e)
                                            or (eq.rhs in solved_c_ec_e)
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    some_component.energy_conservation(
                                                        some_id
                                                    ).rhs,
                                                )
                                                in solved_c_ec_e
                                            )
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    some_component.energy_conservation(
                                                        some_id
                                                    ).lhs,
                                                )
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    some_id
                                                ).subs(some_var, eq.rhs)
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    some_id
                                                ).subs(some_var, eq.lhs)
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    some_id
                                                ).lhs
                                                in solved_eq
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    some_id
                                                ).rhs
                                                in solved_eq
                                            )
                                        ):
                                            flag = True

                                    if flag:
                                        break
                                    else:
                                        self.equations_dict[ULID()] = (
                                            some_component.energy_conservation(some_id)
                                        )
                                        self.equation_list.append(
                                            some_component.energy_conservation(some_id)
                                        )

                                NIE_msg: str = """
                                This part needs to have precise verification of the equation comparison,
                                in a way that the equations are also compared algebraically, and not only
                                in an Object perspective
                                """

                                #! raise NotImplementedError(NIE_msg)

                                print(f"\n{some_component.id = }")
                                print(
                                    f"\n{some_component.energy_conservation(some_id) = }\n"
                                )

                                #! This equation needs to be revised and checked before it's added
                                #! to the self.equations_list

                                # raise NotImplementedError
                                self.equations_dict[ULID()] = (
                                    some_component.energy_conservation(some_id)
                                )
                                self.equation_list.append(
                                    some_component.energy_conservation(some_id)
                                )

                                continue

                            elif (
                                port_uuid_map[some_id].location != some_component.id
                            ) and (
                                port_uuid_map[other_id].location != some_component.id
                            ):
                                raise ValueError("""The some_id and other_id must be inside
                                        the some_component.component_ports list, but they are not""")
                                # raise ValueError(NIE_msg)

                        #!Só falta eu codar essa parte seguindo o
                        #! exemplo do codigo acima, na parte do MajorLossComponent

                        elif (
                            (isinstance(some_component, components.MinorLossComponent))
                            and (
                                some_component.port_quantity
                                != len(some_component.component_ports)
                            )
                            and (isinstance(some_component, components.T_connector))
                        ):
                            another_port_id: UUID | None = None

                            chosen_edge: tuple[UUID, UUID] | None = None

                            if some_id == some_component.component_ports[-1].id:
                                for a_port in some_component.component_ports:
                                    if (
                                        (a_port.id != some_id)
                                        # and (
                                        #     a_port.id
                                        #     != some_component.component_ports[-1]
                                        # )
                                        and (a_port.id != other_id)
                                        and (another_port_id == None)
                                        and (chosen_edge == None)
                                    ):
                                        another_port_id = a_port.id
                                        chosen_edge = (other_id, another_port_id)

                            elif other_id == some_component.component_ports[-1].id:
                                for a_port in some_component.component_ports:
                                    if (
                                        (a_port.id != other_id)
                                        # and (
                                        #     a_port.id
                                        #     != some_component.component_ports[-1]
                                        # )
                                        and (a_port.id != some_id)
                                        and (another_port_id == None)
                                        and (chosen_edge == None)
                                    ):
                                        another_port_id = a_port.id
                                        chosen_edge = (some_id, another_port_id)

                            elif (
                                some_id != some_component.component_ports[-1].id
                            ) and (other_id != some_component.component_ports[-1].id):
                                wrong_edge_error: str = """
                                It should be impossible that the graph has an
                                edge where the root port from the T_connector
                                is not inside. All the edges inside the T_connector
                                should allways contain its root_port.
                                
                                This problem indicates that the graph may
                                have an error
                                """

                                raise ConduitForgeError(f"{wrong_edge_error}")

                            try:
                                assert another_port_id is not None
                                assert chosen_edge is not None
                            except:
                                print(f"\n-----> {chosen_edge = }")
                                print(f"\n-----> {another_port_id = }")
                                if other_id == some_component.component_ports[-1].id:
                                    for a_port in some_component.component_ports:
                                        if (
                                            (a_port.id != other_id)
                                            and (
                                                a_port.id
                                                != some_component.component_ports[-1]
                                            )
                                            and (a_port.id != some_id)
                                            and (another_port_id == None)
                                            and (chosen_edge == None)
                                        ):
                                            another_port_id = a_port.id
                                            chosen_edge = (some_id, another_port_id)

                                            print(f"\n{another_port_id = }")
                                            print(f"\n{chosen_edge = }")

                                print(f"\n{(another_port_id is not None) = }")
                                print(
                                    f"\n{(print(f"\n{(chosen_edge is not None) = }\n"))}"
                                )
                                print(f"\n{some_component.id = }")
                                print(f"\n{some_id = }")
                                print(f"\n{other_id = }")

                                print(
                                    f"\n{(port_uuid_map[some_id].location == some_component.id) = }"
                                )
                                print(
                                    f"\n{(port_uuid_map[other_id].location == some_component.id) = }"
                                )

                                print(
                                    f"\n{(port_uuid_map[some_id].id == some_component.component_ports[-1].id) = }"
                                )

                                print(
                                    f"\n{(port_uuid_map[other_id].id == some_component.component_ports[-1].id) = }"
                                )

                                raise AssertionError
                            inverse_chosen_edge = (chosen_edge[1], chosen_edge[0])

                            if (
                                (
                                    (some_id != some_component.component_ports[-1].id)
                                    or (
                                        other_id
                                        != some_component.component_ports[-1].id
                                    )
                                )
                                and (
                                    some_component.energy_conservation(chosen_edge)
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(chosen_edge)
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            chosen_edge
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                )
                                and (
                                    some_component.energy_conservation(
                                        inverse_chosen_edge
                                    )
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(
                                        inverse_chosen_edge
                                    )
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            inverse_chosen_edge
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                )
                                and (
                                    port_uuid_map[some_id].location == some_component.id
                                )
                                and (
                                    port_uuid_map[other_id].location
                                    == some_component.id
                                )
                            ):
                                self.equations_dict[ULID()] = (
                                    some_component.energy_conservation(chosen_edge)
                                )
                                self.equation_list.append(
                                    some_component.energy_conservation(chosen_edge)
                                )
                                continue

                                # // This part is just a sanity check, and is used just to collect
                                # // abnormal behaviour inside the livrary
                                """
                                # if (
                                #     (other_id in port_uuid_map.keys())
                                #     and (
                                #         port_uuid_map[other_id].location
                                #         == port_uuid_map[some_id].location
                                #     )
                                #     and (
                                #         port_uuid_map[some_id].location == some_component.id
                                #     )
                                #     and (
                                #         port_uuid_map[other_id].location
                                #         == some_component.id
                                #     )
                                # ):
                                #     for port in some_component.component_ports:
                                #         if (port.id != some_id) and (port != other_id):
                                #             raise ConduitForgeError(There should be impossible
                                #                 that some component with two ports has a port
                                #                 that is not some_port neither other_port)
                                """
                                """"""

                            elif (
                                (
                                    (some_id != some_component.component_ports[-1].id)
                                    or (
                                        other_id
                                        != some_component.component_ports[-1].id
                                    )
                                )
                                and (some_component.id == port.location)
                                and (
                                    some_component.energy_conservation(chosen_edge)
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(chosen_edge)
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            chosen_edge
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                    # any(
                                    #     some_component.energy_conservation(
                                    #         (some_id, other_id)
                                    #     ).free_symbols
                                    #     == eq.free_symbols
                                    #     for eq in self.equations_dict.values()
                                    # )
                                )
                                and (
                                    some_component.energy_conservation(
                                        inverse_chosen_edge
                                    )
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(
                                        inverse_chosen_edge
                                    )
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            inverse_chosen_edge
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                    # any(
                                    #     some_component.energy_conservation(
                                    #         (some_id, other_id)
                                    #     ).free_symbols
                                    #     == eq.free_symbols
                                    #     for eq in self.equations_dict.values()
                                    # )
                                )
                                and (
                                    port_uuid_map[some_id].location == some_component.id
                                )
                                and (
                                    port_uuid_map[other_id].location
                                    == some_component.id
                                )
                                and (
                                    port_uuid_map[some_id]
                                    in some_component.component_ports
                                )
                                and (
                                    port_uuid_map[other_id]
                                    in some_component.component_ports
                                )
                            ):
                                other_eq: sy.Basic | None = None
                                other_eqs: list[sy.Basic] = []

                                # // In both cases below, the equation must be
                                # // created with another port_node from some_comp
                                # // that are not inside the eq_list and eqs_dict
                                # // and said node can't be the roor node from the

                                for eq in self.equations_dict.values():
                                    if (
                                        eq.free_symbols
                                        == some_component.energy_conservation(
                                            chosen_edge
                                        ).free_symbols
                                    ) or (
                                        eq.free_symbols
                                        == some_component.energy_conservation(
                                            chosen_edge
                                        ).free_symbols
                                    ):
                                        # print(f"\n{other_eqs = }\n")

                                        other_eqs.append(eq)

                                        # print(f"\n{other_eqs = }\n")

                                        # for obj in other_eqs:
                                        #     if obj is None:
                                        #         other_eqs.remove(None)

                                        other_eqs = [
                                            obj for obj in other_eqs if obj is not None
                                        ]  # type: ignore

                                        # print(f"\n{other_eqs = }\n")

                                if len(other_eqs) == 1:
                                    other_eq = other_eqs[0]

                                # print(
                                #     f"\n{(all(item is not None for item in other_eqs)) = }\n"
                                # )

                                # print(
                                #     f"\n{(any(item is not None for item in other_eqs)) = }\n"
                                # )

                                # print(f"\n{(other_eq is not None) = }\n")

                                # print(
                                #     f"\n{any(
                                #             some_component.energy_conservation(
                                #                 (some_id, other_id)).free_symbols
                                #             == eq.free_symbols
                                #             for eq in self.equations_dict.values()) = }\n"
                                # )

                                # print(f"\n{other_eq = }\n")

                                assert (
                                    (all(item is not None for item in other_eqs))
                                    or (any(item is not None for item in other_eqs))
                                ) or (other_eq is not None)

                                c_ec_e_var_list = list(
                                    some_component.energy_conservation(
                                        chosen_edge
                                    ).free_symbols
                                )

                                i_c_ec_e_var_list = list(
                                    some_component.energy_conservation(
                                        inverse_chosen_edge
                                    ).free_symbols
                                )

                                flag = False

                                for eq in other_eqs:
                                    for some_var in c_ec_e_var_list:
                                        solved_c_ec_e = sy.solve(
                                            some_component.energy_conservation(
                                                chosen_edge
                                            ),
                                            some_var,
                                        )

                                        solved_eq = sy.solve(eq, some_var)

                                        if (
                                            (eq.lhs in solved_c_ec_e)
                                            or (eq.rhs in solved_c_ec_e)
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    some_component.energy_conservation(
                                                        chosen_edge
                                                    ).rhs,
                                                )
                                                in solved_c_ec_e
                                            )
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    some_component.energy_conservation(
                                                        chosen_edge
                                                    ).lhs,
                                                )
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    chosen_edge
                                                ).subs(some_var, eq.rhs)
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    chosen_edge
                                                ).subs(some_var, eq.lhs)
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    chosen_edge
                                                ).lhs
                                                in solved_eq
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    chosen_edge
                                                ).rhs
                                                in solved_eq
                                            )
                                        ):
                                            flag = True

                                    if flag:
                                        break
                                    else:
                                        self.equations_dict[ULID()] = (
                                            some_component.energy_conservation(
                                                chosen_edge
                                            )
                                        )
                                        self.equation_list.append(
                                            some_component.energy_conservation(
                                                chosen_edge
                                            )
                                        )

                                flag = False
                                for eq in other_eqs:
                                    for some_var in i_c_ec_e_var_list:
                                        i_solved_c_ec_e = sy.solve(
                                            some_component.energy_conservation(
                                                inverse_chosen_edge
                                            ),
                                            some_var,
                                        )

                                        solved_eq = sy.solve(eq, some_var)

                                        if (
                                            (eq.lhs in solved_c_ec_e)
                                            or (eq.rhs in solved_c_ec_e)
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    some_component.energy_conservation(
                                                        inverse_chosen_edge
                                                    ).rhs,
                                                )
                                                in solved_c_ec_e
                                            )
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    some_component.energy_conservation(
                                                        inverse_chosen_edge
                                                    ).lhs,
                                                )
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    inverse_chosen_edge
                                                ).subs(some_var, eq.rhs)
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    inverse_chosen_edge
                                                ).subs(some_var, eq.lhs)
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    inverse_chosen_edge
                                                ).lhs
                                                in solved_eq
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    inverse_chosen_edge
                                                ).rhs
                                                in solved_eq
                                            )
                                        ):
                                            flag = True

                                    if flag:
                                        break
                                    else:
                                        self.equations_dict[ULID()] = (
                                            some_component.energy_conservation(
                                                chosen_edge
                                            )
                                        )
                                        self.equation_list.append(
                                            some_component.energy_conservation(
                                                chosen_edge
                                            )
                                        )
                                if (
                                    (
                                        port_uuid_map[some_id].location
                                        != some_component.id
                                    )
                                    or (
                                        port_uuid_map[other_id].location
                                        != some_component.id
                                    )
                                ) or (
                                    (
                                        port_uuid_map[some_id].location
                                        != some_component.id
                                    )
                                    and (
                                        port_uuid_map[other_id].location
                                        != some_component.id
                                    )
                                ):
                                    raise ValueError("""The some_id and other_id must be inside
                                        the some_component.component_ports list, but they are not""")

                                NIE_msg: str = """
                                This part needs to have precise verification of the equation comparison,
                                in a way that the equations are also compared algebraically, and not only
                                in an Object perspective
                                """

                                #! raise NotImplementedError(NIE_msg)

                                # print(f"\n{some_component.id = }")
                                # print(
                                #     f"\n{some_component.energy_conservation((some_id, other_id)) = }\n"
                                # )

                                #! This equation needs to be revised and checked before it's added
                                #! to the self.equations_list

                                # # raise NotImplementedError
                                # self.equations_dict[ULID()] = (
                                #     component.energy_conservation((some_id, other_id))
                                # )
                                # self.equation_list.append(
                                #     component.energy_conservation((some_id, other_id))
                                # )

                                # raise ValueError(local_error_message)

                        elif isinstance(
                            some_component, components.MinorLossComponent
                        ) and (
                            some_component.port_quantity
                            == len(some_component.component_ports)
                        ):
                            if (
                                (
                                    some_component.energy_conservation(
                                        (some_id, other_id)
                                    )
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(
                                        (some_id, other_id)
                                    )
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            (some_id, other_id)
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                )
                                and (
                                    some_component.energy_conservation(
                                        (other_id, some_id)
                                    )
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(
                                        (other_id, some_id)
                                    )
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            (other_id, some_id)
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                )
                                and (
                                    port_uuid_map[some_id].location == some_component.id
                                )
                                and (
                                    port_uuid_map[other_id].location
                                    == some_component.id
                                )
                            ):
                                self.equations_dict[ULID()] = (
                                    some_component.energy_conservation(
                                        (some_id, other_id)
                                    )
                                )
                                self.equation_list.append(
                                    some_component.energy_conservation(
                                        (some_id, other_id)
                                    )
                                )
                                continue

                                # #// This part is just a sanity check, and is used just to collect
                                # #// abnormal behaviour inside the livrary
                                """
                                # if (
                                #     (other_id in port_uuid_map.keys())
                                #     and (
                                #         port_uuid_map[other_id].location
                                #         == port_uuid_map[some_id].location
                                #     )
                                #     and (
                                #         port_uuid_map[some_id].location == some_component.id
                                #     )
                                #     and (
                                #         port_uuid_map[other_id].location
                                #         == some_component.id
                                #     )
                                # ):
                                #     for port in some_component.component_ports:
                                #         if (port.id != some_id) and (port != other_id):
                                #             raise ConduitForgeError(There should be impossible
                                #                 that some component with two ports has a port
                                #                 that is not some_port neither other_port)
                                """

                            elif (
                                (
                                    (some_id != some_component.component_ports[-1].id)
                                    or (
                                        other_id
                                        != some_component.component_ports[-1].id
                                    )
                                )
                                # and (some_component.id == port.location)
                                and (
                                    some_component.energy_conservation(
                                        (some_id, other_id)
                                    )
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(
                                        (some_id, other_id)
                                    )
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            (some_id, other_id)
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                    # any(
                                    #     some_component.energy_conservation(
                                    #         (some_id, other_id)
                                    #     ).free_symbols
                                    #     == eq.free_symbols
                                    #     for eq in self.equations_dict.values()
                                    # )
                                )
                                and (
                                    some_component.energy_conservation(
                                        (other_id, some_id)
                                    )
                                    not in self.equation_list
                                )
                                and (
                                    some_component.energy_conservation(
                                        (other_id, some_id)
                                    )
                                    not in self.equations_dict.values()
                                )
                                and (
                                    all(
                                        some_component.energy_conservation(
                                            (other_id, some_id)
                                        ).free_symbols
                                        != eq.free_symbols
                                        for eq in self.equations_dict.values()
                                    )
                                    # any(
                                    #     some_component.energy_conservation(
                                    #         (some_id, other_id)
                                    #     ).free_symbols
                                    #     == eq.free_symbols
                                    #     for eq in self.equations_dict.values()
                                    # )
                                )
                                and (
                                    port_uuid_map[some_id].location == some_component.id
                                )
                                and (
                                    port_uuid_map[other_id].location
                                    == some_component.id
                                )
                                and (
                                    port_uuid_map[some_id]
                                    in some_component.component_ports
                                )
                                and (
                                    port_uuid_map[other_id]
                                    in some_component.component_ports
                                )
                            ):
                                other_eq: sy.Basic | None = None
                                other_eqs: list[sy.Basic] = []

                                for eq in self.equations_dict.values():
                                    if (
                                        eq.free_symbols
                                        == some_component.energy_conservation(
                                            (some_id, other_id)
                                        ).free_symbols
                                    ):
                                        # print(f"\n{other_eqs = }\n")

                                        other_eqs.append(eq)

                                        # print(f"\n{other_eqs = }\n")

                                        # for obj in other_eqs:
                                        #     if obj is None:
                                        #         other_eqs.remove(None)

                                        other_eqs = [
                                            obj for obj in other_eqs if obj is not None
                                        ]  # type: ignore

                                        # print(f"\n{other_eqs = }\n")

                                if len(other_eqs) == 1:
                                    other_eq = other_eqs[0]

                                # print(
                                #     f"\n{(all(item is not None for item in other_eqs)) = }\n"
                                # )

                                # print(
                                #     f"\n{(any(item is not None for item in other_eqs)) = }\n"
                                # )

                                # print(f"\n{(other_eq is not None) = }\n")

                                # print(
                                #     f"\n{any(
                                #             some_component.energy_conservation(
                                #                 (some_id, other_id)).free_symbols
                                #             == eq.free_symbols
                                #             for eq in self.equations_dict.values()) = }\n"
                                # )

                                # print(f"\n{other_eq = }\n")

                                assert (
                                    (all(item is not None for item in other_eqs))
                                    or (any(item is not None for item in other_eqs))
                                ) or (other_eq is not None)

                                c_ec_e_var_list = list(
                                    some_component.energy_conservation(
                                        (some_id, other_id)
                                    ).free_symbols
                                )

                                flag = False

                                for eq in other_eqs:
                                    for some_var in c_ec_e_var_list:
                                        solved_c_ec_e = sy.solve(
                                            some_component.energy_conservation(
                                                (some_id, other_id)
                                            ),
                                            some_var,
                                        )

                                        solved_eq = sy.solve(eq, some_var)

                                        if (
                                            (eq.lhs in solved_c_ec_e)
                                            or (eq.rhs in solved_c_ec_e)
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    some_component.energy_conservation(
                                                        (some_id, other_id)
                                                    ).rhs,
                                                )
                                                in solved_c_ec_e
                                            )
                                            or (
                                                eq.subs(
                                                    some_var,
                                                    some_component.energy_conservation(
                                                        (some_id, other_id)
                                                    ).lhs,
                                                )
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    (some_id, other_id)
                                                ).subs(some_var, eq.rhs)
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    (some_id, other_id)
                                                ).subs(some_var, eq.lhs)
                                                in solved_c_ec_e
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    (some_id, other_id)
                                                ).lhs
                                                in solved_eq
                                            )
                                            or (
                                                some_component.energy_conservation(
                                                    (some_id, other_id)
                                                ).rhs
                                                in solved_eq
                                            )
                                        ):
                                            flag = True

                                    if flag:
                                        break
                                    else:
                                        self.equations_dict[ULID()] = (
                                            some_component.energy_conservation(
                                                (some_id, other_id)
                                            )
                                        )
                                        self.equation_list.append(
                                            some_component.energy_conservation(
                                                (some_id, other_id)
                                            )
                                        )

                                if (
                                    port_uuid_map[some_id].location != some_component.id
                                ) and (
                                    port_uuid_map[other_id].location
                                    != some_component.id
                                ):
                                    raise ValueError("""The some_id and other_id must be inside
                                        the some_component.component_ports list, but they are not""")

                                NIE_msg: str = """
                                This part needs to have precise verification of the equation comparison,
                                in a way that the equations are also compared algebraically, and not only
                                in an Object perspective
                                """

                                #! raise NotImplementedError(NIE_msg)

                                # print(f"\n{some_component.id = }")
                                # print(
                                #     f"\n{some_component.energy_conservation((some_id, other_id)) = }\n"
                                # )

                                #! This equation needs to be revised and checked before it's added
                                #! to the self.equations_list

                                # # raise NotImplementedError
                                # self.equations_dict[ULID()] = (
                                #     component.energy_conservation((some_id, other_id))
                                # )
                                # self.equation_list.append(
                                #     component.energy_conservation((some_id, other_id))
                                # )

                                # raise ValueError(local_error_message)

                        else:
                            raise TypeError(""" All the components should inherit
                            from some of those classes (Major or Minor Loss Components)""")

        # Fourth part: write the equations that determinate the inlet pressures,
        # // and the part that determinates the outlet pressures

        self.outlet_ports: list[components.Port] = []

        for some_comp in components.Component.component_objects:
            if some_comp.location == self.id:
                for some_port in some_comp.component_ports:
                    if (some_comp.port_quantity != len(some_comp.component_ports)) and (
                        some_port.id == some_comp.component_ports[-1].id
                    ):
                        #! this part skips the loop if some_port is the roor_port
                        #! of some_comp (but this only happens if some_comp has
                        #! a root_port)
                        continue

                    elif (
                        some_comp.port_quantity != len(some_comp.component_ports)
                    ) and (some_port.id != some_comp.component_ports[-1].id):
                        # for joint in self.joints_list:
                        #     if some_port.id in joint:
                        #         continue

                        if all(some_port.id not in joint for joint in self.joints_list):
                            self.outlet_ports.append(some_port)

                    elif some_comp.port_quantity == len(some_comp.component_ports):
                        # for joint in self.joints_list:
                        #   if some_port.id in joint:
                        #       continue

                        if all(some_port.id not in joint for joint in self.joints_list):
                            self.outlet_ports.append(some_port)
                    # else:
                    #
                    #     #! if some_port does not show up in the self.joints_list
                    #     #! it means that this port is an outlet port

        #! self.all_orig_currents id the list of all inlet currents

        print(f"\n{self.all_orig_currents = }\n")
        print(f"\n{len(self.all_orig_currents) = }\n")
        print(f"\n{self.all_orig_currents[0].id = }\n")

        # // creation of the equations for the inlet currents (in_cur.P = cte)
        for in_cur in self.all_orig_currents:
            assert in_cur.pressure is not None

            # print(f"\n{in_cur.id = }\n")
            # print(f"\n{in_cur.composition.P = }\n")
            # print(f"\n{in_cur.pressure = }\n")

            # print(f"\n{in_cur.composition.T = }\n")
            # print(f"\n{in_cur.temperature = }\n")

            for comp in components.Component.component_objects:
                if comp.location == self.id:
                    for comp_port in comp.component_ports:
                        assert comp_port.local_current.id != in_cur.id
                        assert comp_port.local_current != in_cur

            try:
                assert in_cur.composition.P == in_cur.pressure

                assert in_cur.temperature is not None
                assert in_cur.composition.T == in_cur.temperature

            except:
                print(f"\n{in_cur.id = }")
                print(f"\n{in_cur.location = }")
                print(f"\n{in_cur.composition.ID = }")

                print(f"\n{in_cur.composition.P = }")
                print(f"\n{in_cur.pressure = }")

                print(f"\n{in_cur.composition.T = }")
                print(f"\n{in_cur.temperature = }")

                if in_cur.composition.P != in_cur.pressure:
                    in_cur.composition.P = in_cur.pressure
                else:
                    raise ValueError

            in_cur_pressure: sy.Symbol = sy.symbols(str(in_cur.pressure_name))
            in_cur_eq: sy.Basic = sy.Eq(in_cur_pressure, float(in_cur.composition.P))

            if (
                (in_cur_eq not in self.equation_list)
                and (in_cur_eq not in self.equations_dict.values())
                and (
                    all(
                        in_cur_eq.free_symbols != eq.free_symbols
                        for eq in self.equation_list
                    )
                )
            ):
                self.equations_dict[ULID()] = in_cur_eq
                self.equation_list.append(in_cur_eq)

            if (
                (component.id == port.location)
                and (in_cur_eq not in self.equation_list)
                and (in_cur_eq not in self.equations_dict.values())
                and (
                    any(
                        in_cur_eq.free_symbols == eq.free_symbols
                        for eq in self.equations_dict.values()
                    )
                )
            ):
                other_eq: sy.Basic | None = None
                other_eqs: list[sy.Basic] = []

                for eq in self.equations_dict.values():
                    if eq.free_symbols == in_cur_eq.free_symbols:
                        other_eqs = (
                            other_eqs.remove(None) if (None in other_eqs) else other_eqs
                        )  # type: ignore
                        other_eqs.append(eq)

                if len(other_eqs) == 1:
                    other_eq = other_eqs[0]

                # print(f"\n{(all(item is not None for item in other_eqs)) = }\n")

                # print(f"\n{(any(item is not None for item in other_eqs)) = }\n")

                # print(f"\n{(other_eq is not None) = }\n")

                # print(
                #     f"\n{any(
                #                             in_cur_eq.free_symbols
                #                             == eq.free_symbols
                #                             for eq in self.equations_dict.values()) = }\n"
                # )

                # print(f"\n{other_eq = }\n")

                assert (
                    (all(item is not None for item in other_eqs))
                    or (any(item is not None for item in other_eqs))
                ) or (other_eq is not None)

                ic_eq_var_list = list(in_cur_eq.free_symbols)

                flag = False

                for eq in other_eqs:
                    for some_var in ic_eq_var_list:
                        solved_ic_e = sy.solve(in_cur_eq, some_var)

                        solved_eq = sy.solve(eq, some_var)

                        if (
                            (eq.lhs in solved_ic_e)
                            or (eq.rhs in solved_ic_e)
                            or (
                                eq.subs(
                                    some_var,
                                    in_cur_eq.rhs,
                                )
                                in solved_ic_e
                            )
                            or (
                                eq.subs(
                                    some_var,
                                    in_cur_eq.lhs,
                                )
                                in solved_ic_e
                            )
                            or (in_cur_eq.subs(some_var, eq.rhs) in solved_ic_e)
                            or (in_cur_eq.subs(some_var, eq.lhs) in solved_ic_e)
                            or (in_cur_eq.lhs in solved_eq)
                            or (in_cur_eq.rhs in solved_eq)
                        ):
                            flag = True

                    if flag:
                        break
                    else:
                        self.equations_dict[ULID()] = in_cur_eq
                        self.equation_list.append(in_cur_eq)

                NIE_msg: str = """
                                This part needs to have precise verification of the equation comparison,
                                in a way that the equations are also compared algebraically, and not only
                                in an Object perspective
                                """

                #! raise NotImplementedError(NIE_msg)

                #! This equation needs to be revised and checked before it's added
                #! to the self.equations_list

                # raise NotImplementedError

        print(f"\n{self.outlet_ports = }\n")
        print(f"\n{len(self.outlet_ports) = }\n")

        # // creation of the equations for the outlet currents (out_cur.P = cte)
        for out_port in self.outlet_ports:
            out_cur = out_port.local_current

            out_cur.pressure = (
                nc.manometric_atm_pressure
            )  # relative atmosferic pressure, in Pa
            out_cur.composition.P = (
                nc.manometric_atm_pressure
            )  # relative atmosferic pressure, in Pa
            assert out_cur.pressure is not None
            # print(f"\n{out_port.id = }")
            # print(f"\n{out_port.location = }")
            # print(f"\n{out_cur.composition.P = }")
            # print(f"\n{out_cur.pressure = }")
            assert out_cur.composition.P == out_cur.pressure

            assert out_cur.temperature is not None
            assert out_cur.composition.T == out_cur.temperature

            out_cur_pressure: sy.Symbol = sy.symbols(str(out_cur.pressure_name))
            out_cur_eq: sy.Basic = sy.Eq(out_cur_pressure, float(out_cur.composition.P))

            if (
                (out_cur_eq not in self.equation_list)
                and (out_cur_eq not in self.equations_dict.values())
                and (
                    all(
                        out_cur_eq.free_symbols != eq.free_symbols
                        for eq in self.equation_list
                    )
                )
            ):
                self.equations_dict[ULID()] = [out_cur_eq]
                self.equation_list.append(out_cur_eq)

            if (
                (
                    component_uuid_map[out_port.location].id == cp.location
                    for cp in component_uuid_map[out_port.location].component_ports
                )
                and (out_cur_eq not in self.equation_list)
                and (out_cur_eq not in self.equations_dict.values())
                and (
                    any(
                        out_cur_eq.free_symbols == eq.free_symbols
                        for eq in self.equations_dict.values()
                    )
                )
            ):
                other_eq: sy.Basic | None = None
                other_eqs: list[sy.Basic] = []

                for eq in self.equations_dict.values():
                    if eq.free_symbols == out_cur_eq.free_symbols:
                        other_eqs = (
                            other_eqs.remove(None) if (None in other_eqs) else other_eqs
                        )  # type: ignore
                        other_eqs.append(eq)

                if len(other_eqs) == 1:
                    other_eq = other_eqs[0]

                # print(f"\n{(all(item is not None for item in other_eqs)) = }\n")

                # print(f"\n{(any(item is not None for item in other_eqs)) = }\n")

                # print(f"\n{(other_eq is not None) = }\n")

                # print(
                #     f"\n{any(
                #                             out_cur_eq.free_symbols
                #                             == eq.free_symbols
                #                             for eq in self.equations_dict.values()) = }\n"
                # )

                # print(f"\n{other_eq = }\n")

                assert (
                    (all(item is not None for item in other_eqs))
                    or (any(item is not None for item in other_eqs))
                ) or (other_eq is not None)

                oc_eq_var_list = list(out_cur_eq.free_symbols)

                flag = False

                for eq in other_eqs:
                    for some_var in oc_eq_var_list:
                        solved_oc_e = sy.solve(out_cur_eq, some_var)

                        solved_eq = sy.solve(eq, some_var)

                        if (
                            (eq.lhs in solved_oc_e)
                            or (eq.rhs in solved_oc_e)
                            or (
                                eq.subs(
                                    some_var,
                                    out_cur_eq.rhs,
                                )
                                in solved_oc_e
                            )
                            or (
                                eq.subs(
                                    some_var,
                                    out_cur_eq.lhs,
                                )
                                in solved_oc_e
                            )
                            or (out_cur_eq.subs(some_var, eq.rhs) in solved_oc_e)
                            or (out_cur_eq.subs(some_var, eq.lhs) in solved_oc_e)
                            or (out_cur_eq.lhs in solved_eq)
                            or (out_cur_eq.rhs in solved_eq)
                        ):
                            flag = True

                    if flag:
                        break
                    else:
                        self.equations_dict[ULID()] = out_cur_eq
                        self.equation_list.append(out_cur_eq)

                NIE_msg: str = """
                                This part needs to have precise verification of the equation comparison,
                                in a way that the equations are also compared algebraically, and not only
                                in an Object perspective
                                """

                #! raise NotImplementedError(NIE_msg)

                print(f"\n{out_cur_eq = }\n")

                #! This equation needs to be revised and checked before it's added
                #! to the self.equations_list

                # raise NotImplementedError
                self.equations_dict[ULID()] = out_cur_eq
                self.equation_list.append(out_cur_eq)

        # * This list will store all the ports and currents that are registered inside the self.joints_list
        # * i'll use this list to check if some port or current has a joint inside the self mosaic

        flatenned_joints_list: list = [
            item for joint in self.joints_list for item in joint
        ]

        # * This flattend list is important because it does not contain lists inside of it, just simple
        # *elements

        if False:  #! This section is temporarily deactivated
            for joint in self.joints_list:
                for item in joint:
                    if item in component_uuid_map:
                        for comp in components.Component.component_objects:
                            if comp.id == item:
                                # * Checking if all the ports of a component (except for the root_port,
                                ##* in case the component is a T)

                                if not (
                                    len(comp.component_ports) != comp.port_quantity
                                ):
                                    for cp_index, comp_port in enumerate(
                                        comp.component_ports
                                    ):
                                        # * This if excludes the checking for the root_port
                                        # * because there shouldn't exist joints with the root_port of the
                                        # * T_comp

                                        if comp_port.id in flatenned_joints_list:
                                            pass

                                        elif comp_port.id not in flatenned_joints_list:
                                            # // This is the case where the comp_port should be a
                                            # // root or leaf port (in the extreme end or beggining of
                                            ##// a mosaic)

                                            # *checking if the port is also a root or leaf port in the
                                            # * directed graph of the mosaic.

                                            # * root_nodes are the ones with no inlet, and only one outlet
                                            root_nodes: list = [
                                                node
                                                for node in self.graph.nodes()
                                                if (node.in_degree() == 0)
                                                and (node.out_dengree() == 1)
                                            ]

                                            # * leaf_nodes are the ones with no outlet, and only one inlet
                                            leaf_nodes: list = [
                                                node
                                                for node in self.graph.nodes()
                                                if (node.in_degree() == 1)
                                                and (node.out_dengree() == 0)
                                            ]

                                            if comp_port.id in root_nodes:
                                                # * This means that the node passed the requirements,
                                                # * and it should be considered a root node

                                                inlet_original_ports.append(
                                                    comp_port.id
                                                )

                                            elif comp_port.id in leaf_nodes:
                                                # * This means that the node passed the requirements,
                                                # * and it should be considered a leaf node

                                                outlet_ports.append(comp_port.id)

                                            elif (comp_port.id not in root_nodes) and (
                                                comp_port.id not in leaf_nodes
                                            ):
                                                # * This means that the node did not passed the requirements,
                                                # * and it should not be considered a root/leaf node

                                                raise ConduitForgeError("""\n\n This error indicates
                                                    that, eventhoug a current and or a port that was a
                                                    candidate to root/leaf node inside the self moisaic
                                                    graph, is not a root/leaf node inside the graph. This
                                                    shows that there is some erro inside the root/leaf
                                                    candidate ports filtering, or inside the creation of
                                                    the graph""")

                                elif len(comp.component_ports) != comp.port_quantity:
                                    for cp_index, comp_port in enumerate(
                                        comp.component_ports
                                    ):
                                        # * The if statement below excludes the checking for the root_port
                                        # * because there shouldn't exist joints with the root_port of the
                                        # * T_comp

                                        if (comp_port != comp.component_ports[-1]) and (
                                            cp_index != -1
                                        ):
                                            if comp_port.id in flatenned_joints_list:
                                                pass

                                            elif (
                                                comp_port.id
                                                not in flatenned_joints_list
                                            ):
                                                # // This is the case where the comp_port should be a
                                                # // root or leaf port (in the extreme end or beggining of
                                                ##// a mosaic)

                                                # *checking if the port is also a root or leaf port in the
                                                # * directed graph of the mosaic.
                                                # * root_nodes are the ones with no inlet, and only one outlet
                                                root_nodes: list = [
                                                    node
                                                    for node in self.graph.nodes()
                                                    if (node.in_degree() == 0)
                                                    and (node.out_dengree() == 1)
                                                ]

                                                # * leaf_nodes are the ones with no outlet, and only one inlet
                                                leaf_nodes: list = [
                                                    node
                                                    for node in self.graph.nodes()
                                                    if (node.in_degree() == 1)
                                                    and (node.out_dengree() == 0)
                                                ]

                                                if comp_port.id in root_nodes:
                                                    # * This means that the node did not passed the requirements,
                                                    # * and it should be considered a root node

                                                    inlet_original_ports.append(
                                                        comp_port.id
                                                    )

                                                elif comp_port.id in leaf_nodes:
                                                    # * This means that the node passed the requirements,
                                                    # * and it should be considered a leaf node

                                                    outlet_ports.append(comp_port.id)

                                                elif (
                                                    comp_port.id not in root_nodes
                                                ) and (comp_port.id not in leaf_nodes):
                                                    # * This means that the node passed the requirements,
                                                    # * and it should not be considered a root/leaf node

                                                    raise ConduitForgeError("""\n\n This error indicates
                                                    that, eventhoug a current and or a port that was a
                                                    candidate to root/leaf node inside the self moisaic
                                                    graph, is not a root/leaf node inside the graph. This
                                                    shows that there is some erro inside the root/leaf
                                                    candidate ports filtering, or inside the creation of
                                                    the graph""")

                                else:
                                    raise ConduitForgeError("""\n\nThe code should never get to this else
                                    block, because it should be impossible""")

                # * Preciso codar a parte de identificação de todos os nós de entrada, e todos os
                # * nós de saída.

                # * (Como encontrar correntes de saída)Uma forma de fazer isso poderia ser encontrar todas as correntes que a pressão ainda
                # * não está definida, ou correntes que não foram criadas dentro de uma porta.

                # * ((Como encontrar correntes de saída)Depois disso, pra encontrar as correntes de entrada eu poderia encontrar as outras

            # self.global_mosaic_components_as_components

            for joint in self.joints_list:
                for item in joint:
                    if item in current_uuid_map:
                        # * Checking to see if this current has a joint with an inlet_original_port,
                        # * (check that this port is inside the self mosaic graph, and that his port is
                        # * an original port)

                        # // The current should only be an original inlet current if it has a joint with
                        # // an original inlet component, if it does not happen, the code should raise an
                        # // error, and the error indicates that wether the graph creation has problems,
                        # // or the joint creation has problems

                        other_item_in_joint: None | UUID = None

                        assert len(joint) == 2

                        for obj in joint:
                            if obj != item:
                                other_item_in_joint = obj

                        assert other_item_in_joint in inlet_original_ports

                        for comp in components.Component.component_objects:
                            if comp.id == other_item_in_joint:
                                raise ConduitForgeError("""\n\nThis should never happen, because the other
                                obj in a joint with an original current should be a port, and not a
                                component. This indicates that the creation and/or registration of the
                                joints ahve a problem (the problem could be inside the __add__ and
                                __radd__ dunders from the Component class)""")

        # // Inside this part, the equations will be collected from the component
        # // using the ports inside the edges

        #! self.all_eq_variables: set = set()

        #! I could use the Counter Function to Check if some of the current/port
        #! uuid is not being shown inside any equation from the self.equation list

        # // This Counter counts how many times an element appears inside an iterable
        # print(f"\n{Counter(current_uuid_map) = }\n")

        # print(f"\n{len(self.equation_list) = }\n\n")
        # pprint(f"{self.equation_list = }")

        for eq in self.equation_list:
            # print(f"\n{eq = }\n")
            # print(f"\n{eq.free_symbols = }\n")

            # if eq.free_symbols not in self.all_eq_variables:
            self.all_eq_variables.update(eq.free_symbols)

        self.variable_count: Counter = sum(
            (Counter(eq.free_symbols) for eq in self.equation_list), Counter()
        )

        # pprint(self.variable_count)

        # try:
        #     assert len(self.all_eq_variables) == len(self.currents_list)
        #     assert len(self.equations_dict.values()) == len(self.equation_list)

        # except AssertionError:
        #     print(f"\n{len(self.currents_list) = }\n")
        # pprint(f'{list(map(lambda cur: [cur.id for cur in self.currents_list], self.currents_list)) = }')
        # print(f"{self.all_eq_variables = }\n")

        # print(f"{self.equations_dict.values() = }\n")

        # print(f"{len(self.equations_dict.values()) = }\n")

        # print(f"{self.equations_dict.values() = }\n")

        # print(f"{len(self.equation_list) = }\n")

        # // Uma quarta parte poderia ser adicionar uma das equações, que seria a equação de energia em um dos possíves influxos
        # // entre duas das correntes de entrada mais distantes

    def equations_solver(self, verify=True):
        """
        THis method will recieve the equations and solve the entire system, until the error is
        below the tolerance.

        tipically, the tolerance is arround 10^-6. This means that the difference between the
        calculated values and the
        tolerance should be less than 10^-6.
        """

        """ Inside this method, the initial_guess_values will be stored inside a tuple or list, and
        passed to the sympy solver """

        current_uuid_map: dict[UUID, current.Current] = {
            cur.id: cur for cur in current.Current.current_objects
        }

        cur_pressure_name_uuid_map: dict[UUID, current.Current] = {
            cur.pressure_name: cur for cur in current.Current.current_objects
        }

        port_uuid_map: dict[UUID, components.Port] = {
            port.id: port for port in components.Port.port_objects
        }

        component_uuid_map: dict[UUID, components.Component] = {
            comp.id: comp for comp in components.Component.component_objects
        }

        # * All the currents inside this mosaic
        self.all_currents_in_self: dict[UUID, current.Current] = {}
        self.all_ports_in_self: dict[UUID, components.Port] = {}
        self.all_pressure_names_in_self: dict[ULID, current.Current] = {}

        # * Collection of pressure_names from components
        for comp in components.Component.component_objects:
            if comp.location == self.id:
                # * Collection from normal comps
                if len(comp.component_ports) == comp.port_quantity:
                    for port in comp.component_ports:
                        if (
                            port.local_current.pressure_name
                            not in self.all_pressure_names_in_self.keys()
                        ):
                            self.all_pressure_names_in_self[
                                port.local_current.pressure_name
                            ] = port.local_current

                # * Collection from T_connector like components
                elif (len(comp.component_ports) == comp.port_quantity) and (
                    len(comp.component_ports) == 4
                ):
                    for port in comp.component_ports:
                        if (
                            port.local_current.pressure_name
                            not in self.all_pressure_names_in_self.keys()
                        ) and (port.id != comp.component_ports[-1]):
                            self.all_pressure_names_in_self[
                                port.local_current.pressure_name
                            ] = port.local_current

        # * Colection of all local_currents from the self.mosaic
        for comp in components.Component.component_objects:
            if comp.location == self.id:
                if len(comp.component_ports) == comp.port_quantity:
                    for port in comp.component_ports:
                        if port.id not in self.all_ports_in_self.keys():
                            self.all_ports_in_self[port.id] = port

                        if (
                            port.local_current.pressure_name
                            not in self.all_pressure_names_in_self.keys()
                        ):
                            self.all_pressure_names_in_self[
                                port.local_current.pressure_name
                            ] = port.local_current

                elif len(comp.component_ports) != comp.port_quantity:
                    for port in comp.component_ports:
                        if port.id != comp.component_ports:
                            if port.id not in self.all_ports_in_self:
                                self.all_ports_in_self[port.id] = port

                            if (
                                port.local_current.pressure_name
                                not in self.all_pressure_names_in_self
                            ):
                                self.all_pressure_names_in_self[
                                    port.local_current.pressure_name
                                ] = port.local_current

        # // Sanity check, to see if there is some cur in self mosaic that cur.location == None
        for cur in current.Current.current_objects:
            # print(f"\n\n{cur.location = }\n\n")

            if cur.location == None:
                # print(f"\n{cur.id = }\n")
                # print(f"{cur.location = }\n\n")

                for joint in self.joints_list:
                    for obj in joint:
                        if obj == cur.id:
                            raise ValueError(
                                f"\nThe location of the current:{cur} should not be None\n"
                            )

                for comp in components.Component.component_objects:
                    if (comp.port_quantity == len(comp.component_ports)) and (
                        comp.port_quantity == 2
                    ):
                        for port in comp.component_ports:
                            assert port.local_current.id != cur.id

                    if (comp.port_quantity != len(comp.component_ports)) and (
                        len(comp.component_ports) == 4
                    ):
                        for port in comp.component_ports:
                            if port.id != comp.component_ports[-1]:
                                assert port.local_current.id != cur.id

                for orig_cur in self.all_orig_currents:
                    assert orig_cur.id != cur.id

        # * Colection of other currents (that may not be inside a component, but are
        # * inside the self mosaic)
        for cur in current.Current.current_objects:
            # * Collection from curent.Current.current_objects

            # print(f"\n\n{cur.location = }\n\n")

            if cur.location is None:
                for comp in components.Component.component_objects:
                    if comp.location == self.id:
                        for port in comp.component_ports:
                            if port.local_current.id == cur.id:
                                print(f"""I dont know if i should change the location
                                    of the current or just let it pass""")

                                raise ConduitForgeError(
                                    f"""\nIdontKnowWhatToError_LOL\n"""
                                )

            if (
                (not isinstance(cur.location, tuple))
                and (not isinstance(cur.location, list))
                and (cur.location is not None)
            ):
                assert isinstance(cur.location, UUID)

                if (
                    (cur.location in port_uuid_map.keys())
                    and (
                        component_uuid_map[
                            port_uuid_map[cur.location].location
                        ].location
                        == self.id
                    )
                    and (cur.id not in self.all_currents_in_self.keys())
                ):
                    self.all_currents_in_self[cur.id] = cur

            if (
                (isinstance(cur.location, tuple)) or (isinstance(cur.location, list))
            ) and (cur.location is not None):
                if (component_uuid_map[cur.location[0]].location == self.id) and (
                    cur.id not in self.all_currents_in_self.keys()
                ):
                    self.all_currents_in_self[cur.id] = cur

        for self_cur in self.all_currents_in_self.values():
            if (
                UUID(str(self_cur.pressure_name))
                not in self.all_pressure_names_in_self.keys()
            ):
                self.all_pressure_names_in_self[UUID(str(self_cur.pressure_name))] = (
                    self_cur.pressure_name
                )

        # * Colection of currents from the self.joints_list
        for joint in self.joints_list:
            for obj in joint:
                if (obj in current_uuid_map.keys()) and (
                    obj not in self.all_currents_in_self.keys()
                ):
                    print(f"\n{obj = } added to the self.all_cur_in_self\n")
                    self.all_currents_in_self[cur.id] = cur

                else:
                    ...
                #     print(f"\n{(obj in current_uuid_map.keys()) = }\n")
                #     print(
                #         f"\n{(
                #     obj not in self.all_currents_in_self.keys()
                # ) = }\n"
                #     )

                #     print(
                #         f"\n{((obj in current_uuid_map.keys()) and (
                #     obj not in self.all_currents_in_self.keys()
                # )) = }\n"
                #     )
                #     print(f"\n{obj = } NOT added to the self.all_cur_in_self\n")

        #! if this assertion fail, some eq are being added to the self.eq_list but
        #! not to the eqs_dict
        assert len(self.equation_list) == len(self.equations_dict.values())

        # # // Correction of the pressures of outlet ports
        # for node in self.graph.nodes():
        #     for var, var_id in enumerate(self):

        self.initial_values: list = [None for _ in list(self.all_eq_variables)]

        # // print(f"\n{list(self.all_eq_variables) = }\n")

        self.var_list: list = list(self.all_eq_variables)

        # self.inverse_equations_dict = {self.equations_dict[] : self.equations_dict[]keys for key in }

        # // Sanity check
        for obj in self.all_eq_variables:
            if (
                (str(obj) in port_uuid_map.keys())
                or (str(obj) in current_uuid_map.keys())
                or (str(obj) in cur_pressure_name_uuid_map.keys())
                or (UUID(str(obj)) in port_uuid_map.keys())
                or (UUID(str(obj)) in current_uuid_map.keys())
                or (UUID(str(obj)) in cur_pressure_name_uuid_map.keys())
            ):
                # print(f"\n{obj = }\n")
                # print(f"\n{type(obj) = }\n")
                # print(f"\n{str(obj) = }\n")

                pass

            else:
                # print(f"\n{obj = }\n")
                # print(f"\n{type(obj) = }\n")
                # print(f"\n{str(obj) = }\n")
                raise ValueError
        else:
            print(f"\nThe type of the variables is ok\n")

        # // Sanity check
        for obj in self.var_list:
            if (
                (str(obj) in port_uuid_map.keys())
                or (str(obj) in current_uuid_map.keys())
                or (str(obj) in cur_pressure_name_uuid_map.keys())
                or (UUID(str(obj)) in port_uuid_map.keys())
                or (UUID(str(obj)) in current_uuid_map.keys())
                or (UUID(str(obj)) in cur_pressure_name_uuid_map.keys())
            ):
                # print(f"\n{obj = }\n")
                # print(f"\n{type(obj) = }\n")
                # print(f"\n{str(obj) = }\n")

                pass

            else:
                # print(f"\n{obj = }\n")
                # print(f"\n{type(obj) = }\n")
                # print(f"\n{str(obj) = }\n")
                raise ValueError
        else:
            print(f"\nThe type of the variables is ok\n")

        # // The for loop below colects the initial values for each pressure and
        # // volume flow inside the self mosaic

        print(f"\n\n{self.var_list = }\n\n")

        for var_index, var in enumerate(self.var_list):
            # if ((str(var) in current_uuid_map.keys())
            #     or (var in current_uuid_map.keys())):

            #     # self.initial_values[var_index] = current_uuid_map[var].volume_flow

            if (
                (UUID(str(var)) in port_uuid_map.keys())
                and (self.initial_values[var_index] == None)
            ):  # port_uuid_map[UUID(str(var))].local_current.volume_flow not in self.initial_values[var_index]
                # or (var in port_uuid_map.keys())
                self.initial_values[var_index] = port_uuid_map[
                    UUID(str(var))
                ].local_current.volume_flow

            elif (UUID(str(var)) in cur_pressure_name_uuid_map.keys()) and (
                self.initial_values[var_index] == None
            ):
                # != cur_pressure_name_uuid_map[UUID(str(var))]composition.P
                # or (var in cur_pressure_name_uuid_map.keys())
                the_cur: current.Current = cur_pressure_name_uuid_map[UUID(str(var))]
                # for cur in current.Current.current_objects:
                #     if UUID(str(var)) == cur.pressure_name:
                #         the_cur = cur
                assert the_cur is not None

                self.initial_values[var_index] = the_cur.composition.P

            elif (UUID(str(var)) in current_uuid_map.keys()) and (
                self.initial_values[var_index] == None
            ):
                # * print(f"\n{current_uuid_map[UUID(str(var))].id = }\n")
                # * print(f"\n{current_uuid_map[UUID(str(var))].volume_flow = }\n")

                self.initial_values[var_index] = current_uuid_map[
                    UUID(str(var))
                ].volume_flow

            else:
                print(f"\n{var = }\n")

                print(f"\n{(var in current_uuid_map.keys()) = }\n")
                print(f"\n{(var in current_uuid_map.values()) = }\n")

                print(f"\n{(UUID(str(var)) in current_uuid_map.keys()) = }\n")
                print(f"\n{(UUID(str(var)) in current_uuid_map.values()) = }\n")

                print(f"\n{(var in current_uuid_map.keys()) = }\n")
                print(f"\n{(var in current_uuid_map.values()) = }\n")

                print(f"\n{type(var)= }\n")
                print(f"\n{isinstance(var, UUID) = }\n")
                print(f"\n{isinstance(var, ULID) = }\n")
                print(f"\n{isinstance(var, sy.Symbol) = }\n")

                # for eq in self.equation_list:
                #     eq_vars = eq.free_symbols
                #     if (var in eq_vars):

                #         print(f"{self.equations_dict[]}")
                raise TypeError("""The variables should be vars from cur_id, port_id
                    or pressure_name_id""")

        assert len(self.initial_values) == len(self.var_list)

        # // Sanity check
        for value_index, value in enumerate(self.initial_values):
            try:
                assert value is not None
                assert value != None
            except:
                print(f"\n{self.var_list = }\n")

                print(f"\n{value = }\n")
                print(f"\n{value_index = }\n")

                print(f"\n{self.var_list[value_index] = }\n")

                print(f"\n{self.var_list = }\n")

                print(f"\n{self.initial_values = }\n")

                raise ValueError

        # // This list will store all Q(volume flow) variables, and will be used to sort the equations by type
        # // (mass_eq, energy_eq, mixed_eq)
        self.mass_var_list: list = []

        # // This list will store all P (pressure) variables, and will be used to sort the equations by type
        self.energy_var_list: list = []

        # * Filling the energy and mass var lists
        for eq in self.equation_list:
            eq_vars: set = eq.free_symbols

            for var in eq_vars:
                if (UUID(str(var)) not in self.mass_var_list) and (
                    (UUID(str(var)) in self.all_ports_in_self)
                    or (UUID(str(var)) in self.all_currents_in_self)
                ):
                    self.mass_var_list.append(var)

                elif (UUID(str(var)) in self.all_pressure_names_in_self) and (
                    UUID(str(var)) not in self.mass_var_list
                ):
                    self.energy_var_list.append(var)

                elif (
                    (UUID(str(var)) not in self.all_currents_in_self)
                    and (UUID(str(var)) not in self.all_pressure_names_in_self)
                    and (UUID(str(var)) not in self.mass_var_list)
                    and (UUID(str(var)) not in self.energy_var_list)
                ):
                    print(f"\n{(UUID(str(var)) not in self.all_currents_in_self) = }\n")
                    print(
                        f"\n{(UUID(str(var)) not in self.all_pressure_names_in_self) = }\n"
                    )
                    print(f"\n{(UUID(str(var)) not in self.mass_var_list) = }\n")
                    print(f"\n{(UUID(str(var)) not in self.energy_var_list) = }\n")

                    print(f"\n{var = }\n")

                    raise TypeError("""Each var should either be inside self.all_curs_in_self
                        or in self.all_pressure_names_in_self""")

        self.mass_eqs_list: list = []
        self.energy_eqs_list: list = []
        self.mixed_eqs_list: list = []

        # * Classifying all the quations in 3 groups (mass_eq, energy_eq, mixed_eq)
        # * mass_eq are the ones with only mass variables inside
        # * energy_eq are the ones with only energy variables inside
        # * mixed equations are the ones with mass and energy variables
        for eq in self.equation_list:
            eq_vars: set = (
                eq.free_symbols
            )  # () i have got an error by using () to access free_symbols

            if (all(var in self.mass_var_list for var in eq_vars)) and (
                eq not in self.mass_eqs_list
            ):
                self.mass_eqs_list.append(eq)

            elif (all(var in self.energy_var_list for var in eq_vars)) and (
                eq not in self.energy_eqs_list
            ):
                self.energy_eqs_list.append(eq)

            elif (
                (any(var not in self.energy_var_list for var in eq_vars))
                and (any(var not in self.mass_var_list for var in eq_vars))
                and (eq not in self.mixed_eqs_list)
                and (eq not in self.mass_eqs_list)
                and (eq not in self.energy_eqs_list)
            ):
                self.mixed_eqs_list.append(eq)
                # CHECK IF EQ NOT IN MASS OR ENERGY LISTS
                # IF NOT, ADD EQ TO MIXED EQ LIST

        #     self.equation_list, list(self.var_list), self.initial_values
        # )
        # print("\n\n")
        # pprint(solved_system)
        # print("\n\n")

        # // Correction of the pressures of outlet ports

        self.pressure_names_str: dict = {}

        self.string_var_list = [str(var) for var in self.var_list]

        self.nodes_as_dict = dict(self.graph.nodes(data=False))  # * data=True

        self.graph_edges = self.graph.edges(data=True)

        for var_index, var in enumerate(self.var_list):
            for key in self.nodes_as_dict.keys():
                # // Outlet Ports
                if (all(key not in joint for joint in self.joints_list)) and (
                    key in port_uuid_map.keys()
                ):
                    # // Filtering the root ports from the T connector, so that
                    # // they are skipped by the assert and other logic checkup
                    if (
                        len(
                            component_uuid_map[
                                port_uuid_map[key].location
                            ].component_ports
                        )
                        != component_uuid_map[port_uuid_map[key].location].port_quantity
                    ) and (
                        (
                            component_uuid_map[
                                port_uuid_map[key].location
                            ].component_ports.index(port_uuid_map[key])
                            == -1
                        )
                        or (
                            port_uuid_map[key].id
                            == component_uuid_map[port_uuid_map[key].location]
                            .component_ports[-1]
                            .id
                        )
                    ):
                        continue
                    try:
                        assert (
                            (str(key) in self.string_var_list)
                            or (
                                str(port_uuid_map[key].local_current.id)
                                in self.string_var_list
                            )
                            or (
                                str(port_uuid_map[key].local_current.pressure_name)
                                in self.string_var_list
                            )
                        )
                    except:
                        print(f"\n\n{key = }")
                        print(f"\n{str(key) = }")
                        print(f"\n{self.string_var_list = }")
                        print(f"\n{str(port_uuid_map[key].local_current.id) = }")
                        print(
                            f"\n{str(port_uuid_map[key].local_current.pressure_name) = }"
                        )
                        print(f"\n{(str(key) in self.string_var_list) = }")
                        print(
                            f"\n{(
                                str(port_uuid_map[key].local_current.id)
                                in self.string_var_list
                            ) = }"
                        )
                        print(
                            f"\n{(
                                str(port_uuid_map[key].local_current.pressure_name)
                                in self.string_var_list
                            ) = }"
                        )

                        print(
                            f"\n{(
                            (str(key) in self.string_var_list)
                            or (
                                str(port_uuid_map[key].local_current.id)
                                in self.string_var_list
                            )
                            or (
                                str(port_uuid_map[key].local_current.pressure_name)
                                in self.string_var_list
                            )
                        ) = }"
                        )

                        raise AssertionError

                    outlet_port = port_uuid_map[key]

                    outlet_port.local_current.pressure = self.standard_pressure
                    outlet_port.local_current.composition.P = self.standard_pressure

                    outlet_port.local_current.volume_flow = self.standard_volume_flow

                    if key == UUID(str(var)):
                        self.initial_values[var_index] = self.standard_volume_flow

                    elif outlet_port.local_current.id == UUID(str(var)):
                        self.initial_values[var_index] = self.standard_volume_flow

                    elif outlet_port.local_current.pressure_name == UUID(str(var)):
                        # self.initial_values[var_index] = self.standard_pressure
                        self.initial_values[var_index] = 0

                # // Original Currents
                elif (key in current_uuid_map.keys()) and (key == UUID(str(var))):
                    assert str(current_uuid_map[key].id) in self.string_var_list
                    assert (
                        str(current_uuid_map[key].pressure_name) in self.string_var_list
                    )

                    self.initial_values[
                        self.string_var_list.index(
                            str(current_uuid_map[key].pressure_name)
                        )
                    ] = current_uuid_map[key].original_pressure

                    # // Selection of the inlet original ports (the ones inside
                    # // the joint with an original current)

                    orig_joint = None
                    orig_port_index = 0
                    orig_port = None
                    for joint in self.joints_list:
                        if key in joint:
                            orig_joint = joint
                            orig_port_index = joint.index(key) - 1

                            # // Preciso fazer o loop for parar, e fazer o codigo
                            # // sair dele assim que a junta for encontrada
                            continue

                    print(f"\n\n{orig_port_index = }")
                    print(f"\n\n{orig_joint[orig_port_index] = }")
                    print(f"\n\n{port_uuid_map[orig_joint[orig_port_index]] = }")
                    # * print(f"\n\n{ = }")

                    orig_port = port_uuid_map[orig_joint[orig_port_index]]

                    if str(orig_port.id) in self.string_var_list:
                        self.initial_values[
                            self.string_var_list.index(str(orig_port.id))
                        ] = self.standard_volume_flow

                        # self.var_list[self.string_var_list.index(str(orig_port.id))] = (
                        #     self.standard_volume_flow
                        # )

                    if str(orig_port.local_current.id) in self.string_var_list:
                        # self.var_list[
                        #     self.string_var_list.index(str(orig_port.local_current.id))
                        # ] = self.standard_volume_flow

                        self.initial_values[
                            self.string_var_list.index(str(orig_port.local_current.id))
                        ] = self.standard_volume_flow
                    if (
                        str(orig_port.local_current.pressure_name)
                        in self.string_var_list
                    ):
                        self.initial_values[
                            self.string_var_list.index(
                                str(orig_port.local_current.pressure_name)
                            )
                        ] = current_uuid_map[key].original_pressure

                # // Common ports, currents and components (that will recieve the
                # // pressure and vol flow guess from the standard value)
                elif (
                    (key in port_uuid_map.keys())
                    and (UUID(str(var)) == key)
                    and any(key in joint for joint in self.joints_list)
                ):
                    assert str(key in self.string_var_list)

                    assert str(port_uuid_map[key].id) in self.string_var_list

                    #! try:
                    #!     assert (
                    #!         str(port_uuid_map[key].local_current.id)
                    #!         in self.string_var_list
                    #!     )

                    #! except:
                    #!     print(f"\n\n{self.string_var_list = }\n\n")
                    #!     print(f"{str(port_uuid_map[key].local_current.id) = }\n\n")
                    #!     print(f"{str(port_uuid_map[key].id) = }\n\n")

                    #!     raise AssertionError

                    assert (
                        str(port_uuid_map[key].local_current.pressure_name)
                        in self.string_var_list
                    )

                    port_uuid_map[key].local_current.pressure = self.standard_pressure
                    port_uuid_map[
                        key
                    ].local_current.composition.P = self.standard_pressure

                    port_uuid_map[
                        key
                    ].local_current.volume_flow = self.standard_volume_flow

                    self.initial_values[self.string_var_list.index(str(key))] = (
                        self.standard_volume_flow
                    )

                    #!  self.initial_values[
                    #!    self.string_var_list.index(
                    #!         str(port_uuid_map[key].local_current.id)
                    #!     )
                    #! ] = self.standard_volume_flow

                    self.initial_values[
                        self.string_var_list.index(
                            str(port_uuid_map[key].local_current.pressure_name)
                        )
                    ] = self.standard_pressure

                # // The last part is to set all the inlet ports pressure equal to
                # // the respective inlet pressure

                # * The original ports are the ones found inside the graph, and
                # * with a graph edge with an original current

                # * The original inlet ports can also be found from the self.joints_list
                # self.graph

                # print(f"\n\n\n{self.graph_edges = }\n\n\n")

        print(f"\n\n\n{self.var_list = }\n\n\n")
        print(f"\n\n\n{self.initial_values = }\n\n\n")
        # print(f"\n\n\n{self.equation_list = }\n\n\n")
        self.solved_system = sy.nsolve(
            self.equation_list,
            self.var_list,
            self.initial_values,
            verify=verify,  #! verify=False
        )

        #! The next step is to check if the solution given by sy.nsolve() is right
        #! I could also check if the values recieved from the solver are real numbers
        #! and if those values contain some imaginary value.

        #! self.solution_is_right = sy.checksol(
        #!     self.equation_list, self.var_list, self.initial_values
        #! )

        # // * Opttional Feature *
        # // The other_step is to assign the values solved to their respective attribute
        # // inside the current that the attribute comes from
        # for var_index, var in enumerate(self.var_list):
        #     if UUID(str(var)) in port_uuid_map.keys():
        #         # // This is the port that owns the current in which the volume
        #         # // flow (Q) will be setted to the solved value
        #         # //

        #         Q_p = port_uuid_map[UUID(str(var))]

        #         assert str(Q_p.id) == str(var)

        #         old_Q = Q_p.local_current.volume_flow
        #         new_Q = self.solved_system[var_index]

        #         # *print(f"\n{(old_Q - new_Q) = }\n")
        #         # Q_p = port_uuid_map[UUID(str(var))]
        #         Q_p.local_current.volume_flow = self.solved_system[var_index]

        #         # *print(f"\n{Q_p.id = }\n")
        #         # *print(f"\n{Q_p.location = }\n")
        #         # *print(f"\n{Q_p.local_current.id = }\n")
        #         # *print(f"\n{Q_p.local_current.volume_flow = }\n")

        #     elif UUID(str(var)) in current_uuid_map.keys():
        #         # // This is the current in which the volume flow (Q) will be setted
        #         # // to the solved value

        #         Q_cur = current_uuid_map[UUID(str(var))]

        #         assert str(Q_cur.id) == str(var)

        #         old_Q = Q_cur.volume_flow
        #         new_Q = self.solved_system[var_index]

        #         # *print(f"\n{(old_Q - new_Q) = }\n")

        #         # Q_cur = current_uuid_map[UUID(str(var))]
        #         Q_cur.volume_flow = self.solved_system[var_index]

        #         # *print(f"{Q_cur.id = }\n")
        #         # *print(f"\n{Q_cur.location = }\n")
        #         # *print(f"\n{Q_cur.volume_flow = }\n")

        #     elif UUID(str(var)) in cur_pressure_name_uuid_map.keys():
        #         # // This is the current in which the pressure (P) will be setted
        #         # // to the solved value (and also the P_cur.composition.P)

        #         P_cur = cur_pressure_name_uuid_map[UUID(str(var))]

        #         # try:
        #         #     assert str(P_cur.id) == str(var)
        #         # except:
        #         #     print(f"\n{P_cur.location = }\n")

        #         #     print(f"\n{P_cur.id = }\n")
        #         #     print(f"\n{str(P_cur.id) = }\n")

        #         #     print(f"\n{var = }\n")
        #         #     print(f"\n{str(var) = }\n")

        #         #     raise AssertionError

        #         old_P_from_composition = P_cur.composition.P
        #         old_pressure_from_currrent = P_cur.pressure

        #         new_P = self.solved_system[var_index]

        #         # *print(f"\n{(old_P_from_composition - new_P) = }\n")
        #         # *print(f"\n{(old_pressure_from_currrent - new_P) = }\n")

        #         # P_cur = cur_pressure_name_uuid_map[UUID(str(var))]
        #         P_cur.pressure = self.solved_system[var_index]
        #         P_cur.composition.P = self.solved_system[var_index]

        #         # *print(f"\n{P_cur = }\n")
        #         # *print(f"\n{P_cur.id  = }\n")
        #         # *print(f"\n{P_cur.location = }\n")
        #         # *print(f"\n{P_cur.composition.P = }\n")

        #     else:
        #         raise ConduitForgeError(
        #             "The var shoud be inside one of the dicts above"
        #         )
        #     # elif UUID(str(var))

        # self.string_var_dict: dict = {var: str(var) for var in self.var_list}
        # self.string_graph_nodes_dict: dict = {
        #     node: str(node) for node in list[self.graph.nodes()]
        # }

        # * This list stores the strings of the vars, just for easyer comparison
        # * between graph nodes and vars
        self.string_var_list = [str(var) for var in self.var_list]

        # // The final step is to assign the calculated values to the currents and
        # // local currents and, finally, to the nodes of the graph

        #! This section is temporarely deactivated
        if False:
            for str_var_index, str_var in enumerate(self.string_var_list):
                print(f"\n{str_var_index = }, {str_var = }, {type(str_var) = }")
                print(f"\n{UUID(str(var)) = }")

                for node in list(self.graph.nodes()):
                    print(f"\n{node = }")

                    local_error_msg = r"""
                    The code bellow generates some very wrong results, because the 
                    volume_flow values solved get mixed with the pressure values.
                    maybe this is because of the several iterations of all the loops
                    """

                    #! raise ValueError(f"\n{local_error_msg = }")
                    # first_condition: bool = (str(node) in self.string_var_list) and (
                    #     UUID(str(node)) == UUID(str(str_var))
                    # )

                    # print(f"\n{str(node) = }")
                    # print(f"\n{UUID(str(node)) = }")
                    # print(f"\n{UUID(str(str_var)) = }")

                    # print(f"\n{str(node) in self.string_var_list = }")
                    # print(f"\n{UUID(str(node)) == UUID(str(str_var)) = }")

                    # print(f"\n{first_condition = }")

                    # print(f"\n{UUID(str(node)) = }")
                    # print(f"\n{UUID(str(node)) = }")
                    # print(f"\n{UUID(str(str_var)) = }")

                    # print(f"\z{UUID(str(node)) in cur_pressure_name_uuid_map = }")
                    if (UUID(str(node)) in (self.string_var_list)) and (
                        UUID(str(node)) == UUID(str_var)
                    ):
                        if UUID(str(node)) in current_uuid_map.keys():
                            current_uuid_map[
                                UUID(str(node))
                            ].volume_flow = self.solved_system[str_var_index]

                            self.graph.nodes[node]["vol_flow"] = self.solved_system[
                                str_var_index
                            ]

                            print(f"\n{str_var = }, {str_var_index = }")
                            print(
                                f"\n{self.solved_system[
                                str_var_index
                            ] = }\n"
                            )
                            print(f"\n{self.graph.nodes[node]["vol_flow"] = }")

                            print(
                                f"\n{((UUID(str(node)) in port_uuid_map.keys())
                                or (UUID(str(node)) in current_uuid_map.keys())) = }"
                            )

                        elif UUID(str(node)) in port_uuid_map.keys():
                            port_uuid_map[
                                UUID(str(node))
                            ].local_current.volume_flow = self.solved_system[
                                str_var_index
                            ]

                            self.graph.nodes[node]["vol_flow"] = self.solved_system[
                                str_var_index
                            ]

                            print(f"\n{var = }, {var_index = }")
                            print(
                                f"\n{self.solved_system[
                                str_var_index
                            ] = }\n"
                            )

                    if UUID(str(str_var)) not in self.graph.nodes():
                        # print(f"\n{self.graph.nodes[node]["vol_flow"] = }")
                        print(
                            f"\n{UUID(str_var) in cur_pressure_name_uuid_map.keys() = }"
                        )

                        print(f"\n{str_var = }, {str_var_index = }")
                        print(
                            f"\n{self.solved_system[
                            str_var_index
                        ] = }\n"
                        )

                        if (
                            (UUID(str(node)) in current_uuid_map.keys())
                            and (UUID(str_var) in cur_pressure_name_uuid_map.keys())
                            and (
                                cur_pressure_name_uuid_map[UUID(str(str_var))].location
                                in component_uuid_map
                            )
                            and (
                                cur_pressure_name_uuid_map[UUID(str(str_var))].id
                                == UUID(str(node))
                            )
                        ):
                            cur_pressure_name_uuid_map[
                                UUID(str(str_var))
                            ].pressure = self.solved_system[str_var_index]

                            self.graph.nodes[node]["pressure"] = self.solved_system[
                                str_var_index
                            ]

                            print(f"\n{str_var = }, {str_var_index = }")
                            print(
                                f"\n{self.solved_system[
                                str_var_index
                            ] = }\n"
                            )
                            print(f"\n{self.graph.nodes[node]["pressure"] = }")

                        elif (
                            (UUID(str(node)) in port_uuid_map.keys())
                            and (UUID(str_var) in cur_pressure_name_uuid_map.keys())
                            and (
                                cur_pressure_name_uuid_map[UUID(str(str_var))].location
                                in port_uuid_map
                            )
                            and (
                                port_uuid_map[
                                    cur_pressure_name_uuid_map[
                                        UUID(str(str_var))
                                    ].location
                                ]  # type: ignore
                                == UUID(str(node))
                            )
                        ):
                            cur_pressure_name_uuid_map[
                                UUID(str(str_var))
                            ].pressure = self.solved_system[str_var_index]

                            self.graph.nodes[node]["pressure"] = self.solved_system[
                                str_var_index
                            ]

                            print(f"\n{str_var = }, {str_var_index = }")
                            print(
                                f"\n{self.solved_system[
                                str_var_index
                            ] = }\n"
                            )
                            print(f"\n{self.graph.nodes[node]["pressure"] = }")
                            ...

        # // The final step is to assign the calculated values to the currents and
        # // local currents and, finally, to the nodes of the graph
        for str_var in self.string_var_list:
            # * vol_flow for local_cur from ports (nodes with port names)
            if (UUID(str_var) in port_uuid_map) and (
                port_uuid_map[UUID(str_var)].id in self.graph.nodes
            ):
                port_uuid_map[
                    UUID(str_var)
                ].local_current.volume_flow = self.solved_system[
                    self.string_var_list.index(str_var)
                ]

                self.graph.nodes[port_uuid_map[UUID(str_var)].id]["vol_flow"] = (
                    self.solved_system[self.string_var_list.index(str_var)]
                )

            # * vol_flow for original currents (nodes with orig_cur names)
            if (UUID(str_var) in current_uuid_map) and (
                current_uuid_map[UUID(str_var)].id in self.graph.nodes
            ):
                current_uuid_map[UUID(str_var)].volume_flow = self.solved_system[
                    self.string_var_list.index(str_var)
                ]

                self.graph.nodes[current_uuid_map[UUID(str_var)].id]["vol_flow"] = (
                    self.solved_system[self.string_var_list.index(str_var)]
                )

            # * pressure for local_cur from ports (nodes with port names)
            if (UUID(str_var) in cur_pressure_name_uuid_map) and (
                UUID(str_var) not in self.graph.nodes
            ):
                if not (
                    isinstance(
                        cur_pressure_name_uuid_map[UUID(str_var)].location, Iterable
                    )
                ) and (
                    cur_pressure_name_uuid_map[UUID(str_var)].location in port_uuid_map
                ):
                    port_uuid_map[
                        cur_pressure_name_uuid_map[UUID(str_var)].location
                    ].local_current.pressure = self.solved_system[  # type: ignore
                        self.string_var_list.index(str_var)
                    ]

                    self.graph.nodes[
                        port_uuid_map[
                            cur_pressure_name_uuid_map[UUID(str_var)].location
                        ].id  # type: ignore
                    ]["pressure"] = self.solved_system[
                        self.string_var_list.index(str_var)
                    ]

                if (
                    isinstance(
                        cur_pressure_name_uuid_map[UUID(str_var)].location, Iterable
                    )
                ) and (
                    cur_pressure_name_uuid_map[UUID(str_var)].location[1]  # type: ignore
                    in port_uuid_map
                ):
                    cur_pressure_name_uuid_map[
                        UUID(str_var)
                    ].pressure = self.solved_system[self.string_var_list.index(str_var)]

                    self.graph.nodes[
                        cur_pressure_name_uuid_map[UUID(str_var)].location[1]  # type: ignore
                    ]["pressure"] = self.solved_system[
                        self.string_var_list.index(str_var)
                    ]

            # * pressure for original currents (nodes with orig_cur names)
            if (UUID(str_var) in cur_pressure_name_uuid_map) and (
                cur_pressure_name_uuid_map[UUID(str_var)].id in self.graph.nodes
            ):
                cur_pressure_name_uuid_map[
                    UUID(str_var)
                ].volume_flow = self.solved_system[self.string_var_list.index(str_var)]

                self.graph.nodes[cur_pressure_name_uuid_map[UUID(str_var)].id][
                    "pressure"
                ] = self.solved_system[self.string_var_list.index(str_var)]

            if (UUID(str_var) in cur_pressure_name_uuid_map) and (
                UUID(str_var) in self.graph.nodes
            ):
                print(f"\n{cur_pressure_name_uuid_map[UUID(str_var)].location = }")
                print(f"\n{UUID(str_var) = }\n")
                print(
                    f"\n{self.graph.nodes[cur_pressure_name_uuid_map[UUID(str_var)].id] = }\n"
                )
                raise ValueError(
                    "\nThere should be no pressure variable that exists as a node inside the directed graph"
                )

        #! raise NotImplementedError(f"""\n\nPreciso garantir que essa parte está atribuindo
        #! todos os novos valores de forma correta para cada uma das variáveis
        #! calculadas. Preciso colocar uma checagem nessa parte acima para
        #! tentar entender por que os valores quase não foram alterados da primeira
        #! iteração até a ultima""")

    def automatic_solver(
        self,
        v_flow_guess=5,
        p_guess=200_000,
        generate_dir_graph: bool = False,
        data_in_dir_graph: bool = False,
        verify=True,
    ) -> None:
        r"""
        This method will be used as a simplifyed version of the equations solver,
        in a way that the usar dont need to call each part of the solve methods
        manually.

        this method may also include the plotting part of the solve steps.
        """

        self.create_graph_2()
        self.symple_q_p_guess(v_flow_guess, p_guess)
        self.equation_gathering_from_graph()

        freedom_deg_number = len(self.all_eq_variables) - len(self.equation_list)

        pprint(
            f"This is the number of degrees of freedom of the equation system \
            {freedom_deg_number = }"
        )

        self.equations_solver(verify=verify)

        if generate_dir_graph is True:
            plt.figure(1, figsize=(16, 12))  # figsize=(8, 6)

            # pos1 = nx.spring_layout(self.graph, k=3, seed=112)  # *seed=16

            # pos1 = nx.spring_layout(
            #     nx.to_undirected(self.graph), seed=12
            # )

            pos1 = nx.spring_layout(
                nx.to_undirected(self.graph), seed=12, iterations=100, scale=3
            )

            # // Desenha o grafo com o layout escolhido, mostrando as conexões (arestas)
            # nx.draw(
            #     self.graph,  # type: ignore
            #     pos1,
            #     with_labels=False,
            #     node_color="lightblue",
            #     node_size=500,
            #     font_size=18,
            #     font_color="black",
            #     edge_color="gray",
            #     arrows=True,
            #     connectionstyle="arc3,rad=0.2",
            # )

            nx.draw(
                nx.to_undirected(self.graph),
                pos1,
                with_labels=False,
                node_color="lightblue",
                node_size=500,
                font_size=12,
                font_color="black",
                edge_color="gray",
                arrows=True,
                # *connectionstyle="arc3,rad=0.2",
            )

            if data_in_dir_graph is True:
                # // Escrever aqui o codigo pra criar as labels de pressão e vol_flow
                # // pra cada um dos nós do gráfico

                # // Talvez eu precise criar uma nova propriedade para os nós
                # // eu acho q vou precisar criar a propriedade de elevação (z)
                labels = {
                    n: f"{n}\npressure={d.get("pressure")}\nvol_flow={d.get("vol_flow")}"
                    for n, d in self.graph.nodes(data=True)
                }

                nx.draw_networkx_labels(
                    self.graph,
                    pos1,
                    labels,
                    font_size=9,  # *font_size=18
                    font_color="black",
                )

            # * Mostra o gráfico
            plt.show(block=True)

    def reynolds_convergence_step(self):
        """
        in this method i'll check if i could use the subsequent reynolds values,
        so that i don't have to relly on the first guess value
        """

        # * I was planning to calculate the avg_pressure_delta as a weighted average (media ponderada)
        """
        
        n_P is the total number of P values inside the system
        Pi is the  pressure in some part of the system
        PT is the total pressure, and this is the summ of all the pressures of the lists
        
        w_P_avg = Sigma(Pi/Pt)
        
        I was thinking of another way of tdoing this.
        i could choose the just one point in the mosaic, to be the representative 
        of all the mosaic, and if the observated attribute (P or Q) of said point
        converges, i'll accept all other values as if they converged too.
        
        The other way to check the convergence is to set flag boolean vars, that
        will be initialised as False. if the attribute converges, the flag will
        be flipped to True.
        
        I could check on each and every iteration if all the flags are true.
        Once this happens a master flag would be flipped to True, and the code
        would get out of the while loop.
        
        There maybe a problem if the variables converge, and after the convergence,
        they start to diverge again. To prevent the flag to remain flipped to True,
        i need to implement a check in each iteration to determine if the attribute
        converged or diverged.
        
        The problem with this method is that the system does not have guaranteed
        convergencem and the system could remain in a state of divergence eternally.
        
        The only way to stop this is would be to implement the NR method in the
        matrix form manually, without rellying on the nsolve method.
        The problem with this method is that it takes a huge time to implement,
        and the implemented method may be prone to bugs, errors and also 
        convergence problems
        
        
        """
        # // By now, let's just use the boolean flags for all the points inside the
        # // system, as this is the most safe option, and it also has some chance of
        # // convergence

        # // The flags must be created using the UUIDs of the attributes they are
        # // wathcing. The name of each one must be created using UUID + _'flag'

        # // the flags must be created from the self.var_list, using a for loop
        # // it would be better if all the flags are stored inside a list or a dict
        # // The dict would hold the name of the flag, and the boolean value inside
        # // each one

        # // The Master flag must be deffinied out of the while loop

        # // inside the while loop, there must be an if block that states that if all
        # // the minor flags are flipped to true, the master flag must be flipped to
        # // True

        # // There may be a problem if i use the equations without gathering them
        # // again, from scrap from the equation_gathering()

        # *the parameters below should be dicts: dict[UUID, value]containing
        # *  each and every variables of the system (P and Q)

        actual_flows: list[float | int] = []
        previous_flows: list[float | int] = []

        actual_values_and_names: dict[float | int, UUID]

        actual_values: list[float | int] = []
        previous_values: list[float | int] = []

        # * This is the flag that will only be flipped to True if all flags from
        # * all_flags are True
        master_flag: bool = False

        # * The flags stored here will be used to determinate if the values for
        # * some attribute (like P or Q, in some point of the system)
        # * have converged or not
        #! If the value converges, but after convergence it starts to scilate
        #! again i have to make the boolean fot said variable flip to False again
        all_flags: dict[UUID, bool] = {}
        #! actual_pressures
        #! previous_pressures
        #! avg_pressure_delta

        # // Those variables will be used to control the loop manually, to analyse
        # // how is the convergence of each parameter going
        #! Those variables must be deleted after the code is running allwright
        #! THose are just for my use, and maybe other people that may work
        #! with the code in the future
        total_iterations = 10
        iterations_passed = 0

        while master_flag is False:
            print(f"\n---->{ iterations_passed = }\n")

            if all(flag == True for flag in all_flags.values()):
                print()

                master_flag = True

            elif iterations_passed == total_iterations:
                master_flag = True

            if iterations_passed < 1:
                print(f"\n----> self.symple_q_p_guess called{ iterations_passed = }\n")
                self.symple_q_p_guess()

            self.equation_gathering_from_graph()

            self.equations_solver()

            # // Do all things here

            iterations_passed += 1

        # * I was planning to calculate the avg_volume_flow_delta as a weighted average (media ponderada)
        #! avg_volume_flow_delta

        #! while ((delta >= nc.n_tol) and (>= nc.n_tol)):
        # // All the eqs_lis/dicts should be reseted, entirelly made empty
        #! self.all_eq_variables = {}
        #! self.equation_list
        #! self.equations_dict

        #! self.mass_eqs_list
        #! self.energy_var_list

        #! self.mass_var_list
        #! self.energy_var_list

        #! self.var_list
        #! self.mixed_eqs_list
        #! self.all_eq_variables

        #! self.all_pressure_names_in_self
        #! self.all_currents_in_self

        # // The new initial_values should be the values calculated in the
        # // previous iteration of the nsolve() solver
        #! The equations_solver_method already does this!

    def current_handling(self, component):
        """*opt feat
        This method will be used to handle the interaction between the currents and the components.

        In short, it will manage and register which current passes by which component.

        I should create an attribute in the components so that they have an attribute to show which
        current is passing through them.

        if two currents are mixed inside a component, this method should create a new current that
        'is born' inside said component, and flows downstream to the other ones.

        The currents that are in the beggining points of the mosaic should be passed to the
        components downstream.


        this is just to keep track of where each current passes, to make the correct calculation
        of the viscosity, density, velocity and pressure on the other methods.
        """

        def temperature_handle(component):
            """*opt feat?
            This function will calculate the thermal equilibrium temperature if there is a mixture
            in some of the currents,
            or if the composition is the same, but the temperatures of the currents entering a
            component is different

            the output currents will have the same temperature and pressure i guess, but only if
            on the outlet of one of
            them isn't a pump or something simmilar
            """

        ...

        def mass_handle(component): ...
        def velocity_handle(component): ...
        def pressure_handle(component): ...

        ...

    # The methods below here are the fundamental methods of this library, and are the ones that are required
    #! This method may be outdated, and may need to be deleted or refactored

    @DeprecationWarning
    def mass_conservation(self) -> None:
        """
        This method will be used to apply the mass conservation to each and every component inside some mosaic.

        It will calculate the correct velocities and mass/volume flows inside each current, and will also change the
        composition of each current to better represent the composition of the 'original' currents, so that each individual
        current composition has propperties such as temperature and pressure and the composition itself, true to the
        thermodynamics of the flow.

        This method is the first one that the mosaic should run to calculate the pressure loss
        """

        """
        This for block seems to be owrking good in the test of the mass conservation with me mosaic with just one Pipe
        and one Current (The most simple one).
        """

        from current import Current

        self.original_currents: List[Current] = []
        for joint in self.joints_list:
            for obj in joint:
                for cur in Current.current_objects:
                    if obj == cur.id:
                        """
                        The original currents are the ones that wasn't created as a propertty of a port, and are integrated
                        to the mosaic by joints with components.

                        I should start to solve the mass conservation equation by the components liked to them, those components
                        are called 'original components'.


                        """

                        self.original_currents.append(cur)

                        # print(f"\nThe {cur.id = } original_current was found!")

                    else:
                        print("\nno original current found")
                        pass

        print(f"\nOrignal Currents found: {self.original_currents = }\n\n")

        self.joints_with_original_currents: list[list] = []
        for cur in self.original_currents:
            for joint in self.joints_list:
                if cur.id in joint:  # or (cur.id in pair for pair in joint):
                    self.joints_with_original_currents.append(joint)

                    # print(f"\n{joint = } original_joint was found!")

                else:
                    print("\nNo original joint found")
                    pass

        print(f"\nOrignal Joints found: {self.joints_with_original_currents = }\n\n")

        from logic_utils import is_iterable

        # TODO: [High]
        # This block should have some problem
        self.original_components: list[components.Component] = []

        for cur in self.original_currents:
            match is_iterable(cur.location):
                case True:
                    for obj in cur.location:
                        if isinstance(obj, UUID) == True:
                            # print(
                            #     f"\n * The {obj = } inside the tuple location is an UUID"
                            # )
                            for comp in components.Component.component_objects:
                                if comp.id == obj:
                                    # print("\n\n - This part finally run, congrats")

                                    self.original_components.append(comp)
                                    # print(
                                    #     f"\n\nThe self.orig_components recieved the {comp.id = } component"
                                    # )

                                else:
                                    print("\n\nnot this time champ")
                        else:
                            raise TypeError(f"\n\n{type(obj) = }")

                case False if isinstance(cur.location, UUID):
                    for comp in components.Component.component_objects:
                        if comp.id == current.location:
                            self.original_components.append(comp)
                        else:
                            print("\n comp does not match current.location")
                            pass

        print(f"\nOriginal Components found: {self.original_components = }\n\n")

        # return 'everything is ok untill this part'

        """
        After classifying all the original componets, i still have to choose the first of them so that i can start the
        mass conservation by this one.

        I guess that i'll just have to choose the first one. and solve the other things later on.

        if some original component leads to a component which has more than one outlet and/or more than one inlet, and to
        determinate the inlet the software will need to solve an entire branch of pipes, i'll make it do so.

        I'll check if the composition of said outlet current is already setted to be equal to the original current.

        If the composition of the inlet current is None, i'll 'climb it's branch so that the seraching stops when i hit an
        original current. Than i'll solve this original current and all of its componets downstream, untill it has reached the
        component that needed all this branch calculation.

        This process will repeat untill every non-original current has its composition (and velocities, mass flow and volume
        flow)different than None.
        """

        self.orig_components_sorted_by_port_quantity = sorted(
            self.original_components, key=lambda comp: comp.port_quantity
        )

        self.two_port_orig_components = []
        self.three_port_orig_components = []
        self.four_port_orig_components = []
        self.five_port_orig_components = []
        self.six_port_orig_components = []

        for comp in self.orig_components_sorted_by_port_quantity:
            if comp.port_quantity == 2:
                # those are the origninal components with two ports
                self.two_port_orig_components = []
                self.two_port_orig_components.append(comp)

            if comp.port_quantity == 3:
                # those are the origninal components with three ports
                self.three_port_orig_components = []
                self.three_port_orig_components.append(comp)

            if comp.port_quantity == 4:
                # those are the origninal components with four ports
                self.four_port_orig_components = []
                self.four_port_orig_components.append(comp)

            if comp.port_quantity == 5:
                # those are the origninal components with five ports
                self.five_port_orig_components = []
                self.five_port_orig_components.append(comp)

            if comp.port_quantity == 6:
                # those are the origninal components with six ports
                self.six_port_orig_components = []
                self.six_port_orig_components.append(comp)

        print(f"\n{self.two_port_orig_components = }")
        print(f"\n{self.three_port_orig_components = }")
        print(f"\n{self.four_port_orig_components = }")
        print(f"\n{self.five_port_orig_components = }")
        print(f"\n{self.six_port_orig_components = }")

        self.all_orig_components_sorted_by_port_quantity = [
            self.two_port_orig_components,
            self.three_port_orig_components,
            self.four_port_orig_components,
            self.five_port_orig_components,
            self.six_port_orig_components,
        ]

        def two_port_serial_comp_counter(orig_comp: components.Component):
            """
            This function will be used to count how many components with two ports are connected in series with some
            orignal component.

            It will be used to determinate the orden in which the different components should have its mass conservation
            calculated, sothat the mosaic doesn't have any blind spots where the mass conservation is lacking after the
            mass conservation is calculated inside all of the elements of the mosaic
            """

            """
            # for comp in self.two_port_orig_components:

            #     def two_port_comp_chain_detection(comp = comp):
            #         #This function detects what is the number of components with 2 ports chained to some original component
            #         number_of_serial_2_port_comp_chain_after_2_port_orig_comp = 0

            #         list_of_2p_seriam_comp = []
            #         list_of_2p_seriam_comp.append(comp)

            #         import current

            #         for joint in self.joints_list:
            #             for obj in joint:
            #                 for id in obj:
            #                     if id == comp.id:
            #                         #
            #                         Eu preciso lembrar de subtrair 1 do numero de objetos de duas portas em serie, por causa
            #                         da forma como eu criei a contagem. Como uma das jutnas vai ter a conexão do componente
            #                         original com a corrente ela deve ser desconsiderada, e por isso eu preciso pegar o numero
            #                         de componentes de duas portas em serie e somar -1 (n - 1 = numero certo).

            #                         Uma outra forma de fazer isso seria só tentar ignorar essa conexão com uma corrente,
            #                         detectando quando ela acontecer e deixando ela passar.
            #                         
            #                         for current in current.Current.current_objects:
            #                             if current.id in joint:
            #                                 pass
                                        
            #                             #TODO: Essa parte é crítica, preciso arrumar para que o codigo funcione
            #                             
            #                             Essa vai ser a condição que vai verificar se o outro objeto dentro de uma junta é
            #                             um component com duas portas

            #                             Eu percebi um erro meu, é que eu preciso aplicar os loops seguintes para o componente
            #                             ligado a comp (que vem da função) e não ao comp em si, talvez eu tenha que criar uma lista
            #                             dos componentes ligados ao comp, e ir adicionando a ela cada uma dos componentes
            #                             que tiverem duas portas e estiverem direta ou indiretamente ligados ao comp em serie
            #                            

            #                             for component in components.Component.component_objects:
            #                                 if (joint[1] == component.id) and (component.port_quantity == 2):
            #                                     number_of_serial_2_port_comp_chain_after_2_port_orig_comp += 1
            #                                     list_of_2p_seriam_comp.append(component)
                                            
            #                                 else:
            #                                     pass

            #                     else:
            #                         pass
                        
            #             return list_of_2p_seriam_comp, number_of_serial_2_port_comp_chain_after_2_port_orig_comp

            #     # subsituir essa porte por algo desse tipo: sorted(self.original_components, key = lambda comp: comp.port_quantity)
            #     # usar como key function a função two_port_comp_chain_detection(comp = comp)
            #     list(map(two_port_comp_chain_detection, some_comp_list))
                    

        #the orig_comp_should be put inside the list below in order from the greater to the smaller number of members
        # of other 2 port components chained to it
        #self.orig_components_ordered_by_number_of_2_port_serial_components_connected: list[components.Component]
            """

            import current as current
            import logic_utils as logic_utils

            """
            List growing is the parameter that sees if the list of 2p_serial_components connected to some original
            component stays growing. If the list don't grow, it will mean that the chain of 2p components has come to an
            end, and something stopped the list from growing. The things that stops the list from growing are a dead end
            or a component with more than 2p.

            If thee code sees some of these two things, it must shift the list_growing boolean to false.
            """

            chained_2p_components = [orig_comp]

            is_list_growing = True

            some_index = 0

            while is_list_growing == True:
                print("\n chainlink_counter while loop entered")
                old_size = len(chained_2p_components)

                # this is the last item inside the list, so i should verify if the mosaic has a joint registering the
                # union of the las t item inside the list with other component
                for joint_index, joint in enumerate(self.joints_list):
                    for obj_index, obj in enumerate(joint):
                        if (is_iterable(obj) == True) and (
                            all(isinstance(thing, UUID) == True for thing in obj)
                            == True
                        ):
                            print(
                                "\n\nThe obj reading now is iterable and every element inside it is a UUID"
                            )
                            for id_index, id in enumerate(obj):
                                # If the shained comp id is inside the joints_list, the next step is to verify if
                                # there is something linked to it, and the third step is to verify if the linked component
                                # has just two ports

                                # and (any())
                                if (id == chained_2p_components[-1].id) and (
                                    len(joint) == 2
                                ):
                                    print(f"\n\nThe {id = } was found")

                                    if obj_index == 0 and is_iterable(
                                        joint[obj_index + 1]
                                    ):
                                        # print(
                                        #     "\n\n The second object inside the joint is iterable"
                                        # )
                                        for thing in joint[obj_index + 1]:
                                            for (
                                                comp
                                            ) in components.Component.component_objects:
                                                if (
                                                    (thing == comp.id)
                                                    and (
                                                        comp
                                                        not in chained_2p_components
                                                    )
                                                    and (len(comp.component_ports) == 2)
                                                ):
                                                    # print(
                                                    #     f"\n\n=========== {comp.id = } added to the list ==========="
                                                    # )
                                                    chained_2p_components.append(comp)

                                                else:
                                                    print(
                                                        "--------- no chainlink found ---------"
                                                    )

                                                    pass

                                    elif obj_index == 1 and is_iterable(
                                        joint[obj_index - 1]
                                    ):
                                        # print(
                                        #     "\n\n The first object inside the joint is iterable"
                                        # )
                                        pass
                                        # for thing in joint[obj_index - 1]:
                                        #     for comp in components.Component.component_objects:
                                        #         if ((thing == comp.id) and (comp not in chained_2p_components)\
                                        #             and (len(comp.component_ports) == 2)):

                                        #             chained_2p_components.append(comp)

                                elif len(joint) > 2:
                                    raise ValueError(
                                        f"The {joint = } has more than two elements"
                                    )

                                else:
                                    pass

                        elif is_iterable(obj) is False:
                            pass

                    """
                for chain_link_index, chain_link in enumerate(chained_2p_components):
                
                    for joint_index, joint in enumerate(self.joints_list):

                        for obj_index, obj in enumerate(joint):

                            print(f'\n{chain_link_index = } {chain_link = }')
                            print(f'\n{joint_index = } {chain_link = }')
                            print(f'\n{obj_index = } {obj = }')
                            print(f'\n{chained_2p_components = }')
                            print(f'\n{list_growing = } {chain_link = }')
                        
                            # This part ensure that the first and second objects of a joint are components, because of the
                            #format of them inside the joint, which is a list or tuple of a component id and a port id
                            # if ((isinstance(joint[0], list) == True and isinstance(joint[1], list) == True) or\
                            # (isinstance(joint[0], tuple) == True and isinstance(joint[1], list) == tuple) or\
                            # (isinstance(joint[0], tuple) == True and isinstance(joint[1], list) == list)) or\
                            # (isinstance(joint[0], list) == True and isinstance(joint[1], list) == tuple):
                                
                            if (logic_utils.is_iterable(obj) == True):

                            #if (isinstance(obj, list) == True) or (isinstance(obj, tuple)):
                                for id_index, id in enumerate(obj):
                                    if isinstance(id, UUID) == True:
                                        for comp_index, comp in enumerate(self.original_components):

                                            #As iterações precisam andar pelos elementos da lista de componentes de duas portas
                                            #encadeados com algum componente original
                                            # Eu não sei se eu coloco o for loop abaixo no topo ou em algum liugar aqui do meio
                                            #do loop while, preciso pensar mais sobre isso

                                            if id == chained_2p_components[chain_link_index].id:
                                            # This part checks if the other thing inside a joint with an original component
                                            #is a component
                                                for component in components.Component.component_objects:
                                                    if ((isinstance(self.joints_list[joint_index][obj_index], UUID) == False)and\
                                                        (component.id == self.joints_list[joint_index][obj_index][id_index])and\
                                                        (component not in chained_2p_components)and\
                                                        (len(component.component_ports) == 2)):

                                                        chained_2p_components.append(component)

                                                    #TODO: This break criteria needs revision

                                                    #?
                                                    elif ((isinstance(self.joints_list[joint_index][obj_index], UUID) == False)and\
                                                        (component.id == self.joints_list[joint_index][obj_index][id_index])and\
                                                        (component not in chained_2p_components)and\
                                                        ((len(component.component_ports) != 2))):

                                                        list_growing = False
                                                    #?
                                            else:
                                                if list_growing == False:
                                                    break

                                                pass        

                                    else:
                                        raise TypeError(f'The {id = } ({id_index = }, {joint_index = }, {obj_index = }) is not an UUID')
                        
                            else:
                                if list_growing == False:
                                    break
                                # Se alguma junta não for do tipo de junta entre dois componentes, eu não preciso ver ela
                                pass
                        
                        if list_growing == False:
                            break

                    if list_growing == False:
                        break
                    
                        """
                    # if isinstance(obj, UUID) == True:
                    #     for current_index, current in enumerate(current.Current.current_objects):
                    #         if obj == current.id:
                    """
                    """

                new_size = len(chained_2p_components)

                if new_size == old_size:
                    is_list_growing = False

                else:
                    pass

                # In this line, there should be something to check if the list grew, and if it doesn't, it should flip
                # the list_grwing bool to False. This piece of code should be the last one inside the loop, after every
                # other things had been run
                some_index += 1

            print(f"\n\n{chained_2p_components = }")

            return chained_2p_components
            self.two_port_orig_components

        # for list_id, list in enumerate(self.all_orig_components_sorted_by_port_quantity):
        #     for comp in list:

        def len_chainlink_counter(iten):
            chain_list = two_port_serial_comp_counter(iten)
            return len(chain_list)

        self.final_2p_orig_comp = list(
            map(
                two_port_serial_comp_counter,
                self.all_orig_components_sorted_by_port_quantity[0],
            )
        )

        print(f"\n\n{list(self.final_2p_orig_comp) = }\n\n")

        self.final_sorted_2p_orig_comps = sorted(
            self.all_orig_components_sorted_by_port_quantity[0],
            key=len_chainlink_counter,
        )
        self.final_sorted_3p_orig_comps = sorted(
            self.all_orig_components_sorted_by_port_quantity[1],
            key=len_chainlink_counter,
        )
        self.final_sorted_4p_orig_comps = sorted(
            self.all_orig_components_sorted_by_port_quantity[2],
            key=len_chainlink_counter,
        )
        self.final_sorted_5p_orig_comps = sorted(
            self.all_orig_components_sorted_by_port_quantity[3],
            key=len_chainlink_counter,
        )
        self.final_sorted_6p_orig_comps = sorted(
            self.all_orig_components_sorted_by_port_quantity[4],
            key=len_chainlink_counter,
        )

        self.final_all_orig_components_sorted_by_port_quantity = [
            self.final_sorted_2p_orig_comps,
            self.final_sorted_3p_orig_comps,
            self.final_sorted_4p_orig_comps,
            self.final_sorted_5p_orig_comps,
            self.final_sorted_6p_orig_comps,
        ]

        """for chain_link_id, link in enumerate(self.final_2p_orig_comp):
            for two_p_comp in self.final_sorted_2p_orig_comps[chain_link_id]:
                #print(f'\n\n---------> {self.final_sorted_2p_orig_comp = }')
                print(f'\ntwo_p_comp.mass_conservation() Running')
                two_p_comp.mass_conservation()

        for two_p_comp in self.final_sorted_2p_orig_comps:
            two_p_comp.mass_conservation()"""

        for socl_id, sorted_orig_comp_list in enumerate(
            self.final_all_orig_components_sorted_by_port_quantity
        ):
            print(f"\n\n{socl_id+2 = }p_sorted_comp_list")

            for comp in sorted_orig_comp_list:
                # print(f"\n\nmass conservation for {comp.id = } component running")
                comp.mass_conservation()

        # for three_p_comp in self.final_sorted_3p_orig_comp:
        #     three_p_comp.mass_conservation()

        # for four_p_comp in self.final_sorted_4p_orig_comp:
        #     four_p_comp.mass_conservation()

        # for five_p_comp in self.final_sorted_5p_orig_comp:
        #     five_p_comp.mass_conservation()

        # for six_p_comp in self.final_sorted_6p_orig_comp:
        # six_p_comp.mass_conservation()

    def npsh(self) -> float:
        """
        This method will be used to calculate the Net Pressure Suction Head in any of the components throughout the mosaic, given
        the desired component.

        The component shoud be passed to this method as an argument, so that the method knows where to calculate the
        NPSH.

        By standard, this method will calculate the NPSH in the output port of the component, but the user
        can pass the location as a **kwarg so that the method knows if the user whants to calculate on the input, output,
        or exactly in the middle of the component (in the case it's a pipe).
        """
        ...

    def pressure(self) -> float:
        """
        This method will be used to calculate the Pressure in any of the components throughout the mosaic, given
        the desired component.

        The component shoud be passed to this method as an argument, so that the method knows where to calculate the
        Pressure.

        By standard, this method will calculate the pressure in the output port of the component, but the user
        can pass the location as a **kwarg so that the method knows if the user whants to calculate on the input, output,
        or exactly in the middle of the component (in the acse it's a pipe).
        """
        ...

    def velocity(self) -> float:
        """
        This method will be used to calculate the velocity in any of the components throughout the mosaic, given
        the desired component.

        The component shoud be passed to this method as an argument, so that the method knows where to calculate the
        Pressure

        By standard, this method will calculate the pressure in the output port of the component, but the user
        can pass the location as a **kwarg so that the method knows if the user whants to calculate on the input, output,
        or exactly in the middle of the component (in the acse it's a pipe).
        """
        ...

    def mass_flow_rate(self) -> float:
        """
        This method will be used to calculate the mass_flow_rate in any of the components throughout the mosaic, given
        the desired component.

        The component shoud be passed to this method as an argument, so that the method knows where to calculate the
        Pressure

        By standard, this method will calculate the pressure in the output port of the component, but the user
        can pass the location as a **kwarg so that the method knows if the user whants to calculate on the input, output,
        or exactly in the middle of the component (in the acse it's a pipe).
        """
        ...

    def volume_flow_rate(self) -> float:
        """ """
        ...

    def pressure_drop(self) -> float:
        """
        This method will be used to calculate the mechanic energy loss in terms of pressure in any of the components
        throughout the mosaic, given the desired component.

        The component shoud be passed to this method as an argument, so that the method knows where to calculate the
        Pressure drop.

        By standard, this method will calculate the pressure drop in the output port of the component, but the user
        can pass the location as a **kwarg so that the method knows if the user whants to calculate on the input, output,
        or exactly in the middle of the component (in the acse it's a pipe).
        """
        ...

    def head_loss(self) -> float:
        """
        This method will be used to calculate the mechanic energy loss in terms of manometric length, similar to the
        pressure drop method
        """
        ...

    # The methods below here are the optional methods of this library, and must be made ONLY after i finish all the other
    # ones

    def avg_reynolds(self) -> float:
        """
        This method should recieve two components inside a mosaic to calculate the reynolds number in all the components
        in the middle of them, and calculate the average reynolds number.

        The average should be made using the arithmetic average, like described below:

        avg_reyn = (r_1 + r_2 + ... + r_n) / n
        """
        ...

    def total_length(self): ...
