-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7bd1bf3
commit b8ff8a9
Showing
5 changed files
with
142 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// GitHub Game of Life - 1.0.1 | ||
// Chris Johnson | ||
// @defaced / defaced.dev / github.com/workeffortwaste | ||
(function () { | ||
const startGgol = () => { | ||
// Settings | ||
const cols = 53 | ||
const rows = 7 | ||
|
||
// Pull down the contributions from the graph. | ||
const contributions = document.getElementsByClassName('js-calendar-graph-svg')[0].children[0].getElementsByTagName('g') | ||
|
||
// Read contributions as columns from the contribution frame. | ||
const readContributions = (contributions) => { | ||
// Init output Arr. | ||
const output = [] | ||
|
||
for (const contribution of contributions) { | ||
const days = contribution.getElementsByTagName('rect') | ||
const lifeRow = [] | ||
for (const day of days) { | ||
// Convert to live or dead cells. | ||
lifeRow.push(day.getAttribute('data-count') > 0 ? 1 : 0) | ||
} | ||
// Add column to output. | ||
output.push(lifeRow) | ||
} | ||
|
||
// Fill in any blanks in the first and last rows. | ||
for (let i = 0; i < 7; i++) { | ||
if (!output[0][i]) { | ||
output[0][i] = 0 | ||
} | ||
if (!output[output.length - 1][i]) { | ||
output[output.length - 1][i] = 0 | ||
} | ||
} | ||
|
||
return output | ||
} | ||
|
||
// Our initial game of life state. | ||
let lifeArray = readContributions(contributions) | ||
|
||
// Write to the contributions graphic. | ||
const writeContributions = (contributions, nextGenerationArray) => { | ||
for (let i = 0; i < contributions.length; i++) { | ||
const days = contributions[i].getElementsByTagName('rect') | ||
for (let d = 0; d < 7; d++) { // Magic number - 7 days of the week. | ||
try { days[d].setAttribute('fill', nextGenerationArray[i][d] ? '#40c463' : '#ebedf0') } catch {} | ||
} | ||
} | ||
} | ||
|
||
const countNeighbors = (grid, x, y) => { | ||
let sum = 0 | ||
|
||
for (let i = -1; i < 2; i++) { | ||
for (let j = -1; j < 2; j++) { | ||
const col = (x + i + cols) % cols | ||
const row = (y + j + rows) % rows | ||
sum += grid[col][row] | ||
} | ||
} | ||
|
||
sum -= grid[x][y] | ||
return sum | ||
} | ||
|
||
const generateNextIteration = (grid) => { | ||
// Make empty array | ||
const next = [...Array(53)].map(e => Array(7)) | ||
|
||
for (let i = 0; i < cols; i++) { | ||
for (let j = 0; j < rows; j++) { | ||
const state = grid[i][j] | ||
const neighbors = countNeighbors(grid, i, j) | ||
|
||
if (state === 0 && neighbors === 3) { | ||
next[i][j] = 1 | ||
} else if (state === 1 && (neighbors < 2 || neighbors > 3)) { | ||
next[i][j] = 0 | ||
} else { | ||
next[i][j] = state | ||
} | ||
} | ||
} | ||
|
||
return next | ||
} | ||
|
||
const update = () => { | ||
// Generate the next iteration. | ||
const next = generateNextIteration(lifeArray) | ||
|
||
// If the output is the same as the input we've reached a stable state so kill the interval. | ||
if (JSON.stringify(next) === JSON.stringify(lifeArray)) { | ||
clearInterval(timer) | ||
} | ||
|
||
// Update the lifeArray with the next generation. | ||
lifeArray = next | ||
writeContributions(contributions, lifeArray) | ||
} | ||
|
||
// Update every 500 ms. | ||
const timer = setInterval(function () { update() }, 500) | ||
} | ||
|
||
const observerGgol = (entry) => { | ||
if (entry[0].intersectionRatio > 0) { | ||
// Kill the observer. | ||
observer.disconnect() | ||
// Start the game of life. | ||
startGgol() | ||
} | ||
} | ||
|
||
const observer = new IntersectionObserver(observerGgol) | ||
try { observer.observe(document.getElementsByClassName('js-calendar-graph-svg')[0]) } catch {} | ||
})() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "GitHub Game of Life", | ||
"description": "Replace the GitHub contributions graph with Conway's Game of Life.", | ||
"version": "1.0.1", | ||
"icons": { | ||
"16": "icon16.png", | ||
"48": "icon48.png", | ||
"128": "icon128.png" | ||
}, | ||
"content_scripts": [ | ||
{ | ||
"matches": [ | ||
"https://github.com/*" | ||
], | ||
"exclude_globs": ["https://github.com/*/*"], | ||
"js": ["github-game-of-life.js"], | ||
"run_at": "document_end" | ||
} | ||
], | ||
"manifest_version": 2 | ||
} |