Last active
December 19, 2024 14:41
-
-
Save valentinvieriu/1d03d272bb5fb8a96fe0b6eb6babba63 to your computer and use it in GitHub Desktop.
I use this script to generate Eurojackpot numbers for https://www.lotto-bayern.de/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://lotterycodex.com/eurojackpot-550/ | |
// Generate a unique ticket number | |
const ticketNo = [...Array(7).keys()].map((i) => Math.floor(cryptoRandom() * 9)).join(''); | |
const numberOfTickets = 12; | |
const drawings = [5]; // 5 - Friday; 4 - Wednesday ; 8 - Both | |
// Initialize the data object to be sent to the server | |
let data = { | |
"type": "JS", | |
"game": "EUROJACKPOT", | |
"subGame": "NORMAL", | |
ticketNo, | |
"drawings": [numberOfTickets], | |
"duration": 1, | |
drawings, | |
"price": 2, | |
"fee": 0.5, | |
"predate": null, | |
"additionalLotteries": null, | |
"subscription": null, | |
"cardNo": null, | |
"cardTemplateNo": null, | |
"basketIndex": null, | |
"subscriptionNo": null, | |
"extraRaffle": null, | |
"mainPrognosises": { | |
"EUROJACKPOT": [] | |
} | |
}; | |
// Fetch the historical statistics and generate tickets | |
(async () => { | |
// Fetch the statistics | |
let statsData; | |
try { | |
const statsResponse = await fetch('https://www.lotto-bayern.de/getEurojackpotStatisticsCounts?sorting=number', { | |
headers: { | |
'Accept': 'application/json, text/plain, */*', | |
}, | |
}); | |
if (!statsResponse.ok) { | |
throw new Error('Failed to fetch statistics'); | |
} | |
statsData = await statsResponse.json(); | |
if (!statsData.numbers || !statsData.additionalNumbers) { | |
throw new Error('Invalid statistics data'); | |
} | |
} catch (error) { | |
console.error('Error fetching statistics:', error); | |
return; | |
} | |
// Generate tickets using the statistics and alternating logic | |
for (let index = 0; index < numberOfTickets; index++) { | |
const mainNumbers = generateNumbersWithAlternatingLogic(5, statsData.numbers, 50); | |
const euroNumbers = generateNumbersWithAlternatingLogic(2, statsData.additionalNumbers, 12); | |
data.mainPrognosises.EUROJACKPOT.push({ | |
betModeNo: 4001, | |
prognosises: mainNumbers, | |
additionalPrognosises: euroNumbers, | |
fieldIndex: index | |
}); | |
} | |
console.log('Generated data:', data); | |
// Send requests to the server | |
await fetch("https://www.lotto-bayern.de/deleteTicketFromSession?game=EUROJACKPOT&subgame=NORMAL", { | |
"headers": { | |
"accept": "application/json, text/plain, */*", | |
"content-type": "application/json;charset=UTF-8" | |
}, | |
"method": "POST" | |
}).then(response => { | |
console.log(`deleteTicketFromSession: ${response.status}`); | |
}); | |
await fetch("https://www.lotto-bayern.de/saveTicketInSession", { | |
"headers": { | |
"accept": "application/json, text/plain, */*", | |
"content-type": "application/json;charset=UTF-8" | |
}, | |
"body": `{\"data\":\"${encodeURIComponent(JSON.stringify(data))}"}`, | |
"method": "POST" | |
}).then(response => { | |
console.log(`saveTicketInSession: ${response.status}`); | |
}); | |
})(); | |
/** | |
* Generates numbers based on historical statistics and alternating odd/even and high/low logic. | |
* @param {number} count - Number of numbers to generate. | |
* @param {Array} statsArray - Array of number statistics. | |
* @param {number} maxNumber - The maximum number in the range. | |
* @returns {Array} - An array of generated numbers. | |
*/ | |
function generateNumbersWithAlternatingLogic(count, statsArray, maxNumber) { | |
// Adjust counts and calculate probabilities | |
const adjustedStats = statsArray.map(item => ({ | |
number: item.number, | |
adjustedValue: Math.sqrt(item.value), | |
})); | |
// Categorize numbers into Odd/Even and Low/High | |
const categories = { | |
oddLow: [], | |
evenLow: [], | |
oddHigh: [], | |
evenHigh: [], | |
}; | |
const midpoint = Math.floor(maxNumber / 2); | |
adjustedStats.forEach(item => { | |
const isOdd = item.number % 2 !== 0; | |
const isLow = item.number <= midpoint; | |
let categoryName; | |
if (isOdd && isLow) categoryName = 'oddLow'; | |
else if (!isOdd && isLow) categoryName = 'evenLow'; | |
else if (isOdd && !isLow) categoryName = 'oddHigh'; | |
else categoryName = 'evenHigh'; | |
categories[categoryName].push(item); | |
}); | |
// Normalize probabilities within each category | |
for (const category in categories) { | |
const totalAdjustedValue = categories[category].reduce((sum, item) => sum + item.adjustedValue, 0); | |
categories[category] = categories[category].map(item => ({ | |
number: item.number, | |
probability: item.adjustedValue / totalAdjustedValue, | |
})); | |
} | |
// Define the desired sequence of categories (alternating odd/even and high/low) | |
const sequence = ['oddLow', 'evenHigh', 'evenLow', 'oddHigh']; // Adjust as needed | |
let sequenceIndex = 0; | |
const selectedNumbers = new Set(); | |
// Add debugging | |
console.log('Starting number generation...'); | |
console.log('Categories:', categories); | |
while (selectedNumbers.size < count) { | |
const categoryName = sequence[sequenceIndex % sequence.length]; | |
const categoryNumbers = categories[categoryName]; | |
if (categoryNumbers && categoryNumbers.length > 0) { | |
const number = selectWeightedRandomNumber(categoryNumbers); | |
if (!selectedNumbers.has(number)) { | |
selectedNumbers.add(number); | |
console.log(`Selected number ${number} from category ${categoryName}`); | |
} else { | |
console.log(`Number ${number} already selected, retrying...`); | |
} | |
} else { | |
console.log(`Category ${categoryName} is empty, skipping...`); | |
} | |
sequenceIndex++; | |
} | |
return Array.from(selectedNumbers).sort((a, b) => a - b); | |
} | |
/** | |
* Selects a number from a category based on weighted probabilities. | |
* @param {Array} categoryNumbers - Array of numbers with their probabilities. | |
* @returns {number} - The selected number. | |
*/ | |
function selectWeightedRandomNumber(categoryNumbers) { | |
// Compute cumulative probabilities | |
let cumulativeSum = 0; | |
const cumulativeProbabilities = categoryNumbers.map(item => { | |
cumulativeSum += item.probability; | |
return { | |
number: item.number, | |
cumulativeProbability: cumulativeSum, | |
}; | |
}); | |
// Generate a random number between 0 and cumulativeSum | |
const rand = Math.random() * cumulativeSum; | |
// Select the number based on cumulative probabilities | |
for (const item of cumulativeProbabilities) { | |
if (rand <= item.cumulativeProbability) { | |
return item.number; | |
} | |
} | |
// Fallback in case of rounding errors | |
return categoryNumbers[categoryNumbers.length - 1].number; | |
} | |
/** | |
* Generates a cryptographically secure random number between 0 and 1. | |
* @returns {number} - A random number between 0 and 1. | |
*/ | |
function cryptoRandom() { | |
const typedArray = new Uint8Array(1); | |
const randomValue = crypto.getRandomValues(typedArray)[0]; | |
const randomFloat = randomValue / 255; // Divide by 255 to get a number between 0 and 1 | |
return randomFloat; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you want to improve the script or make it more versatile, you can add features such as saving previous numbers or preventing repetitions. I saw how it was implemented by https://zodiac-casinos.at/ on this site, and it works well. Additionally, if you are using a service like Lotto Bayern to play, make sure your script complies with their format and rules so you don't have any issues entering the numbers.