console
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>双色球智能选号模拟器</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 1000px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
h1 {
color: #e60012;
text-align: center;
}
.container {
background-color: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.section {
margin-bottom: 20px;
padding: 15px;
border: 1px solid #ddd;
border-radius: 5px;
}
.section-title {
font-weight: bold;
margin-bottom: 10px;
color: #e60012;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 15px;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
input {
width: 40px;
text-align: center;
padding: 5px;
}
button {
background-color: #e60012;
color: white;
border: none;
padding: 10px 15px;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
margin: 10px 0;
}
button:hover {
background-color: #c5000f;
}
.result {
background-color: #f9f9f9;
padding: 15px;
border-radius: 5px;
margin-top: 20px;
}
.ball {
display: inline-block;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
line-height: 30px;
margin: 5px;
color: white;
font-weight: bold;
}
.red-ball {
background-color: #e60012;
}
.blue-ball {
background-color: #1e50a2;
}
.flex-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.flex-item {
flex: 1;
min-width: 200px;
}
.analysis-item {
margin-bottom: 8px;
}
label {
display: inline-block;
width: 120px;
margin-right: 10px;
}
select {
padding: 5px;
}
.favorite-balls {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 15px;
}
.favorite-ball {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-weight: bold;
}
.favorite-red {
background-color: #ffebee;
border: 2px solid #e60012;
color: #e60012;
}
.favorite-blue {
background-color: #e3f2fd;
border: 2px solid #1e50a2;
color: #1e50a2;
}
.favorite-red.selected {
background-color: #e60012;
color: white;
}
.favorite-blue.selected {
background-color: #1e50a2;
color: white;
}
.favorite-section {
margin-top: 15px;
}
.add-new-section {
margin-top: 20px;
padding: 15px;
background-color: #e8f5e9;
border-radius: 5px;
}
.recommendation-item {
margin-bottom: 15px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
display: flex;
justify-content: space-between;
align-items: center;
}
.add-new-btn {
background-color: #4caf50;
}
.add-new-btn:hover {
background-color: #388e3c;
}
.tail-number-section {
margin-top: 10px;
}
.tail-number-options {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-top: 5px;
}
.tail-number-option {
padding: 5px 10px;
border: 1px solid #ddd;
border-radius: 3px;
cursor: pointer;
}
.tail-number-option.selected {
background-color: #e60012;
color: white;
border-color: #e60012;
}
</style>
</head>
<body>
<div class="container">
<h1>双色球智能选号模拟器</h1>
<div class="section">
<div class="section-title">历史数据输入 (最近30期)</div>
<table id="history-table">
<thead>
<tr>
<th>期号</th>
<th>红球1</th>
<th>红球2</th>
<th>红球3</th>
<th>红球4</th>
<th>红球5</th>
<th>红球6</th>
<th>蓝球</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<div class="section favorite-section">
<div class="section-title">自选号码</div>
<p>请选择您看好的号码(点击号码即可选择/取消选择):</p>
<div>
<h3>红球(1-33):</h3>
<div class="favorite-balls" id="favorite-red">
</div>
</div>
<div>
<h3>蓝球(1-16):</h3>
<div class="favorite-balls" id="favorite-blue">
</div>
</div>
<div>
<h3>已选号码:</h3>
<div id="selected-balls">
红球:<span id="selected-red"></span><br>
蓝球:<span id="selected-blue"></span>
</div>
</div>
</div>
<div class="section">
<div class="section-title">分析参数设置</div>
<div class="flex-container">
<div class="flex-item">
<div class="analysis-item">
<label for="size-ratio">红球大小比:</label>
<select id="size-ratio">
<option value="any">任意</option>
<option value="3:3">3:3</option>
<option value="4:2">4:2</option>
<option value="2:4">2:4</option>
<option value="5:1">5:1</option>
<option value="1:5">1:5</option>
</select>
</div>
<div class="analysis-item">
<label for="area-ratio">红球区域比:</label>
<select id="area-ratio">
<option value="any">任意</option>
<option value="2:2:2">2:2:2</option>
<option value="3:2:1">3:2:1</option>
<option value="1:3:2">1:3:2</option>
<option value="2:1:3">2:1:3</option>
<option value="3:1:2">3:1:2</option>
<option value="1:2:3">1:2:3</option>
</select>
</div>
<div class="analysis-item">
<label for="odd-even">红球奇偶比:</label>
<select id="odd-even">
<option value="any">任意</option>
<option value="3:3">3:3</option>
<option value="4:2">4:2</option>
<option value="2:4">2:4</option>
<option value="5:1">5:1</option>
<option value="1:5">1:5</option>
</select>
</div>
</div>
<div class="flex-item">
<div class="analysis-item">
<label for="sum-range">红球和值范围:</label>
<input type="number" id="sum-min" min="21" max="183" value="70"> -
<input type="number" id="sum-max" min="21" max="183" value="120">
</div>
<div class="analysis-item">
<label for="span-range">红球跨度范围:</label>
<input type="number" id="span-min" min="5" max="32" value="20"> -
<input type="number" id="span-max" min="5" max="32" value="30">
</div>
<div class="analysis-item">
<label for="repeat-num">与上期重复数:</label>
<select id="repeat-num">
<option value="any">任意</option>
<option value="0">0个</option>
<option value="1">1个</option>
<option value="2">2个</option>
<option value="3">3个</option>
</select>
</div>
</div>
<div class="flex-item">
<div class="analysis-item">
<label for="prime-ratio">红球质合比:</label>
<select id="prime-ratio">
<option value="any">任意</option>
<option value="2:4">2:4</option>
<option value="3:3">3:3</option>
<option value="1:5">1:5</option>
<option value="4:2">4:2</option>
</select>
</div>
<div class="analysis-item">
<label for="serial-num">连号数量:</label>
<select id="serial-num">
<option value="any">任意</option>
<option value="0">无连号</option>
<option value="1">1组连号</option>
<option value="2">2组连号</option>
</select>
</div>
<div class="analysis-item">
<label for="blue-size">蓝球大小:</label>
<select id="blue-size">
<option value="any">任意</option>
<option value="small">小(1-9)</option>
<option value="big">大(10-16)</option>
</select>
</div>
</div>
</div>
<div class="tail-number-section">
<div class="analysis-item">
<label for="tail-number">红球尾号选择:</label>
<select id="tail-number-mode">
<option value="any">任意尾号</option>
<option value="include">包含以下尾号</option>
<option value="exclude">排除以下尾号</option>
</select>
</div>
<div class="tail-number-options" id="tail-number-options">
</div>
<div class="analysis-item">
<label for="tail-number-count">尾号数量:</label>
<select id="tail-number-count">
<option value="any">任意</option>
<option value="3">3个不同尾号</option>
<option value="4">4个不同尾号</option>
<option value="5">5个不同尾号</option>
<option value="6">6个不同尾号</option>
</select>
</div>
</div>
<div class="analysis-item">
<label for="favorite-weight">自选号码权重:</label>
<select id="favorite-weight">
<option value="low">低 (优先考虑分析结果)</option>
<option value="medium" selected>中 (平衡自选和分析)</option>
<option value="high">高 (优先考虑自选号码)</option>
</select>
</div>
</div>
<button id="generate-btn">生成推荐号码</button>
<div class="section result" id="result-section" style="display: none;">
<div class="section-title">推荐号码</div>
<div id="recommendations"></div>
<div class="add-new-section" id="add-new-section" style="display: none;">
<div class="section-title">添加到历史数据</div>
<div id="add-new-options"></div>
</div>
<div class="section-title" style="margin-top: 20px;">分析结果</div>
<div id="analysis-results"></div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const tbody = document.querySelector('#history-table tbody');
for (let i = 0; i < 30; i++) {
const row = document.createElement('tr');
const periodCell = document.createElement('td');
periodCell.textContent = `第${2023001 + i}期`;
const cells = [];
for (let j = 0; j < 6; j++) {
const cell = document.createElement('td');
const input = document.createElement('input');
input.type = 'number';
input.min = '1';
input.max = '33';
input.className = 'red-input';
cell.appendChild(input);
cells.push(cell);
}
const blueCell = document.createElement('td');
const blueInput = document.createElement('input');
blueInput.type = 'number';
blueInput.min = '1';
blueInput.max = '16';
blueInput.className = 'blue-input';
blueCell.appendChild(blueInput);
const actionCell = document.createElement('td');
if (i === 29) {
const addBtn = document.createElement('button');
addBtn.textContent = '新增';
addBtn.className = 'add-new-btn';
addBtn.addEventListener('click', function() {
addNewRow();
});
actionCell.appendChild(addBtn);
}
row.appendChild(periodCell);
cells.forEach(cell => row.appendChild(cell));
row.appendChild(blueCell);
row.appendChild(actionCell);
tbody.appendChild(row);
}
const favoriteRed = document.getElementById('favorite-red');
const favoriteBlue = document.getElementById('favorite-blue');
for (let i = 1; i <= 33; i++) {
const ball = document.createElement('div');
ball.className = 'favorite-ball favorite-red';
ball.textContent = i;
ball.dataset.number = i;
ball.addEventListener('click', function() {
this.classList.toggle('selected');
updateSelectedBalls();
});
favoriteRed.appendChild(ball);
}
for (let i = 1; i <= 16; i++) {
const ball = document.createElement('div');
ball.className = 'favorite-ball favorite-blue';
ball.textContent = i;
ball.dataset.number = i;
ball.addEventListener('click', function() {
this.classList.toggle('selected');
updateSelectedBalls();
});
favoriteBlue.appendChild(ball);
}
const tailNumberOptions = document.getElementById('tail-number-options');
for (let i = 0; i <= 9; i++) {
const option = document.createElement('div');
option.className = 'tail-number-option';
option.textContent = i;
option.dataset.tail = i;
option.addEventListener('click', function() {
this.classList.toggle('selected');
});
tailNumberOptions.appendChild(option);
}
document.getElementById('generate-btn').addEventListener('click', generateRecommendations);
});
function addNewRow() {
const tbody = document.querySelector('#history-table tbody');
const rows = tbody.querySelectorAll('tr');
const lastPeriod = parseInt(rows[rows.length - 1].cells[0].textContent.match(/\d+/)[0]);
const newRow = document.createElement('tr');
const periodCell = document.createElement('td');
periodCell.textContent = `第${lastPeriod + 1}期`;
for (let i = 0; i < 6; i++) {
const cell = document.createElement('td');
const input = document.createElement('input');
input.type = 'number';
input.min = '1';
input.max = '33';
input.className = 'red-input';
cell.appendChild(input);
newRow.appendChild(cell);
}
const blueCell = document.createElement('td');
const blueInput = document.createElement('input');
blueInput.type = 'number';
blueInput.min = '1';
blueInput.max = '16';
blueInput.className = 'blue-input';
blueCell.appendChild(blueInput);
newRow.appendChild(blueCell);
const actionCell = document.createElement('td');
const addBtn = document.createElement('button');
addBtn.textContent = '新增';
addBtn.className = 'add-new-btn';
addBtn.addEventListener('click', function() {
addNewRow();
});
actionCell.appendChild(addBtn);
newRow.appendChild(actionCell);
newRow.insertBefore(periodCell, newRow.firstChild);
tbody.removeChild(rows[0]);
tbody.appendChild(newRow);
}
function addToHistory(redBalls, blueBall) {
const tbody = document.querySelector('#history-table tbody');
const rows = tbody.querySelectorAll('tr');
const lastPeriod = parseInt(rows[rows.length - 1].cells[0].textContent.match(/\d+/)[0]);
const newRow = document.createElement('tr');
const periodCell = document.createElement('td');
periodCell.textContent = `第${lastPeriod + 1}期`;
for (let i = 0; i < 6; i++) {
const cell = document.createElement('td');
const input = document.createElement('input');
input.type = 'number';
input.min = '1';
input.max = '33';
input.value = redBalls[i];
input.className = 'red-input';
cell.appendChild(input);
newRow.appendChild(cell);
}
const blueCell = document.createElement('td');
const blueInput = document.createElement('input');
blueInput.type = 'number';
blueInput.min = '1';
blueInput.max = '16';
blueInput.value = blueBall;
blueInput.className = 'blue-input';
blueCell.appendChild(blueInput);
newRow.appendChild(blueCell);
const actionCell = document.createElement('td');
const addBtn = document.createElement('button');
addBtn.textContent = '新增';
addBtn.className = 'add-new-btn';
addBtn.addEventListener('click', function() {
addNewRow();
});
actionCell.appendChild(addBtn);
newRow.appendChild(actionCell);
newRow.insertBefore(periodCell, newRow.firstChild);
tbody.removeChild(rows[0]);
tbody.appendChild(newRow);
alert('已成功添加到历史数据底部,并移除最早的一期!');
}
function updateSelectedBalls() {
const selectedRed = [];
const selectedBlue = [];
document.querySelectorAll('.favorite-red.selected').forEach(ball => {
selectedRed.push(ball.dataset.number);
});
document.querySelectorAll('.favorite-blue.selected').forEach(ball => {
selectedBlue.push(ball.dataset.number);
});
document.getElementById('selected-red').textContent = selectedRed.join(', ') || '无';
document.getElementById('selected-blue').textContent = selectedBlue.join(', ') || '无';
}
function getFavoriteBalls() {
const favoriteRed = [];
const favoriteBlue = [];
document.querySelectorAll('.favorite-red.selected').forEach(ball => {
favoriteRed.push(parseInt(ball.dataset.number));
});
document.querySelectorAll('.favorite-blue.selected').forEach(ball => {
favoriteBlue.push(parseInt(ball.dataset.number));
});
return {
red: favoriteRed,
blue: favoriteBlue
};
}
function getTailNumberSettings() {
const mode = document.getElementById('tail-number-mode').value;
const selectedTails = [];
document.querySelectorAll('.tail-number-option.selected').forEach(option => {
selectedTails.push(parseInt(option.dataset.tail));
});
const tailCount = document.getElementById('tail-number-count').value;
return {
mode: mode,
tails: selectedTails,
count: tailCount
};
}
function generateRecommendations() {
const historyData = [];
const rows = document.querySelectorAll('#history-table tbody tr');
rows.forEach(row => {
const inputs = row.querySelectorAll('input');
const redBalls = [];
for (let i = 0; i < 6; i++) {
const value = parseInt(inputs[i].value);
if (!isNaN(value) && value >= 1 && value <= 33) {
redBalls.push(value);
}
}
const blueBall = parseInt(inputs[6].value);
if (redBalls.length === 6 && !isNaN(blueBall) && blueBall >= 1 && blueBall <= 16) {
historyData.push({
red: redBalls.sort((a, b) => a - b),
blue: blueBall
});
}
});
if (historyData.length < 5) {
alert('请至少输入5期完整的历史数据!');
return;
}
const favoriteBalls = getFavoriteBalls();
const tailSettings = getTailNumberSettings();
const analysis = analyzeHistory(historyData);
const params = {
sizeRatio: document.getElementById('size-ratio').value,
areaRatio: document.getElementById('area-ratio').value,
oddEven: document.getElementById('odd-even').value,
sumMin: parseInt(document.getElementById('sum-min').value),
sumMax: parseInt(document.getElementById('sum-max').value),
spanMin: parseInt(document.getElementById('span-min').value),
spanMax: parseInt(document.getElementById('span-max').value),
repeatNum: document.getElementById('repeat-num').value,
primeRatio: document.getElementById('prime-ratio').value,
serialNum: document.getElementById('serial-num').value,
blueSize: document.getElementById('blue-size').value,
favoriteWeight: document.getElementById('favorite-weight').value,
tailSettings: tailSettings
};
const recommendations = [];
for (let i = 0; i < 5; i++) {
const recommendation = generateNumber(historyData, analysis, params, favoriteBalls);
recommendations.push(recommendation);
}
displayResults(recommendations, analysis);
}
function analyzeHistory(data) {
const analysis = {
hotRed: Array(33).fill(0),
coldRed: Array(33).fill(0),
hotBlue: Array(16).fill(0),
coldBlue: Array(16).fill(0),
sizeRatioStats: { '3:3': 0, '4:2': 0, '2:4': 0, '5:1': 0, '1:5': 0 },
areaRatioStats: { '2:2:2': 0, '3:2:1': 0, '1:3:2': 0, '2:1:3': 0, '3:1:2': 0, '1:2:3': 0 },
oddEvenStats: { '3:3': 0, '4:2': 0, '2:4': 0, '5:1': 0, '1:5': 0 },
primeRatioStats: { '2:4': 0, '3:3': 0, '1:5': 0, '4:2': 0 },
sumStats: { min: 183, max: 21, avg: 0 },
spanStats: { min: 32, max: 5, avg: 0 },
repeatStats: { 0: 0, 1: 0, 2: 0, 3: 0 },
serialStats: { 0: 0, 1: 0, 2: 0 },
blueSizeStats: { small: 0, big: 0 },
blueOddEvenStats: { odd: 0, even: 0 },
tailStats: Array(10).fill(0)
};
let totalSum = 0;
let totalSpan = 0;
data.forEach(item => {
item.red.forEach(num => {
analysis.hotRed[num - 1]++;
const tail = num % 10;
analysis.tailStats[tail]++;
});
analysis.hotBlue[item.blue - 1]++;
});
const redAvg = data.length * 6 / 33;
const blueAvg = data.length / 16;
analysis.hotRed = analysis.hotRed.map((count, index) => count > redAvg ? index + 1 : 0).filter(num => num > 0);
analysis.coldRed = analysis.hotRed.map((count, index) => count <= redAvg ? index + 1 : 0).filter(num => num > 0);
analysis.hotBlue = analysis.hotBlue.map((count, index) => count > blueAvg ? index + 1 : 0).filter(num => num > 0);
analysis.coldBlue = analysis.hotBlue.map((count, index) => count <= blueAvg ? index + 1 : 0).filter(num => num > 0);
data.forEach((item, index) => {
const red = item.red;
const big = red.filter(num => num > 16).length;
const small = 6 - big;
const sizeRatio = `${big}:${small}`;
if (analysis.sizeRatioStats[sizeRatio] !== undefined) {
analysis.sizeRatioStats[sizeRatio]++;
}
const area1 = red.filter(num => num <= 9).length;
const area2 = red.filter(num => num > 9 && num <= 19).length;
const area3 = red.filter(num => num > 19).length;
const areaRatio = `${area1}:${area2}:${area3}`;
if (analysis.areaRatioStats[areaRatio] !== undefined) {
analysis.areaRatioStats[areaRatio]++;
}
const odd = red.filter(num => num % 2 === 1).length;
const even = 6 - odd;
const oddEven = `${odd}:${even}`;
if (analysis.oddEvenStats[oddEven] !== undefined) {
analysis.oddEvenStats[oddEven]++;
}
const primes = [2,3,5,7,11,13,17,19,23,29,31];
const prime = red.filter(num => primes.includes(num)).length;
const composite = 6 - prime;
const primeRatio = `${prime}:${composite}`;
if (analysis.primeRatioStats[primeRatio] !== undefined) {
analysis.primeRatioStats[primeRatio]++;
}
const sum = red.reduce((a, b) => a + b, 0);
totalSum += sum;
analysis.sumStats.min = Math.min(analysis.sumStats.min, sum);
analysis.sumStats.max = Math.max(analysis.sumStats.max, sum);
const span = red[5] - red[0];
totalSpan += span;
analysis.spanStats.min = Math.min(analysis.spanStats.min, span);
analysis.spanStats.max = Math.max(analysis.spanStats.max, span);
if (index > 0) {
const prevRed = data[index - 1].red;
const repeat = red.filter(num => prevRed.includes(num)).length;
if (analysis.repeatStats[repeat] !== undefined) {
analysis.repeatStats[repeat]++;
}
}
let serialCount = 0;
for (let i = 1; i < 6; i++) {
if (red[i] === red[i-1] + 1) {
serialCount++;
}
}
const serialGroups = serialCount > 2 ? 2 : serialCount;
if (analysis.serialStats[serialGroups] !== undefined) {
analysis.serialStats[serialGroups]++;
}
if (item.blue <= 9) {
analysis.blueSizeStats.small++;
} else {
analysis.blueSizeStats.big++;
}
if (item.blue % 2 === 1) {
analysis.blueOddEvenStats.odd++;
} else {
analysis.blueOddEvenStats.even++;
}
});
analysis.sumStats.avg = Math.round(totalSum / data.length);
analysis.spanStats.avg = Math.round(totalSpan / data.length);
return analysis;
}
function generateNumber(history, analysis, params, favoriteBalls) {
let valid = false;
let redBalls = [];
let blueBall = 0;
while (!valid) {
redBalls = generateRedBalls(history, analysis, params, favoriteBalls);
blueBall = generateBlueBall(history, analysis, params, favoriteBalls);
valid = true;
for (const item of history) {
const sameRed = item.red.every((num, index) => num === redBalls[index]);
if (sameRed && item.blue === blueBall) {
valid = false;
break;
}
}
}
return {
red: redBalls,
blue: blueBall
};
}
function generateRedBalls(history, analysis, params, favoriteBalls) {
let redBalls = [];
let valid = false;
while (!valid) {
redBalls = [];
let useFavoriteRatio = 0.5;
if (params.favoriteWeight === 'low') useFavoriteRatio = 0.3;
if (params.favoriteWeight === 'high') useFavoriteRatio = 0.7;
if (favoriteBalls.red.length > 0 && Math.random() < useFavoriteRatio) {
const favoriteCount = Math.min(
Math.floor(Math.random() * 4) + 1,
favoriteBalls.red.length
);
const shuffledFavorites = [...favoriteBalls.red].sort(() => 0.5 - Math.random());
for (let i = 0; i < favoriteCount && redBalls.length < 6; i++) {
if (!redBalls.includes(shuffledFavorites[i])) {
redBalls.push(shuffledFavorites[i]);
}
}
}
if (redBalls.length < 6) {
const hotColdRatio = Math.random();
const useHot = hotColdRatio > 0.3;
let pool = useHot ? [...analysis.hotRed] : [...analysis.coldRed];
if (pool.length < 6) {
pool.push(...analysis.hotRed);
}
while (redBalls.length < 6 && pool.length > 0) {
const randomIndex = Math.floor(Math.random() * pool.length);
const num = pool[randomIndex];
if (!redBalls.includes(num)) {
redBalls.push(num);
}
pool.splice(randomIndex, 1);
}
}
if (redBalls.length < 6) {
const allNumbers = Array.from({length: 33}, (_, i) => i + 1).filter(n => !redBalls.includes(n));
while (redBalls.length < 6 && allNumbers.length > 0) {
const randomIndex = Math.floor(Math.random() * allNumbers.length);
redBalls.push(allNumbers[randomIndex]);
allNumbers.splice(randomIndex, 1);
}
}
redBalls.sort((a, b) => a - b);
valid = checkRedConditions(redBalls, history[history.length - 1].red, params);
}
return redBalls;
}
function checkRedConditions(redBalls, lastRed, params) {
const big = redBalls.filter(num => num > 16).length;
const small = 6 - big;
const sizeRatio = `${big}:${small}`;
if (params.sizeRatio !== 'any' && sizeRatio !== params.sizeRatio) {
return false;
}
const area1 = redBalls.filter(num => num <= 9).length;
const area2 = redBalls.filter(num => num > 9 && num <= 19).length;
const area3 = redBalls.filter(num => num > 19).length;
const areaRatio = `${area1}:${area2}:${area3}`;
if (params.areaRatio !== 'any' && areaRatio !== params.areaRatio) {
return false;
}
const odd = redBalls.filter(num => num % 2 === 1).length;
const even = 6 - odd;
const oddEven = `${odd}:${even}`;
if (params.oddEven !== 'any' && oddEven !== params.oddEven) {
return false;
}
const sum = redBalls.reduce((a, b) => a + b, 0);
if (sum < params.sumMin || sum > params.sumMax) {
return false;
}
const span = redBalls[5] - redBalls[0];
if (span < params.spanMin || span > params.spanMax) {
return false;
}
if (params.repeatNum !== 'any') {
const repeat = redBalls.filter(num => lastRed.includes(num)).length;
if (parseInt(params.repeatNum) !== repeat) {
return false;
}
}
const primes = [2,3,5,7,11,13,17,19,23,29,31];
const prime = redBalls.filter(num => primes.includes(num)).length;
const composite = 6 - prime;
const primeRatio = `${prime}:${composite}`;
if (params.primeRatio !== 'any' && primeRatio !== params.primeRatio) {
return false;
}
let serialCount = 0;
for (let i = 1; i < 6; i++) {
if (redBalls[i] === redBalls[i-1] + 1) {
serialCount++;
}
}
const serialGroups = serialCount > 2 ? 2 : serialCount;
if (params.serialNum !== 'any' && serialGroups !== parseInt(params.serialNum)) {
return false;
}
const tailSettings = params.tailSettings;
if (tailSettings.mode !== 'any' && tailSettings.tails.length > 0) {
const tailsInBalls = new Set();
redBalls.forEach(num => {
tailsInBalls.add(num % 10);
});
if (tailSettings.mode === 'include') {
for (const tail of tailSettings.tails) {
if (!tailsInBalls.has(tail)) {
return false;
}
}
} else if (tailSettings.mode === 'exclude') {
for (const tail of tailSettings.tails) {
if (tailsInBalls.has(tail)) {
return false;
}
}
}
if (tailSettings.count !== 'any') {
const requiredCount = parseInt(tailSettings.count);
if (tailsInBalls.size !== requiredCount) {
return false;
}
}
}
return true;
}
function generateBlueBall(history, analysis, params, favoriteBalls) {
let blueBall = 0;
let valid = false;
while (!valid) {
if (favoriteBalls.blue.length > 0) {
const useFavorite = Math.random() < 0.7;
if (useFavorite) {
const randomIndex = Math.floor(Math.random() * favoriteBalls.blue.length);
blueBall = favoriteBalls.blue[randomIndex];
valid = true;
continue;
}
}
if (params.blueSize === 'small') {
blueBall = Math.floor(Math.random() * 9) + 1;
} else if (params.blueSize === 'big') {
blueBall = Math.floor(Math.random() * 7) + 10;
} else {
blueBall = Math.floor(Math.random() * 16) + 1;
}
valid = true;
}
return blueBall;
}
function displayResults(recommendations, analysis) {
const resultSection = document.getElementById('result-section');
const recommendationsDiv = document.getElementById('recommendations');
const addNewSection = document.getElementById('add-new-section');
const addNewOptions = document.getElementById('add-new-options');
const analysisDiv = document.getElementById('analysis-results');
recommendationsDiv.innerHTML = '';
addNewOptions.innerHTML = '';
recommendations.forEach((item, index) => {
const recDiv = document.createElement('div');
recDiv.style.marginBottom = '15px';
const title = document.createElement('span');
title.textContent = `推荐 ${index + 1}: `;
title.style.fontWeight = 'bold';
recDiv.appendChild(title);
item.red.forEach(num => {
const ball = document.createElement('span');
ball.className = 'ball red-ball';
ball.textContent = num;
recDiv.appendChild(ball);
});
const blueBall = document.createElement('span');
blueBall.className = 'ball blue-ball';
blueBall.textContent = item.blue;
recDiv.appendChild(blueBall);
const tails = new Set();
item.red.forEach(num => {
tails.add(num % 10);
});
const tailInfo = document.createElement('div');
tailInfo.style.marginTop = '5px';
tailInfo.style.fontSize = '14px';
tailInfo.style.color = '#666';
tailInfo.textContent = `尾号: ${Array.from(tails).sort((a, b) => a - b).join(', ')} (共${tails.size}个不同尾号)`;
recDiv.appendChild(tailInfo);
recommendationsDiv.appendChild(recDiv);
const optionDiv = document.createElement('div');
optionDiv.className = 'recommendation-item';
const ballsDiv = document.createElement('div');
item.red.forEach(num => {
const ball = document.createElement('span');
ball.className = 'ball red-ball';
ball.textContent = num;
ballsDiv.appendChild(ball);
});
const blue = document.createElement('span');
blue.className = 'ball blue-ball';
blue.textContent = item.blue;
ballsDiv.appendChild(blue);
const addBtn = document.createElement('button');
addBtn.textContent = '添加这组号码';
addBtn.className = 'add-new-btn';
addBtn.addEventListener('click', function() {
addToHistory(item.red, item.blue);
});
optionDiv.appendChild(ballsDiv);
optionDiv.appendChild(addBtn);
addNewOptions.appendChild(optionDiv);
});
analysisDiv.innerHTML = '';
addAnalysisItem(analysisDiv, '大小比统计', analysis.sizeRatioStats);
addAnalysisItem(analysisDiv, '区域比统计', analysis.areaRatioStats);
addAnalysisItem(analysisDiv, '奇偶比统计', analysis.oddEvenStats);
addAnalysisItem(analysisDiv, '质合比统计', analysis.primeRatioStats);
analysisDiv.innerHTML += `
<div class="analysis-item"><strong>和值统计:</strong> 最小 ${analysis.sumStats.min}, 最大 ${analysis.sumStats.max}, 平均 ${analysis.sumStats.avg}</div>
`;
analysisDiv.innerHTML += `
<div class="analysis-item"><strong>跨度统计:</strong> 最小 ${analysis.spanStats.min}, 最大 ${analysis.spanStats.max}, 平均 ${analysis.spanStats.avg}</div>
`;
addAnalysisItem(analysisDiv, '与上期重复数统计', analysis.repeatStats);
addAnalysisItem(analysisDiv, '连号组数统计', analysis.serialStats);
addAnalysisItem(analysisDiv, '蓝球大小统计', analysis.blueSizeStats);
addAnalysisItem(analysisDiv, '蓝球奇偶统计', analysis.blueOddEvenStats);
let tailStatsHtml = '<div class="analysis-item"><strong>尾号出现频率:</strong><br>';
for (let i = 0; i <= 9; i++) {
tailStatsHtml += `${i}: ${analysis.tailStats[i]}次 | `;
if (i === 4) tailStatsHtml += '<br>';
}
tailStatsHtml += '</div>';
analysisDiv.innerHTML += tailStatsHtml;
analysisDiv.innerHTML += `
<div class="analysis-item"><strong>红球热号:</strong> ${analysis.hotRed.join(', ')}</div>
<div class="analysis-item"><strong>红球冷号:</strong> ${analysis.coldRed.join(', ')}</div>
<div class="analysis-item"><strong>蓝球热号:</strong> ${analysis.hotBlue.join(', ')}</div>
<div class="analysis-item"><strong>蓝球冷号:</strong> ${analysis.coldBlue.join(', ')}</div>
`;
resultSection.style.display = 'block';
addNewSection.style.display = 'block';
}
function addAnalysisItem(container, title, stats) {
let html = `<div class="analysis-item"><strong>${title}:</strong> `;
const items = [];
for (const key in stats) {
items.push(`${key} (${stats[key]}次)`);
}
html += items.join(', ') + '</div>';
container.innerHTML += html;
}
</script>
</body>
</html>