1
0
Fork 0

chore(models): Ported to v3

This commit is contained in:
Joost De Cock 2022-08-28 19:51:15 +02:00
parent 1bcdce2223
commit 1de3e428c1
16 changed files with 282 additions and 359 deletions

View file

@ -25,6 +25,8 @@ i18n:
prebuild: 'node scripts/prebuilder.mjs'
test: *test
testci: *testci
models:
test: "npx mocha tests/*.test.mjs"
new-design:
build: "SITE=new-design/shared node ../../sites/shared/prebuild/i18n-only.mjs && cp ../../scripts/banner.mjs ./lib && node --experimental-json-modules build.mjs"
mbuild: '!'

View file

@ -60,25 +60,6 @@ import { manSize38 } from @freesewing/models
```
which will give you an object with `measurement: value` pairs.
The example above gives you:
```js
{
bicepsCircumference: 305,
centerBackNeckToWaist: 495,
chestCircumference: 965,
headCircumference: 580,
hipsCircumference: 838,
hipsToUpperLeg: 202,
naturalWaistToHip: 110,
neckCircumference: 391,
shoulderSlope: 49,
shoulderToShoulder: 444,
shoulderToWrist: 680,
upperLegCircumference: 598,
wristCircumference: 185
}
```
## Units
@ -86,12 +67,34 @@ All measurements are in mm.
## Available models
- manSize34
- manSize36
- manSize38
- manSize40
- manSize42
- manSize44
We have menswear and womenswear models, but all of them have all measurements.
The digits in the model refer to the neck circumference in cm.
- womenswear28
- womenswear30
- womenswear32
- womenswear34
- womenswear36
- womenswear38
- womenswear40
- womenswear42
- womenswear44
- womenswear46
- menswear32
- menswear34
- menswear36
- menswear38
- menswear40
- menswear42
- menswear44
- menswear46
- menswear48
- menswear50
## Other named exports
- measurements: A list/array of measurement names
- sizes: An object with `menswear` and `womenswear` keys that hold a list/array of sizes we provide

View file

@ -14,7 +14,7 @@ const banner = `/**
const options = {
banner: { js: banner },
bundle: true,
entryPoints: ['src/index.js'],
entryPoints: ['src/index.mjs'],
format: 'esm',
outfile: 'dist/index.mjs',
external: ["@freesewing"],

View file

@ -8,25 +8,6 @@ import { manSize38 } from @freesewing/models
```
which will give you an object with `measurement: value` pairs.
The example above gives you:
```js
{
bicepsCircumference: 305,
centerBackNeckToWaist: 495,
chestCircumference: 965,
headCircumference: 580,
hipsCircumference: 838,
hipsToUpperLeg: 202,
naturalWaistToHip: 110,
neckCircumference: 391,
shoulderSlope: 49,
shoulderToShoulder: 444,
shoulderToWrist: 680,
upperLegCircumference: 598,
wristCircumference: 185
}
```
## Units
@ -34,10 +15,32 @@ All measurements are in mm.
## Available models
- manSize34
- manSize36
- manSize38
- manSize40
- manSize42
- manSize44
We have menswear and womenswear models, but all of them have all measurements.
The digits in the model refer to the neck circumference in cm.
- womenswear28
- womenswear30
- womenswear32
- womenswear34
- womenswear36
- womenswear38
- womenswear40
- womenswear42
- womenswear44
- womenswear46
- menswear32
- menswear34
- menswear36
- menswear38
- menswear40
- menswear42
- menswear44
- menswear46
- menswear48
- menswear50
## Other named exports
- measurements: A list/array of measurement names
- sizes: An object with `menswear` and `womenswear` keys that hold a list/array of sizes we provide

View file

@ -31,7 +31,7 @@
"clean": "rimraf dist",
"mbuild": "NO_MINIFY=1 node --experimental-json-modules build.mjs",
"symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -",
"test": "echo \"models: No tests configured. Perhaps you'd like to do this?\" && exit 0",
"test": "npx mocha tests/*.test.mjs",
"vbuild": "VERBOSE=1 node --experimental-json-modules build.mjs",
"lab": "cd ../../sites/lab && yarn start",
"tips": "node ../../scripts/help.mjs",

View file

@ -1,22 +0,0 @@
import neckstimate from './neckstimate'
import measurements from './measurements'
import sizes from './sizes'
const withBreasts = {}
const withoutBreasts = {}
for (let s of sizes.womenswear) {
withBreasts['size' + s] = {}
for (let m of measurements.womenswear) {
withBreasts['size' + s][m] = neckstimate(s * 10, m, true)
}
}
for (let s of sizes.menswear) {
withoutBreasts['size' + s] = {}
for (let m of measurements.menswear) {
withoutBreasts['size' + s][m] = neckstimate(s * 10, m, false)
}
}
export { measurements, sizes, withoutBreasts, withBreasts }

View file

@ -0,0 +1,39 @@
import { measurements, neckstimate } from './neckstimate.mjs'
const getMeasurements = (size, breasts) => {
const all = {}
for (const m of measurements) {
all[m] = neckstimate(size * 10, m, breasts)
}
return all
}
export const sizes = {
womenswear: [28,30,32,34,36,38,40,42,44,46],
menswear: [32,34,36,38,40,42,44,46,48,50],
}
export const womenswear28 = getMeasurements(28, true)
export const womenswear30 = getMeasurements(30, true)
export const womenswear32 = getMeasurements(32, true)
export const womenswear34 = getMeasurements(34, true)
export const womenswear36 = getMeasurements(36, true)
export const womenswear38 = getMeasurements(38, true)
export const womenswear40 = getMeasurements(40, true)
export const womenswear42 = getMeasurements(42, true)
export const womenswear44 = getMeasurements(44, true)
export const womenswear46 = getMeasurements(46, true)
export const menswear32 = getMeasurements(32, false)
export const menswear34 = getMeasurements(34, false)
export const menswear36 = getMeasurements(36, false)
export const menswear38 = getMeasurements(38, false)
export const menswear40 = getMeasurements(40, false)
export const menswear42 = getMeasurements(42, false)
export const menswear44 = getMeasurements(44, false)
export const menswear46 = getMeasurements(46, false)
export const menswear48 = getMeasurements(48, false)
export const menswear50 = getMeasurements(50, false)
export { measurements }

View file

@ -1,74 +0,0 @@
export default {
menswear: [
'ankle',
'biceps',
'chest',
'crossSeam',
'crossSeamFront',
'crotchDepth',
'head',
'heel',
'hips',
'hpsToBust',
'hpsToWaistBack',
'inseam',
'knee',
'neck',
'seat',
'seatBack',
'shoulderSlope',
'shoulderToElbow',
'shoulderToShoulder',
'shoulderToWrist',
'upperLeg',
'waist',
'waistBack',
'waistToArmhole',
'waistToFloor',
'waistToHips',
'waistToKnee',
'waistToSeat',
'waistToUpperLeg',
'wrist',
],
womenswear: [
'ankle',
'biceps',
'bustFront',
'bustPointToUnderbust',
'bustSpan',
'chest',
'crossSeam',
'crossSeamFront',
'crotchDepth',
'head',
'heel',
'highBust',
'highBustFront',
'hips',
'hpsToBust',
'hpsToWaistBack',
'hpsToWaistFront',
'inseam',
'knee',
'neck',
'seat',
'seatBack',
'shoulderSlope',
'shoulderToElbow',
'shoulderToShoulder',
'shoulderToWrist',
'underbust',
'upperLeg',
'waist',
'waistBack',
'waistToArmhole',
'waistToFloor',
'waistToHips',
'waistToKnee',
'waistToSeat',
'waistToUnderbust',
'waistToUpperLeg',
'wrist',
],
}

View file

@ -0,0 +1,157 @@
/*
* This completes the list of measurements with the ones
* we can calculate based on what we already have
*/
function complete(m) {
// Added by plugin-bust:
m.bust = m.chest
// Added by plugin-measurements:
m.crossSeamBack = [0,1].map(i => m.crossSeam[i] - m.crossSeamFront[i])
m.seatBackArc = [0,1].map(i => m.seatBack[i] / 2)
m.waistBackArc = [0,1].map(i => m.waistBack[i] / 2)
m.bustBack = [0,1].map(i => m.bust[i] - m.bustFront[i])
m.seatFront = [0,1].map(i => m.seat[i] - m.seatBack[i])
m.seatFrontArc = [0,1].map(i => m.seatFront[i] / 2)
m.waistFront = [0,1].map(i => m.waist[i] - m.waistBack[i])
m.waistFrontArc = [0,1].map(i => m.waistFront[i] / 2)
m.highBustBack = [0,1].map(i => m.highBust[i] - m.highBustFront[i])
return m
}
/*
* These are a set of measurements of an average-sized [woman, man].
* We simply extrapolate for other sizes (based on neck)
* by keeping the same proportions.
* That is almost certainly not the best sizing table you can get,
* but we are not in the business of standard sizes, so this will do.
*/
const base = complete({
ankle: [245, 235],
biceps: [270, 350],
bustFront: [480, 560], // FIXME: Estimate
bustPointToUnderbust: [100, 60], // FIXME: Estimate
bustSpan: [160, 190], // FIXME: Estimate
chest: [925, 1000],
crossSeam: [740, 870],
crossSeamFront: [370, 410],
crotchDepth: [270, 340],
heel: [315, 360],
head: [565, 590],
highBust: [865, 1030],
highBustFront: [440, 570], // FIXME: Estimate
hips: [900, 840],
hpsToBust: [275, 280],
hpsToWaistBack: [395, 470],
hpsToWaistFront: [400, 460], // FIXME: Estimate
inseam: [765, 780],
knee: [380, 410],
neck: [340, 380],
seat: [1010, 1020],
seatBack: [520, 560],
shoulderSlope: [13, 13],
shoulderToElbow: [340, 360],
shoulderToShoulder: [415, 450],
shoulderToWrist: [590, 630],
underbust: [780, 980], // FIXME: Estimate
upperLeg: [570, 625],
waist: [750, 810],
waistBack: [380, 410],
waistToArmhole: [170, 210],
waistToFloor: [1050, 1160],
waistToHips: [125, 130],
waistToKnee: [600, 640],
waistToSeat: [250, 270],
waistToUnderbust: [80, ],
waistToUpperLeg: [285, 340],
wrist: [165, 175],
})
/*
* Since linear measurements don't scale the same as circumference
* measurements, we apply a correction ratio.
*/
let a = 0.5 // arc
let c = 1 // circumference
let v = 0.65 // vertical
const ratio = {
// Arc measurements
bustFront: a,
bustPointToUnderbust: a,
bustSpan: a,
highBustFront: a,
// Circumference measurements
ankle: c,
biceps: c,
chest: c,
highBust: c,
hips: c,
neck: c,
underbust: c,
// Vertical measurements
crotchDepth: v,
hpsToBust: v,
hpsToWaistBack: v,
hpsToWaistFront: v,
waistToHips: v,
waistToKnee: v,
waistToSeat: v,
waistToUnderbust: v,
waistToUpperLeg: v,
// Other
seatBack: 0.6,
waistBack: 0.85,
crossSeam: 0.6,
crossSeamFront: 0.3,
head: 0.35,
heel: 0.25,
inseam: 0.25,
knee: 0.65,
seat: 0.6,
shoulderToElbow: 0.5,
shoulderToShoulder: 0.65,
shoulderToWrist: 0.3,
upperLeg: 0.45,
waist: 0.85,
waistToFloor: 0.4,
wrist: 0.5
}
export const measurements = Object.keys(base)
// This estimates a measurement based on the neck
export const neckstimate = (neck = false, measurement = false, breasts = false, noRound=false) => {
if (typeof base[measurement] === 'undefined') {
console.log(
new Error(`neckstimate() called with an invalid measurement name (${measurement})`)
)
return null
}
if (!measurement) {
// No measurement passed
throw new Error(
'new neckstimate() requires a valid measurement name as second parameter. (received ' +
JSON.stringify(measurement) +
')'
)
}
const i = breasts ? 0 : 1
// Shoulder slope is in degrees. Always return the base.
if (measurement === 'shoulderSlope') base.shoulderSlope[i]
if (!neck) throw new Error('neckstimate() requires a neck measurement in mm as first parameter')
// This is what should happen
const delta = (neck / base.neck[i]) * base[measurement][i] - base[measurement][i]
return noRound
? base[measurement][i] + delta * ratio[measurement]
: Math.round(base[measurement][i] + delta * ratio[measurement])
}

View file

@ -1,19 +0,0 @@
// The completes the list of measurements with the ones
// we can calculate based on what we already have
export default function complete(m) {
// Added by plugin-bust:
m.bust = m.chest
// Added by plugin-measurements:
m.crossSeamBack = m.crossSeam - m.crossSeamFront
m.seatBackArc = m.seatBack / 2
m.waistBackArc = m.waistBack / 2
if (m.bust && m.bustFront) m.bustBack = m.bust - m.bustFront
m.seatFront = m.seat - m.seatBack
m.seatFrontArc = m.seatFront / 2
m.waistFront = m.waist - m.waistBack
m.waistFrontArc = m.waistFront / 2
if (m.hightBust && m.highBustFront) m.highBustBack = m.highBust - m.highBustFront
return m
}

View file

@ -1,45 +0,0 @@
import withBreasts from './with-breasts'
import withoutBreasts from './without-breasts'
import ratio from './ratio'
// This estimates a measurement based on the neck
const neckstimate = (neck = false, measurement = false, breasts = false, noRound=false) => {
let data = breasts ? withBreasts : withoutBreasts
// Shoulder slope is in degrees now. Always return de default.
if (measurement === 'shoulderSlope') return withBreasts.shoulderSlope
if (!neck) throw new Error('neckstimate() requires a neck measurement in mm as first parameter')
if (!measurement) {
// No measurement passed
throw new Error(
'new neckstimate() requires a valid measurement name as second parameter. (received ' +
JSON.stringify(measurement) +
')'
)
}
if (typeof data[measurement] === 'undefined') {
if (typeof withBreasts[measurement] === 'undefined') {
// We used to throw this error, but let's just return null instead so things don't go off the rails
console.log(
new Error(`neckstimate() called with an invalid measurement name (${measurement})`)
)
return null
} else {
console.log(
`WARNING: neckstimate() called for a breasts-only measurement (${measurement}) on a no-breasts person`
)
// Return something anyway, rather than fall over
data = withBreasts
}
}
// This is what should happen
let delta = (neck / data.neck) * data[measurement] - data[measurement]
return noRound
? data[measurement] + delta * ratio[measurement]
: Math.round(data[measurement] + delta * ratio[measurement])
}
export default neckstimate

View file

@ -1,51 +0,0 @@
/*
* Since linear measurements don't scale the same as circumference
* measurements, we apply a correction ratio.
*/
let a = 0.5 // arc
let c = 1 // circumference
let v = 0.65 // vertical
export default {
// Arc measurements
bustFront: a,
bustPointToUnderbust: a,
bustSpan: a,
highBustFront: a,
// Circumference measurements
ankle: c,
biceps: c,
chest: c,
highBust: c,
hips: c,
neck: c,
underbust: c,
// Vertical measurements
crotchDepth: v,
hpsToBust: v,
hpsToWaistBack: v,
hpsToWaistFront: v,
waistToHips: v,
waistToKnee: v,
waistToSeat: v,
waistToUnderbust: v,
waistToUpperLeg: v,
// Other
seatBack: 0.6,
waistBack: 0.85,
crossSeam: 0.6,
crossSeamFront: 0.3,
head: 0.35,
heel: 0.25,
inseam: 0.25,
knee: 0.65,
seat: 0.6,
shoulderToElbow: 0.5,
shoulderToShoulder: 0.65,
shoulderToWrist: 0.3,
upperLeg: 0.45,
waist: 0.85,
waistToFloor: 0.4,
wrist: 0.5
}

View file

@ -1,50 +0,0 @@
import complete from './complete'
/*
* These are a set of measurements of an average-sized woman.
* We simply extrapolate for other sizes (based on neck)
* by keeping the same proportions.
* That is almost certainly not the best sizing table you can get,
* but we are not in the business of standard sizes, so this will do.
*/
export default complete({
ankle: 245,
biceps: 270,
bustFront: 480,
bustPointToUnderbust: 100,
bustSpan: 160,
chest: 925,
crossSeam: 740,
crossSeamFront: 370,
crotchDepth: 270,
heel: 315,
head: 565,
highBust: 865,
highBustFront: 440,
hips: 900,
hpsToBust: 275,
hpsToWaistBack: 395,
hpsToWaistFront: 400,
inseam: 765,
knee: 380,
neck: 340,
seat: 1010,
seatBack: 520,
shoulderSlope: 13,
shoulderToElbow: 340,
shoulderToShoulder: 415,
shoulderToWrist: 590,
underbust: 780,
upperLeg: 570,
waist: 750,
waistBack: 380,
waistToArmhole: 17,
waistToFloor: 1050,
waistToHips: 125,
waistToKnee: 600,
waistToSeat: 250,
waistToUnderbust: 80,
waistToUpperLeg: 285,
wrist: 165
})

View file

@ -1,42 +0,0 @@
import complete from './complete'
/*
* These are a set of measurements of an average-sized man.
* We simply extrapolate for other sizes (based on neck)
* by keeping the same proportions.
* That is almost certainly not the best sizing table you can get,
* but we are not in the business of standard sizes, so this will do.
*/
export default complete({
ankle: 235,
biceps: 350,
chest: 1000,
crossSeam: 870,
crossSeamFront: 410,
crotchDepth: 340,
heel: 360,
head: 590,
highBust: 103,
hips: 840,
hpsToBust: 280,
hpsToWaistBack: 470,
inseam: 780,
knee: 410,
neck: 380,
seat: 1020,
seatBack: 560,
shoulderSlope: 13,
shoulderToElbow: 360,
shoulderToShoulder: 450,
shoulderToWrist: 630,
upperLeg: 625,
waist: 810,
waistBack: 410,
waistToArmhole: 21,
waistToFloor: 1160,
waistToHips: 130,
waistToKnee: 640,
waistToSeat: 270,
waistToUpperLeg: 340,
wrist: 175
})

View file

@ -1,4 +0,0 @@
export default {
menswear: [32, 34, 36, 38, 40, 42, 44, 46, 48, 50],
womenswear: [28, 30, 32, 34, 36, 38, 40, 42, 44, 46],
}

View file

@ -0,0 +1,26 @@
import chai from "chai"
import * as all from "./dist/index.mjs"
const expect = chai.expect
const { measurements, sizes } = all
describe('Measurements', () => {
it("Measurements should be a named export and match the sizes", () => {
for (const m of measurements) {
expect(typeof all.womenswear28[m]).to.equal('number');
}
})
})
for (const type in sizes) {
describe(`Sizes: ${type}`, () => {
for (const size of sizes[type]) {
it(`${type}${size} should have all measurements`, () => {
for (const m of measurements) {
expect(typeof all[`${type}${size}`][m]).to.equal('number');
}
})
}
})
}