ad-spend-tracker 2.4.0 → 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 +1 -1
- package/scripts/work_simulator.ps1 +511 -472
- package/Log.txt +0 -28542
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# Amazon Advertising Spend Tracker
|
|
2
|
-
#
|
|
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
|
-
$
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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
|
|
30
|
-
"sponsored brands video
|
|
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://
|
|
37
|
-
"https://
|
|
38
|
-
"https://
|
|
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)
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
"
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
# ==============
|
|
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
|
-
|
|
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
|
|
231
|
-
param([string]$
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
Start-Sleep -Milliseconds (Get-Random -Minimum 300 -Maximum 600)
|
|
249
|
-
}
|
|
322
|
+
function Select-NextTask {
|
|
323
|
+
$catWeights = Get-CategoryWeights
|
|
250
324
|
|
|
251
|
-
|
|
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
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
259
|
-
|
|
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
|
-
|
|
341
|
+
if ($pool.Count -eq 0) {
|
|
342
|
+
# Reset history if pool empty
|
|
343
|
+
$script:taskHistory = @()
|
|
344
|
+
$pool = $script:microTasks
|
|
345
|
+
}
|
|
276
346
|
|
|
277
|
-
|
|
278
|
-
$action = Get-Random -Minimum 1 -Maximum 100
|
|
347
|
+
$selected = $pool | Get-Random
|
|
279
348
|
|
|
280
|
-
#
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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
|
-
|
|
433
|
-
|
|
434
|
-
function Do-TeamsAction {
|
|
435
|
-
$action = Get-Random -Minimum 1 -Maximum 100
|
|
521
|
+
function Execute-TeamsTask {
|
|
522
|
+
param($task)
|
|
436
523
|
|
|
437
|
-
|
|
438
|
-
|
|
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
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
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
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
-
|
|
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
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
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
|
-
|
|
525
|
-
$terms = Get-Random -Minimum 15 -Maximum 35
|
|
590
|
+
# ============== APP SWITCHING ==============
|
|
526
591
|
|
|
527
|
-
|
|
528
|
-
|
|
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
|
-
|
|
554
|
-
|
|
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
|
-
|
|
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
|
-
$
|
|
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]
|
|
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
|
-
|
|
635
|
+
# Select next task (anti-pattern)
|
|
636
|
+
$task = Select-NextTask
|
|
579
637
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
Switch-ToApp $
|
|
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
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
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
|
-
|
|
618
|
-
|
|
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 $
|
|
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
|
-
$
|
|
623
|
-
if ((Get-Random -Minimum 1 -Maximum 100) -le
|
|
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
|
-
$
|
|
631
|
-
Write-Host "`n[STOPPED] Runtime: $
|
|
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
|
|
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
|
|
644
|
-
Write-Host " exit - Close
|
|
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
|
-
|
|
657
|
-
|
|
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
|
}
|