Skip to content
Open
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
.DS_Store
.idea
tailwind-full.config.js
pnpm-lock.yaml
pnpm-lock.yaml
package-lock.json
.README.analysis.md
10 changes: 0 additions & 10 deletions README.md

This file was deleted.

10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"build": "rollup -c --environment NODE_ENV:production",
"postbuild": "node scripts/postbuild.js",
"predev": "rimraf dist",
"dev": "rollup -c -w",
"dev": "node scripts/dev.js",
"dev:watch": "rollup -c -w",
"dev:serve": "sirv dist --dev",
"start": "sirv dist"
},
"devDependencies": {
Expand All @@ -17,7 +19,7 @@
"postcss": "8.4.31",
"postcss-clean": "1.1.0",
"postcss-import": "13.0.0",
"postcss-load-config": "3.0.0",
"postcss-load-config": "^2.1.2",
"reaver": "2.0.0",
"rimraf": "3.0.2",
"rollup": "2.33.3",
Expand All @@ -31,6 +33,10 @@
},
"dependencies": {
"@mattflow/sudoku-solver": "2.2.0",
"axios": "^1.13.2",
"cheerio": "^1.1.0",
"cors": "^2.8.5",
"express": "^5.2.1",
"fake-sudoku-puzzle-generator": "1.2.1",
"sirv-cli": "1.0.0",
"tailwindcss": "1.9.6"
Expand Down
68 changes: 68 additions & 0 deletions scripts/dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const { spawn } = require('child_process');
const scripts = ['dev:watch', 'dev:serve'];
const children = [];
let shuttingDown = false;

function getSpawnCommand(script) {
const nodeExec = process.env.npm_node_execpath || process.execPath;
const npmCli = process.env.npm_execpath;

if (npmCli) {
return {
command: nodeExec,
args: [npmCli, 'run', script],
};
}

const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
return {
command: npmCommand,
args: ['run', script],
};
}

function start(script) {
const { command, args } = getSpawnCommand(script);
const child = spawn(command, args, {
stdio: 'inherit',
env: process.env,
shell: false,
});

children.push(child);

child.on('exit', (code, signal) => {
if (!shuttingDown) {
const exitCode = typeof code === 'number' ? code : signal ? 1 : 0;
shutdown(exitCode);
}
});

child.on('error', (error) => {
console.error(`[dev] Failed to run ${script}:`, error);
if (!shuttingDown) {
shutdown(1);
}
});
}

function shutdown(code = 0) {
if (!shuttingDown) {
shuttingDown = true;
for (const child of children) {
if (!child.killed) {
child.kill();
}
}
}

// Allow child processes a brief moment to exit gracefully.
setTimeout(() => {
process.exit(code);
}, 100);
}

process.on('SIGINT', () => shutdown(0));
process.on('SIGTERM', () => shutdown(0));

scripts.forEach(start);
15 changes: 13 additions & 2 deletions src/components/Controls/ActionBar/Actions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { settings } from '@sudoku/stores/settings';
import { keyboardDisabled } from '@sudoku/stores/keyboard';
import { gamePaused } from '@sudoku/stores/game';
import { modal } from '@sudoku/stores/modal';

$: hintsAvailable = $hints > 0;

Expand All @@ -17,6 +18,16 @@
}

userGrid.applyHint($cursor);
}else{
modal.show('nohints', {
title: 'No Hints Left',
text: 'You have used all available hints for this puzzle.',
button: 'Continue',
callback: () => {
// console.log('User acknowledged no hints');
// 可以在这里添加其他逻辑
}
});
}
}
</script>
Expand All @@ -34,8 +45,8 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 10h-10a8 8 90 00-8 8v2M21 10l-6 6m6-6l-6-6" />
</svg>
</button>

<button class="btn btn-round btn-badge" disabled={$keyboardDisabled || !hintsAvailable || $userGrid[$cursor.y][$cursor.x] !== 0} on:click={handleHint} title="Hints ({$hints})">
<!-- disabled={$keyboardDisabled || !hintsAvailable || $userGrid[$cursor.y][$cursor.x] !== 0} -->
<button class="btn btn-round btn-badge" on:click={handleHint} title="Hints ({$hints})">
<svg class="icon-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
</svg>
Expand Down
74 changes: 64 additions & 10 deletions src/components/Header/Dropdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import { slide, fade } from 'svelte/transition';
import { DIFFICULTIES, DROPDOWN_DURATION, DIFFICULTY_CUSTOM } from '@sudoku/constants';
import { difficulty } from '@sudoku/stores/difficulty';
import SudokuParser from '@sudoku/stores/solver'


let dropdownVisible = false;

Expand All @@ -14,28 +16,74 @@

modal.show('confirm', {
title: 'New Game',
text: 'Start new game with difficulty "' + DIFFICULTIES[difficultyValue] + '"?',
text: 'Start new game with difficulty ' + DIFFICULTIES[difficultyValue] + '"?',
button: 'Continue',
onHide: game.resume,
callback: () => {
game.startNew(difficultyValue);
},
});
}
function extractPuzzleFromUrl(url) {
// 1. 从URL中解析出 'bd' 参数
const urlParams = new URL(url).searchParams;
const boardString = urlParams.get('bd'); // 得到 "400709020000020000090008000..."

// 2. 验证并返回
if (boardString && boardString.length === 81) {
return boardString; // 这就是81位的题目序列
} else {
throw new Error('无法从URL中解析出有效的81位数独题目。');
}
}
function handleSolver(){
dropdownVisible = false;
game.pause()
modal.show('solver', {
title: 'Solver',
text: '',
button: 'Continue',
onHide: game.resume,
callback: (result) => {
const parser = new SudokuParser();
const sequence = parser.parseUrl(result);
game.createNew({
difficulty: "hard",
sequence: sequence
})

},
});
}

function handleCreateOwn() {
dropdownVisible = false;
game.pause();

modal.show('confirm', {
title: 'Create Own',
text: 'Switch to the creator mode to create your own Sudoku puzzle?',
button: 'Continue',
// 在你的代码中调用
modal.show('custom', {
title: 'Create Sudoku Puzzle',
text: 'Fill in the Sudoku puzzle and select difficulty.',
button: 'Validate & Save',
cancelText: 'Cancel',

// 可选的初始序列
initialSequence: '530070000600195000098000060800060003400803001700020006060000280000419005000080079',

// 可选的默认难度(默认是 'veryeasy')
defaultDifficulty: 'medium', // 'veryeasy', 'easy', 'medium', 'hard'

// 关闭时的回调
onHide: game.resume,
callback: () => {
//game.startCreatorMode();
},

// 确认时的回调
callback: (result) => {
if (result.valid) {
game.createNew(result)
}
}
});

}

function handleEnterCode() {
Expand All @@ -53,6 +101,7 @@
},
validate: validateSencode
});

}

function showDropdown() {
Expand Down Expand Up @@ -95,17 +144,22 @@
<svg class="icon-solid" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clip-rule="evenodd" />
</svg>

<span class="align-middle">Create Own</span>
</a>
<a class="dropdown-item" on:click|preventDefault={handleEnterCode} href="/enter-code" title="Enter a Sudoku puzzle code from a friend">
<svg class="icon-solid" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" />
<path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd" />
</svg>

<span class="align-middle">Enter Code</span>
</a>
<a class="dropdown-item" on:click|preventDefault={handleSolver} href="/solver-code" title="crawl the problem from wiki">
<svg class="icon-solid" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" />
<path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd" />
</svg>
<span class="align-middle">Import Solver</span>
</a>
</div>
{/if}
</div>
Expand Down
Loading