Skip to content

Instantly share code, notes, and snippets.

@dclamage
Created October 27, 2021 02:15
Show Gist options
  • Save dclamage/bd07bc571fac98e58953b47db7ddb47a to your computer and use it in GitHub Desktop.
Save dclamage/bd07bc571fac98e58953b47db7ddb47a to your computer and use it in GitHub Desktop.
Modifies the "New Grid" popup to include an entry to paste a string of givens.
// ==UserScript==
// @name Fpuzzles-ImExGivens
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Modifies the "New Grid" popup to include an entry to paste a string of givens.
// Only valid digits that can be placed in the grid (based on the size) will be placed,
// any other character will be ignored.
// Supports sizes 10+ as well, using the characters (upper and lower case) A, B, ...G to
// represent 10, 11, ...16 respectively.
// Export current givens by running the exportGivens() command in the console.
// @author RSP
// @match https://*.f-puzzles.com/*
// @match https://f-puzzles.com/*
// @icon https://www.google.com/s2/favicons?domain=f-puzzles.com
// @grant none
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
const buildImport = function() {
/* rebuild new grid popup */
const confirmButton = buttons.find(b => {return b.id === 'ConfirmNew'});
const extraHeight = 100;
popups.newgrid.h += extraHeight;
buttons.filter(b => b.modes.includes('New Grid')).forEach(b => b.y -= (-5 + extraHeight / 2));
confirmButton.w += 50;
confirmButton.title = 'Blank Grid';
const origDrawPopups = drawPopups;
drawPopups = function(overlapSidebars) {
if (overlapSidebars && popup == 'New Grid') {
var box = popups.newgrid;
var imSL = (importBox.value.trim() ?? '').split('').length;
ctx.lineWidth = lineWW;
ctx.fillStyle = boolSettings['Dark Mode'] ? '#505050' : '#F0F0F0';
ctx.strokeStyle = '#000000';
ctx.fillRect(canvas.width/2 - box.w/2, canvas.height/2 - box.h/2, box.w, box.h);
ctx.strokeRect(canvas.width/2 - box.w/2, canvas.height/2 - box.h/2, box.w, box.h);
ctx.lineWidth = lineWW;
ctx.fillStyle = boolSettings['Dark Mode'] ? '#404040' : '#E0E0E0';
ctx.strokeStyle = '#000000';
ctx.fillRect(canvas.width/2 - box.w/2, canvas.height/2 - box.h/2, box.w, 87.5);
ctx.strokeRect(canvas.width/2 - box.w/2, canvas.height/2 - box.h/2, box.w, 87.5);
ctx.fillStyle = boolSettings['Dark Mode'] ? '#F0F0F0' : '#000000';
ctx.font = '55px Arial';
ctx.fillText('Select a grid size:', canvas.width/2, canvas.height/2 - box.h/2 + 62.5);
ctx.font = '60px Arial';
ctx.fillText(tempSize + 'x' + tempSize, canvas.width/2, canvas.height/2 + (box.h * 0.123) - 7 - extraHeight / 2);
ctx.font = '22px Arial';
ctx.fillText('Givens from String', canvas.width/2 - box.w * 0.33, canvas.height * 0.63);
if (imSL && imSL !== tempSize * tempSize) {
ctx.fillStyle = boolSettings['Dark Mode'] ? '#FF3232' : '#DC0000';
ctx.font = '16px Arial text-align: right';
ctx.fillText('error: string too ' + (imSL > tempSize * tempSize ? 'long' : 'short'), canvas.width/2 + box.w * 0.3, canvas.height/2 + box.h * 0.44);
}
} else {
origDrawPopups(overlapSidebars);
}
}
/* add new controls */
const importBox = document.createElement('input');
importBox.id = 'importBox';
importBox.type = 'text';
importBox.style = 'display: none; position: fixed; top: 60%; width: 24%; height: 4.5%; left: 43.8%; background: rgb(255, 255, 255); border-width: min(0.622222vh, 0.35vw); border-color: rgb(0, 0, 0); border-style: solid; font-family: Arial; text-align: left; outline: none;';
importBox.className = 'importBox';
document.getElementById('canvas1').insertAdjacentElement('afterend', importBox);
/* add functionality */
confirmButton.click = function(override = false) {
if (!(this.hovering() || override)) return;
var imS = (importBox.value.trim() ?? '').split('');
if (!(imS.length && imS.length !== tempSize * tempSize)) {
createGrid(tempSize, false, true);
let r = 0;
let c = 0;
let tens = 'AaBbCcDdEeFfGg'.split('');
let origMode = tempEnterMode;
tempEnterMode = 'Normal';
imS.forEach(char => {
let val = parseInt(char) ? parseInt(char) : (tens.includes(char) ? Math.floor(tens.indexOf(char) / 2) + 10 : 0);
if (val > size) val = 0; //ignore any value that can't be turned into a valid digit at current
grid[r][c].enter(val);
if (++c === size) {
c = 0;
r++;
}
});
tempEnterMode = origMode;
closePopups();
}
updateImportDisplay();
return true;
}
importBox.addEventListener('input', function() {
confirmButton.title = importBox.value.trim() ? 'Import Givens' : 'Blank Grid';
})
importBox.addEventListener('keypress', function(k) {
if (k.key === 'Enter') confirmButton.click(true);
})
const updateImportDisplay = function() {
if (popup !== 'New Grid') {
importBox.style.display = 'none';
importBox.value = '';
confirmButton.title = 'Blank Grid';
} else {
importBox.style.display = 'block';
importBox.focus();
}
}
document.addEventListener('mousedown', updateImportDisplay);
document.addEventListener('mouseup', updateImportDisplay);
}
setTimeout(buildImport, 1000);
/* export function */
window.exportGivens = function() {
let out = '';
const getVal = function(r,c) {
if (!grid[r][c].given) return '.';
else {
let val = grid[r][c].value;
return val < 10 ? val : 'abcdefg'.split('')[val - 10];
}
}
for (let r = 0; r < size; r++) {
for (let c = 0; c < size; c++) {
out += getVal(r,c);
}
}
// does not work when run from console on some browsers sometimes
const el = document.createElement('textarea');
el.value = out;
el.setAttribute('readonly', '');
el.style = 'position: absolute; left: -9999px';
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
console.log('Output: "' + out + '" copied to clipboard (or tried to).');
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment