202 lines
9.4 KiB
Python
202 lines
9.4 KiB
Python
from typing import Dict
|
|
import numpy as np
|
|
from collections import defaultdict
|
|
from sqlalchemy.orm import Session
|
|
from ..models.lottery import SSQLottery, DLTLottery
|
|
|
|
|
|
class AdvancedAnalysisService:
|
|
def __init__(self, db: Session):
|
|
self.db = db
|
|
|
|
def get_missing_value_analysis(self, lottery_type: str, periods: int = 100) -> Dict:
|
|
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
|
recent_draws = self.db.query(model).order_by(
|
|
model.open_time.desc()).limit(periods).all()
|
|
if lottery_type == 'ssq':
|
|
red_range = 33
|
|
blue_range = 16
|
|
else:
|
|
red_range = 35
|
|
blue_range = 12
|
|
red_missing = {i: 0 for i in range(1, red_range + 1)}
|
|
blue_missing = {i: 0 for i in range(1, blue_range + 1)}
|
|
for draw in reversed(recent_draws):
|
|
if lottery_type == 'ssq':
|
|
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
|
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
|
blue_numbers = [draw.blue_ball]
|
|
else:
|
|
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
|
draw.front_ball_4, draw.front_ball_5]
|
|
blue_numbers = [draw.back_ball_1, draw.back_ball_2]
|
|
for num in range(1, red_range + 1):
|
|
if num not in red_numbers:
|
|
red_missing[num] += 1
|
|
for num in range(1, blue_range + 1):
|
|
if num not in blue_numbers:
|
|
blue_missing[num] += 1
|
|
return {
|
|
'red_missing': red_missing,
|
|
'blue_missing': blue_missing,
|
|
'max_red_missing': max(red_missing.values()),
|
|
'max_blue_missing': max(blue_missing.values()),
|
|
'avg_red_missing': sum(red_missing.values()) / len(red_missing),
|
|
'avg_blue_missing': sum(blue_missing.values()) / len(blue_missing)
|
|
}
|
|
|
|
def get_sum_value_analysis(self, lottery_type: str, periods: int = 100) -> Dict:
|
|
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
|
recent_draws = self.db.query(model).order_by(
|
|
model.open_time.desc()).limit(periods).all()
|
|
sums = []
|
|
for draw in recent_draws:
|
|
if lottery_type == 'ssq':
|
|
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
|
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
|
else:
|
|
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
|
draw.front_ball_4, draw.front_ball_5]
|
|
sums.append(sum(red_numbers))
|
|
sum_distribution = defaultdict(int)
|
|
for s in sums:
|
|
sum_distribution[s] += 1
|
|
return {
|
|
'sums': sums,
|
|
'sum_distribution': dict(sum_distribution),
|
|
'min_sum': min(sums),
|
|
'max_sum': max(sums),
|
|
'avg_sum': float(np.mean(sums)),
|
|
'median_sum': float(np.median(sums)),
|
|
'std_sum': float(np.std(sums)),
|
|
'most_common_sums': sorted(sum_distribution.items(), key=lambda x: x[1], reverse=True)[:10]
|
|
}
|
|
|
|
def get_ac_value_analysis(self, lottery_type: str, periods: int = 100) -> Dict:
|
|
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
|
recent_draws = self.db.query(model).order_by(
|
|
model.open_time.desc()).limit(periods).all()
|
|
ac_values = []
|
|
for draw in recent_draws:
|
|
if lottery_type == 'ssq':
|
|
red_numbers = sorted([draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
|
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6])
|
|
else:
|
|
red_numbers = sorted([draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
|
draw.front_ball_4, draw.front_ball_5])
|
|
ac = sum(abs(red_numbers[i+1] - red_numbers[i])
|
|
for i in range(len(red_numbers)-1))
|
|
ac_values.append(ac)
|
|
ac_distribution = defaultdict(int)
|
|
for ac in ac_values:
|
|
ac_distribution[ac] += 1
|
|
return {
|
|
'ac_values': ac_values,
|
|
'ac_distribution': dict(ac_distribution),
|
|
'min_ac': min(ac_values),
|
|
'max_ac': max(ac_values),
|
|
'avg_ac': float(np.mean(ac_values)),
|
|
'median_ac': float(np.median(ac_values)),
|
|
'std_ac': float(np.std(ac_values)),
|
|
'most_common_ac': sorted(ac_distribution.items(), key=lambda x: x[1], reverse=True)[:10]
|
|
}
|
|
|
|
def get_prime_composite_analysis(self, lottery_type: str, periods: int = 100) -> Dict:
|
|
def is_prime(n):
|
|
if n < 2:
|
|
return False
|
|
for i in range(2, int(n**0.5) + 1):
|
|
if n % i == 0:
|
|
return False
|
|
return True
|
|
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
|
recent_draws = self.db.query(model).order_by(
|
|
model.open_time.desc()).limit(periods).all()
|
|
prime_ratios = []
|
|
for draw in recent_draws:
|
|
if lottery_type == 'ssq':
|
|
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
|
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
|
else:
|
|
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
|
draw.front_ball_4, draw.front_ball_5]
|
|
prime_count = sum(1 for num in red_numbers if is_prime(num))
|
|
composite_count = len(red_numbers) - prime_count
|
|
prime_ratios.append(f"{prime_count}:{composite_count}")
|
|
ratio_distribution = defaultdict(int)
|
|
for ratio in prime_ratios:
|
|
ratio_distribution[ratio] += 1
|
|
return {
|
|
'prime_ratios': prime_ratios,
|
|
'ratio_distribution': dict(ratio_distribution),
|
|
'most_common_ratios': sorted(ratio_distribution.items(), key=lambda x: x[1], reverse=True)[:10]
|
|
}
|
|
|
|
def get_road_012_analysis(self, lottery_type: str, periods: int = 100) -> Dict:
|
|
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
|
recent_draws = self.db.query(model).order_by(
|
|
model.open_time.desc()).limit(periods).all()
|
|
road_012_counts = []
|
|
for draw in recent_draws:
|
|
if lottery_type == 'ssq':
|
|
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
|
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
|
else:
|
|
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
|
draw.front_ball_4, draw.front_ball_5]
|
|
road_0 = sum(1 for num in red_numbers if num % 3 == 0)
|
|
road_1 = sum(1 for num in red_numbers if num % 3 == 1)
|
|
road_2 = sum(1 for num in red_numbers if num % 3 == 2)
|
|
road_012_counts.append({
|
|
'road_0': road_0,
|
|
'road_1': road_1,
|
|
'road_2': road_2,
|
|
'pattern': f"{road_0}:{road_1}:{road_2}"
|
|
})
|
|
pattern_distribution = defaultdict(int)
|
|
for count in road_012_counts:
|
|
pattern_distribution[count['pattern']] += 1
|
|
return {
|
|
'road_012_counts': road_012_counts,
|
|
'pattern_distribution': dict(pattern_distribution),
|
|
'most_common_patterns': sorted(pattern_distribution.items(), key=lambda x: x[1], reverse=True)[:10]
|
|
}
|
|
|
|
def get_span_analysis(self, lottery_type: str, periods: int = 100) -> Dict:
|
|
model = SSQLottery if lottery_type == 'ssq' else DLTLottery
|
|
recent_draws = self.db.query(model).order_by(
|
|
model.open_time.desc()).limit(periods).all()
|
|
spans = []
|
|
for draw in recent_draws:
|
|
if lottery_type == 'ssq':
|
|
red_numbers = [draw.red_ball_1, draw.red_ball_2, draw.red_ball_3,
|
|
draw.red_ball_4, draw.red_ball_5, draw.red_ball_6]
|
|
else:
|
|
red_numbers = [draw.front_ball_1, draw.front_ball_2, draw.front_ball_3,
|
|
draw.front_ball_4, draw.front_ball_5]
|
|
span = max(red_numbers) - min(red_numbers)
|
|
spans.append(span)
|
|
span_distribution = defaultdict(int)
|
|
for span in spans:
|
|
span_distribution[span] += 1
|
|
return {
|
|
'spans': spans,
|
|
'span_distribution': dict(span_distribution),
|
|
'min_span': min(spans),
|
|
'max_span': max(spans),
|
|
'avg_span': float(np.mean(spans)),
|
|
'median_span': float(np.median(spans)),
|
|
'std_span': float(np.std(spans)),
|
|
'most_common_spans': sorted(span_distribution.items(), key=lambda x: x[1], reverse=True)[:10]
|
|
}
|
|
|
|
def get_comprehensive_analysis(self, lottery_type: str, periods: int = 100) -> Dict:
|
|
return {
|
|
'missing_value': self.get_missing_value_analysis(lottery_type, periods),
|
|
'sum_value': self.get_sum_value_analysis(lottery_type, periods),
|
|
'ac_value': self.get_ac_value_analysis(lottery_type, periods),
|
|
'prime_composite': self.get_prime_composite_analysis(lottery_type, periods),
|
|
'road_012': self.get_road_012_analysis(lottery_type, periods),
|
|
'span': self.get_span_analysis(lottery_type, periods)
|
|
}
|