Skip to content

Instantly share code, notes, and snippets.

@killroy42
Last active November 23, 2023 11:49
Show Gist options
  • Save killroy42/853ad633da50a61d8dcd23d27c3113c2 to your computer and use it in GitHub Desktop.
Save killroy42/853ad633da50a61d8dcd23d27c3113c2 to your computer and use it in GitHub Desktop.
Prototype Hinting User Plugin
const generateHintFunc = (() => {
/*let board = Array.from({ length: 9 }, () => Array(9).fill(0));
board[0][0] = 1;
board[2][2] = 2;
board[0][1] = 3;
board[1][0] = 4;
*/
let board = [
[0, 9, 0, 0, 0, 7, 0, 5, 0],
[0, 5, 0, 8, 0, 0, 0, 0, 0],
[1, 4, 0, 0, 5, 0, 2, 0, 0],
[7, 0, 4, 0, 9, 0, 0, 0, 0],
[3, 8, 1, 7, 0, 0, 5, 9, 6],
[5, 0, 9, 0, 8, 0, 7, 0, 4],
[0, 7, 5, 0, 3, 8, 0, 4, 1],
[0, 1, 0, 0, 0, 6, 0, 7, 0],
[0, 3, 0, 1, 7, 0, 0, 8, 0] ];
/*
let board = [
[0, 0, 0, 0, 1, 0, 8, 0, 6],
[8, 1, 0, 0, 0, 9, 4, 0, 0],
[9, 0, 6, 8, 3, 0, 5, 1, 0],
[0, 9, 8, 0, 0, 7, 1, 0, 3],
[0, 7, 1, 0, 0, 0, 6, 9, 0],
[6, 0, 0, 0, 9, 1, 0, 7, 8],
[0, 0, 3, 1, 5, 0, 0, 8, 0],
[0, 8, 9, 4, 0, 3, 0, 0, 0],
[0, 0, 0, 9, 0, 8, 0, 0, 0]
];
*/
// prints board to console, not used
function print_board(board){
for(let i=0;i<9;i++){
console.log(board[i].toString());
}
}
// not used
function check_board(board){
/* possible return values and meaning
1 = coluding numbers(same row, col, box)
2 = invalid inpit(outside range)
*/
// check cols and rows
for(let i=0;i<9;i++){
let row = new Set();
let col = new Set();
for(let j=0;j<9;j++){
if(row.has(board[i][j]) || col.has(board[j][i])){
return false;
}
if(board[i][j]>9 || board[i][j]<0){
return false;
}
if(board[i][j]){
row.add(board[i][j]);
}
if(board[j][i]){
col.add(board[j][i]);
}
}
}
// box check
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
const box = new Set();
for (let bRow = 3 * i; bRow < (3 * i + 3); bRow++) {
for (let bCol = 3 * j; bCol < (3 * j + 3); bCol++) {
const boxVal = board[bRow][bCol];
if (boxVal && box.has(boxVal)) {
return false;
}
box.add(boxVal);
}
}
}
}
return true;
}
// this function checks whether a move is valid by checking if the board is still valid after a move
function check_after(board, i,j,num){
for(let k=0;k<9;k++){
if(board[i][k]===num || board[k][j]===num){
return false;
}
}
for(let x=3*Math.floor(i/3);x<(3*Math.floor(i/3))+3;x++){
for(let y=3*Math.floor(j/3);y<(3*Math.floor(j/3))+3;y++){
if(board[x][y]==num){
return false;
}
}
}
return true;
}
// solves the puzzle using backtacking, not really used
function solver1(board){
// find open cell
let i=-1;
let j=-1;
for(let x=0;x<9;x++){
for(let y=0;y<9;y++){
if(!board[x][y]){
i = x;
j = y;
break;
}
}
if(i>-1){
break;
}
}
// finsihed game
if(i<0){
//print_board(board);
return board;
}
// try all numbers
for(let num=1;num<10;num++){
if(check_after(board,i,j,num)){
board[i][j] = num;
if(solver1(board)){
return board;// or return true
}
board[i][j]=0;
}
}
return false;
}
// fills random cell with correct value from solved board (could be used as a type of hint?)
function hint1(board, clarity){
let empty_cells = Array();
for(let i=0;i<9;i++){
for(let j=0;j<9;j++){
if(board[i][j]==0){
empty_cells.push((9*i)+j);
}
}
}
// cell to be selected
let cell = empty_cells[Math.random()%empty_cells.length]
let x = Math.floor(cell/9);
let y = cell%9;
board[x][y] = solver1[board][x][y];
console.log("row",x,"column ",y,"is ", board[x][y]);
}
// returns possible valid moves for every cell in a map
function possible_values4cell(board){
let possible_vals = new Map(); // maps i(cell unit number) to set of possible values
for(let i=0;i<9;i++){
for(let j=0;j<9;j++){
if(board[i][j]==0){
for(let k=1;k<10;k++){
if(check_after(board,i,j,k)){
if(!(possible_vals.has(9*i+j))){
possible_vals.set(9*i+j, new Set());
}
// add k to list of possibilities
const present = possible_vals.get(9*i+j);
present.add(k);
possible_vals.set(9*i+j, present);
}
}
}/*else{
possible_vals.set(9*i+j, [board[i][j]])
}*/
}
}
return possible_vals;
}
// finds hidden singles
function h_singles(board){
/*
cell i,j can only be one value
*/
let hidden_singles = new Map(); // ij number representing single location : single value in cell location
for(let i=0;i<9;i++){
for(let j=0;j<9;j++){
if(possible_values4cell(board).get(9*i+j) && possible_values4cell(board).get(9*i+j).size==1){
let single_value = Array.from(possible_values4cell(board).get(9*i+j))[0];
hidden_singles.set(9*i+j, single_value);
}
}
}
return hidden_singles;
}
// this function is used in finding naked pairs/triples and quad
// it finds the frequency of each possibitity in a given row, column or box(rcb)
// example if row 3: has two cells with freq {2,3} occuring twice then there is a chance we have a naked pair in this row
function possibilities_freq4rcb(board, rcb, rcb_num){// rcb=row(0)/col(1)/box(2), rcb_num is 0 indexed
let temp, x, y, i, j;
let rcb_freq = new Map();
let each_number_freq = new Map();// stores the occurence of each number in every possiblity inthat rcb/rowcolorbox
let possible_vals = possible_values4cell(board);
// row freq
if(rcb==0){
for(let j=0;j<9;j++){
if(possible_vals.get(9*rcb_num+j)){
let arr0 = Array.from(possible_vals.get(9*rcb_num+j));
arr0.sort();
let pNum = 0; // convert possibilities to unique number
if(arr0.length==2){
for(let k=0;k<2;k++){
pNum += arr0[k]*Math.pow(10, 1-k);
if(!each_number_freq || !each_number_freq.has(arr0[k])){
each_number_freq.set(arr0[k], 0);
}
temp = each_number_freq.get(arr0[k]);
temp+=1
each_number_freq.set(arr0[k], temp);
}
}
if(arr0.length==3){
for(let k=0;k<3;k++){
pNum += arr0[k]*Math.pow(10, 2-k);
if(!each_number_freq || !each_number_freq.has(arr0[k])){
each_number_freq.set(arr0[k], 0);
}
temp = each_number_freq.get(arr0[k]);
temp+=1
each_number_freq.set(arr0[k], temp);
}
}
if(!rcb_freq || !rcb_freq.has(pNum)){
rcb_freq.set(pNum, 0);
}
temp = rcb_freq.get(pNum);
temp+=1
rcb_freq.set(pNum, temp);
}
}
if(rcb_freq.has(0)){
rcb_freq.delete(0);
}
}
// column frequency
if(rcb==1){
for(let i=0;i<9;i++){
if(possible_vals.get(9*i+rcb_num)){
let arr0 = Array.from(possible_vals.get(9*i+rcb_num));
arr0.sort();
let pNum = 0; // convert possibilities to unique number
if(arr0.length==2){
for(let k=0;k<2;k++){
pNum += arr0[k]*Math.pow(10, 1-k);
if(!each_number_freq || !each_number_freq.has(arr0[k])){
each_number_freq.set(arr0[k], 0);
}
temp = each_number_freq.get(arr0[k]);
temp+=1
each_number_freq.set(arr0[k], temp);
}
}
if(arr0.length==3){
for(let k=0;k<3;k++){
pNum += arr0[k]*Math.pow(10, 2-k);
if(!each_number_freq || !each_number_freq.has(arr0[k])){
each_number_freq.set(arr0[k], 0);
}
temp = each_number_freq.get(arr0[k]);
temp+=1
each_number_freq.set(arr0[k], temp);
}
}
if(!rcb_freq || !rcb_freq.has(pNum)){
rcb_freq.set(pNum, 0);
}
temp = rcb_freq.get(pNum);
temp+=1
rcb_freq.set(pNum, temp);
}
}
if(rcb_freq.has(0)){
rcb_freq.delete(0);
}
}
// box freq
if(rcb==2){
i = x = 3*Math.floor(rcb_num/3);
j = y = 3*(rcb_num%3);
for(;i<x+3;i++){
for(;j<y+3;j++){
if(possible_vals.get(9*i+j)){
let arr0 = Array.from(possible_vals.get(9*i+j));
arr0.sort();
let pNum = 0; // convert possibilities to unique number
if(arr0.length==2){
for(let k=0;k<2;k++){
pNum += arr0[k]*Math.pow(10, 1-k);
if(!each_number_freq || !each_number_freq.has(arr0[k])){
each_number_freq.set(arr0[k], 0);
}
temp = each_number_freq.get(arr0[k]);
temp+=1
each_number_freq.set(arr0[k], temp);
}
}
if(arr0.length==3){
for(let k=0;k<3;k++){
pNum += arr0[k]*Math.pow(10, 2-k);
if(!each_number_freq || !each_number_freq.has(arr0[k])){
each_number_freq.set(arr0[k], 0);
}
temp = each_number_freq.get(arr0[k]);
temp+=1
each_number_freq.set(arr0[k], temp);
}
}
if(!rcb_freq || !rcb_freq.has(pNum)){
rcb_freq.set(pNum, 0);
}
temp = rcb_freq.get(pNum);
temp+=1
rcb_freq.set(pNum, temp);
}
}
j = y;
}
if(rcb_freq.has(0)){
rcb_freq.delete(0);
}
}
let ret = {
rcb_frequency :rcb_freq,
each_number_frequency : each_number_freq
}
return ret;
}
// using function possibilities_freq4rcb we now find naked pairs or triples
function naked_pairs_triples(board){
let naked_pairs = new Map();// type|type_num : ij, eg 04 : 23 means a naked pair at row 4 involving numbers 2 and 3
let naked_triples = new Map();// type|type_num : ij, eg 24 : 235 means a naked triple at row 4 involving numbers 2, 3 and 5
for(let type=0;type<3;type++){//0=row,1==col,2===box
for(let i=0;i<9;i++){
if(possibilities_freq4rcb(board, type, i)){
for(const val of possibilities_freq4rcb(board, type, i).rcb_frequency){
let each_number__freq = possibilities_freq4rcb(board, type, i).each_number_frequency;
let p_num = val[0];
let freq = val[1];
if(p_num%100==p_num && freq==2){
let num1 = Math.floor(p_num/10);
let num2 = p_num%10;
if(!each_number__freq.get(num1)==freq || !each_number__freq.get(num2)==freq){
continue;
}
let num3 = type*10 + i
naked_pairs.set(num3, p_num);
}
if(p_num%1000==p_num && p_num>99 && freq==3){
let num1 = Math.floor(p_num/100)
let num2 = Math.floor(p_num/10);
let num3 = p_num%10;
if(!each_number__freq.get(num1)==freq || !each_number__freq.get(num2)==freq || !each_number__freq.get(num3)==freq){
continue;
}
let num4 = type*10 + i
naked_triples.set(num4, p_num);
}
}
}
}
}
let result = {
naked__pairs : naked_pairs,
naked__triples : naked_triples
}
return result;
}
// returns => number(1 to 9) : [row_where_its_possible*10+col_where_its_possible(note this are numbers),..., number_of_rows_it_occurs, num_of_cols_it_occurs]
// this function is used in finding pointing pairs and triples as it provides necessary data in finding them
function box_element_mapping(board, box_num){
let x, y, i, j;
let box_info = {// note this mapping is only for UNKNOWN elements in the box,
element_mapping : new Map(),
row_count : new Map(),// contains number : set of the distint rows num is a possibliltiy of in box box_num
col_count : new Map(),
// possible elements in each row of the 3x3 in the 9x9 in order except the ones in the box
// 3 rows 3 cols(6 sets total) left->right, top->bottom
row_col_elements : new Map(),
boxes_pointing_pairs : new Map()// box : numbers involved in the pointing paircontains the possiblities of each cell in the box.e.g 42
}
i = x = 3*Math.floor(box_num/3);
j = y = 3*(box_num%3);
let r = 0;
let possibilities_freq = new Map();// stores frequency of each possiblity
let total_possibilties = new Array(0);// all possiblities for box in one
let restrict = 0 // check frequencies just once
for(let num=1;num<10;num++){
box_info.element_mapping.set(num, new Array(0));
box_info.row_count.set(num, new Set());
box_info.col_count.set(num, new Set());
for(;i<x+3;i++){
for(;j<y+3;(r++,j++)){
//console.log("i",i,"j",j);
//console.log("i*3+j", i*9+j)
//check if duplicate cell possibilies is already in box
if(possible_values4cell(board).get(9*i+j) && restrict==0){
total_possibilties = [...total_possibilties, ...possible_values4cell(board).get(9*i+j)];
}
if(possible_values4cell(board).get(9*i+j) && possible_values4cell(board).get(9*i+j).size==2 && restrict==0 ){
arr0 = [...possible_values4cell(board).get(9*i+j)];
Max = Math.max(...arr0);
Min = Math.min(...arr0);
if(possibilities_freq.has(Max*10+Min)){
let temp = possibilities_freq.get(Max*10+Min);
temp[0]+=1;
temp[1].add(i*10+j);
possibilities_freq.set(Max*10+Min, temp);
}else{
possibilities_freq.set(Max*10+Min, [1, new Set([i*10+j])]);// store {2,3} as 32(key in possiblities_freq) : [frequency, ij(as i*10+j)]
}
}
// space
let check = possible_values4cell(board).get(9*i+j);
if(check && check.has(num)){
// update element mapping
let temp = box_info.element_mapping.get(num);
temp.push(i*10+j);
box_info.element_mapping.set(num,temp);
// update row count
temp = box_info.row_count.get(num)
temp.add(i)
box_info.row_count.set(num, temp);
// update col count
temp = box_info.col_count.get(num)
temp.add(j)
box_info.col_count.set(num, temp);
}
// now that we have info on box, we need to find the other elements in same row/col in search of pointing pair
if(r<3){
box_info.row_col_elements.set(r, new Set());
for(let m = 0;m<9;m++){
if(!(m>=y && m<y+3) && possible_values4cell(board).get(9*(x+r)+m)){
for(let n of possible_values4cell(board).get(9*(x+r)+m)){
let temp = box_info.row_col_elements.get(r);
temp.add(n);
box_info.row_col_elements.set(r, temp);
}
}
}
}else if(r>=3 && r<6){
box_info.row_col_elements.set(r, new Set());
for(let m = 0;m<9;m++){
if(!(m>=x && m<x+3) && possible_values4cell(board).get(9*m+y+r%3)){
for(let n of possible_values4cell(board).get(9*m+y+r%3)){
let temp = box_info.row_col_elements.get(r);
temp.add(n);
box_info.row_col_elements.set(r, temp);
}
}
}
}
}
j = y = 3*(box_num%3);
}
restrict = 1;
i = x = 3*Math.floor(box_num/3);
j = y = 3*(box_num%3);
}
const total_possibilties_frequency = total_possibilties.reduce((acc, curr) => {
acc[curr] = (acc[curr] || 0) + 1;
return acc;
}, {});
for(element of possibilities_freq.entries()){
let duo = element[1];
let same_row = new Set();
let same_col = new Set();
if(duo==undefined){
continue;
}
for(position of duo[1]){
same_row.add(Math.floor(position/10));
same_col.add(position%10);
}
if(same_row.size==1){
let x = Array.from(same_row)[0];
let lonely_check=0;// check if dual is the only one in row
// check if other row spots are filled
for(let j=0;j<9;j++){
if(board[x][j]==0){
lonely_check+=1;
}
}
if(lonely_check==2 && (total_possibilties_frequency[Math.floor(element[0]/10)]>duo[0] || total_possibilties_frequency[element[0]%10]>duo[0])){
if(box_info.boxes_pointing_pairs.has(box_num)){
let temp = box_info.boxes_pointing_pairs.get(box_num);
temp.push(element);
box_info.boxes_pointing_pairs.set(box_num, temp); // store in box_number : array with eah duo pair present
}else{
box_info.boxes_pointing_pairs.set(box_num, [element[0]]);
}
}
}
if(same_col.size==1){
let y = Array.from(same_col)[0];
let lonely_check=0;// check if dual is the only one in row
// check if other row spots are filled
for(let i=0;i<9;i++){
if(board[i][y]==0){
lonely_check+=1;
}
}
if(lonely_check==2 && (total_possibilties_frequency[Math.floor(element[0]/10)]>duo[0] || total_possibilties_frequency[element[0]%10]>duo[0])){
if(box_info.boxes_pointing_pairs.has(box_num)){
let temp = box_info.boxes_pointing_pairs.get(box_num);
temp.push(element);
box_info.boxes_pointing_pairs.set(box_num, temp); // store in box_number : array with eah duo pair present
}else{
box_info.boxes_pointing_pairs.set(box_num, [element[0]]);
}
}
}
}
//console.log("possiblities-freq", possibilities_freq);
return box_info;
}
// using function box_element_mapping, this function finds pointing pairs and triples
function pointing_pairs(board){
let x, y, i, j;
/*
let ppairs = {
ppair_rows : new Map(), // stores number : row with pointing pair/triple of number
ppair_cols : new Map(),
boxes_pointing_pairs_triples : new Map() // box num: pair
}*/
let ppairs = new Map();
for(let box=0;box<9;box++){
i = x = 3*Math.floor(box/3);
j = y = 3*(box%3);
for(let num=1;num<10;num++){
let num_info = box_element_mapping(board, box);
let arr1 = [...num_info.row_count.get(num)];// stores row containing point pair
let arr2 = [...num_info.col_count.get(num)];// stores col containing pointing pair
// check row for pointing pair
if(num_info.row_count.get(num).size==1 && num_info.row_col_elements.get((arr1[0]-x)%3)){
if(num_info.row_col_elements.get((arr1[0]-x)%3).has(num)){// found a row pointing pair/triple
ppairs.set(arr1[0], num)
}
}
// check col for pointing pair
if(num_info.col_count.get(num).size==1 && num_info.row_col_elements.get(3+(arr2[0]-y)%3)){// found a col pointing pair/triple
if(num_info.row_col_elements.get(3+(arr2[0]-y)%3).has(num)){
arr2[0] = 10+arr2[0];
ppairs.set(arr2[0], num)
}
}
// check box for pointing pair
if(num_info.boxes_pointing_pairs.get(box)){
ppairs.set(20+box, num_info.boxes_pointing_pairs.get(box));
}
}
}
return ppairs;
}
// this function calls all previous hint functions and organizes them into an object for sorting
function generate_hints(board){
/*=> Hidden singles: Map of ij(cell number) row-col values to the correct value for the cell
=> naked pairs/triples: Map of ijkl(i=0 means if row, i=1 means col,i=2 means box i is row/col/box number(0 indexed), j is the corresponding number of i(e.g jth row)
the k and l are the location row/col for the pair in ith row/col) row-col values to the list of correct values for the cell
if i is a box, then k-l represent the nth element of the box e.g kl=56 means the 5th and 6th elements for the box
example ijkl = 0106 means there is naked pair at row 1 at columns 0 and 6
=> for pointing pairs, we map ijkl to a set of the point, i=0 means row i=1 means col,i=2 means box
j is the corresponding number of i(e.g jth row)
the k and l are the location row/col for the pair in ith row/col that have pointing pairs
same goes for the triples
*/
let all_hint_info = {
// hint levels are base on Simplicity from 1 to 3
hidden_singles : h_singles(board),
naked_pairs : naked_pairs_triples(board).naked__pairs,
naked_triple : naked_pairs_triples(board).naked__triples,
pointing_pairs : pointing_pairs(board),
Intersection_removal : new Map(),
X_wing : new Map()
}
return all_hint_info
}
// using the generate_hints function, this function sorts the hints based on certain criteria
function sort_hints(board){
// hint levels are base on Simplicity from 1 to 3
let all_hint_info = generate_hints(board);
let level_1_hint = {
hidden_singles : all_hint_info.hidden_singles, // Map of ij(cell number) row-col values to the correct value for the cell
naked_pairs : all_hint_info.naked_pairs, // Map of ijkl(i=0 means if row, i=1 means col,i=2 means box i is row/col/box number(0 indexed), j is the corresponding number of i(e.g jth row)
// the k and l are the location row/col for the pair in ith row/col) row-col values to the list of correct values for the cell
// if i is a box, then k-l represent the nth element of the box e.g kl=56 means the 5th and 6th elements for the box
// for example ijkl = 0106 means there is naked pair at row 1 at columns 0 and 6
naked_triples : all_hint_info.naked_triple, // Same concept as naked pairs but with 3 values hence 21067, means triple at box 1 in the 0th, 6th and 7th digits of the box
naked_quads : new Map() // Same concept as triple pairs but wit 4 vals
}
let level_2_hint = {
// for pointing pairs, we map ijkl to a set of the point, i=0 means row i=1 means col,i=2 means box
// j is the corresponding number of i(e.g jth row)
// the k and l are the location row/col for the pair in ith row/col that have pointing pairs
// same goes for the triples
pointing_pairs : all_hint_info.pointing_pairs,
pointing_triples : new Map(),
}
let level_3_hint = {
Intersection_removal : new Map(),
X_wing : new Map()
}
let result = {
hint_type : "",
hint_location : "", // row/col/box
hint_location_number : 0
}
//
let location = ["row", "column", "box"]
if(level_1_hint.naked_triples.size!=0){
//if(level_1_hint.naked_pairs.size!=0){
result.hint_type = "naked triple";
//let num = Array.from(level_1_hint.naked_pairs)[0][0];
let num = Array.from(level_1_hint.naked_triples)[0][0];
let num1 = Math.floor(num/10);
result.hint_location = location[num1];
result.hint_location_number = num%10 + 1;
}else if(level_1_hint.naked_pairs.size!=0){
result.hint_type = "naked pair";
let num = Array.from(level_1_hint.naked_pairs)[0][0];
let num1 = Math.floor(num/10);
result.hint_location = location[num1];
result.hint_location_number = num%10 + 1;
}else if(level_1_hint.hidden_singles.size!=0){
result.hint_type = "hidden single";
result.hint_location = "column";
let num = Array.from(level_1_hint.hidden_singles)[0][0];
let num1 = Math.floor(num/10);
result.hint_location_number = num%10 + 1;
}else if(level_2_hint.pointing_pairs.size!=0){
result.hint_type = "pointing pair";
let num = Array.from(level_1_hint.naked_pairs)[0][0];
let num1 = Math.floor(num/10);
result.hint_location = location[num1];
result.hint_location_number = num%10;
}else{
//console.log("no hint");
}
//console.log("sort_hints > level_1_hint", level_1_hint);
//console.log("sort_hints > level_2_hint", level_2_hint);
//console.log("sort_hints > level_3_hint", level_3_hint);
return Object.assign(result, {level_1_hint, level_2_hint, level_3_hint});
}
// converts hint data to a basic sentence
function hint_to_word(result){
console.log("There is a ", result.hint_type, " in the ", result.hint_location_number, "th ", result.hint_location )
}
function hintToString() {
const {hint_type, hint_location, hint_location_number} = this;
return `There is a ${hint_type} in ${hint_location} ${hint_location_number}`;
};
const p81ToBoard = p81 => p81.replace(/[^0-9]/g, '0').match(/.{9}/g).map(r=>r.split('').map(d=>parseInt(d)));
function getHint(p81) {
let board = p81ToBoard(p81);
let hint = sort_hints(board);
hint.toString = hintToString;
return hint
}
return getHint;
});
Framework.features.userplugins.addPlugin(
'HintSystemPT01',
`{
settingName: 'HintSystemPT01',
handleInfoClick: function (event) {
document.querySelector('.info-overlay').dispatchEvent(new Event('click'));
let hint = this.generateHint(Framework.app.toP81());
console.log('hint:', hint.toString(), hint);
Framework.showAlert(hint.toString());
},
handleSettingChange: function() {
const setting = Framework.getSetting(this.settingName);
if(setting !== this.enabled) {
this.enabled = setting;
if(this.enabled) {
Framework.app.on('control-info', this.handleInfoClick);
}
else {
Framework.app.off('control-info', this.handleInfoClick);
}
}
},
handleInit: function() {
this.enabled = false;
this.generateHint = (${generateHintFunc})();
Framework.addSetting({
group: 'experimental', name: this.settingName, content: 'Hints',
tag: 'toggle',
init: this.handleSettingChange, onToggle: this.handleSettingChange,
});
},
}`,
{overwrite: true}
);
// Paste into console to add as user plugin. Setting in "Advanced"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment