Structure client files
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="-1 -1 15 15" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx= "6" cy="10" r="2" style="stroke: #000;"/>
|
||||
<circle cx="10" cy= "6" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx= "2" cy= "6" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx= "6" cy= "2" r="2" style="stroke: #000; fill: none;"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 369 B |
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="-1 -1 15 15" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx= "6" cy="10" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx="10" cy= "6" r="2" style="stroke: #000;"/>
|
||||
<circle cx= "2" cy= "6" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx= "6" cy= "2" r="2" style="stroke: #000; fill: none;"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 369 B |
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="-1 -1 15 15" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx= "6" cy="10" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx="10" cy= "6" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx= "2" cy= "6" r="2" style="stroke: #000;"/>
|
||||
<circle cx= "6" cy= "2" r="2" style="stroke: #000; fill: none;"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 369 B |
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="-1 -1 15 15" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx= "6" cy="10" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx="10" cy= "6" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx= "2" cy= "6" r="2" style="stroke: #000; fill: none;"/>
|
||||
<circle cx= "6" cy= "2" r="2" style="stroke: #000;"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 369 B |
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Chart-O-Matic</title>
|
||||
<script type="module" src="chart.mjs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>The Amazing Chart-O-Matic</h1>
|
||||
<canvas id="chart" style="border: solid black 1px; width: 100%;"></canvas>
|
||||
</body>
|
||||
</html>
|
|
@ -11,17 +11,17 @@
|
|||
|
||||
<!-- Vail stuff -->
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="icon" href="vail.png" sizes="256x256" type="image/png">
|
||||
<link rel="icon" href="vail.svg" sizes="any" type="image/svg+xml">
|
||||
<script type="module" src="vail.mjs"></script>
|
||||
<script type="module" src="ui.mjs"></script>
|
||||
<link rel="icon" href="assets/vail.png" sizes="256x256" type="image/png">
|
||||
<link rel="icon" href="assets/vail.svg" sizes="any" type="image/svg+xml">
|
||||
<script type="module" src="scripts/vail.mjs"></script>
|
||||
<script type="module" src="scripts/ui.mjs"></script>
|
||||
<link rel="stylesheet" href="vail.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar is-dark">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item">
|
||||
<img class="" src="vail.svg" alt="">
|
||||
<img class="" src="assets/vail.svg" alt="">
|
||||
<div class="block">Vail</div>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"theme_color": "#009688",
|
||||
"description": "Internet Morse Code client",
|
||||
"icons": [
|
||||
{"src": "vail.png", "sizes": "250x250"},
|
||||
{"src": "vail.svg", "sizes": "150x150"}
|
||||
{"src": "assets/vail.png", "sizes": "250x250"},
|
||||
{"src": "assets/vail.svg", "sizes": "150x150"}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -259,8 +259,8 @@ class TelegraphBuzzer extends AudioBuzzer{
|
|||
|
||||
this.hum = new Oscillator(140, 0.005, "sawtooth")
|
||||
|
||||
this.closeSample = new Sample("telegraph-a.mp3")
|
||||
this.openSample = new Sample("telegraph-b.mp3")
|
||||
this.closeSample = new Sample("../assets/telegraph-a.mp3")
|
||||
this.openSample = new Sample("../assets/telegraph-b.mp3")
|
||||
}
|
||||
|
||||
async Buzz(tx, when=0) {
|
|
@ -53,12 +53,13 @@ export class Vail {
|
|||
"open",
|
||||
msg => {
|
||||
this.connected = true
|
||||
this.rx(0, 0, {connected: true})
|
||||
this.rx(0, 0, {connected: true, notice: "Repeater connected"})
|
||||
}
|
||||
)
|
||||
this.socket.addEventListener(
|
||||
"close",
|
||||
msg => {
|
||||
this.rx(0, 0, {connected: false, notice: `Repeater disconnected: ${msg.reason}`})
|
||||
console.error("Repeater connection dropped:", msg.reason)
|
||||
setTimeout(() => this.reopen(), 2*Second)
|
||||
}
|
||||
|
@ -158,20 +159,20 @@ export class Vail {
|
|||
export class Null {
|
||||
constructor(rx, interval=3*Second) {
|
||||
this.rx = rx
|
||||
this.interval = setInterval(() => this.pulse(), interval)
|
||||
this.pulse()
|
||||
this.init()
|
||||
}
|
||||
|
||||
pulse() {
|
||||
this.rx(0, 0, {note: "local", connected: false})
|
||||
notice(msg) {
|
||||
this.rx(0, 0, {connected: false, notice: msg})
|
||||
}
|
||||
|
||||
Transmit(time, duration, squelch=true) {
|
||||
init() {
|
||||
this.notice("Null repeater: nobody will hear you.")
|
||||
}
|
||||
|
||||
Close() {
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
Transmit(time, duration, squelch=true) {}
|
||||
|
||||
Close() {}
|
||||
}
|
||||
|
||||
export class Echo extends Null {
|
||||
|
@ -180,6 +181,10 @@ export class Echo extends Null {
|
|||
this.delay = delay
|
||||
}
|
||||
|
||||
init () {
|
||||
this.notice("Echo repeater: you can only hear yourself.")
|
||||
}
|
||||
|
||||
Transmit(time, duration, squelch=true) {
|
||||
this.rx(time + this.delay, duration, {note: "local"})
|
||||
}
|
||||
|
@ -189,16 +194,19 @@ export class Fortune extends Null {
|
|||
/**
|
||||
*
|
||||
* @param rx Receive callback
|
||||
* @param {Keyer} keyer Keyer object
|
||||
* @param {Keyer} keyer Robokeyer
|
||||
*/
|
||||
constructor(rx, keyer) {
|
||||
super(rx, 1*Minute)
|
||||
super(rx)
|
||||
this.keyer = keyer
|
||||
this.pulse()
|
||||
}
|
||||
|
||||
init() {
|
||||
this.notice("Say something, and I will tell you your fortune.")
|
||||
}
|
||||
|
||||
pulse() {
|
||||
super.pulse()
|
||||
this.timeout = null
|
||||
if (!this.keyer || this.keyer.Busy()) {
|
||||
return
|
||||
}
|
||||
|
@ -207,6 +215,13 @@ export class Fortune extends Null {
|
|||
this.keyer.EnqueueAsciiString(`${fortune} \x04 `)
|
||||
}
|
||||
|
||||
Transmit(time, duration, squelch=true) {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout)
|
||||
}
|
||||
this.timeout = setTimeout(() => this.pulse(), 3 * Second)
|
||||
}
|
||||
|
||||
Close() {
|
||||
this.keyer.Flush()
|
||||
super.Close()
|
|
@ -281,7 +281,7 @@ class VailClient {
|
|||
number = Number(numberMatch[0])
|
||||
}
|
||||
|
||||
if (name.startsWith("Fortunesf")) {
|
||||
if (name.startsWith("Fortunes")) {
|
||||
this.roboKeyer.SetPauseMultiplier(number || 1)
|
||||
this.repeater = new Repeaters.Fortune(rx, this.roboKeyer)
|
||||
} else if (name.startsWith("Echo")) {
|
||||
|
@ -291,8 +291,6 @@ class VailClient {
|
|||
} else {
|
||||
this.repeater = new Repeaters.Vail(rx, name)
|
||||
}
|
||||
|
||||
toast(`Now using repeater: ${name}`)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -371,6 +369,10 @@ class VailClient {
|
|||
this.rxDurations.splice(20, 2)
|
||||
}
|
||||
|
||||
if (stats.notice) {
|
||||
toast(stats.notice)
|
||||
}
|
||||
|
||||
let averageLag = (stats.averageLag || 0).toFixed(2)
|
||||
let longestRxDuration = this.rxDurations.reduce((a,b) => Math.max(a,b))
|
||||
let suggestedDelay = ((averageLag + longestRxDuration) * 1.2).toFixed(0)
|