Alp57 commited on
Commit
2192e30
·
verified ·
1 Parent(s): c197784

Upload 3 files

Browse files
Files changed (3) hide show
  1. src/mm_predictor.py +217 -0
  2. src/pb_predictor.py +229 -0
  3. src/streamlit_app.py +116 -34
src/mm_predictor.py ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import random
3
+ from collections import Counter
4
+ from datetime import timedelta
5
+
6
+ def is_sum_in_range(numbers, min_sum, max_sum):
7
+ total = sum(numbers)
8
+ return min_sum <= total <= max_sum
9
+
10
+ def mm_predict_star_ball(df, star_probs=None):
11
+ from collections import Counter
12
+ from datetime import timedelta
13
+ import random
14
+
15
+ cutoff_sb = df["Date"].max() - timedelta(days=30)
16
+ recent_starballs = df[df["Date"] >= cutoff_sb]["MB"].astype(int).tolist()
17
+
18
+ star_freq_all = Counter(df["MB"].astype(int))
19
+ star_freq_recent = Counter(recent_starballs)
20
+
21
+ star_probs = star_probs or {}
22
+
23
+ star_ball_weights = {}
24
+ for sb in range(1, 25): #MegaMillions Starball is 1-24
25
+ w = (
26
+ star_freq_all.get(sb, 0) * 0.6 +
27
+ star_freq_recent.get(sb, 0) * 0.2 +
28
+ star_probs.get(sb, 0) * 0.2
29
+ )
30
+ star_ball_weights[sb] = w
31
+
32
+ elements, weight_vals = zip(*star_ball_weights.items())
33
+ return random.choices(elements, weights=weight_vals, k=1)[0]
34
+
35
+
36
+ def weighted_choice(counter_dict, k=1):
37
+ elements, weights = zip(*counter_dict.items())
38
+ return random.choices(elements, weights=weights, k=k)
39
+
40
+
41
+ def get_ml_number_probs(df):
42
+ from sklearn.ensemble import RandomForestClassifier
43
+ from sklearn.model_selection import train_test_split
44
+ from sklearn.preprocessing import OneHotEncoder
45
+ from sklearn.pipeline import make_pipeline
46
+ import numpy as np
47
+
48
+ df["Date"] = pd.to_datetime(df["Date"])
49
+ df["DayOfWeek"] = df["Date"].dt.dayofweek
50
+
51
+ # PRE-PROCESS THE DATA
52
+ records = []
53
+ for _, row in df.iterrows():
54
+ for col in ['1', '2', '3', '4', '5']:
55
+ records.append({
56
+ "DayOfWeek": row["Date"].dayofweek,
57
+ "DrawNumber": int(row[col])
58
+ })
59
+ data = pd.DataFrame(records)
60
+
61
+ X = data[["DayOfWeek"]]
62
+ y = data["DrawNumber"]
63
+
64
+ model = make_pipeline(
65
+ OneHotEncoder(),
66
+ RandomForestClassifier(n_estimators=100, random_state=42)
67
+ )
68
+ model.fit(X, y)
69
+
70
+ latest_day = df["Date"].max().dayofweek
71
+ X_predict = pd.DataFrame({"DayOfWeek": [latest_day] * 70})
72
+ X_predict["Num"] = list(range(1, 71))
73
+
74
+ probs = model.predict_proba(X_predict[["DayOfWeek"]])
75
+ number_probs = dict(zip(model.classes_, probs[0]))
76
+
77
+ return number_probs
78
+
79
+
80
+ def generate_mm_prediction(df, allow_sequences=True):
81
+
82
+ NUMBER_RANGE = range(1, 71) # MegaMillions RANGE
83
+
84
+ df["Date"] = pd.to_datetime(df["Date"])
85
+ df = df.sort_values("Date", ascending=False)
86
+
87
+ last_draw = df.iloc[0][['1', '2', '3', '4', '5']].astype(int).tolist()
88
+
89
+ flat_all = df[['1', '2', '3', '4', '5']].values.flatten()
90
+ freq_all = Counter(flat_all)
91
+
92
+ cutoff = df["Date"].max() - timedelta(days=30)
93
+ recent_df = df[df["Date"] >= cutoff]
94
+ flat_recent = recent_df[['1', '2', '3', '4', '5']].values.flatten()
95
+ freq_recent = Counter(flat_recent)
96
+
97
+ # PICK A NUMBER FROM THE LAST DRAW (FREQUENCY BASED)
98
+ intersection = set(last_draw) & set(freq_all.keys())
99
+ if intersection:
100
+ weights = {n: freq_all[n] for n in intersection}
101
+ selected = [weighted_choice(weights)[0]]
102
+ #print(f"🔹 First Number (From previous Draw): {selected[0]}")
103
+ else:
104
+ selected = [weighted_choice(freq_all)[0]]
105
+
106
+ number_probs = get_ml_number_probs(df)
107
+
108
+ # WEIGHTED NUMBER POOL (ALL FREQUENCY %60 - LAST 30 DAYS %20 - MACHINE LEARNING %20)
109
+ combined_weights = {}
110
+ for num in NUMBER_RANGE:
111
+ if num not in selected:
112
+ w = (
113
+ freq_all.get(num, 0) * 0.6 + #* 0.6 +
114
+ freq_recent.get(num, 0) *0.2 + #* 0.2 +
115
+ number_probs.get(num, 0) *0.2 #* 0.2
116
+ )
117
+ #print(f"Number {num}: w = {w:.4f} (freq_all={freq_all.get(num, 0)}, freq_recent={freq_recent.get(num, 0)}, ml={number_probs.get(num, 0):.4f})")
118
+ combined_weights[num] = w
119
+
120
+
121
+ # SEQUENCE NUMBERS PART
122
+ seq_pair = []
123
+ if allow_sequences:
124
+ for _ in range(5):
125
+ pool = sorted(set(weighted_choice(combined_weights, 20)))
126
+ adjacent_pairs = []
127
+ #print(f"there is pool variable: {pool}")
128
+ for i in range(len(pool) - 1):
129
+ if pool[i] + 1 == pool[i + 1]:
130
+ adjacent_pairs.append([pool[i], pool[i + 1]])
131
+ if adjacent_pairs:
132
+ seq_pair = random.choice(adjacent_pairs) # 🔄 Rastgele ardışık çift seç
133
+ break
134
+
135
+ if seq_pair:
136
+ selected += seq_pair
137
+ #print(f"🔗 Sequencial Numbers are selected: {seq_pair}")
138
+ for n in seq_pair:
139
+ combined_weights.pop(n, None)
140
+
141
+
142
+ # MAKE IT 5 AGAIN
143
+ while len(selected) < 5:
144
+ pick = weighted_choice(combined_weights)[0]
145
+ if pick not in selected:
146
+ #print(f"➕ Weighted Number is added (combined_weights): {pick}")
147
+ selected.append(pick)
148
+ combined_weights.pop(pick, None)
149
+
150
+
151
+ # Parity FIXING (2-3 / 3-2)
152
+ while True:
153
+ even = [n for n in selected if n % 2 == 0]
154
+ odd = [n for n in selected if n % 2 == 1]
155
+ #print(f"Current parity: {len(even)} even, {len(odd)} odd -> {selected}")
156
+
157
+
158
+ if len(even) in [2, 3] and len(odd) in [2, 3]:
159
+ #print("✅ Parity OK. Breaking loop.")
160
+ break
161
+
162
+ for i, num in enumerate(selected):
163
+ if len(even) in [2, 3] and len(odd) in [2, 3]:
164
+ break
165
+ elif len(even) > 3 or len(odd) < 2:
166
+ target_parity = 1
167
+ else:
168
+ target_parity = 0
169
+
170
+ parity_pool = {
171
+ n: w for n, w in combined_weights.items()
172
+ if n % 2 == target_parity and n not in selected
173
+ }
174
+
175
+ if parity_pool:
176
+ r = weighted_choice(parity_pool)[0]
177
+ #print(f"♻️ Parity Fixing → {selected[i]} instead of {r}")
178
+ selected[i] = r
179
+ even = [n for n in selected if n % 2 == 0]
180
+ odd = [n for n in selected if n % 2 == 1]
181
+
182
+ #break
183
+
184
+
185
+ # print("✅ Final selected:", sorted(selected))
186
+ while not is_sum_in_range(selected, 75, 280):
187
+ return generate_mm_prediction(df, allow_sequences)
188
+ return sorted(selected)
189
+
190
+
191
+ def get_hot_and_cold_numbers(df, top_n=10):
192
+ from collections import Counter
193
+
194
+ NUMBER_RANGE = range(1, 71) # MegaMillions: 1–70
195
+
196
+ flat_all = df[['1', '2', '3', '4', '5']].values.flatten()
197
+ freq_all = Counter(flat_all)
198
+
199
+ freq_sorted = sorted(freq_all.items(), key=lambda x: x[1], reverse=True)
200
+
201
+ hot = freq_sorted[:top_n]
202
+ cold = sorted(freq_sorted[-top_n:], key=lambda x: x[1])
203
+
204
+ return hot, cold
205
+
206
+
207
+ if __name__ == "__main__":
208
+ import pandas as pd
209
+ df = pd.read_csv("../data/mm_results.csv")
210
+ result = generate_mm_prediction(df)
211
+
212
+ predicted_star_ball = mm_predict_star_ball(df)
213
+ print(f"🌟 Predicted Star Ball: {predicted_star_ball}")
214
+
215
+ #print("Final result:", result)
216
+
217
+
src/pb_predictor.py ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import random
3
+ from collections import Counter
4
+ from datetime import timedelta
5
+
6
+ def clean_powerball_df(raw_df):
7
+ #DELETE THE ROWS WHICH CONTAINS "DOUBLE PLAY"
8
+
9
+ df = raw_df[~raw_df["DrawDate"].str.contains("Double Play", na=False)].copy()
10
+ df["Date"] = pd.to_datetime(df["DrawDate"])
11
+ return df
12
+
13
+
14
+
15
+
16
+ def is_sum_in_range(numbers, min_sum, max_sum):
17
+ total = sum(numbers)
18
+ return min_sum <= total <= max_sum
19
+
20
+ def pb_predict_star_ball(df, star_probs=None):
21
+ from collections import Counter
22
+ from datetime import timedelta
23
+ import random
24
+
25
+ cutoff_sb = df["Date"].max() - timedelta(days=30)
26
+ recent_starballs = df[df["Date"] >= cutoff_sb]["PB"].astype(int).tolist()
27
+
28
+ star_freq_all = Counter(df["PB"].astype(int))
29
+ star_freq_recent = Counter(recent_starballs)
30
+
31
+ star_probs = star_probs or {}
32
+
33
+ star_ball_weights = {}
34
+ for sb in range(1, 27): #Powerball's Starball is 1-26
35
+ w = (
36
+ star_freq_all.get(sb, 0) * 0.6 +
37
+ star_freq_recent.get(sb, 0) * 0.2 +
38
+ star_probs.get(sb, 0) * 0.2
39
+ )
40
+ star_ball_weights[sb] = w
41
+
42
+ elements, weight_vals = zip(*star_ball_weights.items())
43
+ return random.choices(elements, weights=weight_vals, k=1)[0]
44
+
45
+
46
+ def weighted_choice(counter_dict, k=1):
47
+ elements, weights = zip(*counter_dict.items())
48
+ return random.choices(elements, weights=weights, k=k)
49
+
50
+
51
+ def get_ml_number_probs(df):
52
+ from sklearn.ensemble import RandomForestClassifier
53
+ from sklearn.model_selection import train_test_split
54
+ from sklearn.preprocessing import OneHotEncoder
55
+ from sklearn.pipeline import make_pipeline
56
+ import numpy as np
57
+
58
+ df["Date"] = pd.to_datetime(df["DrawDate"])
59
+ df["DayOfWeek"] = df["Date"].dt.dayofweek
60
+
61
+ # PRE-PROCESS THE DATA
62
+ records = []
63
+ for _, row in df.iterrows():
64
+ for col in ['1', '2', '3', '4', '5']:
65
+ records.append({
66
+ "DayOfWeek": row["Date"].dayofweek,
67
+ "DrawNumber": int(row[col])
68
+ })
69
+ data = pd.DataFrame(records)
70
+
71
+ X = data[["DayOfWeek"]]
72
+ y = data["DrawNumber"]
73
+
74
+ model = make_pipeline(
75
+ OneHotEncoder(),
76
+ RandomForestClassifier(n_estimators=100, random_state=42)
77
+ )
78
+ model.fit(X, y)
79
+
80
+ latest_day = df["Date"].max().dayofweek
81
+ X_predict = pd.DataFrame({"DayOfWeek": [latest_day] * 69}) #PowerBall 1-69
82
+ X_predict["Num"] = list(range(1, 70)) #PowerBall 1-69
83
+
84
+ probs = model.predict_proba(X_predict[["DayOfWeek"]])
85
+ number_probs = dict(zip(model.classes_, probs[0]))
86
+
87
+ return number_probs
88
+
89
+
90
+ def generate_pb_prediction(df, allow_sequences=True):
91
+
92
+
93
+ NUMBER_RANGE = range(1, 70) # Powerball RANGE
94
+
95
+ df = df.sort_values("Date", ascending=False)
96
+
97
+ last_draw = df.iloc[0][['1', '2', '3', '4', '5']].astype(int).tolist()
98
+ flat_all = df[['1', '2', '3', '4', '5']].values.flatten()
99
+ freq_all = Counter(flat_all)
100
+
101
+ cutoff = df["Date"].max() - timedelta(days=30)
102
+ recent_df = df[df["Date"] >= cutoff]
103
+ flat_recent = recent_df[['1', '2', '3', '4', '5']].values.flatten()
104
+ freq_recent = Counter(flat_recent)
105
+
106
+ # PICK A NUMBER FROM THE LAST DRAW (FREQUENCY BASED)
107
+ intersection = set(last_draw) & set(freq_all.keys())
108
+ if intersection:
109
+ weights = {n: freq_all[n] for n in intersection}
110
+ selected = [weighted_choice(weights)[0]]
111
+ #print(f"🔹 First Number (From previous Draw): {selected[0]}")
112
+ else:
113
+ selected = [weighted_choice(freq_all)[0]]
114
+
115
+ number_probs = get_ml_number_probs(df)
116
+
117
+ # WEIGHTED NUMBER POOL (ALL FREQUENCY %60 - LAST 30 DAYS %20 - MACHINE LEARNING %20)
118
+ combined_weights = {}
119
+ for num in NUMBER_RANGE:
120
+ if num not in selected:
121
+ w = (
122
+ freq_all.get(num, 0) * 0.6 + #* 0.6 +
123
+ freq_recent.get(num, 0) *0.2 + #* 0.2 +
124
+ number_probs.get(num, 0) *0.2 #* 0.2
125
+ )
126
+ #print(f"Number {num}: w = {w:.4f} (freq_all={freq_all.get(num, 0)}, freq_recent={freq_recent.get(num, 0)}, ml={number_probs.get(num, 0):.4f})")
127
+ combined_weights[num] = w
128
+
129
+
130
+ # SEQUENCE NUMBERS PART
131
+ seq_pair = []
132
+ if allow_sequences:
133
+ for _ in range(5):
134
+ pool = sorted(set(weighted_choice(combined_weights, 20)))
135
+ adjacent_pairs = []
136
+ #print(f"there is pool variable: {pool}")
137
+ for i in range(len(pool) - 1):
138
+ if pool[i] + 1 == pool[i + 1]:
139
+ adjacent_pairs.append([pool[i], pool[i + 1]])
140
+ if adjacent_pairs:
141
+ seq_pair = random.choice(adjacent_pairs) # 🔄 Rastgele ardışık çift seç
142
+ break
143
+
144
+ if seq_pair:
145
+ selected += seq_pair
146
+ #print(f"🔗 Sequencial Numbers are selected: {seq_pair}")
147
+ for n in seq_pair:
148
+ combined_weights.pop(n, None)
149
+
150
+
151
+ # MAKE IT 5 AGAIN
152
+ while len(selected) < 5:
153
+ pick = weighted_choice(combined_weights)[0]
154
+ if pick not in selected:
155
+ #print(f"➕ Weighted Number is added (combined_weights): {pick}")
156
+ selected.append(pick)
157
+ combined_weights.pop(pick, None)
158
+
159
+
160
+ # Parity FIXING (2-3 / 3-2)
161
+ while True:
162
+ even = [n for n in selected if n % 2 == 0]
163
+ odd = [n for n in selected if n % 2 == 1]
164
+ #print(f"Current parity: {len(even)} even, {len(odd)} odd -> {selected}")
165
+
166
+
167
+ if len(even) in [2, 3] and len(odd) in [2, 3]:
168
+ #print("✅ Parity OK. Breaking loop.")
169
+ break
170
+
171
+ for i, num in enumerate(selected):
172
+ if len(even) in [2, 3] and len(odd) in [2, 3]:
173
+ break
174
+ elif len(even) > 3 or len(odd) < 2:
175
+ target_parity = 1
176
+ else:
177
+ target_parity = 0
178
+
179
+ parity_pool = {
180
+ n: w for n, w in combined_weights.items()
181
+ if n % 2 == target_parity and n not in selected
182
+ }
183
+
184
+ if parity_pool:
185
+ r = weighted_choice(parity_pool)[0]
186
+ #print(f"♻️ Parity Fixing → {selected[i]} instead of {r}")
187
+ selected[i] = r
188
+ even = [n for n in selected if n % 2 == 0]
189
+ odd = [n for n in selected if n % 2 == 1]
190
+
191
+ #break
192
+
193
+
194
+ print("✅ Final selected:", sorted(selected))
195
+ while not is_sum_in_range(selected, 65, 265): #Powerball Sum Range
196
+ return generate_pb_prediction(df, allow_sequences)
197
+ return sorted(selected)
198
+
199
+
200
+ def get_hot_and_cold_numbers(df, top_n=10):
201
+ from collections import Counter
202
+
203
+ NUMBER_RANGE = range(1, 70) # Powerball: 1–69
204
+
205
+ flat_all = df[['1', '2', '3', '4', '5']].values.flatten()
206
+ freq_all = Counter(flat_all)
207
+
208
+ freq_sorted = sorted(freq_all.items(), key=lambda x: x[1], reverse=True)
209
+
210
+ hot = freq_sorted[:top_n]
211
+ cold = sorted(freq_sorted[-top_n:], key=lambda x: x[1]) # sort from less to much
212
+
213
+ return hot, cold
214
+
215
+
216
+ if __name__ == "__main__":
217
+
218
+ raw = pd.read_csv("../data/pb_results.csv")
219
+
220
+ df = clean_powerball_df(raw) #DELETE ROWS WHICH CONTAINS "DOUBLE PLAY"
221
+
222
+ result = generate_pb_prediction(df)
223
+
224
+ predicted_star_ball = pb_predict_star_ball(df)
225
+ print(f"🌟 Predicted Star Ball: {predicted_star_ball}")
226
+
227
+ #print("Final result:", result)
228
+
229
+
src/streamlit_app.py CHANGED
@@ -3,14 +3,73 @@ import pandas as pd
3
  from gimme5_predictor import generate_gimme5_prediction
4
  from la_predictor import generate_la_prediction, la_predict_star_ball
5
  from mb_predictor import generate_mb_prediction, mb_predict_star_ball
 
 
 
 
 
6
  from gimme5_predictor import get_hot_and_cold_numbers as g5_get_hot
7
  from la_predictor import get_hot_and_cold_numbers as la_get_hot
8
  from mb_predictor import get_hot_and_cold_numbers as mb_get_hot
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
 
11
  st.set_page_config(page_title="Multi Lotto AI Engine", layout="centered")
12
 
13
- st.title("🎯 Lotto AI Engine (V1.2)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  with st.expander("🛠️ App Features (click to view)"):
16
  st.markdown("""
@@ -54,32 +113,42 @@ high totals, which historically have a lower likelihood of being drawn.
54
  If a generated set falls outside the allowed range, the system
55
  regenerates a new one until the condition is satisfied.
56
 
57
- **7- Fortuna favet ludens, qui non ludit, non vincit, In ludo est spes**
58
- """)
59
 
 
60
 
61
 
62
  lotto_type = st.selectbox(
63
  "Select Lotto Type:",
64
- options=["LA (Lotto America)", "MB (Megabucks)", "G5 (Gimme 5)"],
65
  index=0
66
  )
67
 
68
  DATA_PATHS = {
69
  "G5 (Gimme 5)": "data/gimme5_results.csv",
70
  "LA (Lotto America)": "data/la_results.csv",
71
- "MB (Megabucks)": "data/mb_results.csv"
 
 
72
  }
73
 
74
 
75
  g5_df = pd.read_csv(DATA_PATHS["G5 (Gimme 5)"])
76
  la_df = pd.read_csv(DATA_PATHS["LA (Lotto America)"])
77
  mb_df = pd.read_csv(DATA_PATHS["MB (Megabucks)"])
 
 
 
 
 
78
 
79
  #WE CALCULATE HOT-COLD NUMBERS HERE
80
  hot_g5, cold_g5 = g5_get_hot(g5_df)
81
  hot_la, cold_la = la_get_hot(la_df)
82
  hot_mb, cold_mb = mb_get_hot(mb_df)
 
 
 
83
 
84
  try:
85
  data_path = DATA_PATHS[lotto_type]
@@ -98,30 +167,24 @@ try:
98
  </style>
99
  """, unsafe_allow_html=True)
100
 
101
-
102
  if lotto_type == "G5 (Gimme 5)":
103
  use_sequence = st.checkbox("🔗 Include Sequential Numbers", value=False)
104
  if st.button("🎰 Generate Prediction"):
105
  result = generate_gimme5_prediction(g5_df, allow_sequences=use_sequence)
106
  st.success(f"🧠 Predicted Numbers: {result}")
107
- st.success("ℹ️ No Star Ball or Megabucks Number for Gimme5")
108
  st.info(f"🔢 Total Sum of Picks: {sum(result)}")
109
 
110
  #HOT-COLD NUMBERS
111
  hot_df = pd.DataFrame(hot_g5, columns=["Number", "Frequency"])
112
  cold_df = pd.DataFrame(cold_g5, columns=["Number", "Frequency"])
113
 
114
- hot_df.index = range(1, len(hot_df)+1)
115
- hot_df.index.name = 'No'
116
- cold_df.index = range(1, len(hot_df)+1)
117
- cold_df.index.name = 'No'
118
-
119
- with st.expander("🔥 Hot Numbers (Top 10)"):
120
- st.table(hot_df)
121
 
122
- with st.expander("❄️ Cold Numbers (Bottom 10)"):
123
- st.table(cold_df)
124
 
 
125
  elif lotto_type == "LA (Lotto America)":
126
  use_sequence = st.checkbox("🔗 Include Sequential Numbers", value=False)
127
  if st.button("🎰 Generate Prediction"):
@@ -135,17 +198,10 @@ try:
135
  hot_df = pd.DataFrame(hot_la, columns=["Number", "Frequency"])
136
  cold_df = pd.DataFrame(cold_la, columns=["Number", "Frequency"])
137
 
138
- hot_df.index = range(1, len(hot_df)+1)
139
- hot_df.index.name = 'No'
140
- cold_df.index = range(1, len(hot_df)+1)
141
- cold_df.index.name = 'No'
142
-
143
- with st.expander("🔥 Hot Numbers (Top 10)"):
144
- st.table(hot_df)
145
-
146
- with st.expander("❄️ Cold Numbers (Bottom 10)"):
147
- st.table(cold_df)
148
 
 
149
  elif lotto_type == "MB (Megabucks)":
150
  use_sequence = st.checkbox("🔗 Include Sequential Numbers", value=False)
151
  if st.button("🎰 Generate Prediction"):
@@ -159,16 +215,42 @@ try:
159
  hot_df = pd.DataFrame(hot_mb, columns=["Number", "Frequency"])
160
  cold_df = pd.DataFrame(cold_mb, columns=["Number", "Frequency"])
161
 
162
- hot_df.index = range(1, len(hot_df)+1)
163
- hot_df.index.name = 'No'
164
- cold_df.index = range(1, len(hot_df)+1)
165
- cold_df.index.name = 'No'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
- with st.expander("🔥 Hot Numbers (Top 10)"):
168
- st.table(hot_df)
 
 
 
 
 
 
 
 
 
 
 
169
 
170
- with st.expander("❄️ Cold Numbers (Bottom 10)"):
171
- st.table(cold_df)
172
 
173
  except FileNotFoundError:
174
  st.error(f"❌ File not found: `{data_path}`")
 
3
  from gimme5_predictor import generate_gimme5_prediction
4
  from la_predictor import generate_la_prediction, la_predict_star_ball
5
  from mb_predictor import generate_mb_prediction, mb_predict_star_ball
6
+ from mm_predictor import generate_mm_prediction, mm_predict_star_ball
7
+ from pb_predictor import generate_pb_prediction, pb_predict_star_ball
8
+
9
+ from pb_predictor import clean_powerball_df
10
+
11
  from gimme5_predictor import get_hot_and_cold_numbers as g5_get_hot
12
  from la_predictor import get_hot_and_cold_numbers as la_get_hot
13
  from mb_predictor import get_hot_and_cold_numbers as mb_get_hot
14
+ from mm_predictor import get_hot_and_cold_numbers as mm_get_hot
15
+ from pb_predictor import get_hot_and_cold_numbers as pb_get_hot
16
+
17
+ def display_wheel_table(hot_df, cold_df):
18
+ """
19
+ 10 hot + 10 cold sayıdan oluşan wheel havuzunu tablo olarak gösterir.
20
+ """
21
+ hot_numbers = [int(n) for n, _ in hot_df.values]
22
+ cold_numbers = [int(n) for n, _ in cold_df.values]
23
+ wheel_numbers = sorted(hot_numbers + cold_numbers)
24
+
25
+ if len(wheel_numbers) == 20:
26
+ wheel_labels = list("ABCDEFGHIJKLMNOPQRST")
27
+ wheel_df = pd.DataFrame([wheel_numbers], columns=wheel_labels)
28
+ # Comment out
29
+ # with st.expander("🎡 Your 20 Numbers to Wheel"):
30
+ # st.table(wheel_df.style.hide(axis="index"))
31
+
32
+ def display_hot_cold_tables(hot_df, cold_df):
33
+ """
34
+ Var olan hot_df ve cold_df tablolarını düzgünce gösterir.
35
+ """
36
+
37
+ hot_df.index = range(1, len(hot_df)+1)
38
+ hot_df.index.name = 'No'
39
+ cold_df.index = range(1, len(cold_df)+1)
40
+ cold_df.index.name = 'No'
41
+
42
+ with st.expander("🔥 Hot Numbers (Top 10)"):
43
+ st.table(hot_df)
44
+
45
+ with st.expander("❄️ Cold Numbers (Bottom 10)"):
46
+ st.table(cold_df)
47
 
48
 
49
  st.set_page_config(page_title="Multi Lotto AI Engine", layout="centered")
50
 
51
+ st.title("🎯 Lotto AI Engine (V1.3)")
52
+
53
+ with st.expander("🛠️ Requirements (click to view)"):
54
+ st.markdown("""
55
+ 1- powerball (pb) and megamillions (mm) game will be added. they also
56
+ should have sum_range.
57
+ **pb = 65 - 265**
58
+ **mm = 75 - 280**
59
+
60
+ 2- their regular numbers:
61
+ **pb = 1-69**
62
+ **mm = 1-70**
63
+
64
+ their powerball:
65
+ **pb = 1-26**
66
+ **mm = 1-24**
67
+
68
+ 3- a wheel will be added. it will contain 10 hot and 10 cold numbers.
69
+ so it will be 20 numbers. it will be sorted. and later by using txt
70
+ file which Randy provided to us, it will return 76 ticket combinations.
71
+
72
+ """)
73
 
74
  with st.expander("🛠️ App Features (click to view)"):
75
  st.markdown("""
 
113
  If a generated set falls outside the allowed range, the system
114
  regenerates a new one until the condition is satisfied.
115
 
116
+ **7- Fortuna favet ludens, qui non ludit, non vincit, In ludo est spes**
 
117
 
118
+ """)
119
 
120
 
121
  lotto_type = st.selectbox(
122
  "Select Lotto Type:",
123
+ options=["LA (Lotto America)", "MB (Megabucks)", "G5 (Gimme 5)", "MM (Mega Millions)", "PB (Powerball)"],
124
  index=0
125
  )
126
 
127
  DATA_PATHS = {
128
  "G5 (Gimme 5)": "data/gimme5_results.csv",
129
  "LA (Lotto America)": "data/la_results.csv",
130
+ "MB (Megabucks)": "data/mb_results.csv",
131
+ "MM (Mega Millions)": "data/mm_results.csv",
132
+ "PB (Powerball)": "data/pb_results.csv"
133
  }
134
 
135
 
136
  g5_df = pd.read_csv(DATA_PATHS["G5 (Gimme 5)"])
137
  la_df = pd.read_csv(DATA_PATHS["LA (Lotto America)"])
138
  mb_df = pd.read_csv(DATA_PATHS["MB (Megabucks)"])
139
+ mm_df = pd.read_csv(DATA_PATHS["MM (Mega Millions)"])
140
+
141
+ #POWERBALL SPECIAL CLEANING
142
+ raw = pd.read_csv(DATA_PATHS["PB (Powerball)"])
143
+ pb_df = clean_powerball_df(raw) #DELETE ROWS WHICH CONTAINS "DOUBLE PLAY"
144
 
145
  #WE CALCULATE HOT-COLD NUMBERS HERE
146
  hot_g5, cold_g5 = g5_get_hot(g5_df)
147
  hot_la, cold_la = la_get_hot(la_df)
148
  hot_mb, cold_mb = mb_get_hot(mb_df)
149
+ hot_mm, cold_mm = mm_get_hot(mm_df)
150
+ hot_pb, cold_pb = pb_get_hot(pb_df)
151
+
152
 
153
  try:
154
  data_path = DATA_PATHS[lotto_type]
 
167
  </style>
168
  """, unsafe_allow_html=True)
169
 
170
+ #GIMME5
171
  if lotto_type == "G5 (Gimme 5)":
172
  use_sequence = st.checkbox("🔗 Include Sequential Numbers", value=False)
173
  if st.button("🎰 Generate Prediction"):
174
  result = generate_gimme5_prediction(g5_df, allow_sequences=use_sequence)
175
  st.success(f"🧠 Predicted Numbers: {result}")
176
+ st.success("ℹ️ No Additional Number for Gimme5")
177
  st.info(f"🔢 Total Sum of Picks: {sum(result)}")
178
 
179
  #HOT-COLD NUMBERS
180
  hot_df = pd.DataFrame(hot_g5, columns=["Number", "Frequency"])
181
  cold_df = pd.DataFrame(cold_g5, columns=["Number", "Frequency"])
182
 
183
+ display_hot_cold_tables(hot_df, cold_df)
184
+ display_wheel_table(hot_df, cold_df)
 
 
 
 
 
185
 
 
 
186
 
187
+ #LOTTO AMERICA
188
  elif lotto_type == "LA (Lotto America)":
189
  use_sequence = st.checkbox("🔗 Include Sequential Numbers", value=False)
190
  if st.button("🎰 Generate Prediction"):
 
198
  hot_df = pd.DataFrame(hot_la, columns=["Number", "Frequency"])
199
  cold_df = pd.DataFrame(cold_la, columns=["Number", "Frequency"])
200
 
201
+ display_hot_cold_tables(hot_df, cold_df)
202
+ display_wheel_table(hot_df, cold_df)
 
 
 
 
 
 
 
 
203
 
204
+ #MEGABUCKS
205
  elif lotto_type == "MB (Megabucks)":
206
  use_sequence = st.checkbox("🔗 Include Sequential Numbers", value=False)
207
  if st.button("🎰 Generate Prediction"):
 
215
  hot_df = pd.DataFrame(hot_mb, columns=["Number", "Frequency"])
216
  cold_df = pd.DataFrame(cold_mb, columns=["Number", "Frequency"])
217
 
218
+ display_hot_cold_tables(hot_df, cold_df)
219
+ display_wheel_table(hot_df, cold_df)
220
+
221
+ #MEGA MILLIONS
222
+ elif lotto_type == "MM (Mega Millions)":
223
+ use_sequence = st.checkbox("🔗 Include Sequential Numbers", value=False)
224
+ if st.button("🎰 Generate Prediction"):
225
+ main_numbers = generate_mm_prediction(mm_df, allow_sequences=use_sequence)
226
+ star_ball = mm_predict_star_ball(mm_df)
227
+ st.success(f"🧠 Predicted Numbers: {main_numbers}")
228
+ st.success(f"🌟 Predicted Mega Ball Number: [{star_ball}]")
229
+ st.info(f"🔢 Total Sum of Picks: {sum(main_numbers)}")
230
+
231
+ #HOT AND COLD NUMBERS
232
+ hot_df = pd.DataFrame(hot_mm, columns=["Number", "Frequency"])
233
+ cold_df = pd.DataFrame(cold_mm, columns=["Number", "Frequency"])
234
+
235
+ display_hot_cold_tables(hot_df, cold_df)
236
+ display_wheel_table(hot_df, cold_df)
237
 
238
+ #POWER BALL
239
+ elif lotto_type == "PB (Powerball)":
240
+ use_sequence = st.checkbox("🔗 Include Sequential Numbers", value=False)
241
+ if st.button("🎰 Generate Prediction"):
242
+ main_numbers = generate_pb_prediction(pb_df, allow_sequences=use_sequence)
243
+ star_ball = pb_predict_star_ball(pb_df)
244
+ st.success(f"🧠 Predicted Numbers: {main_numbers}")
245
+ st.success(f"🌟 Predicted Powerball Number: [{star_ball}]")
246
+ st.info(f"🔢 Total Sum of Picks: {sum(main_numbers)}")
247
+
248
+ #HOT AND COLD NUMBERS
249
+ hot_df = pd.DataFrame(hot_pb, columns=["Number", "Frequency"])
250
+ cold_df = pd.DataFrame(cold_pb, columns=["Number", "Frequency"])
251
 
252
+ display_hot_cold_tables(hot_df, cold_df)
253
+ display_wheel_table(hot_df, cold_df)
254
 
255
  except FileNotFoundError:
256
  st.error(f"❌ File not found: `{data_path}`")