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
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()
|