browsergym-workarena 0.2.1__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- browsergym/workarena/__init__.py +13 -1
- browsergym/workarena/api/category.py +74 -0
- browsergym/workarena/api/change_request.py +87 -0
- browsergym/workarena/api/computer_asset.py +90 -0
- browsergym/workarena/api/cost_center.py +19 -0
- browsergym/workarena/api/expense_line.py +89 -0
- browsergym/workarena/api/incident.py +45 -0
- browsergym/workarena/api/knowledge.py +29 -0
- browsergym/workarena/api/problem.py +90 -0
- browsergym/workarena/api/report.py +183 -0
- browsergym/workarena/api/requested_items.py +63 -0
- browsergym/workarena/api/user.py +11 -8
- browsergym/workarena/api/utils.py +47 -3
- browsergym/workarena/config.py +21 -1
- browsergym/workarena/data_files/setup_files/forms/expected_incident_form_fields.json +1 -1
- browsergym/workarena/data_files/setup_files/forms/expected_request_item_form_fields.json +1 -0
- browsergym/workarena/data_files/setup_files/knowledge/protocols.json +46 -0
- browsergym/workarena/data_files/setup_files/knowledge/test.html +1 -0
- browsergym/workarena/data_files/setup_files/lists/expected_asset_list_columns.json +2 -24
- browsergym/workarena/data_files/setup_files/lists/expected_change_request_list_columns.json +4 -40
- browsergym/workarena/data_files/setup_files/lists/expected_expense_line_list_columns.json +12 -0
- browsergym/workarena/data_files/setup_files/lists/expected_hardware_list_columns.json +1 -42
- browsergym/workarena/data_files/setup_files/lists/expected_incident_list_columns.json +2 -18
- browsergym/workarena/data_files/setup_files/lists/expected_problem_list_columns.json +12 -0
- browsergym/workarena/data_files/setup_files/lists/expected_requested_items_list_columns.json +12 -0
- browsergym/workarena/data_files/setup_files/lists/expected_service_catalog_list_columns.json +2 -19
- browsergym/workarena/data_files/setup_files/lists/expected_user_list_columns.json +3 -50
- browsergym/workarena/data_files/task_configs/all_menu.json +1 -1
- browsergym/workarena/data_files/task_configs/dashboard_retrieval_minmax_task.json +1 -1
- browsergym/workarena/data_files/task_configs/dashboard_retrieval_value_task.json +1 -1
- browsergym/workarena/data_files/task_configs/filter_service_catalog_item_list_task.json +1 -1
- browsergym/workarena/data_files/task_configs/impersonation_users.json +1 -1
- browsergym/workarena/data_files/task_configs/report_retrieval_minmax_task.json +1 -1
- browsergym/workarena/data_files/task_configs/report_retrieval_value_task.json +1 -1
- browsergym/workarena/human_eval/console.js +176 -0
- browsergym/workarena/human_eval/tool.py +366 -0
- browsergym/workarena/install.py +81 -20
- browsergym/workarena/tasks/base.py +55 -20
- browsergym/workarena/tasks/comp_building_block.py +4 -0
- browsergym/workarena/tasks/compositional/__init__.py +76 -0
- browsergym/workarena/tasks/compositional/base.py +364 -0
- browsergym/workarena/tasks/compositional/dash_do_base.py +1366 -0
- browsergym/workarena/tasks/compositional/dash_do_catalog.py +1127 -0
- browsergym/workarena/tasks/compositional/dash_do_catalog_infeasible.py +2047 -0
- browsergym/workarena/tasks/compositional/dash_do_create_incident.py +403 -0
- browsergym/workarena/tasks/compositional/dash_do_create_incident_infeasible.py +278 -0
- browsergym/workarena/tasks/compositional/dash_do_create_problem.py +336 -0
- browsergym/workarena/tasks/compositional/dash_do_create_problem_infeasible.py +235 -0
- browsergym/workarena/tasks/compositional/dash_do_filter.py +1600 -0
- browsergym/workarena/tasks/compositional/dash_do_request_item.py +1315 -0
- browsergym/workarena/tasks/compositional/dash_do_request_item_infeasible.py +693 -0
- browsergym/workarena/tasks/compositional/delete_record.py +341 -0
- browsergym/workarena/tasks/compositional/edit_knowledge_base.py +457 -0
- browsergym/workarena/tasks/compositional/expense_management.py +598 -0
- browsergym/workarena/tasks/compositional/filter_and_do.py +139 -0
- browsergym/workarena/tasks/compositional/find_and_order_item.py +345 -0
- browsergym/workarena/tasks/compositional/manage_change_request_schedule.py +1417 -0
- browsergym/workarena/tasks/compositional/mark_duplicate_problems.py +499 -0
- browsergym/workarena/tasks/compositional/maximize_investment_return.py +1763 -0
- browsergym/workarena/tasks/compositional/navigate_and_do.py +1151 -0
- browsergym/workarena/tasks/compositional/navigate_and_do_infeasible.py +2100 -0
- browsergym/workarena/tasks/compositional/offboard_user.py +207 -0
- browsergym/workarena/tasks/compositional/onboard_user.py +226 -0
- browsergym/workarena/tasks/compositional/update_task.py +145 -0
- browsergym/workarena/tasks/compositional/utils/curriculum.py +215 -0
- browsergym/workarena/tasks/compositional/utils/infeasible_configs.py +151 -0
- browsergym/workarena/tasks/compositional/utils/knapsack.py +192 -0
- browsergym/workarena/tasks/compositional/warranty_check.py +227 -0
- browsergym/workarena/tasks/compositional/work_assignment.py +804 -0
- browsergym/workarena/tasks/compositional/workload_balancing.py +396 -0
- browsergym/workarena/tasks/dashboard.py +188 -8
- browsergym/workarena/tasks/form.py +1024 -232
- browsergym/workarena/tasks/knowledge.py +216 -25
- browsergym/workarena/tasks/list.py +519 -102
- browsergym/workarena/tasks/mark_duplicate_problem.py +171 -0
- browsergym/workarena/tasks/navigation.py +55 -13
- browsergym/workarena/tasks/scripts/extract_all_menu_items.py +9 -2
- browsergym/workarena/tasks/scripts/generate_dashboard_configs.py +6 -5
- browsergym/workarena/tasks/scripts/service_catalog.py +2 -1
- browsergym/workarena/tasks/scripts/validate.py +8 -2
- browsergym/workarena/tasks/send_chat_message.py +90 -0
- browsergym/workarena/tasks/service_catalog.py +94 -26
- browsergym/workarena/tasks/utils/form.py +1 -4
- browsergym/workarena/tasks/utils/private_tasks.py +63 -0
- browsergym/workarena/tasks/utils/utils.py +13 -0
- {browsergym_workarena-0.2.1.dist-info → browsergym_workarena-0.3.0.dist-info}/METADATA +19 -18
- browsergym_workarena-0.3.0.dist-info/RECORD +138 -0
- {browsergym_workarena-0.2.1.dist-info → browsergym_workarena-0.3.0.dist-info}/entry_points.txt +1 -0
- browsergym_workarena-0.2.1.dist-info/RECORD +0 -85
- {browsergym_workarena-0.2.1.dist-info → browsergym_workarena-0.3.0.dist-info}/WHEEL +0 -0
- {browsergym_workarena-0.2.1.dist-info → browsergym_workarena-0.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import faker
|
|
2
|
+
|
|
3
|
+
fake = faker.Faker()
|
|
4
|
+
|
|
5
|
+
from playwright.sync_api._generated import Page
|
|
6
|
+
|
|
7
|
+
from .base import CompositionalTask, HumanEvalTask
|
|
8
|
+
|
|
9
|
+
from ..base import AbstractServiceNowTask
|
|
10
|
+
from ..dashboard import WorkLoadBalancingMinMaxRetrievalTask
|
|
11
|
+
from ..form import EditProblemTask
|
|
12
|
+
from ..knowledge import KnowledgeBaseSearchTask
|
|
13
|
+
from ..list import FilterProblemListForWorkLoadBalancingTask
|
|
14
|
+
from ..navigation import AllMenuTask
|
|
15
|
+
from ..send_chat_message import SendChatMessageGenericTask
|
|
16
|
+
|
|
17
|
+
from ...api.problem import create_problem
|
|
18
|
+
from ...api.report import create_report
|
|
19
|
+
from ...api.user import create_user
|
|
20
|
+
from ...api.utils import db_delete_from_table, table_api_call
|
|
21
|
+
from ...instance import SNowInstance
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class WorkloadBalancingTask(CompositionalTask):
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
seed: int = None,
|
|
28
|
+
instance: SNowInstance = None,
|
|
29
|
+
fixed_config: list[AbstractServiceNowTask] = None,
|
|
30
|
+
level: int = 2,
|
|
31
|
+
min_users: int = 2,
|
|
32
|
+
max_users: int = 4,
|
|
33
|
+
# Ranges to randomly choose from
|
|
34
|
+
max_problem_range: int = [3, 4],
|
|
35
|
+
mid_problem_range: int = [2, 3],
|
|
36
|
+
min_problem_range: int = [1, 2],
|
|
37
|
+
) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Workload balancing task:
|
|
40
|
+
- Navigate to the KB
|
|
41
|
+
- Find the protocol for re-distributing work
|
|
42
|
+
- Find the user who has the greatest number of problems assigned to them
|
|
43
|
+
- Re-assign the problems to the user having the least number of problems assigned to them
|
|
44
|
+
|
|
45
|
+
Parameters:
|
|
46
|
+
-----------
|
|
47
|
+
instance: SNowInstance
|
|
48
|
+
The ServiceNow instance to run the task on.
|
|
49
|
+
fixed_config: list[AbstractServiceNowTask]
|
|
50
|
+
A list of subtasks.
|
|
51
|
+
level: int
|
|
52
|
+
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.
|
|
53
|
+
L3 will start in a private task page describing the information needed to complete the task and the related company protocol
|
|
54
|
+
to complete it.
|
|
55
|
+
min_users: int
|
|
56
|
+
The minimum number of users to create and to distribute the problems to
|
|
57
|
+
max_users: int
|
|
58
|
+
The maximum number of users to create and to distribute the problems to
|
|
59
|
+
max_problem_range: list[int, int]
|
|
60
|
+
The range of the number of problems to assign to the user with the most problems
|
|
61
|
+
mid_problem_range: list[int, int]
|
|
62
|
+
The range of the number of problems to assign to all users but the ones with the least/most problems
|
|
63
|
+
min_problem_range: list[int, int]
|
|
64
|
+
The range of the number of problems to assign to the user with the least problems
|
|
65
|
+
Attributes:
|
|
66
|
+
-----------
|
|
67
|
+
task_description: str
|
|
68
|
+
The start of the task description to be completed. e.g. "Referring to company protocol 'Agent Workload Balancing', re-distribute the problems with description containing {self.problem_hashtag}"
|
|
69
|
+
short_description: str
|
|
70
|
+
A short description of the task to be completed. e.g. "Balance the workload for problems with description containing {self.problem_hashtag}"
|
|
71
|
+
"""
|
|
72
|
+
assert level in [2, 3], "Level must be either 2 or 3"
|
|
73
|
+
self.level = level
|
|
74
|
+
self.protocol_name = "Agent Workload Balancing"
|
|
75
|
+
super().__init__(
|
|
76
|
+
seed=seed,
|
|
77
|
+
instance=instance,
|
|
78
|
+
fixed_config=fixed_config,
|
|
79
|
+
level=level,
|
|
80
|
+
protocol_name=self.protocol_name,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
self.problem_hashtag = (
|
|
84
|
+
f"#PRB{str(id(self) % (10**8)).zfill(9)}" # identifier to select problems
|
|
85
|
+
)
|
|
86
|
+
self.task_description = None
|
|
87
|
+
self.short_description = None
|
|
88
|
+
self.min_users = min_users
|
|
89
|
+
self.max_users = max_users
|
|
90
|
+
self.max_problem_range = max_problem_range
|
|
91
|
+
self.mid_problem_range = mid_problem_range
|
|
92
|
+
self.min_problem_range = min_problem_range
|
|
93
|
+
|
|
94
|
+
# In this case, there will only be 2 users as the values are bound and the top value is excluded in the randint function
|
|
95
|
+
if self.min_users == 2 and self.max_users == 3:
|
|
96
|
+
assert (
|
|
97
|
+
self.min_problem_range[1] <= self.max_problem_range[0]
|
|
98
|
+
), "The problem ranges should not overlap"
|
|
99
|
+
# In this case, there will be 3 users
|
|
100
|
+
else:
|
|
101
|
+
assert (
|
|
102
|
+
self.min_problem_range[1] <= self.mid_problem_range[0]
|
|
103
|
+
and self.mid_problem_range[1] <= self.max_problem_range[0]
|
|
104
|
+
), "The problem ranges should not overlap"
|
|
105
|
+
assert self.max_problem_range[1] <= 6, "The maximum number of problems should not exceed 6"
|
|
106
|
+
|
|
107
|
+
self.plot_title = None # The title of the plot created for the report
|
|
108
|
+
self.lowest_priority = 0 # The lowest priority of the problems; a high number indicates a low priority. Set in the setup_goal method
|
|
109
|
+
|
|
110
|
+
self.category_name = (
|
|
111
|
+
fake.word() + "-" + fake.word()
|
|
112
|
+
) # The category of the problems to re-distribute
|
|
113
|
+
self.category_sys_id = (
|
|
114
|
+
None # The sys_id of the category created for the task; create in the setup_goal method
|
|
115
|
+
)
|
|
116
|
+
self.user_sys_ids = [] # The sys_ids of the users created for the task
|
|
117
|
+
self.problem_sys_ids = [] # The sys_ids of the problems created for the task
|
|
118
|
+
self.report_sys_id = None # The sys_id of the report created for the task
|
|
119
|
+
self.user_with_most_problems = None # The name of the user that has the most problems assigned; defined in the setup_goal method
|
|
120
|
+
self.user_with_least_problems = None # The name of the user that has the least problems assigned; defined in the setup_goal method
|
|
121
|
+
self.problem_to_edit_sys_id = (
|
|
122
|
+
None # The sys_id of the problem to re-assign; defined in the setup_goal method
|
|
123
|
+
)
|
|
124
|
+
self.problem_to_edit_number = (
|
|
125
|
+
None # The number of the problem to re-assign; defined in the setup_goal method
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
def setup_goal(self, page: Page) -> tuple[str, dict]:
|
|
129
|
+
num_users = self.random.randint(self.min_users, self.max_users)
|
|
130
|
+
max_problems = self.random.randint(*self.max_problem_range)
|
|
131
|
+
min_problems = self.random.randint(*self.min_problem_range)
|
|
132
|
+
|
|
133
|
+
# Create users, create problems and assign problems to users
|
|
134
|
+
for i in range(num_users):
|
|
135
|
+
if i == 0:
|
|
136
|
+
num_problems = max_problems
|
|
137
|
+
elif i == num_users - 1:
|
|
138
|
+
num_problems = min_problems
|
|
139
|
+
else:
|
|
140
|
+
num_problems = self.random.randint(*self.mid_problem_range)
|
|
141
|
+
first_name = fake.first_name() + "-" + fake.first_name()
|
|
142
|
+
last_name = fake.last_name() + "-" + fake.last_name()
|
|
143
|
+
user_full_name = first_name + " " + last_name
|
|
144
|
+
_, _, user_sys_id = create_user(
|
|
145
|
+
instance=self.instance,
|
|
146
|
+
first_name=first_name,
|
|
147
|
+
last_name=last_name,
|
|
148
|
+
user_roles=[
|
|
149
|
+
"admin",
|
|
150
|
+
"problem_admin",
|
|
151
|
+
"problem_manager",
|
|
152
|
+
"problem_coordinator",
|
|
153
|
+
"problem_task_analyst",
|
|
154
|
+
],
|
|
155
|
+
random=self.random,
|
|
156
|
+
)
|
|
157
|
+
self.user_sys_ids.append(user_sys_id)
|
|
158
|
+
|
|
159
|
+
if i == 0:
|
|
160
|
+
self.user_with_most_problems = user_full_name
|
|
161
|
+
elif i == num_users - 1:
|
|
162
|
+
self.user_with_least_problems = user_full_name
|
|
163
|
+
|
|
164
|
+
# Create problems assigned to current user
|
|
165
|
+
for j in range(num_problems):
|
|
166
|
+
# Assign a priority to the problem; 1 being highest priority and 5 being lowest
|
|
167
|
+
# the use of j % 5 is to ensure that the priority is between 1 and 5 and that there is
|
|
168
|
+
# only one problem with the lowest priority
|
|
169
|
+
priority = (j % 5) + 1
|
|
170
|
+
self.lowest_priority = max(self.lowest_priority, priority)
|
|
171
|
+
problem_sys_id, problem_number = create_problem(
|
|
172
|
+
instance=self.instance,
|
|
173
|
+
user_sys_id=user_sys_id,
|
|
174
|
+
priority=priority,
|
|
175
|
+
problem_hashtag=self.problem_hashtag,
|
|
176
|
+
return_number=True,
|
|
177
|
+
)
|
|
178
|
+
# The last problem created is the one to re-assign as it will be the one with the lowest priority (highest priority value)
|
|
179
|
+
# and the first user will be the one with the most problems assigned
|
|
180
|
+
if i == 0 and j == num_problems - 1:
|
|
181
|
+
self.problem_to_edit_sys_id = problem_sys_id
|
|
182
|
+
self.problem_to_edit_number = problem_number
|
|
183
|
+
self.problem_sys_ids.append(problem_sys_id)
|
|
184
|
+
|
|
185
|
+
# Create a report for problems of the current category
|
|
186
|
+
self.report_sys_id, plot_title = create_report(
|
|
187
|
+
instance=self.instance,
|
|
188
|
+
table="problem",
|
|
189
|
+
filter_hashtag=self.problem_hashtag,
|
|
190
|
+
field="assigned_to",
|
|
191
|
+
plot_title=f"Problems for with hashtag {self.problem_hashtag}",
|
|
192
|
+
random=self.random,
|
|
193
|
+
)
|
|
194
|
+
self.plot_title = plot_title
|
|
195
|
+
|
|
196
|
+
# Sample a configuration
|
|
197
|
+
config = self._get_config()
|
|
198
|
+
# Get the task description
|
|
199
|
+
self.short_description = (
|
|
200
|
+
f"Balance the workload for problems with hashtag {self.problem_hashtag}"
|
|
201
|
+
)
|
|
202
|
+
self.task_description = f"Referring to company protocol '{self.protocol_name}' (located in the \"Company Protocols\" knowledge base) re-distribute the problems with hashtag={self.problem_hashtag}."
|
|
203
|
+
|
|
204
|
+
goal, info = super().setup_goal(page=page, config=config)
|
|
205
|
+
|
|
206
|
+
return goal, info
|
|
207
|
+
|
|
208
|
+
def _get_config(self) -> list[AbstractServiceNowTask]:
|
|
209
|
+
""" """
|
|
210
|
+
navigate_to_protocol_subtask = [
|
|
211
|
+
# Navigate to the KB
|
|
212
|
+
AllMenuTask(
|
|
213
|
+
instance=self.instance,
|
|
214
|
+
fixed_config={
|
|
215
|
+
"application": "Self-Service",
|
|
216
|
+
"module": "Knowledge",
|
|
217
|
+
"url": "/now/nav/ui/classic/params/target/%24knowledge.do",
|
|
218
|
+
},
|
|
219
|
+
is_validated=False,
|
|
220
|
+
used_in_level_2=False,
|
|
221
|
+
),
|
|
222
|
+
# Find the protocol for on-boarding a new user
|
|
223
|
+
KnowledgeBaseSearchTask(
|
|
224
|
+
instance=self.instance,
|
|
225
|
+
fixed_config={
|
|
226
|
+
"alternative_answers": [],
|
|
227
|
+
"item": f"{self.protocol_name}",
|
|
228
|
+
"question": f"Can you find the '{self.protocol_name}' Protocol in the Knowledge Base?",
|
|
229
|
+
"value": "",
|
|
230
|
+
},
|
|
231
|
+
is_validated=False,
|
|
232
|
+
used_in_level_2=False,
|
|
233
|
+
),
|
|
234
|
+
]
|
|
235
|
+
|
|
236
|
+
find_most_and_least_busy_users_subtask = [
|
|
237
|
+
# Navigate to the reports list
|
|
238
|
+
AllMenuTask(
|
|
239
|
+
instance=self.instance,
|
|
240
|
+
fixed_config={
|
|
241
|
+
"application": "Reports",
|
|
242
|
+
"module": "Administration > All",
|
|
243
|
+
"url": "/now/nav/ui/classic/params/target/sys_report_list.do",
|
|
244
|
+
},
|
|
245
|
+
is_validated=False,
|
|
246
|
+
used_in_level_2=True,
|
|
247
|
+
),
|
|
248
|
+
WorkLoadBalancingMinMaxRetrievalTask(
|
|
249
|
+
instance=self.instance,
|
|
250
|
+
fixed_config={
|
|
251
|
+
"url": "/now/nav/ui/classic/params/target/sys_report",
|
|
252
|
+
"chart_title": self.plot_title,
|
|
253
|
+
"chart_series": "",
|
|
254
|
+
"question": "min",
|
|
255
|
+
},
|
|
256
|
+
is_validated=False,
|
|
257
|
+
used_in_level_2=True,
|
|
258
|
+
problem_hashtag=self.problem_hashtag,
|
|
259
|
+
),
|
|
260
|
+
]
|
|
261
|
+
|
|
262
|
+
reassign_problem_subtask = [
|
|
263
|
+
# Navigate to the hardware asset list
|
|
264
|
+
AllMenuTask(
|
|
265
|
+
instance=self.instance,
|
|
266
|
+
fixed_config={
|
|
267
|
+
"application": "Problem",
|
|
268
|
+
"module": "All",
|
|
269
|
+
"url": "/now/nav/ui/classic/params/target/problem_list.do",
|
|
270
|
+
},
|
|
271
|
+
is_validated=False,
|
|
272
|
+
used_in_level_2=True,
|
|
273
|
+
),
|
|
274
|
+
# Filter the problems by assignee, and priority = lowest priority
|
|
275
|
+
# The existence of a lower priority problem is guaranteed
|
|
276
|
+
FilterProblemListForWorkLoadBalancingTask(
|
|
277
|
+
instance=self.instance,
|
|
278
|
+
fixed_config={
|
|
279
|
+
"filter_columns": ["assigned_to", "priority"],
|
|
280
|
+
"filter_kind": "AND",
|
|
281
|
+
"filter_values": [
|
|
282
|
+
f"{self.user_with_most_problems}",
|
|
283
|
+
f"{self.lowest_priority}",
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
is_validated=False,
|
|
287
|
+
used_in_level_2=True,
|
|
288
|
+
goal=f'Create a filter to find problems where \n - "Assigned to" is the user with the most problems assigned and \n - "Priority" is "{self.lowest_priority}".',
|
|
289
|
+
),
|
|
290
|
+
# Assign a problem to the user with the least problems assigned to them
|
|
291
|
+
EditProblemTask(
|
|
292
|
+
instance=self.instance,
|
|
293
|
+
new_values={"assigned_to": f"{self.user_with_least_problems}"},
|
|
294
|
+
record_sys_id=self.problem_to_edit_sys_id,
|
|
295
|
+
record_number=self.problem_to_edit_number,
|
|
296
|
+
is_validated=True,
|
|
297
|
+
used_in_level_2=True,
|
|
298
|
+
level=self.level,
|
|
299
|
+
),
|
|
300
|
+
]
|
|
301
|
+
|
|
302
|
+
config = (
|
|
303
|
+
navigate_to_protocol_subtask
|
|
304
|
+
+ find_most_and_least_busy_users_subtask
|
|
305
|
+
+ reassign_problem_subtask
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
return config
|
|
309
|
+
|
|
310
|
+
def teardown(self) -> None:
|
|
311
|
+
# Delete the users
|
|
312
|
+
for user_sys_id in self.user_sys_ids:
|
|
313
|
+
record_exists = table_api_call(
|
|
314
|
+
instance=self.instance,
|
|
315
|
+
table="sys_user",
|
|
316
|
+
params={"sysparm_query": f"sys_id={user_sys_id}"},
|
|
317
|
+
)
|
|
318
|
+
if record_exists:
|
|
319
|
+
db_delete_from_table(
|
|
320
|
+
instance=self.instance,
|
|
321
|
+
table="sys_user",
|
|
322
|
+
sys_id=user_sys_id,
|
|
323
|
+
)
|
|
324
|
+
# Delete the problems
|
|
325
|
+
for problem_sys_id in self.problem_sys_ids:
|
|
326
|
+
record_exists = table_api_call(
|
|
327
|
+
instance=self.instance,
|
|
328
|
+
table="problem",
|
|
329
|
+
params={"sysparm_query": f"sys_id={problem_sys_id}"},
|
|
330
|
+
)
|
|
331
|
+
if record_exists:
|
|
332
|
+
db_delete_from_table(
|
|
333
|
+
instance=self.instance,
|
|
334
|
+
table="problem",
|
|
335
|
+
sys_id=problem_sys_id,
|
|
336
|
+
)
|
|
337
|
+
# Delete the report
|
|
338
|
+
db_delete_from_table(
|
|
339
|
+
instance=self.instance,
|
|
340
|
+
table="sys_report",
|
|
341
|
+
sys_id=self.report_sys_id,
|
|
342
|
+
)
|
|
343
|
+
super().teardown()
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
class WorkloadBalancingSmallTask(WorkloadBalancingTask, HumanEvalTask):
|
|
347
|
+
def __init__(self, seed: int = None, instance: SNowInstance = None, level: int = 2) -> None:
|
|
348
|
+
super().__init__(
|
|
349
|
+
seed=seed,
|
|
350
|
+
instance=instance,
|
|
351
|
+
level=level,
|
|
352
|
+
min_users=2,
|
|
353
|
+
max_users=4,
|
|
354
|
+
max_problem_range=[4, 6],
|
|
355
|
+
mid_problem_range=[3, 4],
|
|
356
|
+
min_problem_range=[1, 3],
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class WorkloadBalancingMediumTask(WorkloadBalancingTask):
|
|
361
|
+
def __init__(self, seed: int = None, instance: SNowInstance = None, level: int = 2) -> None:
|
|
362
|
+
super().__init__(
|
|
363
|
+
seed=seed,
|
|
364
|
+
instance=instance,
|
|
365
|
+
level=level,
|
|
366
|
+
min_users=5,
|
|
367
|
+
max_users=7,
|
|
368
|
+
max_problem_range=[5, 6],
|
|
369
|
+
mid_problem_range=[3, 5],
|
|
370
|
+
min_problem_range=[1, 3],
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class WorkloadBalancingLargeTask(WorkloadBalancingTask):
|
|
375
|
+
def __init__(self, seed: int = None, instance: SNowInstance = None, level: int = 2) -> None:
|
|
376
|
+
super().__init__(
|
|
377
|
+
seed=seed,
|
|
378
|
+
instance=instance,
|
|
379
|
+
level=level,
|
|
380
|
+
min_users=8,
|
|
381
|
+
max_users=10,
|
|
382
|
+
max_problem_range=[5, 6],
|
|
383
|
+
mid_problem_range=[3, 5],
|
|
384
|
+
min_problem_range=[1, 3],
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
local_vars = locals().copy()
|
|
389
|
+
|
|
390
|
+
__TASKS__ = [
|
|
391
|
+
var
|
|
392
|
+
for var in local_vars.values()
|
|
393
|
+
if isinstance(var, type)
|
|
394
|
+
and issubclass(var, WorkloadBalancingTask)
|
|
395
|
+
and var is not WorkloadBalancingTask
|
|
396
|
+
]
|