Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add comparison constraints #7

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion js/constraint_displays.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class ConstraintDisplays {
this.Quad,
this.Givens,
this.OutsideClue,
this.Comparison,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this before Letter. Constraints are rendered in this order.

]
}
}
Expand Down Expand Up @@ -553,7 +554,6 @@ ConstraintDisplays.Dot = class Dot extends BaseConstraintDisplayItem {
return dot;
}
}

ConstraintDisplays.Letter = class Letter extends BaseConstraintDisplayItem {
drawItem(constraint, _) {
const cells = constraint.cells;
Expand Down Expand Up @@ -1230,3 +1230,56 @@ ConstraintDisplays.Givens = class Givens extends BaseConstraintDisplayItem {
this._maskMap.clear();
}
}

ConstraintDisplays.Comparison = class Comparison extends BaseConstraintDisplayItem {
drawItem(constraint, options) {
const primaryCell = constraint.primaryCell;
const secondaryCells = constraint.secondaryCells;

let result = createSvgElement("g");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const where possible.

let drawDecoration = (primaryCell, secondaryCell) => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull this out into a proper method. No reason for this to be inline.

// Find the midpoint between the squares.
let [x0, y0] = this.cellIdCenter(primaryCell);
let [x1, y1] = this.cellIdCenter(secondaryCell);
let x = (x0 + x1) / 2;
let y = (y0 + y1) / 2;
const cellSize = DisplayItem.CELL_SIZE;
const comparisonSize = 0.1 * cellSize;
const inset = 0;
const squash = 0.75;
var dC = x0 < x1 ? 1 : (x0 > x1 ? -1 : 0);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use var anywhere.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const dC = x1-x0; should be equivalent because the cells are adjacent.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sorry, forgot this wasn't an index. Then just use Math.sign()

var dR = y0 < y1 ? 1 : (y0 > y1 ? -1 : 0);
let directions;
if (dC == 0) {
// Vertical comparison
if (dR == 0)
throw new Error("Whelp this makes no sense")
let comparisonDirection = dR * constraint.mode;
directions = [
'M', x - comparisonSize, y - comparisonDirection * comparisonSize * squash - dR * inset,
'L', x , y + comparisonDirection * comparisonSize * squash - dR * inset,
'L', x + comparisonSize, y - comparisonDirection * comparisonSize * squash - dR * inset,
]
} else {
if (dC == 0) throw new Error("Whelp this makes no sense")
let comparisonDirection = dC * constraint.mode;
directions = [
'M', x - comparisonDirection * comparisonSize * squash - dC * inset, y - comparisonSize,
'L', x + comparisonDirection * comparisonSize * squash - dC * inset, y,
'L', x - comparisonDirection * comparisonSize * squash - dC * inset, y + comparisonSize,
]
}
let path = createSvgElement('path');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use this._makePath, then you can just pass a list of points.

path.setAttribute('d', directions.join(' '));
path.setAttribute('fill', 'transparent');
path.setAttribute('stroke', 'black');
path.setAttribute('stroke-width', 1);
path.setAttribute('stroke-linecap', 'round');
result.appendChild(path);
}
for (let secondaryCell of secondaryCells)
drawDecoration(primaryCell, secondaryCell)
this._svg.append(result);
return result;
}
}
68 changes: 68 additions & 0 deletions js/sudoku_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -1632,6 +1632,63 @@ class SudokuConstraint {
);
}

static Comparison = class Comparison extends SudokuConstraintBase {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, change to GreaterThan

static DESCRIPTION = (`
Comparison: compare value between adjacent cells.`);
static CATEGORY = 'LinesAndSets';
static DISPLAY_CONFIG = {
displayClass: 'Comparison',
};
static ARGUMENT_CONFIG = {
label: "mode",
options: [
{ value: '1', text: 'Maximum' },
{ value: '-1', text: 'Minimum' },
],
};

static VALIDATE_CELLS_FN = ([primary, ...secondaries], shape) => {
if (!secondaries.length)
return false;
for (let secondary of secondaries) {
if (!this._cellsAreAdjacent([primary, secondary], shape))
return false;
}
return true;
}

constructor(mode, primaryCell, ...secondaryCells) {
secondaryCells.sort();
super([mode, primaryCell, ...secondaryCells]);
this.mode = +mode;
this.primaryCell = primaryCell;
this.secondaryCells = secondaryCells;
}

static displayName() {
return 'Comparison'
}

_symbol() {
switch (this.mode) {
case 1:
return '>';
case -1:
return '<';
default:
throw new Error("Invalid state")
}
}
chipLabel() {
return `${this.primaryCell} ${this._symbol()} [${this.secondaryCells}]`;
}

static fnKey = memoize((mode, numValues) =>
SudokuConstraint.Binary.fnToKey((a, b) => (mode < 0) ? (a < b) : (a > b), numValues)
);

}

static X = class X extends SudokuConstraintBase {
static DESCRIPTION = (`
Values must add to 10. Adjacent cells only.`);
Expand Down Expand Up @@ -2865,6 +2922,17 @@ class SudokuBuilder {
yield new SudokuConstraintHandler.Sum(cells, 5);
break;

case 'Comparison': {
let mode = constraint.mode;
let primaryCell = shape.parseCellId(constraint.primaryCell).cell;
let fn = SudokuConstraint.Comparison.fnKey(mode, shape.numValues);
for (let secondary of constraint.secondaryCells) {
let secondaryCell = shape.parseCellId(secondary).cell;
yield new SudokuConstraintHandler.BinaryConstraint(primaryCell, secondaryCell, fn);
}
break;
}

case 'ValueIndexing':
{
const cells = constraint.cells.map(
Expand Down