Skip to content

Instantly share code, notes, and snippets.

@valentinvieriu
Last active December 19, 2024 14:41
Show Gist options
  • Save valentinvieriu/1d03d272bb5fb8a96fe0b6eb6babba63 to your computer and use it in GitHub Desktop.
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/
// 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