Skip to content

Commit

Permalink
Make it optional to show CS, variety and brightness on Analysis
Browse files Browse the repository at this point in the history
Store preferences for maximum matrix width and computation of CS, variety and brightness.
Replace repetitive local storage code with a handy utility.
Fix gas label being on the wrong side of the input.
  • Loading branch information
frostburn committed Apr 5, 2024
1 parent fa9cc73 commit 00e469c
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 35 deletions.
6 changes: 2 additions & 4 deletions src/stores/scale.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Scale } from '@/scale'
import { midiNoteNumberToEnharmonics, type AccidentalStyle } from '@/utils'
import { midiNoteNumberToEnharmonics, type AccidentalStyle, syncValues } from '@/utils'
import { defineStore } from 'pinia'
import { computed, ref, watch } from 'vue'
import { mmod, mtof } from 'xen-dev-utils'
Expand Down Expand Up @@ -272,9 +272,7 @@ export const useScaleStore = defineStore('scale', () => {
})

// Local storage watchers
watch(accidentalPreference, (newValue) => localStorage.setItem('accidentalPreference', newValue))
watch(hasLeftOfZ, (newValue) => window.localStorage.setItem('hasLeftOfZ', newValue.toString()))
watch(gas, (newValue) => window.localStorage.setItem('gas', newValue.toString()))
syncValues({ accidentalPreference, hasLeftOfZ, gas })

function latticeView(this: ExpressionVisitor) {
const scale = this.getCurrentScale()
Expand Down
50 changes: 30 additions & 20 deletions src/stores/state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { reactive, ref, watch } from 'vue'
import { defineStore } from 'pinia'
import { UNIX_NEWLINE } from '@/constants'
import { syncValues } from '@/utils'

export const useStateStore = defineStore('state', () => {
const isomorphicVertical = ref(5)
Expand All @@ -23,7 +24,15 @@ export const useStateStore = defineStore('state', () => {
const centsFractionDigits = ref(parseInt(storage.getItem('centsFractionDigits') ?? '3', 10))
const decimalFractionDigits = ref(parseInt(storage.getItem('decimalFractionDigits') ?? '5', 10))
const showVirtualQwerty = ref(storage.getItem('showVirtualQwerty') === 'true')

// Analysis preferences
const intervalMatrixIndexing = ref(parseInt(storage.getItem('intervalMatrixIndexing') ?? '0', 10))
const maxMatrixWidth = ref(parseInt(storage.getItem('maxMatrixWidth') ?? '100', 10))
const calculateConstantStructureViolations = ref(
storage.getItem('calculateConstantStructureViolations') === 'true'
)
const calculateVariety = ref(storage.getItem('calculateVariety') === 'true')
const calculateBrightness = ref(storage.getItem('calculateBrightness') === 'true')

// Special keyboard codes also from local storage.
const deactivationCode = ref(storage.getItem('deactivationCode') ?? 'Backquote')
Expand All @@ -33,33 +42,30 @@ export const useStateStore = defineStore('state', () => {
const degreeDownCode = ref(storage.getItem('degreeDownCode') ?? 'NumpadSubtract')

// Local storage watchers
watch(newline, (newValue) => window.localStorage.setItem('newline', newValue))
syncValues({
newline,
centsFractionDigits,
decimalFractionDigits,
showVirtualQwerty,
intervalMatrixIndexing,
maxMatrixWidth,
calculateConstantStructureViolations,
calculateVariety,
calculateBrightness,
deactivationCode,
equaveUpCode,
equaveDownCode,
degreeUpCode,
degreeDownCode
})
watch(
colorScheme,
(newValue) => {
window.localStorage.setItem('colorScheme', newValue)
storage.setItem('colorScheme', newValue)
document.documentElement.setAttribute('data-theme', newValue)
},
{ immediate: true }
)
watch(centsFractionDigits, (newValue) =>
window.localStorage.setItem('centsFractionDigits', newValue.toString())
)
watch(decimalFractionDigits, (newValue) =>
window.localStorage.setItem('decimalFractionDigits', newValue.toString())
)
watch(showVirtualQwerty, (newValue) =>
window.localStorage.setItem('showVirtualQwerty', newValue.toString())
)
watch(intervalMatrixIndexing, (newValue) =>
window.localStorage.setItem('intervalMatrixIndexing', newValue.toString())
)
// Store keymaps
watch(deactivationCode, (newValue) => window.localStorage.setItem('deactivationCode', newValue))
watch(equaveUpCode, (newValue) => window.localStorage.setItem('equaveUpCode', newValue))
watch(equaveDownCode, (newValue) => window.localStorage.setItem('equaveDownCode', newValue))
watch(degreeUpCode, (newValue) => window.localStorage.setItem('degreeUpCode', newValue))
watch(degreeDownCode, (newValue) => window.localStorage.setItem('degreeDownCode', newValue))

return {
// Live state
Expand All @@ -75,6 +81,10 @@ export const useStateStore = defineStore('state', () => {
decimalFractionDigits,
showVirtualQwerty,
intervalMatrixIndexing,
maxMatrixWidth,
calculateConstantStructureViolations,
calculateVariety,
calculateBrightness,
deactivationCode,
equaveUpCode,
equaveDownCode,
Expand Down
12 changes: 11 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { computed, type ComputedRef } from 'vue'
import { computed, watch, type ComputedRef, type Ref } from 'vue'
import { gcd, mmod } from 'xen-dev-utils'
import {
evaluateExpression,
Expand Down Expand Up @@ -445,3 +445,13 @@ export function annotateColors(sourceLines: string[], keyColors: string[]) {
sourceLines[i] += ' ' + keyColors[mmod(i + 1, keyColors.length)].replace(/%/g, '')
}
}

/**
* Synchronize local storage with the values of Vue refs.
* @param values Vue refs to watch in a `{ref1, ref2}` record.
*/
export function syncValues(values: Record<string, Ref>) {
for (const [key, value] of Object.entries(values)) {
watch(value, (newValue) => window.localStorage.setItem(key, String(newValue)))
}
}
56 changes: 47 additions & 9 deletions src/views/AnalysisView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ import { useScaleStore } from '@/stores/scale'
import { mmod } from 'xen-dev-utils'
import { OCTAVE } from '@/constants'
const MAX_SCALE_SIZE = 100
const audio = useAudioStore()
const state = useStateStore()
const scale = useScaleStore()
const cellFormat = ref<'best' | 'cents' | 'decimal'>('best')
const showOptions = ref(false)
const trailLongevity = ref(70)
const maxOtonalRoot = ref(16)
const maxUtonalRoot = ref(23)
Expand Down Expand Up @@ -80,7 +79,9 @@ function formatMatrixCell(interval: Interval) {
const highlights = reactive<boolean[][]>([])
const matrix = computed(() => intervalMatrix(scale.relativeIntervals))
const matrix = computed(() =>
intervalMatrix(scale.relativeIntervals.slice(0, state.maxMatrixWidth))
)
const matrixRows = computed(() => matrix.value.map((row) => row.map(formatMatrixCell)))
Expand Down Expand Up @@ -124,6 +125,9 @@ const nedjiProjector = computed(() => {
})
function highlight(y?: number, x?: number) {
if (!state.calculateConstantStructureViolations) {
return
}
if (highlights.length !== matrix.value.length) {
highlights.length = 0
for (let i = 0; i < matrix.value.length; ++i) {
Expand Down Expand Up @@ -170,11 +174,11 @@ function highlight(y?: number, x?: number) {
<table @mouseleave="highlight()">
<tr>
<th></th>
<th v-for="i of Math.min(scale.scale.size, MAX_SCALE_SIZE)" :key="i">
<th v-for="i of Math.min(scale.scale.size, state.maxMatrixWidth)" :key="i">
{{ i - 1 + state.intervalMatrixIndexing }}
</th>
<th>({{ scale.scale.size + state.intervalMatrixIndexing }})</th>
<th class="brightness">Bright %</th>
<th class="brightness" v-if="state.calculateBrightness">Bright %</th>
</tr>
<tr v-for="(row, i) of matrixRows" :key="i">
<th :class="{ held: heldScaleDegrees.has(i) }">
Expand All @@ -183,17 +187,20 @@ function highlight(y?: number, x?: number) {
<td
v-for="(name, j) of row"
:key="j"
:class="{ violator: violations[i][j], highlight: (highlights[i] ?? [])[j] }"
:class="{
violator: state.calculateConstantStructureViolations && violations[i][j],
highlight: (highlights[i] ?? [])[j]
}"
@mouseover="highlight(i, j)"
>
{{ name }}
</td>
<td class="brightness">{{ brightness[i] }}</td>
<td class="brightness" v-if="state.calculateBrightness">{{ brightness[i] }}</td>
</tr>
<tr class="variety">
<tr class="variety" v-if="state.calculateVariety">
<th>Var</th>
<td v-for="(v, i) of variety" :key="i">{{ v }}</td>
<td class="brightness"></td>
<td class="brightness" v-if="state.calculateBrightness"></td>
</tr>
</table>
</div>
Expand All @@ -215,6 +222,11 @@ function highlight(y?: number, x?: number) {
<label for="format-decimal"> Decimal ratio </label>
</span>
</div>
</div>
<p class="section" :class="{ open: showOptions }" @click="showOptions = !showOptions">
More options
</p>
<div class="control-group" v-show="showOptions">
<div class="control radio-group">
<label>Interval indexing</label>
<span>
Expand All @@ -227,6 +239,32 @@ function highlight(y?: number, x?: number) {
<label for="indexing-one"> 1-indexing </label>
</span>
</div>
<div class="control">
<label for="max-matrix-width">Maximum matrix width</label>
<input
id="max-matrix-width"
type="number"
min="1"
step="1"
v-model="state.maxMatrixWidth"
/>
</div>
<div class="control checkbox-container">
<input
id="calculate-violators"
type="checkbox"
v-model="state.calculateConstantStructureViolations"
/>
<label for="calculate-violators"> Show constant structure violations</label>
</div>
<div class="control checkbox-container">
<input id="calculate-variety" type="checkbox" v-model="state.calculateVariety" />
<label for="calculate-variety"> Show variety signature</label>
</div>
<div class="control checkbox-container">
<input id="calculate-brightness" type="checkbox" v-model="state.calculateBrightness" />
<label for="calculate-brightness"> Show mode brightness</label>
</div>
</div>
<div class="columns-container">
<div class="column">
Expand Down
2 changes: 1 addition & 1 deletion src/views/PreferencesView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ const scale = useScaleStore()
<label for="virtual-qwerty"> Virtual QWERTY in top menu</label>
</div>
<div class="control">
<input id="gas" type="number" min="1" v-model="scale.gas" />
<label for="gas">Computational budget (gas)</label>
<input id="gas" type="number" min="1" v-model="scale.gas" />
</div>
</div>
</div>
Expand Down

0 comments on commit 00e469c

Please sign in to comment.