This commit is contained in:
Seth Trowbridge 2022-12-10 00:33:38 -05:00
parent 2c4d506f40
commit 7b969e0bfa
3 changed files with 72 additions and 72 deletions

View File

@ -64,7 +64,19 @@ const Audiogram =()=>
<svg class="absolute top-0 w-full h-full overflow-visible stroke(blue-700 bold draw) opacity-50">${testMarksL}${testLinesL}</svg>
<svg class="absolute top-0 w-full h-full overflow-visible stroke(red-700 bold draw) opacity-50">${testMarksR}${testLinesR}</svg>
<svg class="absolute top-0 w-full h-full overflow-visible stroke(blue-700 2 draw)">${userMarksL}${userLinesL}</svg>
<svg class="absolute top-0 w-full h-full overflow-visible stroke(red-700 2 draw)">${userMarksR}${userLinesR}</svg>`;
<svg class="absolute top-0 w-full h-full overflow-visible stroke(red-700 2 draw)">${userMarksR}${userLinesR}</svg>
<svg class="absolute top-0 w-full h-full overflow-visible" >
<ellipse cx="0" cy="0" rx="5" ry="30" fill="url(#glow)"></ellipse>
<ellipse cx="0" cy="0" rx="30" ry="5" fill="url(#glow)"></ellipse>
<defs>
<radialGradient id="glow">
<stop stop-color="blue" stop-opacity="0.6" offset="0.0"></stop>
<stop stop-color="blue" stop-opacity="0.3" offset="0.2"></stop>
<stop stop-color="blue" stop-opacity="0.0" offset="1.0"></stop>
</radialGradient>
</defs>
</svg>
`;
};
React.render(html`

View File

@ -28,8 +28,6 @@ export const ColumnLookup =(inFrequency)=>
/** @type {(freq:Store.TestFrequency, chan:number, user:boolean)=>Store.TestFrequencySample|undefined} */
export const MarkGet =(freq, chan, user)=> freq[/** @type {Store.PlotKey} */ (`${user ? "User" : "Test"}${chan ? "R" : "L"}`)];
/** @type {(freq:Store.TestFrequency, chan:number, mark:Store.TestFrequencySample|undefined)=>Store.TestFrequencySample|undefined} */
export const MarkSet =(freq, chan, mark)=> freq[ chan ? "UserR" : "UserL" ] = mark;
/** @type {Store.State} */
export const Initial =
@ -67,74 +65,65 @@ export const Initial =
]
};
/** @type {Record<string, Store.ContextUpdater>} */
const Update =
/** @type {(inState:Store.State, inTest?:Store.Test)=>Store.Context} */
const Reselect =(inState, inTest)=>
{
Freq(inState)
/** @type {Store.Context} */
const output = { Test:inTest??inState.Live.Test };
const column = ColumnMapping[inState.Freq.Value];
if(column && inState.Live.Test)
{
const column = ColumnMapping[inState.Freq.Value];
if(column && inState.Live.Test)
const hz = column[0];
for(let i=0; i<inState.Live.Test.Plot.length; i++)
{
const hz = column[0];
inState.Live.Freq = undefined;
for(let i=0; i<inState.Live.Test.Plot.length; i++)
const plot = inState.Live.Test.Plot[i];
if(plot.Hz == hz)
{
const plot = inState.Live.Test.Plot[i];
if(plot.Hz == hz)
{
inState.Live.Freq = plot;
return true;
}
output.Freq = plot;
output.Mark = plot[`User${inState.Chan.Value ? "R" : "L"}`];
}
}
return false;
},
Mark(inState)
{
const freq = inState.Live.Freq;
if(freq)
{
inState.Live.Mark = MarkGet(freq, inState.Chan.Value, true);
return true;
}
return false;
}
return output;
};
/** @type {(inTest:Store.Test, inChan:number, inStim:Store.Range, inIsUser:boolean)=>Store.DrawGroup} */
export function Congtiguous(inTest, inChan, inStim, inIsUser)
/** @type {(inTest:Store.Test|undefined, inChan:number, inStim:Store.Range, inIsUser:boolean)=>Store.DrawGroup} */
const Redraw =(inTest, inChan, inStim, inIsUser)=>
{
/** @type {Store.DrawGroup} */
const output = {Points:[], Paths:[]};
let plot;
for(let i=0; i<inTest.Plot.length; i++)
if(inTest)
{
plot = inTest.Plot[i];
const mark = MarkGet(plot, inChan, inIsUser);
if(mark)
let plot;
for(let i=0; i<inTest.Plot.length; i++)
{
const lookup = ColumnLookup(plot.Hz);
if(lookup)
plot = inTest.Plot[i];
const mark = MarkGet(plot, inChan, inIsUser);
if(mark)
{
/** @type {Store.DrawPoint} */
const point = {
X: lookup[1],
Y: (mark.Stim - inStim.Min)/(inStim.Max - inStim.Min),
Mark: mark
};
output.Points.push(point);
const lookup = ColumnLookup(plot.Hz);
if(lookup)
{
/** @type {Store.DrawPoint} */
const point = {
X: lookup[1],
Y: (mark.Stim - inStim.Min)/(inStim.Max - inStim.Min),
Mark: mark
};
output.Points.push(point);
}
}
}
}
for(let i=1; i<output.Points.length; i++)
{
/** @type {Store.DrawLine} */
const line = {Head:output.Points[i-1], Tail:output.Points[i]};
if(line.Head.Mark.Resp && line.Tail.Mark.Resp)
for(let i=1; i<output.Points.length; i++)
{
output.Paths.push(line);
/** @type {Store.DrawLine} */
const line = {Head:output.Points[i-1], Tail:output.Points[i]};
if(line.Head.Mark.Resp && line.Tail.Mark.Resp)
{
output.Paths.push(line);
}
}
}
return output;
@ -149,24 +138,27 @@ export function Reducer(inState, inAction)
if(Name == "Test")
{
clone.Live.Test = clone.Tests[Data];
Update.Freq(clone);
Update.Mark(clone);
const test = clone.Tests[Data];
clone.Live = Reselect(clone, test);
clone.Draw = {
UserL: Congtiguous(clone.Live.Test, 0, clone.Stim, true ),
UserR: Congtiguous(clone.Live.Test, 1, clone.Stim, true ),
TestL: Congtiguous(clone.Live.Test, 0, clone.Stim, false),
TestR: Congtiguous(clone.Live.Test, 1, clone.Stim, false)
UserL: Redraw(test, 0, clone.Stim, true ),
UserR: Redraw(test, 1, clone.Stim, true ),
TestL: Redraw(test, 0, clone.Stim, false),
TestR: Redraw(test, 1, clone.Stim, false)
};
clone.Live = {...clone.Live};
}
else if (Name == "Mark")
{
if(clone.Live.Test && clone.Live.Freq)
{
clone.Live.Mark = MarkSet(clone.Live.Freq, clone.Chan.Value, Data !== null ? {Stim:clone.Stim.Value, Resp:Data} : undefined);
clone.Draw[clone.Chan.Value == 0 ? "UserL" : "UserR"] = Congtiguous(clone.Live.Test, clone.Chan.Value, clone.Stim, true);
const key = clone.Chan.Value == 0 ? "UserL" : "UserR";
clone.Live.Mark = Data !== null ? {Stim:clone.Stim.Value, Resp:Data} : undefined;
clone.Live.Freq[key] = clone.Live.Mark;
clone.Live.Freq = {...clone.Live.Freq};
clone.Live = {...clone.Live};
clone.Draw[key] = Redraw(clone.Live.Test, clone.Chan.Value, clone.Stim, true);
clone.Draw = {...clone.Draw};
}
}
@ -179,9 +171,7 @@ export function Reducer(inState, inAction)
clone[Name] = tone;
if(Name != "Stim")
{
Update.Freq(clone);
Update.Mark(clone);
clone.Live = {...clone.Live};
clone.Live = Reselect(clone);
}
}

View File

@ -1,6 +1,6 @@
import React from "https://esm.sh/preact@10.11.3/compat";
import { html } from "https://esm.sh/htm@3.1.1/preact";
import { ColumnMapping } from "./store.js";
import * as Store from "./store.js";
/** @typedef {({children}:{children?:preact.ComponentChildren})=>preact.VNode} BasicElement */
@ -37,10 +37,11 @@ export function Button({children, icon, light, disabled, inactive, onClick})
/** @type {BasicElement} */
export function Chart({children})
{
const [State] = Store.Consumer();
const inset = 20;
/** @type {Array<preact.VNode>} */
const rules = [];
ColumnMapping.forEach(([label, position, normal])=>
Store.ColumnMapping.forEach(([label, position, normal])=>
{
rules.push(html`
<span class="block absolute top-[-${inset}px] left-[${position*100}%] w-0 h-[calc(100%+${inset*2}px)] border-r(1 slate-400) ${!normal && "border-dashed"}">
@ -49,12 +50,10 @@ export function Chart({children})
);
});
const dbMin = -10;
const dbMax = 120;
for(let db = dbMin; db <= dbMax; db+=10)
for(let db = State.Stim.Min; db <= State.Stim.Max; db+=10)
{
rules.push(html`
<span class="block absolute left-[-${inset}px] top-[${((db-dbMin) / (dbMax-dbMin))*100}%] h-0 w-[calc(100%+${inset*2}px)] border-b(${db == 0 ? "2 black" : "1 slate-400"})">
<span class="block absolute left-[-${inset}px] top-[${((db-State.Stim.Min) / (State.Stim.Max-State.Stim.Min))*100}%] h-0 w-[calc(100%+${inset*2}px)] border-b(${db == 0 ? "2 black" : "1 slate-400"})">
<span class="block absolute top-0 left-0 -translate-x-full -translate-y-1/2 pr-2">${db}</span>
</span>`
);
@ -87,7 +86,6 @@ const Glyph = {
<line vector-effect="non-scaling-stroke" x1="100%" y1="100%" x2="25%" y2="100%"></line>
<line vector-effect="non-scaling-stroke" x1="100%" y1="100%" x2="100%" y2="25%" ></line>`,
//style="transform: translate(50%, 50%) rotate(-15deg) scale(0.5);"
X: ({children})=> html`
<line x1="-50%" y1="-50%" x2="50%" y2="50%" ></line>
<line x1="-50%" y1="50%" x2="50%" y2="-50%"></line>