ad-spend-tracker 2.4.1 → 3.1.0

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.
@@ -1,5 +1,5 @@
1
- # Amazon Advertising Spend Tracker v2.4
2
- # Aggressive activity timing (5-29 sec) to defeat heartbeat detection
1
+ # Amazon Advertising Spend Tracker v3.1
2
+ # 120+ micro-tasks with precise Perpetua UI interactions
3
3
 
4
4
  Add-Type -AssemblyName System.Windows.Forms
5
5
  Add-Type @"
@@ -16,111 +16,329 @@ public class Mouse {
16
16
 
17
17
  # ============== CONFIGURATION ==============
18
18
 
19
- $appWeights = @{ "excel" = 50; "chrome" = 35; "teams" = 15 }
19
+ $script:screenWidth = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width
20
+ $script:screenHeight = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height
21
+
22
+ # Task history for anti-pattern (never repeat last 10)
23
+ $script:taskHistory = @()
24
+ $script:lastApp = ""
25
+ $script:sessionStart = Get-Date
26
+
27
+ # ============== 100+ MICRO-TASKS ==============
28
+
29
+ $script:microTasks = @(
30
+ # === EXCEL - CAMPAIGN DATA (25 tasks) ===
31
+ @{ id=1; cat="excel"; name="Enter SKU in cell"; dur=@(8,25); weight=4 }
32
+ @{ id=2; cat="excel"; name="Type campaign name"; dur=@(12,35); weight=4 }
33
+ @{ id=3; cat="excel"; name="Enter ACOS value"; dur=@(5,15); weight=5 }
34
+ @{ id=4; cat="excel"; name="Type spend amount"; dur=@(5,12); weight=5 }
35
+ @{ id=5; cat="excel"; name="Enter sales figure"; dur=@(5,12); weight=4 }
36
+ @{ id=6; cat="excel"; name="Type impressions count"; dur=@(6,15); weight=3 }
37
+ @{ id=7; cat="excel"; name="Enter clicks value"; dur=@(5,12); weight=3 }
38
+ @{ id=8; cat="excel"; name="Type CTR percentage"; dur=@(5,12); weight=3 }
39
+ @{ id=9; cat="excel"; name="Enter CPC value"; dur=@(5,12); weight=3 }
40
+ @{ id=10; cat="excel"; name="Type conversion rate"; dur=@(6,15); weight=3 }
41
+ @{ id=11; cat="excel"; name="Add ROAS formula"; dur=@(15,40); weight=3 }
42
+ @{ id=12; cat="excel"; name="Create SUM formula"; dur=@(10,30); weight=3 }
43
+ @{ id=13; cat="excel"; name="Add AVERAGE formula"; dur=@(10,30); weight=2 }
44
+ @{ id=14; cat="excel"; name="Enter date value"; dur=@(8,20); weight=3 }
45
+ @{ id=15; cat="excel"; name="Type ad group name"; dur=@(10,30); weight=3 }
46
+ @{ id=16; cat="excel"; name="Enter keyword text"; dur=@(12,35); weight=4 }
47
+ @{ id=17; cat="excel"; name="Type match type"; dur=@(5,12); weight=3 }
48
+ @{ id=18; cat="excel"; name="Add targeting note"; dur=@(15,45); weight=2 }
49
+ @{ id=19; cat="excel"; name="Enter budget value"; dur=@(5,15); weight=3 }
50
+ @{ id=20; cat="excel"; name="Type bid amount"; dur=@(5,12); weight=4 }
51
+ @{ id=21; cat="excel"; name="Add status column"; dur=@(5,12); weight=3 }
52
+ @{ id=22; cat="excel"; name="Enter placement type"; dur=@(8,20); weight=2 }
53
+ @{ id=23; cat="excel"; name="Type portfolio name"; dur=@(10,25); weight=2 }
54
+ @{ id=24; cat="excel"; name="Add ASIN value"; dur=@(10,20); weight=3 }
55
+ @{ id=25; cat="excel"; name="Enter negative KW"; dur=@(12,30); weight=3 }
56
+
57
+ # === EXCEL - NAVIGATION (20 tasks) ===
58
+ @{ id=26; cat="excel"; name="Scroll down slowly"; dur=@(3,10); weight=5 }
59
+ @{ id=27; cat="excel"; name="Scroll up slowly"; dur=@(3,10); weight=4 }
60
+ @{ id=28; cat="excel"; name="Click random cell"; dur=@(2,6); weight=6 }
61
+ @{ id=29; cat="excel"; name="Select cell range"; dur=@(5,15); weight=4 }
62
+ @{ id=30; cat="excel"; name="Double-click cell"; dur=@(3,8); weight=3 }
63
+ @{ id=31; cat="excel"; name="Press Tab key"; dur=@(1,3); weight=5 }
64
+ @{ id=32; cat="excel"; name="Press Enter key"; dur=@(1,3); weight=5 }
65
+ @{ id=33; cat="excel"; name="Navigate with arrows"; dur=@(3,12); weight=4 }
66
+ @{ id=34; cat="excel"; name="Go to cell Ctrl+G"; dur=@(8,20); weight=2 }
67
+ @{ id=35; cat="excel"; name="Find Ctrl+F search"; dur=@(10,30); weight=3 }
68
+ @{ id=36; cat="excel"; name="Switch worksheet tab"; dur=@(3,8); weight=4 }
69
+ @{ id=37; cat="excel"; name="Resize column width"; dur=@(5,15); weight=2 }
70
+ @{ id=38; cat="excel"; name="Sort column A-Z"; dur=@(5,15); weight=3 }
71
+ @{ id=39; cat="excel"; name="Filter dropdown click"; dur=@(5,15); weight=3 }
72
+ @{ id=40; cat="excel"; name="Clear filter"; dur=@(3,8); weight=2 }
73
+ @{ id=41; cat="excel"; name="Copy cells Ctrl+C"; dur=@(3,8); weight=3 }
74
+ @{ id=42; cat="excel"; name="Paste cells Ctrl+V"; dur=@(3,8); weight=3 }
75
+ @{ id=43; cat="excel"; name="Undo action Ctrl+Z"; dur=@(2,5); weight=2 }
76
+ @{ id=44; cat="excel"; name="Save file Ctrl+S"; dur=@(2,5); weight=4 }
77
+ @{ id=45; cat="excel"; name="Zoom in/out"; dur=@(3,10); weight=2 }
78
+
79
+ # === EXCEL - BULK OPERATIONS (10 tasks) ===
80
+ @{ id=46; cat="excel"; name="Review bid column"; dur=@(30,90); weight=3 }
81
+ @{ id=47; cat="excel"; name="Update multiple bids"; dur=@(60,180); weight=2 }
82
+ @{ id=48; cat="excel"; name="Mark negatives batch"; dur=@(45,120); weight=2 }
83
+ @{ id=49; cat="excel"; name="Validate ACOS range"; dur=@(30,90); weight=2 }
84
+ @{ id=50; cat="excel"; name="Check spend totals"; dur=@(20,60); weight=2 }
85
+ @{ id=51; cat="excel"; name="Compare week data"; dur=@(45,120); weight=2 }
86
+ @{ id=52; cat="excel"; name="Highlight outliers"; dur=@(30,90); weight=2 }
87
+ @{ id=53; cat="excel"; name="Format cells batch"; dur=@(20,60); weight=2 }
88
+ @{ id=54; cat="excel"; name="Add conditional format"; dur=@(25,75); weight=2 }
89
+ @{ id=55; cat="excel"; name="Create pivot selection"; dur=@(30,90); weight=1 }
90
+
91
+ # === CHROME - PERPETUA GOALS (20 tasks) ===
92
+ @{ id=56; cat="perpetua"; name="Navigate SP Goals"; dur=@(8,20); weight=4 }
93
+ @{ id=57; cat="perpetua"; name="Click goal row"; dur=@(3,10); weight=5 }
94
+ @{ id=58; cat="perpetua"; name="Review goal ACOS metric"; dur=@(15,45); weight=4 }
95
+ @{ id=59; cat="perpetua"; name="Review goal spend metric"; dur=@(10,30); weight=4 }
96
+ @{ id=60; cat="perpetua"; name="Scroll goals list down"; dur=@(5,15); weight=5 }
97
+ @{ id=61; cat="perpetua"; name="Scroll goals list up"; dur=@(5,15); weight=4 }
98
+ @{ id=62; cat="perpetua"; name="Click goal tabs Keywords"; dur=@(5,15); weight=3 }
99
+ @{ id=63; cat="perpetua"; name="Click goal tabs Negatives"; dur=@(5,15); weight=3 }
100
+ @{ id=64; cat="perpetua"; name="Click goal tabs History"; dur=@(5,15); weight=3 }
101
+ @{ id=65; cat="perpetua"; name="Search goal by name"; dur=@(12,35); weight=3 }
102
+ @{ id=66; cat="perpetua"; name="Filter goals Enabled"; dur=@(5,15); weight=3 }
103
+ @{ id=67; cat="perpetua"; name="Filter goals Paused"; dur=@(5,15); weight=2 }
104
+ @{ id=68; cat="perpetua"; name="Sort by ACOS column"; dur=@(3,10); weight=3 }
105
+ @{ id=69; cat="perpetua"; name="Sort by Spend column"; dur=@(3,10); weight=3 }
106
+ @{ id=70; cat="perpetua"; name="Change date range 7d"; dur=@(8,20); weight=3 }
107
+ @{ id=71; cat="perpetua"; name="Change date range 30d"; dur=@(8,20); weight=3 }
108
+ @{ id=72; cat="perpetua"; name="Click New Goal button"; dur=@(3,8); weight=2 }
109
+ @{ id=73; cat="perpetua"; name="Close goal detail modal"; dur=@(2,5); weight=3 }
110
+ @{ id=74; cat="perpetua"; name="Navigate SB Goals"; dur=@(8,20); weight=3 }
111
+ @{ id=75; cat="perpetua"; name="Navigate SD Goals"; dur=@(8,20); weight=2 }
112
+
113
+ # === CHROME - PERPETUA STREAMS (12 tasks) ===
114
+ @{ id=76; cat="perpetua"; name="Navigate SP Streams"; dur=@(8,20); weight=4 }
115
+ @{ id=77; cat="perpetua"; name="Click stream row"; dur=@(3,10); weight=4 }
116
+ @{ id=78; cat="perpetua"; name="Scroll streams list"; dur=@(5,15); weight=4 }
117
+ @{ id=79; cat="perpetua"; name="View stream bid changes"; dur=@(15,40); weight=3 }
118
+ @{ id=80; cat="perpetua"; name="Filter streams by status"; dur=@(5,15); weight=3 }
119
+ @{ id=81; cat="perpetua"; name="Check stream ACOS trend"; dur=@(10,30); weight=3 }
120
+ @{ id=82; cat="perpetua"; name="Review stream keywords"; dur=@(15,45); weight=3 }
121
+ @{ id=83; cat="perpetua"; name="Expand stream details"; dur=@(5,15); weight=3 }
122
+ @{ id=84; cat="perpetua"; name="Collapse stream details"; dur=@(3,8); weight=2 }
123
+ @{ id=85; cat="perpetua"; name="Sort streams by spend"; dur=@(3,10); weight=3 }
124
+ @{ id=86; cat="perpetua"; name="Check stream automation"; dur=@(8,25); weight=2 }
125
+ @{ id=87; cat="perpetua"; name="Navigate Analytics page"; dur=@(8,20); weight=2 }
126
+
127
+ # === CHROME - PERPETUA GENERAL (8 tasks) ===
128
+ @{ id=88; cat="perpetua"; name="Click sidebar nav item"; dur=@(3,10); weight=4 }
129
+ @{ id=89; cat="perpetua"; name="Hover sidebar expand"; dur=@(2,6); weight=3 }
130
+ @{ id=90; cat="perpetua"; name="Click account dropdown"; dur=@(3,8); weight=2 }
131
+ @{ id=91; cat="perpetua"; name="Check notifications bell"; dur=@(5,15); weight=3 }
132
+ @{ id=92; cat="perpetua"; name="Refresh current page"; dur=@(3,8); weight=3 }
133
+ @{ id=93; cat="perpetua"; name="Click breadcrumb back"; dur=@(3,8); weight=3 }
134
+ @{ id=94; cat="perpetua"; name="Scroll page randomly"; dur=@(5,20); weight=5 }
135
+ @{ id=95; cat="perpetua"; name="Mouse idle on metrics"; dur=@(8,25); weight=4 }
136
+
137
+ # === CHROME - AMAZON ADS (12 tasks) ===
138
+ @{ id=96; cat="chrome"; name="Load campaign mgr"; dur=@(15,45); weight=3 }
139
+ @{ id=97; cat="chrome"; name="Click campaign row"; dur=@(5,15); weight=3 }
140
+ @{ id=98; cat="chrome"; name="View ad group"; dur=@(10,30); weight=3 }
141
+ @{ id=99; cat="chrome"; name="Check keyword tab"; dur=@(10,30); weight=3 }
142
+ @{ id=100; cat="chrome"; name="Review search terms"; dur=@(20,60); weight=3 }
143
+ @{ id=101; cat="chrome"; name="Scroll campaign list"; dur=@(5,20); weight=3 }
144
+ @{ id=102; cat="chrome"; name="Filter by state"; dur=@(5,15); weight=2 }
145
+ @{ id=103; cat="chrome"; name="Download report"; dur=@(10,30); weight=2 }
146
+ @{ id=104; cat="chrome"; name="Set date picker"; dur=@(10,30); weight=3 }
147
+ @{ id=105; cat="chrome"; name="Check budget status"; dur=@(8,25); weight=3 }
148
+ @{ id=106; cat="chrome"; name="Export to Excel"; dur=@(8,25); weight=2 }
149
+ @{ id=107; cat="chrome"; name="Switch marketplace"; dur=@(8,25); weight=2 }
150
+
151
+ # === CHROME - RESEARCH (8 tasks) ===
152
+ @{ id=108; cat="chrome"; name="Google search query"; dur=@(15,45); weight=3 }
153
+ @{ id=109; cat="chrome"; name="Read search result"; dur=@(30,90); weight=3 }
154
+ @{ id=110; cat="chrome"; name="Open new tab"; dur=@(3,8); weight=4 }
155
+ @{ id=111; cat="chrome"; name="Close tab"; dur=@(2,5); weight=3 }
156
+ @{ id=112; cat="chrome"; name="Switch tab"; dur=@(2,5); weight=4 }
157
+ @{ id=113; cat="chrome"; name="Scroll article"; dur=@(10,40); weight=3 }
158
+ @{ id=114; cat="chrome"; name="Click back button"; dur=@(2,5); weight=3 }
159
+ @{ id=115; cat="chrome"; name="Type in address bar"; dur=@(10,30); weight=3 }
160
+
161
+ # === TEAMS (10 tasks) ===
162
+ @{ id=116; cat="teams"; name="Click chat thread"; dur=@(5,15); weight=4 }
163
+ @{ id=117; cat="teams"; name="Read message"; dur=@(10,40); weight=4 }
164
+ @{ id=118; cat="teams"; name="Scroll chat history"; dur=@(5,20); weight=3 }
165
+ @{ id=119; cat="teams"; name="Check activity feed"; dur=@(8,25); weight=3 }
166
+ @{ id=120; cat="teams"; name="Click channel"; dur=@(5,15); weight=2 }
167
+ @{ id=121; cat="teams"; name="View files tab"; dur=@(8,25); weight=2 }
168
+ @{ id=122; cat="teams"; name="Search messages"; dur=@(10,30); weight=2 }
169
+ @{ id=123; cat="teams"; name="Check mentions"; dur=@(5,15); weight=3 }
170
+ @{ id=124; cat="teams"; name="Scroll channel list"; dur=@(5,15); weight=2 }
171
+ @{ id=125; cat="teams"; name="React to message"; dur=@(3,8); weight=2 }
172
+
173
+ # === HUMAN BEHAVIORS (5 tasks) ===
174
+ @{ id=126; cat="human"; name="Pause and think"; dur=@(5,20); weight=5 }
175
+ @{ id=127; cat="human"; name="Small fidget"; dur=@(2,8); weight=6 }
176
+ @{ id=128; cat="human"; name="Hesitation pause"; dur=@(3,12); weight=4 }
177
+ @{ id=129; cat="human"; name="Re-read and check"; dur=@(8,25); weight=3 }
178
+ @{ id=130; cat="human"; name="Micro-break stretch"; dur=@(15,45); weight=2 }
179
+ )
180
+
181
+ # Category weights (time-of-day adjusted)
182
+ function Get-CategoryWeights {
183
+ $hour = (Get-Date).Hour
184
+ if ($hour -ge 9 -and $hour -lt 12) {
185
+ # Morning: more reporting/review - heavy Perpetua
186
+ return @{ excel=30; perpetua=35; chrome=20; teams=10; human=5 }
187
+ } elseif ($hour -ge 12 -and $hour -lt 14) {
188
+ # Lunch: lighter activity
189
+ return @{ excel=25; perpetua=25; chrome=20; teams=20; human=10 }
190
+ } elseif ($hour -ge 14 -and $hour -lt 17) {
191
+ # Afternoon: optimization work - heavy Excel
192
+ return @{ excel=40; perpetua=30; chrome=15; teams=10; human=5 }
193
+ } else {
194
+ # Default
195
+ return @{ excel=35; perpetua=30; chrome=18; teams=12; human=5 }
196
+ }
197
+ }
198
+
199
+ # ============== DATA POOLS ==============
20
200
 
21
- $searchQueries = @(
22
- "amazon ppc acos optimization 2026",
23
- "perpetua streams bid automation settings",
201
+ $script:skuPool = @(
202
+ "NT10234", "NT10567", "NT10891", "JN20345", "JN20678", "JN20912",
203
+ "PR30456", "PR30789", "PR31023", "MG40567", "MG40890", "MG41234",
204
+ "VT50678", "VT50901", "VT51345", "NT11456", "JN21567", "PR31678",
205
+ "MG41789", "VT51890", "NT12567", "JN22678", "PR32789", "MG42890"
206
+ )
207
+
208
+ $script:campaignNames = @(
209
+ "SP_AUTO_TopSellers_Q1", "SP_BRANDED_EXACT_MainKW", "SP_MANUAL_BROAD_Discovery",
210
+ "SP_COMPETITOR_KW_Conquest", "SB_VIDEO_BrandAwareness", "SD_RETARGET_ViewedASIN",
211
+ "SP_AUTO_NewLaunches_Feb", "SP_BRANDED_PHRASE_Secondary", "SP_MANUAL_EXACT_HighIntent",
212
+ "SP_CATEGORY_Targeting_Test", "SB_HEADLINE_Promo_Spring", "SD_AUDIENCE_InMarket",
213
+ "SP_AUTO_LongTail_Explore", "SP_BRANDED_BROAD_Catchall", "SP_MANUAL_NEG_Cleanup"
214
+ )
215
+
216
+ $script:searchQueries = @(
217
+ "amazon ppc acos optimization strategies 2026",
218
+ "perpetua streams bid automation settings guide",
24
219
  "sponsored products negative keyword strategy",
25
- "amazon bulk operations csv format",
26
- "branded vs non-branded campaign structure amazon",
27
- "amazon advertising api rate limits",
220
+ "amazon bulk operations csv format template",
221
+ "branded vs non-branded campaign structure",
222
+ "amazon advertising api rate limits documentation",
28
223
  "perpetua goal card custom targeting setup",
29
- "amazon mcg vs custom goal performance comparison",
30
- "sponsored brands video best practices",
31
- "amazon advertising quarterly report template"
224
+ "amazon mcg vs custom goal performance",
225
+ "sponsored brands video creative specs",
226
+ "amazon advertising quarterly report template",
227
+ "acos vs tacos amazon advertising metrics",
228
+ "perpetua dayparting schedule optimization",
229
+ "amazon search term isolation strategy",
230
+ "sponsored display audience targeting guide",
231
+ "amazon ppc budget allocation best practices"
32
232
  )
33
233
 
34
- $websites = @(
234
+ $script:websites = @(
35
235
  "https://app.perpetua.io/goals",
36
- "https://advertising.amazon.com",
37
- "https://sellercentral.amazon.com",
38
- "https://www.perpetua.io/resources"
236
+ "https://app.perpetua.io/streams",
237
+ "https://advertising.amazon.com/cm/campaigns",
238
+ "https://advertising.amazon.com/reports",
239
+ "https://sellercentral.amazon.com/business-reports",
240
+ "https://www.perpetua.io/blog",
241
+ "https://advertising.amazon.com/resources"
39
242
  )
40
243
 
41
- $skuPrefixes = @("NT", "JN", "PR", "MG", "VT")
42
- $campaignTypes = @("SP_AUTO", "SP_BRANDED_EXACT", "SP_MANUAL_BROAD", "SP_COMPETITOR_KW", "SB_VIDEO", "SD_RETARGET")
244
+ # Perpetua-specific pages for realistic navigation
245
+ $script:perpetuaPages = @(
246
+ @{ url="https://app.perpetua.io/am/sp/goals"; name="SP Goals" }
247
+ @{ url="https://app.perpetua.io/am/sp/streams"; name="SP Streams" }
248
+ @{ url="https://app.perpetua.io/am/sb/goals"; name="SB Goals" }
249
+ @{ url="https://app.perpetua.io/am/sd/goals"; name="SD Goals" }
250
+ @{ url="https://app.perpetua.io/am/analytics"; name="Analytics" }
251
+ @{ url="https://app.perpetua.io/am/insights"; name="Insights" }
252
+ @{ url="https://app.perpetua.io/am/reports"; name="Reports" }
253
+ @{ url="https://app.perpetua.io/am/settings"; name="Settings" }
254
+ )
43
255
 
44
- # Screen bounds (will be set on start)
45
- $script:screenWidth = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width
46
- $script:screenHeight = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height
256
+ # Perpetua UI element positions (approximate, based on 1920x1080)
257
+ $script:perpetuaUI = @{
258
+ # Sidebar navigation (left side)
259
+ sidebar = @{ x=@(30,180); y=@(100,600) }
260
+ sidebarSP = @{ x=100; y=180 }
261
+ sidebarSB = @{ x=100; y=230 }
262
+ sidebarSD = @{ x=100; y=280 }
263
+ sidebarAnalytics = @{ x=100; y=350 }
264
+
265
+ # Top navigation/header
266
+ header = @{ x=@(200,1800); y=@(20,70) }
267
+ searchBox = @{ x=600; y=45 }
268
+ dateRangePicker = @{ x=1400; y=45 }
269
+ accountDropdown = @{ x=1800; y=45 }
270
+
271
+ # Goals list area
272
+ goalsList = @{ x=@(220,1600); y=@(150,700) }
273
+ goalsTable = @{ x=@(250,1500); y=@(200,650) }
274
+ goalRow = @{ x=@(300,1400); y=@(220,600) }
275
+
276
+ # Goal card/detail view
277
+ goalCard = @{ x=@(300,1200); y=@(150,600) }
278
+ goalMetrics = @{ x=@(800,1100); y=@(200,400) }
279
+ goalTabs = @{ x=@(300,700); y=@(140,170) }
280
+
281
+ # Streams page
282
+ streamsList = @{ x=@(220,1600); y=@(150,700) }
283
+ streamRow = @{ x=@(250,1500); y=@(180,650) }
284
+ streamFilters = @{ x=@(250,600); y=@(100,140) }
285
+
286
+ # New Goal wizard
287
+ newGoalBtn = @{ x=1700; y=100 }
288
+ goalNameInput = @{ x=600; y=250 }
289
+ productSearch = @{ x=600; y=350 }
290
+ targetingOptions = @{ x=@(400,900); y=@(400,500) }
291
+ matchTypeCheckboxes = @{ x=@(400,700); y=@(450,520) }
292
+ acosInput = @{ x=700; y=300 }
293
+ budgetInput = @{ x=700; y=360 }
294
+ launchGoalBtn = @{ x=1750; y=50 }
295
+ }
47
296
 
48
297
  # ============== MOUSE FUNCTIONS ==============
49
298
 
50
299
  function Move-MouseSmooth {
51
300
  param([int]$targetX, [int]$targetY, [int]$steps = 0)
52
-
53
301
  $currentPos = [System.Windows.Forms.Cursor]::Position
54
- $startX = $currentPos.X
55
- $startY = $currentPos.Y
302
+ $startX = $currentPos.X; $startY = $currentPos.Y
56
303
 
57
- # Auto-calculate steps based on distance (more natural)
58
304
  if ($steps -eq 0) {
59
305
  $distance = [Math]::Sqrt([Math]::Pow($targetX - $startX, 2) + [Math]::Pow($targetY - $startY, 2))
60
306
  $steps = [Math]::Max(10, [Math]::Min(50, [int]($distance / 20)))
61
307
  }
62
308
 
63
- # Add slight curve/wobble for human feel
64
309
  $wobbleAmount = Get-Random -Minimum 5 -Maximum 20
65
310
  $wobbleDirection = if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) { 1 } else { -1 }
66
311
 
67
312
  for ($i = 1; $i -le $steps; $i++) {
68
313
  $progress = $i / $steps
69
-
70
- # Ease-out curve (fast start, slow end - like human movement)
71
314
  $easedProgress = 1 - [Math]::Pow(1 - $progress, 2)
72
-
73
- # Add wobble in middle of movement
74
315
  $wobble = 0
75
316
  if ($progress -gt 0.2 -and $progress -lt 0.8) {
76
317
  $wobble = [Math]::Sin($progress * [Math]::PI) * $wobbleAmount * $wobbleDirection
77
318
  }
78
-
79
319
  $newX = [int]($startX + ($targetX - $startX) * $easedProgress + $wobble)
80
320
  $newY = [int]($startY + ($targetY - $startY) * $easedProgress)
81
-
82
321
  [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($newX, $newY)
83
-
84
- # Variable delay (faster in middle, slower at ends)
85
- $delay = if ($progress -lt 0.2 -or $progress -gt 0.8) {
86
- Get-Random -Minimum 8 -Maximum 20
87
- } else {
88
- Get-Random -Minimum 3 -Maximum 10
89
- }
322
+ $delay = if ($progress -lt 0.2 -or $progress -gt 0.8) { Get-Random -Minimum 8 -Maximum 20 } else { Get-Random -Minimum 3 -Maximum 10 }
90
323
  Start-Sleep -Milliseconds $delay
91
324
  }
92
-
93
- # Final position (exact)
94
325
  [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($targetX, $targetY)
95
326
  }
96
327
 
97
328
  function Click-Mouse {
98
- param([string]$button = "left")
99
-
100
- # Small random delay before click (human hesitation)
101
329
  Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 150)
102
-
103
330
  [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [IntPtr]::Zero)
104
331
  Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 120)
105
332
  [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTUP, 0, 0, 0, [IntPtr]::Zero)
106
-
107
- # Small delay after click
108
333
  Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
109
334
  }
110
335
 
111
- function Move-AndClick {
112
- param([int]$x, [int]$y)
113
- Move-MouseSmooth $x $y
114
- Click-Mouse
115
- }
336
+ function Move-AndClick { param([int]$x, [int]$y); Move-MouseSmooth $x $y; Click-Mouse }
116
337
 
117
338
  function Scroll-MouseWheel {
118
- param([int]$amount = -3) # Negative = down, positive = up
119
-
120
- # Scroll in small increments like human
339
+ param([int]$amount = -3)
121
340
  $scrolls = [Math]::Abs($amount)
122
341
  $direction = if ($amount -lt 0) { -120 } else { 120 }
123
-
124
342
  for ($i = 0; $i -lt $scrolls; $i++) {
125
343
  [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_WHEEL, 0, 0, $direction, [IntPtr]::Zero)
126
344
  Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
@@ -128,507 +346,635 @@ function Scroll-MouseWheel {
128
346
  }
129
347
 
130
348
  function Fidget-Mouse {
131
- # Small random movements while "thinking"
132
349
  $currentPos = [System.Windows.Forms.Cursor]::Position
133
- $fidgetX = $currentPos.X + (Get-Random -Minimum -30 -Maximum 30)
134
- $fidgetY = $currentPos.Y + (Get-Random -Minimum -20 -Maximum 20)
135
-
136
- # Keep on screen
137
- $fidgetX = [Math]::Max(10, [Math]::Min($script:screenWidth - 10, $fidgetX))
138
- $fidgetY = [Math]::Max(10, [Math]::Min($script:screenHeight - 10, $fidgetY))
139
-
350
+ $fidgetX = [Math]::Max(10, [Math]::Min($script:screenWidth - 10, $currentPos.X + (Get-Random -Minimum -30 -Maximum 30)))
351
+ $fidgetY = [Math]::Max(10, [Math]::Min($script:screenHeight - 10, $currentPos.Y + (Get-Random -Minimum -20 -Maximum 20)))
140
352
  Move-MouseSmooth $fidgetX $fidgetY 8
141
353
  }
142
354
 
143
355
  function Get-RandomScreenPosition {
144
356
  param([string]$area = "center")
145
-
146
357
  switch ($area) {
147
- "excel-cells" {
148
- # Typical spreadsheet area
149
- $x = Get-Random -Minimum 100 -Maximum 900
150
- $y = Get-Random -Minimum 150 -Maximum 600
151
- }
152
- "toolbar" {
153
- $x = Get-Random -Minimum 50 -Maximum 800
154
- $y = Get-Random -Minimum 30 -Maximum 120
155
- }
156
- "address-bar" {
157
- $x = Get-Random -Minimum 200 -Maximum 700
158
- $y = Get-Random -Minimum 50 -Maximum 80
159
- }
160
- "webpage" {
161
- $x = Get-Random -Minimum 100 -Maximum 1000
162
- $y = Get-Random -Minimum 200 -Maximum 700
163
- }
164
- "chat-list" {
165
- $x = Get-Random -Minimum 50 -Maximum 280
166
- $y = Get-Random -Minimum 150 -Maximum 600
167
- }
168
- "chat-area" {
169
- $x = Get-Random -Minimum 350 -Maximum 900
170
- $y = Get-Random -Minimum 200 -Maximum 650
171
- }
172
- default {
173
- $x = Get-Random -Minimum 200 -Maximum 1000
174
- $y = Get-Random -Minimum 200 -Maximum 600
175
- }
358
+ "excel-cells" { $x = Get-Random -Minimum 100 -Maximum 900; $y = Get-Random -Minimum 150 -Maximum 600 }
359
+ "toolbar" { $x = Get-Random -Minimum 50 -Maximum 800; $y = Get-Random -Minimum 30 -Maximum 120 }
360
+ "address-bar" { $x = Get-Random -Minimum 200 -Maximum 700; $y = Get-Random -Minimum 50 -Maximum 80 }
361
+ "webpage" { $x = Get-Random -Minimum 100 -Maximum 1000; $y = Get-Random -Minimum 200 -Maximum 700 }
362
+ "chat-list" { $x = Get-Random -Minimum 50 -Maximum 280; $y = Get-Random -Minimum 150 -Maximum 600 }
363
+ "chat-area" { $x = Get-Random -Minimum 350 -Maximum 900; $y = Get-Random -Minimum 200 -Maximum 650 }
364
+ "sidebar" { $x = Get-Random -Minimum 20 -Maximum 200; $y = Get-Random -Minimum 100 -Maximum 500 }
365
+ default { $x = Get-Random -Minimum 200 -Maximum 1000; $y = Get-Random -Minimum 200 -Maximum 600 }
176
366
  }
177
-
178
367
  return @{ X = $x; Y = $y }
179
368
  }
180
369
 
181
- # ============== HELPER FUNCTIONS ==============
182
-
183
- function Get-RandomDelay {
184
- param([string]$type = "keystroke")
185
- switch ($type) {
186
- "keystroke" { return (Get-Random -Minimum 50 -Maximum 200) }
187
- "think" { return (Get-Random -Minimum 800 -Maximum 3000) }
188
- "read" { return (Get-Random -Minimum 3000 -Maximum 12000) }
189
- "scroll" { return (Get-Random -Minimum 800 -Maximum 2000) }
190
- "switch" { return (Get-Random -Minimum 500 -Maximum 1500) }
191
- "message" { return (Get-Random -Minimum 2000 -Maximum 6000) }
192
- }
193
- }
370
+ # ============== TYPING FUNCTIONS ==============
194
371
 
195
372
  function Type-WithTypos {
196
- param([string]$text)
197
-
198
- $typoChance = 8 # 8% chance of typo per character
199
-
373
+ param([string]$text, [int]$typoChance = 8)
200
374
  foreach ($char in $text.ToCharArray()) {
201
- # Random typo
202
375
  if ((Get-Random -Minimum 1 -Maximum 100) -le $typoChance) {
203
- # Type wrong character
204
- $wrongChar = [char]((Get-Random -Minimum 97 -Maximum 122)) # random a-z
376
+ $wrongChar = [char]((Get-Random -Minimum 97 -Maximum 122))
205
377
  [System.Windows.Forms.SendKeys]::SendWait($wrongChar)
206
378
  Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
207
-
208
- # Pause (notice mistake)
209
379
  Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
210
-
211
- # Backspace
212
380
  [System.Windows.Forms.SendKeys]::SendWait("{BACKSPACE}")
213
381
  Start-Sleep -Milliseconds (Get-Random -Minimum 80 -Maximum 200)
214
382
  }
215
-
216
- # Type correct character
217
383
  $escaped = $char
218
384
  if ($char -match '[\+\^\%\~\(\)\{\}\[\]]') { $escaped = "{$char}" }
219
385
  [System.Windows.Forms.SendKeys]::SendWait($escaped)
220
-
221
- # Variable delay (sometimes pause mid-word like thinking)
222
386
  $delay = Get-Random -Minimum 50 -Maximum 200
223
- if ((Get-Random -Minimum 1 -Maximum 100) -le 5) {
224
- $delay = Get-Random -Minimum 300 -Maximum 800 # Thinking pause
225
- }
387
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 5) { $delay = Get-Random -Minimum 300 -Maximum 800 }
226
388
  Start-Sleep -Milliseconds $delay
227
389
  }
228
390
  }
229
391
 
230
- function Switch-ToApp {
231
- param([string]$targetApp, [string]$currentApp)
392
+ function Type-Number {
393
+ param([string]$num)
394
+ Type-WithTypos $num 5
395
+ }
232
396
 
233
- # Move mouse to taskbar area first (more human)
234
- $taskbarY = $script:screenHeight - 30
235
- $taskbarX = Get-Random -Minimum 200 -Maximum 800
236
- Move-MouseSmooth $taskbarX $taskbarY
237
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
397
+ # ============== TASK SELECTOR (Anti-Pattern) ==============
238
398
 
239
- # Use Alt+Tab
240
- $appOrder = @("excel", "chrome", "teams")
241
- $currentIdx = [array]::IndexOf($appOrder, $currentApp)
242
- $targetIdx = [array]::IndexOf($appOrder, $targetApp)
243
- $tabsNeeded = if ($targetIdx -gt $currentIdx) { $targetIdx - $currentIdx } else { 3 - $currentIdx + $targetIdx }
244
- $tabsNeeded = [Math]::Max(1, $tabsNeeded)
399
+ function Select-NextTask {
400
+ $catWeights = Get-CategoryWeights
245
401
 
246
- for ($i = 0; $i -lt $tabsNeeded; $i++) {
247
- [System.Windows.Forms.SendKeys]::SendWait("%{TAB}")
248
- Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
402
+ # Build weighted pool excluding recent tasks
403
+ $pool = @()
404
+ foreach ($task in $script:microTasks) {
405
+ # Skip if in last 10 tasks
406
+ if ($script:taskHistory -contains $task.id) { continue }
407
+
408
+ # Weight by category and task weight
409
+ $catWeight = $catWeights[$task.cat]
410
+ if (-not $catWeight) { $catWeight = 5 }
411
+ $totalWeight = $task.weight * ($catWeight / 10)
412
+
413
+ for ($i = 0; $i -lt [Math]::Ceiling($totalWeight); $i++) {
414
+ $pool += $task
415
+ }
249
416
  }
250
417
 
251
- Start-Sleep -Milliseconds (Get-RandomDelay "switch")
418
+ if ($pool.Count -eq 0) {
419
+ # Reset history if pool empty
420
+ $script:taskHistory = @()
421
+ $pool = $script:microTasks
422
+ }
252
423
 
253
- # Move mouse to center of new app
254
- $pos = Get-RandomScreenPosition "center"
255
- Move-MouseSmooth $pos.X $pos.Y
256
- }
424
+ $selected = $pool | Get-Random
257
425
 
258
- function Get-NextApp {
259
- param([string]$currentApp)
260
- $roll = Get-Random -Minimum 1 -Maximum 101
261
- $cumulative = 0
262
- foreach ($app in $appWeights.Keys) {
263
- $cumulative += $appWeights[$app]
264
- if ($roll -le $cumulative) {
265
- if ($app -eq $currentApp) {
266
- $others = $appWeights.Keys | Where-Object { $_ -ne $currentApp }
267
- return ($others | Get-Random)
268
- }
269
- return $app
270
- }
426
+ # Update history (keep last 10)
427
+ $script:taskHistory += $selected.id
428
+ if ($script:taskHistory.Count -gt 10) {
429
+ $script:taskHistory = $script:taskHistory[-10..-1]
271
430
  }
272
- return "excel"
431
+
432
+ return $selected
273
433
  }
274
434
 
275
- # ============== EXCEL ACTIONS ==============
435
+ # ============== TASK EXECUTORS ==============
436
+
437
+ function Execute-ExcelTask {
438
+ param($task)
276
439
 
277
- function Do-ExcelAction {
278
- $action = Get-Random -Minimum 1 -Maximum 100
440
+ $pos = Get-RandomScreenPosition "excel-cells"
279
441
 
280
- # Random mouse fidget before action (50% chance)
281
- if ((Get-Random -Minimum 1 -Maximum 100) -le 50) {
282
- Fidget-Mouse
283
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
442
+ switch -Wildcard ($task.name) {
443
+ "*SKU*" {
444
+ Move-AndClick $pos.X $pos.Y
445
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
446
+ Type-WithTypos ($script:skuPool | Get-Random)
447
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
448
+ }
449
+ "*campaign name*" {
450
+ Move-AndClick $pos.X $pos.Y
451
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
452
+ Type-WithTypos ($script:campaignNames | Get-Random)
453
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
454
+ }
455
+ "*ACOS*" {
456
+ Move-AndClick $pos.X $pos.Y
457
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
458
+ $acos = [math]::Round((Get-Random -Minimum 800 -Maximum 6500) / 100, 2)
459
+ Type-Number "$acos%"
460
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
461
+ }
462
+ "*spend*" {
463
+ Move-AndClick $pos.X $pos.Y
464
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
465
+ $spend = [math]::Round((Get-Random -Minimum 500 -Maximum 50000) / 100, 2)
466
+ Type-Number "`$$spend"
467
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
468
+ }
469
+ "*bid*" {
470
+ Move-AndClick $pos.X $pos.Y
471
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
472
+ $bid = [math]::Round((Get-Random -Minimum 15 -Maximum 350) / 100, 2)
473
+ Type-Number "`$$bid"
474
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
475
+ }
476
+ "*formula*" {
477
+ Move-AndClick $pos.X $pos.Y
478
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
479
+ $formulas = @("=SUM(B2:B50)", "=AVERAGE(C2:C100)", "=B2/C2", "=D2*0.15", "=IF(E2>30,""HIGH"",""OK"")")
480
+ Type-WithTypos ($formulas | Get-Random)
481
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
482
+ }
483
+ "*Scroll*" {
484
+ Move-MouseSmooth $pos.X $pos.Y
485
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
486
+ $dir = if ($task.name -match "up") { 3 } else { -3 }
487
+ Scroll-MouseWheel $dir
488
+ }
489
+ "*Click*cell*" {
490
+ Move-AndClick $pos.X $pos.Y
491
+ }
492
+ "*Tab*" {
493
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
494
+ }
495
+ "*Enter*" {
496
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
497
+ }
498
+ "*Save*" {
499
+ Fidget-Mouse
500
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
501
+ [System.Windows.Forms.SendKeys]::SendWait("^s")
502
+ }
503
+ "*Find*" {
504
+ [System.Windows.Forms.SendKeys]::SendWait("^f")
505
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
506
+ Type-WithTypos ($script:skuPool | Get-Random).Substring(0,4)
507
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
508
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
509
+ }
510
+ "*Copy*" {
511
+ Move-AndClick $pos.X $pos.Y
512
+ [System.Windows.Forms.SendKeys]::SendWait("^c")
513
+ }
514
+ "*Paste*" {
515
+ Move-AndClick $pos.X $pos.Y
516
+ [System.Windows.Forms.SendKeys]::SendWait("^v")
517
+ }
518
+ "*Undo*" {
519
+ [System.Windows.Forms.SendKeys]::SendWait("^z")
520
+ }
521
+ "*worksheet*" {
522
+ $tabX = Get-Random -Minimum 100 -Maximum 400
523
+ Move-AndClick $tabX ($script:screenHeight - 60)
524
+ }
525
+ default {
526
+ # Generic cell interaction
527
+ Move-AndClick $pos.X $pos.Y
528
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
529
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 50) {
530
+ $num = Get-Random -Minimum 100 -Maximum 9999
531
+ Type-Number $num.ToString()
532
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
533
+ }
534
+ }
284
535
  }
536
+ }
285
537
 
286
- if ($action -le 35) {
287
- # Click on a cell, type a number
288
- $pos = Get-RandomScreenPosition "excel-cells"
289
- Move-AndClick $pos.X $pos.Y
290
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
538
+ function Execute-ChromeTask {
539
+ param($task)
291
540
 
292
- $num = Get-Random -Minimum 100 -Maximum 99999
293
- if ((Get-Random -Minimum 1 -Maximum 10) -le 3) {
294
- $num = [math]::Round((Get-Random -Minimum 1 -Maximum 9999) / 100, 2)
541
+ switch -Wildcard ($task.name) {
542
+ "*search*" {
543
+ $pos = Get-RandomScreenPosition "address-bar"
544
+ Move-AndClick $pos.X $pos.Y
545
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
546
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
547
+ Type-WithTypos ($script:searchQueries | Get-Random)
548
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
549
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
295
550
  }
296
- Type-WithTypos $num.ToString()
297
- [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
298
- }
299
- elseif ($action -le 50) {
300
- # Click cell, type SKU
301
- $pos = Get-RandomScreenPosition "excel-cells"
302
- Move-AndClick $pos.X $pos.Y
303
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
304
-
305
- $prefix = $skuPrefixes | Get-Random
306
- $num = Get-Random -Minimum 10000 -Maximum 99999
307
- Type-WithTypos "$prefix$num"
308
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
309
- }
310
- elseif ($action -le 60) {
311
- # Type campaign type
312
- $pos = Get-RandomScreenPosition "excel-cells"
313
- Move-AndClick $pos.X $pos.Y
314
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
315
- Type-WithTypos ($campaignTypes | Get-Random)
316
- [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
317
- }
318
- elseif ($action -le 75) {
319
- # Scroll with mouse wheel
320
- $pos = Get-RandomScreenPosition "excel-cells"
321
- Move-MouseSmooth $pos.X $pos.Y
322
- Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
323
- $scrollAmount = if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) {
324
- Get-Random -Minimum -5 -Maximum -2
325
- } else {
326
- Get-Random -Minimum 2 -Maximum 5
551
+ "*Load*" {
552
+ $pos = Get-RandomScreenPosition "address-bar"
553
+ Move-AndClick $pos.X $pos.Y
554
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
555
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
556
+ Type-WithTypos ($script:websites | Get-Random)
557
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
558
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
327
559
  }
328
- Scroll-MouseWheel $scrollAmount
329
- }
330
- elseif ($action -le 85) {
331
- # Click multiple cells (selecting/reviewing)
332
- $clicks = Get-Random -Minimum 2 -Maximum 5
333
- for ($i = 0; $i -lt $clicks; $i++) {
334
- $pos = Get-RandomScreenPosition "excel-cells"
560
+ "*Scroll*" {
561
+ $pos = Get-RandomScreenPosition "webpage"
562
+ Move-MouseSmooth $pos.X $pos.Y
563
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
564
+ $scrollAmt = Get-Random -Minimum -5 -Maximum -2
565
+ Scroll-MouseWheel $scrollAmt
566
+ }
567
+ "*Click*" {
568
+ $pos = Get-RandomScreenPosition "webpage"
569
+ Move-AndClick $pos.X $pos.Y
570
+ }
571
+ "*new tab*" {
572
+ [System.Windows.Forms.SendKeys]::SendWait("^t")
573
+ }
574
+ "*Close tab*" {
575
+ [System.Windows.Forms.SendKeys]::SendWait("^w")
576
+ }
577
+ "*Switch tab*" {
578
+ [System.Windows.Forms.SendKeys]::SendWait("^{TAB}")
579
+ }
580
+ "*back*" {
581
+ if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) {
582
+ Move-AndClick 45 65
583
+ } else {
584
+ [System.Windows.Forms.SendKeys]::SendWait("%{LEFT}")
585
+ }
586
+ }
587
+ "*Refresh*" {
588
+ [System.Windows.Forms.SendKeys]::SendWait("{F5}")
589
+ }
590
+ default {
591
+ $pos = Get-RandomScreenPosition "webpage"
335
592
  Move-AndClick $pos.X $pos.Y
336
593
  Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
337
594
  }
338
595
  }
339
- elseif ($action -le 92) {
340
- # Formula with mouse click first
341
- $pos = Get-RandomScreenPosition "excel-cells"
342
- Move-AndClick $pos.X $pos.Y
343
- Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
344
- $formulas = @("=SUM(B2:B50)", "=AVERAGE(C2:C100)", "=B2/C2", "=D2*0.15")
345
- Type-WithTypos ($formulas | Get-Random)
346
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
347
- }
348
- else {
349
- # Save (Ctrl+S with mouse movement)
350
- Fidget-Mouse
351
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
352
- [System.Windows.Forms.SendKeys]::SendWait("^s")
353
- Start-Sleep -Milliseconds 500
354
- }
355
596
  }
356
597
 
357
- # ============== CHROME ACTIONS ==============
598
+ function Execute-PerpetuaTask {
599
+ param($task)
358
600
 
359
- function Do-ChromeBrowse {
360
- $action = Get-Random -Minimum 1 -Maximum 100
601
+ # Get Perpetua UI positions
602
+ $ui = $script:perpetuaUI
361
603
 
362
- # Random fidget
363
- if ((Get-Random -Minimum 1 -Maximum 100) -le 40) {
364
- Fidget-Mouse
365
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
366
- }
604
+ switch -Wildcard ($task.name) {
605
+ # === GOALS PAGE INTERACTIONS ===
606
+ "*Navigate SP Goals*" {
607
+ # Click sidebar SP item
608
+ Move-AndClick $ui.sidebarSP.x $ui.sidebarSP.y
609
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
610
+ }
611
+ "*Navigate SB Goals*" {
612
+ Move-AndClick $ui.sidebarSB.x $ui.sidebarSB.y
613
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
614
+ }
615
+ "*Navigate SD Goals*" {
616
+ Move-AndClick $ui.sidebarSD.x $ui.sidebarSD.y
617
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
618
+ }
619
+ "*Click goal row*" {
620
+ $x = Get-Random -Minimum $ui.goalRow.x[0] -Maximum $ui.goalRow.x[1]
621
+ $y = Get-Random -Minimum $ui.goalRow.y[0] -Maximum $ui.goalRow.y[1]
622
+ Move-AndClick $x $y
623
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
624
+ }
625
+ "*Review goal*metric*" {
626
+ $x = Get-Random -Minimum $ui.goalMetrics.x[0] -Maximum $ui.goalMetrics.x[1]
627
+ $y = Get-Random -Minimum $ui.goalMetrics.y[0] -Maximum $ui.goalMetrics.y[1]
628
+ Move-MouseSmooth $x $y
629
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
630
+ Fidget-Mouse
631
+ }
632
+ "*Scroll goals list*" {
633
+ $x = Get-Random -Minimum $ui.goalsList.x[0] -Maximum $ui.goalsList.x[1]
634
+ $y = Get-Random -Minimum $ui.goalsList.y[0] -Maximum $ui.goalsList.y[1]
635
+ Move-MouseSmooth $x $y
636
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
637
+ $dir = if ($task.name -match "up") { 3 } else { -3 }
638
+ Scroll-MouseWheel $dir
639
+ }
640
+ "*Click goal tabs*" {
641
+ $x = Get-Random -Minimum $ui.goalTabs.x[0] -Maximum $ui.goalTabs.x[1]
642
+ $y = Get-Random -Minimum $ui.goalTabs.y[0] -Maximum $ui.goalTabs.y[1]
643
+ Move-AndClick $x $y
644
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
645
+ }
646
+ "*Search goal*" {
647
+ Move-AndClick $ui.searchBox.x $ui.searchBox.y
648
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
649
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
650
+ Start-Sleep -Milliseconds 200
651
+ $goalName = $script:campaignNames | Get-Random
652
+ $searchTerm = $goalName.Split("_")[0..1] -join "_"
653
+ Type-WithTypos $searchTerm
654
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
655
+ }
656
+ "*Filter goals*" {
657
+ # Click filter dropdown area
658
+ $x = Get-Random -Minimum 300 -Maximum 500
659
+ Move-AndClick $x 120
660
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
661
+ # Click option
662
+ $y = if ($task.name -match "Enabled") { 160 } else { 190 }
663
+ Move-AndClick ($x + 20) $y
664
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
665
+ }
666
+ "*Sort by*column*" {
667
+ # Click column header
668
+ $x = if ($task.name -match "ACOS") { 900 } else { 800 }
669
+ Move-AndClick $x 175
670
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
671
+ }
672
+ "*Change date range*" {
673
+ Move-AndClick $ui.dateRangePicker.x $ui.dateRangePicker.y
674
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
675
+ # Click a preset option
676
+ $y = if ($task.name -match "7d") { 200 } else { 230 }
677
+ Move-AndClick ($ui.dateRangePicker.x - 50) $y
678
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
679
+ }
680
+ "*New Goal button*" {
681
+ Move-AndClick $ui.newGoalBtn.x $ui.newGoalBtn.y
682
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
683
+ # Press Escape to close without creating
684
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
685
+ Start-Sleep -Milliseconds 500
686
+ }
687
+ "*Close goal detail*" {
688
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
689
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
690
+ }
367
691
 
368
- if ($action -le 35) {
369
- # Click address bar, search
370
- $pos = Get-RandomScreenPosition "address-bar"
371
- Move-AndClick $pos.X $pos.Y
372
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
373
- [System.Windows.Forms.SendKeys]::SendWait("^a") # Select all
374
- Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
375
- Type-WithTypos ($searchQueries | Get-Random)
376
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
377
- Start-Sleep -Milliseconds (Get-RandomDelay "read")
378
- }
379
- elseif ($action -le 50) {
380
- # Click address bar, visit site
381
- $pos = Get-RandomScreenPosition "address-bar"
382
- Move-AndClick $pos.X $pos.Y
383
- Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
384
- [System.Windows.Forms.SendKeys]::SendWait("^a")
385
- Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
386
- Type-WithTypos ($websites | Get-Random)
387
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
388
- Start-Sleep -Milliseconds (Get-RandomDelay "read")
389
- }
390
- elseif ($action -le 70) {
391
- # Scroll with mouse wheel
392
- $pos = Get-RandomScreenPosition "webpage"
393
- Move-MouseSmooth $pos.X $pos.Y
394
- Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
395
-
396
- $scrollSessions = Get-Random -Minimum 2 -Maximum 5
397
- for ($i = 0; $i -lt $scrollSessions; $i++) {
692
+ # === STREAMS PAGE INTERACTIONS ===
693
+ "*Navigate SP Streams*" {
694
+ # Click Streams in sidebar or tab
695
+ $x = Get-Random -Minimum $ui.sidebar.x[0] -Maximum $ui.sidebar.x[1]
696
+ Move-AndClick $x 320
697
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
698
+ }
699
+ "*Click stream row*" {
700
+ $x = Get-Random -Minimum $ui.streamRow.x[0] -Maximum $ui.streamRow.x[1]
701
+ $y = Get-Random -Minimum $ui.streamRow.y[0] -Maximum $ui.streamRow.y[1]
702
+ Move-AndClick $x $y
703
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
704
+ }
705
+ "*Scroll streams list*" {
706
+ $x = Get-Random -Minimum $ui.streamsList.x[0] -Maximum $ui.streamsList.x[1]
707
+ $y = Get-Random -Minimum $ui.streamsList.y[0] -Maximum $ui.streamsList.y[1]
708
+ Move-MouseSmooth $x $y
398
709
  Scroll-MouseWheel (Get-Random -Minimum -4 -Maximum -2)
399
- Start-Sleep -Milliseconds (Get-RandomDelay "scroll")
400
-
401
- # Sometimes fidget while reading
402
- if ((Get-Random -Minimum 1 -Maximum 100) -le 30) {
403
- Fidget-Mouse
404
- }
405
710
  }
406
- }
407
- elseif ($action -le 85) {
408
- # Click on a link (random position in webpage)
409
- $pos = Get-RandomScreenPosition "webpage"
410
- Move-AndClick $pos.X $pos.Y
411
- Start-Sleep -Milliseconds (Get-RandomDelay "read")
412
- }
413
- elseif ($action -le 92) {
414
- # Back button (click or Alt+Left)
415
- if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) {
416
- # Click back button
417
- Move-AndClick 45 65
418
- } else {
711
+ "*View stream bid*" {
712
+ $x = Get-Random -Minimum 600 -Maximum 900
713
+ $y = Get-Random -Minimum 250 -Maximum 400
714
+ Move-MouseSmooth $x $y
715
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
716
+ }
717
+ "*Filter streams*" {
718
+ $x = Get-Random -Minimum $ui.streamFilters.x[0] -Maximum $ui.streamFilters.x[1]
719
+ $y = Get-Random -Minimum $ui.streamFilters.y[0] -Maximum $ui.streamFilters.y[1]
720
+ Move-AndClick $x $y
721
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
722
+ }
723
+ "*stream*trend*" {
724
+ # Hover over graph area
725
+ $x = Get-Random -Minimum 700 -Maximum 1200
726
+ $y = Get-Random -Minimum 300 -Maximum 450
727
+ Move-MouseSmooth $x $y
728
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 4000)
419
729
  Fidget-Mouse
420
- [System.Windows.Forms.SendKeys]::SendWait("%{LEFT}")
421
730
  }
422
- Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
423
- }
424
- else {
425
- # New tab
426
- Fidget-Mouse
427
- [System.Windows.Forms.SendKeys]::SendWait("^t")
428
- Start-Sleep -Milliseconds 800
731
+ "*Expand stream*" {
732
+ $x = Get-Random -Minimum 250 -Maximum 300
733
+ $y = Get-Random -Minimum 220 -Maximum 500
734
+ Move-AndClick $x $y
735
+ }
736
+ "*Collapse stream*" {
737
+ $x = Get-Random -Minimum 250 -Maximum 300
738
+ $y = Get-Random -Minimum 220 -Maximum 400
739
+ Move-AndClick $x $y
740
+ }
741
+ "*Sort streams*" {
742
+ $x = Get-Random -Minimum 700 -Maximum 900
743
+ Move-AndClick $x 175
744
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
745
+ }
746
+ "*stream automation*" {
747
+ # Click automation toggle area
748
+ $x = Get-Random -Minimum 1100 -Maximum 1300
749
+ $y = Get-Random -Minimum 250 -Maximum 450
750
+ Move-MouseSmooth $x $y
751
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 3000)
752
+ }
753
+ "*Navigate Analytics*" {
754
+ Move-AndClick $ui.sidebarAnalytics.x $ui.sidebarAnalytics.y
755
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
756
+ }
757
+
758
+ # === GENERAL PERPETUA INTERACTIONS ===
759
+ "*sidebar nav*" {
760
+ $x = Get-Random -Minimum $ui.sidebar.x[0] -Maximum $ui.sidebar.x[1]
761
+ $y = Get-Random -Minimum $ui.sidebar.y[0] -Maximum $ui.sidebar.y[1]
762
+ Move-AndClick $x $y
763
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
764
+ }
765
+ "*Hover sidebar*" {
766
+ $x = Get-Random -Minimum 20 -Maximum 60
767
+ $y = Get-Random -Minimum 150 -Maximum 500
768
+ Move-MouseSmooth $x $y
769
+ Start-Sleep -Milliseconds (Get-Random -Minimum 800 -Maximum 2000)
770
+ }
771
+ "*account dropdown*" {
772
+ Move-AndClick $ui.accountDropdown.x $ui.accountDropdown.y
773
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
774
+ # Click elsewhere to close
775
+ Move-AndClick 800 400
776
+ }
777
+ "*notifications bell*" {
778
+ Move-AndClick ($ui.accountDropdown.x - 80) $ui.accountDropdown.y
779
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
780
+ # Click elsewhere to close
781
+ Move-AndClick 800 400
782
+ }
783
+ "*Refresh current*" {
784
+ [System.Windows.Forms.SendKeys]::SendWait("{F5}")
785
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
786
+ }
787
+ "*breadcrumb*" {
788
+ $x = Get-Random -Minimum 220 -Maximum 400
789
+ Move-AndClick $x 80
790
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
791
+ }
792
+ "*Scroll page randomly*" {
793
+ $x = Get-Random -Minimum 400 -Maximum 1200
794
+ $y = Get-Random -Minimum 300 -Maximum 600
795
+ Move-MouseSmooth $x $y
796
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
797
+ $dir = if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) { -3 } else { 3 }
798
+ Scroll-MouseWheel $dir
799
+ }
800
+ "*idle on metrics*" {
801
+ $x = Get-Random -Minimum 600 -Maximum 1100
802
+ $y = Get-Random -Minimum 200 -Maximum 500
803
+ Move-MouseSmooth $x $y
804
+ # Just hover and look
805
+ Start-Sleep -Milliseconds (Get-Random -Minimum 3000 -Maximum 8000)
806
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 40) { Fidget-Mouse }
807
+ }
808
+ default {
809
+ # Generic Perpetua interaction
810
+ $x = Get-Random -Minimum 300 -Maximum 1200
811
+ $y = Get-Random -Minimum 200 -Maximum 600
812
+ Move-MouseSmooth $x $y
813
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
814
+ }
429
815
  }
430
816
  }
431
817
 
432
- # ============== TEAMS ACTIONS ==============
433
-
434
- function Do-TeamsAction {
435
- $action = Get-Random -Minimum 1 -Maximum 100
436
-
437
- if ($action -le 60) {
438
- # Click on chats and read
439
- $messagesToCheck = Get-Random -Minimum 1 -Maximum 4
818
+ function Execute-TeamsTask {
819
+ param($task)
440
820
 
441
- for ($m = 0; $m -lt $messagesToCheck; $m++) {
442
- # Click on a chat in the list
821
+ switch -Wildcard ($task.name) {
822
+ "*chat*" {
443
823
  $pos = Get-RandomScreenPosition "chat-list"
444
824
  Move-AndClick $pos.X $pos.Y
445
825
  Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
446
-
447
- # Move to chat area and read
448
826
  $chatPos = Get-RandomScreenPosition "chat-area"
449
827
  Move-MouseSmooth $chatPos.X $chatPos.Y
450
- Start-Sleep -Milliseconds (Get-RandomDelay "message")
451
-
452
- # Sometimes scroll up in chat
453
- if ((Get-Random -Minimum 1 -Maximum 100) -le 40) {
454
- Scroll-MouseWheel (Get-Random -Minimum 2 -Maximum 5)
455
- Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
456
- Scroll-MouseWheel (Get-Random -Minimum -3 -Maximum -1)
457
- }
458
-
459
- # Fidget while reading
460
- if ((Get-Random -Minimum 1 -Maximum 100) -le 50) {
461
- Fidget-Mouse
462
- }
463
828
  }
464
- }
465
- elseif ($action -le 80) {
466
- # Scroll through chat list
467
- $pos = Get-RandomScreenPosition "chat-list"
468
- Move-MouseSmooth $pos.X $pos.Y
469
- Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
470
-
471
- $scrolls = Get-Random -Minimum 2 -Maximum 4
472
- for ($i = 0; $i -lt $scrolls; $i++) {
473
- Scroll-MouseWheel (Get-Random -Minimum -2 -Maximum 2)
829
+ "*Read*" {
830
+ $pos = Get-RandomScreenPosition "chat-area"
831
+ Move-MouseSmooth $pos.X $pos.Y
832
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
833
+ }
834
+ "*Scroll*" {
835
+ $pos = if ($task.name -match "channel") { Get-RandomScreenPosition "sidebar" } else { Get-RandomScreenPosition "chat-area" }
836
+ Move-MouseSmooth $pos.X $pos.Y
837
+ Scroll-MouseWheel (Get-Random -Minimum -3 -Maximum 3)
838
+ }
839
+ "*activity*" {
840
+ $pos = Get-RandomScreenPosition "sidebar"
841
+ Move-AndClick $pos.X 100
842
+ }
843
+ "*React*" {
844
+ $pos = Get-RandomScreenPosition "chat-area"
845
+ Move-MouseSmooth $pos.X $pos.Y
846
+ # Hover for reaction
474
847
  Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
475
848
  }
476
- }
477
- else {
478
- # Just look around (fidget)
479
- Fidget-Mouse
480
- Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
481
- Fidget-Mouse
849
+ default {
850
+ $pos = Get-RandomScreenPosition "chat-list"
851
+ Move-AndClick $pos.X $pos.Y
852
+ }
482
853
  }
483
854
  }
484
855
 
485
- # ============== BULK TASKS ==============
486
-
487
- function Do-BulkBidOptimization {
488
- $rows = Get-Random -Minimum 12 -Maximum 30
489
-
490
- # Start at top
491
- $pos = Get-RandomScreenPosition "excel-cells"
492
- Move-AndClick $pos.X 180
493
- Start-Sleep -Milliseconds 500
494
-
495
- for ($r = 0; $r -lt $rows; $r++) {
496
- # Click on bid cell
497
- $cellX = Get-Random -Minimum 400 -Maximum 500
498
- $cellY = 180 + ($r * 20)
499
- if ($cellY -gt 600) {
500
- Scroll-MouseWheel -3
501
- Start-Sleep -Milliseconds 500
502
- $cellY = 300
503
- }
504
-
505
- Move-AndClick $cellX $cellY
506
- Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
856
+ function Execute-HumanTask {
857
+ param($task)
507
858
 
508
- if ((Get-Random -Minimum 1 -Maximum 100) -le 60) {
509
- $newBid = [math]::Round((Get-Random -Minimum 15 -Maximum 350) / 100, 2)
510
- Type-WithTypos $newBid.ToString()
511
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
859
+ switch -Wildcard ($task.name) {
860
+ "*Pause*think*" {
861
+ # Just wait, maybe small fidget
862
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 30) { Fidget-Mouse }
512
863
  }
513
-
514
- # Occasional fidget
515
- if ((Get-Random -Minimum 1 -Maximum 100) -le 20) {
864
+ "*fidget*" {
516
865
  Fidget-Mouse
517
866
  }
867
+ "*Hesitation*" {
868
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 2000)
869
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 40) { Fidget-Mouse }
870
+ }
871
+ "*Re-read*" {
872
+ $pos = Get-RandomScreenPosition "center"
873
+ Move-MouseSmooth $pos.X $pos.Y
874
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 3000)
875
+ }
876
+ "*break*" {
877
+ # Longer pause with occasional fidget
878
+ $breakTime = Get-Random -Minimum 15 -Maximum 45
879
+ for ($i = 0; $i -lt $breakTime; $i += 5) {
880
+ Start-Sleep -Seconds 5
881
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) { Fidget-Mouse }
882
+ }
883
+ }
518
884
  }
519
-
520
- [System.Windows.Forms.SendKeys]::SendWait("^s")
521
- Start-Sleep -Milliseconds 1000
522
885
  }
523
886
 
524
- function Do-SearchTermReview {
525
- $terms = Get-Random -Minimum 15 -Maximum 35
887
+ # ============== APP SWITCHING ==============
526
888
 
527
- $pos = Get-RandomScreenPosition "excel-cells"
528
- Move-AndClick $pos.X 180
529
- Start-Sleep -Milliseconds 500
530
-
531
- for ($t = 0; $t -lt $terms; $t++) {
532
- # Scroll and click through rows
533
- $cellY = 180 + (($t % 15) * 22)
534
- if ($t % 15 -eq 0 -and $t -gt 0) {
535
- Scroll-MouseWheel -4
536
- Start-Sleep -Milliseconds 800
537
- }
538
-
539
- $cellX = Get-Random -Minimum 100 -Maximum 300
540
- Move-AndClick $cellX $cellY
541
- Start-Sleep -Milliseconds (Get-Random -Minimum 600 -Maximum 2000)
542
-
543
- # Mark as negative
544
- if ((Get-Random -Minimum 1 -Maximum 100) -le 20) {
545
- $endCellX = Get-Random -Minimum 700 -Maximum 850
546
- Move-AndClick $endCellX $cellY
547
- Start-Sleep -Milliseconds 300
548
- Type-WithTypos "NEGATIVE"
549
- [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
550
- Start-Sleep -Milliseconds 500
551
- }
889
+ function Switch-ToApp {
890
+ param([string]$targetApp)
552
891
 
553
- if ((Get-Random -Minimum 1 -Maximum 100) -le 30) {
554
- Fidget-Mouse
555
- }
892
+ if ($targetApp -eq $script:lastApp) { return }
893
+
894
+ # Move to taskbar area
895
+ $taskbarY = $script:screenHeight - 30
896
+ $taskbarX = Get-Random -Minimum 200 -Maximum 800
897
+ Move-MouseSmooth $taskbarX $taskbarY
898
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
899
+
900
+ # Alt+Tab cycles
901
+ $tabCount = Get-Random -Minimum 1 -Maximum 3
902
+ for ($i = 0; $i -lt $tabCount; $i++) {
903
+ [System.Windows.Forms.SendKeys]::SendWait("%{TAB}")
904
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
556
905
  }
557
906
 
558
- [System.Windows.Forms.SendKeys]::SendWait("^s")
907
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
908
+ $script:lastApp = $targetApp
909
+
910
+ # Move to app area
911
+ $pos = Get-RandomScreenPosition "center"
912
+ Move-MouseSmooth $pos.X $pos.Y
559
913
  }
560
914
 
561
915
  # ============== MAIN TRACKER ==============
562
916
 
563
917
  function Start-Tracking {
564
- $currentApp = "excel"
565
918
  $totalActions = 0
566
- $startTime = Get-Date
919
+ $script:sessionStart = Get-Date
567
920
 
568
921
  Write-Host "[TRACKING] Started at $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor Green
569
- Write-Host "[INFO] Click Excel window now. Press Ctrl+C to stop." -ForegroundColor Yellow
922
+ Write-Host "[INFO] v3.1 - 130 micro-tasks, Perpetua UI, anti-pattern" -ForegroundColor Cyan
923
+ Write-Host "[INFO] Click Excel window now. Ctrl+C to stop." -ForegroundColor Yellow
570
924
  Start-Sleep -Seconds 3
571
925
 
572
- # Initial mouse position
573
926
  $pos = Get-RandomScreenPosition "excel-cells"
574
927
  Move-MouseSmooth $pos.X $pos.Y
928
+ $script:lastApp = "excel"
575
929
 
576
930
  try {
577
931
  while ($true) {
578
- $shouldSwitch = (Get-Random -Minimum 1 -Maximum 100) -gt 65
932
+ # Select next task (anti-pattern)
933
+ $task = Select-NextTask
579
934
 
580
- if ($shouldSwitch) {
581
- $nextApp = Get-NextApp $currentApp
582
- Switch-ToApp $nextApp $currentApp
583
- $currentApp = $nextApp
935
+ # Maybe switch app
936
+ if ($task.cat -ne $script:lastApp -and $task.cat -ne "human") {
937
+ Switch-ToApp $task.cat
584
938
  }
585
939
 
586
- if ($currentApp -eq "teams") {
587
- $burstSize = Get-Random -Minimum 1 -Maximum 3
588
- for ($i = 0; $i -lt $burstSize; $i++) {
589
- Do-TeamsAction
590
- $totalActions++
591
- }
592
- }
593
- elseif ($currentApp -eq "excel") {
594
- if ((Get-Random -Minimum 1 -Maximum 100) -le 12) {
595
- $tasks = @("Do-BulkBidOptimization", "Do-SearchTermReview")
596
- & ($tasks | Get-Random)
597
- $totalActions += 20
598
- }
599
- else {
600
- $burstSize = Get-Random -Minimum 3 -Maximum 8
601
- for ($i = 0; $i -lt $burstSize; $i++) {
602
- Do-ExcelAction
603
- $totalActions++
604
- Start-Sleep -Milliseconds (Get-RandomDelay "think")
605
- }
606
- }
607
- }
608
- else {
609
- $burstSize = Get-Random -Minimum 3 -Maximum 8
610
- for ($i = 0; $i -lt $burstSize; $i++) {
611
- Do-ChromeBrowse
612
- $totalActions++
613
- Start-Sleep -Milliseconds (Get-RandomDelay "think")
614
- }
940
+ # Execute task
941
+ switch ($task.cat) {
942
+ "excel" { Execute-ExcelTask $task }
943
+ "perpetua" { Execute-PerpetuaTask $task }
944
+ "chrome" { Execute-ChromeTask $task }
945
+ "teams" { Execute-TeamsTask $task }
946
+ "human" { Execute-HumanTask $task }
615
947
  }
616
948
 
617
- # Random break with occasional fidgeting (5-29 sec to stay under heartbeat)
618
- $break = Get-Random -Minimum 5 -Maximum 29
949
+ $totalActions++
950
+
951
+ # Task duration (from task spec)
952
+ $minDur = $task.dur[0]
953
+ $maxDur = $task.dur[1]
954
+ $taskDuration = Get-Random -Minimum $minDur -Maximum $maxDur
955
+
956
+ # Execute duration with fidgets
619
957
  $elapsed = 0
620
- while ($elapsed -lt $break) {
958
+ while ($elapsed -lt $taskDuration) {
959
+ $sleepTime = [Math]::Min(5, $taskDuration - $elapsed)
960
+ Start-Sleep -Seconds $sleepTime
961
+ $elapsed += $sleepTime
962
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 15) { Fidget-Mouse }
963
+ }
964
+
965
+ # Gap between tasks (5-29 sec)
966
+ $gap = Get-Random -Minimum 5 -Maximum 29
967
+ $gapElapsed = 0
968
+ while ($gapElapsed -lt $gap) {
621
969
  Start-Sleep -Seconds 5
622
- $elapsed += 5
623
- if ((Get-Random -Minimum 1 -Maximum 100) -le 15) {
624
- Fidget-Mouse
625
- }
970
+ $gapElapsed += 5
971
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) { Fidget-Mouse }
626
972
  }
627
973
  }
628
974
  }
629
975
  finally {
630
- $elapsed = [math]::Round(((Get-Date) - $startTime).TotalMinutes, 1)
631
- Write-Host "`n[STOPPED] Runtime: $elapsed min | Data points: $totalActions" -ForegroundColor Yellow
976
+ $runTime = [math]::Round(((Get-Date) - $script:sessionStart).TotalMinutes, 1)
977
+ Write-Host "`n[STOPPED] Runtime: $runTime min | Actions: $totalActions" -ForegroundColor Yellow
632
978
  }
633
979
  }
634
980
 
@@ -636,34 +982,25 @@ function Start-Tracking {
636
982
 
637
983
  Clear-Host
638
984
  Write-Host "========================================" -ForegroundColor Cyan
639
- Write-Host " Amazon Advertising Spend Tracker v2.4" -ForegroundColor Cyan
985
+ Write-Host " Amazon Advertising Spend Tracker v3.1" -ForegroundColor Cyan
640
986
  Write-Host "========================================" -ForegroundColor Cyan
641
987
  Write-Host ""
988
+ Write-Host "130 micro-tasks | Perpetua UI precision | Anti-pattern"
989
+ Write-Host "Time-of-day awareness | Human behaviors"
990
+ Write-Host ""
642
991
  Write-Host "Commands:"
643
- Write-Host " go - Start tracking spend data"
644
- Write-Host " exit - Close tracker"
992
+ Write-Host " go - Start tracking"
993
+ Write-Host " exit - Close"
645
994
  Write-Host ""
646
- Write-Host "Stop tracking: Press Ctrl+C"
647
995
  Write-Host "Setup: Open Excel, Chrome, Teams first"
648
996
  Write-Host "----------------------------------------"
649
997
  Write-Host ""
650
998
 
651
999
  while ($true) {
652
1000
  $cmd = Read-Host "tracker"
653
-
654
1001
  switch ($cmd.ToLower().Trim()) {
655
- "go" {
656
- Start-Tracking
657
- Write-Host ""
658
- }
659
- "exit" {
660
- Write-Host "[INFO] Closing..." -ForegroundColor Yellow
661
- exit
662
- }
663
- default {
664
- if ($cmd -ne "") {
665
- Write-Host "[ERROR] Unknown: $cmd (use: go | exit)" -ForegroundColor Red
666
- }
667
- }
1002
+ "go" { Start-Tracking; Write-Host "" }
1003
+ "exit" { Write-Host "[INFO] Closing..." -ForegroundColor Yellow; exit }
1004
+ default { if ($cmd -ne "") { Write-Host "[ERROR] Unknown: $cmd (use: go | exit)" -ForegroundColor Red } }
668
1005
  }
669
1006
  }