| 1 | package llm |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "strings" |
| 6 | ) |
| 7 | |
| 8 | // InsultTemplate defines components for dynamic insult generation |
| 9 | type InsultTemplate struct { |
| 10 | Prefixes []string |
| 11 | Cores []string |
| 12 | Suffixes []string |
| 13 | Modifiers []string |
| 14 | } |
| 15 | |
| 16 | // Template components for dynamic generation |
| 17 | var ( |
| 18 | achievementPrefixes = []string{ |
| 19 | "Achievement unlocked:", |
| 20 | "Congratulations:", |
| 21 | "Well done:", |
| 22 | "Outstanding:", |
| 23 | "Impressive:", |
| 24 | "Remarkable:", |
| 25 | "Exceptional:", |
| 26 | "Unprecedented:", |
| 27 | "Historic moment:", |
| 28 | "Breaking news:", |
| 29 | "Alert:", |
| 30 | "Notable achievement:", |
| 31 | "Milestone reached:", |
| 32 | "Record broken:", |
| 33 | "Hall of shame:", |
| 34 | } |
| 35 | |
| 36 | failureCores = []string{ |
| 37 | "catastrophically breaking production", |
| 38 | "spectacularly failing", |
| 39 | "magnificently destroying the codebase", |
| 40 | "expertly corrupting the database", |
| 41 | "professionally crashing the server", |
| 42 | "brilliantly introducing critical bugs", |
| 43 | "masterfully deploying garbage", |
| 44 | "skillfully breaking everything", |
| 45 | "artfully creating disasters", |
| 46 | "elegantly failing upward", |
| 47 | "gracefully achieving nothing", |
| 48 | "flawlessly executing incompetence", |
| 49 | "perfectly demonstrating failure", |
| 50 | "seamlessly integrating bugs", |
| 51 | "efficiently wasting everyone's time", |
| 52 | "successfully accomplishing disaster", |
| 53 | "consistently breaking the build", |
| 54 | "reliably causing incidents", |
| 55 | "predictably failing", |
| 56 | "systematically destroying progress", |
| 57 | "methodically sabotaging the project", |
| 58 | "deliberately creating chaos", |
| 59 | "intentionally breaking everything", |
| 60 | "strategically failing", |
| 61 | "tactically creating problems", |
| 62 | } |
| 63 | |
| 64 | timingSuffixes = []string{ |
| 65 | "on a Friday afternoon", |
| 66 | "right before the demo", |
| 67 | "during peak hours", |
| 68 | "in front of stakeholders", |
| 69 | "right before release", |
| 70 | "during the all-hands meeting", |
| 71 | "on your first day", |
| 72 | "right after being promoted", |
| 73 | "during the CEO's visit", |
| 74 | "at the worst possible moment", |
| 75 | "right before vacation", |
| 76 | "on a Monday morning", |
| 77 | "during standup", |
| 78 | "in the production environment", |
| 79 | "right before code freeze", |
| 80 | "during the sprint review", |
| 81 | "at 11:59 PM on the deadline", |
| 82 | "right after saying 'it works on my machine'", |
| 83 | "moments after merge to main", |
| 84 | "during the live demo", |
| 85 | "in front of the entire team", |
| 86 | "right after claiming expertise", |
| 87 | "while everyone is watching", |
| 88 | "at the critical moment", |
| 89 | "during the investor pitch", |
| 90 | } |
| 91 | |
| 92 | intensityModifiers = []string{ |
| 93 | "Spectacularly", |
| 94 | "Catastrophically", |
| 95 | "Magnificently", |
| 96 | "Epically", |
| 97 | "Gloriously", |
| 98 | "Tremendously", |
| 99 | "Monumentally", |
| 100 | "Colossally", |
| 101 | "Phenomenally", |
| 102 | "Extraordinarily", |
| 103 | "Remarkably", |
| 104 | "Incredibly", |
| 105 | "Unbelievably", |
| 106 | "Astoundingly", |
| 107 | "Staggeringly", |
| 108 | } |
| 109 | ) |
| 110 | |
| 111 | // GenerateDynamicInsult creates a dynamic insult from templates |
| 112 | func GenerateDynamicInsult(ctx SmartFallbackContext, history *UserFailureHistory) string { |
| 113 | var insults []string |
| 114 | |
| 115 | // Achievement-style insults |
| 116 | prefix := selectInsult(achievementPrefixes, ctx.FullCommand) |
| 117 | core := selectInsult(failureCores, ctx.FullCommand+ctx.Command) |
| 118 | suffix := selectInsult(timingSuffixes, ctx.FullCommand+fmt.Sprintf("%d", ctx.ExitCode)) |
| 119 | |
| 120 | insults = append(insults, fmt.Sprintf("%s %s %s.", prefix, core, suffix)) |
| 121 | |
| 122 | // Variable substitution insults |
| 123 | if history != nil { |
| 124 | stats := history.GetStats() |
| 125 | |
| 126 | if stats.CurrentStreak >= 3 { |
| 127 | insults = append(insults, |
| 128 | fmt.Sprintf("Failure #%d in a row. Consistency: Your only skill.", stats.CurrentStreak), |
| 129 | ) |
| 130 | } |
| 131 | |
| 132 | if stats.WorstCommandCount > 10 && ctx.Command == stats.WorstCommand { |
| 133 | insults = append(insults, |
| 134 | fmt.Sprintf("Failed '%s' %d times. Have you considered '%s-yourself-out'?", |
| 135 | stats.WorstCommand, stats.WorstCommandCount, stats.WorstCommand), |
| 136 | ) |
| 137 | } |
| 138 | |
| 139 | if stats.WorstHour == ctx.TimeOfDay && stats.TodayFailures > 3 { |
| 140 | insults = append(insults, |
| 141 | fmt.Sprintf("%d:00 again? This is your power hour for disasters.", ctx.TimeOfDay), |
| 142 | ) |
| 143 | } |
| 144 | |
| 145 | if stats.WorstBranch == ctx.GitBranch && stats.WorstBranchCount > 5 { |
| 146 | insults = append(insults, |
| 147 | fmt.Sprintf("Breaking '%s' for the %d%s time. Team morale: -%d.", |
| 148 | ctx.GitBranch, stats.WorstBranchCount, getOrdinalSuffix(stats.WorstBranchCount), |
| 149 | stats.WorstBranchCount*10), |
| 150 | ) |
| 151 | } |
| 152 | |
| 153 | if stats.TotalFailures > 100 { |
| 154 | insults = append(insults, |
| 155 | fmt.Sprintf("%d total failures logged. You're in the hall of shame.", stats.TotalFailures), |
| 156 | ) |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | // Command-specific dynamic insults |
| 161 | if ctx.Command != "" { |
| 162 | insults = append(insults, generateCommandSpecificInsult(ctx)) |
| 163 | } |
| 164 | |
| 165 | // Exit code specific |
| 166 | if ctx.ExitCode > 0 { |
| 167 | insults = append(insults, generateExitCodeInsult(ctx)) |
| 168 | } |
| 169 | |
| 170 | // Select one from generated insults |
| 171 | if len(insults) > 0 { |
| 172 | return selectInsult(insults, ctx.FullCommand) |
| 173 | } |
| 174 | |
| 175 | return "" |
| 176 | } |
| 177 | |
| 178 | // generateCommandSpecificInsult creates command-aware insults |
| 179 | func generateCommandSpecificInsult(ctx SmartFallbackContext) string { |
| 180 | templates := map[string][]string{ |
| 181 | "git": { |
| 182 | "git {subcommand}: Commit to a new career instead.", |
| 183 | "Git error: Git good? Git out.", |
| 184 | "{command} failed: Version control can't control your incompetence.", |
| 185 | }, |
| 186 | "docker": { |
| 187 | "Docker {subcommand} failed: Can't containerize catastrophe.", |
| 188 | "Container crashed: Can't contain your mistakes.", |
| 189 | "{command}: Image of failure successfully built.", |
| 190 | }, |
| 191 | "npm": { |
| 192 | "npm {subcommand}: Node Package Misery delivered.", |
| 193 | "{command} failed: Dependencies: Many. Skills: None.", |
| 194 | "npm error: Not Particularly Competent detected.", |
| 195 | }, |
| 196 | "cargo": { |
| 197 | "cargo {subcommand}: Can't cargo your way out of this.", |
| 198 | "Rust build failed: Your code is the rust.", |
| 199 | "{command}: Ownership model violated. Ownership of brain: Questionable.", |
| 200 | }, |
| 201 | "kubectl": { |
| 202 | "kubectl {subcommand}: Kube-can't-do anything right.", |
| 203 | "Kubernetes error: Can't orchestrate competence.", |
| 204 | "{command} failed: Your cluster is the disaster.", |
| 205 | }, |
| 206 | "terraform": { |
| 207 | "terraform {subcommand}: Infrastructure as Code. Incompetence as Career.", |
| 208 | "Terraform failed: Terraform your way to unemployment.", |
| 209 | "{command}: State corrupted. Mental state: Also corrupted.", |
| 210 | }, |
| 211 | } |
| 212 | |
| 213 | if tmpl, exists := templates[ctx.Command]; exists { |
| 214 | selected := selectInsult(tmpl, ctx.FullCommand) |
| 215 | selected = strings.ReplaceAll(selected, "{command}", ctx.Command) |
| 216 | selected = strings.ReplaceAll(selected, "{subcommand}", ctx.Subcommand) |
| 217 | return selected |
| 218 | } |
| 219 | |
| 220 | return "" |
| 221 | } |
| 222 | |
| 223 | // generateExitCodeInsult creates exit-code-aware insults |
| 224 | func generateExitCodeInsult(ctx SmartFallbackContext) string { |
| 225 | templates := map[int]string{ |
| 226 | 1: "Exit code 1: The classic. Failure so generic it's embarrassing.", |
| 227 | 2: "Exit code 2: Misuse detected. Misuse of profession detected.", |
| 228 | 126: "Exit code 126: Permission denied. Reality denying you success.", |
| 229 | 127: "Exit code 127: Command not found. Competence: Also not found.", |
| 230 | 130: "Exit code 130: Ctrl+C pressed. Career: Press Ctrl+Alt+Delete.", |
| 231 | 137: "Exit code 137: Process killed. Career should be too.", |
| 232 | 139: "Exit code 139: Segmentation fault. Segmented from reality.", |
| 233 | 255: "Exit code 255: Maximum failure achieved. Congratulations?", |
| 234 | } |
| 235 | |
| 236 | if msg, exists := templates[ctx.ExitCode]; exists { |
| 237 | return msg |
| 238 | } |
| 239 | |
| 240 | return fmt.Sprintf("Exit code %d: %d reasons to reconsider your career.", ctx.ExitCode, ctx.ExitCode) |
| 241 | } |
| 242 | |
| 243 | // getOrdinalSuffix returns the ordinal suffix for a number (st, nd, rd, th) |
| 244 | func getOrdinalSuffix(n int) string { |
| 245 | if n%100 >= 11 && n%100 <= 13 { |
| 246 | return "th" |
| 247 | } |
| 248 | switch n % 10 { |
| 249 | case 1: |
| 250 | return "st" |
| 251 | case 2: |
| 252 | return "nd" |
| 253 | case 3: |
| 254 | return "rd" |
| 255 | default: |
| 256 | return "th" |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | // GenerateStreakEscalation creates increasingly brutal insults based on streak |
| 261 | func GenerateStreakEscalation(streak int, ctx SmartFallbackContext) string { |
| 262 | if streak < 2 { |
| 263 | return "" |
| 264 | } |
| 265 | |
| 266 | var templates []string |
| 267 | |
| 268 | if streak >= 10 { |
| 269 | templates = []string{ |
| 270 | fmt.Sprintf("%d CONSECUTIVE FAILURES. This is beyond incompetence. This is performance art.", streak), |
| 271 | fmt.Sprintf("%d IN A ROW. Your team has a betting pool on when you'll quit.", streak), |
| 272 | fmt.Sprintf("STREAK: %d. Failure this consistent requires dedication.", streak), |
| 273 | fmt.Sprintf("%d FAILURES. Even your errors have given up on you.", streak), |
| 274 | fmt.Sprintf("%d STRAIGHT. Breaking records nobody wanted broken.", streak), |
| 275 | } |
| 276 | } else if streak >= 5 { |
| 277 | templates = []string{ |
| 278 | fmt.Sprintf("%d failures in a row. Einstein called: That's insanity.", streak), |
| 279 | fmt.Sprintf("Streak of %d. Consistency is key. Consistent incompetence is keyer.", streak), |
| 280 | fmt.Sprintf("%d consecutive disasters. Your specialty: Reliability in failure.", streak), |
| 281 | fmt.Sprintf("Failure #%d. This is a pattern. You are the pattern.", streak), |
| 282 | fmt.Sprintf("%d in a row. Some people learn from mistakes. You're not some people.", streak), |
| 283 | } |
| 284 | } else if streak >= 3 { |
| 285 | templates = []string{ |
| 286 | fmt.Sprintf("Failure #%d in a row. Three strikes: You're out.", streak), |
| 287 | fmt.Sprintf("%d consecutive fails. Trying the same thing expecting different results?", streak), |
| 288 | fmt.Sprintf("Failure #%d. Pattern detected: You.", streak), |
| 289 | fmt.Sprintf("%d in a row. Maybe read the docs this time?", streak), |
| 290 | } |
| 291 | } else { |
| 292 | templates = []string{ |
| 293 | "Second failure. The sequel nobody asked for.", |
| 294 | "Failed again. Doing it twice doesn't make it work.", |
| 295 | "Another failure. Two data points make a trend: Downward.", |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | return selectInsult(templates, ctx.FullCommand+fmt.Sprintf("%d", streak)) |
| 300 | } |
| 301 | |
| 302 | // GenerateHistoricalInsult creates insults based on long-term patterns |
| 303 | func GenerateHistoricalInsult(history *UserFailureHistory, ctx SmartFallbackContext) string { |
| 304 | if history == nil { |
| 305 | return "" |
| 306 | } |
| 307 | |
| 308 | stats := history.GetStats() |
| 309 | var insults []string |
| 310 | |
| 311 | // Total failures milestones |
| 312 | if stats.TotalFailures >= 1000 { |
| 313 | insults = append(insults, fmt.Sprintf("1000+ failures logged. Four digits of disappointment.")) |
| 314 | } else if stats.TotalFailures >= 500 { |
| 315 | insults = append(insults, fmt.Sprintf("500+ failures. Half a thousand reasons to quit.")) |
| 316 | } else if stats.TotalFailures >= 100 { |
| 317 | insults = append(insults, fmt.Sprintf("100+ failures in your history. Century of incompetence achieved.")) |
| 318 | } |
| 319 | |
| 320 | // Worst command patterns |
| 321 | if stats.WorstCommandCount >= 50 && ctx.Command == stats.WorstCommand { |
| 322 | insults = append(insults, |
| 323 | fmt.Sprintf("'%s' failed %d times. Definition of insanity achieved.", |
| 324 | stats.WorstCommand, stats.WorstCommandCount)) |
| 325 | } |
| 326 | |
| 327 | // Time patterns |
| 328 | if stats.WorstHour >= 0 && ctx.TimeOfDay == stats.WorstHour { |
| 329 | insults = append(insults, |
| 330 | fmt.Sprintf("%d:00: Your statistically worst hour. And you're proving it again.", stats.WorstHour)) |
| 331 | } |
| 332 | |
| 333 | // Branch disaster patterns |
| 334 | if stats.WorstBranchCount >= 20 && ctx.GitBranch == stats.WorstBranch { |
| 335 | insults = append(insults, |
| 336 | fmt.Sprintf("'%s' branch: %d failures logged. Your personal disaster zone.", |
| 337 | stats.WorstBranch, stats.WorstBranchCount)) |
| 338 | } |
| 339 | |
| 340 | // Longest streak |
| 341 | if stats.LongestStreak >= 10 { |
| 342 | insults = append(insults, |
| 343 | fmt.Sprintf("Personal record: %d consecutive failures. Still unbeaten.", stats.LongestStreak)) |
| 344 | } |
| 345 | |
| 346 | // Today's performance |
| 347 | if stats.TodayFailures >= 10 { |
| 348 | insults = append(insults, |
| 349 | fmt.Sprintf("%d failures today. Double digits of disaster before lunch.", stats.TodayFailures)) |
| 350 | } else if stats.TodayFailures >= 5 { |
| 351 | insults = append(insults, |
| 352 | fmt.Sprintf("%d failures today. Productive day for disasters.", stats.TodayFailures)) |
| 353 | } |
| 354 | |
| 355 | if len(insults) > 0 { |
| 356 | return selectInsult(insults, ctx.FullCommand) |
| 357 | } |
| 358 | |
| 359 | return "" |
| 360 | } |
| 361 |