        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        dashboard_class: AbstractServiceNowTask = SingleChartMinMaxRetrievalTask,
        question: str = None,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        self.order_item_class = OrderLoanerLaptopTask
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=dashboard_class,
            question=question,
            min_catalog_item="Loaner Laptop",
        )

class DashboardRetrieveCatalogAndMaxOrderLoanerLaptopTask(
    DashboardRetrieveCatalogAndOrderLoanerLaptopTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMinMaxRetrievalTask,
            question="max",
        )

class DashboardRetrieveCatalogAndMeanOrderLoanerLaptopTask(
    DashboardRetrieveCatalogAndOrderLoanerLaptopTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,


    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMinMaxRetrievalTask,
            question="max",
        )

class DashboardRetrieveCatalogAndMeanOrderLoanerLaptopTask(
    DashboardRetrieveCatalogAndOrderLoanerLaptopTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMeanMedianModeRetrievalTask,
            question="mean",
        )

class DashboardRetrieveCatalogAndMedianOrderLoanerLaptopTask(
    DashboardRetrieveCatalogAndOrderLoanerLaptopTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,


    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMeanMedianModeRetrievalTask,
            question="mean",
        )

class DashboardRetrieveCatalogAndMedianOrderLoanerLaptopTask(
    DashboardRetrieveCatalogAndOrderLoanerLaptopTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMeanMedianModeRetrievalTask,
            question="median",
        )

class DashboardRetrieveCatalogAndModeOrderLoanerLaptopTask(
    DashboardRetrieveCatalogAndOrderLoanerLaptopTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,


    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMeanMedianModeRetrievalTask,
            question="median",
        )

class DashboardRetrieveCatalogAndModeOrderLoanerLaptopTask(
    DashboardRetrieveCatalogAndOrderLoanerLaptopTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMeanMedianModeRetrievalTask,
            question="mode",
        )

local_vars = locals().copy()

__TASKS__ = [
    var
    for var in local_vars.values()
    if isinstance(var, type) and issubclass(var, DashDoFinalTask) and var is not DashDoFinalTask
]

DASH_AND_ORDER = [
    DashboardRetrieveCatalogAndMaxOrderDeveloperLaptopTask,
    DashboardRetrieveCatalogAndMaxOrderiPadMiniTask,
    DashboardRetrieveCatalogAndMaxOrderiPadProTask,
    DashboardRetrieveCatalogAndMaxOrderSalesLaptopTask,
    DashboardRetrieveCatalogAndMaxOrderStandardLaptopTask,
    DashboardRetrieveCatalogAndMaxOrderAppleWatchTask,
    DashboardRetrieveCatalogAndMaxOrderAppleMacbookPro15Task,
    DashboardRetrieveCatalogAndMaxOrderDevelopmentLaptopPCTask,
    DashboardRetrieveCatalogAndMaxOrderLoanerLaptopTask,


        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMeanMedianModeRetrievalTask,
            question="median",
        )

class DashboardRetrieveCatalogAndModeOrderLoanerLaptopTask(
    DashboardRetrieveCatalogAndOrderLoanerLaptopTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve information based on incidents from the dashboard and do the task.
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            dashboard_class=SingleChartMeanMedianModeRetrievalTask,
            question="mode",
        )

local_vars = locals().copy()

__TASKS__ = [
    var
    for var in local_vars.values()
    if isinstance(var, type) and issubclass(var, DashDoFinalTask) and var is not DashDoFinalTask
]

DASH_AND_ORDER = [
    DashboardRetrieveCatalogAndMaxOrderDeveloperLaptopTask,
    DashboardRetrieveCatalogAndMaxOrderiPadMiniTask,
    DashboardRetrieveCatalogAndMaxOrderiPadProTask,
    DashboardRetrieveCatalogAndMaxOrderSalesLaptopTask,
    DashboardRetrieveCatalogAndMaxOrderStandardLaptopTask,
    DashboardRetrieveCatalogAndMaxOrderAppleWatchTask,
    DashboardRetrieveCatalogAndMaxOrderAppleMacbookPro15Task,
    DashboardRetrieveCatalogAndMaxOrderDevelopmentLaptopPCTask,
    DashboardRetrieveCatalogAndMaxOrderLoanerLaptopTask,


import random
from playwright.sync_api._generated import Page
from typing import Tuple

from .dash_do_base import DashboardRetrieveIncidentAndDoInfeasibleTask, DashDoFinalTask
from .utils.infeasible_configs import get_infeasible_form_config

from ..base import AbstractServiceNowTask
from ..dashboard import SingleChartMinMaxRetrievalTask

from ...api.utils import table_api_call, db_delete_from_table
from ...instance import SNowInstance

from browsergym.workarena.tasks.navigation import AllMenuTask
from browsergym.workarena.tasks.form import CreateIncidentTask

class DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask(
    DashboardRetrieveIncidentAndDoInfeasibleTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
        provide_reason: bool = True,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
            function=get_infeasible_form_config,
            provide_reason=provide_reason,
        )
        self.task_description = ""
        self.short_description = (
            "Create an incident for the worst performing employee from the list."
        )
        self.filter_than = "lesser"
        self.attribute_name = "assigned_to"
        self.prefix = "ICI"

    def set_compositional_task(self) -> None:
        # The unique name for the user is created once the task is instantiated
        base_user = table_api_call(
            instance=self.instance,
            table="sys_user",
            params={
                "sysparm_query": f"sys_id={self._base_user_sysid}",
            },
        )["result"][0]
        self.user_name = base_user["first_name"] + " " + base_user["last_name"]

        agent_full_names, agent_value_sysids = self.get_agent_values(
            self.attribute_name, self.filter_than
        )
        self.agent_value_sysids = agent_value_sysids
        incident_numbers = []
        for _ in range(len(agent_full_names)):
            incident_number = "INC" + str(random.randint(1000000, 9999999))
            while (
                incident_number in self.all_incident_numbers or incident_number in incident_numbers
            ):
                incident_number = "INC" + str(random.randint(1000000, 9999999))
            incident_numbers.append(incident_number)

        self.incident_numbers = incident_numbers

        create_incident_subtasks = []

        for agent_full_name, incident_number in zip(agent_full_names, incident_numbers):
            incident_config = {
                "fields": {
                    "caller_id": "Caller",
                    "category": "Category",
                    "description": "Description",
                    "short_description": "Short description",
                    "impact": "Impact",
                    "number": "Number",
                    "urgency": "Urgency",
                    "assigned_to": "Assigned to",
                },
                "task_fields": [
                    "caller_id",
                    "category",
                    "description",
                    "short_description",
                    "impact",
                    "number",
                    "urgency",
                    "assigned_to",
                ],
                "template_record": {
                    "caller_id": self.user_name,
                    "category": "Inquiry / Help",
                    "description": "Compulsory training for employee in probation",
                    "short_description": "Compulsory training for employee in probation",
                    "impact": "1 - High",
                    "number": incident_number,
                    "urgency": "1 - High",
                    "assigned_to": agent_full_name,
                },
                "infeasible_task_fields": [
                    "category",
                    "description",
                    "short_description",
                    "impact",
                    "number",
                ],
            }

            incident_config, self.infeasible_reasons = self.function(
                config=incident_config, random=self.random
            )

            create_incident_subtask = [
                # Navigate to the incident list
                AllMenuTask(
                    instance=self.instance,
                    fixed_config={
                        "application": "Service Desk",
                        "module": "Incidents",
                        "url": "/now/nav/ui/classic/params/target/incident_list.do",
                    },
                    is_validated=False,
                    used_in_level_2=True,
                    has_description=False,
                ),
                # Create an incident
                CreateIncidentTask(
                    instance=self.instance,
                    fixed_config=incident_config,
                    is_validated=False,
                    used_in_level_2=True,
                    check_record_created=False,
                    has_description=True,
                ),
            ]
            create_incident_subtasks += create_incident_subtask

        self.compositional_task = create_incident_subtasks

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self.create_report()
        self.set_compositional_task()
        config = self.fixed_config if self.fixed_config else self._get_config()
        incident_numbers_string = ", ".join(self.incident_numbers)

        if self.level == 3:
            self.task_description = (
                self.task_description
                + f"Value to retrieve: {self.description_mapping[self.question]} of all the incidents. Comparator: Less than or equal to the value.\n"
                + f"Task: Create incidents with the following information: \n"
                + f"Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation', Caller: '{self.user_name}'.\n"
                + f"Assign the incidents you create to the agents mentioned above. You can use the incident numbers: {incident_numbers_string}, one for each."
            )

        goal, info = super().setup_goal(
            page=page, config=config, build_pretty_print_description=False
        )

        if self.level == 2:
            goal = (
                self.task_description
                + f"\n1. Navigate to the CMDB reports and look for the report with the mentioned hashtag. \n"
                + f"\n2. Find the agents with number of incidents less than or equal to the  {self.description_mapping[self.question]} of the incidents assigned to every one. \n"
                + f"\n3. Navigate to Service Desk > Incidents. \n"
                + f"\n4. Create new incidents with the following field values:- Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation' and assign them to each of the agents. You will create as many incidents as there are agents.\n"
                + f"\nYou should use the following incident numbers for each incident (one for each): {incident_numbers_string}."
            )

        return goal, info

    def teardown(self) -> None:
        for incident_number in self.incident_numbers:
            created_incident_response = table_api_call(
                instance=self.instance,
                table="incident",
                params={
                    "sysparm_query": f"number={incident_number}",
                },
                method="GET",
            )["result"]
            if len(created_incident_response) > 1:
                raise Exception("Multiple incidents created")
            if len(created_incident_response) == 1:
                created_incident_sysid = created_incident_response[0]["sys_id"]
                db_delete_from_table(
                    instance=self.instance,
                    table="incident",
                    sys_id=created_incident_sysid,
                )

        return super().teardown()

class DashboardRetrieveIncidentAndMinCreateIncidentInfeasibleWithReasonTask(
    DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 3,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question="min",
            dashboard_class=SingleChartMinMaxRetrievalTask,
            provide_reason=True,
        )

class DashboardRetrieveIncidentAndMinCreateIncidentInfeasibleTask(
    DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question="min",
            dashboard_class=SingleChartMinMaxRetrievalTask,
            provide_reason=False,
        )

local_vars = locals().copy()

__TASKS__ = [
    var
    for var in local_vars.values()
    if isinstance(var, type) and issubclass(var, DashDoFinalTask) and var is not DashDoFinalTask
]


import random
from playwright.sync_api._generated import Page
from typing import Tuple

from .dash_do_base import DashboardRetrieveIncidentAndDoInfeasibleTask, DashDoFinalTask
from .utils.infeasible_configs import get_infeasible_form_config

from ..base import AbstractServiceNowTask
from ..dashboard import SingleChartMinMaxRetrievalTask

from ...api.utils import table_api_call, db_delete_from_table
from ...instance import SNowInstance

from browsergym.workarena.tasks.navigation import AllMenuTask
from browsergym.workarena.tasks.form import CreateIncidentTask

class DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask(
    DashboardRetrieveIncidentAndDoInfeasibleTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
        provide_reason: bool = True,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
            function=get_infeasible_form_config,
            provide_reason=provide_reason,
        )
        self.task_description = ""
        self.short_description = (
            "Create an incident for the worst performing employee from the list."
        )
        self.filter_than = "lesser"
        self.attribute_name = "assigned_to"
        self.prefix = "ICI"

    def set_compositional_task(self) -> None:
        # The unique name for the user is created once the task is instantiated
        base_user = table_api_call(
            instance=self.instance,
            table="sys_user",
            params={
                "sysparm_query": f"sys_id={self._base_user_sysid}",
            },
        )["result"][0]
        self.user_name = base_user["first_name"] + " " + base_user["last_name"]

        agent_full_names, agent_value_sysids = self.get_agent_values(
            self.attribute_name, self.filter_than
        )
        self.agent_value_sysids = agent_value_sysids
        incident_numbers = []
        for _ in range(len(agent_full_names)):
            incident_number = "INC" + str(random.randint(1000000, 9999999))
            while (
                incident_number in self.all_incident_numbers or incident_number in incident_numbers
            ):
                incident_number = "INC" + str(random.randint(1000000, 9999999))
            incident_numbers.append(incident_number)

        self.incident_numbers = incident_numbers

        create_incident_subtasks = []

        for agent_full_name, incident_number in zip(agent_full_names, incident_numbers):
            incident_config = {
                "fields": {
                    "caller_id": "Caller",
                    "category": "Category",
                    "description": "Description",
                    "short_description": "Short description",
                    "impact": "Impact",
                    "number": "Number",
                    "urgency": "Urgency",
                    "assigned_to": "Assigned to",
                },
                "task_fields": [
                    "caller_id",
                    "category",
                    "description",
                    "short_description",
                    "impact",
                    "number",
                    "urgency",
                    "assigned_to",
                ],
                "template_record": {
                    "caller_id": self.user_name,
                    "category": "Inquiry / Help",
                    "description": "Compulsory training for employee in probation",
                    "short_description": "Compulsory training for employee in probation",
                    "impact": "1 - High",
                    "number": incident_number,
                    "urgency": "1 - High",
                    "assigned_to": agent_full_name,
                },
                "infeasible_task_fields": [
                    "category",
                    "description",
                    "short_description",
                    "impact",
                    "number",
                ],
            }

            incident_config, self.infeasible_reasons = self.function(
                config=incident_config, random=self.random
            )

            create_incident_subtask = [
                # Navigate to the incident list
                AllMenuTask(
                    instance=self.instance,
                    fixed_config={
                        "application": "Service Desk",
                        "module": "Incidents",
                        "url": "/now/nav/ui/classic/params/target/incident_list.do",
                    },
                    is_validated=False,
                    used_in_level_2=True,
                    has_description=False,
                ),
                # Create an incident
                CreateIncidentTask(
                    instance=self.instance,
                    fixed_config=incident_config,
                    is_validated=False,
                    used_in_level_2=True,
                    check_record_created=False,
                    has_description=True,
                ),
            ]
            create_incident_subtasks += create_incident_subtask

        self.compositional_task = create_incident_subtasks

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self.create_report()
        self.set_compositional_task()
        config = self.fixed_config if self.fixed_config else self._get_config()
        incident_numbers_string = ", ".join(self.incident_numbers)

        if self.level == 3:
            self.task_description = (
                self.task_description
                + f"Value to retrieve: {self.description_mapping[self.question]} of all the incidents. Comparator: Less than or equal to the value.\n"
                + f"Task: Create incidents with the following information: \n"
                + f"Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation', Caller: '{self.user_name}'.\n"
                + f"Assign the incidents you create to the agents mentioned above. You can use the incident numbers: {incident_numbers_string}, one for each."
            )

        goal, info = super().setup_goal(
            page=page, config=config, build_pretty_print_description=False
        )

        if self.level == 2:
            goal = (
                self.task_description
                + f"\n1. Navigate to the CMDB reports and look for the report with the mentioned hashtag. \n"
                + f"\n2. Find the agents with number of incidents less than or equal to the  {self.description_mapping[self.question]} of the incidents assigned to every one. \n"
                + f"\n3. Navigate to Service Desk > Incidents. \n"
                + f"\n4. Create new incidents with the following field values:- Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation' and assign them to each of the agents. You will create as many incidents as there are agents.\n"
                + f"\nYou should use the following incident numbers for each incident (one for each): {incident_numbers_string}."
            )

        return goal, info

    def teardown(self) -> None:
        for incident_number in self.incident_numbers:
            created_incident_response = table_api_call(
                instance=self.instance,
                table="incident",
                params={
                    "sysparm_query": f"number={incident_number}",
                },
                method="GET",
            )["result"]
            if len(created_incident_response) > 1:
                raise Exception("Multiple incidents created")
            if len(created_incident_response) == 1:
                created_incident_sysid = created_incident_response[0]["sys_id"]
                db_delete_from_table(
                    instance=self.instance,
                    table="incident",
                    sys_id=created_incident_sysid,
                )

        return super().teardown()

class DashboardRetrieveIncidentAndMinCreateIncidentInfeasibleWithReasonTask(
    DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 3,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"


                instance=self.instance,
                table="incident",
                params={
                    "sysparm_query": f"number={incident_number}",
                },
                method="GET",
            )["result"]
            if len(created_incident_response) > 1:
                raise Exception("Multiple incidents created")
            if len(created_incident_response) == 1:
                created_incident_sysid = created_incident_response[0]["sys_id"]
                db_delete_from_table(
                    instance=self.instance,
                    table="incident",
                    sys_id=created_incident_sysid,
                )

        return super().teardown()

class DashboardRetrieveIncidentAndMinCreateIncidentInfeasibleWithReasonTask(
    DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 3,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question="min",
            dashboard_class=SingleChartMinMaxRetrievalTask,
            provide_reason=True,
        )

class DashboardRetrieveIncidentAndMinCreateIncidentInfeasibleTask(
    DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"


        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question="min",
            dashboard_class=SingleChartMinMaxRetrievalTask,
            provide_reason=True,
        )

class DashboardRetrieveIncidentAndMinCreateIncidentInfeasibleTask(
    DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question="min",
            dashboard_class=SingleChartMinMaxRetrievalTask,
            provide_reason=False,
        )

local_vars = locals().copy()

__TASKS__ = [
    var
    for var in local_vars.values()
    if isinstance(var, type) and issubclass(var, DashDoFinalTask) and var is not DashDoFinalTask
]


        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question="min",
            dashboard_class=SingleChartMinMaxRetrievalTask,
            provide_reason=True,
        )

class DashboardRetrieveIncidentAndMinCreateIncidentInfeasibleTask(
    DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question="min",
            dashboard_class=SingleChartMinMaxRetrievalTask,
            provide_reason=False,
        )

local_vars = locals().copy()

__TASKS__ = [
    var
    for var in local_vars.values()
    if isinstance(var, type) and issubclass(var, DashDoFinalTask) and var is not DashDoFinalTask
]


            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
            function=get_infeasible_form_config,
            provide_reason=provide_reason,
        )
        self.task_description = ""
        self.short_description = (
            "Create an incident for the worst performing employee from the list."
        )
        self.filter_than = "lesser"
        self.attribute_name = "assigned_to"
        self.prefix = "ICI"

    def set_compositional_task(self) -> None:
        # The unique name for the user is created once the task is instantiated
        base_user = table_api_call(
            instance=self.instance,
            table="sys_user",
            params={
                "sysparm_query": f"sys_id={self._base_user_sysid}",
            },
        )["result"][0]
        self.user_name = base_user["first_name"] + " " + base_user["last_name"]

        agent_full_names, agent_value_sysids = self.get_agent_values(
            self.attribute_name, self.filter_than
        )
        self.agent_value_sysids = agent_value_sysids
        incident_numbers = []
        for _ in range(len(agent_full_names)):
            incident_number = "INC" + str(random.randint(1000000, 9999999))
            while (
                incident_number in self.all_incident_numbers or incident_number in incident_numbers
            ):
                incident_number = "INC" + str(random.randint(1000000, 9999999))
            incident_numbers.append(incident_number)

        self.incident_numbers = incident_numbers

        create_incident_subtasks = []

        for agent_full_name, incident_number in zip(agent_full_names, incident_numbers):
            incident_config = {
                "fields": {
                    "caller_id": "Caller",
                    "category": "Category",
                    "description": "Description",
                    "short_description": "Short description",
                    "impact": "Impact",
                    "number": "Number",
                    "urgency": "Urgency",
                    "assigned_to": "Assigned to",
                },
                "task_fields": [
                    "caller_id",
                    "category",
                    "description",
                    "short_description",
                    "impact",
                    "number",
                    "urgency",
                    "assigned_to",
                ],
                "template_record": {
                    "caller_id": self.user_name,
                    "category": "Inquiry / Help",
                    "description": "Compulsory training for employee in probation",
                    "short_description": "Compulsory training for employee in probation",
                    "impact": "1 - High",
                    "number": incident_number,
                    "urgency": "1 - High",
                    "assigned_to": agent_full_name,
                },
                "infeasible_task_fields": [
                    "category",
                    "description",
                    "short_description",
                    "impact",
                    "number",
                ],
            }

            incident_config, self.infeasible_reasons = self.function(
                config=incident_config, random=self.random
            )

            create_incident_subtask = [
                # Navigate to the incident list
                AllMenuTask(
                    instance=self.instance,
                    fixed_config={
                        "application": "Service Desk",
                        "module": "Incidents",
                        "url": "/now/nav/ui/classic/params/target/incident_list.do",
                    },
                    is_validated=False,
                    used_in_level_2=True,
                    has_description=False,
                ),
                # Create an incident
                CreateIncidentTask(
                    instance=self.instance,
                    fixed_config=incident_config,
                    is_validated=False,
                    used_in_level_2=True,
                    check_record_created=False,
                    has_description=True,
                ),
            ]
            create_incident_subtasks += create_incident_subtask

        self.compositional_task = create_incident_subtasks

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self.create_report()
        self.set_compositional_task()
        config = self.fixed_config if self.fixed_config else self._get_config()
        incident_numbers_string = ", ".join(self.incident_numbers)

        if self.level == 3:
            self.task_description = (
                self.task_description
                + f"Value to retrieve: {self.description_mapping[self.question]} of all the incidents. Comparator: Less than or equal to the value.\n"
                + f"Task: Create incidents with the following information: \n"
                + f"Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation', Caller: '{self.user_name}'.\n"
                + f"Assign the incidents you create to the agents mentioned above. You can use the incident numbers: {incident_numbers_string}, one for each."
            )

        goal, info = super().setup_goal(
            page=page, config=config, build_pretty_print_description=False
        )


                        "url": "/now/nav/ui/classic/params/target/incident_list.do",
                    },
                    is_validated=False,
                    used_in_level_2=True,
                    has_description=False,
                ),
                # Create an incident
                CreateIncidentTask(
                    instance=self.instance,
                    fixed_config=incident_config,
                    is_validated=False,
                    used_in_level_2=True,
                    check_record_created=False,
                    has_description=True,
                ),
            ]
            create_incident_subtasks += create_incident_subtask

        self.compositional_task = create_incident_subtasks

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self.create_report()
        self.set_compositional_task()
        config = self.fixed_config if self.fixed_config else self._get_config()
        incident_numbers_string = ", ".join(self.incident_numbers)

        if self.level == 3:
            self.task_description = (
                self.task_description
                + f"Value to retrieve: {self.description_mapping[self.question]} of all the incidents. Comparator: Less than or equal to the value.\n"
                + f"Task: Create incidents with the following information: \n"
                + f"Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation', Caller: '{self.user_name}'.\n"
                + f"Assign the incidents you create to the agents mentioned above. You can use the incident numbers: {incident_numbers_string}, one for each."
            )

        goal, info = super().setup_goal(
            page=page, config=config, build_pretty_print_description=False
        )

        if self.level == 2:
            goal = (
                self.task_description
                + f"\n1. Navigate to the CMDB reports and look for the report with the mentioned hashtag. \n"
                + f"\n2. Find the agents with number of incidents less than or equal to the  {self.description_mapping[self.question]} of the incidents assigned to every one. \n"
                + f"\n3. Navigate to Service Desk > Incidents. \n"
                + f"\n4. Create new incidents with the following field values:- Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation' and assign them to each of the agents. You will create as many incidents as there are agents.\n"
                + f"\nYou should use the following incident numbers for each incident (one for each): {incident_numbers_string}."
            )

        return goal, info

    def teardown(self) -> None:
        for incident_number in self.incident_numbers:
            created_incident_response = table_api_call(
                instance=self.instance,
                table="incident",
                params={
                    "sysparm_query": f"number={incident_number}",
                },
                method="GET",
            )["result"]
            if len(created_incident_response) > 1:
                raise Exception("Multiple incidents created")
            if len(created_incident_response) == 1:
                created_incident_sysid = created_incident_response[0]["sys_id"]
                db_delete_from_table(
                    instance=self.instance,
                    table="incident",
                    sys_id=created_incident_sysid,
                )


teardown

                + f"Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation', Caller: '{self.user_name}'.\n"
                + f"Assign the incidents you create to the agents mentioned above. You can use the incident numbers: {incident_numbers_string}, one for each."
            )

        goal, info = super().setup_goal(
            page=page, config=config, build_pretty_print_description=False
        )

        if self.level == 2:
            goal = (
                self.task_description
                + f"\n1. Navigate to the CMDB reports and look for the report with the mentioned hashtag. \n"
                + f"\n2. Find the agents with number of incidents less than or equal to the  {self.description_mapping[self.question]} of the incidents assigned to every one. \n"
                + f"\n3. Navigate to Service Desk > Incidents. \n"
                + f"\n4. Create new incidents with the following field values:- Category: 'Inquiry / Help', Impact: '1 - High', Urgency: '1 - High', Short description: 'Compulsory training for employee in probation' and assign them to each of the agents. You will create as many incidents as there are agents.\n"
                + f"\nYou should use the following incident numbers for each incident (one for each): {incident_numbers_string}."
            )

        return goal, info

    def teardown(self) -> None:
        for incident_number in self.incident_numbers:
            created_incident_response = table_api_call(
                instance=self.instance,
                table="incident",
                params={
                    "sysparm_query": f"number={incident_number}",
                },
                method="GET",
            )["result"]
            if len(created_incident_response) > 1:
                raise Exception("Multiple incidents created")
            if len(created_incident_response) == 1:
                created_incident_sysid = created_incident_response[0]["sys_id"]
                db_delete_from_table(
                    instance=self.instance,
                    table="incident",
                    sys_id=created_incident_sysid,
                )

        return super().teardown()

class DashboardRetrieveIncidentAndMinCreateIncidentInfeasibleWithReasonTask(
    DashboardRetrieveIncidentAndCreateIncidentInfeasibleTask, DashDoFinalTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 3,
    ) -> None:
        """
        Retrieve the worst performing employee and create an incident to assign them a probation course.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Create an incident for the worst performing employee from the list"


from faker import Faker

fake = Faker()

from playwright.sync_api._generated import Page

from browsergym.workarena.tasks.knowledge import KnowledgeBaseSearchTask
from browsergym.workarena.tasks.list import FilterListTask
from browsergym.workarena.tasks.navigation import AllMenuTask

from .base import CompositionalTask

from ..base import AbstractServiceNowTask

from ...instance import SNowInstance

class FilterAndDoTask(CompositionalTask):
    def __init__(
        self,
        seed: int,
        instance: SNowInstance = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        navigation_config: dict = None,
        protocol_name: str = None,
        level: int = 2,
    ) -> None:
        """
        Generic task to navigate to a specific page, run a filter and perform a task.

        Parameters:
        -----------
        instance: SNowInstance
            The ServiceNow instance to run the task on.
        fixed_config: list[AbstractServiceNowTask]
            A list of tuples, each containing a subtask
        navigation_config: dict
            Configuration to use for the navigation to the list that will be filtered. Contains application and module.
            URL is not necessary as the navigation steps are not validated
        protocol_name: str
            The name of the protocol to refer to in the task description for L3.
        level: int
            The level of the task; choice between 2 and 3. L2 will have all the info in the the goal and start in the SNOW home page.
            L3 will start in a private task page describing the information needed to complete the task and the related company protocol
            to complete it.

        Attributes:
        -----------
        filter_config: dict
            Configuration to use for the filter that will be applied to the list. Contains filter_columns, filter_values and filter_kind in addition to the path to the expected fields in the list.
            this is set by the _setup_list method.
        tasks: List[AbstractServiceNowTask]
            The tasks to perform after having filtered the list. Set by the child setup
        task_description: str
            The start of the task description to be completed. Provided by the child class.
        short_description: str
            A short description of the task to be completed. "Create a new user". Provided by the child class.
        """
        assert level in [2, 3], "Level must be either 2 or 3"
        self.level = level
        super().__init__(
            seed=seed,
            instance=instance,
            fixed_config=fixed_config,
            level=level,
        )
        self.used_in_level_2 = self.level == 2
        self.navigation_config = navigation_config
        self.filter_config = None
        self.protocol_name = protocol_name
        self.task_description = None
        self.short_description = None
        self.tasks = []

    def _setup_list(self) -> None:
        """Used to create the necessary records in the list + setting up the list filter attribute before filtering it."""
        raise NotImplementedError

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self._setup_list()
        config = self.fixed_config if self.fixed_config else self._get_config()

        goal, info = super().setup_goal(page=page, config=config)

        return goal, info

    def _get_config(self) -> list[AbstractServiceNowTask]:
        list_url = self.filter_config["list_url"]

        navigate_to_protocol_config = [
            # Navigate to the KB
            AllMenuTask(
                instance=self.instance,
                fixed_config={
                    "application": "Self-Service",
                    "module": "Knowledge",
                    "url": "/now/nav/ui/classic/params/target/%24knowledge.do",
                },
                is_validated=False,
                used_in_level_2=False,
            ),
            # Find the protocol for on-boarding a new user
            KnowledgeBaseSearchTask(
                instance=self.instance,
                fixed_config={
                    "alternative_answers": [],
                    "item": f"{self.protocol_name}",
                    "question": f'Can you find the "{self.protocol_name}" Protocol in the Knowledge Base?',
                    "value": "",
                },
                is_validated=False,
                used_in_level_2=False,
            ),
        ]

        config = [
            # Navigate to the task start page
            AllMenuTask(
                instance=self.instance,
                fixed_config=self.navigation_config,
                is_validated=False,
                used_in_level_2=True,
            ),
            # Filter the the list; the config it uses is set by the _setup_list method
            FilterListTask(
                instance=self.instance,
                list_url=list_url,
                fixed_config=self.filter_config,
                expected_fields_path=self.filter_config["expected_fields_path"],
                is_validated=False,
                used_in_level_2=True,
            ),
        ] + self.tasks

        # To support the option of having no protocol
        if self.protocol_name:
            config = navigate_to_protocol_config + config

        return config


from faker import Faker

fake = Faker()

from playwright.sync_api._generated import Page

from browsergym.workarena.tasks.knowledge import KnowledgeBaseSearchTask
from browsergym.workarena.tasks.list import FilterListTask
from browsergym.workarena.tasks.navigation import AllMenuTask

from .base import CompositionalTask

from ..base import AbstractServiceNowTask

from ...instance import SNowInstance

class FilterAndDoTask(CompositionalTask):
    def __init__(
        self,
        seed: int,
        instance: SNowInstance = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        navigation_config: dict = None,
        protocol_name: str = None,
        level: int = 2,
    ) -> None:
        """
        Generic task to navigate to a specific page, run a filter and perform a task.

        Parameters:
        -----------
        instance: SNowInstance
            The ServiceNow instance to run the task on.
        fixed_config: list[AbstractServiceNowTask]
            A list of tuples, each containing a subtask
        navigation_config: dict
            Configuration to use for the navigation to the list that will be filtered. Contains application and module.
            URL is not necessary as the navigation steps are not validated
        protocol_name: str
            The name of the protocol to refer to in the task description for L3.
        level: int
            The level of the task; choice between 2 and 3. L2 will have all the info in the the goal and start in the SNOW home page.
            L3 will start in a private task page describing the information needed to complete the task and the related company protocol
            to complete it.

        Attributes:
        -----------
        filter_config: dict
            Configuration to use for the filter that will be applied to the list. Contains filter_columns, filter_values and filter_kind in addition to the path to the expected fields in the list.
            this is set by the _setup_list method.
        tasks: List[AbstractServiceNowTask]
            The tasks to perform after having filtered the list. Set by the child setup
        task_description: str
            The start of the task description to be completed. Provided by the child class.
        short_description: str
            A short description of the task to be completed. "Create a new user". Provided by the child class.
        """
        assert level in [2, 3], "Level must be either 2 or 3"
        self.level = level
        super().__init__(
            seed=seed,
            instance=instance,
            fixed_config=fixed_config,
            level=level,
        )
        self.used_in_level_2 = self.level == 2
        self.navigation_config = navigation_config
        self.filter_config = None
        self.protocol_name = protocol_name
        self.task_description = None
        self.short_description = None
        self.tasks = []

    def _setup_list(self) -> None:
        """Used to create the necessary records in the list + setting up the list filter attribute before filtering it."""
        raise NotImplementedError

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self._setup_list()
        config = self.fixed_config if self.fixed_config else self._get_config()

        goal, info = super().setup_goal(page=page, config=config)

        return goal, info

    def _get_config(self) -> list[AbstractServiceNowTask]:
        list_url = self.filter_config["list_url"]

        navigate_to_protocol_config = [
            # Navigate to the KB
            AllMenuTask(
                instance=self.instance,


            The start of the task description to be completed. Provided by the child class.
        short_description: str
            A short description of the task to be completed. "Create a new user". Provided by the child class.
        """
        assert level in [2, 3], "Level must be either 2 or 3"
        self.level = level
        super().__init__(
            seed=seed,
            instance=instance,
            fixed_config=fixed_config,
            level=level,
        )
        self.used_in_level_2 = self.level == 2
        self.navigation_config = navigation_config
        self.filter_config = None
        self.protocol_name = protocol_name
        self.task_description = None
        self.short_description = None
        self.tasks = []

    def _setup_list(self) -> None:
        """Used to create the necessary records in the list + setting up the list filter attribute before filtering it."""
        raise NotImplementedError

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self._setup_list()
        config = self.fixed_config if self.fixed_config else self._get_config()

        goal, info = super().setup_goal(page=page, config=config)

        return goal, info

    def _get_config(self) -> list[AbstractServiceNowTask]:
        list_url = self.filter_config["list_url"]

        navigate_to_protocol_config = [
            # Navigate to the KB
            AllMenuTask(
                instance=self.instance,
                fixed_config={
                    "application": "Self-Service",
                    "module": "Knowledge",
                    "url": "/now/nav/ui/classic/params/target/%24knowledge.do",


        assert level in [2, 3], "Level must be either 2 or 3"
        self.level = level
        super().__init__(
            seed=seed,
            instance=instance,
            fixed_config=fixed_config,
            level=level,
        )
        self.used_in_level_2 = self.level == 2
        self.navigation_config = navigation_config
        self.filter_config = None
        self.protocol_name = protocol_name
        self.task_description = None
        self.short_description = None
        self.tasks = []

    def _setup_list(self) -> None:
        """Used to create the necessary records in the list + setting up the list filter attribute before filtering it."""
        raise NotImplementedError

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self._setup_list()
        config = self.fixed_config if self.fixed_config else self._get_config()

        goal, info = super().setup_goal(page=page, config=config)

        return goal, info

    def _get_config(self) -> list[AbstractServiceNowTask]:
        list_url = self.filter_config["list_url"]

        navigate_to_protocol_config = [
            # Navigate to the KB
            AllMenuTask(
                instance=self.instance,
                fixed_config={
                    "application": "Self-Service",
                    "module": "Knowledge",
                    "url": "/now/nav/ui/classic/params/target/%24knowledge.do",
                },
                is_validated=False,
                used_in_level_2=False,
            ),
            # Find the protocol for on-boarding a new user
            KnowledgeBaseSearchTask(
                instance=self.instance,
                fixed_config={


        self.used_in_level_2 = self.level == 2
        self.navigation_config = navigation_config
        self.filter_config = None
        self.protocol_name = protocol_name
        self.task_description = None
        self.short_description = None
        self.tasks = []

    def _setup_list(self) -> None:
        """Used to create the necessary records in the list + setting up the list filter attribute before filtering it."""
        raise NotImplementedError

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self._setup_list()
        config = self.fixed_config if self.fixed_config else self._get_config()

        goal, info = super().setup_goal(page=page, config=config)

        return goal, info

    def _get_config(self) -> list[AbstractServiceNowTask]:
        list_url = self.filter_config["list_url"]

        navigate_to_protocol_config = [
            # Navigate to the KB
            AllMenuTask(
                instance=self.instance,
                fixed_config={
                    "application": "Self-Service",
                    "module": "Knowledge",
                    "url": "/now/nav/ui/classic/params/target/%24knowledge.do",
                },
                is_validated=False,
                used_in_level_2=False,
            ),
            # Find the protocol for on-boarding a new user
            KnowledgeBaseSearchTask(
                instance=self.instance,
                fixed_config={
                    "alternative_answers": [],
                    "item": f"{self.protocol_name}",
                    "question": f'Can you find the "{self.protocol_name}" Protocol in the Knowledge Base?',
                    "value": "",
                },
                is_validated=False,
                used_in_level_2=False,
            ),
        ]

        config = [
            # Navigate to the task start page
            AllMenuTask(
                instance=self.instance,
                fixed_config=self.navigation_config,
                is_validated=False,
                used_in_level_2=True,
            ),
            # Filter the the list; the config it uses is set by the _setup_list method
            FilterListTask(
                instance=self.instance,
                list_url=list_url,
                fixed_config=self.filter_config,
                expected_fields_path=self.filter_config["expected_fields_path"],
                is_validated=False,
                used_in_level_2=True,
            ),
        ] + self.tasks

        # To support the option of having no protocol
        if self.protocol_name:
            config = navigate_to_protocol_config + config

        return config


import random
from playwright.sync_api._generated import Page

from .dash_do_base import DashboardRetrieveIncidentAndDoTask, DashDoFinalTask

from ..base import AbstractServiceNowTask
from ..dashboard import SingleChartMinMaxRetrievalTask, SingleChartMeanMedianModeRetrievalTask

from ...api.utils import table_api_call, db_delete_from_table
from ...instance import SNowInstance

from browsergym.workarena.tasks.navigation import AllMenuTask
from browsergym.workarena.tasks.list import (
    FilterAssetListTask,
    FilterHardwareListTask,
    FilterIncidentListTask,
    FilterUserListTask,
)

class DashboardRetrieveIncidentAndFilterListTask(DashboardRetrieveIncidentAndDoTask):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
    ) -> None:
        """
        Retrieve the best or worst performing agent and filter a list based on their assignments.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Retrieve the best or worst performing agent and filter a list based on their assignments"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
        )
        self.prefix = "DIF"

    def get_filter_config(self, attribute_name, filter_than) -> dict:
        filter_values, agent_value_sysids = self.get_agent_values(
            attribute_name=attribute_name, filter_than=filter_than
        )
        self.agent_value_sysids = agent_value_sysids
        if len(filter_values) == 1:
            filter_kind = "AND"
        else:
            filter_kind = "OR"

        filter_config = {
            "filter_columns": [self.attribute_name] * len(filter_values),
            "filter_kind": filter_kind,
            "filter_values": filter_values,
        }
        return filter_config

class DashboardRetrieveIncidentAndFilterAssetListTask(DashboardRetrieveIncidentAndFilterListTask):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        max_assets_per_agent: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
    ) -> None:
        """
        Retrieve the best or worst performing agent and filter an asset list based on their assignments.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Filter the asset list based on incidents assigned to an employee"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
        )
        self.max_assets_per_agent = max_assets_per_agent
        self.attribute_name = "assigned_to"

    def set_compositional_task(self) -> None:
        filter_config = self.get_filter_config(
            attribute_name=self.attribute_name, filter_than=self.filter_than
        )

        filter_asset_list_subtask = [
            # Navigate to the asset list
            AllMenuTask(
                instance=self.instance,
                fixed_config={
                    "application": "Asset",
                    "module": "Portfolios > All Assets",
                    "url": "/now/nav/ui/classic/params/target/alm_asset_list.do",
                },
                is_validated=False,
                used_in_level_2=True,
            ),
            # Filter asset list
            FilterAssetListTask(
                is_validated=True,
                list_name="alm_asset",
                used_in_level_2=True,
                fixed_config=filter_config,
            ),
        ]

        self.compositional_task = filter_asset_list_subtask

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self.create_report()

        # We create dummy assets for the consumable and license categories here
        ### NOTE: We can create assets without any of the following information, save time, and still assign them to the user. The task should be fine.
        consumable_category_sysid = table_api_call(
            instance=self.instance,
            table="cmdb_model_category",
            method="GET",
            params={"sysparm_query": "asset_class=alm_consumable", "sysparm_fields": "sys_id"},
        )["result"][0]["sys_id"]

        consumables = table_api_call(
            instance=self.instance,
            table="cmdb_model",
            method="GET",
            params={
                "sysparm_query": f"cmdb_model_category={consumable_category_sysid}",
                "sysparm_fields": "sys_id",
            },
        )["result"]
        consumables_sysids = [consumable["sys_id"] for consumable in consumables]

        license_category_sysid = table_api_call(
            instance=self.instance,
            table="cmdb_model_category",
            method="GET",
            params={"sysparm_query": "asset_class=alm_license", "sysparm_fields": "sys_id"},
        )["result"][0]["sys_id"]

        licenses = table_api_call(
            instance=self.instance,
            table="cmdb_model",
            method="GET",
            params={
                "sysparm_query": f"cmdb_model_category={license_category_sysid}",
                "sysparm_fields": "sys_id",
            },
        )["result"][:10]
        license_sysids = [license["sys_id"] for license in licenses]

        self.new_asset_sys_ids = []
        for agent_sysid in self.agent_sysids:
            num_assets = self.random.choice(range(1, self.max_assets_per_agent))
            for _ in range(num_assets):
                consumable_asset_data = {
                    "asset_tag": "CONSUMABLE" + str(random.randint(100, 999)),
                    "model": self.random.choice(consumables_sysids),
                    "model_category": consumable_category_sysid,
                    "assigned_to": agent_sysid,
                    "cost": 1000.00,
                    "purchase_date": "2024-05-08",
                    "substatus": "in_use",
                }
                response = table_api_call(
                    instance=self.instance,
                    table="alm_asset",
                    json=consumable_asset_data,
                    method="POST",
                )
                self.new_asset_sys_ids.append(response["result"]["sys_id"])
                license_asset_data = {
                    "asset_tag": "LICENSE" + str(random.randint(100, 999)),
                    "model": self.random.choice(license_sysids),
                    "model_category": license_category_sysid,
                    "assigned_to": agent_sysid,
                    "cost": 1000.00,
                    "purchase_date": "2024-05-08",
                    "substatus": "in_use",
                }
                response = table_api_call(
                    instance=self.instance,
                    table="alm_asset",
                    json=license_asset_data,
                    method="POST",
                )
                self.new_asset_sys_ids.append(response["result"]["sys_id"])

        self.set_compositional_task()
        config = self.fixed_config if self.fixed_config else self._get_config()

        if self.level == 3:
            filter_than = f"{self.filter_than} than or " if self.filter_than else ""
            self.task_description = (
                self.task_description
                + f"\t - Please retrieve the '{self.description_mapping[self.question]}' value of the number of incidents assigned across agents. Retrieve agents that have {filter_than}equal number of incidents assigned to them compared to this value.\n"
                + f"\t   For example, if you were asked to find the 'mean' or 'average' for a case where there are 4 agents assigned 1,2,3,2 incidents respectively, the mean would be 2. The list of agents required for solving the following task would be all the agents that have {filter_than}equal to 2 assigned incidents.\n\n"
                + f"\t - Task: Filter the Asset List using the {self.attribute_name} field corresponding to the agents that fit the criteria above. \n"
                + f"The list is present at Portfolios > All Assets. \n\n"
                + self.final_private_task_instructions
            )

        goal, info = super().setup_goal(
            page=page, config=config, build_pretty_print_description=False
        )

        if self.level == 2:
            if self.filter_than:
                step_3 = f"\n3. Find the agents with number of incidents {self.filter_than} than or equal to the {self.description_mapping[self.question]} value of the number of incidents assigned across agents. \n"
            else:
                step_3 = f"\n3. Find the agent with the {self.description_mapping[self.question]} assigned incidents. \n"
            goal = (
                self.short_description
                + f"\n1. Navigate to the Reports > View/Run page. \n"
                + f"\n2. Given the title of the report, search for it on this page. The report shows the number of 'incidents' assigned to an 'agent'.\n"
                + step_3
                + f"\n4. Navigate to Portfolios > All Assets. \n"
                + f"\nUsing the field {self.attribute_name} for the agent/ agents that fit the critera above, filter the list.\n"
            )

        return goal, info

    def teardown(self) -> None:
        # Delete all assets
        for new_asset_sysid in self.new_asset_sys_ids:
            db_delete_from_table(
                instance=self.instance,
                table="alm_asset",
                sys_id=new_asset_sysid,
            )
        return super().teardown()

class DashboardRetrieveIncidentAndFilterHardwareListTask(
    DashboardRetrieveIncidentAndFilterListTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        max_assets_per_agent: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
    ) -> None:
        """
        Retrieve the best or worst performing agent and filter a hardware list based on their assignments.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Retrieve the best or worst performing agent and filter a hardware list based on their assignments."
        """
        self.max_assets_per_agent = max_assets_per_agent
        self.attribute_name = "assigned_to"
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
        )

    def set_compositional_task(self) -> None:

        filter_config = self.get_filter_config(
            attribute_name=self.attribute_name, filter_than=self.filter_than
        )

        filter_hardware_asset_list_subtask = [
            # Navigate to the hardware asset list
            AllMenuTask(
                instance=self.instance,
                fixed_config={
                    "application": "Asset",
                    "module": "Portfolios > Hardware Assets",
                    "url": "/now/nav/ui/classic/params/target/alm_hardware_list.do",
                },
                is_validated=False,
                used_in_level_2=True,
            ),
            # Filter hardware list
            FilterHardwareListTask(
                is_validated=True,
                list_name="alm_hardware",
                used_in_level_2=True,
                fixed_config=filter_config,
            ),
        ]

        self.compositional_task = filter_hardware_asset_list_subtask

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self.create_report()

        hardware_category_sysid = table_api_call(
            instance=self.instance,
            table="cmdb_model_category",
            method="GET",
            params={"sysparm_query": "asset_class=alm_hardware", "sysparm_fields": "sys_id"},
        )["result"][0]["sys_id"]

        hardwares = table_api_call(
            instance=self.instance,
            table="cmdb_model",
            method="GET",
            params={
                "sysparm_query": f"cmdb_model_category={hardware_category_sysid}",
                "sysparm_fields": "sys_id",
            },
        )["result"]
        hardware_sysids = [hardware["sys_id"] for hardware in hardwares]
        self.new_asset_sysids = []
        for agent_sysid in self.agent_sysids:
            num_assets = self.random.choice(range(1, self.max_assets_per_agent))
            for _ in range(num_assets):
                hardware_asset_data = {
                    "asset_tag": "CONSUMABLE" + str(random.randint(100, 999)),
                    "model": self.random.choice(hardware_sysids),
                    "model_category": hardware_category_sysid,
                    "assigned_to": agent_sysid,
                    "cost": 1000.00,
                    "purchase_date": "2024-05-08",
                    "substatus": "in_use",
                }
                response = table_api_call(
                    instance=self.instance,
                    table="alm_hardware",
                    json=hardware_asset_data,
                    method="POST",
                )
                self.new_asset_sysids.append(response["result"]["sys_id"])

        self.set_compositional_task()
        config = self.fixed_config if self.fixed_config else self._get_config()

        if self.level == 3:
            filter_than = f"{self.filter_than} than or " if self.filter_than else ""
            self.task_description = (
                self.task_description
                + f"\t - Please retrieve the '{self.description_mapping[self.question]}' value of the number of incidents assigned across agents. Retrieve agents that have {filter_than}equal number of incidents assigned to them compared to this value.\n"
                + f"\t   For example, if you were asked to find the 'mean' or 'average' for a case where there are 4 agents assigned 1,2,3,2 incidents respectively, the mean would be 2. The list of agents required for solving the following task would be all the agents that have {filter_than}equal to 2 assigned incidents.\n\n"
                + f"\t - Task: Filter the Hardware List using the {self.attribute_name} field corresponding to the agents that fit the criteria above. \n"
                + f"The list is present at Portfolios > Hardware Assets. \n\n"
                + self.final_private_task_instructions
            )

        goal, info = super().setup_goal(
            page=page, config=config, build_pretty_print_description=False
        )

        if self.level == 2:
            if self.filter_than:
                step_3 = f"\n3. Find the agents with number of incidents {self.filter_than} than or equal to the {self.description_mapping[self.question]} value of the number of incidents assigned across agents. \n"
            else:
                step_3 = f"\n3. Find the agent with the {self.description_mapping[self.question]} assigned incidents. \n"
            goal = (
                self.short_description
                + f"\n1. Navigate to the Reports > View/Run page. \n"
                + f"\n2. Given the title of the report, search for it on this page. The report shows the number of 'incidents' assigned to an 'agent'.\n"
                + step_3
                + f"\n4. Navigate to Portfolios > Hardware Assets. \n"
                + f"\nUsing the field {self.attribute_name} for the agent/ agents that fit the critera above, filter the list.\n"
            )

        return goal, info

    def teardown(self) -> None:
        # Delete all assets
        for new_asset_sysid in self.new_asset_sysids:
            db_delete_from_table(
                instance=self.instance,
                table="alm_hardware",
                sys_id=new_asset_sysid,
            )
        return super().teardown()

class DashboardRetrieveIncidentAndFilterIncidentListTask(
    DashboardRetrieveIncidentAndFilterListTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
    ) -> None:
        """
        Retrieve the best or worst performing agent and filter an incident list based on their assignments.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Retrieve the best or worst performing agent and filter an incident list based on their assignments."
        """
        self.attribute_name = "assigned_to"
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
        )

    def set_compositional_task(self) -> None:

        filter_config = self.get_filter_config(
            attribute_name=self.attribute_name, filter_than=self.filter_than
        )

        filter_incident_list_subtask = [
            # Navigate to the incident list
            AllMenuTask(
                instance=self.instance,
                fixed_config={
                    "application": "Service Desk",
                    "module": "Incidents",
                    "url": "/now/nav/ui/classic/params/target/incident_list.do",
                },
                is_validated=False,
                used_in_level_2=True,
            ),
            # Filter incident list
            FilterIncidentListTask(
                is_validated=True,
                list_name="incident",
                used_in_level_2=True,
                fixed_config=filter_config,
            ),
        ]

        self.compositional_task = filter_incident_list_subtask

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self.create_report()
        self.set_compositional_task()
        config = self.fixed_config if self.fixed_config else self._get_config()

        if self.level == 3:
            filter_than = f"{self.filter_than} than or " if self.filter_than else ""
            self.task_description = (
                self.task_description
                + f"\t - Please retrieve the '{self.description_mapping[self.question]}' value of the number of incidents assigned across agents. Retrieve agents that have {filter_than}equal number of incidents assigned to them compared to this value.\n"
                + f"\t   For example, if you were asked to find the 'mean' or 'average' for a case where there are 4 agents assigned 1,2,3,2 incidents respectively, the mean would be 2. The list of agents required for solving the following task would be all the agents that have {filter_than}equal to 2 assigned incidents.\n\n"
                + f"\t - Task: Filter the Incident
# ... truncated ...


import random
from playwright.sync_api._generated import Page

from .dash_do_base import DashboardRetrieveIncidentAndDoTask, DashDoFinalTask

from ..base import AbstractServiceNowTask
from ..dashboard import SingleChartMinMaxRetrievalTask, SingleChartMeanMedianModeRetrievalTask

from ...api.utils import table_api_call, db_delete_from_table
from ...instance import SNowInstance

from browsergym.workarena.tasks.navigation import AllMenuTask
from browsergym.workarena.tasks.list import (
    FilterAssetListTask,
    FilterHardwareListTask,
    FilterIncidentListTask,
    FilterUserListTask,
)

class DashboardRetrieveIncidentAndFilterListTask(DashboardRetrieveIncidentAndDoTask):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
    ) -> None:
        """
        Retrieve the best or worst performing agent and filter a list based on their assignments.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Retrieve the best or worst performing agent and filter a list based on their assignments"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
        )
        self.prefix = "DIF"

    def get_filter_config(self, attribute_name, filter_than) -> dict:
        filter_values, agent_value_sysids = self.get_agent_values(
            attribute_name=attribute_name, filter_than=filter_than
        )
        self.agent_value_sysids = agent_value_sysids
        if len(filter_values) == 1:
            filter_kind = "AND"
        else:
            filter_kind = "OR"

        filter_config = {
            "filter_columns": [self.attribute_name] * len(filter_values),
            "filter_kind": filter_kind,
            "filter_values": filter_values,
        }
        return filter_config

class DashboardRetrieveIncidentAndFilterAssetListTask(DashboardRetrieveIncidentAndFilterListTask):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        max_assets_per_agent: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
    ) -> None:
        """
        Retrieve the best or worst performing agent and filter an asset list based on their assignments.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str


        self.prefix = "DIF"

    def get_filter_config(self, attribute_name, filter_than) -> dict:
        filter_values, agent_value_sysids = self.get_agent_values(
            attribute_name=attribute_name, filter_than=filter_than
        )
        self.agent_value_sysids = agent_value_sysids
        if len(filter_values) == 1:
            filter_kind = "AND"
        else:
            filter_kind = "OR"

        filter_config = {
            "filter_columns": [self.attribute_name] * len(filter_values),
            "filter_kind": filter_kind,
            "filter_values": filter_values,
        }
        return filter_config

class DashboardRetrieveIncidentAndFilterAssetListTask(DashboardRetrieveIncidentAndFilterListTask):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        max_assets_per_agent: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
    ) -> None:
        """
        Retrieve the best or worst performing agent and filter an asset list based on their assignments.
        Attributes:
        -----------
        task_description: str
            The start of the task description to be completed.
        short_description: str
            A short description of the task to be completed. "Filter the asset list based on incidents assigned to an employee"
        """
        super().__init__(
            instance=instance,
            seed=seed,
            fixed_config=fixed_config,
            level=level,
            question=question,
            dashboard_class=dashboard_class,
        )
        self.max_assets_per_agent = max_assets_per_agent
        self.attribute_name = "assigned_to"

    def set_compositional_task(self) -> None:
        filter_config = self.get_filter_config(
            attribute_name=self.attribute_name, filter_than=self.filter_than
        )

        filter_asset_list_subtask = [
            # Navigate to the asset list
            AllMenuTask(
                instance=self.instance,
                fixed_config={
                    "application": "Asset",
                    "module": "Portfolios > All Assets",
                    "url": "/now/nav/ui/classic/params/target/alm_asset_list.do",
                },
                is_validated=False,
                used_in_level_2=True,
            ),
            # Filter asset list
            FilterAssetListTask(
                is_validated=True,
                list_name="alm_asset",
                used_in_level_2=True,
                fixed_config=filter_config,
            ),
        ]

        self.compositional_task = filter_asset_list_subtask

    def setup_goal(self, page: Page) -> tuple[str, dict]:
        self.create_report()

        # We create dummy assets for the consumable and license categories here
        ### NOTE: We can create assets without any of the following information, save time, and still assign them to the user. The task should be fine.
        consumable_category_sysid = table_api_call(
            instance=self.instance,
            table="cmdb_model_category",
            method="GET",
            params={"sysparm_query": "asset_class=alm_consumable", "sysparm_fields": "sys_id"},
        )["result"][0]["sys_id"]

        consumables = table_api_call(
            instance=self.instance,
            table="cmdb_model",
            method="GET",
            params={
                "sysparm_query": f"cmdb_model_category={consumable_category_sysid}",
                "sysparm_fields": "sys_id",
            },
        )["result"]
        consumables_sysids = [consumable["sys_id"] for consumable in consumables]

        license_category_sysid = table_api_call(
            instance=self.instance,
            table="cmdb_model_category",
            method="GET",
            params={"sysparm_query": "asset_class=alm_license", "sysparm_fields": "sys_id"},
        )["result"][0]["sys_id"]

        licenses = table_api_call(
            instance=self.instance,
            table="cmdb_model",
            method="GET",
            params={
                "sysparm_query": f"cmdb_model_category={license_category_sysid}",
                "sysparm_fields": "sys_id",
            },
        )["result"][:10]
        license_sysids = [license["sys_id"] for license in licenses]

        self.new_asset_sys_ids = []
        for agent_sysid in self.agent_sysids:
            num_assets = self.random.choice(range(1, self.max_assets_per_agent))
            for _ in range(num_assets):
                consumable_asset_data = {
                    "asset_tag": "CONSUMABLE" + str(random.randint(100, 999)),
                    "model": self.random.choice(consumables_sysids),
                    "model_category": consumable_category_sysid,
                    "assigned_to": agent_sysid,
                    "cost": 1000.00,
                    "purchase_date": "2024-05-08",
                    "substatus": "in_use",
                }
                response = table_api_call(
                    instance=self.instance,
                    table="alm_asset",
                    json=consumable_asset_data,
                    method="POST",
                )
                self.new_asset_sys_ids.append(response["result"]["sys_id"])
                license_asset_data = {
                    "asset_tag": "LICENSE" + str(random.randint(100, 999)),
                    "model": self.random.choice(license_sysids),
                    "model_category": license_category_sysid,
                    "assigned_to": agent_sysid,
                    "cost": 1000.00,
                    "purchase_date": "2024-05-08",
                    "substatus": "in_use",
                }
                response = table_api_call(
                    instance=self.instance,
                    table="alm_asset",
                    json=license_asset_data,
                    method="POST",
                )
                self.new_asset_sys_ids.append(response["result"]["sys_id"])

        self.set_compositional_task()
        config = self.fixed_config if self.fixed_config else self._get_config()

        if self.level == 3:
            filter_than = f"{self.filter_than} than or " if self.filter_than else ""
            self.task_description = (
                self.task_description
                + f"\t - Please retrieve the '{self.description_mapping[self.question]}' value of the number of incidents assigned across agents. Retrieve agents that have {filter_than}equal number of incidents assigned to them compared to this value.\n"
                + f"\t   For example, if you were asked to find the 'mean' or 'average' for a case where there are 4 agents assigned 1,2,3,2 incidents respectively, the mean would be 2. The list of agents required for solving the following task would be all the agents that have {filter_than}equal to 2 assigned incidents.\n\n"
                + f"\t - Task: Filter the Asset List using the {self.attribute_name} field corresponding to the agents that fit the criteria above. \n"
                + f"The list is present at Portfolios > All Assets. \n\n"
                + self.final_private_task_instructions
            )

        goal, info = super().setup_goal(
            page=page, config=config, build_pretty_print_description=False
        )

        if self.level == 2:
            if self.filter_than:
                step_3 = f"\n3. Find the agents with number of incidents {self.filter_than} than or equal to the {self.description_mapping[self.question]} value of the number of incidents assigned across agents. \n"
            else:
                step_3 = f"\n3. Find the agent with the {self.description_mapping[self.question]} assigned incidents. \n"
            goal = (
                self.short_description
                + f"\n1. Navigate to the Reports > View/Run page. \n"
                + f"\n2. Given the title of the report, search for it on this page. The report shows the number of 'incidents' assigned to an 'agent'.\n"
                + step_3
                + f"\n4. Navigate to Portfolios > All Assets. \n"
                + f"\nUsing the field {self.attribute_name} for the agent/ agents that fit the critera above, filter the list.\n"
            )

        return goal, info

    def teardown(self) -> None:
        # Delete all assets
        for new_asset_sysid in self.new_asset_sys_ids:
            db_delete_from_table(
                instance=self.instance,
                table="alm_asset",
                sys_id=new_asset_sysid,
            )
        return super().teardown()

class DashboardRetrieveIncidentAndFilterHardwareListTask(
    DashboardRetrieveIncidentAndFilterListTask
):
    def __init__(
        self,
        instance: SNowInstance = None,
        seed: int = None,
        fixed_config: list[AbstractServiceNowTask] = None,
        level: int = 2,
        max_assets_per_agent: int = 2,
        question: str = None,
        dashboard_class: AbstractServiceNowTask = None,
    ) -> None:
        """
        Retrieve the best or worst performing agent and filter a hardware list based on their assignments.
        Attributes:
        -----------
        task_description: str