cursor, initialization

This commit is contained in:
Seth Trowbridge 2022-12-10 13:24:31 -05:00
parent da9f569308
commit 78049da309
3 changed files with 39 additions and 27 deletions

View File

@ -49,31 +49,29 @@ const Audiogram =()=>
{
const [State] = Store.Consumer();
/** @type {(inAmount:number)=>string} */ const Perc =(inAmount)=> (inAmount*100)+"%";
const testMarksL = State.Draw.TestL.Points.map(p=>html`<${UI.Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${false}/>`);
const userMarksL = State.Draw.UserL.Points.map(p=>html`<${UI.Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${false} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`);
const testMarksR = State.Draw.TestR.Points.map(p=>html`<${UI.Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${true} />`);
const userMarksR = State.Draw.UserR.Points.map(p=>html`<${UI.Mark} x=${p.X} y=${p.Y} response=${p.Mark?.Resp} right=${true} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`);
const testMarksL = State.Draw.TestL.Points.map(p=>html`<${UI.Mark} x=${Perc(p.X)} y=${Perc(p.Y)} response=${p.Mark.Resp} right=${false}/>`);
const userMarksL = State.Draw.UserL.Points.map(p=>html`<${UI.Mark} x=${Perc(p.X)} y=${Perc(p.Y)} response=${p.Mark.Resp} right=${false} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`);
const testMarksR = State.Draw.TestR.Points.map(p=>html`<${UI.Mark} x=${Perc(p.X)} y=${Perc(p.Y)} response=${p.Mark.Resp} right=${true} />`);
const userMarksR = State.Draw.UserR.Points.map(p=>html`<${UI.Mark} x=${Perc(p.X)} y=${Perc(p.Y)} response=${p.Mark.Resp} right=${true} classes=${State.Live.Mark == p.Mark ? "stroke-bold":""}/>`);
const testLinesL = State.Draw.TestL.Paths.map( p=>html`<line class="opacity-60" x1=${Perc(p.Head.X)} y1=${Perc(p.Head.Y)} x2=${Perc(p.Tail.X)} y2=${Perc(p.Tail.Y)} />`);
const userLinesL = State.Draw.UserL.Paths.map( p=>html`<line class="opacity-60" x1=${Perc(p.Head.X)} y1=${Perc(p.Head.Y)} x2=${Perc(p.Tail.X)} y2=${Perc(p.Tail.Y)} />`);
const testLinesR = State.Draw.TestR.Paths.map( p=>html`<line class="opacity-60" x1=${Perc(p.Head.X)} y1=${Perc(p.Head.Y)} x2=${Perc(p.Tail.X)} y2=${Perc(p.Tail.Y)} />`);
const userLinesR = State.Draw.UserR.Paths.map( p=>html`<line class="opacity-60" x1=${Perc(p.Head.X)} y1=${Perc(p.Head.Y)} x2=${Perc(p.Tail.X)} y2=${Perc(p.Tail.Y)} />`);
const testLinesL = State.Draw.TestL.Paths.map( p=>html`<line class="opacity-60" x1=${p.Head.X} y1=${p.Head.Y} x2=${p.Tail.X} y2=${p.Tail.Y} />`);
const userLinesL = State.Draw.UserL.Paths.map( p=>html`<line class="opacity-60" x1=${p.Head.X} y1=${p.Head.Y} x2=${p.Tail.X} y2=${p.Tail.Y} />`);
const testLinesR = State.Draw.TestR.Paths.map( p=>html`<line class="opacity-60" x1=${p.Head.X} y1=${p.Head.Y} x2=${p.Tail.X} y2=${p.Tail.Y} />`);
const userLinesR = State.Draw.UserR.Paths.map( p=>html`<line class="opacity-60" x1=${p.Head.X} y1=${p.Head.Y} x2=${p.Tail.X} y2=${p.Tail.Y} />`);
return html`
<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" >
<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>
<svg class="absolute top-0 w-full h-full overflow-visible transition-all duration-500" style=${{top:State.Draw.Cross?.Y, left:State.Draw.Cross?.X}}>
<ellipse cx="0" cy="0" rx="8" ry="30" fill="url(#glow)"></ellipse>
<ellipse cx="0" cy="0" rx="30" ry="8" 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>
<stop stop-color=${State.Chan.Value ? "red" : "blue"} stop-opacity="0.6" offset="0.0"></stop>
<stop stop-color=${State.Chan.Value ? "red" : "blue"} stop-opacity="0.3" offset="0.2"></stop>
<stop stop-color=${State.Chan.Value ? "red" : "blue"} stop-opacity="0.0" offset="1.0"></stop>
</radialGradient>
</defs>
</svg>

View File

@ -25,6 +25,9 @@ export const ColumnLookup =(inFrequency)=>
return false;
};
/** @type {(inDecimal:number)=>string} */
const Perc =(inDecimal)=> `${inDecimal*100}%`;
/** Creates a new Store.Context object that contain the current selections
* @type {(inState:Store.State, inTest?:Store.Test)=>Store.Context} */
const Reselect =(inState, inTest)=>
@ -69,8 +72,8 @@ const Redraw =(inTest, inChan, inStim, inIsUser)=>
{
/** @type {Store.DrawPoint} */
const point = {
X: lookup[1],
Y: (mark.Stim - inStim.Min)/(inStim.Max - inStim.Min),
X: Perc(lookup[1]),
Y: Perc((mark.Stim - inStim.Min)/(inStim.Max - inStim.Min)),
Mark: mark
};
output.Points.push(point);
@ -81,14 +84,21 @@ const Redraw =(inTest, inChan, inStim, inIsUser)=>
{
/** @type {Store.DrawLine} */
const line = {Head:output.Points[i-1], Tail:output.Points[i]};
if(line.Head.Mark.Resp && line.Tail.Mark.Resp)
if(line.Head.Mark?.Resp && line.Tail.Mark?.Resp)
{
output.Paths.push(line);
}
}
}
return output;
}
};
/** Create a new cursor position from the state
* @type {(inState:Store.State)=>Store.DrawPoint} */
const Reposition =(inState)=> ({
X: Perc(ColumnMapping[inState.Freq.Value][1]),
Y: Perc((inState.Stim.Value - inState.Stim.Min)/(inState.Stim.Max - inState.Stim.Min))
});
/** @type {Store.Reducer} */
export function Reducer(inState, inAction)
@ -100,7 +110,9 @@ export function Reducer(inState, inAction)
{
const test = clone.Tests[Data];
clone.Live = Reselect(clone, test);
clone.Draw = {
clone.Draw =
{
Cross: Reposition(clone),
UserL: Redraw(test, 0, clone.Stim, true ),
UserR: Redraw(test, 1, clone.Stim, true ),
TestL: Redraw(test, 0, clone.Stim, false),
@ -123,6 +135,8 @@ export function Reducer(inState, inAction)
tone.Value += Data*tone.Step;
tone.Value = Math.max(tone.Value, tone.Min);
tone.Value = Math.min(tone.Value, tone.Max);
clone.Draw.Cross = Reposition(clone);
if(Name != "Stim")
{
clone.Live = Reselect(clone);
@ -133,7 +147,7 @@ export function Reducer(inState, inAction)
}
/** @type {Store.State} */
export const Initial =
export const Initial = Reducer(
{
Chan: { Min:0, Max:1, Value:0, Step:1 },
Freq: { Min:2, Max:8, Value:2, Step:1 },
@ -166,7 +180,7 @@ export const Initial =
]
}
]
};
}, {Name:"Test", Data:0});
/** @type {preact.Context<Store.Binding>} */
export const Context = React.createContext([Initial, (_a)=>{}]);
@ -175,7 +189,7 @@ export const Context = React.createContext([Initial, (_a)=>{}]);
export const Provider =(props)=>
{
/** @type {Store.Binding} */
const reducer = React.useReducer(Reducer, Initial, ()=>Reducer(Initial, {Name:"Test", Data:0}));
const reducer = React.useReducer(Reducer, Initial);
return React.createElement(Context.Provider, {value:reducer, children:props.children});
};

6
store.d.ts vendored
View File

@ -25,7 +25,7 @@ declare namespace Store {
Freq: Range;
Stim: Range;
Live: Context;
Draw: DrawTest;
Draw: DrawChart;
Tests: Array<Test>;
};
@ -42,10 +42,10 @@ declare namespace Store {
type PlotKeyTest = "TestL" | "TestR";
type PlotKey = PlotKeyUser | PlotKeyTest;
type DrawPoint = { X: number; Y: number; Mark: TestFrequencySample };
type DrawPoint = { X: string; Y: string; Mark?: TestFrequencySample };
type DrawLine = { Head:DrawPoint, Tail:DrawPoint};
type DrawGroup = { Points: Array<DrawPoint>; Paths: Array<DrawLine> };
type DrawTest = { UserL: DrawGroup, UserR: DrawGroup, TestL: DrawGroup, TestR: DrawGroup };
type DrawChart = { Cross?:DrawPoint, UserL: DrawGroup, UserR: DrawGroup, TestL: DrawGroup, TestR: DrawGroup };
type Binding = [state:State, dispatch:(inAction:Action)=>void]
}