import template from '../templates/weighted-working-groups/working-group-block.mustache' const defaultOptions = { count: 1, wrapperClass: '' } // Working groups with a weight of -1 will not be displayed. const weights = { default: -1, 'jakarta-ee': 1, sdv: 20, 'cloud-development-tools': 30, adoptium: 38, oniro: 38, 'eclipse-ide': 44, 'internet-things-iot': 44, aice: 50, asciidoc: 50, 'edge-native': 50, microprofile: 50, openmobility: 50, osgi: 50, sparkplug: 50, }; const fallbackLogos = { sdv: '/images/collaborations/logos/software-defined-vehicle-fallback.png' } const removeDuplicates = (value, index, self) => self.indexOf(value) === index; const getWeightedRandomIndex = (weightBuckets, categorizedArrayByWeight) => { const largestWeight = Object.values(weights).sort().at(-1); const randomNumber = Math.floor(Math.random() * largestWeight); // Returns whatever number is the closest to a weight bucket const closest = Object.values(weights).reduce((prev, curr) => { return (Math.abs(curr - randomNumber) < Math.abs(prev - randomNumber) ? curr : prev); }) const weightBucketSelectionIndex = weightBuckets.indexOf(closest); const weightBucketSelection = weightBuckets[weightBucketSelectionIndex]; const selectionIndex = Math.floor(Math.random() * categorizedArrayByWeight[weightBucketSelection].length); return categorizedArrayByWeight[weightBucketSelection][selectionIndex]; } function getUniqueRandomWorkingGroups(workingGroupsCategorizedByWeight, weightBuckets, count) { // Creates a set of selected working groups. This will omit duplicates. let selectionSet = new Set(); while (selectionSet.size < count) { const randomWorkingGroup = getWeightedRandomIndex(weightBuckets, workingGroupsCategorizedByWeight); if (selectionSet.has(randomWorkingGroup)) continue; selectionSet.add(randomWorkingGroup); } return Array.from(selectionSet); } async function getWeightedRandomWorkingGroups(count) { const cachedWorkingGroups = JSON.parse(sessionStorage.getItem('weighted-working-groups')); const isCached = cachedWorkingGroups != null; // Only return the cached working groups if the count hasn't changed since last time run if (isCached && cachedWorkingGroups.length === count) return cachedWorkingGroups; const response = await fetch('https://membership.eclipse.org/api/working_groups'); const workingGroups = await response.json(); const weightBuckets = Object .values(weights) .filter(removeDuplicates); // Create an object where the key is a bucket (or weight), and the value an array of working groups tied to that bucket const weightBucketObject = weightBuckets.reduce((acc, bucket) => ({...acc, [bucket]: [] }), {}) const workingGroupsCategorizedByWeight = workingGroups.reduce((acc, wg) => { const weight = weights[wg.alias] || weights.default; acc[weight].push(wg); return acc; }, { ...weightBucketObject }); // Retrieves weighted random working groups and stores it in session storage cache const randomWorkingGroups = getUniqueRandomWorkingGroups(workingGroupsCategorizedByWeight, weightBuckets, count); sessionStorage.setItem('weighted-working-groups', JSON.stringify(randomWorkingGroups)); return randomWorkingGroups; }; const matchHeightForLogos = (baseElement) => { const imgElements = baseElement.querySelectorAll('.weighted-working-group-logo'); imgElements.forEach(el => { el.addEventListener('load', () => { $('.weighted-working-group-block-wrapper').matchHeight(); }); }); } const getWorkingGroupLogo = ({ alias, logo } = workingGroup) => { const fallbackLogo = fallbackLogos[alias]; if (logo === '') return fallbackLogo || ''; return logo; } (async function renderWeightedWorkingGroups() { const element = document.querySelector('.eclipsefdn-weighted-working-groups'); if (!element) return; const options = { ...defaultOptions, ...element.dataset, count: +element.dataset.count }; element.innerHTML = template({ isFetching: true, items: new Array(options.count) , wrapperClass: options.wrapperClass }) const workingGroups = await getWeightedRandomWorkingGroups(options.count); const data = { isFetching: false, wrapperClass: options.wrapperClass, items: workingGroups.map(wg => ({ title: wg.title, logo: getWorkingGroupLogo(wg), websiteUrl: wg.resources.website, })) }; element.innerHTML = template(data); matchHeightForLogos(element); })();