diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8675ad5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "deno.enable": true, + "deno.unstable": true +} \ No newline at end of file diff --git a/app.js b/app.js index 6355aad..40fa2e2 100644 --- a/app.js +++ b/app.js @@ -3,6 +3,7 @@ import * as TW from "https://esm.sh/@twind/core@1.0.1"; import TWPreTail from "https://esm.sh/@twind/preset-tailwind@1.0.1"; import TWPreAuto from "https://esm.sh/@twind/preset-autoprefix@1.0.1"; +/** @type {TW.TwindConfig} */ const Configure = { theme: { @@ -41,8 +42,9 @@ const Configure = { [ "stroke-draw", { - "vector-effect":"non-scaling-stroke", - "stroke-linecap":"square" + "vector-effect": "non-scaling-stroke", + "stroke-linecap": "square", + "fill": "none" }, ], [ @@ -77,8 +79,10 @@ render(html` <${UI.Button} inactive>Right <${UI.Button} disabled>Right <${UI.Chart}> - - <${UI.Mark} /> + + <${UI.Mark} right=${true} x=${"20%"} y="20%" /> + <${UI.Mark} right=${false} x=${"10%"} y="20%" response=${true} /> + <${UI.Mark} right=${false}/> `, ShadowDiv); \ No newline at end of file diff --git a/squarespace.html b/squarespace.html deleted file mode 100644 index c096acb..0000000 --- a/squarespace.html +++ /dev/null @@ -1,899 +0,0 @@ - - -
- - - - - - - - - - -Earmark Hearing Conservation | Philadelphia - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - - - - - - - - - - - - - - - - - -
- -
- -
-
- - Earmark-Logo-Medium-Web-Ocean (2).png -
-
- -
- - -
- - - -
-
- - - - -

Serving musicians, music industry professionals, and music lovers in the Greater Philadelphia community.

- - - - -
-
- - -
- - - - - - -
- - - - - - - - - - - - - - - - - - - -
- -
- - -
- - -
-
- -
- - -
- - - -
-
- - -

Online Courses Available

- - - - - - -
-
- - -
- - - - - - -
 
- -

Your Ears. your MUSIC.

 Hearing wellness for musicians is healthcare, hearing protection, and occupational safety, but it is much more than that. It is reducing barriers to great performance, increasing personal satisfaction, and ensuring career longevity. Contact us to see how we can help your ears.

- - -
- - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - - -
-
- -
-
- -
- - - - -
- - -
- - - - - - -
- -

Talking Ears

A new podcast about hearing health in the music industry.

- - -
- - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - - -
-
- Serving musicians and music lovers, Earmark aims to provide customized solutions for listening, monitoring and performance needs for years to come. -
-
- -
- - - - -
- - -
- - - - -
- -

About Earmark

About Earmark and Frank Wartinger, Au.D.

- - -
-
- -
- -
- -
- - -
- - - - - - - \ No newline at end of file diff --git a/store.js b/store.js index e898d79..a5d368e 100644 --- a/store.js +++ b/store.js @@ -1,31 +1,109 @@ //@ts-check -/** @typedef {[f1:ListEntry, f2:ListEntry, f3:ListEntry, f4:ListEntry, f5:ListEntry, f6:ListEntry, f7:ListEntry]} FreqList */ -/** @typedef {number|TestMark} ListEntry */ -/** @typedef {{Name:string, Sample:{Left:FreqList, Right:FreqList}, Answer?:{Left:FreqList, Right:FreqList}}} Test */ -/** @typedef {{Stim:number|null, Resp:boolean}|null} TestMark*/ -/** @type FreqList */ -export const Frequencies = [500, 1000, 2000, 3000, 4000, 6000, 8000]; -/** @type Array */ -export const Tests = [ - { - Name: "Patient A Asymmetric Notch", - Sample:{ - Left:[15, 10, 15, 30, 40, 35, 20], - Right:[10, 10, 20, 40, 55, 40, 15] - } - } +const size = 100/6; +/** @typedef {[frequency:number, position:number, normal:boolean]} ColumnMapping */ +/** @type {Array} */ +export const ColumnMapping = [ + [ 125, size*0.0, true ], + [ 250, size*1.0, true ], + [ 500, size*2.0, true ], + [1000, size*3.0, true ], + [2000, size*4.0, true ], + [3000, size*4.5, false], + [4000, size*5.0, true ], + [6000, size*5.5, false], + [8000, size*6.0, true ] ]; - -export const Controls = +/** @type {(inFrequency:number)=>ColumnMapping|false} */ +export const ColumnLookup =(inFrequency)=> { - Test:0, - Channel: "left", - Frequency: 1, - Stimulus: 30 + for(let i=0; i}} Test */ +/** @typedef {{Test?:Test, Freq?:TestFrequency, Mark?:TestFrequencySample}} Context */ +/** @typedef {{Chan:"left"|"right", Freq:number, Stim:number, Selection:Context, Tests:Array}} State */ +/** @type {State} */ +export const Initial = +{ + Chan: "left", + Freq: 3, + Stim: 30, + Selection: + { + Test: undefined, + Freq: undefined, + Mark: undefined + }, + Tests: [ + { + Name: "Patient A Asymmetric Notch", + Plot: + [ + { Hz: 500, TestL: { Stim: 30, Resp: true }, TestR: { Stim: 50, Resp: true } }, + { Hz: 1000, TestL: { Stim: 50, Resp: true }, TestR: { Stim: 55, Resp: true } } + ] + } + ] }; -function Reducer(inState, inAction) +/** @typedef {{Name:"Mark", Data:boolean|undefined}} ActionMark */ +/** @typedef {{Name:"Test", Data:number}} ActionTest*/ +/** @typedef {ActionMark|ActionTest} Action */ +/** @typedef {(inState:State, inAction:Action)=>State} Reducer */ +/** @type {Reducer} */ +export function Reducer(inState, inAction) { + const clone = {...inState}; + switch(inAction.Name) + { + case "Test" : + { + let selTest = clone.Tests[inAction.Data]; + let selFreq = undefined; + let selMark = undefined; + const column = ColumnLookup(clone.Freq); + if(column) + { + let hz = column[0]; + let plot; + for(let i=0; i -import {html} from "https://esm.sh/htm@3.1.1/preact"; +import { html } from "https://esm.sh/htm@3.1.1/preact"; +import { ColumnMapping, ColumnLookup } from "./store.js"; /** @typedef {({children}:{children:React.ReactNode})=>JSX.Element} BasicElement */ +/** @type {({children, icon, light, disabled, inactive}:{children:React.ReactNode, icon?:JSX.Element, light:boolean, disabled:boolean, inactive:boolean})=>JSX.Element} */ export function Button({children, icon, light, disabled, inactive}) { const [LightGet, LightSet] = React.useState(light); @@ -38,36 +39,23 @@ export function Button({children, icon, light, disabled, inactive}) /** @type {BasicElement} */ export function Chart({children}) { - const inset = 20 - - const size = 1/6; - /** @type {Record} */ - const rulesXMapping = { - "125": [size*0.0, true ], - "250": [size*1.0, true ], - "500": [size*2.0, true ], - "1000": [size*3.0, true ], - "2000": [size*4.0, true ], - "3000": [size*4.5, false], - "4000": [size*5.0, true ], - "6000": [size*5.5, false], - "8000": [size*6.0, true ] - }; - const rulesX = Object.entries(rulesXMapping).map(([label, [position, normal]])=> + const inset = 20; + /** @type {Array} */ + const rules = []; + ColumnMapping.forEach(([label, position, normal])=> { - return html` - + rules.push(html` + ${label} - `; + `); }); - const rulesY = []; - const rulesYMin = -10; - const rulesYMax = 120; - for(let db = rulesYMin; db <= rulesYMax; db+=10) + + const dbMin = -10; + const dbMax = 120; + for(let db = dbMin; db <= dbMax; db+=10) { - const percent = ((db-rulesYMin) / (rulesYMax-rulesYMin))*100; - rulesY.push(html` -
- ${ rulesX } - ${ rulesY } + ${ rules }
${ children }
@@ -94,6 +81,7 @@ export function Chart({children}) `; } + /** @type {Record} */ const Glyph = { Arrow:({children})=> html`