mottery/backend/app/services/advanced_analysis.py

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)
}