You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
5.2 KiB

window.glmdev = window.glmdev || {}
window.glmdev.themeStats = window.glmdev.themeStats || []
window.glmdev.taglines = [
'...is proud that this site is Google-free',
'...is a supporter of FLOSS',
'...prefers TypeScript, but C++ will do',
'...occasionally rants about dependency injection',
'...loves GNU/Linux',
'(or as I\'ve recently taken to calling it, GNU+Linux)',
'...uses spaces, not tabs',
'...self-hosts all the things',
'...uses the Oxford comma',
'...occasionally does contract work',
'...reads the terms and conditions',
'...is an RSS nerd',
'...just lost the game',
'...listens to indie music',
'...is running out of tag-line ideas',
`copyright © ${(new Date()).getFullYear()}`,
]
document.querySelector('#tagline')
?.addEventListener('click', event => {
if ( typeof glmdev.tagline_index === 'undefined' ) glmdev.tagline_index = 0
else if ( glmdev.tagline_index === glmdev.taglines.length - 1 ) glmdev.tagline_index = 0
else glmdev.tagline_index += 1
document.querySelector('#tagline').innerHTML = glmdev.taglines[glmdev.tagline_index]
})
document.querySelector('#timeline-view-all')
?.addEventListener('click', event => {
const hidden = document.querySelectorAll('.work-container.theme-hide')
for ( const item of hidden ) {
item.classList.remove('theme-hide')
}
document.querySelector('#timeline-view-all').classList.add('theme-hide')
}, false)
function getRandomArbitrary(min, max) {
min = Math.ceil(min)
max = Math.floor(max)
return Math.floor(Math.random() * (max - min + 1)) + min
}
const calculateMean = (values) => {
return (values.reduce((sum, current) => sum + current)) / values.length;
}
const calculateVariance = (values) => {
const average = calculateMean(values);
const squareDiffs = values.map((value) => {
const diff = value - average;
return diff * diff;
});
return calculateMean(squareDiffs);
}
const calculateStdev = (values) => {
return Math.sqrt(calculateVariance(values))
}
function calculateDistance(ax, ay, bx, by) {
return Math.sqrt(Math.pow(ax-bx, 2) + Math.pow(ay-by, 2))
}
function placeStars() {
const widths = []
const heights = []
document.querySelectorAll('.stars svg')
.forEach(function(star) {
var width = window.innerWidth - 50
var height = (window.innerHeight / 3) - 50
var widthOffset = getRandomArbitrary(50, width)
var heightOffset = getRandomArbitrary(50, height)
star.style.left = widthOffset + 'px'
star.style.top = heightOffset + 'px'
widths.push(widthOffset)
heights.push(heightOffset)
})
return [widths, heights]
}
function isGoodStarPattern(widths, heights) {
const starCount = document.querySelectorAll('.stars svg').length
const minWidthStdev = window.innerWidth / (starCount / 1.5)
const widthStdev = calculateStdev(widths)
const minHeightStdev = (window.innerHeight / 3) / (starCount)
const heightStdev = calculateStdev(heights)
const [centroidWidth, centroidHeight] = [window.innerWidth / 2, (window.innerHeight / 3) / 2]
const distances = widths.map((w, i) => [w, heights[i]])
.map(([w, h]) => calculateDistance(w, h, centroidWidth, centroidHeight))
const minDistanceStdev = Math.min(window.innerWidth, window.innerHeight) / 10
const distanceStdev = calculateStdev(distances)
return widthStdev > minWidthStdev && heightStdev > minHeightStdev && distanceStdev > minDistanceStdev
}
function placeStarsWithRetry() {
if ( !document.querySelectorAll('.stars svg').length ) {
return
}
let tries = 30
do {
var [widths, heights] = placeStars()
tries -= 1
} while ( !isGoodStarPattern(widths, heights) && tries > 0 )
const [centroidWidth, centroidHeight] = [window.innerWidth / 2, (window.innerHeight / 3) / 2]
const distances = widths.map((w, i) => [w, heights[i]])
.map(([w, h]) => calculateDistance(w, h, centroidWidth, centroidHeight))
window.glmdev.themeStats.push(
`# of constellations generated: ${30 - tries}`,
`Width stdev: ${Math.round(calculateStdev(widths))}`,
`Height stdev: ${Math.round(calculateStdev(heights))}`,
`Distance stdev: ${Math.round(calculateStdev(distances))}`
)
}
window.placeStars = placeStars
window.isGoodStarPattern = isGoodStarPattern
window.placeStarsWithRetry = placeStarsWithRetry
placeStarsWithRetry()
function updateThemeStatsDisplay() {
const ul = document.querySelector('footer.theme-stats ul')
for ( const stat of glmdev.themeStats ) {
const li = document.createElement('li')
li.innerText = stat
ul.appendChild(li)
}
ul.style.display = glmdev.themeStats.length ? 'unset' : 'none'
}
var resizeDebufHandle = false
window.onresize = () => {
if ( resizeDebufHandle ) {
clearTimeout(resizeDebufHandle)
}
resizeDebufHandle = setTimeout(() => {
placeStarsWithRetry()
resizeDebufHandle = false
}, 500)
}
window.updateThemeStatsDisplay = updateThemeStatsDisplay
updateThemeStatsDisplay()