v7.8 — share strings 2.0: big-base packing cuts them to ~28% of the script (was ~51%)
The user asked for more compression 'by any means possible', suggesting
base-62 numbers and dictionary phrases. Both ideas shipped — cranked up:
- Dictionary grew ~170 data-mined entries: every function WITH its open
paren (sin(, if(, megabuf(, …), every engine variable (vol_att, time,
bpm, sv, …), AVS idioms ("hue = hue + dt * ", "t = t + dt * ", " * 0.",
") * ", "(0."), header lines ("linewidth: ", "blend: additive",
"mode: lines"), blank-line+section skeletons ("\n\n[point]\n"), CRLF
statement ends, ~70 number literals, and the library's common variable
names (ring, spokes, chroma, segs, …) — all mined by frequency over the
101-preset embedded corpus with a greedy-cover scorer.
- New scheme ▼ 'big-base packing': the dictionary output is read as ONE
BIG NUMBER over its own alphabet and rewritten in base 32,164 — one
digit per character from CJK Unified + Hangul. ~15 bits/char vs
base-62's 5.95 ("1400" costs ~0.85 chars). The body's alphabet rides
in a ~32-char bitmap header (dict-symbol bitmap + ASCII bitmap + raw
non-ASCII tail) instead of ~80 literal symbols.
- Pair-packing kept as the fallback for short scripts (encoder picks
whichever body is shorter); ▲ strings from v7.7 still decode via the
kept legacy tables; still lossless for ANY text (verified: 101-preset
corpus + 21 edge cases incl. CRLF, Hangul/CJK literals, lone
surrogates, platform-injected zero-widths), still copy-safe, still
self-checking (8 FNV check digits).
- Base packing gated at 16K symbols (O(n²) BigInt); encode 1.1 ms on the
largest preset. Decode input capped at 40K chars.
Corpus measure: 64854 → 18026 chars = 72.2% reduction (v7.7: 49.1%);
median share string 26.9% of source, best 21.9%. Bass Bloom: 1341 → 326.
Browser-verified: encode→copy→paste→decode→load round-trip through the
dialogs for both ▼ and legacy ▲ strings, What's New 7.8 entry, mobile +
desktop layout, sticky footer.
This commit is contained in:
parent
80782609b2
commit
698fc1c2a3
4 changed files with 897 additions and 167 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
// AVA — Script ⇢ Hash share dialogs (v7.7).
|
// AVA — Script ⇢ Hash share dialogs (v7.8).
|
||||||
//
|
//
|
||||||
// Two dialogs used by the Script tab toolbar:
|
// Two dialogs used by the Script tab toolbar:
|
||||||
// • ScriptToHashDialog — encodes the current editor script into ONE
|
// • ScriptToHashDialog — encodes the current editor script into ONE
|
||||||
|
|
@ -126,11 +126,13 @@ export function ScriptToHashDialog({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="rounded-md border border-zinc-800 bg-zinc-900/40 px-2.5 py-2 text-[11px] leading-relaxed text-zinc-400">
|
<p className="rounded-md border border-zinc-800 bg-zinc-900/40 px-2.5 py-2 text-[11px] leading-relaxed text-zinc-400">
|
||||||
Built-in references keep it short:{' '}
|
Short scripts spell themselves in built-in references (
|
||||||
<span className="font-mono text-zinc-300">
|
<span className="font-mono text-zinc-300">
|
||||||
{SHARE_LEGEND.map((l) => `${l.symbol} = ${l.meaning}`).join(' · ')}
|
{SHARE_LEGEND.map((l) => `${l.symbol} = ${l.meaning}`).join(' · ')}
|
||||||
</span>
|
</span>
|
||||||
. The string works even if the script doesn't compile — perfect for asking for
|
) — longer ones additionally pack ~15 bits of script into every
|
||||||
|
character, which is why they read as dense CJK. Either way the string
|
||||||
|
works even if the script doesn't compile — perfect for asking for
|
||||||
help or sharing work in progress.
|
help or sharing work in progress.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -248,7 +250,7 @@ export function HashToScriptDialog({
|
||||||
setInput(e.target.value)
|
setInput(e.target.value)
|
||||||
setError(null)
|
setError(null)
|
||||||
}}
|
}}
|
||||||
placeholder={'My Script:[▲…]'}
|
placeholder={'My Script:[▼…]'}
|
||||||
aria-label="Paste a share string here"
|
aria-label="Paste a share string here"
|
||||||
rows={5}
|
rows={5}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -33,6 +33,24 @@ export interface ReleaseNote {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RELEASE_NOTES: ReleaseNote[] = [
|
export const RELEASE_NOTES: ReleaseNote[] = [
|
||||||
|
{
|
||||||
|
version: '7.8',
|
||||||
|
name: 'Share strings, supersized',
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
kind: 'improved',
|
||||||
|
text: 'Script⇢Hash strings are now ~72% shorter than the script (was ~49%) — the median share string is about a QUARTER of the script’s length. “1400” now costs less than one character: the whole script is packed into CJK + Hangul digits carrying ~15 bits apiece (your base-62 idea, with 32,164 digits instead of 62).',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'improved',
|
||||||
|
text: 'The symbol dictionary grew ~170 data-mined entries — every function with its open paren, every audio variable, AVS idioms like “hue = hue + dt * ”, header lines like “linewidth: ”, and ~70 number literals.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'added',
|
||||||
|
text: 'Share strings from v7.7 (the ▲ ones) still paste back perfectly — and short scripts keep the readable symbol form, since the encoder always picks whichever is shorter.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
version: '7.7',
|
version: '7.7',
|
||||||
name: 'Share scripts as one string',
|
name: 'Share scripts as one string',
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,24 @@
|
||||||
// warns in the console when the two drift apart.
|
// warns in the console when the two drift apart.
|
||||||
//
|
//
|
||||||
// History:
|
// History:
|
||||||
|
// 7.8 — share strings 2.0: ~72% shorter than the script (was ~49%). The
|
||||||
|
// base-62 idea, cranked to 11,172… 32,164: after the symbol
|
||||||
|
// dictionary (which grew ~170 data-mined entries — every function
|
||||||
|
// WITH its open paren, every engine variable, the AVS idioms
|
||||||
|
// "hue = hue + dt * " and "t = t + dt * ", " * 0.", ") * ",
|
||||||
|
// blank-line+section skeletons, "linewidth: " / "blend: additive"
|
||||||
|
// headers, ~70 number literals, and the library's common
|
||||||
|
// variable names incl. chroma) the whole body is read as ONE BIG
|
||||||
|
// NUMBER and rewritten in base 32,164 — one digit per character
|
||||||
|
// from the CJK + Hangul blocks, ~15 bits a character vs base-62's
|
||||||
|
// 5.95 (so "1400" costs ~0.85 of a character). The decoder gets
|
||||||
|
// the body's alphabet back from a ~32-character bitmap header
|
||||||
|
// instead of ~80 literal symbols. Short scripts where the header
|
||||||
|
// wouldn't pay keep the v7.7 symbol form (encoder picks whichever
|
||||||
|
// is shorter); ▲ strings from v7.7 still decode; still lossless
|
||||||
|
// for ANY text, still copy-safe, still self-checking. Corpus
|
||||||
|
// measure: median share string is 27% of the script's length
|
||||||
|
// (best 22%), e.g. Bass Bloom 1341 → 326 characters
|
||||||
// 7.7 — script sharing + settings declutter. Script⇢Hash / Hash⇢Script:
|
// 7.7 — script sharing + settings declutter. Script⇢Hash / Hash⇢Script:
|
||||||
// two buttons in the Script tab turn the editor's script into ONE
|
// two buttons in the Script tab turn the editor's script into ONE
|
||||||
// short shareable Unicode string ("Bass Bloom:[▲…①①①①①①①①]") and
|
// short shareable Unicode string ("Bass Bloom:[▲…①①①①①①①①]") and
|
||||||
|
|
@ -242,4 +260,4 @@
|
||||||
|
|
||||||
export const APP_NAME = 'Open Visualization Engine'
|
export const APP_NAME = 'Open Visualization Engine'
|
||||||
export const APP_SHORT = 'OVE'
|
export const APP_SHORT = 'OVE'
|
||||||
export const APP_VERSION = '7.7'
|
export const APP_VERSION = '7.8'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue