Created
January 27, 2024 08:39
-
-
Save f-o/1bf2dd8a3364d51c5a666119eb334a9b to your computer and use it in GitHub Desktop.
Userscript to streamline Jigidi solving
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
// ==UserScript== | |
// @name Jigidi Magic Stripes | |
// @namespace me.danq.com.jigidi.magicstripes | |
// @match https://www.jigidi.com/solve/* | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @version 1.1 | |
// @author Dan Q <https://danq.me> | |
// @description 23/03/2023, 14:32:30 | |
// ==/UserScript== | |
/* | |
RainbowVis-JS ()Eclipse Public License - v 1.0) | https://github.com/anomal/RainbowVis-JS/blob/master/rainbowvis.js | |
*/ | |
function Rainbow(){"use strict";var gradients=null;var minNum=0;var maxNum=100;var colours=['ff0000','ffff00','00ff00','0000ff'];setColours(colours);function setColours(spectrum){if(spectrum.length<2){throw new Error('Rainbow must have two or more colours.')}else{var increment=(maxNum-minNum)/(spectrum.length-1);var firstGradient=new ColourGradient();firstGradient.setGradient(spectrum[0],spectrum[1]);firstGradient.setNumberRange(minNum,minNum+increment);gradients=[firstGradient];for(var i=1;i<spectrum.length-1;i++){var colourGradient=new ColourGradient();colourGradient.setGradient(spectrum[i],spectrum[i+1]);colourGradient.setNumberRange(minNum+increment*i,minNum+increment*(i+1));gradients[i]=colourGradient} | |
colours=spectrum}} | |
this.setSpectrum=function(){setColours(arguments);return this} | |
this.setSpectrumByArray=function(array){setColours(array);return this} | |
this.colourAt=function(number){if(isNaN(number)){throw new TypeError(number+' is not a number')}else if(gradients.length===1){return gradients[0].colourAt(number)}else{var segment=(maxNum-minNum)/(gradients.length);var index=Math.min(Math.floor((Math.max(number,minNum)-minNum)/segment),gradients.length-1);return gradients[index].colourAt(number)}} | |
this.colorAt=this.colourAt;this.setNumberRange=function(minNumber,maxNumber){if(maxNumber>minNumber){minNum=minNumber;maxNum=maxNumber;setColours(colours)}else{throw new RangeError('maxNumber ('+maxNumber+') is not greater than minNumber ('+minNumber+')')} | |
return this}} | |
function ColourGradient(){"use strict";var startColour='ff0000';var endColour='0000ff';var minNum=0;var maxNum=100;this.setGradient=function(colourStart,colourEnd){startColour=getHexColour(colourStart);endColour=getHexColour(colourEnd)} | |
this.setNumberRange=function(minNumber,maxNumber){if(maxNumber>minNumber){minNum=minNumber;maxNum=maxNumber}else{throw new RangeError('maxNumber ('+maxNumber+') is not greater than minNumber ('+minNumber+')')}} | |
this.colourAt=function(number){return calcHex(number,startColour.substring(0,2),endColour.substring(0,2))+calcHex(number,startColour.substring(2,4),endColour.substring(2,4))+calcHex(number,startColour.substring(4,6),endColour.substring(4,6))} | |
function calcHex(number,channelStart_Base16,channelEnd_Base16){var num=number;if(num<minNum){num=minNum} | |
if(num>maxNum){num=maxNum} | |
var numRange=maxNum-minNum;var cStart_Base10=parseInt(channelStart_Base16,16);var cEnd_Base10=parseInt(channelEnd_Base16,16);var cPerUnit=(cEnd_Base10-cStart_Base10)/numRange;var c_Base10=Math.round(cPerUnit*(num-minNum)+cStart_Base10);return formatHex(c_Base10.toString(16))} | |
function formatHex(hex){if(hex.length===1){return'0'+hex}else{return hex}} | |
function isHexColour(string){var regex=/^#?[0-9a-fA-F]{6}$/i;return regex.test(string)} | |
function getHexColour(string){if(isHexColour(string)){return string.substring(string.length-6,string.length)}else{var name=string.toLowerCase();if(colourNames.hasOwnProperty(name)){return colourNames[name]} | |
throw new Error(string+' is not a valid colour.')}} | |
var colourNames={aliceblue:"F0F8FF",antiquewhite:"FAEBD7",aqua:"00FFFF",aquamarine:"7FFFD4",azure:"F0FFFF",beige:"F5F5DC",bisque:"FFE4C4",black:"000000",blanchedalmond:"FFEBCD",blue:"0000FF",blueviolet:"8A2BE2",brown:"A52A2A",burlywood:"DEB887",cadetblue:"5F9EA0",chartreuse:"7FFF00",chocolate:"D2691E",coral:"FF7F50",cornflowerblue:"6495ED",cornsilk:"FFF8DC",crimson:"DC143C",cyan:"00FFFF",darkblue:"00008B",darkcyan:"008B8B",darkgoldenrod:"B8860B",darkgray:"A9A9A9",darkgreen:"006400",darkgrey:"A9A9A9",darkkhaki:"BDB76B",darkmagenta:"8B008B",darkolivegreen:"556B2F",darkorange:"FF8C00",darkorchid:"9932CC",darkred:"8B0000",darksalmon:"E9967A",darkseagreen:"8FBC8F",darkslateblue:"483D8B",darkslategray:"2F4F4F",darkslategrey:"2F4F4F",darkturquoise:"00CED1",darkviolet:"9400D3",deeppink:"FF1493",deepskyblue:"00BFFF",dimgray:"696969",dimgrey:"696969",dodgerblue:"1E90FF",firebrick:"B22222",floralwhite:"FFFAF0",forestgreen:"228B22",fuchsia:"FF00FF",gainsboro:"DCDCDC",ghostwhite:"F8F8FF",gold:"FFD700",goldenrod:"DAA520",gray:"808080",green:"008000",greenyellow:"ADFF2F",grey:"808080",honeydew:"F0FFF0",hotpink:"FF69B4",indianred:"CD5C5C",indigo:"4B0082",ivory:"FFFFF0",khaki:"F0E68C",lavender:"E6E6FA",lavenderblush:"FFF0F5",lawngreen:"7CFC00",lemonchiffon:"FFFACD",lightblue:"ADD8E6",lightcoral:"F08080",lightcyan:"E0FFFF",lightgoldenrodyellow:"FAFAD2",lightgray:"D3D3D3",lightgreen:"90EE90",lightgrey:"D3D3D3",lightpink:"FFB6C1",lightsalmon:"FFA07A",lightseagreen:"20B2AA",lightskyblue:"87CEFA",lightslategray:"778899",lightslategrey:"778899",lightsteelblue:"B0C4DE",lightyellow:"FFFFE0",lime:"00FF00",limegreen:"32CD32",linen:"FAF0E6",magenta:"FF00FF",maroon:"800000",mediumaquamarine:"66CDAA",mediumblue:"0000CD",mediumorchid:"BA55D3",mediumpurple:"9370DB",mediumseagreen:"3CB371",mediumslateblue:"7B68EE",mediumspringgreen:"00FA9A",mediumturquoise:"48D1CC",mediumvioletred:"C71585",midnightblue:"191970",mintcream:"F5FFFA",mistyrose:"FFE4E1",moccasin:"FFE4B5",navajowhite:"FFDEAD",navy:"000080",oldlace:"FDF5E6",olive:"808000",olivedrab:"6B8E23",orange:"FFA500",orangered:"FF4500",orchid:"DA70D6",palegoldenrod:"EEE8AA",palegreen:"98FB98",paleturquoise:"AFEEEE",palevioletred:"DB7093",papayawhip:"FFEFD5",peachpuff:"FFDAB9",peru:"CD853F",pink:"FFC0CB",plum:"DDA0DD",powderblue:"B0E0E6",purple:"800080",red:"FF0000",rosybrown:"BC8F8F",royalblue:"4169E1",saddlebrown:"8B4513",salmon:"FA8072",sandybrown:"F4A460",seagreen:"2E8B57",seashell:"FFF5EE",sienna:"A0522D",silver:"C0C0C0",skyblue:"87CEEB",slateblue:"6A5ACD",slategray:"708090",slategrey:"708090",snow:"FFFAFA",springgreen:"00FF7F",steelblue:"4682B4",tan:"D2B48C",teal:"008080",thistle:"D8BFD8",tomato:"FF6347",turquoise:"40E0D0",violet:"EE82EE",wheat:"F5DEB3",white:"FFFFFF",whitesmoke:"F5F5F5",yellow:"FFFF00",yellowgreen:"9ACD32"}} | |
// Are we logged-in? | |
const loggedIn = !document.querySelector('account-status.guest'); | |
console.log(`Magic Stripes: loggedIn=${loggedIn ? 'true' : 'false'}`); | |
// Prepare Magic Stripes UI | |
const jigidiMagicStripes = document.createElement('div'); | |
jigidiMagicStripes.id = 'jigidi-magic-stripes'; | |
// Inject Magic Stripes UI | |
const creatorElem = document.getElementById('info-creator'); | |
creatorElem.before(jigidiMagicStripes); | |
if(!loggedIn){ | |
// Magic Stripes UI only works if logged in (we need Jigidi's state saving through page refreshes) | |
jigidiMagicStripes.innerHTML = '<p><strong>Magic Stripes</strong><br>Disabled. <a href="https://www.jigidi.com/login.php">Sign in to Jigidi</a> to enable.</p>'; | |
} else { | |
// Logged in: jigsaw ID and settings for this jigsaw, enumerate lengths of jigsaw dimensions, and update Magic Stripes UI | |
const jigsawId = window.location.href.match(/solve\/(\w+)\//)[1]; | |
const magicStripesSettings = GM_getValue(`magicStripesSettings_${jigsawId}`, { col: 0 }); | |
const jDimensions = creatorElem.innerText.match(/(\d+)×(\d+)/); | |
const jCols = parseInt(jDimensions[1]); | |
const jRows = parseInt(jDimensions[2]); | |
console.log(`Magic Stripes: jCols=${jCols} jRows=${jRows}`); | |
jigidiMagicStripes.innerHTML = ` | |
<p> | |
<strong>Magic Stripes</strong><br> | |
<label for="magicStripesCol">Help with column? (0 to disable)</label><br> | |
<input type="number" id="magicStripesCol" value="${magicStripesSettings.col}" min="0" max="${jCols}" style="width: 4em;"> | |
<button id="magicStripesGo">Go</button> | |
<button id="magicStripesPlusOne">+1 and Go</button> | |
</p> | |
`; | |
const magicStripesCol = document.getElementById('magicStripesCol'); | |
const magicStripesGo = document.getElementById('magicStripesGo'); | |
magicStripesGo.addEventListener('click', ()=>{ | |
magicStripesSettings.col = parseInt(magicStripesCol.value); | |
GM_setValue(`magicStripesSettings_${jigsawId}`, magicStripesSettings); | |
window.location.reload(); | |
}); | |
document.getElementById('magicStripesPlusOne').addEventListener('click', ()=>{ | |
magicStripesCol.value = (parseInt(magicStripesCol.value) + 1) % (jCols + 1); | |
magicStripesGo.dispatchEvent(new Event('click')); | |
}); | |
// Generate spectrum to use: | |
var rainbow = new Rainbow(); | |
let jColors = []; | |
rainbow.setNumberRange(1, jRows); | |
//rainbow.setSpectrum('red', 'violet'); | |
rainbow.setSpectrum('ff0000','ffff00','00ff00','0000ff'); | |
for(var i = 1; i <= jRows; i++) { | |
jColors.push(`#${rainbow.colourAt(i)}`); | |
} | |
let jC = 0; | |
const targetCol = parseInt(magicStripesSettings.col); | |
if(targetCol > 0) { | |
// Override putImageData with a manipulated version for THIS page load | |
CanvasRenderingContext2D.prototype.putImageData = function(imageData, dx, dy){ | |
console.log('Magic Stripes: putImageData'); | |
const targetCol = parseInt(magicStripesSettings.col); | |
const col = jC % jCols; | |
const row = Math.floor(jC / jCols); | |
if((col + 1) === targetCol) { | |
// Target column: color and number | |
this.fillStyle = jColors[row % jColors.length]; | |
this.fillRect(-1000,-1000,2000,2000); | |
this.font = 'bold 2rem sans-serif'; | |
this.fillStyle = 'black'; | |
this.fillText(`${row+1}`, imageData.width / 2 - 5, imageData.height / 2 + 5); | |
/** | |
this.fillStyle = 'black'; | |
this.fillText(`${row + 1} - `.repeat(10), 0, 25); | |
this.fillText(`${row + 1} - `.repeat(10), 0, 50); | |
this.fillText(`${row + 1} - `.repeat(10), 0, 75); | |
this.fillStyle = 'white'; | |
this.fillText(`${row + 1} - `.repeat(10), 0, 38); | |
this.fillText(`${row + 1} - `.repeat(10), 0, 63); | |
this.fillText(`${row + 1} - `.repeat(10), 0, 88); | |
**/ | |
} else if ((col + 2) === targetCol) { | |
// Previous column: lightly color, don't number | |
this.fillStyle = jColors[row % jColors.length]; | |
this.fillRect(-1000,-1000,2000,2000); | |
this.fillStyle = '#ffffffbb'; | |
this.fillRect(-1000,-1000,2000,2000); | |
this.font = 'bold 2rem sans-serif'; | |
this.fillStyle = 'black'; | |
this.fillText(`${row+1}`, imageData.width / 2 - 5, imageData.height / 2 + 5); | |
} else { | |
// Other columns: white-out | |
this.fillStyle = '#ffffffdd'; | |
this.fillRect(-1000,-1000,2000,2000); | |
} | |
jC++; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Amazing; love it!