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

Implement grid symmetry #10

Merged
merged 2 commits into from
Mar 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ done
# v= needs to be changed on every push. Find a better way to do this, e.g.
# originated from the server once this is all rendered in Soy.
cat main.html | sed -e $sedcommand | \
sed -e 's#dist/runlocal.js#static/code.js?v=7#' | \
sed -e 's#dist/runlocal.js#static/code.js?v=8#' | \
sed -e 's#"static/#"/static/#g' | \
html-minifier --remove-comments --collapse-whitespace --minify-css \
> build.html
Expand Down
11 changes: 10 additions & 1 deletion main.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@
width: 32px;
height: 32px;
}
.colorButton {
min-width: 48px;
margin: 0;
vertical-align: top;
}
.colorButton.isSelected {
border: 2px solid black;
}
.gridSquare {
margin: 4px;
display: inline-block;
Expand Down Expand Up @@ -198,8 +206,9 @@
.tcell {
min-width: 32px;
min-height: 32px;
margin: 0 3px;
margin: 3px 3px;
background-color: gray;
vertical-align: top;
}
.tcell.yellow {
background-color: yellow;
Expand Down
40 changes: 29 additions & 11 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,12 +319,12 @@ var EditorCtrl = function(
}
$scope['neg'] = false;
$scope['origin'] = window.location.origin;
// May be nullable.
var initializeGridData = function() {
if ($grid.isGridInitialized()) {
var dim = $grid.getDimensions();
$scope['w'] = dim.width;
$scope['h'] = dim.height;
var init = $grid.getInitialState();
$scope['w'] = init.width;
$scope['h'] = init.height;
$scope['symmetry'] = init.symmetry;
}
// If initialized from hash, manually close pane.
// With sunsetting of static simulator, this has changed
Expand All @@ -347,6 +347,8 @@ var EditorCtrl = function(
'hexagon',
'disjoint'
];
// Should match grid.proto.
// In theory could derive a reverse mapping here.
$scope['ccodes'] = {
1: 'black',
2: 'white',
Expand All @@ -355,8 +357,15 @@ var EditorCtrl = function(
5: 'yellow',
6: 'red',
7: 'green',
8: 'blue'
}
8: 'blue',
9: 'orange'
};
$scope['scodes'] = {
1: 'No symmetry',
2: 'Horizontal symmetry',
3: 'Vertical symmetry',
4: 'Rotational symmetry'
};
// Some utilities.
var safeInt = function(i) {
i = parseInt(i);
Expand Down Expand Up @@ -390,6 +399,9 @@ var EditorCtrl = function(
$scope.getSelectClass = function(n) {
return n == $scope['obj'] ? 'isSelected' : null;
}
$scope.getSelectColorClass = function(n) {
return n == $scope['color'] ? 'isSelected' : null;
}
$scope.selectColor = function(n) {
$scope['color'] = n;
}
Expand Down Expand Up @@ -429,7 +441,8 @@ var EditorCtrl = function(
grid: tetris['g'],
gridWidth: 5,
gridFixed: tetris['f'],
count: $scope['count']
count: $scope['count'],
symmetry: safeInt($scope['symmetry'])
};
$grid.setEditEntity(data);
} else if ($mdMedia('gt-sm')) {
Expand All @@ -443,7 +456,7 @@ var EditorCtrl = function(
var tetris = $scope['tetris'][$scope['neg']];
return [
$scope['obj'], $scope['color'], $scope['w'], $scope['h'],
tetris['f'], $scope['neg'], $scope['count']
tetris['f'], $scope['neg'], $scope['count'], $scope['symmetry']
].join('.')
}, alertGrid);
$scope.$watch(function() {
Expand Down Expand Up @@ -514,6 +527,7 @@ var EditorCtrl = function(
// Timeout necessary because the grid can't just be rendered, it has to
// be in the document, and the controller is initiated before document
// inclusion.
// TODO: Revisit this given recent Grid/GridRenderer refactor.
setTimeout(function() {
$grid.render();
if (!gridAvailable) {
Expand Down Expand Up @@ -1030,9 +1044,13 @@ GridService.prototype.getSolvePath = function() {
return grid.solvedPuzzleVersion == grid.solvedPuzzleVersion ?
grid.solvedPuzzlePath : null;
}
GridService.prototype.getDimensions = function() {
GridService.prototype.getInitialState = function() {
var grid = goog.asserts.assert(this.currentGrid());
return {width: grid.grid.width, height: grid.grid.height};
return {
width: grid.grid.width,
height: grid.grid.height,
symmetry: grid.grid.symmetry
};
}
GridService.prototype.setEditEntity = function(opt_data) {
var grid = goog.asserts.assert(this.currentGrid());
Expand Down Expand Up @@ -1101,7 +1119,7 @@ var Config = function(
window.location.href = path;
}
$mdIconProvider
.iconSet('witness', '/static/witness.svg?v=0', 100)
.iconSet('witness', '/static/witness.svg?v=2', 100)
$mdIconProvider
.icon('basic', '/static/basic.svg', 550)

Expand Down
16 changes: 13 additions & 3 deletions src/build.tmpl.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@
</div>
<div style="margin-top: 20px;">
<md-button ng-repeat="(id, name) in ccodes"
style="background-color: {{::name}}; min-width: 48px; margin: 0;"
style="background-color: {{::name}};"
class="colorButton"
title="{{::name|capitalize}}"
aria-label="{{::name|capitalize}}"
ng-click="selectColor(id); $event.stopPropagation()">
ng-click="selectColor(id); $event.stopPropagation()"
ng-class="getSelectColorClass(id)">
</md-button>
</div>
<md-card ng-show="obj == 'tetris' || obj == 'negative'"
Expand All @@ -53,7 +55,7 @@
</div>
<div style="margin-top: 10px">
<md-checkbox ng-model="tetris[neg].f">
Fixed position
Fixed orientation
</md-checkbox>
</div>
</md-card-content>
Expand Down Expand Up @@ -82,6 +84,14 @@
<md-icon md-svg-src="basic"></md-icon>
</md-button>
</div>
<hr>
<div layout="row" style="margin-top: 0;">
<md-input-container style="margin: 0;">
<md-select ng-model="symmetry" aria-label="Symmetry">
<md-option ng-repeat="(id, name) in scodes" ng-value="id">{{name}}</md-option>
</md-select>
</md-input-container>
</div>
<p class="md-body">
See <a href="/faq.html" target="_blank">FAQ</a> for feedback and remaining bugs.
</p>
Expand Down
76 changes: 75 additions & 1 deletion src/grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var GridProto = windmill.GridProto;
var Entity = GridProto.Entity;
var Shape = GridProto.Shape;
var Type = GridProto.Type;
var SymmetryType = GridProto.SymmetryType;
var Color = GridProto.Color;
var Storage = GridProto.Storage;
var Orientation = GridProto.Orientation;
Expand Down Expand Up @@ -72,11 +73,14 @@ Grid.prototype.initialize = function(width, height, opt_data) {
// Grid state.
if (storage) {
this.entities = storage.entity;
this.symmetry = storage.symmetry || SymmetryType.NONE;
this.sanitize();
} else {
this.entities = [];
for (var i = 0; i < this.storeWidth * this.storeHeight; i++) {
this.entities[i] = new Entity();
}
this.symmetry = SymmetryType.NONE;
// Some freebies.
// TODO: More configurations.
this.pointEntity(0, this.height, new Entity(Type.START));
Expand Down Expand Up @@ -192,7 +196,11 @@ Grid.prototype.getHash = function() {
entities.push(e);
}
}, this);
var encode = new Storage(this.storeWidth, entities).encode64();
var storage = new Storage(this.storeWidth, entities);
if (this.symmetry && this.symmetry != SymmetryType.NONE) {
storage.symmetry = this.symmetry;
}
var encode = storage.encode64();
// Make it more URL-safe.
// Note that this only affects 0x3E and 0x3F, which does not occur
// much in protobufs due to how it encodes things.
Expand Down Expand Up @@ -294,6 +302,39 @@ Grid.prototype.forEachEntity = function(fn, opt_scope) {
}
}
}
Grid.prototype.setSymmetry = function(symmetry) {
this.symmetry = symmetry;
this.sanitize();
}
Grid.prototype.sanitize = function() {
var sym = this.getSymmetry();
if (!sym) {
return;
}
this.forEachEntity(function(value, i, j, drawType) {
if (drawType == DrawType.POINT &&
(value.type == Type.START || value.type == Type.END)) {
var ref = sym.reflectPoint({i: i, j: j});
var refValue = this.pointEntity(ref.i, ref.j);
if (value.type != refValue.type) {
if (value.type == Type.END) {
value = new Entity(value);
value.orientation = this.getEndPlacement(ref.i, ref.j);
}
this.pointEntity(ref.i, ref.j, value);
}
}
}, this);
}
Grid.prototype.getSymmetry = function() {
if (this.symmetry == SymmetryType.NONE) {
return null;
} else {
return new Grid.Symmetry(this.symmetry, this.width, this.height);
}
}
// Returns the automatic end orientation at a coord i, j.
// This is symmetrical for all coordinates and symmetries.
Grid.prototype.getEndPlacement = function(i, j) {
for (var di = -1; di <= 1; di += 2) {
var line = this.lineBetweenEntity(i, j, i + di, j);
Expand All @@ -310,4 +351,37 @@ Grid.prototype.getEndPlacement = function(i, j) {
return null;
}

/** @constructor */
Grid.Symmetry = function(type, width, height) {
this.type = type;
this.width = width;
this.height = height;
}
Grid.Symmetry.prototype.reflectPoint = function(coord) {
if (this.type == SymmetryType.HORIZONTAL) {
return {i: this.width - coord.i, j: coord.j};
} else if (this.type == SymmetryType.VERTICAL) {
return {i: coord.i, j: this.height - coord.j};
} else if (this.type == SymmetryType.ROTATIONAL) {
return {i: this.width - coord.i, j: this.height - coord.j};
} else {
throw Error(this.type);
}
}
Grid.Symmetry.prototype.reflectDelta = function(delta) {
// Avoid introducing negative zero here.
var negate = function(n) {
return n == 0 ? n : -n;
}
if (this.type == SymmetryType.HORIZONTAL) {
return {di: negate(delta.di), dj: delta.dj};
} else if (this.type == SymmetryType.VERTICAL) {
return {di: delta.di, dj: negate(delta.dj)};
} else if (this.type == SymmetryType.ROTATIONAL) {
return {di: negate(delta.di), dj: negate(delta.dj)};
} else {
throw Error(this.type);
}
}

});
25 changes: 18 additions & 7 deletions src/grid.proto
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,31 @@ enum Color {
RED = 6;
GREEN = 7;
BLUE = 8;
ORANGE = 9;
}
enum SymmetryType {
UNKNOWN = 0;
NONE = 1;
HORIZONTAL = 2;
VERTICAL = 3;
ROTATIONAL = 4;
}
message Storage {
int32 width = 1;
repeated Entity entity = 2;
optional SymmetryType symmetry = 3;
}
// Non-wire enums.
enum DrawType {
CELL = 0;
POINT = 1;
HLINE = 2;
VLINE = 3;
UNKNOWN = 0;
CELL = 1;
POINT = 2;
HLINE = 3;
VLINE = 4;
}
enum SegmentType {
START = 0;
MIDDLE = 1;
END = 2;
UNKNOWN = 0;
START = 1;
MIDDLE = 2;
END = 3;
}
5 changes: 4 additions & 1 deletion src/grouping.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ var coordKey = windmill.keys.coordKey;
var lineKey = windmill.keys.lineKey;

/** @constructor */
windmill.Path = function(coords, width, height) {
windmill.Path = function(coords, width, height, opt_newPaths) {
// TODO: Also take in a grid shape, to enable non-standard grids.
this.coords = coords;
this.coordsMap = goog.array.toObject(coords, coordKey);
var lines = [];
for (var i = 1; i < coords.length; i++) {
if (opt_newPaths && goog.array.contains(opt_newPaths, i)) {
continue;
}
var c1 = coords[i-1];
var c2 = coords[i];
lines.push({
Expand Down
Loading