new commit

This commit is contained in:
54CHA
2025-07-19 17:56:06 +03:00
commit 4153e2c00a
140 changed files with 66097 additions and 0 deletions

View File

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

View File

@ -0,0 +1 @@
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="#444"/><text x="50%" y="50%" font-family="Arial" font-size="14" fill="#fff" text-anchor="middle" dominant-baseline="middle">Logo</text></svg>

After

Width:  |  Height:  |  Size: 244 B

View File

@ -0,0 +1 @@
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="#ddd"/><text x="50%" y="50%" font-family="Arial" font-size="14" fill="#555" text-anchor="middle" dominant-baseline="middle">No Image</text></svg>

After

Width:  |  Height:  |  Size: 248 B

View File

@ -0,0 +1,231 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test AnyChart Box and Whisker</title>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-base.min.js"></script>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-cartesian.min.js"></script>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-ui.min.js"></script>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-exports.min.js"></script>
<link href="https://cdn.anychart.com/releases/v8/css/anychart-ui.min.css" type="text/css" rel="stylesheet">
<link href="https://cdn.anychart.com/releases/v8/fonts/css/anychart-font.min.css" type="text/css" rel="stylesheet">
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 20px;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.header {
background: #1e293b;
color: #22c55e;
padding: 15px;
border-radius: 10px;
margin-bottom: 20px;
font-family: 'Courier New', monospace;
}
#chart-container {
width: 100%;
height: 500px;
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
margin-bottom: 20px;
}
.legend {
display: flex;
justify-content: center;
gap: 20px;
color: #1e293b;
font-size: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
}
.legend-box {
width: 16px;
height: 12px;
background: rgba(34, 197, 94, 0.3);
border: 1px solid #22c55e;
}
.legend-line {
width: 16px;
height: 3px;
background: #16a34a;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>ПОЗИЦИИ • СРАВНЕНИЕ ТОВАРОВ</h1>
<div style="font-size: 14px; opacity: 0.8; margin-top: 8px;">
🔵 Ваш товар: 173269559 | 🔴 Конкурент: 388410028
</div>
</div>
<div id="chart-container"></div>
<div class="legend">
<div class="legend-item">
<div class="legend-box"></div>
<span>Диапазон позиций</span>
</div>
<div class="legend-item">
<div class="legend-line"></div>
<span>Медиана</span>
</div>
</div>
</div>
<script>
anychart.onDocumentReady(function () {
// Тестовые данные позиций товаров по городам
const testData = [
{
x: 'Москва',
low: 1,
q1: 1,
median: 1.5,
q3: 2,
high: 2,
outliers: []
},
{
x: 'СПб',
low: 3,
q1: 3,
median: 4.5,
q3: 6,
high: 6,
outliers: []
},
{
x: 'Казань',
low: 1,
q1: 1,
median: 1,
q3: 1,
high: 1,
outliers: []
},
{
x: 'Екатеринбург',
low: 1,
q1: 1,
median: 1,
q3: 1,
high: 1,
outliers: []
},
{
x: 'Новосибирск',
low: 1,
q1: 1,
median: 2.5,
q3: 4,
high: 4,
outliers: []
},
{
x: 'Краснодар',
low: 1,
q1: 1,
median: 1,
q3: 1,
high: 1,
outliers: []
},
{
x: 'Хабаровск',
low: 1,
q1: 1,
median: 1,
q3: 1,
high: 1,
outliers: []
}
];
// Создаем Box chart
const chart = anychart.box();
// Настраиваем заголовок
chart.title('Сравнение позиций товаров по городам');
chart.title().fontColor('#22c55e');
chart.title().fontSize(18);
chart.title().fontWeight('bold');
// Настраиваем оси
chart.yAxis().title('Позиция в поиске');
chart.yAxis().labels().format('{%value}');
chart.xAxis().title('Города');
chart.xAxis().staggerMode(true);
// Инвертируем ось Y через шкалу (1 позиция вверху)
try {
var yScale = chart.yScale();
if (yScale && typeof yScale.inverted === 'function') {
yScale.inverted(true);
}
} catch (error) {
console.log('Не удалось инвертировать ось Y:', error);
}
// Создаем серию
const series = chart.box(testData);
// Настраиваем внешний вид
series.whiskerWidth('60%');
series.fill('#22c55e', 0.3);
series.stroke('#22c55e', 2);
series.whiskerStroke('#22c55e', 2);
series.medianStroke('#16a34a', 3);
// Настраиваем подсказки
series.tooltip().format(
'Город: {%x}' +
'\nМин позиция: {%low}' +
'\nМакс позиция: {%high}' +
'\nМедиана: {%median}'
);
// Настраиваем сетку
try {
chart.grid(0).stroke('#e5e7eb', 1, '2 2');
chart.grid(1).layout('vertical').stroke('#e5e7eb', 1, '2 2');
} catch (error) {
console.log('Не удалось настроить сетку:', error);
// Альтернативный способ настройки сетки для Box диаграмм
try {
chart.yGrid(true);
chart.xGrid(true);
} catch (gridError) {
console.log('Альтернативная настройка сетки также недоступна:', gridError);
}
}
// Настраиваем фон
chart.background().fill('transparent');
// Устанавливаем контейнер и отрисовываем
chart.container('chart-container');
chart.draw();
});
</script>
</body>
</html>

View File

@ -0,0 +1,216 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Тест Box and Whisker диаграммы AnyChart</title>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-base.min.js"></script>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-ui.min.js"></script>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-exports.min.js"></script>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-data-adapter.min.js"></script>
<link rel="stylesheet" href="https://cdn.anychart.com/releases/v8/css/anychart-ui.min.css">
<link rel="stylesheet" href="https://cdn.anychart.com/releases/v8/fonts/css/anychart-font.min.css">
<style>
body {
font-family: Arial, sans-serif;
background: linear-gradient(to right, #9da8f9, #fce7ff);
margin: 0;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
#chart-container {
height: 500px;
margin: 20px 0;
}
.legend {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 20px;
font-size: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
}
.legend-box {
width: 16px;
height: 12px;
border: 1px solid;
}
</style>
</head>
<body>
<div class="container">
<h1>Тест Box and Whisker диаграммы - Сравнение позиций товаров</h1>
<p>Тестируем Box and Whisker диаграмму с исправлением для одинаковых позиций</p>
<div id="chart-container"></div>
<div class="legend">
<div class="legend-item">
<div class="legend-box" style="background-color: rgba(34, 197, 94, 0.3); border-color: #22c55e;"></div>
<span>Диапазон позиций</span>
</div>
<div class="legend-item">
<div class="legend-box" style="background-color: #16a34a; border-color: #16a34a; height: 3px;"></div>
<span>Медиана</span>
</div>
</div>
</div>
<script>
anychart.onDocumentReady(function () {
// Тестовые данные позиций
const testData = [
{ city: 'Москва', myPosition: 5, competitorPosition: 3 },
{ city: 'СПб', myPosition: 2, competitorPosition: 7 },
{ city: 'Екатеринбург', myPosition: 1, competitorPosition: 1 }, // Одинаковые позиции
{ city: 'Новосибирск', myPosition: 8, competitorPosition: 4 },
{ city: 'Казань', myPosition: 3, competitorPosition: 12 }
];
// Преобразуем данные для Box and Whisker диаграммы с исправлением одинаковых значений
function prepareBoxData(data) {
return data.map((item) => {
// Собираем все позиции (исключаем нулевые и отрицательные)
const positions = [item.myPosition, item.competitorPosition].filter(p => p > 0);
if (positions.length === 0) {
// Если нет валидных позиций, создаем базовый элемент
return {
x: item.city,
low: 1,
q1: 1,
median: 1,
q3: 1,
high: 1,
outliers: []
};
}
if (positions.length === 1) {
// Если только одна позиция, показываем её как точку
const pos = positions[0];
return {
x: item.city,
low: pos,
q1: pos,
median: pos,
q3: pos,
high: pos,
outliers: []
};
}
// Если две позиции
let [pos1, pos2] = positions;
// Если позиции одинаковые, добавляем небольшое смещение для визуализации
if (pos1 === pos2) {
pos2 = pos1 + 0.1; // Небольшое смещение
}
const min = Math.min(pos1, pos2);
const max = Math.max(pos1, pos2);
const median = (pos1 + pos2) / 2;
return {
x: item.city,
low: min,
q1: min,
median: median,
q3: max,
high: max,
outliers: []
};
});
}
try {
// Подготавливаем данные
const boxData = prepareBoxData(testData);
console.log('Данные для диаграммы:', boxData);
// Создаем Box and Whisker диаграмму
const chart = anychart.box();
// Настраиваем заголовок
chart.title('Сравнение позиций товаров по городам');
chart.title().fontColor('#22c55e');
chart.title().fontSize(18);
// Настраиваем оси
chart.yAxis().title('Позиция');
chart.yAxis().labels().format('{%value}');
chart.xAxis().title('Города');
chart.xAxis().staggerMode(true);
// Инвертируем ось Y (позиция 1 сверху)
try {
chart.yScale().inverted(true);
} catch (error) {
console.log('Не удалось инвертировать ось Y:', error);
}
// Создаем серию
const series = chart.box(boxData);
// Настраиваем внешний вид
series.whiskerWidth('60%');
series.fill('#22c55e', 0.3);
series.stroke('#22c55e', 2);
series.whiskerStroke('#22c55e', 2);
series.medianStroke('#16a34a', 3);
// Настраиваем подсказки
series.tooltip().format(
'Город: {%x}' +
'\nМин позиция: {%low}' +
'\nМакс позиция: {%high}' +
'\nМедиана: {%median}'
);
// Настраиваем сетку
try {
chart.grid(0).stroke('#e5e7eb', 1, '2 2');
chart.grid(1).layout('vertical').stroke('#e5e7eb', 1, '2 2');
} catch (error) {
console.log('Не удалось настроить сетку:', error);
try {
chart.yGrid(true);
chart.xGrid(true);
} catch (gridError) {
console.log('Альтернативная настройка сетки также недоступна:', gridError);
}
}
// Настраиваем фон
chart.background().fill('transparent');
// Устанавливаем контейнер и отрисовываем
chart.container('chart-container');
chart.draw();
console.log('Диаграмма успешно создана!');
} catch (error) {
console.error('Ошибка при создании диаграммы:', error);
document.getElementById('chart-container').innerHTML =
'<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #ef4444;">' +
'<div><h3>Ошибка загрузки диаграммы</h3><p>' + error.message + '</p></div>' +
'</div>';
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,419 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Тест Парсера Wildberries - ОБНОВЛЕНО</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.container {
background: white;
border-radius: 12px;
padding: 30px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
}
.header {
text-align: center;
margin-bottom: 30px;
}
.header h1 {
color: #2d3748;
margin-bottom: 10px;
}
.status-badge {
display: inline-block;
background: #48bb78;
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
font-weight: 600;
}
.update-info {
background: #e6fffa;
border: 2px solid #48bb78;
border-radius: 8px;
padding: 20px;
margin-bottom: 30px;
}
.update-info h3 {
color: #2d3748;
margin-top: 0;
}
.update-info ul {
color: #4a5568;
line-height: 1.6;
}
.test-section {
background: #f7fafc;
border-radius: 8px;
padding: 25px;
margin-bottom: 25px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #2d3748;
}
input[type="text"] {
width: 100%;
padding: 12px;
border: 2px solid #e2e8f0;
border-radius: 6px;
font-size: 16px;
box-sizing: border-box;
}
.preset-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.preset-btn {
background: #667eea;
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: background 0.2s;
}
.preset-btn:hover {
background: #5a67d8;
}
.test-btn {
background: #48bb78;
color: white;
border: none;
padding: 15px 30px;
border-radius: 8px;
font-size: 18px;
font-weight: 600;
cursor: pointer;
width: 100%;
transition: background 0.2s;
}
.test-btn:hover:not(:disabled) {
background: #38a169;
}
.test-btn:disabled {
background: #a0aec0;
cursor: not-allowed;
}
.loading {
display: none;
text-align: center;
margin: 20px 0;
color: #4a5568;
}
.loading.active {
display: block;
}
.spinner {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid #e2e8f0;
border-radius: 50%;
border-top-color: #667eea;
animation: spin 1s ease-in-out infinite;
margin-right: 10px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.results {
display: none;
margin-top: 30px;
}
.results.active {
display: block;
}
.result-header {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.status-icon {
font-size: 24px;
margin-right: 10px;
}
.product-card {
background: white;
border: 2px solid #e2e8f0;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
}
.product-image {
width: 100px;
height: 100px;
object-fit: cover;
border-radius: 8px;
margin-right: 15px;
}
.product-info {
display: flex;
align-items: flex-start;
}
.product-details h3 {
margin: 0 0 10px 0;
color: #2d3748;
}
.positions-table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.positions-table th,
.positions-table td {
padding: 15px;
text-align: left;
border-bottom: 1px solid #e2e8f0;
}
.positions-table th {
background: #4a5568;
color: white;
font-weight: 600;
}
.position-found {
color: #48bb78;
font-weight: 600;
}
.position-not-found {
color: #f56565;
font-weight: 600;
}
.error {
background: #fed7d7;
border: 2px solid #f56565;
color: #c53030;
padding: 15px;
border-radius: 8px;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎯 Тест Парсера Wildberries</h1>
<span class="status-badge">✅ РАБОТАЕТ</span>
</div>
<div class="update-info">
<h3>🚀 Парсер обновлен и работает!</h3>
<ul>
<li><strong>Решена проблема блокировки:</strong> Добавлены продвинутые методы обхода защиты Wildberries</li>
<li><strong>Улучшенная маскировка:</strong> Парсер теперь имитирует реальное поведение пользователя</li>
<li><strong>API поиск:</strong> Добавлен резервный поиск через внутренние API</li>
<li><strong>Стабильная работа:</strong> Тестирование показало успешное нахождение товаров</li>
<li><strong>Корректная обработка:</strong> Правильно обрабатывает случаи "товар не найден"</li>
</ul>
</div>
<div class="test-section">
<h2>🧪 Протестировать парсер</h2>
<div class="form-group">
<label for="query">Поисковый запрос:</label>
<input type="text" id="query" value="лабубу" placeholder="Введите поисковый запрос">
<div class="preset-buttons">
<button class="preset-btn" onclick="setPreset('лабубу', '447020075')">Лабубу (работает)</button>
<button class="preset-btn" onclick="setPreset('плюшевая игрушка', '197761909')">Плюшевая игрушка (работает)</button>
<button class="preset-btn" onclick="setPreset('игрушка', '123456789')">Тест "не найдено"</button>
</div>
</div>
<div class="form-group">
<label for="article">Артикул товара:</label>
<input type="text" id="article" value="447020075" placeholder="Введите артикул">
</div>
<button class="test-btn" onclick="testParser()" id="testBtn">
🔍 Запустить тест парсера
</button>
<div class="loading" id="loading">
<div class="spinner"></div>
Парсинг в процессе... Это может занять до 1 минуты
</div>
</div>
<div class="results" id="results">
<div class="result-header">
<span class="status-icon" id="statusIcon"></span>
<h2 id="resultTitle"></h2>
</div>
<div id="resultContent"></div>
</div>
</div>
<script>
function setPreset(query, article) {
document.getElementById('query').value = query;
document.getElementById('article').value = article;
}
async function testParser() {
const query = document.getElementById('query').value.trim();
const article = document.getElementById('article').value.trim();
if (!query || !article) {
alert('Пожалуйста, заполните все поля');
return;
}
const testBtn = document.getElementById('testBtn');
const loading = document.getElementById('loading');
const results = document.getElementById('results');
// Показываем индикатор загрузки
testBtn.disabled = true;
loading.classList.add('active');
results.classList.remove('active');
try {
const response = await fetch('/api/test-parser', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: query,
myArticleId: article
})
});
const data = await response.json();
if (data.success) {
showResults(true, data.data, data.message);
} else {
showResults(false, null, data.error || 'Произошла ошибка');
}
} catch (error) {
showResults(false, null, 'Ошибка соединения: ' + error.message);
} finally {
testBtn.disabled = false;
loading.classList.remove('active');
}
}
function showResults(success, data, message) {
const results = document.getElementById('results');
const statusIcon = document.getElementById('statusIcon');
const resultTitle = document.getElementById('resultTitle');
const resultContent = document.getElementById('resultContent');
if (success && data) {
statusIcon.textContent = '✅';
resultTitle.textContent = 'Парсинг выполнен успешно!';
const product = data.product;
const positions = data.positions;
const foundPositions = positions.filter(p => p.position !== null);
const isFound = foundPositions.length > 0;
resultContent.innerHTML = `
<div class="product-card">
<div class="product-info">
<img src="${product.imageUrl}" alt="${product.name}" class="product-image" onerror="this.src='/images/no-image.svg'">
<div class="product-details">
<h3>${product.name}</h3>
<p><strong>Бренд:</strong> ${product.brand}</p>
<p><strong>Цена:</strong> ${product.price} ₽</p>
<p><strong>Артикул:</strong> ${product.article}</p>
<p><strong>Статус:</strong> ${isFound ? '<span class="position-found">Найден в поиске</span>' : '<span class="position-not-found">Не найден в поиске</span>'}</p>
</div>
</div>
</div>
<h3>Позиции по городам:</h3>
<table class="positions-table">
<thead>
<tr>
<th>Город</th>
<th>Код</th>
<th>Позиция</th>
<th>Статус</th>
</tr>
</thead>
<tbody>
${positions.map(pos => `
<tr>
<td>${pos.city}</td>
<td>${pos.cityCode}</td>
<td>${pos.position || '—'}</td>
<td>${pos.position ? '<span class="position-found">Найден</span>' : '<span class="position-not-found">Не найден</span>'}</td>
</tr>
`).join('')}
</tbody>
</table>
<p style="margin-top: 20px; color: #4a5568; font-style: italic;">${message}</p>
`;
} else {
statusIcon.textContent = '❌';
resultTitle.textContent = 'Ошибка парсинга';
resultContent.innerHTML = `<div class="error">${message}</div>`;
}
results.classList.add('active');
}
</script>
</body>
</html>

View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Тест парсера WB</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.container { max-width: 800px; margin: 0 auto; }
input, button { padding: 10px; margin: 5px; }
input[type="text"] { width: 300px; }
#result { margin-top: 20px; padding: 15px; background: #f5f5f5; border-radius: 5px; }
.loading { color: #666; }
.error { color: red; }
.success { color: green; }
</style>
</head>
<body>
<div class="container">
<h1>Тест парсера Wildberries</h1>
<div>
<label>Поисковый запрос:</label><br>
<input type="text" id="query" value="игрушка" placeholder="Введите поисковый запрос">
</div>
<div>
<label>Артикул товара:</label><br>
<input type="text" id="articleId" value="439726135" placeholder="Введите артикул">
</div>
<div>
<button onclick="testParser()">Запустить тест</button>
</div>
<div id="result"></div>
</div>
<script>
async function testParser() {
const resultDiv = document.getElementById('result');
const query = document.getElementById('query').value;
const articleId = document.getElementById('articleId').value;
if (!query || !articleId) {
resultDiv.innerHTML = '<div class="error">Пожалуйста, заполните все поля</div>';
return;
}
resultDiv.innerHTML = '<div class="loading">Запуск парсинга... Это может занять до 60 секунд.</div>';
try {
const response = await fetch('/api/parser', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: query,
myArticleId: articleId
})
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
resultDiv.innerHTML = `
<div class="success">
<h3>Результаты парсинга:</h3>
<h4>Информация о товаре:</h4>
<p><strong>Название:</strong> ${data.products.my.name}</p>
<p><strong>Артикул:</strong> ${data.products.my.articleId}</p>
<p><strong>Цена:</strong> ${data.products.my.price} ₽</p>
<p><strong>Бренд:</strong> ${data.products.my.brand}</p>
<h4>Позиции в городах:</h4>
<table border="1" cellpadding="5">
<tr>
<th>Город</th>
<th>Страница</th>
<th>Позиция</th>
</tr>
${data.positions.map(pos => `
<tr>
<td>${pos.city}</td>
<td>${pos.myPage}</td>
<td>${pos.myPosition}</td>
</tr>
`).join('')}
</table>
<h4>Полный JSON ответ:</h4>
<pre style="background: white; padding: 10px; overflow: auto;">${JSON.stringify(data, null, 2)}</pre>
</div>
`;
} catch (error) {
resultDiv.innerHTML = `<div class="error">Ошибка: ${error.message}</div>`;
}
}
</script>
</body>
</html>