Codex commited on
Commit
a0f98a7
·
1 Parent(s): cf14c48

Add Circa post-parse validation

Browse files
src/market-scanner.js CHANGED
@@ -770,7 +770,45 @@ export function parseCircaOcrText(text) {
770
  entries.push(entry);
771
  }
772
 
773
- return dedupeBy(entries, (entry) => `${entry.marketKey}|${entry.book}`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
774
  }
775
 
776
  function dedupeBy(values, getKey) {
 
770
  entries.push(entry);
771
  }
772
 
773
+ return dedupeBy(entries.filter(isLikelyValidCircaEntry), (entry) => `${entry.marketKey}|${entry.book}`);
774
+ }
775
+
776
+ function isLikelyValidCircaEntry(entry) {
777
+ const playerName = normalizeWhitespace(entry.playerName);
778
+ if (!playerName || playerName.length < 3 || /\d/.test(playerName)) {
779
+ return false;
780
+ }
781
+
782
+ const words = playerName.split(/\s+/).filter(Boolean);
783
+ if (words.length < 2 || words.length > 4) {
784
+ return false;
785
+ }
786
+
787
+ if (words.some((word) => word.length < 2)) {
788
+ return false;
789
+ }
790
+
791
+ const oddsValue = Number(entry.oddsInput);
792
+ if (!Number.isFinite(oddsValue)) {
793
+ return false;
794
+ }
795
+
796
+ if (entry.marketType === 'home_runs') {
797
+ if (entry.side === 'yes' && (oddsValue < 100 || oddsValue > 2000)) {
798
+ return false;
799
+ }
800
+ if (entry.side === 'no' && (oddsValue > -100 || oddsValue < -5000)) {
801
+ return false;
802
+ }
803
+ }
804
+
805
+ if (entry.lineValue !== null && entry.lineValue !== undefined) {
806
+ if (entry.lineValue < 0 || entry.lineValue > 20) {
807
+ return false;
808
+ }
809
+ }
810
+
811
+ return true;
812
  }
813
 
814
  function dedupeBy(values, getKey) {
test/market-scanner.test.js CHANGED
@@ -93,6 +93,17 @@ test('recovers multiple packed home run rows from one OCR line', () => {
93
  assert.ok(entries.some((entry) => entry.playerName === 'GUNNAR HENDERSON' && entry.oddsInput === '+525'));
94
  });
95
 
 
 
 
 
 
 
 
 
 
 
 
96
  test('ranks discrepancy, width, and circa alerts', () => {
97
  const entries = [
98
  {
 
93
  assert.ok(entries.some((entry) => entry.playerName === 'GUNNAR HENDERSON' && entry.oddsInput === '+525'));
94
  });
95
 
96
+ test('filters obviously invalid circa player-name rows', () => {
97
+ const entries = parseCircaOcrText([
98
+ 'WILL [PLAYER] HIT A HOME RUN?',
99
+ 'AARON JUDGE (NYY) 83681 +235 83682 -280',
100
+ 'AS667 NATIONALS A YANKEES 83681 +235 83682 -280',
101
+ ].join('\n'));
102
+
103
+ assert.ok(entries.some((entry) => entry.playerName === 'AARON JUDGE'));
104
+ assert.ok(!entries.some((entry) => /NATIONALS A YANKEES/.test(entry.playerName)));
105
+ });
106
+
107
  test('ranks discrepancy, width, and circa alerts', () => {
108
  const entries = [
109
  {