1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Omega II Blackjack Calculator | PerfectPlay</title> 7 <meta name="description" content="Omega II blackjack calculator. Ace-neutral level-two card counting assistant with live stats and betting ramp."> 8 <link rel="canonical" href="https://perfectplay.dev/omega-2"> 9 10 <!-- JSON-LD Structured Schema --> 11
11<script type="application/ld+json"> 12 { 13 "@context": "https://schema.org", 14 "@type": "SoftwareApplication", 15 "name": "Omega II Blackjack Calculator", 16 "url": "https://perfectplay.dev/omega-2", 17 "description": "Omega II blackjack calculator. Ace-neutral level-two card counting assistant with live stats and betting ramp.", 18 "applicationCategory": "GameApplication", 19 "operatingSystem": "All" 20 } 21 </script>
21 22 23 <link rel="preconnect" href="https://fonts.googleapis.com"> 24 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 25 <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;600;700;800&family=Source+Code+Pro:wght@300;400;500;600;700&display=swap" rel="stylesheet"> 26 <link rel="stylesheet" href="style.css"> 27 <style> 28 :root { 29 --bg1: #7a0000; 30 --bg2: #b00000; 31 --card: rgba(255,255,255,0.12); 32 --card-border: rgba(255,255,255,0.18); 33 --text: #fff7f7; 34 --muted: rgba(255,247,247,0.78); 35 --accent: #ffd9d9; 36 --shadow: 0 10px 30px rgba(0,0,0,0.22); 37 } 38 39 body { 40 margin: 0; 41 padding: 0; 42 background: #000; 43 font-family: Arial, sans-serif; 44 color: var(--text); 45 background: linear-gradient(135deg, var(--bg1), var(--bg2)); 46 min-height: 100vh; 47 box-sizing: border-box; 48 padding-top: 90px; 49 } 50 51 .o2-wrap { 52 max-width: 1100px; 53 margin: 0 auto; 54 padding: 18px; 55 } 56 57 .o2-header { 58 display: flex; 59 justify-content: space-between; 60 align-items: flex-start; 61 gap: 12px; 62 margin-bottom: 16px; 63 } 64 65 .o2-title { 66 font-size: 28px; 67 font-weight: 700; 68 line-height: 1.1; 69 margin: 0; 70 } 71 72 .o2-sub { 73 font-size: 14px; 74 color: var(--muted); 75 margin-top: 6px; 76 } 77 78 .o2-row { 79 display: grid; 80 grid-template-columns: repeat(2, minmax(0,1fr)); 81 gap: 10px; 82 } 83 84 .o2-field { 85 display: flex; 86 flex-direction: column; 87 gap: 6px; 88 margin-bottom: 10px; 89 } 90 91 label { 92 font-size: 12px; 93 color: var(--muted); 94 font-weight: 700; 95 } 96 97 input, select, textarea, button { 98 font: inherit; 99 } 100 101 input, select, textarea { 102 width: 100%; 103 padding: 10px 12px; 104 border-radius: 12px; 105 border: 1px solid rgba(255,255,255,0.18); 106 background: rgba(255,255,255,0.96); 107 color: #2b0000; 108 outline: none; 109 } 110 111 textarea { 112 min-height: 110px; 113 resize: vertical; 114 } 115 116 .o2-actions { 117 display: flex; 118 flex-wrap: wrap; 119 gap: 10px; 120 margin-top: 10px; 121 } 122 123 button { 124 border: 0; 125 border-radius: 12px; 126 padding: 10px 14px; 127 cursor: pointer; 128 background: #fff; 129 color: #7a0000; 130 font-weight: 700; 131 } 132 133 button.o2-secondary { 134 background: rgba(255,255,255,0.18); 135 color: var(--text); 136 border: 1px solid rgba(255,255,255,0.18); 137 } 138 139 .o2-preset-btns { 140 display: flex; 141 flex-wrap: wrap; 142 gap: 8px; 143 margin-bottom: 8px; 144 } 145 146 .o2-preset-btns button { 147 padding: 6px 12px; 148 font-size: 12px; 149 background: rgba(255,255,255,0.18); 150 color: var(--text); 151 border: 1px solid rgba(255,255,255,0.28); 152 border-radius: 999px; 153 font-weight: 700; 154 cursor: pointer; 155 } 156 157 .o2-preset-btns button:hover { 158 background: rgba(255,255,255,0.30); 159 } 160 161 .o2-stats { 162 display: grid; 163 grid-template-columns: repeat(3, minmax(0,1fr)); 164 gap: 10px; 165 } 166 167 .o2-stat { 168 background: rgba(255,255,255,0.09); 169 border: 1px solid rgba(255,255,255,0.14); 170 border-radius: 14px; 171 padding: 14px; 172 } 173 174 .o2-stat .k { 175 font-size: 12px; 176 color: var(--muted); 177 margin-bottom: 6px; 178 font-weight: 700; 179 } 180 181 .o2-stat .v { 182 font-size: 24px; 183 font-weight: 700; 184 line-height: 1; 185 } 186 187 .o2-note { 188 margin-top: 12px; 189 font-size: 12px; 190 color: var(--muted); 191 line-height: 1.45; 192 } 193 194 .o2-tags { 195 display: flex; 196 flex-wrap: wrap; 197 gap: 8px; 198 margin-top: 8px; 199 justify-content: flex-end; 200 } 201 202 .o2-tag { 203 font-size: 12px; 204 background: rgba(255,255,255,0.12); 205 border: 1px solid rgba(255,255,255,0.12); 206 border-radius: 999px; 207 padding: 5px 8px; 208 color: var(--accent); 209 } 210 211 .o2-divider { 212 height: 1px; 213 background: rgba(255,255,255,0.14); 214 margin: 14px 0; 215 } 216 217 .o2-full { 218 grid-column: 1 / -1; 219 } 220 221 .o2-chart-label { 222 font-size: 11px; 223 font-weight: 700; 224 color: var(--muted); 225 letter-spacing: 0.06em; 226 text-transform: uppercase; 227 margin-bottom: 6px; 228 margin-top: 14px; 229 } 230 231 .o2-tc-svg { 232 width: 100%; 233 display: block; 234 } 235 236 .o2-dist-legend { 237 display: flex; 238 gap: 14px; 239 margin-bottom: 8px; 240 flex-wrap: wrap; 241 } 242 243 .o2-dist-legend span { 244 font-size: 11px; 245 color: var(--muted); 246 display: flex; 247 align-items: center; 248 gap: 5px; 249 } 250 251 .o2-dist-legend i { 252 display: inline-block; 253 width: 10px; 254 height: 10px; 255 border-radius: 2px; 256 flex-shrink: 0; 257 } 258 259 .o2-bar-wrap { 260 display: flex; 261 align-items: flex-end; 262 gap: 5px; 263 height: 130px; 264 margin-top: 4px; 265 } 266 267 .o2-bar-col { 268 display: flex; 269 flex-direction: column; 270 align-items: center; 271 flex: 1; 272 height: 100%; 273 justify-content: flex-end; 274 gap: 2px; 275 } 276 277 .o2-bar { 278 width: 100%; 279 border-radius: 4px 4px 0 0; 280 min-height: 2px; 281 } 282 283 .o2-bar-lbl { 284 font-size: 10px; 285 color: var(--muted); 286 } 287 288 .o2-bar-pct { 289 font-size: 10px; 290 font-weight: 700; 291 color: var(--text); 292 line-height: 1.2; 293 } 294 295 .o2-bar-cnt { 296 font-size: 9px; 297 color: var(--muted); 298 line-height: 1.2; 299 } 300 301 .o2-no-data { 302 font-size: 13px; 303 color: var(--muted); 304 padding: 10px 0; 305 } 306 307 .o2-approx-note { 308 font-size: 11px; 309 color: var(--muted); 310 margin-bottom: 8px; 311 } 312 313 @media (max-width: 900px) { 314 .o2-header { 315 align-items: flex-start; 316 flex-direction: column; 317 } 318 .o2-tags { 319 justify-content: flex-start; 320 } 321 } 322 323 @media (max-width: 640px) { 324 .o2-row, .o2-stats { 325 grid-template-columns: 1fr; 326 } 327 .o2-title { 328 font-size: 24px; 329 } 330 } 331 332 /* Draggable Collapsible Block Styles */ 333 .blocks-container { 334 display: flex; 335 flex-direction: column; 336 gap: 16px; 337 margin-top: 16px; 338 } 339 340 .drag-block { 341 background: var(--card); 342 border: 1px solid var(--card-border); 343 border-radius: 16px; 344 box-shadow: var(--shadow); 345 backdrop-filter: blur(4px); 346 transition: opacity 0.2s ease, transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease; 347 } 348 349 .drag-block.dragging { 350 opacity: 0.4; 351 transform: scale(0.98); 352 border: 2px dashed rgba(255, 255, 255, 0.4); 353 } 354 355 .drag-block.drag-over { 356 border-color: #ffd9d9; 357 box-shadow: 0 0 15px rgba(255, 217, 217, 0.3); 358 } 359 360 .block-header { 361 display: flex; 362 align-items: center; 363 padding: 14px 18px; 364 border-bottom: 1px solid rgba(255, 255, 255, 0.08); 365 user-select: none; 366 } 367 368 .block-header.collapsible { 369 cursor: pointer; 370 } 371 372 .block-header h3 { 373 margin: 0; 374 font-size: 16px; 375 font-weight: 700; 376 flex: 1; 377 } 378 379 .drag-handle { 380 font-size: 18px; 381 color: var(--muted); 382 cursor: grab; 383 margin-right: 12px; 384 padding: 0 4px; 385 } 386 387 .drag-handle:active { 388 cursor: grabbing; 389 } 390 391 .collapse-toggle { 392 font-size: 10px; 393 color: var(--muted); 394 transition: transform 0.2s ease; 395 margin-left: 10px; 396 } 397 398 .block-header.collapsed .collapse-toggle { 399 transform: rotate(-90deg); 400 } 401 402 .block-header.collapsed { 403 border-bottom-color: transparent; 404 } 405 406 .block-content { 407 padding: 18px; 408 overflow: hidden; 409 } 410 411 .block-content.collapsed { 412 display: none; 413 } 414 </style> 415</head> 416<body> 417 418 <!-- ===== NAVIGATION ===== --> 419 <header class="site-header" id="top"> 420 <nav class="nav-inner"> 421 <a href="/" class="logo" aria-label="PerfectPlay Home">
422 <span class="logo-text">PerfectPlay</span> 423 </a> 424 <button class="hamburger" id="hamburger" aria-label="Toggle menu" aria-expanded="false"> 425 <span></span><span></span><span></span> 426 </button> 427 <ul class="nav-links" id="nav-links"> 428 <li><a href="/" class="nav-link">HOME</a></li> 429 <li><a href="/wong-halves" class="nav-link">WONG HALVES</a></li> 430 <li><a href="/omega-2" class="nav-link active">OMEGA 2</a></li> 431 <li><a href="/hi-opt-ii" class="nav-link">HI OPT II</a></li> 432 <li><a href="/hi-lo" class="nav-link">HI-LO</a></li> 433 <li><a href="/zen" class="nav-link">ZEN COUNT</a></li> 434 <li class="nav-dropdown-wrap"> 435 <button class="more-btn" aria-label="More options"> 436 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> 437 <circle cx="12" cy="12" r="1"></circle> 438 <circle cx="19" cy="12" r="1"></circle> 439 <circle cx="5" cy="12" r="1"></circle> 440 </svg> 441 </button> 442 <ul class="dropdown-menu"> 443 <li><a href="/wong-halves">WONG HALVES</a></li> 444 <li><a href="/omega-2">OMEGA 2</a></li> 445 <li><a href="/hi-opt-ii">HI OPT II</a></li> 446 <li><a href="/hi-lo">HI-LO</a></li> 447 <li><a href="/zen">ZEN COUNT</a></li> 448 <li><a href="/full-composition">FULL COMPOSITION</a></li> 449 <li><a href="/privacy">Privacy Policy</a></li> 450 <li class="dropdown-divider" style="border-top: 1px solid rgba(255,255,255,0.1); margin: 6px 0;"></li> 451 <li><a href="/" style="font-weight: 600; color: #fff;">English</a></li> 452 <li><a href="/zh">䏿 (Mandarin)</a></li> 453 <li><a href="/fr">Français</a></li> 454 <li><a href="/ru">Ð ÑÑÑкий</a></li> 455 </ul> 456 </li> 457 </ul> 458 </nav> 459 </header> 460<body> 461 462 <div class="o2-wrap"> 463 <!-- Header --> 464 <div class="o2-header"> 465 <div> 466 <h2 class="o2-title">Omega II Assistant</h2> 467 <div class="o2-sub">Ace-neutral level-two count. Betting uses granular betting TC rather than rounded TC for better accuracy. Rounded TC is displayed only as an extra reference.</div> 468 </div> 469 <div class="o2-tags"> 470 <span class="o2-tag">T/J/Q/K:-2</span> 471 <span class="o2-tag">A:0 side</span> 472 </div> 473 </div> 474 475 <!-- Draggable Collapsible Blocks Container --> 476 <div class="blocks-container" id="blocks-container"> 477 478 <!-- Card Entry Block --> 479 <div class="drag-block" draggable="true" data-block-id="card-entry" id="block-card-entry"> 480 <div class="block-header"> 481 <span class="drag-handle">☰</span> 482 <h3>Card Entry</h3> 483 </div> 484 <div class="block-content"> 485 <div class="o2-field"> 486 <label for="o2-cards">Cards seen</label> 487 <input id="o2-cards" type="text" placeholder="Example: 2 5 A T 9"> 488 </div> 489 <div class="o2-row"> 490 <div class="o2-field"> 491 <label for="o2-decksTotal">Number of decks</label> 492 <input id="o2-decksTotal" type="number" min="1" max="12" step="1"> 493 </div> 494 <div class="o2-field"> 495 <label for="o2-shuffleAt">Shuffle when decks remaining <=</label> 496 <input id="o2-shuffleAt" type="number" min="0" step="0.1"> 497 </div> 498 </div> 499 <div class="o2-actions"> 500 <button id="o2-add">Add</button> 501 <button id="o2-undo" class="o2-secondary">Undo last add</button> 502 <button id="o2-reset" class="o2-secondary">New shoe</button> 503 </div> 504 <div class="o2-note">10 becomes T. Aces are side-counted and used only for betting true count adjustment.</div> 505 </div> 506 </div> 507 508 <!-- Live Stats Block --> 509 <div class="drag-block" draggable="true" data-block-id="live-stats" id="block-live-stats"> 510 <div class="block-header collapsible" id="header-live-stats">
511 <span class="drag-handle">☰</span> 512 <h3>Live Stats</h3> 513 <span class="collapse-toggle">▼</span> 514 </div> 515 <div class="block-content" id="content-live-stats"> 516 <div class="o2-stats"> 517 <div class="o2-stat"><div class="k">Running count</div><div class="v" id="o2-rc"></div></div> 518 <div class="o2-stat"><div class="k">Ace side count</div><div class="v" id="o2-asc"></div></div> 519 <div class="o2-stat"><div class="k">Decks remaining</div><div class="v" id="o2-dr"></div></div> 520 <div class="o2-stat"><div class="k">Main true count</div><div class="v" id="o2-mtc"></div></div> 521 <div class="o2-stat"><div class="k">Ace adjustment</div><div class="v" id="o2-aa"></div></div> 522 <div class="o2-stat"><div class="k">Betting true count</div><div class="v" id="o2-tc"></div></div> 523 <div class="o2-stat"><div class="k">Rounded TC</div><div class="v" id="o2-tcr"></div></div> 524 </div> 525 </div> 526 </div> 527 528 <!-- Relevant Settings Block --> 529 <div class="drag-block" draggable="true" data-block-id="relevant-settings" id="block-relevant-settings"> 530 <div class="block-header collapsible" id="header-relevant-settings"> 531 <span class="drag-handle">☰</span> 532 <h3>Relevant Settings</h3> 533 <span class="collapse-toggle">▼</span> 534 </div> 535 <div class="block-content" id="content-relevant-settings"> 536 <div class="o2-row"> 537 <div class="o2-field"> 538 <label for="o2-tableMin">Table minimum</label> 539 <input id="o2-tableMin" type="number" min="1" step="1"> 540 </div> 541 <div class="o2-field"> 542 <label for="o2-tableMax">Table maximum</label> 543 <input id="o2-tableMax" type="number" min="1" step="1"> 544 </div> 545 </div> 546 <div class="o2-field"> 547 <label for="o2-insuranceIndex">Insurance index</label> 548 <input id="o2-insuranceIndex" type="number" step="0.5"> 549 </div> 550 <div class="o2-field"> 551 <label>How much to bet at each true count level</label> 552 <div class="o2-preset-btns"> 553 <button id="o2-preset-1-8">Spread 1-8</button> 554 <button id="o2-preset-1-12">Spread 1-12</button> 555 <button id="o2-preset-1-16">Spread 1-16</button> 556 </div> 557 <textarea id="o2-customRamp"></textarea> 558 </div> 559 <div class="o2-note">Edit directly or tap a preset above to load it. Each line: TC<=0:1, TC>=1:2, TC>=4:12 etc. Insurance uses main true count. Betting uses ace-adjusted true count.</div> 560 </div> 561 </div> 562 563 <!-- History Stats Block --> 564 <div class="drag-block" draggable="true" data-block-id="history-stats" id="block-history-stats"> 565 <div class="block-header collapsible" id="header-history-stats"> 566 <span class="drag-handle">☰</span> 567 <h3>History & Stats</h3> 568 <span class="collapse-toggle">▼</span> 569 </div> 570 <div class="block-content" id="content-history-stats"> 571 <div id="o2-history-body"></div> 572 </div> 573 </div> 574 575 </div> 576 </div> 577 578
578<script src="main.js"></script>
578 579
579<script src="omega-2.js"></script>
579 580</body> 581</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.