mirror of https://github.com/nealey/vail.git
Fortunes are now a repeater
This commit is contained in:
parent
42c88c3896
commit
fbc489dfdc
|
@ -462,6 +462,6 @@ export const fortunes = [
|
||||||
/**
|
/**
|
||||||
* Return a randomly-chosen fortune.
|
* Return a randomly-chosen fortune.
|
||||||
*/
|
*/
|
||||||
export function getFortune() {
|
export function GetFortune() {
|
||||||
return fortunes[Math.floor(Math.random() * fortunes.length)]
|
return fortunes[Math.floor(Math.random() * fortunes.length)]
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,15 @@
|
||||||
<a class="mdl-navigation__link" href="?repeater=21-99+WPM">21-99 WPM</a>
|
<a class="mdl-navigation__link" href="?repeater=21-99+WPM">21-99 WPM</a>
|
||||||
</nav>
|
</nav>
|
||||||
<hr>
|
<hr>
|
||||||
|
<span class="mdl-layout-title">Local Practice</span>
|
||||||
|
<nav class="mdl-navigation">
|
||||||
|
<a class="mdl-navigation__link" href="?repeater=Fortunes">Fortunes</a>
|
||||||
|
<a class="mdl-navigation__link" href="?repeater=Fortunes: Pauses ×2">Fortunes (slow)</a>
|
||||||
|
<a class="mdl-navigation__link" href="?repeater=Fortunes: Pauses ×4">Fortunes (very slow)</a>
|
||||||
|
<a class="mdl-navigation__link" href="?repeater=Fortunes: Pauses ×6">Fortunes (very very slow)</a>
|
||||||
|
<a class="mdl-navigation__link" href="?repeater=Fortunes: Pauses ×10">Fortunes (crazy slow)</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<nav class="mdl-navigation">
|
<nav class="mdl-navigation">
|
||||||
<a class="mdl-navigation__link" href="https://morse.withgoogle.com/learn/">Learn Morse Code</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>
|
<a class="mdl-navigation__link" href="https://github.com/nealey/vail-adapter">Use a physical key</a>
|
||||||
|
@ -71,6 +80,10 @@
|
||||||
<option>1-15 WPM</option>
|
<option>1-15 WPM</option>
|
||||||
<option>16-20 WPM</option>
|
<option>16-20 WPM</option>
|
||||||
<option>21+ WPM</option>
|
<option>21+ WPM</option>
|
||||||
|
<option>Fortunes: Pauses ×8</option>
|
||||||
|
<option>Fortunes: Pauses ×4</option>
|
||||||
|
<option>Fortunes: Pauses ×2</option>
|
||||||
|
<option>Fortunes</option>
|
||||||
</datalist>
|
</datalist>
|
||||||
<label class="mdl-textfield__label" for="repeater">Repeater</label>
|
<label class="mdl-textfield__label" for="repeater">Repeater</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -90,11 +90,12 @@ if (!window.AudioContext) {
|
||||||
*/
|
*/
|
||||||
class Keyer {
|
class Keyer {
|
||||||
/**
|
/**
|
||||||
* Create an Iambic control
|
* Create an Keyer
|
||||||
*
|
*
|
||||||
* @param {TxControl} beginTxFunc Function to begin transmitting
|
* @param {TxControl} beginTxFunc Callback to begin transmitting
|
||||||
* @param {TxControl} endTxFunc Function to end transmitting
|
* @param {TxControl} endTxFunc Callback to end transmitting
|
||||||
* @param {number} intervalDuration Dit duration (milliseconds)
|
* @param {number} intervalDuration Dit duration (milliseconds)
|
||||||
|
* @param {number} pauseMultiplier How long to stretch out inter-letter and inter-word pauses
|
||||||
*/
|
*/
|
||||||
constructor(beginTxFunc, endTxFunc, {intervalDuration=100, pauseMultiplier=1}={}) {
|
constructor(beginTxFunc, endTxFunc, {intervalDuration=100, pauseMultiplier=1}={}) {
|
||||||
this.beginTxFunc = beginTxFunc
|
this.beginTxFunc = beginTxFunc
|
||||||
|
@ -201,6 +202,11 @@ class Keyer {
|
||||||
this.maybePulse()
|
this.maybePulse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue a morse code string (eg "... --- ...")
|
||||||
|
*
|
||||||
|
* @param {string} ms String to enqueue
|
||||||
|
*/
|
||||||
EnqueueMorseString(ms) {
|
EnqueueMorseString(ms) {
|
||||||
for (let mc of ms) {
|
for (let mc of ms) {
|
||||||
switch (mc) {
|
switch (mc) {
|
||||||
|
@ -217,6 +223,11 @@ class Keyer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue an ASCII string (eg "SOS help")
|
||||||
|
*
|
||||||
|
* @param {string} s String to enqueue
|
||||||
|
*/
|
||||||
EnqueueAsciiString(s, {pauseLetter = PAUSE_LETTER, pauseWord = PAUSE_WORD} = {}) {
|
EnqueueAsciiString(s, {pauseLetter = PAUSE_LETTER, pauseWord = PAUSE_WORD} = {}) {
|
||||||
for (let c of s.toLowerCase()) {
|
for (let c of s.toLowerCase()) {
|
||||||
let m = MorseMap[c]
|
let m = MorseMap[c]
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
import {GetFortune} from "./fortunes.mjs"
|
||||||
|
|
||||||
|
const Millisecond = 1
|
||||||
|
const Second = 1000 * Millisecond
|
||||||
|
const Minute = 60 * Second
|
||||||
|
|
||||||
export class Vail {
|
export class Vail {
|
||||||
constructor(name, rx) {
|
constructor(name, rx) {
|
||||||
this.name = name
|
this.name = name
|
||||||
|
@ -104,7 +110,7 @@ export class Vail {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Null {
|
export class Null {
|
||||||
constructor(name, rx) {
|
constructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Transmit(time, duration, squelch=True) {
|
Transmit(time, duration, squelch=True) {
|
||||||
|
@ -113,3 +119,35 @@ export class Null {
|
||||||
Close() {
|
Close() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class Fortune {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param rx Receive callback
|
||||||
|
* @param {Keyer} keyer Keyer object
|
||||||
|
*/
|
||||||
|
constructor(rx, keyer) {
|
||||||
|
this.rx = rx
|
||||||
|
this.keyer = keyer
|
||||||
|
|
||||||
|
this.interval = setInterval(() => this.pulse(), 1 * Minute)
|
||||||
|
this.pulse()
|
||||||
|
}
|
||||||
|
|
||||||
|
pulse() {
|
||||||
|
if (this.keyer.Busy()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let fortune = GetFortune()
|
||||||
|
this.keyer.EnqueueAsciiString(`${fortune}\x04 `)
|
||||||
|
}
|
||||||
|
|
||||||
|
Transmit(time, duration, squelch=true) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
Close() {
|
||||||
|
clearInterval(this.interval)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
import * as Morse from "./morse.mjs"
|
import * as Morse from "./morse.mjs"
|
||||||
import * as Inputs from "./inputs.mjs"
|
import * as Inputs from "./inputs.mjs"
|
||||||
import * as Repeaters from "./repeaters.mjs"
|
import * as Repeaters from "./repeaters.mjs"
|
||||||
import {getFortune} from "./fortunes.mjs"
|
|
||||||
|
|
||||||
const DefaultRepeater = "General Chaos"
|
const DefaultRepeater = "General Chaos"
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ class VailClient {
|
||||||
this.sent = []
|
this.sent = []
|
||||||
this.lagTimes = [0]
|
this.lagTimes = [0]
|
||||||
this.rxDurations = [0]
|
this.rxDurations = [0]
|
||||||
this.clockOffset = 0 // How badly our clock is off of the server's
|
this.clockOffset = "unknown" // How badly our clock is off of the server's
|
||||||
this.rxDelay = 0 // Milliseconds to add to incoming timestamps
|
this.rxDelay = 0 // Milliseconds to add to incoming timestamps
|
||||||
this.beginTxTime = null // Time when we began transmitting
|
this.beginTxTime = null // Time when we began transmitting
|
||||||
this.debug = localStorage.debug
|
this.debug = localStorage.debug
|
||||||
|
@ -37,14 +36,14 @@ class VailClient {
|
||||||
let me = new URL(location)
|
let me = new URL(location)
|
||||||
let repeater = me.searchParams.get("repeater")
|
let repeater = me.searchParams.get("repeater")
|
||||||
me.search = ""
|
me.search = ""
|
||||||
me.hash = repeater
|
me.hash = decodeURIComponent(repeater)
|
||||||
window.location = me
|
window.location = me
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make helpers
|
// Make helpers
|
||||||
this.buzzer = new Morse.Buzzer()
|
this.buzzer = new Morse.Buzzer()
|
||||||
this.keyer = new Morse.Keyer(() => this.beginTx(), () => this.endTx())
|
this.keyer = new Morse.Keyer(() => this.beginTx(), () => this.endTx())
|
||||||
this.iambicKeyer = new Morse.Keyer(() => this.buzzer.Buzz(), () => this.buzzer.Silence())
|
this.roboKeyer = new Morse.Keyer(() => this.buzzer.Buzz(), () => this.buzzer.Silence())
|
||||||
|
|
||||||
// Set up various input methods
|
// Set up various input methods
|
||||||
this.inputs = Inputs.SetupAll(this.keyer)
|
this.inputs = Inputs.SetupAll(this.keyer)
|
||||||
|
@ -60,7 +59,7 @@ class VailClient {
|
||||||
// Set up sliders
|
// Set up sliders
|
||||||
this.sliderInit("#iambic-duration", e => {
|
this.sliderInit("#iambic-duration", e => {
|
||||||
this.keyer.SetIntervalDuration(e.target.value)
|
this.keyer.SetIntervalDuration(e.target.value)
|
||||||
this.iambicKeyer.SetIntervalDuration(e.target.value)
|
this.roboKeyer.SetIntervalDuration(e.target.value)
|
||||||
})
|
})
|
||||||
this.sliderInit("#rx-delay", e => {
|
this.sliderInit("#rx-delay", e => {
|
||||||
this.rxDelay = Number(e.target.value)
|
this.rxDelay = Number(e.target.value)
|
||||||
|
@ -68,7 +67,7 @@ class VailClient {
|
||||||
|
|
||||||
// Fill in the name of our repeater
|
// Fill in the name of our repeater
|
||||||
let repeaterElement = document.querySelector("#repeater").addEventListener("change", e => this.setRepeater(e.target.value.trim()))
|
let repeaterElement = document.querySelector("#repeater").addEventListener("change", e => this.setRepeater(e.target.value.trim()))
|
||||||
this.setRepeater(decodeURI(unescape(window.location.hash.split("#")[1] || "")))
|
this.setRepeater(decodeURI(decodeURIComponent(window.location.hash.split("#")[1] || "")))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,7 +80,7 @@ class VailClient {
|
||||||
*/
|
*/
|
||||||
setRepeater(name) {
|
setRepeater(name) {
|
||||||
if (!name || (name == "")) {
|
if (!name || (name == "")) {
|
||||||
name = "General Chaos"
|
name = DefaultRepeater
|
||||||
}
|
}
|
||||||
this.repeaterName = name
|
this.repeaterName = name
|
||||||
|
|
||||||
|
@ -106,7 +105,20 @@ class VailClient {
|
||||||
if (this.repeater) {
|
if (this.repeater) {
|
||||||
this.repeater.Close()
|
this.repeater.Close()
|
||||||
}
|
}
|
||||||
this.repeater = new Repeaters.Vail(name, (w,d,s) => this.receive(w,d,s))
|
let rx = (w,d,s) => this.receive(w,d,s)
|
||||||
|
|
||||||
|
// You can set the repeater name to "Fortunes: Pauses×10" for a nice and easy intro
|
||||||
|
if (name.startsWith("Fortunes")) {
|
||||||
|
let m = name.match(/[x×]([0-9]+)/)
|
||||||
|
let mult = 1
|
||||||
|
if (m) {
|
||||||
|
mult = Number(m[1])
|
||||||
|
}
|
||||||
|
this.roboKeyer.SetPauseMultiplier(mult)
|
||||||
|
this.repeater = new Repeaters.Fortune(rx, this.roboKeyer)
|
||||||
|
} else {
|
||||||
|
this.repeater = new Repeaters.Vail(name, rx)
|
||||||
|
}
|
||||||
|
|
||||||
toast(`Now using repeater: ${name}`)
|
toast(`Now using repeater: ${name}`)
|
||||||
}
|
}
|
||||||
|
@ -180,7 +192,7 @@ class VailClient {
|
||||||
* @param {dict} stats Stuff the repeater class would like us to know about
|
* @param {dict} stats Stuff the repeater class would like us to know about
|
||||||
*/
|
*/
|
||||||
receive(when, duration, stats) {
|
receive(when, duration, stats) {
|
||||||
this.clockOffset = stats.clockOffset
|
this.clockOffset = stats.clockOffset || "unknown"
|
||||||
let now = Date.now()
|
let now = Date.now()
|
||||||
when += this.rxDelay
|
when += this.rxDelay
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue