mirror of https://github.com/nealey/vail.git
Charts, pare down UI
This commit is contained in:
parent
2290c2ff02
commit
01ed64ad2d
|
@ -14,7 +14,7 @@ class HistoryChart {
|
||||||
* @param {string} strokeStyle strokeStyle to draw in
|
* @param {string} strokeStyle strokeStyle to draw in
|
||||||
* @param {Duration} duration Time to display history for
|
* @param {Duration} duration Time to display history for
|
||||||
*/
|
*/
|
||||||
constructor(canvas, strokeStyle, duration) {
|
constructor(canvas, strokeStyle="black", duration=20*Second) {
|
||||||
this.canvas = canvas
|
this.canvas = canvas
|
||||||
this.ctx = canvas.getContext("2d")
|
this.ctx = canvas.getContext("2d")
|
||||||
this.duration = duration
|
this.duration = duration
|
||||||
|
@ -29,8 +29,10 @@ class HistoryChart {
|
||||||
this.ctx.translate(0, -canvas.height)
|
this.ctx.translate(0, -canvas.height)
|
||||||
|
|
||||||
this.ctx.strokeStyle = strokeStyle
|
this.ctx.strokeStyle = strokeStyle
|
||||||
|
this.ctx.fillStyle = strokeStyle
|
||||||
this.ctx.lineWdith = 2
|
this.ctx.lineWdith = 2
|
||||||
|
|
||||||
|
this.running=true
|
||||||
this.draw()
|
this.draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +44,8 @@ class HistoryChart {
|
||||||
* This also cleans up the event list,
|
* This also cleans up the event list,
|
||||||
* purging anything that is too old to be displayed.
|
* purging anything that is too old to be displayed.
|
||||||
*
|
*
|
||||||
* @param when Time the event happened
|
* @param {Number} when Time the event happened
|
||||||
* @param value Value for the event
|
* @param {Number} value Value for the event
|
||||||
*/
|
*/
|
||||||
Add(when, value) {
|
Add(when, value) {
|
||||||
let now = Date.now()
|
let now = Date.now()
|
||||||
|
@ -54,8 +56,10 @@ class HistoryChart {
|
||||||
while ((this.data.length > 1) && (this.data[1][0] < earliest)) {
|
while ((this.data.length > 1) && (this.data[1][0] < earliest)) {
|
||||||
this.data.shift()
|
this.data.shift()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log(this.data)
|
Stop() {
|
||||||
|
this.running = false
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
|
@ -64,43 +68,29 @@ class HistoryChart {
|
||||||
let xScale = this.canvas.width / this.duration
|
let xScale = this.canvas.width / this.duration
|
||||||
let yScale = this.canvas.height * 0.95
|
let yScale = this.canvas.height * 0.95
|
||||||
let y = 0
|
let y = 0
|
||||||
|
let x = 0
|
||||||
|
|
||||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
||||||
|
|
||||||
this.ctx.moveTo(0, 0)
|
|
||||||
this.ctx.beginPath()
|
|
||||||
for (let point of this.data) {
|
for (let point of this.data) {
|
||||||
let x = (point[0] - earliest) * xScale
|
let x2 = (point[0] - earliest) * xScale
|
||||||
this.ctx.lineTo(x, y)
|
let y2 = point[1] * yScale
|
||||||
y = point[1] * yScale
|
|
||||||
this.ctx.lineTo(x, y)
|
|
||||||
}
|
|
||||||
this.ctx.lineTo(this.canvas.width, y)
|
|
||||||
this.ctx.stroke()
|
|
||||||
|
|
||||||
|
if (y > 0) {
|
||||||
|
this.ctx.fillRect(x, 0, x2-x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
x=x2
|
||||||
|
y=y2
|
||||||
|
}
|
||||||
|
if (y > 0) {
|
||||||
|
this.ctx.fillRect(x, 0, this.canvas.width, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.running) {
|
||||||
requestAnimationFrame(() => this.draw())
|
requestAnimationFrame(() => this.draw())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {HistoryChart}
|
export {HistoryChart}
|
||||||
|
|
||||||
|
|
||||||
// XXX: remove after testing
|
|
||||||
let chart
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
let canvas = document.querySelector("#chart")
|
|
||||||
chart = new HistoryChart(canvas, "red", 20 * Second)
|
|
||||||
setInterval(update, 500 * Millisecond)
|
|
||||||
}
|
|
||||||
|
|
||||||
function update() {
|
|
||||||
let now = Date.now()
|
|
||||||
chart.Add(now, Math.sin(now/Second)/2 + 0.5)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.readyState === "loading") {
|
|
||||||
document.addEventListener("DOMContentLoaded", init)
|
|
||||||
} else {
|
|
||||||
init()
|
|
||||||
}
|
|
|
@ -27,9 +27,6 @@
|
||||||
<div class="mdl-layout-spacer"></div>
|
<div class="mdl-layout-spacer"></div>
|
||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
<nav class="mdl-navigation">
|
<nav class="mdl-navigation">
|
||||||
<a class="mdl-navigation__link" href="https://discord.gg/GBzj8cBat7">Discord</a>
|
|
||||||
<a class="mdl-navigation__link" href="https://morse.withgoogle.com/learn/">Learn Morse</a>
|
|
||||||
<a class="mdl-navigation__link" href="https://github.com/nealey/vail-adapter">USB Adapter</a>
|
|
||||||
<a class="mdl-navigation__link" href="https://github.com/nealey/vail">Source Code</a>
|
<a class="mdl-navigation__link" href="https://github.com/nealey/vail">Source Code</a>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
@ -54,10 +51,10 @@
|
||||||
<a class="mdl-navigation__link" href="#Fortunes: Pauses ×10">Fortunes (crazy slow)</a>
|
<a class="mdl-navigation__link" href="#Fortunes: Pauses ×10">Fortunes (crazy slow)</a>
|
||||||
</nav>
|
</nav>
|
||||||
<hr>
|
<hr>
|
||||||
|
<span class="mdl-layout-title">Resources</span>
|
||||||
<nav class="mdl-navigation">
|
<nav class="mdl-navigation">
|
||||||
|
<a class="mdl-navigation__link" href="https://github.com/nealey/vail/wiki">Wiki</a>
|
||||||
<a class="mdl-navigation__link" href="https://discord.gg/GBzj8cBat7">Discord</a>
|
<a class="mdl-navigation__link" href="https://discord.gg/GBzj8cBat7">Discord</a>
|
||||||
<a class="mdl-navigation__link" href="https://morse.withgoogle.com/learn/">Learn Morse Code</a>
|
|
||||||
<a class="mdl-navigation__link" href="https://github.com/nealey/vail-adapter">Use a physical key</a>
|
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -96,6 +93,13 @@
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<output id="note"></output>
|
<output id="note"></output>
|
||||||
|
|
||||||
|
<div id="charts">
|
||||||
|
<canvas class="chart" id="txChart"></canvas>
|
||||||
|
<canvas class="chart" id="ditChart"></canvas>
|
||||||
|
<canvas class="chart" id="dahChart"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
|
<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
|
||||||
<div class="mdl-tabs__tab-bar">
|
<div class="mdl-tabs__tab-bar">
|
||||||
<a href="#straight" class="mdl-tabs__tab is-active" data-singlekey="straight">Straight Key</a>
|
<a href="#straight" class="mdl-tabs__tab is-active" data-singlekey="straight">Straight Key</a>
|
||||||
|
@ -217,6 +221,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="mdl-card__supporting-text">
|
<div class="mdl-card__supporting-text">
|
||||||
<textarea class="notes" placeholder="Enter your own notes here"></textarea>
|
<textarea class="notes" placeholder="Enter your own notes here"></textarea>
|
||||||
|
<a href="https://github.com/nealey/vail/wiki">Vail Wiki</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -265,6 +270,12 @@
|
||||||
<span class="mdl-switch__label">Telegraph sounds</span>
|
<span class="mdl-switch__label">Telegraph sounds</span>
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect" for="timing-chart">
|
||||||
|
<input type="checkbox" id="timing-chart" class="mdl-switch__input">
|
||||||
|
<span class="mdl-switch__label">Timing chart</span>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
<hr>
|
<hr>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -305,269 +316,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mdl-card mdl-shadow--4dp">
|
|
||||||
<div class="mdl-card__title">
|
|
||||||
<h2 class="mdl-card__title-text">Alphabet</h2>
|
|
||||||
</div>
|
|
||||||
<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
|
|
||||||
<div class="mdl-tabs__tab-bar">
|
|
||||||
<a href="#morse-tree" class="mdl-tabs__tab is-active">Dichotomous Key</a>
|
|
||||||
<a href="#morse-list" class="mdl-tabs__tab">List</a>
|
|
||||||
</div>
|
|
||||||
<div class="mdl-tabs__panel mdl-card__supporting-text long is-active" id="morse-tree">
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="8">E .</td>
|
|
||||||
<td rowspan="4">I ..</td>
|
|
||||||
<td rowspan="2">S ...</td>
|
|
||||||
<td rowspan="1">H ....</td>
|
|
||||||
<td class="dah">4 ....-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="1">V ...-</td>
|
|
||||||
<td class="dah">3 ...--</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="2">U ..-</td>
|
|
||||||
<td rowspan="1">F ..-.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="1"></td>
|
|
||||||
<td class="dah">2 ..---</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="4">A .-</td>
|
|
||||||
<td rowspan="2">R .-.</td>
|
|
||||||
<td rowspan="1">L .-..</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="1"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="2">W .--</td>
|
|
||||||
<td rowspan="1">P .--.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="1">J .---</td>
|
|
||||||
<td class="dah">1 .----</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td rowspan="8">T -</td>
|
|
||||||
<td rowspan="4">N -.</td>
|
|
||||||
<td rowspan="2">D -..</td>
|
|
||||||
<td rowspan="1">B -...</td>
|
|
||||||
<td>6 -....</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="1">X -..-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="2">K -.-</td>
|
|
||||||
<td rowspan="1">C -.-.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="1">Y -.--</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="4">M --</td>
|
|
||||||
<td rowspan="2">G --.</td>
|
|
||||||
<td rowspan="1">Z --..</td>
|
|
||||||
<td>7 --...</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="1">Q --.-</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="2">O ---</td>
|
|
||||||
<td rowspan="1"></td>
|
|
||||||
<td>8 ---..</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan="1"></td>
|
|
||||||
<td>9 ----.</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="mdl-tabs__panel mdl-card__supporting-text long" id="morse-list">
|
|
||||||
<span>A .-</span>
|
|
||||||
<span>B -...</span>
|
|
||||||
<span>C -.-.</span>
|
|
||||||
<span>D -..</span>
|
|
||||||
<span>E .</span>
|
|
||||||
<span>F ..-.</span>
|
|
||||||
<span>G --.</span>
|
|
||||||
<span>H ....</span>
|
|
||||||
<span>I ..</span>
|
|
||||||
<span>J .---</span>
|
|
||||||
<span>K -.-</span>
|
|
||||||
<span>L .-..</span>
|
|
||||||
<span>M --</span>
|
|
||||||
<span>N -.</span>
|
|
||||||
<span>O ---</span>
|
|
||||||
<span>P .--.</span>
|
|
||||||
<span>Q --.-</span>
|
|
||||||
<span>R .-.</span>
|
|
||||||
<span>S ...</span>
|
|
||||||
<span>T -</span>
|
|
||||||
<span>U ..-</span>
|
|
||||||
<span>V ...-</span>
|
|
||||||
<span>W .--</span>
|
|
||||||
<span>X -..-</span>
|
|
||||||
<span>Y -.--</span>
|
|
||||||
<span>Z --..</span>
|
|
||||||
<br>
|
|
||||||
<span>0 -----</span>
|
|
||||||
<span>1 .----</span>
|
|
||||||
<span>2 ..---</span>
|
|
||||||
<span>3 ...--</span>
|
|
||||||
<span>4 ....-</span>
|
|
||||||
<span>5 .....</span>
|
|
||||||
<span>6 -....</span>
|
|
||||||
<span>7 --...</span>
|
|
||||||
<span>8 ---..</span>
|
|
||||||
<span>9 ----.</span>
|
|
||||||
<br>
|
|
||||||
<span>End of transmission .-.-.</span>
|
|
||||||
<span>Over -.-</span>
|
|
||||||
<span>Correction ........</span>
|
|
||||||
<span>? / Say Again ..--..</span>
|
|
||||||
<span>Speak Slower --.- .-. ...</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mdl-card mdl-shadow--4dp">
|
|
||||||
<div class="mdl-card__title">
|
|
||||||
<h2 class="mdl-card__title-text">Documentation</h2>
|
|
||||||
</div>
|
|
||||||
<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
|
|
||||||
<div class="mdl-tabs__tab-bar">
|
|
||||||
<a href="#doc-about" class="mdl-tabs__tab is-active">About</a>
|
|
||||||
<a href="#doc-faq" class="mdl-tabs__tab">FAQ</a>
|
|
||||||
<a href="#doc-geek" class="mdl-tabs__tab">Geek Stuff</a>
|
|
||||||
</div>
|
|
||||||
<div class="mdl-tabs__panel mdl-card__supporting-text long is-active" id="doc-about">
|
|
||||||
<p>
|
|
||||||
This is a CW repeater,
|
|
||||||
named after Alfred Vail,
|
|
||||||
who may or may not have invented what's called "Morse code",
|
|
||||||
but clearly had some role in it.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Just like a radio repeater,
|
|
||||||
anybody can connect and start transmitting stuff,
|
|
||||||
and this will broadcast it to everyone connected.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mdl-tabs__panel mdl-card__supporting-text long" id="doc-faq">
|
|
||||||
<h3 class="mdl-card__title-text">Why Does This Exist?</h3>
|
|
||||||
<p>
|
|
||||||
I needed a place to practice CW with actual human beings,
|
|
||||||
and I wanted it to be as close as possible to what I'd experience on a radio.
|
|
||||||
I also didn't have a lot of money to spend on equipment, but I did have a computer, phone, and gamepad.
|
|
||||||
Nothing else like this exists on the Internet, as far as I can tell.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 class="mdl-card__title-text">What does "local" mean next to the repeater name?</h3>
|
|
||||||
<p>
|
|
||||||
It means this repeater doesn't repeat anything:
|
|
||||||
nothing you key in will be sent anywhere.
|
|
||||||
These are to help people practice and learn,
|
|
||||||
without worrying about anyone else hearing them fumble around.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 class="mdl-card__title-text">Why do I hear a low tone?</h3>
|
|
||||||
<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>
|
|
||||||
Vail attempts to correct for clock differences,
|
|
||||||
but making sure your computer has correct time,
|
|
||||||
down to the millisecond,
|
|
||||||
can help with reliability.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 class="mdl-card__title-text">How can I help?</h3>
|
|
||||||
<ul>
|
|
||||||
<li>Improve the <a href="https://github.com/nealey/vail/">source code</a></li>
|
|
||||||
<li>Email me and let me know you're using it</li>
|
|
||||||
<li>Vail costs me 50¢ a year to run: you could buy me a cup of coffee every 5 years or so to offset the expense</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3 class="mdl-card__title-text">Who made this?</h3>
|
|
||||||
<p>
|
|
||||||
<a href="mailto:neale@woozle.org">Neale Pickett</a> kd7oqi
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="mdl-tabs__panel mdl-card__supporting-text long" id="doc-geek">
|
|
||||||
<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>
|
|
||||||
</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>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import * as Chart from "./chart.mjs"
|
||||||
|
|
||||||
/** Silent period between words */
|
/** Silent period between words */
|
||||||
const PAUSE_WORD = -7
|
const PAUSE_WORD = -7
|
||||||
/** Silent period between letters */
|
/** Silent period between letters */
|
||||||
|
@ -145,10 +147,16 @@ class Keyer {
|
||||||
next *= this.pauseMultiplier
|
next *= this.pauseMultiplier
|
||||||
} else {
|
} else {
|
||||||
this.endTxFunc()
|
this.endTxFunc()
|
||||||
|
if (this.txChart) {
|
||||||
|
this.txChart.Add(Date.now(), 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.last = next
|
this.last = next
|
||||||
this.beginTxFunc()
|
this.beginTxFunc()
|
||||||
|
if (this.txChart) {
|
||||||
|
this.txChart.Add(Date.now(), 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.pulseTimer = setTimeout(() => this.pulse(), next * this.intervalDuration)
|
this.pulseTimer = setTimeout(() => this.pulse(), next * this.intervalDuration)
|
||||||
}
|
}
|
||||||
|
@ -180,6 +188,25 @@ class Keyer {
|
||||||
return this.last
|
return this.last
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up various charts by providing canvases for them.
|
||||||
|
*
|
||||||
|
* @param {Element} txCanvas
|
||||||
|
* @param {Element} straightCanvas
|
||||||
|
* @param {Element} ditCanvas
|
||||||
|
* @param {Element} dahCanvas
|
||||||
|
*/
|
||||||
|
SetCanvas(txCanvas=null, straightCanvas=null, ditCanvas=null, dahCanvas=null) {
|
||||||
|
for (let c of [this.txChart, this.straightChart, this.ditChart, this.dahChart]) {
|
||||||
|
if (c) c.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.txChart = txCanvas?new Chart.HistoryChart(txCanvas, "red"):null
|
||||||
|
this.straightChart =straightCanvas?new Chart.HistoryChart(straightCanvas, "teal"):null
|
||||||
|
this.ditChart =ditCanvas?new Chart.HistoryChart(ditCanvas, "olive"):null
|
||||||
|
this.dahChart =dahCanvas?new Chart.HistoryChart(dahCanvas, "purple"):null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if we are currently playing out something
|
* Return true if we are currently playing out something
|
||||||
*/
|
*/
|
||||||
|
@ -324,6 +351,9 @@ class Keyer {
|
||||||
} else {
|
} else {
|
||||||
this.endTxFunc()
|
this.endTxFunc()
|
||||||
}
|
}
|
||||||
|
if (this.straightChart) {
|
||||||
|
this.straightChart.Add(Date.now(), down?1:0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -340,6 +370,9 @@ class Keyer {
|
||||||
this.Enqueue(DIT)
|
this.Enqueue(DIT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.ditChart) {
|
||||||
|
this.ditChart.Add(Date.now(), down?1:0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -356,6 +389,9 @@ class Keyer {
|
||||||
this.Enqueue(DAH)
|
this.Enqueue(DAH)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.dahChart) {
|
||||||
|
this.dahChart.Add(Date.now(), down?1:0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,3 +153,11 @@ img {
|
||||||
padding: 0.4em;
|
padding: 0.4em;
|
||||||
min-width: 4em;
|
min-width: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#charts {
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
#charts canvas {
|
||||||
|
height: 0.5em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -87,6 +87,10 @@ class VailClient {
|
||||||
this.inputInit("#telegraph-buzzer", e => {
|
this.inputInit("#telegraph-buzzer", e => {
|
||||||
this.setTelegraphBuzzer(e.target.checked)
|
this.setTelegraphBuzzer(e.target.checked)
|
||||||
})
|
})
|
||||||
|
this.inputInit("#timing-chart", e => {
|
||||||
|
console.log("moo")
|
||||||
|
this.setTimingCharts(e.target.checked)
|
||||||
|
})
|
||||||
|
|
||||||
// Fill in the name of our repeater
|
// Fill in the name of our repeater
|
||||||
document.querySelector("#repeater").addEventListener("change", e => this.setRepeater(e.target.value.trim()))
|
document.querySelector("#repeater").addEventListener("change", e => this.setRepeater(e.target.value.trim()))
|
||||||
|
@ -101,6 +105,30 @@ class VailClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle timing charts.
|
||||||
|
*
|
||||||
|
* @param enable True to enable charts
|
||||||
|
*/
|
||||||
|
setTimingCharts(enable) {
|
||||||
|
// XXX: UI code shouldn't be in the Keyer class.
|
||||||
|
// Actually, the charts calls should be in vail
|
||||||
|
let chartsContainer = document.querySelector("#charts")
|
||||||
|
if (enable) {
|
||||||
|
chartsContainer.classList.remove("hidden")
|
||||||
|
this.keyer.SetCanvas(
|
||||||
|
document.querySelector("#txChart"),
|
||||||
|
document.querySelector("#straightChart"),
|
||||||
|
document.querySelector("#ditChart"),
|
||||||
|
document.querySelector("#dahChart"),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
chartsContainer.classList.add("hidden")
|
||||||
|
this.keyer.SetCanvas()
|
||||||
|
}
|
||||||
|
console.log("timing chart", enable)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the clicktastic buzzer, instead of the beeptastic one.
|
* Toggle the clicktastic buzzer, instead of the beeptastic one.
|
||||||
*
|
*
|
||||||
|
@ -210,6 +238,7 @@ class VailClient {
|
||||||
inputInit(selector, callback) {
|
inputInit(selector, callback) {
|
||||||
let element = document.querySelector(selector)
|
let element = document.querySelector(selector)
|
||||||
if (!element) {
|
if (!element) {
|
||||||
|
console.warn("Unable to find an input to init", selector)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let storedValue = localStorage[element.id]
|
let storedValue = localStorage[element.id]
|
||||||
|
@ -234,6 +263,7 @@ class VailClient {
|
||||||
outputWpmElement.value = (1200 / value).toFixed(1)
|
outputWpmElement.value = (1200 / value).toFixed(1)
|
||||||
}
|
}
|
||||||
if (callback) {
|
if (callback) {
|
||||||
|
console.log("callback", selector)
|
||||||
callback(e)
|
callback(e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue