mirror of https://github.com/nealey/vail.git
Many client updates
This commit is contained in:
parent
56486979a8
commit
3a16ebb7af
|
@ -34,7 +34,8 @@
|
|||
<div class="mdl-layout__drawer">
|
||||
<span class="mdl-layout-title">Repeaters</span>
|
||||
<nav class="mdl-navigation">
|
||||
<a class="mdl-navigation__link" href="?repeater=">1-15 WPM</a>
|
||||
<a class="mdl-navigation__link" href="?repeater=">General Chaos</a>
|
||||
<a class="mdl-navigation__link" href="?repeater=beg">1-15 WPM</a>
|
||||
<a class="mdl-navigation__link" href="?repeater=int">16-20 WPM</a>
|
||||
<a class="mdl-navigation__link" href="?repeater=adv">21-99 WPM</a>
|
||||
</nav>
|
||||
|
@ -48,9 +49,7 @@
|
|||
<div class="flex">
|
||||
<div class="mdl-card mdl-shadow--4dp">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">
|
||||
Input
|
||||
</h2>
|
||||
<h2 class="mdl-card__title-text">Input</h2>
|
||||
</div>
|
||||
<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
|
||||
<div class="mdl-tabs__tab-bar">
|
||||
|
@ -69,7 +68,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>⇧</code>
|
||||
<kbd>c</kbd> or <kbd>,</kbd> or <kbd>⇧ Shift</kbd>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -90,10 +89,12 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>.</code> or <code>z</code>
|
||||
<kbd>.</kbd> or <kbd>z</kbd>
|
||||
<br>
|
||||
right-click for Dah
|
||||
</td>
|
||||
<td>
|
||||
<code>/</code> or <code>x</code>
|
||||
<kbd>/</kbd> or <kbd>x</kbd>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -117,13 +118,42 @@
|
|||
|
||||
<div class="mdl-card mdl-shadow--4dp">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">
|
||||
Knobs
|
||||
</h2>
|
||||
<h2 class="mdl-card__title-text">Knobs</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
<p>
|
||||
Dit length (iambic):
|
||||
<output id="iambic-duration-value"></output>ms
|
||||
<input
|
||||
id="iambic-duration"
|
||||
class="mdl-slider mdl-js-slider"
|
||||
type="range"
|
||||
min="40"
|
||||
max="255"
|
||||
value="100">
|
||||
</p>
|
||||
<p>
|
||||
Recieve delay:
|
||||
<output id="rx-delay-value"></output>ms
|
||||
<input
|
||||
id="rx-delay"
|
||||
class="mdl-slider mdl-js-slider"
|
||||
type="range"
|
||||
min="0"
|
||||
max="9999"
|
||||
value="4000">
|
||||
</p>
|
||||
<hr>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
Suggested receive delay:
|
||||
</td>
|
||||
<td>
|
||||
<output id="suggested-delay-value">0</output>ms
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Average round-trip time:
|
||||
|
@ -142,47 +172,23 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Suggested receive delay:
|
||||
Repeater:
|
||||
</td>
|
||||
<td>
|
||||
<output id="suggested-delay-value">0</output>ms
|
||||
<span id="repeater"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<p>
|
||||
Recieve delay:
|
||||
<output id="rx-delay-value"></output>ms
|
||||
<input
|
||||
id="rx-delay"
|
||||
class="mdl-slider mdl-js-slider"
|
||||
type="range"
|
||||
min="0"
|
||||
max="5000"
|
||||
value="400">
|
||||
</p>
|
||||
<p>
|
||||
Dit length (iambic):
|
||||
<output id="iambic-duration-value"></output>ms
|
||||
<input
|
||||
id="iambic-duration"
|
||||
class="mdl-slider mdl-js-slider"
|
||||
type="range"
|
||||
min="40"
|
||||
max="255"
|
||||
value="100">
|
||||
</p>
|
||||
<p>Errors</p>
|
||||
<div id="errors"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mdl-card mdl-shadow--4dp">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">
|
||||
Code Tree
|
||||
</h2>
|
||||
<h2 class="mdl-card__title-text">Code Tree</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
<img src="code-tree.png">
|
||||
|
@ -191,9 +197,7 @@
|
|||
|
||||
<div class="mdl-card mdl-shadow--4dp">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">
|
||||
Vail
|
||||
</h2>
|
||||
<h2 class="mdl-card__title-text">Vail</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
<p>
|
||||
|
@ -220,6 +224,99 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mdl-card mdl-shadow--4dp">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">How It Works</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
|
||||
<p>
|
||||
The Internet isn't exactly like radio waves:
|
||||
it still goes at near the speed of light,
|
||||
but there are multiple hops between endpoints,
|
||||
which buffer up transmissions, and multiplex them onto a single uplink connection.
|
||||
These repeaters (routers)
|
||||
are also allowed to just drop things if they need to.
|
||||
It's the responsibility of the communicating parties
|
||||
to work out whether something needs to be retransmitted.
|
||||
Because of this,
|
||||
there's no telling how long it will take for a transmission to get to a destination.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Each Vail transmission (packet) consists of:
|
||||
</p>
|
||||
<ul>
|
||||
<li>timestamp (milliseconds since 1 Jan 1970, 00:00:00 in Reykjavík)</li>
|
||||
<li>transmission duration (milliseconds)</li>
|
||||
<li>silence duration (milliseconds, optional)</li>
|
||||
<li>transmission duration (milliseconds, optional)</li>
|
||||
<li>silence duration (milliseconds, optional)</li>
|
||||
<li>Repeat as necessary</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The repeater does nothing but broadcast everything it gets
|
||||
to every connected Vail client,
|
||||
including the one that sent the packet.
|
||||
When your client gets back the exact same thing it sent,
|
||||
it compares the current time to the time in the packet.
|
||||
This is the <i>round-trip time</i>:
|
||||
the time it takes for a packet to get from your computer to the repeater and back.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When the client gets a packet it didn't send,
|
||||
it adds the <i>receive delay</i> to the timestamp,
|
||||
and schedules to play the tones and silences in the packet
|
||||
at that time.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
By adding the maximum round-trip time to the <i>longest recent transmission</i>
|
||||
(the length of a dah, hopefully),
|
||||
your client can make a guess about how much time needs to be added to a received timestamp,
|
||||
in order to have it play back in the future at the time it comes in.
|
||||
This is just a guess.
|
||||
If you're communicating with somebody with a higher round-trip time than you have,
|
||||
you'll need to raise your receive delay to account for it.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mdl-card mdl-shadow--4dp">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">Why do I hear a low tone?</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
<p>
|
||||
This is the "drop tone", and will be accompanied by an error.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This means the packet arrived so late, it can't be played in time.
|
||||
In technical terms: the timestamp of the packet plus the receive delay
|
||||
is less than the current time.
|
||||
It can't be scheduled to play, because we can't go back in time.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This could be happening for three reasons:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>You (the person hearing the drop tone) need a larger receive delay</li>
|
||||
<li>The receiving computer's clock is in the future (running fast)</li>
|
||||
<li>The sending computer's clock is in the past (running slow)</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Make sure your clock is synced with an Internet time server.
|
||||
Accurate time is very important to how Vail works.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mdl-card mdl-shadow--4dp">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">Future plans</h2>
|
||||
|
|
|
@ -22,6 +22,29 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
#errors {
|
||||
color: rgba(127, 0, 0, .54);
|
||||
max-height: 5em;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
@keyframes yellow-fade {
|
||||
0% {background: yellow;}
|
||||
100% {background: none;}
|
||||
}
|
||||
#errors p {
|
||||
margin: 0;
|
||||
animation: yellow-fade 2s ease-in 1;
|
||||
}
|
||||
|
||||
kbd {
|
||||
background-color: #eee;
|
||||
border: 1px solid #bbb;
|
||||
border-radius: 3px;
|
||||
font-size: 9pt;
|
||||
padding: .1em .6em;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
|
@ -31,3 +54,8 @@ code {
|
|||
img {
|
||||
max-width: 20em;
|
||||
}
|
||||
|
||||
.mdl-card__supporting-text {
|
||||
max-height: 20em;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
|
|
@ -228,6 +228,10 @@ class Vail {
|
|||
// Listen for slider values
|
||||
this.inputInit("#iambic-duration", e => this.iambic.SetInterval(e.target.value))
|
||||
this.inputInit("#rx-delay", e => {this.rxDelay = Number(e.target.value)})
|
||||
|
||||
// Show what repeater we're on
|
||||
let repeater = (new URL(location)).searchParams.get("repeater") || "Default"
|
||||
document.querySelector("#repeater").textContent = repeater
|
||||
}
|
||||
|
||||
inputInit(selector, func) {
|
||||
|
@ -247,6 +251,17 @@ class Vail {
|
|||
element.dispatchEvent(new Event("input"))
|
||||
}
|
||||
|
||||
error(msg) {
|
||||
let now = new Date()
|
||||
let e = document.querySelector("#errors")
|
||||
if (e) {
|
||||
let p = e.appendChild(document.createElement("p"))
|
||||
p.innerText = "[" + now.toLocaleTimeString() + "] " + msg
|
||||
e.scrollTop = e.scrollHeight
|
||||
}
|
||||
this.buzzer.ErrorTone()
|
||||
}
|
||||
|
||||
beginTx() {
|
||||
this.beginTxTime = Date.now()
|
||||
this.buzzer.Buzz(true)
|
||||
|
@ -320,7 +335,7 @@ class Vail {
|
|||
|
||||
let adjustedTxTime = beginTxTime+this.rxDelay
|
||||
if (adjustedTxTime < now) {
|
||||
this.buzzer.ErrorTone()
|
||||
this.error("Packet requested playback " + (now - adjustedTxTime) + "ms in the past. Increase receive delay!")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -353,7 +368,7 @@ class Vail {
|
|||
event.preventDefault()
|
||||
this.iambic.Key(begin, DAH)
|
||||
}
|
||||
if ((event.key == "Shift")) {
|
||||
if ((event.code == "KeyC") || (event.code == "Comma") || (event.key == "Shift")) {
|
||||
event.preventDefault()
|
||||
if (begin) {
|
||||
this.beginTx()
|
||||
|
|
Loading…
Reference in New Issue