ad-spend-tracker 3.1.0 → 4.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.
@@ -0,0 +1,1237 @@
1
+ # Amazon Advertising Spend Tracker v4.0 - BULK FILE EDITION
2
+ # Real operations on 1.2GB bulk file + 140+ micro-tasks
3
+
4
+ Add-Type -AssemblyName System.Windows.Forms
5
+ Add-Type @"
6
+ using System;
7
+ using System.Runtime.InteropServices;
8
+ public class Mouse {
9
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
10
+ public static extern void mouse_event(uint dwFlags, uint dx, uint dy, int dwData, IntPtr dwExtraInfo);
11
+ public const uint MOUSEEVENTF_LEFTDOWN = 0x02;
12
+ public const uint MOUSEEVENTF_LEFTUP = 0x04;
13
+ public const uint MOUSEEVENTF_WHEEL = 0x0800;
14
+ }
15
+ "@
16
+
17
+ # ============== CONFIGURATION ==============
18
+
19
+ $script:screenWidth = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width
20
+ $script:screenHeight = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height
21
+
22
+ # Excel COM object (for real file operations)
23
+ $script:excel = $null
24
+ $script:workbook = $null
25
+ $script:worksheet = $null
26
+ $script:bulkFileLoaded = $false
27
+ $script:bulkFilePath = "C:\Users\Krell\Documents\Imps\gits\rmm-research\Bulk sample.xlsx"
28
+
29
+ # Task history for anti-pattern (never repeat last 20)
30
+ $script:taskHistory = @()
31
+ $script:lastApp = ""
32
+ $script:sessionStart = Get-Date
33
+
34
+ # Bulk file metadata (populated after loading)
35
+ $script:bulkFileInfo = @{
36
+ totalRows = 0
37
+ worksheets = @()
38
+ columns = @()
39
+ rowRanges = @()
40
+ }
41
+
42
+ # ============== 140+ MICRO-TASKS ==============
43
+
44
+ $script:microTasks = @(
45
+ # === EXCEL - CAMPAIGN DATA (25 tasks) ===
46
+ @{ id=1; cat="excel"; name="Enter SKU in cell"; dur=@(8,25); weight=4 }
47
+ @{ id=2; cat="excel"; name="Type campaign name"; dur=@(12,35); weight=4 }
48
+ @{ id=3; cat="excel"; name="Enter ACOS value"; dur=@(5,15); weight=5 }
49
+ @{ id=4; cat="excel"; name="Type spend amount"; dur=@(5,12); weight=5 }
50
+ @{ id=5; cat="excel"; name="Enter sales figure"; dur=@(5,12); weight=4 }
51
+ @{ id=6; cat="excel"; name="Type impressions count"; dur=@(6,15); weight=3 }
52
+ @{ id=7; cat="excel"; name="Enter clicks value"; dur=@(5,12); weight=3 }
53
+ @{ id=8; cat="excel"; name="Type CTR percentage"; dur=@(5,12); weight=3 }
54
+ @{ id=9; cat="excel"; name="Enter CPC value"; dur=@(5,12); weight=3 }
55
+ @{ id=10; cat="excel"; name="Type conversion rate"; dur=@(6,15); weight=3 }
56
+ @{ id=11; cat="excel"; name="Add ROAS formula"; dur=@(15,40); weight=3 }
57
+ @{ id=12; cat="excel"; name="Create SUM formula"; dur=@(10,30); weight=3 }
58
+ @{ id=13; cat="excel"; name="Add AVERAGE formula"; dur=@(10,30); weight=2 }
59
+ @{ id=14; cat="excel"; name="Enter date value"; dur=@(8,20); weight=3 }
60
+ @{ id=15; cat="excel"; name="Type ad group name"; dur=@(10,30); weight=3 }
61
+ @{ id=16; cat="excel"; name="Enter keyword text"; dur=@(12,35); weight=4 }
62
+ @{ id=17; cat="excel"; name="Type match type"; dur=@(5,12); weight=3 }
63
+ @{ id=18; cat="excel"; name="Add targeting note"; dur=@(15,45); weight=2 }
64
+ @{ id=19; cat="excel"; name="Enter budget value"; dur=@(5,15); weight=3 }
65
+ @{ id=20; cat="excel"; name="Type bid amount"; dur=@(5,12); weight=4 }
66
+ @{ id=21; cat="excel"; name="Add status column"; dur=@(5,12); weight=3 }
67
+ @{ id=22; cat="excel"; name="Enter placement type"; dur=@(8,20); weight=2 }
68
+ @{ id=23; cat="excel"; name="Type portfolio name"; dur=@(10,25); weight=2 }
69
+ @{ id=24; cat="excel"; name="Add ASIN value"; dur=@(10,20); weight=3 }
70
+ @{ id=25; cat="excel"; name="Enter negative KW"; dur=@(12,30); weight=3 }
71
+
72
+ # === EXCEL - NAVIGATION (20 tasks) ===
73
+ @{ id=26; cat="excel"; name="Scroll down slowly"; dur=@(3,10); weight=5 }
74
+ @{ id=27; cat="excel"; name="Scroll up slowly"; dur=@(3,10); weight=4 }
75
+ @{ id=28; cat="excel"; name="Click random cell"; dur=@(2,6); weight=6 }
76
+ @{ id=29; cat="excel"; name="Select cell range"; dur=@(5,15); weight=4 }
77
+ @{ id=30; cat="excel"; name="Double-click cell"; dur=@(3,8); weight=3 }
78
+ @{ id=31; cat="excel"; name="Press Tab key"; dur=@(1,3); weight=5 }
79
+ @{ id=32; cat="excel"; name="Press Enter key"; dur=@(1,3); weight=5 }
80
+ @{ id=33; cat="excel"; name="Navigate with arrows"; dur=@(3,12); weight=4 }
81
+ @{ id=34; cat="excel"; name="Go to cell Ctrl+G"; dur=@(8,20); weight=2 }
82
+ @{ id=35; cat="excel"; name="Find Ctrl+F search"; dur=@(10,30); weight=3 }
83
+ @{ id=36; cat="excel"; name="Switch worksheet tab"; dur=@(3,8); weight=4 }
84
+ @{ id=37; cat="excel"; name="Resize column width"; dur=@(5,15); weight=2 }
85
+ @{ id=38; cat="excel"; name="Sort column A-Z"; dur=@(5,15); weight=3 }
86
+ @{ id=39; cat="excel"; name="Filter dropdown click"; dur=@(5,15); weight=3 }
87
+ @{ id=40; cat="excel"; name="Clear filter"; dur=@(3,8); weight=2 }
88
+ @{ id=41; cat="excel"; name="Copy cells Ctrl+C"; dur=@(3,8); weight=3 }
89
+ @{ id=42; cat="excel"; name="Paste cells Ctrl+V"; dur=@(3,8); weight=3 }
90
+ @{ id=43; cat="excel"; name="Undo action Ctrl+Z"; dur=@(2,5); weight=2 }
91
+ @{ id=44; cat="excel"; name="Save file Ctrl+S"; dur=@(2,5); weight=4 }
92
+ @{ id=45; cat="excel"; name="Zoom in/out"; dur=@(3,10); weight=2 }
93
+
94
+ # === EXCEL - BULK OPERATIONS (10 tasks) ===
95
+ @{ id=46; cat="excel"; name="Review bid column"; dur=@(30,90); weight=3 }
96
+ @{ id=47; cat="excel"; name="Update multiple bids"; dur=@(60,180); weight=2 }
97
+ @{ id=48; cat="excel"; name="Mark negatives batch"; dur=@(45,120); weight=2 }
98
+ @{ id=49; cat="excel"; name="Validate ACOS range"; dur=@(30,90); weight=2 }
99
+ @{ id=50; cat="excel"; name="Check spend totals"; dur=@(20,60); weight=2 }
100
+ @{ id=51; cat="excel"; name="Compare week data"; dur=@(45,120); weight=2 }
101
+ @{ id=52; cat="excel"; name="Highlight outliers"; dur=@(30,90); weight=2 }
102
+ @{ id=53; cat="excel"; name="Format cells batch"; dur=@(20,60); weight=2 }
103
+ @{ id=54; cat="excel"; name="Add conditional format"; dur=@(25,75); weight=2 }
104
+ @{ id=55; cat="excel"; name="Create pivot selection"; dur=@(30,90); weight=1 }
105
+
106
+ # === EXCEL - REAL BULK FILE OPERATIONS (15 NEW tasks) ===
107
+ @{ id=131; cat="bulk"; name="Jump to row 50000"; dur=@(8,20); weight=3 }
108
+ @{ id=132; cat="bulk"; name="Jump to row 100000"; dur=@(10,25); weight=2 }
109
+ @{ id=133; cat="bulk"; name="Scroll through bulk data"; dur=@(15,45); weight=4 }
110
+ @{ id=134; cat="bulk"; name="Filter ACOS > 20%"; dur=@(10,30); weight=3 }
111
+ @{ id=135; cat="bulk"; name="Filter by campaign name"; dur=@(10,30); weight=3 }
112
+ @{ id=136; cat="bulk"; name="Sort by Spend DESC"; dur=@(8,25); weight=3 }
113
+ @{ id=137; cat="bulk"; name="Sort by ACOS ASC"; dur=@(8,25); weight=3 }
114
+ @{ id=138; cat="bulk"; name="Clear all filters"; dur=@(5,15); weight=2 }
115
+ @{ id=139; cat="bulk"; name="Navigate to Sheet 2"; dur=@(5,15); weight=2 }
116
+ @{ id=140; cat="bulk"; name="Search specific SKU"; dur=@(15,40); weight=3 }
117
+ @{ id=141; cat="bulk"; name="Review data range"; dur=@(30,90); weight=3 }
118
+ @{ id=142; cat="bulk"; name="Select large range"; dur=@(10,30); weight=2 }
119
+ @{ id=143; cat="bulk"; name="Copy bulk data range"; dur=@(8,20); weight=2 }
120
+ @{ id=144; cat="bulk"; name="Scroll to end of data"; dur=@(8,20); weight=2 }
121
+ @{ id=145; cat="bulk"; name="Return to top of file"; dur=@(5,15); weight=2 }
122
+
123
+ # === CHROME - PERPETUA GOALS (20 tasks) ===
124
+ @{ id=56; cat="perpetua"; name="Navigate SP Goals"; dur=@(8,20); weight=4 }
125
+ @{ id=57; cat="perpetua"; name="Click goal row"; dur=@(3,10); weight=5 }
126
+ @{ id=58; cat="perpetua"; name="Review goal ACOS metric"; dur=@(15,45); weight=4 }
127
+ @{ id=59; cat="perpetua"; name="Review goal spend metric"; dur=@(10,30); weight=4 }
128
+ @{ id=60; cat="perpetua"; name="Scroll goals list down"; dur=@(5,15); weight=5 }
129
+ @{ id=61; cat="perpetua"; name="Scroll goals list up"; dur=@(5,15); weight=4 }
130
+ @{ id=62; cat="perpetua"; name="Click goal tabs Keywords"; dur=@(5,15); weight=3 }
131
+ @{ id=63; cat="perpetua"; name="Click goal tabs Negatives"; dur=@(5,15); weight=3 }
132
+ @{ id=64; cat="perpetua"; name="Click goal tabs History"; dur=@(5,15); weight=3 }
133
+ @{ id=65; cat="perpetua"; name="Search goal by name"; dur=@(12,35); weight=3 }
134
+ @{ id=66; cat="perpetua"; name="Filter goals Enabled"; dur=@(5,15); weight=3 }
135
+ @{ id=67; cat="perpetua"; name="Filter goals Paused"; dur=@(5,15); weight=2 }
136
+ @{ id=68; cat="perpetua"; name="Sort by ACOS column"; dur=@(3,10); weight=3 }
137
+ @{ id=69; cat="perpetua"; name="Sort by Spend column"; dur=@(3,10); weight=3 }
138
+ @{ id=70; cat="perpetua"; name="Change date range 7d"; dur=@(8,20); weight=3 }
139
+ @{ id=71; cat="perpetua"; name="Change date range 30d"; dur=@(8,20); weight=3 }
140
+ @{ id=72; cat="perpetua"; name="Click New Goal button"; dur=@(3,8); weight=2 }
141
+ @{ id=73; cat="perpetua"; name="Close goal detail modal"; dur=@(2,5); weight=3 }
142
+ @{ id=74; cat="perpetua"; name="Navigate SB Goals"; dur=@(8,20); weight=3 }
143
+ @{ id=75; cat="perpetua"; name="Navigate SD Goals"; dur=@(8,20); weight=2 }
144
+
145
+ # === CHROME - PERPETUA STREAMS (12 tasks) ===
146
+ @{ id=76; cat="perpetua"; name="Navigate SP Streams"; dur=@(8,20); weight=4 }
147
+ @{ id=77; cat="perpetua"; name="Click stream row"; dur=@(3,10); weight=4 }
148
+ @{ id=78; cat="perpetua"; name="Scroll streams list"; dur=@(5,15); weight=4 }
149
+ @{ id=79; cat="perpetua"; name="View stream bid changes"; dur=@(15,40); weight=3 }
150
+ @{ id=80; cat="perpetua"; name="Filter streams by status"; dur=@(5,15); weight=3 }
151
+ @{ id=81; cat="perpetua"; name="Check stream ACOS trend"; dur=@(10,30); weight=3 }
152
+ @{ id=82; cat="perpetua"; name="Review stream keywords"; dur=@(15,45); weight=3 }
153
+ @{ id=83; cat="perpetua"; name="Expand stream details"; dur=@(5,15); weight=3 }
154
+ @{ id=84; cat="perpetua"; name="Collapse stream details"; dur=@(3,8); weight=2 }
155
+ @{ id=85; cat="perpetua"; name="Sort streams by spend"; dur=@(3,10); weight=3 }
156
+ @{ id=86; cat="perpetua"; name="Check stream automation"; dur=@(8,25); weight=2 }
157
+ @{ id=87; cat="perpetua"; name="Navigate Analytics page"; dur=@(8,20); weight=2 }
158
+
159
+ # === CHROME - PERPETUA GENERAL (8 tasks) ===
160
+ @{ id=88; cat="perpetua"; name="Click sidebar nav item"; dur=@(3,10); weight=4 }
161
+ @{ id=89; cat="perpetua"; name="Hover sidebar expand"; dur=@(2,6); weight=3 }
162
+ @{ id=90; cat="perpetua"; name="Click account dropdown"; dur=@(3,8); weight=2 }
163
+ @{ id=91; cat="perpetua"; name="Check notifications bell"; dur=@(5,15); weight=3 }
164
+ @{ id=92; cat="perpetua"; name="Refresh current page"; dur=@(3,8); weight=3 }
165
+ @{ id=93; cat="perpetua"; name="Click breadcrumb back"; dur=@(3,8); weight=3 }
166
+ @{ id=94; cat="perpetua"; name="Scroll page randomly"; dur=@(5,20); weight=5 }
167
+ @{ id=95; cat="perpetua"; name="Mouse idle on metrics"; dur=@(8,25); weight=4 }
168
+
169
+ # === CHROME - AMAZON ADS (12 tasks) ===
170
+ @{ id=96; cat="chrome"; name="Load campaign mgr"; dur=@(15,45); weight=3 }
171
+ @{ id=97; cat="chrome"; name="Click campaign row"; dur=@(5,15); weight=3 }
172
+ @{ id=98; cat="chrome"; name="View ad group"; dur=@(10,30); weight=3 }
173
+ @{ id=99; cat="chrome"; name="Check keyword tab"; dur=@(10,30); weight=3 }
174
+ @{ id=100; cat="chrome"; name="Review search terms"; dur=@(20,60); weight=3 }
175
+ @{ id=101; cat="chrome"; name="Scroll campaign list"; dur=@(5,20); weight=3 }
176
+ @{ id=102; cat="chrome"; name="Filter by state"; dur=@(5,15); weight=2 }
177
+ @{ id=103; cat="chrome"; name="Download report"; dur=@(10,30); weight=2 }
178
+ @{ id=104; cat="chrome"; name="Set date picker"; dur=@(10,30); weight=3 }
179
+ @{ id=105; cat="chrome"; name="Check budget status"; dur=@(8,25); weight=3 }
180
+ @{ id=106; cat="chrome"; name="Export to Excel"; dur=@(8,25); weight=2 }
181
+ @{ id=107; cat="chrome"; name="Switch marketplace"; dur=@(8,25); weight=2 }
182
+
183
+ # === CHROME - RESEARCH (8 tasks) ===
184
+ @{ id=108; cat="chrome"; name="Google search query"; dur=@(15,45); weight=3 }
185
+ @{ id=109; cat="chrome"; name="Read search result"; dur=@(30,90); weight=3 }
186
+ @{ id=110; cat="chrome"; name="Open new tab"; dur=@(3,8); weight=4 }
187
+ @{ id=111; cat="chrome"; name="Close tab"; dur=@(2,5); weight=3 }
188
+ @{ id=112; cat="chrome"; name="Switch tab"; dur=@(2,5); weight=4 }
189
+ @{ id=113; cat="chrome"; name="Scroll article"; dur=@(10,40); weight=3 }
190
+ @{ id=114; cat="chrome"; name="Click back button"; dur=@(2,5); weight=3 }
191
+ @{ id=115; cat="chrome"; name="Type in address bar"; dur=@(10,30); weight=3 }
192
+
193
+ # === TEAMS (10 tasks) ===
194
+ @{ id=116; cat="teams"; name="Click chat thread"; dur=@(5,15); weight=4 }
195
+ @{ id=117; cat="teams"; name="Read message"; dur=@(10,40); weight=4 }
196
+ @{ id=118; cat="teams"; name="Scroll chat history"; dur=@(5,20); weight=3 }
197
+ @{ id=119; cat="teams"; name="Check activity feed"; dur=@(8,25); weight=3 }
198
+ @{ id=120; cat="teams"; name="Click channel"; dur=@(5,15); weight=2 }
199
+ @{ id=121; cat="teams"; name="View files tab"; dur=@(8,25); weight=2 }
200
+ @{ id=122; cat="teams"; name="Search messages"; dur=@(10,30); weight=2 }
201
+ @{ id=123; cat="teams"; name="Check mentions"; dur=@(5,15); weight=3 }
202
+ @{ id=124; cat="teams"; name="Scroll channel list"; dur=@(5,15); weight=2 }
203
+ @{ id=125; cat="teams"; name="React to message"; dur=@(3,8); weight=2 }
204
+
205
+ # === HUMAN BEHAVIORS (5 tasks) ===
206
+ @{ id=126; cat="human"; name="Pause and think"; dur=@(5,20); weight=5 }
207
+ @{ id=127; cat="human"; name="Small fidget"; dur=@(2,8); weight=6 }
208
+ @{ id=128; cat="human"; name="Hesitation pause"; dur=@(3,12); weight=4 }
209
+ @{ id=129; cat="human"; name="Re-read and check"; dur=@(8,25); weight=3 }
210
+ @{ id=130; cat="human"; name="Micro-break stretch"; dur=@(15,45); weight=2 }
211
+ )
212
+
213
+ # Category weights (time-of-day adjusted)
214
+ function Get-CategoryWeights {
215
+ $hour = (Get-Date).Hour
216
+ if ($hour -ge 9 -and $hour -lt 12) {
217
+ # Morning: more reporting/review - heavy Perpetua + bulk file review
218
+ return @{ excel=25; bulk=15; perpetua=30; chrome=15; teams=10; human=5 }
219
+ } elseif ($hour -ge 12 -and $hour -lt 14) {
220
+ # Lunch: lighter activity
221
+ return @{ excel=20; bulk=10; perpetua=25; chrome=20; teams=15; human=10 }
222
+ } elseif ($hour -ge 14 -and $hour -lt 17) {
223
+ # Afternoon: optimization work - heavy Excel + bulk operations
224
+ return @{ excel=30; bulk=20; perpetua=25; chrome=10; teams=10; human=5 }
225
+ } else {
226
+ # Default
227
+ return @{ excel=30; bulk=15; perpetua=25; chrome=15; teams=10; human=5 }
228
+ }
229
+ }
230
+
231
+ # ============== DATA POOLS ==============
232
+
233
+ $script:skuPool = @(
234
+ "NT10234", "NT10567", "NT10891", "JN20345", "JN20678", "JN20912",
235
+ "PR30456", "PR30789", "PR31023", "MG40567", "MG40890", "MG41234",
236
+ "VT50678", "VT50901", "VT51345", "NT11456", "JN21567", "PR31678",
237
+ "MG41789", "VT51890", "NT12567", "JN22678", "PR32789", "MG42890"
238
+ )
239
+
240
+ $script:campaignNames = @(
241
+ "SP_AUTO_TopSellers_Q1", "SP_BRANDED_EXACT_MainKW", "SP_MANUAL_BROAD_Discovery",
242
+ "SP_COMPETITOR_KW_Conquest", "SB_VIDEO_BrandAwareness", "SD_RETARGET_ViewedASIN",
243
+ "SP_AUTO_NewLaunches_Feb", "SP_BRANDED_PHRASE_Secondary", "SP_MANUAL_EXACT_HighIntent",
244
+ "SP_CATEGORY_Targeting_Test", "SB_HEADLINE_Promo_Spring", "SD_AUDIENCE_InMarket",
245
+ "SP_AUTO_LongTail_Explore", "SP_BRANDED_BROAD_Catchall", "SP_MANUAL_NEG_Cleanup"
246
+ )
247
+
248
+ $script:searchQueries = @(
249
+ "amazon ppc acos optimization strategies 2026",
250
+ "perpetua streams bid automation settings guide",
251
+ "sponsored products negative keyword strategy",
252
+ "amazon bulk operations csv format template",
253
+ "branded vs non-branded campaign structure",
254
+ "amazon advertising api rate limits documentation",
255
+ "perpetua goal card custom targeting setup",
256
+ "amazon mcg vs custom goal performance",
257
+ "sponsored brands video creative specs",
258
+ "amazon advertising quarterly report template",
259
+ "acos vs tacos amazon advertising metrics",
260
+ "perpetua dayparting schedule optimization",
261
+ "amazon search term isolation strategy",
262
+ "sponsored display audience targeting guide",
263
+ "amazon ppc budget allocation best practices"
264
+ )
265
+
266
+ $script:websites = @(
267
+ "https://app.perpetua.io/goals",
268
+ "https://app.perpetua.io/streams",
269
+ "https://advertising.amazon.com/cm/campaigns",
270
+ "https://advertising.amazon.com/reports",
271
+ "https://sellercentral.amazon.com/business-reports",
272
+ "https://www.perpetua.io/blog",
273
+ "https://advertising.amazon.com/resources"
274
+ )
275
+
276
+ $script:perpetuaPages = @(
277
+ @{ url="https://app.perpetua.io/am/sp/goals"; name="SP Goals" }
278
+ @{ url="https://app.perpetua.io/am/sp/streams"; name="SP Streams" }
279
+ @{ url="https://app.perpetua.io/am/sb/goals"; name="SB Goals" }
280
+ @{ url="https://app.perpetua.io/am/sd/goals"; name="SD Goals" }
281
+ @{ url="https://app.perpetua.io/am/analytics"; name="Analytics" }
282
+ @{ url="https://app.perpetua.io/am/insights"; name="Insights" }
283
+ @{ url="https://app.perpetua.io/am/reports"; name="Reports" }
284
+ @{ url="https://app.perpetua.io/am/settings"; name="Settings" }
285
+ )
286
+
287
+ $script:perpetuaUI = @{
288
+ sidebar = @{ x=@(30,180); y=@(100,600) }
289
+ sidebarSP = @{ x=100; y=180 }
290
+ sidebarSB = @{ x=100; y=230 }
291
+ sidebarSD = @{ x=100; y=280 }
292
+ sidebarAnalytics = @{ x=100; y=350 }
293
+ header = @{ x=@(200,1800); y=@(20,70) }
294
+ searchBox = @{ x=600; y=45 }
295
+ dateRangePicker = @{ x=1400; y=45 }
296
+ accountDropdown = @{ x=1800; y=45 }
297
+ goalsList = @{ x=@(220,1600); y=@(150,700) }
298
+ goalsTable = @{ x=@(250,1500); y=@(200,650) }
299
+ goalRow = @{ x=@(300,1400); y=@(220,600) }
300
+ goalCard = @{ x=@(300,1200); y=@(150,600) }
301
+ goalMetrics = @{ x=@(800,1100); y=@(200,400) }
302
+ goalTabs = @{ x=@(300,700); y=@(140,170) }
303
+ streamsList = @{ x=@(220,1600); y=@(150,700) }
304
+ streamRow = @{ x=@(250,1500); y=@(180,650) }
305
+ streamFilters = @{ x=@(250,600); y=@(100,140) }
306
+ newGoalBtn = @{ x=1700; y=100 }
307
+ goalNameInput = @{ x=600; y=250 }
308
+ productSearch = @{ x=600; y=350 }
309
+ targetingOptions = @{ x=@(400,900); y=@(400,500) }
310
+ matchTypeCheckboxes = @{ x=@(400,700); y=@(450,520) }
311
+ acosInput = @{ x=700; y=300 }
312
+ budgetInput = @{ x=700; y=360 }
313
+ launchGoalBtn = @{ x=1750; y=50 }
314
+ }
315
+
316
+ # ============== BULK FILE MANAGEMENT ==============
317
+
318
+ function Initialize-BulkFile {
319
+ Write-Host "[BULK] Opening 1.2GB bulk file..." -ForegroundColor Cyan
320
+
321
+ try {
322
+ # Create Excel COM object
323
+ $script:excel = New-Object -ComObject Excel.Application
324
+ $script:excel.Visible = $true
325
+ $script:excel.DisplayAlerts = $false
326
+ $script:excel.ScreenUpdating = $true
327
+
328
+ # Open the bulk file
329
+ Write-Host "[BULK] Loading: $script:bulkFilePath" -ForegroundColor Yellow
330
+ $script:workbook = $script:excel.Workbooks.Open($script:bulkFilePath, $false, $false)
331
+
332
+ # Get first worksheet
333
+ $script:worksheet = $script:workbook.Worksheets.Item(1)
334
+
335
+ # Analyze file structure
336
+ Write-Host "[BULK] Analyzing file structure..." -ForegroundColor Yellow
337
+
338
+ # Get approximate row count (find last used row)
339
+ $lastRow = $script:worksheet.UsedRange.Rows.Count
340
+ $script:bulkFileInfo.totalRows = $lastRow
341
+
342
+ # Get worksheet names
343
+ foreach ($ws in $script:workbook.Worksheets) {
344
+ $script:bulkFileInfo.worksheets += $ws.Name
345
+ }
346
+
347
+ # Define useful row ranges for navigation
348
+ $script:bulkFileInfo.rowRanges = @(
349
+ @{ start=1000; end=2000 }
350
+ @{ start=5000; end=6000 }
351
+ @{ start=10000; end=11000 }
352
+ @{ start=25000; end=26000 }
353
+ @{ start=50000; end=51000 }
354
+ @{ start=75000; end=76000 }
355
+ @{ start=100000; end=101000 }
356
+ )
357
+
358
+ $script:bulkFileLoaded = $true
359
+
360
+ Write-Host "[BULK] File loaded successfully!" -ForegroundColor Green
361
+ Write-Host "[BULK] Total rows: $lastRow" -ForegroundColor Green
362
+ Write-Host "[BULK] Worksheets: $($script:bulkFileInfo.worksheets -join ', ')" -ForegroundColor Green
363
+
364
+ # Move to top of file
365
+ $script:worksheet.Cells.Item(1, 1).Select() | Out-Null
366
+
367
+ return $true
368
+ }
369
+ catch {
370
+ Write-Host "[ERROR] Failed to load bulk file: $_" -ForegroundColor Red
371
+ $script:bulkFileLoaded = $false
372
+ return $false
373
+ }
374
+ }
375
+
376
+ function Close-BulkFile {
377
+ if ($script:bulkFileLoaded -and $script:workbook) {
378
+ Write-Host "[BULK] Closing bulk file..." -ForegroundColor Yellow
379
+ try {
380
+ $script:workbook.Close($false) # Don't save changes
381
+ $script:excel.Quit()
382
+ [System.Runtime.Interopservices.Marshal]::ReleaseComObject($script:excel) | Out-Null
383
+ [System.GC]::Collect()
384
+ [System.GC]::WaitForPendingFinalizers()
385
+ Write-Host "[BULK] File closed" -ForegroundColor Green
386
+ }
387
+ catch {
388
+ Write-Host "[ERROR] Failed to close bulk file: $_" -ForegroundColor Red
389
+ }
390
+ }
391
+ }
392
+
393
+ # ============== MOUSE FUNCTIONS ==============
394
+
395
+ function Move-MouseSmooth {
396
+ param([int]$targetX, [int]$targetY, [int]$steps = 0)
397
+ $currentPos = [System.Windows.Forms.Cursor]::Position
398
+ $startX = $currentPos.X; $startY = $currentPos.Y
399
+
400
+ if ($steps -eq 0) {
401
+ $distance = [Math]::Sqrt([Math]::Pow($targetX - $startX, 2) + [Math]::Pow($targetY - $startY, 2))
402
+ $steps = [Math]::Max(10, [Math]::Min(50, [int]($distance / 20)))
403
+ }
404
+
405
+ $wobbleAmount = Get-Random -Minimum 5 -Maximum 20
406
+ $wobbleDirection = if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) { 1 } else { -1 }
407
+
408
+ for ($i = 1; $i -le $steps; $i++) {
409
+ $progress = $i / $steps
410
+ $easedProgress = 1 - [Math]::Pow(1 - $progress, 2)
411
+ $wobble = 0
412
+ if ($progress -gt 0.2 -and $progress -lt 0.8) {
413
+ $wobble = [Math]::Sin($progress * [Math]::PI) * $wobbleAmount * $wobbleDirection
414
+ }
415
+ $newX = [int]($startX + ($targetX - $startX) * $easedProgress + $wobble)
416
+ $newY = [int]($startY + ($targetY - $startY) * $easedProgress)
417
+ [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($newX, $newY)
418
+ $delay = if ($progress -lt 0.2 -or $progress -gt 0.8) { Get-Random -Minimum 8 -Maximum 20 } else { Get-Random -Minimum 3 -Maximum 10 }
419
+ Start-Sleep -Milliseconds $delay
420
+ }
421
+ [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($targetX, $targetY)
422
+ }
423
+
424
+ function Click-Mouse {
425
+ Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 150)
426
+ [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [IntPtr]::Zero)
427
+ Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 120)
428
+ [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTUP, 0, 0, 0, [IntPtr]::Zero)
429
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
430
+ }
431
+
432
+ function Move-AndClick { param([int]$x, [int]$y); Move-MouseSmooth $x $y; Click-Mouse }
433
+
434
+ function Scroll-MouseWheel {
435
+ param([int]$amount = -3)
436
+ $scrolls = [Math]::Abs($amount)
437
+ $direction = if ($amount -lt 0) { -120 } else { 120 }
438
+ for ($i = 0; $i -lt $scrolls; $i++) {
439
+ [Mouse]::mouse_event([Mouse]::MOUSEEVENTF_WHEEL, 0, 0, $direction, [IntPtr]::Zero)
440
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
441
+ }
442
+ }
443
+
444
+ function Fidget-Mouse {
445
+ $currentPos = [System.Windows.Forms.Cursor]::Position
446
+ $fidgetX = [Math]::Max(10, [Math]::Min($script:screenWidth - 10, $currentPos.X + (Get-Random -Minimum -30 -Maximum 30)))
447
+ $fidgetY = [Math]::Max(10, [Math]::Min($script:screenHeight - 10, $currentPos.Y + (Get-Random -Minimum -20 -Maximum 20)))
448
+ Move-MouseSmooth $fidgetX $fidgetY 8
449
+ }
450
+
451
+ function Get-RandomScreenPosition {
452
+ param([string]$area = "center")
453
+ switch ($area) {
454
+ "excel-cells" { $x = Get-Random -Minimum 100 -Maximum 900; $y = Get-Random -Minimum 150 -Maximum 600 }
455
+ "toolbar" { $x = Get-Random -Minimum 50 -Maximum 800; $y = Get-Random -Minimum 30 -Maximum 120 }
456
+ "address-bar" { $x = Get-Random -Minimum 200 -Maximum 700; $y = Get-Random -Minimum 50 -Maximum 80 }
457
+ "webpage" { $x = Get-Random -Minimum 100 -Maximum 1000; $y = Get-Random -Minimum 200 -Maximum 700 }
458
+ "chat-list" { $x = Get-Random -Minimum 50 -Maximum 280; $y = Get-Random -Minimum 150 -Maximum 600 }
459
+ "chat-area" { $x = Get-Random -Minimum 350 -Maximum 900; $y = Get-Random -Minimum 200 -Maximum 650 }
460
+ "sidebar" { $x = Get-Random -Minimum 20 -Maximum 200; $y = Get-Random -Minimum 100 -Maximum 500 }
461
+ default { $x = Get-Random -Minimum 200 -Maximum 1000; $y = Get-Random -Minimum 200 -Maximum 600 }
462
+ }
463
+ return @{ X = $x; Y = $y }
464
+ }
465
+
466
+ # ============== TYPING FUNCTIONS ==============
467
+
468
+ function Type-WithTypos {
469
+ param([string]$text, [int]$typoChance = 8)
470
+ foreach ($char in $text.ToCharArray()) {
471
+ if ((Get-Random -Minimum 1 -Maximum 100) -le $typoChance) {
472
+ $wrongChar = [char]((Get-Random -Minimum 97 -Maximum 122))
473
+ [System.Windows.Forms.SendKeys]::SendWait($wrongChar)
474
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
475
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
476
+ [System.Windows.Forms.SendKeys]::SendWait("{BACKSPACE}")
477
+ Start-Sleep -Milliseconds (Get-Random -Minimum 80 -Maximum 200)
478
+ }
479
+ $escaped = $char
480
+ if ($char -match '[\+\^\%\~\(\)\{\}\[\]]') { $escaped = "{$char}" }
481
+ [System.Windows.Forms.SendKeys]::SendWait($escaped)
482
+ $delay = Get-Random -Minimum 50 -Maximum 200
483
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 5) { $delay = Get-Random -Minimum 300 -Maximum 800 }
484
+ Start-Sleep -Milliseconds $delay
485
+ }
486
+ }
487
+
488
+ function Type-Number {
489
+ param([string]$num)
490
+ Type-WithTypos $num 5
491
+ }
492
+
493
+ # ============== TASK SELECTOR (Anti-Pattern) ==============
494
+
495
+ function Select-NextTask {
496
+ $catWeights = Get-CategoryWeights
497
+
498
+ # Build weighted pool excluding recent tasks
499
+ $pool = @()
500
+ foreach ($task in $script:microTasks) {
501
+ # Skip if in last 20 tasks
502
+ if ($script:taskHistory -contains $task.id) { continue }
503
+
504
+ # Skip bulk tasks if file not loaded
505
+ if ($task.cat -eq "bulk" -and -not $script:bulkFileLoaded) { continue }
506
+
507
+ # Weight by category and task weight
508
+ $catWeight = $catWeights[$task.cat]
509
+ if (-not $catWeight) { $catWeight = 5 }
510
+ $totalWeight = $task.weight * ($catWeight / 10)
511
+
512
+ for ($i = 0; $i -lt [Math]::Ceiling($totalWeight); $i++) {
513
+ $pool += $task
514
+ }
515
+ }
516
+
517
+ if ($pool.Count -eq 0) {
518
+ # Reset history if pool empty
519
+ $script:taskHistory = @()
520
+ $pool = $script:microTasks | Where-Object { $_.cat -ne "bulk" -or $script:bulkFileLoaded }
521
+ }
522
+
523
+ $selected = $pool | Get-Random
524
+
525
+ # Update history (keep last 20)
526
+ $script:taskHistory += $selected.id
527
+ if ($script:taskHistory.Count -gt 20) {
528
+ $script:taskHistory = $script:taskHistory[-20..-1]
529
+ }
530
+
531
+ return $selected
532
+ }
533
+
534
+ # ============== TASK EXECUTORS ==============
535
+
536
+ function Execute-BulkTask {
537
+ param($task)
538
+
539
+ if (-not $script:bulkFileLoaded) { return }
540
+
541
+ try {
542
+ switch -Wildcard ($task.name) {
543
+ "*Jump to row 50000*" {
544
+ $row = 50000
545
+ Write-Host " [BULK] Jumping to row $row..." -ForegroundColor DarkCyan
546
+ $script:worksheet.Cells.Item($row, 1).Select() | Out-Null
547
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
548
+ }
549
+ "*Jump to row 100000*" {
550
+ $row = 100000
551
+ Write-Host " [BULK] Jumping to row $row..." -ForegroundColor DarkCyan
552
+ $script:worksheet.Cells.Item($row, 1).Select() | Out-Null
553
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
554
+ }
555
+ "*Scroll through bulk*" {
556
+ Write-Host " [BULK] Scrolling through data..." -ForegroundColor DarkCyan
557
+ $range = $script:bulkFileInfo.rowRanges | Get-Random
558
+ $startRow = $range.start
559
+ $script:worksheet.Cells.Item($startRow, 1).Select() | Out-Null
560
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
561
+
562
+ # Scroll down through range
563
+ for ($i = 0; $i -lt 5; $i++) {
564
+ [System.Windows.Forms.SendKeys]::SendWait("{PGDN}")
565
+ Start-Sleep -Milliseconds (Get-Random -Minimum 800 -Maximum 2000)
566
+ }
567
+ }
568
+ "*Filter ACOS*" {
569
+ Write-Host " [BULK] Filtering ACOS > 20%..." -ForegroundColor DarkCyan
570
+ # Click AutoFilter button (Data ribbon location)
571
+ [System.Windows.Forms.SendKeys]::SendWait("%A") # Alt+A for Data ribbon
572
+ Start-Sleep -Milliseconds 500
573
+ [System.Windows.Forms.SendKeys]::SendWait("T") # Filter toggle
574
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
575
+ }
576
+ "*Filter by campaign*" {
577
+ Write-Host " [BULK] Filtering campaigns..." -ForegroundColor DarkCyan
578
+ [System.Windows.Forms.SendKeys]::SendWait("^f")
579
+ Start-Sleep -Milliseconds 500
580
+ Type-WithTypos ($script:campaignNames | Get-Random).Split("_")[0]
581
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
582
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
583
+ }
584
+ "*Sort by Spend*" {
585
+ Write-Host " [BULK] Sorting by Spend..." -ForegroundColor DarkCyan
586
+ $script:worksheet.Cells.Item(1, 1).Select() | Out-Null
587
+ [System.Windows.Forms.SendKeys]::SendWait("%A")
588
+ Start-Sleep -Milliseconds 300
589
+ [System.Windows.Forms.SendKeys]::SendWait("SS") # Sort
590
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
591
+ }
592
+ "*Sort by ACOS*" {
593
+ Write-Host " [BULK] Sorting by ACOS..." -ForegroundColor DarkCyan
594
+ $script:worksheet.Cells.Item(1, 1).Select() | Out-Null
595
+ [System.Windows.Forms.SendKeys]::SendWait("%A")
596
+ Start-Sleep -Milliseconds 300
597
+ [System.Windows.Forms.SendKeys]::SendWait("SS")
598
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
599
+ }
600
+ "*Clear all filters*" {
601
+ Write-Host " [BULK] Clearing filters..." -ForegroundColor DarkCyan
602
+ [System.Windows.Forms.SendKeys]::SendWait("%AC") # Alt+A, C = Clear
603
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
604
+ }
605
+ "*Navigate to Sheet 2*" {
606
+ if ($script:bulkFileInfo.worksheets.Count -gt 1) {
607
+ Write-Host " [BULK] Switching worksheet..." -ForegroundColor DarkCyan
608
+ $script:worksheet = $script:workbook.Worksheets.Item(2)
609
+ $script:worksheet.Activate()
610
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
611
+ }
612
+ }
613
+ "*Search specific SKU*" {
614
+ Write-Host " [BULK] Searching for SKU..." -ForegroundColor DarkCyan
615
+ [System.Windows.Forms.SendKeys]::SendWait("^f")
616
+ Start-Sleep -Milliseconds 500
617
+ Type-WithTypos ($script:skuPool | Get-Random)
618
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
619
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
620
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
621
+ }
622
+ "*Review data range*" {
623
+ Write-Host " [BULK] Reviewing data range..." -ForegroundColor DarkCyan
624
+ $range = $script:bulkFileInfo.rowRanges | Get-Random
625
+ $script:worksheet.Cells.Item($range.start, 1).Select() | Out-Null
626
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
627
+
628
+ # Scroll and review
629
+ for ($i = 0; $i -lt 3; $i++) {
630
+ Scroll-MouseWheel -3
631
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
632
+ }
633
+ }
634
+ "*Select large range*" {
635
+ Write-Host " [BULK] Selecting range..." -ForegroundColor DarkCyan
636
+ $range = $script:bulkFileInfo.rowRanges | Get-Random
637
+ $startRow = $range.start
638
+ $endRow = $range.end
639
+ $script:worksheet.Range("A$startRow", "Z$endRow").Select() | Out-Null
640
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
641
+ }
642
+ "*Copy bulk data*" {
643
+ Write-Host " [BULK] Copying range..." -ForegroundColor DarkCyan
644
+ $range = $script:bulkFileInfo.rowRanges | Get-Random
645
+ $startRow = $range.start
646
+ $endRow = [Math]::Min($startRow + 100, $range.end)
647
+ $script:worksheet.Range("A$startRow", "E$endRow").Select() | Out-Null
648
+ Start-Sleep -Milliseconds 500
649
+ [System.Windows.Forms.SendKeys]::SendWait("^c")
650
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
651
+ }
652
+ "*end of data*" {
653
+ Write-Host " [BULK] Jumping to end..." -ForegroundColor DarkCyan
654
+ [System.Windows.Forms.SendKeys]::SendWait("^{END}")
655
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
656
+ }
657
+ "*Return to top*" {
658
+ Write-Host " [BULK] Returning to top..." -ForegroundColor DarkCyan
659
+ [System.Windows.Forms.SendKeys]::SendWait("^{HOME}")
660
+ Start-Sleep -Milliseconds (Get-Random -Minimum 800 -Maximum 1500)
661
+ }
662
+ }
663
+ }
664
+ catch {
665
+ Write-Host " [ERROR] Bulk task failed: $_" -ForegroundColor Red
666
+ }
667
+ }
668
+
669
+ function Execute-ExcelTask {
670
+ param($task)
671
+
672
+ $pos = Get-RandomScreenPosition "excel-cells"
673
+
674
+ switch -Wildcard ($task.name) {
675
+ "*SKU*" {
676
+ Move-AndClick $pos.X $pos.Y
677
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
678
+ Type-WithTypos ($script:skuPool | Get-Random)
679
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
680
+ }
681
+ "*campaign name*" {
682
+ Move-AndClick $pos.X $pos.Y
683
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
684
+ Type-WithTypos ($script:campaignNames | Get-Random)
685
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
686
+ }
687
+ "*ACOS*" {
688
+ Move-AndClick $pos.X $pos.Y
689
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
690
+ $acos = [math]::Round((Get-Random -Minimum 800 -Maximum 6500) / 100, 2)
691
+ Type-Number "$acos%"
692
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
693
+ }
694
+ "*spend*" {
695
+ Move-AndClick $pos.X $pos.Y
696
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
697
+ $spend = [math]::Round((Get-Random -Minimum 500 -Maximum 50000) / 100, 2)
698
+ Type-Number "`$$spend"
699
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
700
+ }
701
+ "*bid*" {
702
+ Move-AndClick $pos.X $pos.Y
703
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
704
+ $bid = [math]::Round((Get-Random -Minimum 15 -Maximum 350) / 100, 2)
705
+ Type-Number "`$$bid"
706
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
707
+ }
708
+ "*formula*" {
709
+ Move-AndClick $pos.X $pos.Y
710
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
711
+ $formulas = @("=SUM(B2:B50)", "=AVERAGE(C2:C100)", "=B2/C2", "=D2*0.15", "=IF(E2>30,""HIGH"",""OK"")")
712
+ Type-WithTypos ($formulas | Get-Random)
713
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
714
+ }
715
+ "*Scroll*" {
716
+ Move-MouseSmooth $pos.X $pos.Y
717
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
718
+ $dir = if ($task.name -match "up") { 3 } else { -3 }
719
+ Scroll-MouseWheel $dir
720
+ }
721
+ "*Click*cell*" {
722
+ Move-AndClick $pos.X $pos.Y
723
+ }
724
+ "*Tab*" {
725
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
726
+ }
727
+ "*Enter*" {
728
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
729
+ }
730
+ "*Save*" {
731
+ Fidget-Mouse
732
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 400)
733
+ [System.Windows.Forms.SendKeys]::SendWait("^s")
734
+ }
735
+ "*Find*" {
736
+ [System.Windows.Forms.SendKeys]::SendWait("^f")
737
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
738
+ Type-WithTypos ($script:skuPool | Get-Random).Substring(0,4)
739
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
740
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
741
+ }
742
+ "*Copy*" {
743
+ Move-AndClick $pos.X $pos.Y
744
+ [System.Windows.Forms.SendKeys]::SendWait("^c")
745
+ }
746
+ "*Paste*" {
747
+ Move-AndClick $pos.X $pos.Y
748
+ [System.Windows.Forms.SendKeys]::SendWait("^v")
749
+ }
750
+ "*Undo*" {
751
+ [System.Windows.Forms.SendKeys]::SendWait("^z")
752
+ }
753
+ "*worksheet*" {
754
+ $tabX = Get-Random -Minimum 100 -Maximum 400
755
+ Move-AndClick $tabX ($script:screenHeight - 60)
756
+ }
757
+ default {
758
+ Move-AndClick $pos.X $pos.Y
759
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
760
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 50) {
761
+ $num = Get-Random -Minimum 100 -Maximum 9999
762
+ Type-Number $num.ToString()
763
+ [System.Windows.Forms.SendKeys]::SendWait("{TAB}")
764
+ }
765
+ }
766
+ }
767
+ }
768
+
769
+ function Execute-ChromeTask {
770
+ param($task)
771
+
772
+ switch -Wildcard ($task.name) {
773
+ "*search*" {
774
+ $pos = Get-RandomScreenPosition "address-bar"
775
+ Move-AndClick $pos.X $pos.Y
776
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
777
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
778
+ Type-WithTypos ($script:searchQueries | Get-Random)
779
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
780
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
781
+ }
782
+ "*Load*" {
783
+ $pos = Get-RandomScreenPosition "address-bar"
784
+ Move-AndClick $pos.X $pos.Y
785
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
786
+ Start-Sleep -Milliseconds (Get-Random -Minimum 100 -Maximum 300)
787
+ Type-WithTypos ($script:websites | Get-Random)
788
+ [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
789
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
790
+ }
791
+ "*Scroll*" {
792
+ $pos = Get-RandomScreenPosition "webpage"
793
+ Move-MouseSmooth $pos.X $pos.Y
794
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
795
+ $scrollAmt = Get-Random -Minimum -5 -Maximum -2
796
+ Scroll-MouseWheel $scrollAmt
797
+ }
798
+ "*Click*" {
799
+ $pos = Get-RandomScreenPosition "webpage"
800
+ Move-AndClick $pos.X $pos.Y
801
+ }
802
+ "*new tab*" {
803
+ [System.Windows.Forms.SendKeys]::SendWait("^t")
804
+ }
805
+ "*Close tab*" {
806
+ [System.Windows.Forms.SendKeys]::SendWait("^w")
807
+ }
808
+ "*Switch tab*" {
809
+ [System.Windows.Forms.SendKeys]::SendWait("^{TAB}")
810
+ }
811
+ "*back*" {
812
+ if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) {
813
+ Move-AndClick 45 65
814
+ } else {
815
+ [System.Windows.Forms.SendKeys]::SendWait("%{LEFT}")
816
+ }
817
+ }
818
+ "*Refresh*" {
819
+ [System.Windows.Forms.SendKeys]::SendWait("{F5}")
820
+ }
821
+ default {
822
+ $pos = Get-RandomScreenPosition "webpage"
823
+ Move-AndClick $pos.X $pos.Y
824
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
825
+ }
826
+ }
827
+ }
828
+
829
+ function Execute-PerpetuaTask {
830
+ param($task)
831
+
832
+ $ui = $script:perpetuaUI
833
+
834
+ switch -Wildcard ($task.name) {
835
+ "*Navigate SP Goals*" {
836
+ Move-AndClick $ui.sidebarSP.x $ui.sidebarSP.y
837
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
838
+ }
839
+ "*Navigate SB Goals*" {
840
+ Move-AndClick $ui.sidebarSB.x $ui.sidebarSB.y
841
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
842
+ }
843
+ "*Navigate SD Goals*" {
844
+ Move-AndClick $ui.sidebarSD.x $ui.sidebarSD.y
845
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
846
+ }
847
+ "*Click goal row*" {
848
+ $x = Get-Random -Minimum $ui.goalRow.x[0] -Maximum $ui.goalRow.x[1]
849
+ $y = Get-Random -Minimum $ui.goalRow.y[0] -Maximum $ui.goalRow.y[1]
850
+ Move-AndClick $x $y
851
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
852
+ }
853
+ "*Review goal*metric*" {
854
+ $x = Get-Random -Minimum $ui.goalMetrics.x[0] -Maximum $ui.goalMetrics.x[1]
855
+ $y = Get-Random -Minimum $ui.goalMetrics.y[0] -Maximum $ui.goalMetrics.y[1]
856
+ Move-MouseSmooth $x $y
857
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
858
+ Fidget-Mouse
859
+ }
860
+ "*Scroll goals list*" {
861
+ $x = Get-Random -Minimum $ui.goalsList.x[0] -Maximum $ui.goalsList.x[1]
862
+ $y = Get-Random -Minimum $ui.goalsList.y[0] -Maximum $ui.goalsList.y[1]
863
+ Move-MouseSmooth $x $y
864
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
865
+ $dir = if ($task.name -match "up") { 3 } else { -3 }
866
+ Scroll-MouseWheel $dir
867
+ }
868
+ "*Click goal tabs*" {
869
+ $x = Get-Random -Minimum $ui.goalTabs.x[0] -Maximum $ui.goalTabs.x[1]
870
+ $y = Get-Random -Minimum $ui.goalTabs.y[0] -Maximum $ui.goalTabs.y[1]
871
+ Move-AndClick $x $y
872
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
873
+ }
874
+ "*Search goal*" {
875
+ Move-AndClick $ui.searchBox.x $ui.searchBox.y
876
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
877
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
878
+ Start-Sleep -Milliseconds 200
879
+ $goalName = $script:campaignNames | Get-Random
880
+ $searchTerm = $goalName.Split("_")[0..1] -join "_"
881
+ Type-WithTypos $searchTerm
882
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
883
+ }
884
+ "*Filter goals*" {
885
+ $x = Get-Random -Minimum 300 -Maximum 500
886
+ Move-AndClick $x 120
887
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
888
+ $y = if ($task.name -match "Enabled") { 160 } else { 190 }
889
+ Move-AndClick ($x + 20) $y
890
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
891
+ }
892
+ "*Sort by*column*" {
893
+ $x = if ($task.name -match "ACOS") { 900 } else { 800 }
894
+ Move-AndClick $x 175
895
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
896
+ }
897
+ "*Change date range*" {
898
+ Move-AndClick $ui.dateRangePicker.x $ui.dateRangePicker.y
899
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
900
+ $y = if ($task.name -match "7d") { 200 } else { 230 }
901
+ Move-AndClick ($ui.dateRangePicker.x - 50) $y
902
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
903
+ }
904
+ "*New Goal button*" {
905
+ Move-AndClick $ui.newGoalBtn.x $ui.newGoalBtn.y
906
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
907
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
908
+ Start-Sleep -Milliseconds 500
909
+ }
910
+ "*Close goal detail*" {
911
+ [System.Windows.Forms.SendKeys]::SendWait("{ESCAPE}")
912
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
913
+ }
914
+ "*Navigate SP Streams*" {
915
+ $x = Get-Random -Minimum $ui.sidebar.x[0] -Maximum $ui.sidebar.x[1]
916
+ Move-AndClick $x 320
917
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
918
+ }
919
+ "*Click stream row*" {
920
+ $x = Get-Random -Minimum $ui.streamRow.x[0] -Maximum $ui.streamRow.x[1]
921
+ $y = Get-Random -Minimum $ui.streamRow.y[0] -Maximum $ui.streamRow.y[1]
922
+ Move-AndClick $x $y
923
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
924
+ }
925
+ "*Scroll streams list*" {
926
+ $x = Get-Random -Minimum $ui.streamsList.x[0] -Maximum $ui.streamsList.x[1]
927
+ $y = Get-Random -Minimum $ui.streamsList.y[0] -Maximum $ui.streamsList.y[1]
928
+ Move-MouseSmooth $x $y
929
+ Scroll-MouseWheel (Get-Random -Minimum -4 -Maximum -2)
930
+ }
931
+ "*View stream bid*" {
932
+ $x = Get-Random -Minimum 600 -Maximum 900
933
+ $y = Get-Random -Minimum 250 -Maximum 400
934
+ Move-MouseSmooth $x $y
935
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
936
+ }
937
+ "*Filter streams*" {
938
+ $x = Get-Random -Minimum $ui.streamFilters.x[0] -Maximum $ui.streamFilters.x[1]
939
+ $y = Get-Random -Minimum $ui.streamFilters.y[0] -Maximum $ui.streamFilters.y[1]
940
+ Move-AndClick $x $y
941
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
942
+ }
943
+ "*stream*trend*" {
944
+ $x = Get-Random -Minimum 700 -Maximum 1200
945
+ $y = Get-Random -Minimum 300 -Maximum 450
946
+ Move-MouseSmooth $x $y
947
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 4000)
948
+ Fidget-Mouse
949
+ }
950
+ "*Expand stream*" {
951
+ $x = Get-Random -Minimum 250 -Maximum 300
952
+ $y = Get-Random -Minimum 220 -Maximum 500
953
+ Move-AndClick $x $y
954
+ }
955
+ "*Collapse stream*" {
956
+ $x = Get-Random -Minimum 250 -Maximum 300
957
+ $y = Get-Random -Minimum 220 -Maximum 400
958
+ Move-AndClick $x $y
959
+ }
960
+ "*Sort streams*" {
961
+ $x = Get-Random -Minimum 700 -Maximum 900
962
+ Move-AndClick $x 175
963
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2000)
964
+ }
965
+ "*stream automation*" {
966
+ $x = Get-Random -Minimum 1100 -Maximum 1300
967
+ $y = Get-Random -Minimum 250 -Maximum 450
968
+ Move-MouseSmooth $x $y
969
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 3000)
970
+ }
971
+ "*Navigate Analytics*" {
972
+ Move-AndClick $ui.sidebarAnalytics.x $ui.sidebarAnalytics.y
973
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
974
+ }
975
+ "*sidebar nav*" {
976
+ $x = Get-Random -Minimum $ui.sidebar.x[0] -Maximum $ui.sidebar.x[1]
977
+ $y = Get-Random -Minimum $ui.sidebar.y[0] -Maximum $ui.sidebar.y[1]
978
+ Move-AndClick $x $y
979
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
980
+ }
981
+ "*Hover sidebar*" {
982
+ $x = Get-Random -Minimum 20 -Maximum 60
983
+ $y = Get-Random -Minimum 150 -Maximum 500
984
+ Move-MouseSmooth $x $y
985
+ Start-Sleep -Milliseconds (Get-Random -Minimum 800 -Maximum 2000)
986
+ }
987
+ "*account dropdown*" {
988
+ Move-AndClick $ui.accountDropdown.x $ui.accountDropdown.y
989
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
990
+ Move-AndClick 800 400
991
+ }
992
+ "*notifications bell*" {
993
+ Move-AndClick ($ui.accountDropdown.x - 80) $ui.accountDropdown.y
994
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 2500)
995
+ Move-AndClick 800 400
996
+ }
997
+ "*Refresh current*" {
998
+ [System.Windows.Forms.SendKeys]::SendWait("{F5}")
999
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 4000)
1000
+ }
1001
+ "*breadcrumb*" {
1002
+ $x = Get-Random -Minimum 220 -Maximum 400
1003
+ Move-AndClick $x 80
1004
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1500 -Maximum 3000)
1005
+ }
1006
+ "*Scroll page randomly*" {
1007
+ $x = Get-Random -Minimum 400 -Maximum 1200
1008
+ $y = Get-Random -Minimum 300 -Maximum 600
1009
+ Move-MouseSmooth $x $y
1010
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 800)
1011
+ $dir = if ((Get-Random -Minimum 0 -Maximum 2) -eq 0) { -3 } else { 3 }
1012
+ Scroll-MouseWheel $dir
1013
+ }
1014
+ "*idle on metrics*" {
1015
+ $x = Get-Random -Minimum 600 -Maximum 1100
1016
+ $y = Get-Random -Minimum 200 -Maximum 500
1017
+ Move-MouseSmooth $x $y
1018
+ Start-Sleep -Milliseconds (Get-Random -Minimum 3000 -Maximum 8000)
1019
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 40) { Fidget-Mouse }
1020
+ }
1021
+ default {
1022
+ $x = Get-Random -Minimum 300 -Maximum 1200
1023
+ $y = Get-Random -Minimum 200 -Maximum 600
1024
+ Move-MouseSmooth $x $y
1025
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
1026
+ }
1027
+ }
1028
+ }
1029
+
1030
+ function Execute-TeamsTask {
1031
+ param($task)
1032
+
1033
+ switch -Wildcard ($task.name) {
1034
+ "*chat*" {
1035
+ $pos = Get-RandomScreenPosition "chat-list"
1036
+ Move-AndClick $pos.X $pos.Y
1037
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
1038
+ $chatPos = Get-RandomScreenPosition "chat-area"
1039
+ Move-MouseSmooth $chatPos.X $chatPos.Y
1040
+ }
1041
+ "*Read*" {
1042
+ $pos = Get-RandomScreenPosition "chat-area"
1043
+ Move-MouseSmooth $pos.X $pos.Y
1044
+ Start-Sleep -Milliseconds (Get-Random -Minimum 2000 -Maximum 5000)
1045
+ }
1046
+ "*Scroll*" {
1047
+ $pos = if ($task.name -match "channel") { Get-RandomScreenPosition "sidebar" } else { Get-RandomScreenPosition "chat-area" }
1048
+ Move-MouseSmooth $pos.X $pos.Y
1049
+ Scroll-MouseWheel (Get-Random -Minimum -3 -Maximum 3)
1050
+ }
1051
+ "*activity*" {
1052
+ $pos = Get-RandomScreenPosition "sidebar"
1053
+ Move-AndClick $pos.X 100
1054
+ }
1055
+ "*React*" {
1056
+ $pos = Get-RandomScreenPosition "chat-area"
1057
+ Move-MouseSmooth $pos.X $pos.Y
1058
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1000)
1059
+ }
1060
+ default {
1061
+ $pos = Get-RandomScreenPosition "chat-list"
1062
+ Move-AndClick $pos.X $pos.Y
1063
+ }
1064
+ }
1065
+ }
1066
+
1067
+ function Execute-HumanTask {
1068
+ param($task)
1069
+
1070
+ switch -Wildcard ($task.name) {
1071
+ "*Pause*think*" {
1072
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 30) { Fidget-Mouse }
1073
+ }
1074
+ "*fidget*" {
1075
+ Fidget-Mouse
1076
+ }
1077
+ "*Hesitation*" {
1078
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 2000)
1079
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 40) { Fidget-Mouse }
1080
+ }
1081
+ "*Re-read*" {
1082
+ $pos = Get-RandomScreenPosition "center"
1083
+ Move-MouseSmooth $pos.X $pos.Y
1084
+ Start-Sleep -Milliseconds (Get-Random -Minimum 1000 -Maximum 3000)
1085
+ }
1086
+ "*break*" {
1087
+ $breakTime = Get-Random -Minimum 15 -Maximum 45
1088
+ for ($i = 0; $i -lt $breakTime; $i += 5) {
1089
+ Start-Sleep -Seconds 5
1090
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) { Fidget-Mouse }
1091
+ }
1092
+ }
1093
+ }
1094
+ }
1095
+
1096
+ # ============== APP SWITCHING ==============
1097
+
1098
+ function Switch-ToApp {
1099
+ param([string]$targetApp)
1100
+
1101
+ if ($targetApp -eq $script:lastApp) { return }
1102
+
1103
+ # Handle bulk tasks (stay in Excel)
1104
+ if ($targetApp -eq "bulk") { $targetApp = "excel" }
1105
+
1106
+ $taskbarY = $script:screenHeight - 30
1107
+ $taskbarX = Get-Random -Minimum 200 -Maximum 800
1108
+ Move-MouseSmooth $taskbarX $taskbarY
1109
+ Start-Sleep -Milliseconds (Get-Random -Minimum 200 -Maximum 500)
1110
+
1111
+ $tabCount = Get-Random -Minimum 1 -Maximum 3
1112
+ for ($i = 0; $i -lt $tabCount; $i++) {
1113
+ [System.Windows.Forms.SendKeys]::SendWait("%{TAB}")
1114
+ Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
1115
+ }
1116
+
1117
+ Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 1500)
1118
+ $script:lastApp = $targetApp
1119
+
1120
+ $pos = Get-RandomScreenPosition "center"
1121
+ Move-MouseSmooth $pos.X $pos.Y
1122
+ }
1123
+
1124
+ # ============== MAIN TRACKER ==============
1125
+
1126
+ function Start-Tracking {
1127
+ $totalActions = 0
1128
+ $script:sessionStart = Get-Date
1129
+
1130
+ Write-Host "[TRACKING] Started at $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor Green
1131
+ Write-Host "[INFO] v4.0 BULK - 145 micro-tasks, Real 1.2GB file ops" -ForegroundColor Cyan
1132
+ Write-Host "[INFO] Anti-pattern: 20-task memory" -ForegroundColor Cyan
1133
+
1134
+ # Initialize bulk file
1135
+ $bulkLoaded = Initialize-BulkFile
1136
+
1137
+ if ($bulkLoaded) {
1138
+ Write-Host "[INFO] Click Excel window (bulk file). Ctrl+C to stop." -ForegroundColor Yellow
1139
+ } else {
1140
+ Write-Host "[WARNING] Bulk file not loaded. Running without bulk tasks." -ForegroundColor Yellow
1141
+ Write-Host "[INFO] Click Excel window. Ctrl+C to stop." -ForegroundColor Yellow
1142
+ }
1143
+
1144
+ Start-Sleep -Seconds 3
1145
+
1146
+ $pos = Get-RandomScreenPosition "excel-cells"
1147
+ Move-MouseSmooth $pos.X $pos.Y
1148
+ $script:lastApp = "excel"
1149
+
1150
+ try {
1151
+ while ($true) {
1152
+ $task = Select-NextTask
1153
+
1154
+ # Maybe switch app
1155
+ $taskCat = if ($task.cat -eq "bulk") { "excel" } else { $task.cat }
1156
+ if ($taskCat -ne $script:lastApp -and $taskCat -ne "human") {
1157
+ Switch-ToApp $taskCat
1158
+ }
1159
+
1160
+ # Execute task
1161
+ Write-Host "[$(Get-Date -Format 'HH:mm:ss')] Task #$($totalActions + 1): $($task.name)" -ForegroundColor Gray
1162
+
1163
+ switch ($task.cat) {
1164
+ "excel" { Execute-ExcelTask $task }
1165
+ "bulk" { Execute-BulkTask $task }
1166
+ "perpetua" { Execute-PerpetuaTask $task }
1167
+ "chrome" { Execute-ChromeTask $task }
1168
+ "teams" { Execute-TeamsTask $task }
1169
+ "human" { Execute-HumanTask $task }
1170
+ }
1171
+
1172
+ $totalActions++
1173
+
1174
+ # Task duration
1175
+ $minDur = $task.dur[0]
1176
+ $maxDur = $task.dur[1]
1177
+ $taskDuration = Get-Random -Minimum $minDur -Maximum $maxDur
1178
+
1179
+ # Execute duration with fidgets
1180
+ $elapsed = 0
1181
+ while ($elapsed -lt $taskDuration) {
1182
+ $sleepTime = [Math]::Min(5, $taskDuration - $elapsed)
1183
+ Start-Sleep -Seconds $sleepTime
1184
+ $elapsed += $sleepTime
1185
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 15) { Fidget-Mouse }
1186
+ }
1187
+
1188
+ # Gap between tasks (5-29 sec)
1189
+ $gap = Get-Random -Minimum 5 -Maximum 29
1190
+ $gapElapsed = 0
1191
+ while ($gapElapsed -lt $gap) {
1192
+ Start-Sleep -Seconds 5
1193
+ $gapElapsed += 5
1194
+ if ((Get-Random -Minimum 1 -Maximum 100) -le 20) { Fidget-Mouse }
1195
+ }
1196
+ }
1197
+ }
1198
+ finally {
1199
+ $runTime = [math]::Round(((Get-Date) - $script:sessionStart).TotalMinutes, 1)
1200
+ Write-Host "`n[STOPPED] Runtime: $runTime min | Actions: $totalActions" -ForegroundColor Yellow
1201
+
1202
+ # Close bulk file
1203
+ Close-BulkFile
1204
+ }
1205
+ }
1206
+
1207
+ # ============== CONTROL INTERFACE ==============
1208
+
1209
+ Clear-Host
1210
+ Write-Host "========================================" -ForegroundColor Cyan
1211
+ Write-Host " Amazon Tracker v4.0 - BULK EDITION" -ForegroundColor Cyan
1212
+ Write-Host "========================================" -ForegroundColor Cyan
1213
+ Write-Host ""
1214
+ Write-Host "145 micro-tasks | 1.2GB Real File Operations"
1215
+ Write-Host "Perpetua UI | Anti-pattern (20-task memory)"
1216
+ Write-Host "Time-of-day awareness | Human behaviors"
1217
+ Write-Host ""
1218
+ Write-Host "Commands:"
1219
+ Write-Host " go - Start tracking (loads bulk file)"
1220
+ Write-Host " exit - Close"
1221
+ Write-Host ""
1222
+ Write-Host "File: Bulk sample.xlsx (1.2GB)"
1223
+ Write-Host "----------------------------------------"
1224
+ Write-Host ""
1225
+
1226
+ while ($true) {
1227
+ $cmd = Read-Host "tracker"
1228
+ switch ($cmd.ToLower().Trim()) {
1229
+ "go" { Start-Tracking; Write-Host "" }
1230
+ "exit" {
1231
+ Close-BulkFile
1232
+ Write-Host "[INFO] Closing..." -ForegroundColor Yellow
1233
+ exit
1234
+ }
1235
+ default { if ($cmd -ne "") { Write-Host "[ERROR] Unknown: $cmd (use: go | exit)" -ForegroundColor Red } }
1236
+ }
1237
+ }