Найден корректный robots.txt
Файл управления сканированием сайта роботами
?
Robots.txt указывает поисковым роботам, какие страницы сканировать, а какие — нет. Ошибки в файле могут случайно закрыть важные разделы от индексации.
Robots.txt настроен корректно. Размер файла: 29756 байт. Загружен за: 1сек.
Проверяемая страница не запрещена в robots.txt.
Цепочка редиректов для файла robots.txt:
http://vailmaster.netlify.app/robots.txt
301 MovedPermanently
https://vailmaster.netlify.app/robots.txt
200 OK
Показать содержимое robots.txt
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vail Master - CW Sending Trainer</title>
<link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="alternate icon" href="favicon.ico">
<link rel="stylesheet" href="styles/dark.css?v=1781104578">
<link rel="stylesheet" href="styles/main.css?v=1781104578">
</head>
<body>
<div class="app-container">
<!-- Header -->
<header class="app-header">
<h1 class="app-title">VAIL MASTER</h1>
<button type="button" class="button button-help" id="help-button">How to Use</button>
<div class="header-info">
<span id="midi-status" class="help" title="MIDI device status">No MIDI</span>
</div>
</header>
<!-- Vail Adapter Banner (Top) -->
<div class="adapter-banner">
<span class="adapter-icon">🔌</span>
<span>Want to use your real CW keys with your computer? Build or buy an adapter at <a href="https://vailadapter.com" target="_blank" rel="noopener noreferrer">vailadapter.com</a></span>
</div>
<!-- Main Content -->
<main class="main-content">
<!-- Practice Area (Left) -->
<div class="practice-area">
<!-- Target and Echo Display -->
<div class="text-display">
<div class="text-row">
<span class="text-label">Target</span>
<div class="text-content" id="target-text">
<!-- Target text appears here -->
</div>
</div>
<div class="text-row">
<span class="text-label">Echo</span>
<div class="echo-container">
<div class="echo-content" id="echo-text">
<span></span>
</div>
</div>
</div>
<div class="ready-indicator" id="ready-indicator">
Press Start to begin
</div>
</div>
<!-- Scoreboard and Controls Row -->
<div class="controls-row">
<!-- Scoreboard -->
<div class="scoreboard">
<div class="scoreboard-title">Scoreboard</div>
<div class="scoreboard-item">
<span class="scoreboard-label">Score</span>
<span class="scoreboard-value" id="score-value">0 (0.0%)</span>
</div>
<div class="scoreboard-item">
<span class="scoreboard-label">Perfect</span>
<span class="scoreboard-value" id="perfect-value">0 (0.0%)</span>
</div>
<div class="scoreboard-item">
<span class="scoreboard-label">Streak</span>
<span class="scoreboard-value" id="streak-value">0 / 0</span>
</div>
<div class="scoreboard-item">
<span class="scoreboard-label">Trial</span>
<span class="scoreboard-value highlight" id="trial-value">- of -</span>
</div>
<div class="scoreboard-item">
<span class="scoreboard-label">Trial Time</span>
<span class="scoreboard-value" id="trial-time">0.0s</span>
</div>
<div class="scoreboard-item">
<span class="scoreboard-label">Run Time</span>
<span class="scoreboard-value" id="run-time">0:00</span>
</div>
</div>
<!-- Controls Panel -->
<div class="controls-panel">
<div class="control-row">
<!-- Speed Control -->
<div class="control-item">
<label class="control-label" for="speed-slider">Speed</label>
<div class="slider-control">
<input type="range" id="speed-slider" min="5" max="50" value="20">
<span class="value-display" id="speed-value">20 WPM</span>
</div>
</div>
<!-- Sidetone Frequency -->
<div class="control-item">
<label class="control-label" for="tone-slider">Sidetone</label>
<div class="slider-control">
<input type="range" id="tone-slider" min="400" max="800" value="550">
<span class="value-display" id="tone-value">550 Hz</span>
</div>
</div>
</div>
<div class="control-row">
<!-- Practice Mode -->
<div class="control-item">
<label class="control-label" for="mode-select">Mode</label>
<select id="mode-select">
<option value="sprint">Sprint</option>
<option value="sweepstakes">Sweepstakes</option>
<option value="mixed">Mixed</option>
<option value="uniform">Uniform</option>
<option value="clipboard">Clipboard</option>
</select>
</div>
<!-- Run Length -->
<div class="control-item">
<label class="control-label" for="length-select">Run Length</label>
<select id="length-select">
<option value="10">10 trials</option>
<option value="25">25 trials</option>
<option value="50">50 trials</option>
</select>
</div>
</div>
<div class="control-row">
<!-- Keyer Mode -->
<div class="control-item">
<label class="control-label" for="keyer-select">Keyer</label>
<select id="keyer-select">
<option value="cootie">Straight Key / Cootie</option>
<option value="bug">Bug</option>
<option value="elbug">ElBug</option>
<option value="singledot">Single Dot</option>
<option value="ultimatic">Ultimatic</option>
<option value="iambic">Iambic (Plain)</option>
<option value="iambica">Iambic A</option>
<option value="iambicb" selected>Iambic B</option>
<option value="keyahead">Keyahead</option>
</select>
</div>
<!-- Your Callsign -->
<div class="control-item">
<label class="control-label" for="callsign-input">Your Call</label>
<input type="text" id="callsign-input" class="input" placeholder="CALL" maxlength="10">
</div>
</div>
<!-- Mixed/Uniform Mode Options (hidden by default) -->
<div class="control-row" id="random-options" style="display: none;">
<div class="control-item">
<label class="control-label" for="group-count">Groups</label>
<select id="group-count">
<option value="1">1</option>
<option value="2" selected>2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<div class="control-item">
<label class="control-label" for="group-length">Length</label>
<select id="group-length">
<option value="3">3</option>
<option value="4">4</option>
<option value="5" selected>5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="10">10</option>
</select>
</div>
<div class="control-item">
<label class="control-label" for="charset-select">Characters</label>
<select id="charset-select">
<option value="letters">Letters (A-Z)</option>
<option value="numbers">Numbers (0-9)</option>
<option value="punctuation">Punctuation</option>
<option value="prosigns">Prosigns</option>
<option value="full" selected>Full Set</option>
<option value="custom">Custom</option>
</select>
</div>
</div>
<!-- Volume Control -->
<div class="control-row">
<div class="control-item">
<label class="control-label" for="volume-slider">Volume</label>
<div class="slider-control">
<input type="range" id="volume-slider" min="0" max="100" value="50">
<span class="value-display" id="volume-value">50%</span>
</div>
</div>
</div>
<!-- Advanced Settings (Collapsible) -->
<details class="advanced-section">
<summary class="advanced-toggle">Advanced Decoder Settings</summary>
<div class="advanced-content">
<div class="control-row">
<div class="control-item">
<label class="control-label" for="buffer-slider">Adaptive Buffer</label>
<div class="slider-control">
<input type="range" id="buffer-slider" min="5" max="50" value="20">
<span class="value-display" id="buffer-value">20</span>
</div>
</div>
<div class="control-item">
<label class="control-label" for="flush-slider">Flush Timeout</label>
<div class="slider-control">
<input type="range" id="flush-slider" min="200" max="2000" step="100" value="600">
<span class="value-display" id="flush-value">600 ms</span>
</div>
</div>
</div>
<p class="help advanced-help">Lower buffer = faster but less adaptive. Lower flush = quicker character finalization.</p>
</div>
</details>
<!-- Action Buttons -->
<div class="action-buttons">
<button type="button" class="button is-primary" id="start-button">Start</button>
<button type="button" class="button" id="practice-button">Free Practice</button>
<button type="button" class="button is-danger" id="abort-button" style="display: none;">Abort</button>
</div>
</div>
</div>
<!-- Touch Buttons for Mobile -->
<div class="touch-buttons">
<button type="button" class="touch-button dit key" data-key="0">DIT</button>
<button type="button" class="touch-button straight key" data-key="2">KEY</button>
<button type="button" class="touch-button dah key" data-key="1">DAH</button>
</div>
</div>
<!-- Score History Panel (Right) -->
<div class="score-panel">
<div class="score-panel-title">Score History</div>
<!-- Mode Tabs -->
<div class="score-tabs">
<button type="button" class="is-active" data-mode="sprint">Sprint</button>
<button type="button" data-mode="sweepstakes">SS</button>
<button type="button" data-mode="mixed">Mixed</button>
<button type="button" data-mode="uniform">Uniform</button>
<button type="button" data-mode="clipboard">Clip</button>
</div>
<!-- Run Length Selector -->
<div class="run-length-selector">
<button type="button" class="is-active" data-length="10">10</button>
<button type="button" data-length="25">25</button>
<button type="button" data-length="50">50</button>
</div>
<!-- Score Table -->
<div class="score-table-container">
<table class="score-table">
<thead>
<tr>
<th>Date</th>
<th>Call</th>
<th>Score</th>
<th>Eff%</th>
<th>Perf</th>
<th>Strk</th>
</tr>
</thead>
<tbody id="score-table-body">
<!-- Score rows populated by JavaScript -->
<tr>
<td colspan="6" style="text-align: center; color: #999;">No scores yet</td>
</tr>
</tbody>
</table>
</div>
<!-- Analytics Section -->
<div class="analytics-section">
<div class="scoreboard-title">Problem Characters</div>
<div class="problem-chars" id="problem-chars">
<span class="help">Complete some runs to see analytics</span>
</div>
</div>
</div>
</main>
<!-- Footer -->
<footer class="app-footer">
<div class="footer-content">
<!-- Credits -->
<div class="footer-credits">
<p class="footer-credit">Inspired by <strong>Iambic Master</strong> by <strong>NA0N</strong></p>
<p class="footer-credit">Developed by <strong>Brett KE9BOS</strong></p>
</div>
<!-- Links -->
<div class="footer-links">
<a href="mailto:ke9bos@pigletradio.org" class="footer-link">
<span class="footer-link-icon">✉️</span>
<span>ke9bos@pigletradio.org</span>
</a>
<a href="https://discord.gg/ERceAGnCr7" target="_blank" rel="noopener noreferrer" class="footer-link">
<span class="footer-link-icon">💬</span>
<span>Vail Community Discord</span>
</a>
</div>
<!-- Buy Me a Coffee -->
<div class="footer-coffee">
<script type="text/javascript" src="https://cdnjs.buymeacoffee.com/1.0.0/button.prod.min.js" data-name="bmc-button" data-slug="ke9bos" data-color="#5F7FFF" data-emoji="☕" data-font="Cookie" data-text="Buy me a coffee" data-outline-color="#000000" data-font-color="#ffffff" data-coffee-color="#FFDD00"></script>
</div>
</div>
</footer>
</div>
<!-- Character Set Editor Modal (hidden by default) -->
<div class="modal-overlay" id="charset-modal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3>Custom Character Set</h3>
</div>
<div class="modal-body">
<p class="help">Click characters to include/exclude them from practice:</p>
<div class="charset-editor" id="charset-editor">
<!-- Characters populated by JavaScript -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="button" id="charset-cancel">Cancel</button>
<button type="button" class="button is-primary" id="charset-save">Save</button>
</div>
</div>
</div>
<!-- How to Use Modal -->
<div class="modal-overlay" id="help-modal" style="display: none;">
<div class="modal-content modal-large">
<div class="modal-header">
<h3>How to Use Vail Master</h3>
<button type="button" class="modal-close" id="help-close" aria-label="Close">×</button>
</div>
<div class="modal-body">
<!-- Section 1: Getting Started -->
<div class="help-section">
<h4>Getting Started</h4>
<p>Vail Master is a Morse code sending trainer that helps you improve your CW (continuous wave) sending skills. The app displays target text, you send it using your key, and the decoder shows what you sent in real-time.</p>
<p><strong>How it works:</strong></p>
<ul>
<li>Choose a practice mode and settings</li>
<li>Press Start to begin a run</li>
<li>Target text appears - send each character in Morse code</li>
<li>Your sending appears in the Echo line as it's decoded</li>
<li>Green = correct, Red = error</li>
<li>Scoreboard tracks your accuracy and progress</li>
</ul>
<p><strong>IMPORTANT - What Happens When You Make a Mistake:</strong></p>
<p style="color: #ff6b6b; font-weight: bold;">If you send the wrong character, DON'T STOP! Keep sending until you get the target text perfect. The Echo will scroll like a ticker to the left, showing everything you sent. You must continue sending the entire target sequence correctly from the beginning to complete the trial. The Echo box acts like a scrolling ticker tape - it will keep sliding left as you send more characters until you finally match the target perfectly.</p>
</div>
<!-- Section 2: Understanding the Echo Ticker (CRITICAL) -->
<div class="help-section" style="background-color: #2a1a1a; padding: 1rem; border-left: 4px solid #ff6b6b; border-radius: 4px;">
<h4 style="color: #ff6b6b;">🔴 CRITICAL: How the Echo Ticker Works</h4>
<p><strong>This is the most important thing to understand about Vail Master:</strong></p>
<p><strong>When you make a mistake:</strong></p>
<ol style="margin-left: 1.5rem; line-height: 1.8;">
<li><strong>DO NOT STOP SENDING!</strong> Keep going no matter what.</li>
<li>The Echo box will <strong>scroll left like a ticker tape</strong>, showing all the characters you're sending.</li>
<li>You must <strong>start over from the beginning</strong> of the target text and send it perfectly.</li>
<li>The Echo keeps scrolling left until your most recent characters match the target perfectly.</li>
<li>Only when the Echo matches the target exactly will the trial complete.</li>
</ol>
<p><strong>Example:</strong> If the target is <code>ABC</code> and you send:</p>
<ul style="margin-left: 1.5rem;">
<li>You send: A ✓ (Echo shows: <span style="color: #0f0;">A</span>)</li>
<li>You send: X ✗ (Echo shows: <span style="color: #0f0;">A</span><span style="color: #f00;">X</span>)</li>
<li>Don't stop! Start over from the beginning...</li>
<li>You send: A (Echo scrolls left, shows: <span style="color: #999;">AX</span><span style="color: #0f0;">A</span>)</li>
<li>You send: B (Echo scrolls left, shows: <span style="color: #999;">XA</span><span style="color: #0f0;">AB</span>)</li>
<li>You send: C (Echo scrolls left, shows: <span style="color: #999;">A</span><span style="color: #0f0;">ABC</span> ✓ Trial complete!)</li>
</ul>
<p><strong>Remember:</strong> The Echo is like a ticker tape that continuously scrolls left. Your job is to keep sending until the rightmost characters in the Echo match the target perfectly. Never stop - just start over and keep going!</p>
</div>
<!-- Section 2: Practice Modes -->
<div class="help-section">
<h4>Practice Modes</h4>
<p><strong>Sprint:</strong> Contest-style exchanges in the format <code>CALL # CALL NAME STATE</code><br>
Example: <code>W1AW 123 A K3NK JOHN PA</code></p>
<p><strong>Sweepstakes:</strong> ARRL Sweepstakes format <code>NR PREC CALL CK SEC</code><br>
Example: <code>123 A W1AW 72 CT</code></p>
<p><strong>Mixed:</strong> Random character groups for general practice. Configure groups, length, and character set.</p>
<p><strong>Uniform:</strong> Repeated character groups (e.g., <code>AAAAA BBBBB</code>) for timing and rhythm practice.</p>
<p><strong>Clipboard:</strong> Paste any text to practice. Text is automatically formatted.</p>
<p><strong>Free Practice:</strong> No scoring, just practice sending with real-time echo feedback.</p>
</div>
<!-- Section 3: Input Methods -->
<div class="help-section">
<h4>Input Methods</h4>
<p><strong>Keyboard Controls:</strong></p>
<ul>
<li><code>Ctrl</code> (either side) - DIT paddle</li>
<li><code>[</code> (left bracket) - DIT paddle</li>
<li><code>]</code> (right bracket) - DAH paddle</li>
<li><code>X</code> - DIT paddle (alternative)</li>
<li><code>Z</code> - DAH paddle (alternative)</li>
</ul>
<p><strong>MIDI Devices:</strong> Connect USB MIDI paddles - status shown in header. Auto-detected when connected.</p>
<p><strong>Touch Buttons:</strong> DIT/DAH buttons appear on mobile devices. Touch and hold to send.</p>
</div>
<!-- Section 4: Keyer Modes -->
<div class="help-section">
<h4>Keyer Modes</h4>
<ul>
<li><strong>Straight Key / Cootie:</strong> Manual timing control</li>
<li><strong>Bug:</strong> Automatic dits, manual dahs</li>
<li><strong>ElBug:</strong> Enhanced bug mode</li>
<li><strong>Single Dot:</strong> Single dit per press</li>
<li><strong>Ultimatic:</strong> Last paddle wins</li>
<li><strong>Iambic (Plain):</strong> Basic iambic keyer</li>
<li><strong>Iambic A:</strong> Standard iambic mode</li>
<li><strong>Iambic B:</strong> Most popular (default) - completes elements automatically</li>
<li><strong>Keyahead:</strong> Buffers paddle input for smoother sending</li>
</ul>
</div>
<!-- Section 5: Speed & Settings -->
<div class="help-section">
<h4>Speed & Settings</h4>
<p><strong>Speed (WPM):</strong> Range 5-50 WPM using standard PARIS timing. Adjustable during practice.</p>
<p><strong>Sidetone Frequency:</strong> 400-800 Hz audio feedback when sending. Find your preferred tone.</p>
<p><strong>Volume:</strong> 0-100% control for sidetone and feedback sounds.</p>
<p><strong>Advanced Decoder Settings:</strong></p>
<ul>
<li><strong>Adaptive Buffer:</strong> Lower = faster character recognition but less adaptive to timing variations</li>
<li><strong>Flush Timeout:</strong> Time before decoder finalizes a character (lower = quicker finalization)</li>
</ul>
</div>
<!-- Section 6: Understanding the Scoreboard -->
<div class="help-section">
<h4>Understanding the Scoreboard</h4>
<p><strong>Score:</strong> Total correct characters / total characters, with efficiency percentage</p>
<p><strong>Perfect:</strong> Trials with 100% accuracy, shown as count and percentage</p>
<p><strong>Streak:</strong> Current and longest consecutive perfect trials</p>
<p><strong>Trial:</strong> Current trial number out of total run length</p>
<p><strong>Trial Time:</strong> Duration of current trial</p>
<p><strong>Run Time:</strong> Total session duration</p>
</div>
<!-- Section 7: Score History -->
<div class="help-section">
<h4>Score History & Analytics</h4>
<p><strong>Score Table:</strong> View up to 20 recent scores, sorted by date. Filter by mode and run length.</p>
<p><strong>Problem Characters:</strong> The app automatically tracks error rates for each character. After runs, check which characters need more practice.</p>
<p>All data is saved locally in your browser and persists between sessions.</p>
</div>
<!-- Section 8: Tips for Success -->
<div class="help-section">
<h4>Tips for Success</h4>
<ul>
<li><strong style="color: #ff6b6b;">🔴 MOST IMPORTANT: When you make a mistake, NEVER STOP! Keep sending and start the target over. The Echo will scroll like a ticker until you get it right.</strong></li>
<li>Start slow - prioritize accuracy over speed</li>
<li>Use Free Practice to warm up before scored runs</li>
<li>Focus on consistent rhythm and timing</li>
<li>Check Problem Characters and practice them in Uniform mode</li>
<li>Gradually increase WPM as your accuracy improves</li>
<li>Keep practice sessions short (10-15 minutes) but frequent</li>
<li>Try different modes to keep practice varied and engaging</li>
<li>Adjust decoder settings if characters aren't recognized correctly</li>
<li><strong>Remember: The Echo scrolls left like a ticker tape - just keep sending until you match the target!</strong></li>
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="button is-primary" id="help-done">Got it!</button>
</div>
</div>
</div>
<!-- Scripts -->
<script type="module" src="scripts/main.mjs?v=1781104578"></script>
</body>
</html>