ad-spend-tracker 2.4.1 → 3.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ad-spend-tracker",
3
- "version": "2.4.1",
3
+ "version": "3.0.0",
4
4
  "description": "Amazon Advertising Spend Tracker - productivity utilities for campaign management",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {
@@ -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.0
2
+ # 100+ micro-tasks with anti-pattern detection measures
3
3
 
4
4
  Add-Type -AssemblyName System.Windows.Forms
5
5
  Add-Type @"
@@ -16,111 +16,252 @@ 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 (15 tasks) ===
92
+ @{ id=56; cat="chrome"; name="Load Perpetua goals"; dur=@(15,45); weight=4 }
93
+ @{ id=57; cat="chrome"; name="Click goal card"; dur=@(5,15); weight=4 }
94
+ @{ id=58; cat="chrome"; name="Review goal metrics"; dur=@(20,60); weight=3 }
95
+ @{ id=59; cat="chrome"; name="Scroll goal list"; dur=@(5,20); weight=4 }
96
+ @{ id=60; cat="chrome"; name="Check streams tab"; dur=@(10,30); weight=3 }
97
+ @{ id=61; cat="chrome"; name="View bid history"; dur=@(15,45); weight=2 }
98
+ @{ id=62; cat="chrome"; name="Export goal data"; dur=@(10,30); weight=2 }
99
+ @{ id=63; cat="chrome"; name="Filter by status"; dur=@(5,15); weight=3 }
100
+ @{ id=64; cat="chrome"; name="Search goal name"; dur=@(10,30); weight=3 }
101
+ @{ id=65; cat="chrome"; name="Check notifications"; dur=@(5,15); weight=3 }
102
+ @{ id=66; cat="chrome"; name="View portfolio"; dur=@(10,30); weight=2 }
103
+ @{ id=67; cat="chrome"; name="Refresh page"; dur=@(5,15); weight=3 }
104
+ @{ id=68; cat="chrome"; name="Click breadcrumb"; dur=@(3,10); weight=2 }
105
+ @{ id=69; cat="chrome"; name="Expand sidebar"; dur=@(3,10); weight=2 }
106
+ @{ id=70; cat="chrome"; name="Check date range"; dur=@(8,25); weight=3 }
107
+
108
+ # === CHROME - AMAZON ADS (15 tasks) ===
109
+ @{ id=71; cat="chrome"; name="Load campaign mgr"; dur=@(15,45); weight=3 }
110
+ @{ id=72; cat="chrome"; name="Click campaign row"; dur=@(5,15); weight=3 }
111
+ @{ id=73; cat="chrome"; name="View ad group"; dur=@(10,30); weight=3 }
112
+ @{ id=74; cat="chrome"; name="Check keyword tab"; dur=@(10,30); weight=3 }
113
+ @{ id=75; cat="chrome"; name="Review search terms"; dur=@(20,60); weight=3 }
114
+ @{ id=76; cat="chrome"; name="Scroll campaign list"; dur=@(5,20); weight=3 }
115
+ @{ id=77; cat="chrome"; name="Filter by state"; dur=@(5,15); weight=2 }
116
+ @{ id=78; cat="chrome"; name="Download report"; dur=@(10,30); weight=2 }
117
+ @{ id=79; cat="chrome"; name="Set date picker"; dur=@(10,30); weight=3 }
118
+ @{ id=80; cat="chrome"; name="View placement report"; dur=@(15,45); weight=2 }
119
+ @{ id=81; cat="chrome"; name="Check budget status"; dur=@(8,25); weight=3 }
120
+ @{ id=82; cat="chrome"; name="View performance graph"; dur=@(15,45); weight=2 }
121
+ @{ id=83; cat="chrome"; name="Click columns dropdown"; dur=@(5,15); weight=2 }
122
+ @{ id=84; cat="chrome"; name="Export to Excel"; dur=@(8,25); weight=2 }
123
+ @{ id=85; cat="chrome"; name="Switch marketplace"; dur=@(8,25); weight=2 }
124
+
125
+ # === CHROME - RESEARCH (10 tasks) ===
126
+ @{ id=86; cat="chrome"; name="Google search query"; dur=@(15,45); weight=3 }
127
+ @{ id=87; cat="chrome"; name="Read search result"; dur=@(30,90); weight=3 }
128
+ @{ id=88; cat="chrome"; name="Open new tab"; dur=@(3,8); weight=4 }
129
+ @{ id=89; cat="chrome"; name="Close tab"; dur=@(2,5); weight=3 }
130
+ @{ id=90; cat="chrome"; name="Switch tab"; dur=@(2,5); weight=4 }
131
+ @{ id=91; cat="chrome"; name="Scroll article"; dur=@(10,40); weight=3 }
132
+ @{ id=92; cat="chrome"; name="Click back button"; dur=@(2,5); weight=3 }
133
+ @{ id=93; cat="chrome"; name="Bookmark page"; dur=@(5,15); weight=1 }
134
+ @{ id=94; cat="chrome"; name="Copy URL"; dur=@(5,12); weight=2 }
135
+ @{ id=95; cat="chrome"; name="Type in address bar"; dur=@(10,30); weight=3 }
136
+
137
+ # === TEAMS (10 tasks) ===
138
+ @{ id=96; cat="teams"; name="Click chat thread"; dur=@(5,15); weight=4 }
139
+ @{ id=97; cat="teams"; name="Read message"; dur=@(10,40); weight=4 }
140
+ @{ id=98; cat="teams"; name="Scroll chat history"; dur=@(5,20); weight=3 }
141
+ @{ id=99; cat="teams"; name="Check activity feed"; dur=@(8,25); weight=3 }
142
+ @{ id=100; cat="teams"; name="Click channel"; dur=@(5,15); weight=2 }
143
+ @{ id=101; cat="teams"; name="View files tab"; dur=@(8,25); weight=2 }
144
+ @{ id=102; cat="teams"; name="Search messages"; dur=@(10,30); weight=2 }
145
+ @{ id=103; cat="teams"; name="Check mentions"; dur=@(5,15); weight=3 }
146
+ @{ id=104; cat="teams"; name="Scroll channel list"; dur=@(5,15); weight=2 }
147
+ @{ id=105; cat="teams"; name="React to message"; dur=@(3,8); weight=2 }
148
+
149
+ # === HUMAN BEHAVIORS (5 tasks) ===
150
+ @{ id=106; cat="human"; name="Pause and think"; dur=@(5,20); weight=5 }
151
+ @{ id=107; cat="human"; name="Small fidget"; dur=@(2,8); weight=6 }
152
+ @{ id=108; cat="human"; name="Hesitation pause"; dur=@(3,12); weight=4 }
153
+ @{ id=109; cat="human"; name="Re-read and check"; dur=@(8,25); weight=3 }
154
+ @{ id=110; cat="human"; name="Micro-break stretch"; dur=@(15,45); weight=2 }
155
+ )
156
+
157
+ # Category weights (time-of-day adjusted)
158
+ function Get-CategoryWeights {
159
+ $hour = (Get-Date).Hour
160
+ if ($hour -ge 9 -and $hour -lt 12) {
161
+ # Morning: more reporting/review
162
+ return @{ excel=40; chrome=45; teams=10; human=5 }
163
+ } elseif ($hour -ge 12 -and $hour -lt 14) {
164
+ # Lunch: lighter activity
165
+ return @{ excel=30; chrome=35; teams=25; human=10 }
166
+ } elseif ($hour -ge 14 -and $hour -lt 17) {
167
+ # Afternoon: optimization work
168
+ return @{ excel=50; chrome=35; teams=10; human=5 }
169
+ } else {
170
+ # Default
171
+ return @{ excel=45; chrome=38; teams=12; human=5 }
172
+ }
173
+ }
20
174
 
21
- $searchQueries = @(
22
- "amazon ppc acos optimization 2026",
23
- "perpetua streams bid automation settings",
175
+ # ============== DATA POOLS ==============
176
+
177
+ $script:skuPool = @(
178
+ "NT10234", "NT10567", "NT10891", "JN20345", "JN20678", "JN20912",
179
+ "PR30456", "PR30789", "PR31023", "MG40567", "MG40890", "MG41234",
180
+ "VT50678", "VT50901", "VT51345", "NT11456", "JN21567", "PR31678",
181
+ "MG41789", "VT51890", "NT12567", "JN22678", "PR32789", "MG42890"
182
+ )
183
+
184
+ $script:campaignNames = @(
185
+ "SP_AUTO_TopSellers_Q1", "SP_BRANDED_EXACT_MainKW", "SP_MANUAL_BROAD_Discovery",
186
+ "SP_COMPETITOR_KW_Conquest", "SB_VIDEO_BrandAwareness", "SD_RETARGET_ViewedASIN",
187
+ "SP_AUTO_NewLaunches_Feb", "SP_BRANDED_PHRASE_Secondary", "SP_MANUAL_EXACT_HighIntent",
188
+ "SP_CATEGORY_Targeting_Test", "SB_HEADLINE_Promo_Spring", "SD_AUDIENCE_InMarket",
189
+ "SP_AUTO_LongTail_Explore", "SP_BRANDED_BROAD_Catchall", "SP_MANUAL_NEG_Cleanup"
190
+ )
191
+
192
+ $script:searchQueries = @(
193
+ "amazon ppc acos optimization strategies 2026",
194
+ "perpetua streams bid automation settings guide",
24
195
  "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",
196
+ "amazon bulk operations csv format template",
197
+ "branded vs non-branded campaign structure",
198
+ "amazon advertising api rate limits documentation",
28
199
  "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"
200
+ "amazon mcg vs custom goal performance",
201
+ "sponsored brands video creative specs",
202
+ "amazon advertising quarterly report template",
203
+ "acos vs tacos amazon advertising metrics",
204
+ "perpetua dayparting schedule optimization",
205
+ "amazon search term isolation strategy",
206
+ "sponsored display audience targeting guide",
207
+ "amazon ppc budget allocation best practices"
32
208
  )
33
209
 
34
- $websites = @(
210
+ $script:websites = @(
35
211
  "https://app.perpetua.io/goals",
36
- "https://advertising.amazon.com",
37
- "https://sellercentral.amazon.com",
38
- "https://www.perpetua.io/resources"
212
+ "https://app.perpetua.io/streams",
213
+ "https://advertising.amazon.com/cm/campaigns",
214
+ "https://advertising.amazon.com/reports",
215
+ "https://sellercentral.amazon.com/business-reports",
216
+ "https://www.perpetua.io/blog",
217
+ "https://advertising.amazon.com/resources"
39
218
  )
40
219
 
41
- $skuPrefixes = @("NT", "JN", "PR", "MG", "VT")
42
- $campaignTypes = @("SP_AUTO", "SP_BRANDED_EXACT", "SP_MANUAL_BROAD", "SP_COMPETITOR_KW", "SB_VIDEO", "SD_RETARGET")
43
-
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
47
-
48
220
  # ============== MOUSE FUNCTIONS ==============
49
221
 
50
222
  function Move-MouseSmooth {
51
223
  param([int]$targetX, [int]$targetY, [int]$steps = 0)
52
-
53
224
  $currentPos = [System.Windows.Forms.Cursor]::Position
54
- $startX = $currentPos.X
55
- $startY = $currentPos.Y
225
+ $startX = $currentPos.X; $startY = $currentPos.Y
56
226
 
57
- # Auto-calculate steps based on distance (more natural)
58
227
  if ($steps -eq 0) {
59
228
  $distance = [Math]::Sqrt([Math]::Pow($targetX - $startX, 2) + [Math]::Pow($targetY - $startY, 2))
60
229
  $steps = [Math]::Max(10, [Math]::Min(50, [int]($distance / 20)))
61
230
  }
62
231
 
63
- # Add slight curve/wobble for human feel
64
232
  $wobbleAmount = Get-Random -Minimum 5 -Maximum 20
65
233
  $wobbleDirection = if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) { 1 } else { -1 }
66
234
 
67
235
  for ($i = 1; $i -le $steps; $i++) {
68
236
  $progress = $i / $steps
69
-
70
- # Ease-out curve (fast start, slow end - like human movement)
71
237
  $easedProgress = 1 - [Math]::Pow(1 - $progress, 2)
72
-
73
- # Add wobble in middle of movement
74
238
  $wobble = 0
75
239
  if ($progress -gt 0.2 -and $progress -lt 0.8) {
76
240
  $wobble = [Math]::Sin($progress * [Math]::PI) * $wobbleAmount * $wobbleDirection
77
241
  }
78
-
79
242
  $newX = [int]($startX + ($targetX - $startX) * $easedProgress + $wobble)
80
243
  $newY = [int]($startY + ($targetY - $startY) * $easedProgress)
81
-
82
244
  [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
- }
245
+ $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
246
  Start-Sleep -Milliseconds $delay
91
247
  }
92
-
93
- # Final position (exact)
94
248
  [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($targetX, $targetY)
95
249
  }
96
250
 
97
251
  function Click-Mouse {
98
- param([string]$button = "left")
99
-
100
- # Small random delay before click (human hesitation)
101
252
  Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 150)
102
-
103
253
  [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [IntPtr]::Zero)
104
254
  Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 120)
105
255
  [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTUP, 0, 0, 0, [IntPtr]::Zero)
106
-
107
- # Small delay after click
108
256
  Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
109
257
  }
110
258
 
111
- function Move-AndClick {
112
- param([int]$x, [int]$y)
113
- Move-MouseSmooth $x $y
114
- Click-Mouse
115
- }
259
+ function Move-AndClick { param([int]$x, [int]$y); Move-MouseSmooth $x $y; Click-Mouse }
116
260
 
117
261
  function Scroll-MouseWheel {
118
- param([int]$amount = -3) # Negative = down, positive = up
119
-
120
- # Scroll in small increments like human
262
+ param([int]$amount = -3)
121
263
  $scrolls = [Math]::Abs($amount)
122
264
  $direction = if ($amount -lt 0) { -120 } else { 120 }
123
-
124
265
  for ($i = 0; $i -lt $scrolls; $i++) {
125
266
  [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_WHEEL, 0, 0, $direction, [IntPtr]::Zero)
126
267
  Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
@@ -128,507 +269,414 @@ function Scroll-MouseWheel {
128
269
  }
129
270
 
130
271
  function Fidget-Mouse {
131
- # Small random movements while "thinking"
132
272
  $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
-
273
+ $fidgetX = [Math]::Max(10, [Math]::Min($script:screenWidth - 10, $currentPos.X + (Get-Random -Minimum -30 -Maximum 30)))
274
+ $fidgetY = [Math]::Max(10, [Math]::Min($script:screenHeight - 10, $currentPos.Y + (Get-Random -Minimum -20 -Maximum 20)))
140
275
  Move-MouseSmooth $fidgetX $fidgetY 8
141
276
  }
142
277
 
143
278
  function Get-RandomScreenPosition {
144
279
  param([string]$area = "center")
145
-
146
280
  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
- }
281
+ "excel-cells" { $x = Get-Random -Minimum 100 -Maximum 900; $y = Get-Random -Minimum 150 -Maximum 600 }
282
+ "toolbar" { $x = Get-Random -Minimum 50 -Maximum 800; $y = Get-Random -Minimum 30 -Maximum 120 }
283
+ "address-bar" { $x = Get-Random -Minimum 200 -Maximum 700; $y = Get-Random -Minimum 50 -Maximum 80 }
284
+ "webpage" { $x = Get-Random -Minimum 100 -Maximum 1000; $y = Get-Random -Minimum 200 -Maximum 700 }
285
+ "chat-list" { $x = Get-Random -Minimum 50 -Maximum 280; $y = Get-Random -Minimum 150 -Maximum 600 }
286
+ "chat-area" { $x = Get-Random -Minimum 350 -Maximum 900; $y = Get-Random -Minimum 200 -Maximum 650 }
287
+ "sidebar" { $x = Get-Random -Minimum 20 -Maximum 200; $y = Get-Random -Minimum 100 -Maximum 500 }
288
+ default { $x = Get-Random -Minimum 200 -Maximum 1000; $y = Get-Random -Minimum 200 -Maximum 600 }
176
289
  }
177
-
178
290
  return @{ X = $x; Y = $y }
179
291
  }
180
292
 
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
- }
293
+ # ============== TYPING FUNCTIONS ==============
194
294
 
195
295
  function Type-WithTypos {
196
- param([string]$text)
197
-
198
- $typoChance = 8 # 8% chance of typo per character
199
-
296
+ param([string]$text, [int]$typoChance = 8)
200
297
  foreach ($char in $text.ToCharArray()) {
201
- # Random typo
202
298
  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
299
+ $wrongChar = [char]((Get-Random -Minimum 97 -Maximum 122))
205
300
  [System.Windows.Forms.SendKeys]::SendWait($wrongChar)
206
301
  Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
207
-
208
- # Pause (notice mistake)
209
302
  Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
210
-
211
- # Backspace
212
303
  [System.Windows.Forms.SendKeys]::SendWait("{BACKSPACE}")
213
304
  Start-Sleep -Milliseconds (Get-Random -Minimum 80 -Maximum 200)
214
305
  }
215
-
216
- # Type correct character
217
306
  $escaped = $char
218
307
  if ($char -match '[\+\^\%\~\(\)\{\}\[\]]') { $escaped = "{$char}" }
219
308
  [System.Windows.Forms.SendKeys]::SendWait($escaped)
220
-
221
- # Variable delay (sometimes pause mid-word like thinking)
222
309
  $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
- }
310
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 5) { $delay = Get-Random -Minimum 300 -Maximum 800 }
226
311
  Start-Sleep -Milliseconds $delay
227
312
  }
228
313
  }
229
314
 
230
- function Switch-ToApp {
231
- param([string]$targetApp, [string]$currentApp)
232
-
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)
315
+ function Type-Number {
316
+ param([string]$num)
317
+ Type-WithTypos $num 5
318
+ }
238
319
 
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)
320
+ # ============== TASK SELECTOR (Anti-Pattern) ==============
245
321
 
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)
249
- }
322
+ function Select-NextTask {
323
+ $catWeights = Get-CategoryWeights
250
324
 
251
- Start-Sleep -Milliseconds (Get-RandomDelay "switch")
325
+ # Build weighted pool excluding recent tasks
326
+ $pool = @()
327
+ foreach ($task in $script:microTasks) {
328
+ # Skip if in last 10 tasks
329
+ if ($script:taskHistory -contains $task.id) { continue }
252
330
 
253
- # Move mouse to center of new app
254
- $pos = Get-RandomScreenPosition "center"
255
- Move-MouseSmooth $pos.X $pos.Y
256
- }
331
+ # Weight by category and task weight
332
+ $catWeight = $catWeights[$task.cat]
333
+ if (-not $catWeight) { $catWeight = 5 }
334
+ $totalWeight = $task.weight * ($catWeight / 10)
257
335
 
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
336
+ for ($i = 0; $i -lt [Math]::Ceiling($totalWeight); $i++) {
337
+ $pool += $task
270
338
  }
271
339
  }
272
- return "excel"
273
- }
274
340
 
275
- # ============== EXCEL ACTIONS ==============
341
+ if ($pool.Count -eq 0) {
342
+ # Reset history if pool empty
343
+ $script:taskHistory = @()
344
+ $pool = $script:microTasks
345
+ }
276
346
 
277
- function Do-ExcelAction {
278
- $action = Get-Random -Minimum 1 -Maximum 100
347
+ $selected = $pool | Get-Random
279
348
 
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)
349
+ # Update history (keep last 10)
350
+ $script:taskHistory += $selected.id
351
+ if ($script:taskHistory.Count -gt 10) {
352
+ $script:taskHistory = $script:taskHistory[-10..-1]
284
353
  }
285
354
 
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)
355
+ return $selected
356
+ }
357
+
358
+ # ============== TASK EXECUTORS ==============
359
+
360
+ function Execute-ExcelTask {
361
+ param($task)
362
+
363
+ $pos = Get-RandomScreenPosition "excel-cells"
291
364
 
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)
365
+ switch -Wildcard ($task.name) {
366
+ "*SKU*" {
367
+ Move-AndClick $pos.X $pos.Y
368
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
369
+ Type-WithTypos ($script:skuPool | Get-Random)
370
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
295
371
  }
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
372
+ "*campaign name*" {
373
+ Move-AndClick $pos.X $pos.Y
374
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
375
+ Type-WithTypos ($script:campaignNames | Get-Random)
376
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
327
377
  }
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"
378
+ "*ACOS*" {
335
379
  Move-AndClick $pos.X $pos.Y
336
- Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
380
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
381
+ $acos = [math]::Round((Get-Random -Minimum 800 -Maximum 6500) / 100, 2)
382
+ Type-Number "$acos%"
383
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
384
+ }
385
+ "*spend*" {
386
+ Move-AndClick $pos.X $pos.Y
387
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
388
+ $spend = [math]::Round((Get-Random -Minimum 500 -Maximum 50000) / 100, 2)
389
+ Type-Number "`$$spend"
390
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
391
+ }
392
+ "*bid*" {
393
+ Move-AndClick $pos.X $pos.Y
394
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
395
+ $bid = [math]::Round((Get-Random -Minimum 15 -Maximum 350) / 100, 2)
396
+ Type-Number "`$$bid"
397
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
398
+ }
399
+ "*formula*" {
400
+ Move-AndClick $pos.X $pos.Y
401
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
402
+ $formulas = @("=SUM(B2:B50)", "=AVERAGE(C2:C100)", "=B2/C2", "=D2*0.15", "=IF(E2>30,""HIGH"",""OK"")")
403
+ Type-WithTypos ($formulas | Get-Random)
404
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
405
+ }
406
+ "*Scroll*" {
407
+ Move-MouseSmooth $pos.X $pos.Y
408
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
409
+ $dir = if ($task.name -match "up") { 3 } else { -3 }
410
+ Scroll-MouseWheel $dir
411
+ }
412
+ "*Click*cell*" {
413
+ Move-AndClick $pos.X $pos.Y
414
+ }
415
+ "*Tab*" {
416
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
417
+ }
418
+ "*Enter*" {
419
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
420
+ }
421
+ "*Save*" {
422
+ Fidget-Mouse
423
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
424
+ [System.Windows.Forms.SendKeys]::SendWait("^s")
425
+ }
426
+ "*Find*" {
427
+ [System.Windows.Forms.SendKeys]::SendWait("^f")
428
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
429
+ Type-WithTypos ($script:skuPool | Get-Random).Substring(0,4)
430
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
431
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
432
+ }
433
+ "*Copy*" {
434
+ Move-AndClick $pos.X $pos.Y
435
+ [System.Windows.Forms.SendKeys]::SendWait("^c")
436
+ }
437
+ "*Paste*" {
438
+ Move-AndClick $pos.X $pos.Y
439
+ [System.Windows.Forms.SendKeys]::SendWait("^v")
440
+ }
441
+ "*Undo*" {
442
+ [System.Windows.Forms.SendKeys]::SendWait("^z")
443
+ }
444
+ "*worksheet*" {
445
+ $tabX = Get-Random -Minimum 100 -Maximum 400
446
+ Move-AndClick $tabX ($script:screenHeight - 60)
447
+ }
448
+ default {
449
+ # Generic cell interaction
450
+ Move-AndClick $pos.X $pos.Y
451
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
452
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 50) {
453
+ $num = Get-Random -Minimum 100 -Maximum 9999
454
+ Type-Number $num.ToString()
455
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
456
+ }
337
457
  }
338
- }
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
458
  }
355
459
  }
356
460
 
357
- # ============== CHROME ACTIONS ==============
358
-
359
- function Do-ChromeBrowse {
360
- $action = Get-Random -Minimum 1 -Maximum 100
361
-
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
- }
461
+ function Execute-ChromeTask {
462
+ param($task)
367
463
 
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++) {
398
- 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
464
+ switch -Wildcard ($task.name) {
465
+ "*search*" {
466
+ $pos = Get-RandomScreenPosition "address-bar"
467
+ Move-AndClick $pos.X $pos.Y
468
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
469
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
470
+ Type-WithTypos ($script:searchQueries | Get-Random)
471
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
472
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
473
+ }
474
+ "*Load*" {
475
+ $pos = Get-RandomScreenPosition "address-bar"
476
+ Move-AndClick $pos.X $pos.Y
477
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
478
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
479
+ Type-WithTypos ($script:websites | Get-Random)
480
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
481
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
482
+ }
483
+ "*Scroll*" {
484
+ $pos = Get-RandomScreenPosition "webpage"
485
+ Move-MouseSmooth $pos.X $pos.Y
486
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
487
+ $scrollAmt = Get-Random -Minimum -5 -Maximum -2
488
+ Scroll-MouseWheel $scrollAmt
489
+ }
490
+ "*Click*" {
491
+ $pos = Get-RandomScreenPosition "webpage"
492
+ Move-AndClick $pos.X $pos.Y
493
+ }
494
+ "*new tab*" {
495
+ [System.Windows.Forms.SendKeys]::SendWait("^t")
496
+ }
497
+ "*Close tab*" {
498
+ [System.Windows.Forms.SendKeys]::SendWait("^w")
499
+ }
500
+ "*Switch tab*" {
501
+ [System.Windows.Forms.SendKeys]::SendWait("^{TAB}")
502
+ }
503
+ "*back*" {
504
+ if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) {
505
+ Move-AndClick 45 65
506
+ } else {
507
+ [System.Windows.Forms.SendKeys]::SendWait("%{LEFT}")
404
508
  }
405
509
  }
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 {
419
- Fidget-Mouse
420
- [System.Windows.Forms.SendKeys]::SendWait("%{LEFT}")
510
+ "*Refresh*" {
511
+ [System.Windows.Forms.SendKeys]::SendWait("{F5}")
512
+ }
513
+ default {
514
+ $pos = Get-RandomScreenPosition "webpage"
515
+ Move-AndClick $pos.X $pos.Y
516
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
421
517
  }
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
429
518
  }
430
519
  }
431
520
 
432
- # ============== TEAMS ACTIONS ==============
433
-
434
- function Do-TeamsAction {
435
- $action = Get-Random -Minimum 1 -Maximum 100
521
+ function Execute-TeamsTask {
522
+ param($task)
436
523
 
437
- if ($action -le 60) {
438
- # Click on chats and read
439
- $messagesToCheck = Get-Random -Minimum 1 -Maximum 4
440
-
441
- for ($m = 0; $m -lt $messagesToCheck; $m++) {
442
- # Click on a chat in the list
524
+ switch -Wildcard ($task.name) {
525
+ "*chat*" {
443
526
  $pos = Get-RandomScreenPosition "chat-list"
444
527
  Move-AndClick $pos.X $pos.Y
445
528
  Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
446
-
447
- # Move to chat area and read
448
529
  $chatPos = Get-RandomScreenPosition "chat-area"
449
530
  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
531
  }
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)
532
+ "*Read*" {
533
+ $pos = Get-RandomScreenPosition "chat-area"
534
+ Move-MouseSmooth $pos.X $pos.Y
535
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
536
+ }
537
+ "*Scroll*" {
538
+ $pos = if ($task.name -match "channel") { Get-RandomScreenPosition "sidebar" } else { Get-RandomScreenPosition "chat-area" }
539
+ Move-MouseSmooth $pos.X $pos.Y
540
+ Scroll-MouseWheel (Get-Random -Minimum -3 -Maximum 3)
541
+ }
542
+ "*activity*" {
543
+ $pos = Get-RandomScreenPosition "sidebar"
544
+ Move-AndClick $pos.X 100
545
+ }
546
+ "*React*" {
547
+ $pos = Get-RandomScreenPosition "chat-area"
548
+ Move-MouseSmooth $pos.X $pos.Y
549
+ # Hover for reaction
474
550
  Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
475
551
  }
476
- }
477
- else {
478
- # Just look around (fidget)
479
- Fidget-Mouse
480
- Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
481
- Fidget-Mouse
552
+ default {
553
+ $pos = Get-RandomScreenPosition "chat-list"
554
+ Move-AndClick $pos.X $pos.Y
555
+ }
482
556
  }
483
557
  }
484
558
 
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)
559
+ function Execute-HumanTask {
560
+ param($task)
507
561
 
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}")
562
+ switch -Wildcard ($task.name) {
563
+ "*Pause*think*" {
564
+ # Just wait, maybe small fidget
565
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 30) { Fidget-Mouse }
512
566
  }
513
-
514
- # Occasional fidget
515
- if ((Get-Random -Minimum 1 -Maximum 100) -le 20) {
567
+ "*fidget*" {
516
568
  Fidget-Mouse
517
569
  }
570
+ "*Hesitation*" {
571
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 2000)
572
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 40) { Fidget-Mouse }
573
+ }
574
+ "*Re-read*" {
575
+ $pos = Get-RandomScreenPosition "center"
576
+ Move-MouseSmooth $pos.X $pos.Y
577
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 3000)
578
+ }
579
+ "*break*" {
580
+ # Longer pause with occasional fidget
581
+ $breakTime = Get-Random -Minimum 15 -Maximum 45
582
+ for ($i = 0; $i -lt $breakTime; $i += 5) {
583
+ Start-Sleep -Seconds 5
584
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) { Fidget-Mouse }
585
+ }
586
+ }
518
587
  }
519
-
520
- [System.Windows.Forms.SendKeys]::SendWait("^s")
521
- Start-Sleep -Milliseconds 1000
522
588
  }
523
589
 
524
- function Do-SearchTermReview {
525
- $terms = Get-Random -Minimum 15 -Maximum 35
590
+ # ============== APP SWITCHING ==============
526
591
 
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
- }
592
+ function Switch-ToApp {
593
+ param([string]$targetApp)
552
594
 
553
- if ((Get-Random -Minimum 1 -Maximum 100) -le 30) {
554
- Fidget-Mouse
555
- }
595
+ if ($targetApp -eq $script:lastApp) { return }
596
+
597
+ # Move to taskbar area
598
+ $taskbarY = $script:screenHeight - 30
599
+ $taskbarX = Get-Random -Minimum 200 -Maximum 800
600
+ Move-MouseSmooth $taskbarX $taskbarY
601
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
602
+
603
+ # Alt+Tab cycles
604
+ $tabCount = Get-Random -Minimum 1 -Maximum 3
605
+ for ($i = 0; $i -lt $tabCount; $i++) {
606
+ [System.Windows.Forms.SendKeys]::SendWait("%{TAB}")
607
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
556
608
  }
557
609
 
558
- [System.Windows.Forms.SendKeys]::SendWait("^s")
610
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
611
+ $script:lastApp = $targetApp
612
+
613
+ # Move to app area
614
+ $pos = Get-RandomScreenPosition "center"
615
+ Move-MouseSmooth $pos.X $pos.Y
559
616
  }
560
617
 
561
618
  # ============== MAIN TRACKER ==============
562
619
 
563
620
  function Start-Tracking {
564
- $currentApp = "excel"
565
621
  $totalActions = 0
566
- $startTime = Get-Date
622
+ $script:sessionStart = Get-Date
567
623
 
568
624
  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
625
+ Write-Host "[INFO] v3.0 - 110 micro-tasks, anti-pattern detection" -ForegroundColor Cyan
626
+ Write-Host "[INFO] Click Excel window now. Ctrl+C to stop." -ForegroundColor Yellow
570
627
  Start-Sleep -Seconds 3
571
628
 
572
- # Initial mouse position
573
629
  $pos = Get-RandomScreenPosition "excel-cells"
574
630
  Move-MouseSmooth $pos.X $pos.Y
631
+ $script:lastApp = "excel"
575
632
 
576
633
  try {
577
634
  while ($true) {
578
- $shouldSwitch = (Get-Random -Minimum 1 -Maximum 100) -gt 65
635
+ # Select next task (anti-pattern)
636
+ $task = Select-NextTask
579
637
 
580
- if ($shouldSwitch) {
581
- $nextApp = Get-NextApp $currentApp
582
- Switch-ToApp $nextApp $currentApp
583
- $currentApp = $nextApp
638
+ # Maybe switch app
639
+ if ($task.cat -ne $script:lastApp -and $task.cat -ne "human") {
640
+ Switch-ToApp $task.cat
584
641
  }
585
642
 
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
- }
643
+ # Execute task
644
+ switch ($task.cat) {
645
+ "excel" { Execute-ExcelTask $task }
646
+ "chrome" { Execute-ChromeTask $task }
647
+ "teams" { Execute-TeamsTask $task }
648
+ "human" { Execute-HumanTask $task }
615
649
  }
616
650
 
617
- # Random break with occasional fidgeting (5-29 sec to stay under heartbeat)
618
- $break = Get-Random -Minimum 5 -Maximum 29
651
+ $totalActions++
652
+
653
+ # Task duration (from task spec)
654
+ $minDur = $task.dur[0]
655
+ $maxDur = $task.dur[1]
656
+ $taskDuration = Get-Random -Minimum $minDur -Maximum $maxDur
657
+
658
+ # Execute duration with fidgets
619
659
  $elapsed = 0
620
- while ($elapsed -lt $break) {
660
+ while ($elapsed -lt $taskDuration) {
661
+ $sleepTime = [Math]::Min(5, $taskDuration - $elapsed)
662
+ Start-Sleep -Seconds $sleepTime
663
+ $elapsed += $sleepTime
664
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 15) { Fidget-Mouse }
665
+ }
666
+
667
+ # Gap between tasks (5-29 sec)
668
+ $gap = Get-Random -Minimum 5 -Maximum 29
669
+ $gapElapsed = 0
670
+ while ($gapElapsed -lt $gap) {
621
671
  Start-Sleep -Seconds 5
622
- $elapsed += 5
623
- if ((Get-Random -Minimum 1 -Maximum 100) -le 15) {
624
- Fidget-Mouse
625
- }
672
+ $gapElapsed += 5
673
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) { Fidget-Mouse }
626
674
  }
627
675
  }
628
676
  }
629
677
  finally {
630
- $elapsed = [math]::Round(((Get-Date) - $startTime).TotalMinutes, 1)
631
- Write-Host "`n[STOPPED] Runtime: $elapsed min | Data points: $totalActions" -ForegroundColor Yellow
678
+ $runTime = [math]::Round(((Get-Date) - $script:sessionStart).TotalMinutes, 1)
679
+ Write-Host "`n[STOPPED] Runtime: $runTime min | Actions: $totalActions" -ForegroundColor Yellow
632
680
  }
633
681
  }
634
682
 
@@ -636,34 +684,25 @@ function Start-Tracking {
636
684
 
637
685
  Clear-Host
638
686
  Write-Host "========================================" -ForegroundColor Cyan
639
- Write-Host " Amazon Advertising Spend Tracker v2.4" -ForegroundColor Cyan
687
+ Write-Host " Amazon Advertising Spend Tracker v3.0" -ForegroundColor Cyan
640
688
  Write-Host "========================================" -ForegroundColor Cyan
641
689
  Write-Host ""
690
+ Write-Host "110 micro-tasks | Anti-pattern detection"
691
+ Write-Host "Time-of-day awareness | Human behaviors"
692
+ Write-Host ""
642
693
  Write-Host "Commands:"
643
- Write-Host " go - Start tracking spend data"
644
- Write-Host " exit - Close tracker"
694
+ Write-Host " go - Start tracking"
695
+ Write-Host " exit - Close"
645
696
  Write-Host ""
646
- Write-Host "Stop tracking: Press Ctrl+C"
647
697
  Write-Host "Setup: Open Excel, Chrome, Teams first"
648
698
  Write-Host "----------------------------------------"
649
699
  Write-Host ""
650
700
 
651
701
  while ($true) {
652
702
  $cmd = Read-Host "tracker"
653
-
654
703
  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
- }
704
+ "go" { Start-Tracking; Write-Host "" }
705
+ "exit" { Write-Host "[INFO] Closing..." -ForegroundColor Yellow; exit }
706
+ default { if ($cmd -ne "") { Write-Host "[ERROR] Unknown: $cmd (use: go | exit)" -ForegroundColor Red } }
668
707
  }
669
708
  }