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 daily puzzles #50

Merged
merged 18 commits into from
Aug 21, 2022
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
35 changes: 35 additions & 0 deletions src/lib/header/Grids.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script>
import { page } from '$app/stores';
</script>

<div class="container">
<div class="grids">
<span>Grid:</span>
<a href="/hexagonal/5" class:active={$page.url.pathname.startsWith(`/hexagonal/`)}>
Hexagonal
</a>
<a href="/hexagonal-wrap/5" class:active={$page.url.pathname.startsWith(`/hexagonal-wrap/`)}>
Hexagonal wrap
</a>
</div>
</div>

<style>
.grids {
display: flex;
flex-wrap: wrap;
column-gap: 20px;
margin: auto;
justify-content: center;
color: var(--text-color);
padding: 5px;
}
.grids a,
.grids span {
display: block;
padding: 5px;
}
.active {
outline: 1px solid var(--accent-color);
}
</style>
8 changes: 4 additions & 4 deletions src/lib/header/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
</svg>
<ul>
<li class:active={$page.url.pathname === '/'}><a sveltekit:prefetch href="/">Home</a></li>
<li class:active={$page.url.pathname.startsWith('/hexagonal/')}>
<a sveltekit:prefetch href="/hexagonal">Hexagonal</a>
<li class:active={$page.url.pathname === '/daily'}>
<a sveltekit:prefetch href="/daily">Daily</a>
</li>
<li class:active={$page.url.pathname.startsWith('/hexagonal-wrap/')}>
<a sveltekit:prefetch href="/hexagonal-wrap">Hexagonal wrap</a>
<li class:active={$page.url.pathname.startsWith('/hexagonal')}>
<a sveltekit:prefetch href="/hexagonal">Play</a>
</li>
</ul>
<svg viewBox="0 0 2 3" aria-hidden="true">
Expand Down
11 changes: 4 additions & 7 deletions src/lib/puzzle/EdgeMark.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
import { createEventDispatcher } from 'svelte';
/** @type {import('$lib/puzzle/hexagrid').HexaGrid} */
export let grid;
// coordinates of tile center
export let cx = 0;
export let cy = 0;
export let state = 'none';
export let direction = 1;

Expand All @@ -25,10 +22,10 @@
class="mark"
class:wall={state === 'wall'}
class:connection={state === 'connection'}
x1={cx + 0.5 * offsetX - dx * lineLength}
y1={cy - 0.5 * offsetY + dy * lineLength}
x2={cx + 0.5 * offsetX + dx * lineLength}
y2={cy - 0.5 * offsetY - dy * lineLength}
x1={+0.5 * offsetX - dx * lineLength}
y1={-0.5 * offsetY + dy * lineLength}
x2={+0.5 * offsetX + dx * lineLength}
y2={-0.5 * offsetY - dy * lineLength}
stroke="green"
stroke-width="0.04"
/>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/puzzle/Puzzle.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
let svgWidth = 500;
let svgHeight = 500;

let grid = new HexaGrid(width, height, wrap);
let grid = new HexaGrid(width, height, wrap, tiles);
let game = new PipesGame(grid, tiles, savedProgress);
let solved = game.solved;

Expand Down
34 changes: 10 additions & 24 deletions src/lib/puzzle/Tile.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<script>
import EdgeMark from '$lib/puzzle/EdgeMark.svelte';
import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';

/** @type {Number} i*/
export let i;
Expand All @@ -19,11 +17,6 @@

let bgColor = '#aaa';

let rotationAnimate = tweened($state.rotations, {
duration: 75,
easing: cubicOut
});

// disable edge marks on outer edges of non-wrap puzzles
if (!game.grid.wrap) {
game.grid.EDGEMARK_DIRECTIONS.forEach((direction, index) => {
Expand All @@ -39,13 +32,13 @@
const deltas = myDirections.map((direction) => game.grid.XY_DELTAS.get(direction));
let angle = game.grid.getTileAngle($state.tile);

let path = `M ${cx} ${cy}`;
let path = `M 0 0`;
for (let [dx, dy] of deltas) {
path += ` l ${0.5 * dx} ${-0.5 * dy} L ${cx} ${cy}`;
path += ` l ${0.5 * dx} ${-0.5 * dy} L 0 0`;
}
const isSink = myDirections.length === 1;

const hexagon = `M ${cx} ${cy} ` + game.grid.tilePath;
const hexagon = game.grid.tilePath;

/**
* Choose tile background color
Expand All @@ -61,17 +54,14 @@
}

$: chooseBgColor($state.locked, $state.isPartOfLoop);

// want to animate even if rotation is from another wrap tile
$: rotationAnimate.set($state.rotations);
</script>

<g class="tile" data-index={i} data-x={cx} data-y={cy}>
<g class="tile" data-index={i} data-x={cx} data-y={cy} transform="translate({cx},{cy})">
<!-- Tile hexagon -->
<path d={hexagon} stroke="#aaa" stroke-width="0.02" fill={bgColor} />

<!-- Pipe shape -->
<g transform="rotate({60 * $rotationAnimate}, {cx}, {cy})">
<g class="pipe" style="transform:rotate({60 * $state.rotations}deg)">
<!-- Pipe outline -->
<path
d={path}
Expand All @@ -83,8 +73,8 @@
<!-- Sink circle -->
{#if isSink}
<circle
{cx}
{cy}
cx="0"
cy="0"
r="0.15"
fill={$state.color}
stroke="#888"
Expand All @@ -104,8 +94,8 @@
{#if controlMode === 'orient_lock' && !$state.locked && !solved}
<!-- Guide dot -->
<circle
cx={cx + 0.4 * Math.cos(angle)}
cy={cy - 0.4 * Math.sin(angle)}
cx={0.4 * Math.cos(angle)}
cy={-0.4 * Math.sin(angle)}
fill="orange"
stroke="white"
r="0.03"
Expand All @@ -117,8 +107,6 @@
{#each $state.edgeMarks as _, index (index)}
<EdgeMark
grid={game.grid}
{cx}
{cy}
state={$state.edgeMarks[index]}
direction={game.grid.EDGEMARK_DIRECTIONS[index]}
/>
Expand All @@ -127,9 +115,7 @@
</g>

<style>
.tile {
transform-origin: center;
transform-box: fill-box;
.pipe {
transition: transform 100ms;
}
</style>
15 changes: 10 additions & 5 deletions src/lib/puzzle/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,21 +325,26 @@ export function PipesGame(grid, tiles, savedProgress) {
}
};

let firstValidIndex = 0;
while (self.grid.emptyCells.has(firstValidIndex)) {
firstValidIndex += 1;
}
/**
* @returns {boolean}
*/
self.isSolved = function () {
// console.log('=================== Solved check ======================')
const component = self.components.get(0);
const total = self.grid.total - self.grid.emptyCells.size;
const component = self.components.get(firstValidIndex);
if (component === undefined) {
return false;
}
if (component.tiles.size < self.grid.total) {
if (component.tiles.size < total) {
// console.log('not everything connected yet')
// not everything connected yet
return false;
}
let startCheckAtIndex = 0;
let startCheckAtIndex = firstValidIndex;
let toCheck = new Set([{ fromIndex: -1, tileIndex: startCheckAtIndex }]);
// console.log('start at', startCheckAtIndex)
/** @type Set<Number> */
Expand Down Expand Up @@ -389,8 +394,8 @@ export function PipesGame(grid, tiles, savedProgress) {
toCheck = newChecks;
}
}
if (checked.size < grid.total) {
// console.log('not solved because only', checked.size, 'of', grid.total, 'were reached')
if (checked.size < total) {
// console.log('not solved because only', checked.size, 'of', total, 'were reached')
// it's an island
return false;
}
Expand Down
17 changes: 16 additions & 1 deletion src/lib/puzzle/hexagrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ import { writable, derived, get } from 'svelte/store';
* @param {Number} width
* @param {Number} height
* @param {Boolean} wrap
* @param {Number[]} tiles
*/
export function HexaGrid(width, height, wrap = false) {
export function HexaGrid(width, height, wrap = false, tiles = []) {
let self = this;

const EAST = 1;
Expand Down Expand Up @@ -65,6 +66,13 @@ export function HexaGrid(width, height, wrap = false) {

this.width = width;
this.height = height;
/** @type {Set<Number>} */
this.emptyCells = new Set();
tiles.forEach((tile, index) => {
if (tile === 0) {
this.emptyCells.add(index);
}
});
this.total = width * height;
this.wrap = wrap;

Expand Down Expand Up @@ -287,6 +295,9 @@ export function HexaGrid(width, height, wrap = false) {
} else {
neighbour = self.width * r + c;
}
if (self.emptyCells.has(neighbour)) {
neighbour = -1;
}
return {
neighbour,
wrapped
Expand Down Expand Up @@ -367,6 +378,10 @@ export function HexaGrid(width, height, wrap = false) {
const visibleTiles = [];
for (let r = rmin; r <= rmax; r++) {
for (let c = cmin; c <= cmax; c++) {
const index = self.rc_to_index(r, c);
if (self.emptyCells.has(index)) {
continue;
}
const x = c + (r % 2 === 0 ? 0.0 : 0.5);
const y = r * self.YSTEP;
const key = `${Math.round(10 * x)}_${Math.round(10 * y)}`;
Expand Down
5 changes: 4 additions & 1 deletion src/lib/puzzleWrapper/PuzzleButtons.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { createEventDispatcher } from 'svelte';

export let solved = false;
export let includeNewPuzzleButton = true;

const dispatch = createEventDispatcher();

Expand Down Expand Up @@ -32,7 +33,9 @@
{/if}
</button>
<!-- New puzzle button -->
<button on:click={newPuzzle}> ➡️ New puzzle </button>
{#if includeNewPuzzleButton}
<button on:click={newPuzzle}> ➡️ New puzzle </button>
{/if}
</div>

<style>
Expand Down
2 changes: 2 additions & 0 deletions src/lib/puzzleWrapper/PuzzleWrapper.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import PuzzleButtons from '$lib/puzzleWrapper/PuzzleButtons.svelte';
import Timer from '$lib/Timer.svelte';
import Stats from '$lib/Stats.svelte';
import Settings from '$lib/settings/Settings.svelte';
import { getSolves, getStats } from '$lib/stores';
import { onMount } from 'svelte';

Expand Down Expand Up @@ -124,6 +125,7 @@
});
</script>

<Settings />
{#key `/${category}/${size}/${puzzleId}`}
<Puzzle
{width}
Expand Down
3 changes: 3 additions & 0 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@
<div class="container">
<h2>Changelog</h2>
<ul>
<li>
<em>2022-08-21</em> Added initial version of daily puzzles.
</li>
<li>
<em>2022-08-15</em>
<ul>
Expand Down
26 changes: 26 additions & 0 deletions src/routes/daily/+page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { error } from '@sveltejs/kit';

/** @type {import('./$types').PageLoad} */
export async function load({ fetch }) {
const today = new Date().toISOString();
const year = today.slice(0, 4);
const month = today.slice(5, 7);
const day = today.slice(8, 10);
const url = `/_instances/daily/${year}/${month}/${day}.json`;
const response = await fetch(url);

if (response.ok) {
const data = await response.json();
return {
date: `${year}-${month}-${day}`,
grid: data.grid,
wrap: data.wrap,
width: data.width,
height: data.height,
tiles: data.tiles,
comment: data.comment
};
} else {
throw error(response.status, '');
}
}
Loading