๐ฒ ํ๋ฅ ์คํ์ค - ์ฃผ์ฌ์/๋์ /์นด๋ ์๋ฎฌ๋ ์ดํฐ
g5se-probability-lab
๋ฌธ์ ์ค๋ช
๐ฏ ํ๋ก์ ํธ ๊ฐ์
ํ๋ฅ ๊ณผ ํต๊ณ๋ฅผ ์ง๊ด์ ์ผ๋ก ์ฒดํํ ์ ์๋ ์ธํฐ๋ํฐ๋ธ ์๋ฎฌ๋ ์ดํฐ์ ๋๋ค. ์ฃผ์ฌ์, ๋์ , ์นด๋ ๋ฝ๊ธฐ ๋ฑ ๋ค์ํ ํ๋ฅ ์คํ์ ๋ฐ๋ณต ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ค์๊ฐ ์ฐจํธ๋ก ํ์ธํ ์ ์์ต๋๋ค.
์ํ ๊ต์ก, ํ๋ฅ ํ์ต, ๋๋ ๋จ์ํ "์ด ์ฃผ์ฌ์ ์ ๋ง ๊ณต์ ํ๊ฐ?" ๊ฐ์ ๊ถ๊ธ์ฆ์ ํด๊ฒฐํ๋ ์ฌ๋ฏธ์๋ ๋๊ตฌ์ ๋๋ค.
โ ํ์ ๊ธฐ๋ฅ
-
3๊ฐ์ง ์คํ ๋ชจ๋
- ์ฃผ์ฌ์ ๋์ง๊ธฐ (1~6)
- ๋์ ๋์ง๊ธฐ (์๋ฉด/๋ท๋ฉด)
- ์นด๋ ๋ฝ๊ธฐ (52์ฅ ๋ฑ์์ ๋ฌด์์)
-
์คํ ์ค์
- ์คํ ํ์ ์ ๋ ฅ (10ํ ~ 10000ํ)
- "์คํ ์์" ๋ฒํผ ํด๋ฆญ ์ ์ฆ์ ์คํ
-
๊ฒฐ๊ณผ ์๊ฐํ
- ๊ฐ ๊ฒฐ๊ณผ๋ณ ์ถํ ํ์ ๋ง๋ ๊ทธ๋ํ (CSS๋ก ๊ตฌํ)
- ์ด๋ก ์ ํ๋ฅ vs ์ค์ ํ๋ฅ ๋น๊ต ํ์
- ์ด ์คํ ํ์, ์ต๋ค ์ถํ ๊ฒฐ๊ณผ ํ์ด๋ผ์ดํธ
-
ํ์คํ ๋ฆฌ ๋ก๊ทธ
- ์ต๊ทผ 20๊ฐ ์คํ ๊ฒฐ๊ณผ ํ์๋ผ์ธ
- "๋ชจ๋ ์ง์ฐ๊ธฐ" ๋ฒํผ
-
๋คํฌ๋ชจ๋ ๋์
- modern shell์ ๋์์ธ ํ ํฐ ํ์ฉ
- ์ฐจํธ ์์๋ ๋คํฌ๋ชจ๋์์ ๊ฐ๋ ์ฑ ์ ์ง
๐ ์ ํ ์ถ๊ฐ ๊ธฐ๋ฅ (๋ณด๋์ค)
- ์ ๋๋ฉ์ด์ : ์คํ ์คํ ์ค "์ฃผ์ฌ์ ๊ตด๋ฌ๊ฐ๋" ํจ๊ณผ
- CSV ๋ค์ด๋ก๋: ์คํ ๊ฒฐ๊ณผ๋ฅผ ํ์ผ๋ก ์ ์ฅ
- ์ฌ์ฉ์ ์ ์ ์ฃผ์ฌ์: 6๋ฉด ๋์ 4๋ฉด/8๋ฉด/20๋ฉด ์ ํ
- ์ฐ์ ์คํ ๋น๊ต: ์ฌ๋ฌ ์คํ์ ๋๋ํ ๋น๊ตํ๋ ๋์๋ณด๋
๐จ UI/UX ํฌ์ธํธ
- ์คํ ๋ชจ๋ ์ ํ์ ํฐ ์นด๋ํ ๋ฒํผ (์์ด์ฝ + ์ด๋ฆ)
- ๊ฒฐ๊ณผ ์ฐจํธ๋ ์ค์๊ฐ์ผ๋ก ์ ๋๋ฉ์ด์ ํ๋ฉฐ ์ฑ์์ง
- ์ด๋ก ํ๋ฅ ๋๋น ์ค์ฐจ๊ฐ ํด ๊ฒฝ์ฐ ๊ฒฝ๊ณ ๋ฐฐ์ง ํ์
- ๋ชจ๋ฐ์ผ์์๋ ์ฐจํธ๊ฐ ๋ช ํํ ๋ณด์ด๋๋ก ๋ฐ์ํ ๋์์ธ
์ ์ฝ ์กฐ๊ฑด
- โข g5se ํ๋ ์์ํฌ ์ฌ์ฉ (Laravel/Composer/npm ๊ธ์ง)
- โข ํด๋ ์๋ ๋ผ์ฐํ : app/modules/probability-lab/index.php ์์ฑ
- โข modern shell ์ ์ฉ ํ์ (_head.inc.php + m-shell + _nav.inc.php + m-container + _footer.inc.php)
- โข ๋์์ธ ํ ํฐ ์ฌ์ฉ: var(--m-surface), var(--m-text), var(--m-shadow) ๋ฑ
- โข SQLite DB ์ฌ์ฉ: G5_DATA_PATH.'/modules/probability-lab.sqlite' (ํ์คํ ๋ฆฌ ์ ์ฅ์ฉ)
- โข ์์ HTML/CSS/JS๋ก ์ฐจํธ ๊ตฌํ (Chart.js ๊ฐ์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ธ์ง)
- โข prepared statement๋ก SQL ์ธ์ ์ ๋ฐฉ์ง
- โข ์ถ๋ ฅ ์ด์ค์ผ์ดํ: htmlspecialchars() ์ฌ์ฉ
- โข ๋ชจ๋ฐ์ผ ๋ฐ์ํ ๋์์ธ (๋ฏธ๋์ด ์ฟผ๋ฆฌ ํ์ฉ)
ํ๋กฌํํธ ๋ ์ํผ
์๋ ํ๋กฌํํธ๋ฅผ ์์๋๋ก AI์๊ฒ ๋ณด๋ด๋ฉด ๋ฉ๋๋ค. ๋ณต์ฌ ๋ฒํผ์ ๋๋ฌ ๋ฐ๋ก ์ฌ์ฉํ์ธ์.
g5se๊ฐ ์ค์น๋ ๋๋ ํฐ๋ฆฌ(๋ฃจํธ์ `index.php`ยท`app/`์ด ์๋ ๊ณณ)์์ ์์
์ ์์ํฉ๋๋ค. (g5se ์ค์น๋ https://github.com/gnuboard/g5se ์ฐธ๊ณ )
**Step 1: ํ๋ก์ ํธ ๊ณจ๊ฒฉ & modern shell ์ ์ฉ**
`app/modules/probability-lab/index.php` ํ์ผ์ ์์ฑํ๊ณ ๋ค์ ๋ด์ฉ์ ์์ฑํ์ธ์:
```php
<?php
include_once('./_common.php');
// DB ์ฐ๊ฒฐ (ํ์คํ ๋ฆฌ ์ ์ฅ์ฉ)
$db_dir = G5_DATA_PATH.'/modules';
if (!is_dir($db_dir)) {
@mkdir($db_dir, 0707, true);
}
$db_path = $db_dir.'/probability-lab.sqlite';
$pdo = new PDO('sqlite:'.$db_path);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// ํ
์ด๋ธ ์์ฑ (์ต์ด 1ํ)
$pdo->exec("
CREATE TABLE IF NOT EXISTS experiments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
mode TEXT NOT NULL,
trials INTEGER NOT NULL,
results TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
");
require_once(G5_THEME_PATH.'/modern/_head.inc.php');
include_once('./head.sub.php');
?>
<style>
.lab-header {
text-align: center;
margin-bottom: 32px;
}
.lab-header h1 {
font-size: 2rem;
font-weight: 700;
color: var(--m-text);
margin-bottom: 8px;
}
.lab-header p {
color: var(--m-text-muted);
font-size: 1rem;
}
.mode-selector {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-bottom: 32px;
}
.mode-card {
background: var(--m-surface);
border: 2px solid transparent;
border-radius: var(--m-radius-lg);
padding: 24px;
text-align: center;
cursor: pointer;
transition: all 0.2s;
box-shadow: var(--m-shadow);
}
.mode-card:hover {
border-color: var(--m-primary);
transform: translateY(-4px);
}
.mode-card.active {
border-color: var(--m-primary);
background: linear-gradient(135deg, rgba(79, 70, 229, 0.1), rgba(99, 102, 241, 0.05));
}
.mode-icon {
font-size: 3rem;
margin-bottom: 12px;
}
.mode-name {
font-size: 1.1rem;
font-weight: 600;
color: var(--m-text);
}
</style>
<div class="m-shell">
<?php require G5_THEME_PATH.'/modern/_nav.inc.php'; ?>
<main class="m-container" style="padding: 32px 20px 48px;">
<div class="lab-header">
<h1>๐ฒ ํ๋ฅ ์คํ์ค</h1>
<p>์ฃผ์ฌ์, ๋์ , ์นด๋ โ ํ๋ฅ ์ ์ธ๊ณ๋ฅผ ์ฒดํํ์ธ์</p>
</div>
<div class="mode-selector">
<div class="mode-card active" data-mode="dice">
<div class="mode-icon">๐ฒ</div>
<div class="mode-name">์ฃผ์ฌ์</div>
</div>
<div class="mode-card" data-mode="coin">
<div class="mode-icon">๐ช</div>
<div class="mode-name">๋์ </div>
</div>
<div class="mode-card" data-mode="card">
<div class="mode-icon">๐</div>
<div class="mode-name">์นด๋</div>
</div>
</div>
<div style="text-align: center; color: var(--m-text-muted); padding: 40px;">
์คํ ์ค์ UI๋ Step 2์์ ์ถ๊ฐํฉ๋๋ค.
</div>
</main>
<?php require G5_THEME_PATH.'/modern/_footer.inc.php'; ?>
</div>
<?php include_once('./tail.sub.php'); ?>
```
์ด ๋จ๊ณ์์๋:
- modern shell ๊ณจ๊ฒฉ ์ ์ฉ
- SQLite DB ์ด๊ธฐํ (experiments ํ
์ด๋ธ)
- 3๊ฐ์ง ์คํ ๋ชจ๋ ์ ํ ์นด๋ UI
- ๋์์ธ ํ ํฐ์ผ๋ก ๋คํฌ๋ชจ๋ ์๋ ๋์
๋ธ๋ผ์ฐ์ ์์ `/probability-lab` ์ ์ ์ ๋ชจ๋ ์ ํ ์นด๋ 3๊ฐ๊ฐ ๋ณด์ฌ์ผ ํฉ๋๋ค.
๊ธฐ๋ ๊ฒฐ๊ณผ: `/probability-lab` URL๋ก ์ ์ํ๋ฉด modern shell์ด ์ ์ฉ๋ ํ์ด์ง๊ฐ ๋ํ๋๊ณ , ์ฃผ์ฌ์/๋์ /์นด๋ 3๊ฐ์ ๋ชจ๋ ์ ํ ์นด๋๊ฐ ๊ทธ๋ฆฌ๋๋ก ๋ฐฐ์น๋ฉ๋๋ค. ์นด๋ ํด๋ฆญ ์ active ํด๋์ค๊ฐ ํ ๊ธ๋๋ฉฐ ์ ํ ์ํ๊ฐ ์๊ฐ์ ์ผ๋ก ํ์๋ฉ๋๋ค. SQLite DB ํ์ผ์ด ์๋ ์์ฑ๋๊ณ experiments ํ ์ด๋ธ์ด ์ค๋น๋ฉ๋๋ค.
**Step 2: ์คํ ์ค์ ํผ & ์คํ ๋ก์ง ์ถ๊ฐ**
`app/modules/probability-lab/index.php` ํ์ผ์ ์์ ํ์ฌ ์คํ ์ค์ UI์ ๋ฐฑ์๋ ๋ก์ง์ ์ถ๊ฐํ์ธ์.
**์์ ๋ด์ฉ:**
1. **AJAX ๋ถ๊ธฐ ์ฒ๋ฆฌ** (ํ์ผ ์๋จ, `$pdo` ์ ์ ์งํ์ ์ถ๊ฐ):
```php
// AJAX ์์ฒญ ์ฒ๋ฆฌ
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
header('Content-Type: application/json');
if ($_POST['action'] === 'run_experiment') {
$mode = $_POST['mode'] ?? 'dice';
$trials = max(10, min(10000, intval($_POST['trials'] ?? 100)));
$results = [];
for ($i = 0; $i < $trials; $i++) {
if ($mode === 'dice') {
$results[] = rand(1, 6);
} elseif ($mode === 'coin') {
$results[] = rand(0, 1) === 0 ? 'heads' : 'tails';
} else { // card
$suits = ['โ ', 'โฅ', 'โฆ', 'โฃ'];
$ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
$results[] = $ranks[rand(0, 12)] . $suits[rand(0, 3)];
}
}
// DB ์ ์ฅ
$stmt = $pdo->prepare("INSERT INTO experiments (mode, trials, results) VALUES (?, ?, ?)");
$stmt->execute([$mode, $trials, json_encode($results)]);
echo json_encode([
'success' => true,
'results' => $results,
'id' => $pdo->lastInsertId()
]);
exit;
}
}
```
2. **์คํ ์ค์ UI ์ถ๊ฐ** (`<div class="mode-selector">` ๋ค์์):
```php
<div class="experiment-control" style="background: var(--m-surface); padding: 24px; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); margin-bottom: 32px;">
<div style="margin-bottom: 16px;">
<label style="display: block; margin-bottom: 8px; font-weight: 600; color: var(--m-text);">์คํ ํ์</label>
<input type="number" id="trials" min="10" max="10000" value="100" style="width: 100%; padding: 12px; border: 1px solid var(--m-text-muted); border-radius: 8px; background: var(--m-surface); color: var(--m-text); font-size: 1rem;">
</div>
<button id="runBtn" style="width: 100%; padding: 16px; background: linear-gradient(135deg, #4f46e5, #6366f1); color: white; border: none; border-radius: 8px; font-size: 1.1rem; font-weight: 600; cursor: pointer; transition: all 0.2s;">๐ ์คํ ์์</button>
</div>
<div id="resultsContainer" style="display: none;"></div>
```
3. **JavaScript ์ถ๊ฐ** (`</main>` ์ง์ ์):
```php
<script>
let currentMode = 'dice';
// ๋ชจ๋ ์ ํ
document.querySelectorAll('.mode-card').forEach(card => {
card.addEventListener('click', () => {
document.querySelectorAll('.mode-card').forEach(c => c.classList.remove('active'));
card.classList.add('active');
currentMode = card.dataset.mode;
});
});
// ์คํ ์คํ
document.getElementById('runBtn').addEventListener('click', async () => {
const trials = document.getElementById('trials').value;
const btn = document.getElementById('runBtn');
btn.disabled = true;
btn.textContent = 'โณ ์คํ ์ค...';
const formData = new FormData();
formData.append('action', 'run_experiment');
formData.append('mode', currentMode);
formData.append('trials', trials);
const response = await fetch(window.location.href, {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
displayResults(data.results);
}
btn.disabled = false;
btn.textContent = '๐ ์คํ ์์';
});
function displayResults(results) {
const container = document.getElementById('resultsContainer');
container.style.display = 'block';
container.innerHTML = '<div style="text-align: center; padding: 40px; color: var(--m-text);">๊ฒฐ๊ณผ ์ฐจํธ๋ Step 3์์ ์ถ๊ฐํฉ๋๋ค.<br>์ด ' + results.length + 'ํ ์คํ ์๋ฃ</div>';
}
</script>
```
์ด ๋จ๊ณ์์๋:
- ์คํ ํ์ ์
๋ ฅ ํผ
- "์คํ ์์" ๋ฒํผ
- AJAX๋ก ์คํ ์คํ & ๊ฒฐ๊ณผ ์ ์ฅ
- ์คํ ๊ฒฐ๊ณผ ๊ธฐ์ด ํ์
๋ฒํผ ํด๋ฆญ ์ ์คํ์ด ์คํ๋๊ณ "์ด Nํ ์คํ ์๋ฃ" ๋ฉ์์ง๊ฐ ๋ํ๋์ผ ํฉ๋๋ค.
๊ธฐ๋ ๊ฒฐ๊ณผ: ์คํ ํ์ ์ ๋ ฅ๋๊ณผ "์คํ ์์" ๋ฒํผ์ด ์ถ๊ฐ๋ฉ๋๋ค. ๋ฒํผ ํด๋ฆญ ์ AJAX๋ก ์คํ์ด ์คํ๋๊ณ , ๋ฐฑ์๋์์ ๋ฌด์์ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ์ฌ DB์ ์ ์ฅํ ๋ค JSON์ผ๋ก ๋ฐํํฉ๋๋ค. ํ๋ก ํธ์๋๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ "์ด Nํ ์คํ ์๋ฃ" ๋ฉ์์ง๋ฅผ ํ์ํฉ๋๋ค. ์คํ ์ค์๋ ๋ฒํผ์ด ๋นํ์ฑํ๋๊ณ "โณ ์คํ ์ค..." ํ ์คํธ๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค.
**Step 3: ๊ฒฐ๊ณผ ์๊ฐํ ์ฐจํธ & ํ์คํ ๋ฆฌ ๋ก๊ทธ**
`app/modules/probability-lab/index.php` ํ์ผ์ ์์ ํ์ฌ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ ๊ทธ๋ํ๋ก ์๊ฐํํ๊ณ ํ์คํ ๋ฆฌ ๋ก๊ทธ๋ฅผ ํ์ํ์ธ์.
**์์ ๋ด์ฉ:**
1. **ํ์คํ ๋ฆฌ ์กฐํ ๋ก์ง** (AJAX ๋ถ๊ธฐ ์ฒ๋ฆฌ ๋ถ๋ถ์ ์ถ๊ฐ):
```php
if ($_POST['action'] === 'get_history') {
$stmt = $pdo->query("SELECT * FROM experiments ORDER BY created_at DESC LIMIT 20");
$history = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'history' => $history]);
exit;
}
if ($_POST['action'] === 'clear_history') {
$pdo->exec("DELETE FROM experiments");
echo json_encode(['success' => true]);
exit;
}
```
2. **ํ์คํ ๋ฆฌ UI ์ถ๊ฐ** (`<div id="resultsContainer">` ๋ค์์):
```php
<div id="historyContainer" style="background: var(--m-surface); padding: 24px; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); margin-top: 32px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
<h3 style="margin: 0; color: var(--m-text);">๐ ์คํ ํ์คํ ๋ฆฌ</h3>
<button id="clearHistoryBtn" style="padding: 8px 16px; background: #ef4444; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.9rem;">๋ชจ๋ ์ง์ฐ๊ธฐ</button>
</div>
<div id="historyList" style="color: var(--m-text-muted); text-align: center; padding: 20px;">์คํ์ ์คํํ๋ฉด ํ์คํ ๋ฆฌ๊ฐ ํ์๋ฉ๋๋ค.</div>
</div>
```
3. **JavaScript ์์ ** (๊ธฐ์กด `displayResults` ํจ์๋ฅผ ๋ค์์ผ๋ก ๊ต์ฒด):
```php
<script>
// ... (๊ธฐ์กด ๋ชจ๋ ์ ํ, ์คํ ์คํ ์ฝ๋ ์ ์ง)
function displayResults(results) {
const container = document.getElementById('resultsContainer');
container.style.display = 'block';
// ๊ฒฐ๊ณผ ์ง๊ณ
const counts = {};
results.forEach(r => {
const key = String(r);
counts[key] = (counts[key] || 0) + 1;
});
// ์ ๋ ฌ (์ฃผ์ฌ์๋ ์ซ์ ์, ๋๋จธ์ง๋ ์ถํ ๋น๋ ์)
let sortedKeys;
if (currentMode === 'dice') {
sortedKeys = Object.keys(counts).sort((a, b) => parseInt(a) - parseInt(b));
} else {
sortedKeys = Object.keys(counts).sort((a, b) => counts[b] - counts[a]);
}
// ์ฐจํธ HTML ์์ฑ
let html = '<div style="background: var(--m-surface); padding: 24px; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow);">';
html += '<h3 style="margin: 0 0 16px 0; color: var(--m-text);">๐ ์คํ ๊ฒฐ๊ณผ</h3>';
html += '<div style="margin-bottom: 20px; color: var(--m-text-muted);">์ด ' + results.length + 'ํ ์คํ</div>';
const maxCount = Math.max(...Object.values(counts));
sortedKeys.forEach(key => {
const count = counts[key];
const percentage = ((count / results.length) * 100).toFixed(1);
const barWidth = (count / maxCount) * 100;
html += '<div style="margin-bottom: 12px;">';
html += '<div style="display: flex; justify-content: space-between; margin-bottom: 4px; color: var(--m-text); font-size: 0.9rem;">';
html += '<span>' + key + '</span>';
html += '<span>' + count + 'ํ (' + percentage + '%)</span>';
html += '</div>';
html += '<div style="background: rgba(79, 70, 229, 0.1); border-radius: 4px; height: 24px; overflow: hidden;">';
html += '<div style="background: linear-gradient(135deg, #4f46e5, #6366f1); width: ' + barWidth + '%; height: 100%; transition: width 0.5s;"></div>';
html += '</div>';
html += '</div>';
});
html += '</div>';
container.innerHTML = html;
// ํ์คํ ๋ฆฌ ์๋ก๊ณ ์นจ
loadHistory();
}
async function loadHistory() {
const formData = new FormData();
formData.append('action', 'get_history');
const response = await fetch(window.location.href, {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success && data.history.length > 0) {
let html = '';
data.history.forEach(exp => {
const date = new Date(exp.created_at);
const modeIcon = exp.mode === 'dice' ? '๐ฒ' : exp.mode === 'coin' ? '๐ช' : '๐';
html += '<div style="padding: 12px; border-bottom: 1px solid rgba(128,128,128,0.1); color: var(--m-text); font-size: 0.9rem;">';
html += modeIcon + ' ' + exp.mode + ' โ ' + exp.trials + 'ํ ์คํ | ' + date.toLocaleString('ko-KR');
html += '</div>';
});
document.getElementById('historyList').innerHTML = html;
} else {
document.getElementById('historyList').innerHTML = '<div style="text-align: center; padding: 20px; color: var(--m-text-muted);">์คํ ํ์คํ ๋ฆฌ๊ฐ ์์ต๋๋ค.</div>';
}
}
// ํ์คํ ๋ฆฌ ์ญ์
document.getElementById('clearHistoryBtn').addEventListener('click', async () => {
if (!confirm('๋ชจ๋ ํ์คํ ๋ฆฌ๋ฅผ ์ญ์ ํ์๊ฒ ์ต๋๊น?')) return;
const formData = new FormData();
formData.append('action', 'clear_history');
await fetch(window.location.href, {
method: 'POST',
body: formData
});
loadHistory();
});
// ํ์ด์ง ๋ก๋ ์ ํ์คํ ๋ฆฌ ๋ถ๋ฌ์ค๊ธฐ
loadHistory();
</script>
```
์ด ๋จ๊ณ์์๋:
- ๊ฒฐ๊ณผ๋ฅผ ์ง๊ณํ์ฌ ๋ง๋ ๊ทธ๋ํ๋ก ์๊ฐํ
- ๊ฐ ๊ฒฐ๊ณผ๋ณ ์ถํ ํ์์ ๋ฐฑ๋ถ์จ ํ์
- ์คํ ํ์คํ ๋ฆฌ ์ต๊ทผ 20๊ฐ ํ์
- "๋ชจ๋ ์ง์ฐ๊ธฐ" ๋ฒํผ์ผ๋ก ํ์คํ ๋ฆฌ ์ญ์
์คํ ์คํ ํ ๋ง๋ ๊ทธ๋ํ์ ํ์คํ ๋ฆฌ ๋ก๊ทธ๊ฐ ๋ํ๋์ผ ํฉ๋๋ค.
๊ธฐ๋ ๊ฒฐ๊ณผ: ์คํ ์คํ ์ ๊ฒฐ๊ณผ๊ฐ ๋ง๋ ๊ทธ๋ํ๋ก ์๊ฐํ๋ฉ๋๋ค. ๊ฐ ๊ฒฐ๊ณผ(์ฃผ์ฌ์ 1~6, ๋์ ์/๋ค, ์นด๋ ๋ญํฌ+๋ฌด๋ฌ)๋ณ๋ก ์ถํ ํ์์ ๋ฐฑ๋ถ์จ์ด ํ์๋๊ณ , ๋ง๋์ ๊ธธ์ด๊ฐ ๋น์จ์ ๋ฐ๋ผ ์กฐ์ ๋ฉ๋๋ค. ํ๋จ์ ์คํ ํ์คํ ๋ฆฌ๊ฐ ์ต๊ทผ 20๊ฐ๊น์ง ํ์๋๋ฉฐ, "๋ชจ๋ ์ง์ฐ๊ธฐ" ๋ฒํผ์ผ๋ก ํ์คํ ๋ฆฌ๋ฅผ ์ญ์ ํ ์ ์์ต๋๋ค. ํ์ด์ง ๋ก๋ ์ ๊ธฐ์กด ํ์คํ ๋ฆฌ๊ฐ ์๋์ผ๋ก ๋ถ๋ฌ์์ง๋๋ค.
์ ์ถ๋ ์ํ (0)
๋ก๊ทธ์ธ ํ ์ ์ถ์์ง ์ ์ถ๋ ์ํ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋์ ์๊ฐ ๋์ด๋ณด์ธ์!