powerball-quantum 1.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,239 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateMomentum = calculateMomentum;
4
+ exports.calculateZScores = calculateZScores;
5
+ exports.calculateRecentMomentum = calculateRecentMomentum;
6
+ exports.analyzePairFrequency = analyzePairFrequency;
7
+ exports.weightedSample = weightedSample;
8
+ exports.quantumSelect = quantumSelect;
9
+ exports.checkSumRange = checkSumRange;
10
+ exports.checkOddEvenRatio = checkOddEvenRatio;
11
+ exports.checkHighLowBalance = checkHighLowBalance;
12
+ exports.checkDecadeBalance = checkDecadeBalance;
13
+ exports.checkEndingDiversity = checkEndingDiversity;
14
+ exports.checkNoTripleConsecutive = checkNoTripleConsecutive;
15
+ exports.isInHistory = isInHistory;
16
+ exports.buildHistorySet = buildHistorySet;
17
+ const types_1 = require("./types");
18
+ /**
19
+ * Calculate exponential decay momentum scores
20
+ */
21
+ function calculateMomentum(draws, decayAlpha = 0.03) {
22
+ const whiteScores = {};
23
+ const redScores = {};
24
+ // Initialize scores
25
+ for (let n = types_1.WHITE_BALL_RANGE.min; n <= types_1.WHITE_BALL_RANGE.max; n++) {
26
+ whiteScores[n] = 0.1;
27
+ }
28
+ for (let n = types_1.RED_BALL_RANGE.min; n <= types_1.RED_BALL_RANGE.max; n++) {
29
+ redScores[n] = 0.1;
30
+ }
31
+ // Sort by date ascending
32
+ const sorted = [...draws].sort((a, b) => a.date.getTime() - b.date.getTime());
33
+ const total = sorted.length;
34
+ sorted.forEach((draw, idx) => {
35
+ const t = total - 1 - idx; // t=0 for most recent
36
+ const weight = Math.exp(-decayAlpha * t);
37
+ draw.whiteBalls.forEach(w => {
38
+ if (whiteScores[w] !== undefined) {
39
+ whiteScores[w] += weight;
40
+ }
41
+ });
42
+ if (redScores[draw.powerball] !== undefined) {
43
+ redScores[draw.powerball] += weight;
44
+ }
45
+ });
46
+ return { white: whiteScores, red: redScores };
47
+ }
48
+ /**
49
+ * Calculate Z-scores for gap analysis (mean reversion)
50
+ */
51
+ function calculateZScores(draws) {
52
+ const whiteGaps = {};
53
+ const redGaps = {};
54
+ const lastSeenWhite = {};
55
+ const lastSeenRed = {};
56
+ // Initialize
57
+ for (let n = types_1.WHITE_BALL_RANGE.min; n <= types_1.WHITE_BALL_RANGE.max; n++) {
58
+ whiteGaps[n] = [];
59
+ lastSeenWhite[n] = -1;
60
+ }
61
+ for (let n = types_1.RED_BALL_RANGE.min; n <= types_1.RED_BALL_RANGE.max; n++) {
62
+ redGaps[n] = [];
63
+ lastSeenRed[n] = -1;
64
+ }
65
+ const sorted = [...draws].sort((a, b) => a.date.getTime() - b.date.getTime());
66
+ sorted.forEach((draw, idx) => {
67
+ // White balls
68
+ draw.whiteBalls.forEach(w => {
69
+ if (lastSeenWhite[w] !== -1) {
70
+ whiteGaps[w].push(idx - lastSeenWhite[w]);
71
+ }
72
+ lastSeenWhite[w] = idx;
73
+ });
74
+ // Red ball
75
+ if (lastSeenRed[draw.powerball] !== -1) {
76
+ redGaps[draw.powerball].push(idx - lastSeenRed[draw.powerball]);
77
+ }
78
+ lastSeenRed[draw.powerball] = idx;
79
+ });
80
+ const total = sorted.length;
81
+ const whiteZ = {};
82
+ const redZ = {};
83
+ // Calculate Z-scores
84
+ for (let n = types_1.WHITE_BALL_RANGE.min; n <= types_1.WHITE_BALL_RANGE.max; n++) {
85
+ const currentGap = total - 1 - lastSeenWhite[n];
86
+ const gaps = whiteGaps[n];
87
+ if (gaps.length === 0) {
88
+ whiteZ[n] = 0;
89
+ continue;
90
+ }
91
+ const mean = gaps.reduce((a, b) => a + b, 0) / gaps.length;
92
+ const variance = gaps.reduce((sum, g) => sum + Math.pow(g - mean, 2), 0) / gaps.length;
93
+ const stdev = Math.sqrt(variance) || 1;
94
+ whiteZ[n] = (currentGap - mean) / stdev;
95
+ }
96
+ for (let n = types_1.RED_BALL_RANGE.min; n <= types_1.RED_BALL_RANGE.max; n++) {
97
+ const currentGap = total - 1 - lastSeenRed[n];
98
+ const gaps = redGaps[n];
99
+ if (gaps.length === 0) {
100
+ redZ[n] = 0;
101
+ continue;
102
+ }
103
+ const mean = gaps.reduce((a, b) => a + b, 0) / gaps.length;
104
+ const variance = gaps.reduce((sum, g) => sum + Math.pow(g - mean, 2), 0) / gaps.length;
105
+ const stdev = Math.sqrt(variance) || 1;
106
+ redZ[n] = (currentGap - mean) / stdev;
107
+ }
108
+ return { white: whiteZ, red: redZ };
109
+ }
110
+ /**
111
+ * Calculate recent momentum (last N draws)
112
+ */
113
+ function calculateRecentMomentum(draws, nRecent = 15, decay = 0.15) {
114
+ const whiteScores = {};
115
+ const redScores = {};
116
+ for (let n = types_1.WHITE_BALL_RANGE.min; n <= types_1.WHITE_BALL_RANGE.max; n++) {
117
+ whiteScores[n] = 0.1;
118
+ }
119
+ for (let n = types_1.RED_BALL_RANGE.min; n <= types_1.RED_BALL_RANGE.max; n++) {
120
+ redScores[n] = 0.1;
121
+ }
122
+ const sorted = [...draws].sort((a, b) => b.date.getTime() - a.date.getTime()).slice(0, nRecent);
123
+ sorted.forEach((draw, idx) => {
124
+ const weight = Math.exp(-decay * idx) * 2;
125
+ draw.whiteBalls.forEach(w => {
126
+ if (whiteScores[w] !== undefined) {
127
+ whiteScores[w] += weight;
128
+ }
129
+ });
130
+ if (redScores[draw.powerball] !== undefined) {
131
+ redScores[draw.powerball] += weight;
132
+ }
133
+ });
134
+ return { white: whiteScores, red: redScores };
135
+ }
136
+ /**
137
+ * Analyze pair frequency
138
+ */
139
+ function analyzePairFrequency(draws, topN = 50) {
140
+ const pairCounts = new Map();
141
+ draws.forEach(draw => {
142
+ const whites = [...draw.whiteBalls].sort((a, b) => a - b);
143
+ for (let i = 0; i < whites.length; i++) {
144
+ for (let j = i + 1; j < whites.length; j++) {
145
+ const key = `${whites[i]}-${whites[j]}`;
146
+ pairCounts.set(key, (pairCounts.get(key) || 0) + 1);
147
+ }
148
+ }
149
+ });
150
+ const pairBonus = {};
151
+ const sorted = [...pairCounts.entries()]
152
+ .sort((a, b) => b[1] - a[1])
153
+ .slice(0, topN);
154
+ sorted.forEach(([pair, count]) => {
155
+ const [a, b] = pair.split('-').map(Number);
156
+ pairBonus[a] = (pairBonus[a] || 0) + count * 0.1;
157
+ pairBonus[b] = (pairBonus[b] || 0) + count * 0.1;
158
+ });
159
+ return pairBonus;
160
+ }
161
+ /**
162
+ * Weighted random selection
163
+ */
164
+ function weightedSample(candidates, weights, k) {
165
+ const selected = new Set();
166
+ const totalWeight = weights.reduce((a, b) => a + b, 0);
167
+ while (selected.size < k) {
168
+ let r = Math.random() * totalWeight;
169
+ for (let i = 0; i < candidates.length; i++) {
170
+ r -= weights[i];
171
+ if (r <= 0) {
172
+ selected.add(candidates[i]);
173
+ break;
174
+ }
175
+ }
176
+ }
177
+ return [...selected];
178
+ }
179
+ /**
180
+ * Quantum selector combining all signals
181
+ */
182
+ function quantumSelect(momentum, zScores, recentMomentum, pairBonus, nPicks) {
183
+ const candidates = Object.keys(momentum).map(Number);
184
+ const weights = candidates.map(n => {
185
+ const base = momentum[n] || 0;
186
+ const zBoost = Math.max(0, zScores[n] || 0) * 5;
187
+ const recentBoost = (recentMomentum[n] || 0) * 1.5;
188
+ const pairB = (pairBonus[n] || 0) * 0.5;
189
+ return Math.max(0.1, base + zBoost + recentBoost + pairB);
190
+ });
191
+ return weightedSample(candidates, weights, nPicks);
192
+ }
193
+ // --- FILTERS ---
194
+ function checkSumRange(whiteBalls, min = 130, max = 220) {
195
+ const sum = whiteBalls.reduce((a, b) => a + b, 0);
196
+ return sum >= min && sum <= max;
197
+ }
198
+ function checkOddEvenRatio(whiteBalls) {
199
+ const odds = whiteBalls.filter(x => x % 2 !== 0).length;
200
+ const evens = 5 - odds;
201
+ return (odds === 3 && evens === 2) || (odds === 2 && evens === 3);
202
+ }
203
+ function checkHighLowBalance(whiteBalls, threshold = 35) {
204
+ const lows = whiteBalls.filter(x => x < threshold).length;
205
+ const highs = 5 - lows;
206
+ return (lows === 3 && highs === 2) || (lows === 2 && highs === 3);
207
+ }
208
+ function checkDecadeBalance(whiteBalls) {
209
+ const decades = new Set(whiteBalls.map(n => Math.floor(n / 10)));
210
+ return decades.size >= 3;
211
+ }
212
+ function checkEndingDiversity(whiteBalls) {
213
+ const endings = new Set(whiteBalls.map(n => n % 10));
214
+ return endings.size >= 4;
215
+ }
216
+ function checkNoTripleConsecutive(whiteBalls) {
217
+ const sorted = [...whiteBalls].sort((a, b) => a - b);
218
+ const diffs = [];
219
+ for (let i = 0; i < sorted.length - 1; i++) {
220
+ diffs.push(sorted[i + 1] - sorted[i]);
221
+ }
222
+ const consecutiveOnes = diffs.filter(d => d === 1).length;
223
+ return consecutiveOnes < 2;
224
+ }
225
+ /**
226
+ * Check if combination exists in history
227
+ */
228
+ function isInHistory(whiteBalls, powerball, history) {
229
+ const key = [...whiteBalls].sort((a, b) => a - b).join(',') + '-' + powerball;
230
+ return history.has(key);
231
+ }
232
+ function buildHistorySet(draws) {
233
+ const history = new Set();
234
+ draws.forEach(draw => {
235
+ const key = [...draw.whiteBalls].sort((a, b) => a - b).join(',') + '-' + draw.powerball;
236
+ history.add(key);
237
+ });
238
+ return history;
239
+ }
@@ -0,0 +1,27 @@
1
+ export interface Draw {
2
+ date: Date;
3
+ whiteBalls: number[];
4
+ powerball: number;
5
+ multiplier: number;
6
+ }
7
+ export interface Pick {
8
+ whiteBalls: number[];
9
+ powerball: number;
10
+ score?: number;
11
+ }
12
+ export interface Scores {
13
+ [key: number]: number;
14
+ }
15
+ export interface PredictOptions {
16
+ count?: number;
17
+ showAnalysis?: boolean;
18
+ }
19
+ export declare const WHITE_BALL_RANGE: {
20
+ min: number;
21
+ max: number;
22
+ };
23
+ export declare const RED_BALL_RANGE: {
24
+ min: number;
25
+ max: number;
26
+ };
27
+ export declare const DATA_URL = "https://data.ny.gov/api/views/d6yy-54nr/rows.csv?accessType=DOWNLOAD";
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DATA_URL = exports.RED_BALL_RANGE = exports.WHITE_BALL_RANGE = void 0;
4
+ exports.WHITE_BALL_RANGE = { min: 1, max: 69 };
5
+ exports.RED_BALL_RANGE = { min: 1, max: 26 };
6
+ exports.DATA_URL = "https://data.ny.gov/api/views/d6yy-54nr/rows.csv?accessType=DOWNLOAD";
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "powerball-quantum",
3
+ "version": "1.0.0",
4
+ "description": "Powerball number predictor using quantum-inspired algorithm with momentum, mean reversion, and statistical filters",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "powerball-quantum": "./dist/cli.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "predict": "node dist/cli.js predict",
13
+ "update": "node dist/cli.js update",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "powerball",
18
+ "lottery",
19
+ "predictor",
20
+ "quantum",
21
+ "statistics",
22
+ "probability"
23
+ ],
24
+ "author": "seochan99",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/seochan99/Powerball-Predictor-Quantum"
29
+ },
30
+ "dependencies": {
31
+ "axios": "^1.6.0",
32
+ "commander": "^11.1.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.10.0",
36
+ "typescript": "^5.3.0"
37
+ },
38
+ "engines": {
39
+ "node": ">=16.0.0"
40
+ }
41
+ }