|
// ==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.0 |
|
// @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'); |
|
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 14px sans-serif'; |
|
this.fillStyle = 'black'; |
|
this.fillText(`${row+1}`, -5, 0); |
|
} 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 14px sans-serif'; |
|
this.fillStyle = 'black'; |
|
this.fillText(`${row+1}`, -5, 0); |
|
} else { |
|
// Other columns: white-out |
|
this.fillStyle = '#ffffffdd'; |
|
this.fillRect(-1000,-1000,2000,2000); |
|
} |
|
jC++; |
|
} |
|
} |
|
} |
I personally run Firefox as my daily browser, so everything has been developed to function natively on Firefox.
While I did test with Greasemonkey (which is undeniably the most popular user-script manager), I do run ViolentMonkey myself, because of the drama that surrounded the Greasemonkey project.
I'll do some testing privately with Greasemonkey, to see if I am able to replicate the issue, but I'd encourage you to try out Violentmonkey instead, and see if that fixes things for you.
If it does not, I'm more than willing to go in-depth with this issue with you, though I'd prefer if we then moved to a dedicated issue in my repository, to prevent spamming all the subscribers to this script (including the big man Dan himself).