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.
|
||||
*/
|
||||
export function getFortune() {
|
||||
export function GetFortune() {
|
||||
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>
|
||||
</nav>
|
||||
<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">
|
||||
<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>
|
||||
|
@ -71,6 +80,10 @@
|
|||
<option>1-15 WPM</option>
|
||||
<option>16-20 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>
|
||||
<label class="mdl-textfield__label" for="repeater">Repeater</label>
|
||||
</div>
|
||||
|
|
|
@ -90,11 +90,12 @@ if (!window.AudioContext) {
|
|||
*/
|
||||
class Keyer {
|
||||
/**
|
||||
* Create an Iambic control
|
||||
* Create an Keyer
|
||||
*
|
||||
* @param {TxControl} beginTxFunc Function to begin transmitting
|
||||
* @param {TxControl} endTxFunc Function to end transmitting
|
||||
* @param {TxControl} beginTxFunc Callback to begin transmitting
|
||||
* @param {TxControl} endTxFunc Callback to end transmitting
|
||||
* @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}={}) {
|
||||
this.beginTxFunc = beginTxFunc
|
||||
|
@ -201,6 +202,11 @@ class Keyer {
|
|||
this.maybePulse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a morse code string (eg "... --- ...")
|
||||
*
|
||||
* @param {string} ms String to enqueue
|
||||
*/
|
||||
EnqueueMorseString(ms) {
|
||||
for (let mc of ms) {
|
||||
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} = {}) {
|
||||
for (let c of s.toLowerCase()) {
|
||||
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 {
|
||||
constructor(name, rx) {
|
||||
this.name = name
|
||||
|
@ -104,7 +110,7 @@ export class Vail {
|
|||
}
|
||||
|
||||
export class Null {
|
||||
constructor(name, rx) {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
Transmit(time, duration, squelch=True) {
|
||||
|
@ -113,3 +119,35 @@ export class Null {
|
|||
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 Inputs from "./inputs.mjs"
|
||||
import * as Repeaters from "./repeaters.mjs"
|
||||
import {getFortune} from "./fortunes.mjs"
|
||||
|
||||
const DefaultRepeater = "General Chaos"
|
||||
|
||||
|
@ -27,7 +26,7 @@ class VailClient {
|
|||
this.sent = []
|
||||
this.lagTimes = [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.beginTxTime = null // Time when we began transmitting
|
||||
this.debug = localStorage.debug
|
||||
|
@ -37,14 +36,14 @@ class VailClient {
|
|||
let me = new URL(location)
|
||||
let repeater = me.searchParams.get("repeater")
|
||||
me.search = ""
|
||||
me.hash = repeater
|
||||
me.hash = decodeURIComponent(repeater)
|
||||
window.location = me
|
||||
}
|
||||
|
||||
// Make helpers
|
||||
this.buzzer = new Morse.Buzzer()
|
||||
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
|
||||
this.inputs = Inputs.SetupAll(this.keyer)
|
||||
|
@ -60,7 +59,7 @@ class VailClient {
|
|||
// Set up sliders
|
||||
this.sliderInit("#iambic-duration", e => {
|
||||
this.keyer.SetIntervalDuration(e.target.value)
|
||||
this.iambicKeyer.SetIntervalDuration(e.target.value)
|
||||
this.roboKeyer.SetIntervalDuration(e.target.value)
|
||||
})
|
||||
this.sliderInit("#rx-delay", e => {
|
||||
this.rxDelay = Number(e.target.value)
|
||||
|
@ -68,7 +67,7 @@ class VailClient {
|
|||
|
||||
// Fill in the name of our repeater
|
||||
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) {
|
||||
if (!name || (name == "")) {
|
||||
name = "General Chaos"
|
||||
name = DefaultRepeater
|
||||
}
|
||||
this.repeaterName = name
|
||||
|
||||
|
@ -106,7 +105,20 @@ class VailClient {
|
|||
if (this.repeater) {
|
||||
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}`)
|
||||
}
|
||||
|
@ -180,7 +192,7 @@ class VailClient {
|
|||
* @param {dict} stats Stuff the repeater class would like us to know about
|
||||
*/
|
||||
receive(when, duration, stats) {
|
||||
this.clockOffset = stats.clockOffset
|
||||
this.clockOffset = stats.clockOffset || "unknown"
|
||||
let now = Date.now()
|
||||
when += this.rxDelay
|
||||
|
||||
|
|
Loading…
Reference in New Issue