refactor (core) separate sampling into its own handler
This commit is contained in:
parent
3c54e94c43
commit
e59341effa
3 changed files with 231 additions and 194 deletions
|
@ -13,6 +13,7 @@ import { version } from '../../data.mjs'
|
||||||
import { __loadPatternDefaults } from '../config.mjs'
|
import { __loadPatternDefaults } from '../config.mjs'
|
||||||
import { PatternConfig, getPluginName } from './pattern-config.mjs'
|
import { PatternConfig, getPluginName } from './pattern-config.mjs'
|
||||||
import { PatternDraftQueue } from './pattern-draft-queue.mjs'
|
import { PatternDraftQueue } from './pattern-draft-queue.mjs'
|
||||||
|
import { PatternSampler } from './pattern-sampler.mjs'
|
||||||
import cloneDeep from 'lodash.clonedeep'
|
import cloneDeep from 'lodash.clonedeep'
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
|
@ -254,14 +255,7 @@ Pattern.prototype.getRenderProps = function () {
|
||||||
* @return {object} this - The Pattern instance
|
* @return {object} this - The Pattern instance
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.sample = function () {
|
Pattern.prototype.sample = function () {
|
||||||
this.__init()
|
return new PatternSampler(this).sample()
|
||||||
if (this.settings[0].sample.type === 'option') {
|
|
||||||
return this.sampleOption(this.settings[0].sample.option)
|
|
||||||
} else if (this.settings[0].sample.type === 'measurement') {
|
|
||||||
return this.sampleMeasurement(this.settings[0].sample.measurement)
|
|
||||||
} else if (this.settings[0].sample.type === 'models') {
|
|
||||||
return this.sampleModels(this.settings[0].sample.models, this.settings[0].sample.focus || false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -270,13 +264,7 @@ Pattern.prototype.sample = function () {
|
||||||
* @return {object} this - The Pattern instance
|
* @return {object} this - The Pattern instance
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.sampleMeasurement = function (measurementName) {
|
Pattern.prototype.sampleMeasurement = function (measurementName) {
|
||||||
this.store.log.debug(`Sampling measurement \`${measurementName}\``)
|
return new PatternSampler(this).sampleMeasurement(measurementName)
|
||||||
this.__runHooks('preSample')
|
|
||||||
this.__applySettings(this.__measurementSets(measurementName))
|
|
||||||
this.__init()
|
|
||||||
this.__runHooks('postSample')
|
|
||||||
|
|
||||||
return this.draft()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -285,13 +273,7 @@ Pattern.prototype.sampleMeasurement = function (measurementName) {
|
||||||
* @return {object} this - The Pattern instance
|
* @return {object} this - The Pattern instance
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.sampleModels = function (models, focus = false) {
|
Pattern.prototype.sampleModels = function (models, focus = false) {
|
||||||
this.store.log.debug(`Sampling models \`${Object.keys(models).join(', ')}\``)
|
return new PatternSampler(this).sampleModels(models, focus)
|
||||||
this.__runHooks('preSample')
|
|
||||||
this.__applySettings(this.__modelSets(models, focus))
|
|
||||||
this.__init()
|
|
||||||
this.__runHooks('postSample')
|
|
||||||
|
|
||||||
return this.draft()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -300,13 +282,7 @@ Pattern.prototype.sampleModels = function (models, focus = false) {
|
||||||
* @return {object} this - The Pattern instance
|
* @return {object} this - The Pattern instance
|
||||||
*/
|
*/
|
||||||
Pattern.prototype.sampleOption = function (optionName) {
|
Pattern.prototype.sampleOption = function (optionName) {
|
||||||
this.store.log.debug(`Sampling option \`${optionName}\``)
|
return new PatternSampler(this).sampleOption(optionName)
|
||||||
this.__runHooks('preSample')
|
|
||||||
this.__applySettings(this.__optionSets(optionName))
|
|
||||||
this.__init()
|
|
||||||
this.__runHooks('postSample')
|
|
||||||
|
|
||||||
return this.draft()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -527,36 +503,6 @@ Pattern.prototype.__isStackHidden = function (stackName) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an array of settings.options objects for sampling a list or boolean option
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {string} optionName - Name of the option to sample
|
|
||||||
* @return {Array} sets - The list of settings objects
|
|
||||||
*/
|
|
||||||
Pattern.prototype.__listBoolOptionSets = function (optionName) {
|
|
||||||
let option = this.config.options[optionName]
|
|
||||||
const base = this.__setBase()
|
|
||||||
const sets = []
|
|
||||||
let run = 1
|
|
||||||
if (typeof option.bool !== 'undefined') option = { list: [false, true] }
|
|
||||||
for (const choice of option.list) {
|
|
||||||
const settings = {
|
|
||||||
...base,
|
|
||||||
options: {
|
|
||||||
...base.options,
|
|
||||||
},
|
|
||||||
idPrefix: `sample-${run}`,
|
|
||||||
partClasses: `sample-${run}`,
|
|
||||||
}
|
|
||||||
settings.options[optionName] = choice
|
|
||||||
sets.push(settings)
|
|
||||||
run++
|
|
||||||
}
|
|
||||||
|
|
||||||
return sets
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an array of settings.absoluteOptions objects for sampling a list option
|
* Generates an array of settings.absoluteOptions objects for sampling a list option
|
||||||
*
|
*
|
||||||
|
@ -729,75 +675,6 @@ Pattern.prototype.__macro = function (key, method) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an array of settings objects for sampling a measurement
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {string} measurementName - The name of the measurement to sample
|
|
||||||
* @return {Array} sets - The list of settings objects
|
|
||||||
*/
|
|
||||||
Pattern.prototype.__measurementSets = function (measurementName) {
|
|
||||||
let val = this.settings[0].measurements[measurementName]
|
|
||||||
if (val === undefined)
|
|
||||||
this.store.log.error(
|
|
||||||
`Cannot sample measurement \`${measurementName}\` because it's \`undefined\``
|
|
||||||
)
|
|
||||||
let step = val / 50
|
|
||||||
val = val * 0.9
|
|
||||||
const sets = []
|
|
||||||
const base = this.__setBase()
|
|
||||||
for (let run = 1; run < 11; run++) {
|
|
||||||
const settings = {
|
|
||||||
...base,
|
|
||||||
measurements: {
|
|
||||||
...base.measurements,
|
|
||||||
},
|
|
||||||
idPrefix: `sample-${run}`,
|
|
||||||
partClasses: `sample-${run}`,
|
|
||||||
}
|
|
||||||
settings.measurements[measurementName] = val
|
|
||||||
sets.push(settings)
|
|
||||||
val += step
|
|
||||||
}
|
|
||||||
|
|
||||||
return sets
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an array of settings objects for sampling a list of models
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {object} models - The models to sample
|
|
||||||
* @param {string} focus - The ID of the model that should be highlighted
|
|
||||||
* @return {Array} sets - The list of settings objects
|
|
||||||
*/
|
|
||||||
Pattern.prototype.__modelSets = function (models, focus = false) {
|
|
||||||
const sets = []
|
|
||||||
const base = this.__setBase()
|
|
||||||
let run = 1
|
|
||||||
// If there's a focus, do it first so it's at the bottom of the SVG
|
|
||||||
if (focus) {
|
|
||||||
sets.push({
|
|
||||||
...base,
|
|
||||||
measurements: models[focus],
|
|
||||||
idPrefix: `sample-${run}`,
|
|
||||||
partClasses: `sample-${run} sample-focus`,
|
|
||||||
})
|
|
||||||
run++
|
|
||||||
delete models[focus]
|
|
||||||
}
|
|
||||||
for (const measurements of Object.values(models)) {
|
|
||||||
sets.push({
|
|
||||||
...base,
|
|
||||||
measurements,
|
|
||||||
idPrefix: `sample-${run}`,
|
|
||||||
partClasses: `sample-${run}`,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return sets
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether a part is needed, depending on the 'only' setting and the configured dependencies
|
* Determines whether a part is needed, depending on the 'only' setting and the configured dependencies
|
||||||
*
|
*
|
||||||
|
@ -830,58 +707,6 @@ Pattern.prototype.__needs = function (partName, set = 0) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates an array of settings objects for sampling an option
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {string} optionName - The name of the option to sample
|
|
||||||
* @return {Array} sets - The list of settings objects
|
|
||||||
*/
|
|
||||||
Pattern.prototype.__optionSets = function (optionName) {
|
|
||||||
const sets = []
|
|
||||||
if (!(optionName in this.config.options)) return sets
|
|
||||||
let option = this.config.options[optionName]
|
|
||||||
if (typeof option.list === 'object' || typeof option.bool !== 'undefined')
|
|
||||||
return this.__listBoolOptionSets(optionName)
|
|
||||||
let factor = 1
|
|
||||||
let step, val
|
|
||||||
let numberRuns = 10
|
|
||||||
let stepFactor = numberRuns - 1
|
|
||||||
if (typeof option.min === 'undefined' || typeof option.max === 'undefined') {
|
|
||||||
const min = option * 0.9
|
|
||||||
const max = option * 1.1
|
|
||||||
option = { min, max }
|
|
||||||
}
|
|
||||||
if (typeof option.pct !== 'undefined') factor = 100
|
|
||||||
val = option.min / factor
|
|
||||||
if (typeof option.count !== 'undefined' || typeof option.mm !== 'undefined') {
|
|
||||||
const numberOfCounts = option.max - option.min + 1
|
|
||||||
if (numberOfCounts < 10) {
|
|
||||||
numberRuns = numberOfCounts
|
|
||||||
stepFactor = Math.max(numberRuns - 1, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
step = (option.max / factor - val) / stepFactor
|
|
||||||
const base = this.__setBase()
|
|
||||||
for (let run = 1; run <= numberRuns; run++) {
|
|
||||||
const settings = {
|
|
||||||
...base,
|
|
||||||
options: {
|
|
||||||
...base.options,
|
|
||||||
},
|
|
||||||
idPrefix: `sample-${run}`,
|
|
||||||
partClasses: `sample-${run}`,
|
|
||||||
}
|
|
||||||
settings.options[optionName] = val
|
|
||||||
sets.push(settings)
|
|
||||||
val += step
|
|
||||||
if (typeof option.count !== 'undefined' || typeof option.mm !== 'undefined')
|
|
||||||
val = Math.round(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
return sets
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packs stacks in a 2D space and sets pattern size
|
* Packs stacks in a 2D space and sets pattern size
|
||||||
*
|
*
|
||||||
|
@ -999,20 +824,6 @@ Pattern.prototype.__runHooks = function (hookName, data = false) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the base/defaults to generate a set of settings
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @return {object} settings - The settings object
|
|
||||||
*/
|
|
||||||
Pattern.prototype.__setBase = function () {
|
|
||||||
return {
|
|
||||||
...this.settings[0],
|
|
||||||
measurements: { ...(this.settings[0].measurements || {}) },
|
|
||||||
options: { ...(this.settings[0].options || {}) },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the absolute value of a snapped percentage option
|
* Returns the absolute value of a snapped percentage option
|
||||||
*
|
*
|
||||||
|
|
0
packages/core/src/pattern/pattern-draft-handler.mjs
Normal file
0
packages/core/src/pattern/pattern-draft-handler.mjs
Normal file
226
packages/core/src/pattern/pattern-sampler.mjs
Normal file
226
packages/core/src/pattern/pattern-sampler.mjs
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
export function PatternSampler(pattern) {
|
||||||
|
this.pattern = pattern
|
||||||
|
}
|
||||||
|
|
||||||
|
PatternSampler.prototype.sample = function () {
|
||||||
|
this.pattern.__init()
|
||||||
|
const sampleSetting = this.pattern.settings[0].sample
|
||||||
|
if (sampleSetting.type === 'option') {
|
||||||
|
return this.sampleOption(sampleSetting.option)
|
||||||
|
} else if (sampleSetting.type === 'measurement') {
|
||||||
|
return this.sampleMeasurement(sampleSetting.measurement)
|
||||||
|
} else if (sampleSetting.type === 'models') {
|
||||||
|
return this.sampleModels(sampleSetting.models, sampleSetting.focus || false)
|
||||||
|
}
|
||||||
|
return this.pattern
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles measurement sampling
|
||||||
|
*
|
||||||
|
* @return {object} this - The Pattern instance
|
||||||
|
*/
|
||||||
|
PatternSampler.prototype.sampleMeasurement = function (measurementName) {
|
||||||
|
this.pattern.store.log.debug(`Sampling measurement \`${measurementName}\``)
|
||||||
|
this.pattern.__runHooks('preSample')
|
||||||
|
this.pattern.__applySettings(this.__measurementSets(measurementName))
|
||||||
|
this.pattern.__init()
|
||||||
|
this.pattern.__runHooks('postSample')
|
||||||
|
|
||||||
|
return this.pattern.draft()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles models sampling
|
||||||
|
*
|
||||||
|
* @return {object} this - The Pattern instance
|
||||||
|
*/
|
||||||
|
PatternSampler.prototype.sampleModels = function (models, focus = false) {
|
||||||
|
this.pattern.store.log.debug(`Sampling models \`${Object.keys(models).join(', ')}\``)
|
||||||
|
this.pattern.__runHooks('preSample')
|
||||||
|
this.pattern.__applySettings(this.__modelSets(models, focus))
|
||||||
|
this.pattern.__init()
|
||||||
|
this.pattern.__runHooks('postSample')
|
||||||
|
|
||||||
|
return this.pattern.draft()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles option sampling
|
||||||
|
*
|
||||||
|
* @return {object} this - The Pattern instance
|
||||||
|
*/
|
||||||
|
PatternSampler.prototype.sampleOption = function (optionName) {
|
||||||
|
this.pattern.store.log.debug(`Sampling option \`${optionName}\``)
|
||||||
|
this.pattern.__runHooks('preSample')
|
||||||
|
this.pattern.__applySettings(this.__optionSets(optionName))
|
||||||
|
this.pattern.__init()
|
||||||
|
this.pattern.__runHooks('postSample')
|
||||||
|
|
||||||
|
return this.pattern.draft()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base/defaults to generate a set of settings
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @return {object} settings - The settings object
|
||||||
|
*/
|
||||||
|
PatternSampler.prototype.__setBase = function () {
|
||||||
|
return {
|
||||||
|
measurements: {},
|
||||||
|
options: {},
|
||||||
|
...this.pattern.settings[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an array of settings.options objects for sampling a list or boolean option
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} optionName - Name of the option to sample
|
||||||
|
* @return {Array} sets - The list of settings objects
|
||||||
|
*/
|
||||||
|
PatternSampler.prototype.__listBoolOptionSets = function (optionName) {
|
||||||
|
let option = this.pattern.config.options[optionName]
|
||||||
|
const base = this.__setBase()
|
||||||
|
const sets = []
|
||||||
|
let run = 1
|
||||||
|
if (typeof option.bool !== 'undefined') option = { list: [false, true] }
|
||||||
|
for (const choice of option.list) {
|
||||||
|
const settings = {
|
||||||
|
...base,
|
||||||
|
options: {
|
||||||
|
...base.options,
|
||||||
|
},
|
||||||
|
idPrefix: `sample-${run}`,
|
||||||
|
partClasses: `sample-${run}`,
|
||||||
|
}
|
||||||
|
settings.options[optionName] = choice
|
||||||
|
sets.push(settings)
|
||||||
|
run++
|
||||||
|
}
|
||||||
|
|
||||||
|
return sets
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an array of settings objects for sampling a measurement
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} measurementName - The name of the measurement to sample
|
||||||
|
* @return {Array} sets - The list of settings objects
|
||||||
|
*/
|
||||||
|
PatternSampler.prototype.__measurementSets = function (measurementName) {
|
||||||
|
let val = this.pattern.settings[0].measurements[measurementName]
|
||||||
|
if (val === undefined)
|
||||||
|
this.pattern.store.log.error(
|
||||||
|
`Cannot sample measurement \`${measurementName}\` because it's \`undefined\``
|
||||||
|
)
|
||||||
|
let step = val / 50
|
||||||
|
val = val * 0.9
|
||||||
|
const sets = []
|
||||||
|
const base = this.__setBase()
|
||||||
|
for (let run = 1; run < 11; run++) {
|
||||||
|
const settings = {
|
||||||
|
...base,
|
||||||
|
measurements: {
|
||||||
|
...base.measurements,
|
||||||
|
},
|
||||||
|
idPrefix: `sample-${run}`,
|
||||||
|
partClasses: `sample-${run}`,
|
||||||
|
}
|
||||||
|
settings.measurements[measurementName] = val
|
||||||
|
sets.push(settings)
|
||||||
|
val += step
|
||||||
|
}
|
||||||
|
|
||||||
|
return sets
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an array of settings objects for sampling a list of models
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {object} models - The models to sample
|
||||||
|
* @param {string} focus - The ID of the model that should be highlighted
|
||||||
|
* @return {Array} sets - The list of settings objects
|
||||||
|
*/
|
||||||
|
PatternSampler.prototype.__modelSets = function (models, focus = false) {
|
||||||
|
const sets = []
|
||||||
|
const base = this.__setBase()
|
||||||
|
let run = 1
|
||||||
|
// If there's a focus, do it first so it's at the bottom of the SVG
|
||||||
|
if (focus) {
|
||||||
|
sets.push({
|
||||||
|
...base,
|
||||||
|
measurements: models[focus],
|
||||||
|
idPrefix: `sample-${run}`,
|
||||||
|
partClasses: `sample-${run} sample-focus`,
|
||||||
|
})
|
||||||
|
run++
|
||||||
|
delete models[focus]
|
||||||
|
}
|
||||||
|
for (const measurements of Object.values(models)) {
|
||||||
|
sets.push({
|
||||||
|
...base,
|
||||||
|
measurements,
|
||||||
|
idPrefix: `sample-${run}`,
|
||||||
|
partClasses: `sample-${run}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return sets
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates an array of settings objects for sampling an option
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} optionName - The name of the option to sample
|
||||||
|
* @return {Array} sets - The list of settings objects
|
||||||
|
*/
|
||||||
|
PatternSampler.prototype.__optionSets = function (optionName) {
|
||||||
|
const sets = []
|
||||||
|
if (!(optionName in this.pattern.config.options)) return sets
|
||||||
|
let option = this.pattern.config.options[optionName]
|
||||||
|
if (typeof option.list === 'object' || typeof option.bool !== 'undefined')
|
||||||
|
return this.__listBoolOptionSets(optionName)
|
||||||
|
let factor = 1
|
||||||
|
let step, val
|
||||||
|
let numberRuns = 10
|
||||||
|
let stepFactor = numberRuns - 1
|
||||||
|
if (typeof option.min === 'undefined' || typeof option.max === 'undefined') {
|
||||||
|
const min = option * 0.9
|
||||||
|
const max = option * 1.1
|
||||||
|
option = { min, max }
|
||||||
|
}
|
||||||
|
if (typeof option.pct !== 'undefined') factor = 100
|
||||||
|
val = option.min / factor
|
||||||
|
if (typeof option.count !== 'undefined' || typeof option.mm !== 'undefined') {
|
||||||
|
const numberOfCounts = option.max - option.min + 1
|
||||||
|
if (numberOfCounts < 10) {
|
||||||
|
numberRuns = numberOfCounts
|
||||||
|
stepFactor = Math.max(numberRuns - 1, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
step = (option.max / factor - val) / stepFactor
|
||||||
|
const base = this.__setBase()
|
||||||
|
for (let run = 1; run <= numberRuns; run++) {
|
||||||
|
const settings = {
|
||||||
|
...base,
|
||||||
|
options: {
|
||||||
|
...base.options,
|
||||||
|
},
|
||||||
|
idPrefix: `sample-${run}`,
|
||||||
|
partClasses: `sample-${run}`,
|
||||||
|
}
|
||||||
|
settings.options[optionName] = val
|
||||||
|
sets.push(settings)
|
||||||
|
val += step
|
||||||
|
if (typeof option.count !== 'undefined' || typeof option.mm !== 'undefined')
|
||||||
|
val = Math.round(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sets
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue