|
// ==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++; |
|
} |
|
} |
|
} |
May I suggest increase the font size to
2rem
from14px
, and move the text position to(0, 0)
from(-5, 0)
.It seems that the number is not shown up currently.