...
This commit is contained in:
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user