This commit is contained in:
2025-08-29 18:01:38 +09:00
parent 3a0a29ec02
commit 373964146c
9 changed files with 383 additions and 1 deletions
@@ -96,3 +96,7 @@ spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
# Increase server connection timeout to 60 seconds (default is often 20 or 30s)
server.tomcat.connection-timeout=60s
# For reactive applications (like yours), also set this timeout
spring.webflux.response-timeout=60s
+41
View File
@@ -0,0 +1,41 @@
#puzzle-container {
display: grid;
/* We will set grid-template-columns/rows with JS */
grid-gap: 2px;
margin-top: 20px;
background-color: #333;
border: 2px solid #333;
width: fit-content;
}
.grid-cell {
width: 25px;
height: 25px;
background-color: #f0f0f0;
text-align: center;
line-height: 25px;
font-size: 14px;
}
.clue-cell {
background-color: #cce7ff;
display: flex;
justify-content: center;
align-items: center;
padding: 5px;
min-height: 25px;
font-weight: bold;
}
.solution-cell {
width: 25px;
height: 25px;
}
.filled {
background-color: #333;
}
.empty {
background-color: #fff;
}
+88
View File
@@ -0,0 +1,88 @@
function drawPuzzle(puzzleData) {
const container = document.getElementById('puzzle-container');
container.innerHTML = ''; // Clear previous puzzle
const { solutionGrid, rowClues, colClues } = puzzleData;
const numRows = solutionGrid.length;
const numCols = solutionGrid[0].length;
// Set up the CSS Grid layout
container.style.gridTemplateColumns = `auto repeat(${numCols}, 1fr)`;
container.style.gridTemplateRows = `auto repeat(${numRows}, 1fr)`;
// 1. Create top-left empty corner
const corner = document.createElement('div');
corner.className = 'grid-cell';
container.appendChild(corner);
// 2. Create column clues (top row)
for (const clues of colClues) {
const clueCell = document.createElement('div');
clueCell.className = 'clue-cell';
clueCell.innerHTML = clues.join('<br>'); // Display clues vertically
container.appendChild(clueCell);
}
// 3. Create row clues and the solution grid
for (let i = 0; i < numRows; i++) {
// Create row clue cell for this row
const rowClueCell = document.createElement('div');
rowClueCell.className = 'clue-cell';
rowClueCell.textContent = rowClues[i].join(' ');
container.appendChild(rowClueCell);
// Create the solution cells for this row
for (let j = 0; j < numCols; j++) {
const cell = document.createElement('div');
cell.className = 'solution-cell';
if (solutionGrid[i][j] === 1) {
cell.classList.add('filled'); // Black square
} else {
cell.classList.add('empty'); // White square
}
container.appendChild(cell);
}
}
}
// Modify your existing click listener
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('createBtn').addEventListener('click', async () => {
const uploader = document.getElementById('imageUploader');
const statusDiv = document.getElementById('status');
const puzzleContainer = document.getElementById('puzzle-container');
if (uploader.files.length === 0) {
statusDiv.textContent = '이미지 파일을 선택해주세요.';
return;
}
const imageFile = uploader.files[0];
const formData = new FormData();
formData.append('imageFile', imageFile);
statusDiv.textContent = '문제를 생성하는 중...';
puzzleContainer.innerHTML = ''; // Clear old puzzle while loading
try {
const response = await fetch(getMainPath()+'/puzzle/upload.bjx', { // Make sure this URL is correct
method: 'POST',
body: formData,
});
if (response.ok) {
const puzzleData = await response.json();
statusDiv.textContent = '문제 생성 성공!';
// Call the new function to draw the puzzle!
drawPuzzle(puzzleData);
} else {
const errorMessage = await response.text();
statusDiv.textContent = `생성 실패: ${errorMessage}`;
}
} catch (error) {
console.error('네트워크 오류:', error);
statusDiv.textContent = '서버와 통신 중 오류가 발생했습니다.';
}
});
});
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
layout:decorate="~{layout/default_layout}"
>
<th:block layout:fragment="head" id="head">
<script type="text/javascript" th:src="@{/js/upload.js}"></script>
<link th:href="@{/css/puzzle.css}" rel="stylesheet" />
<script th:inline="javascript">
</script>
<script type="text/javascript" th:src="@{/js/user.js}"></script>
</th:block >
<th:block layout:fragment="content">
<div id="puzzle-container">
</div>
<hr>
<h1>이미지로 네모로직 문제 만들기</h1>
<input type="file" id="imageUploader" accept="image/*">
<button id="createBtn">문제 생성</button>
<div id="status"></div>
<hr>
<h2>결과</h2>
<div id="result"></div>
</th:block>
</html>