UNPKG

brassiere

Version:

Compute bra measurements for various regional standards and length units

298 lines (266 loc) 9.34 kB
(function() { 'use strict'; var Qty = require('js-quantities'); // Code lists var itCupCodes = ['AA','A','B','C','D','E','F','FF','G','GG']; var euCupCodes = ['AA','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R']; var ukCupCodes = ['AA','A','B','C','D','DD','E','F','FF','G','GG','H','HH','J','JJ','K','KK','L','LL','M','MM','N']; var usCupCodes = ['AA','A','B','C','D','DD','DDD','DDDD','H','I','J','K','L','M','N','O','P','Q','R','S','T','U']; var itBandCodes = [0, 'I','II','III','IV','V','VI','VII','VIII','IX','X','XI','XII','XIII','XIIII']; // Object returned by the getSize function var BraSize = function(band, cup, unit) { return { band: band, cup: cup, unit: unit, }; }; // Object used internally to represent a set of measures var Measures = function(underbust, bust) { // Parse a measurement value. // Use metric system if no explicit unit is given var normalize = function(value) { if (typeof(value) === 'number') { return new Qty(String(value) + ' cm'); } else if (typeof(value) === 'string') { return new Qty(value); } }; return { u: normalize(underbust), b: normalize(bust), }; }; // Convert measures to a specific length unit // Example usage: convertMeasures(m, 'cm') var convertMeasures = function(measures, unit) { return { u: measures.u.to(unit), b: measures.b.to(unit), }; }; // Compute bra size with the measures and functions given var evaluateSize = function(measures, unit, computeBand, computeCup, options) { options = options || {}; var m = convertMeasures(measures, unit); var band = computeBand(m, options); var cup = computeCup(m, band, options); return new BraSize(band, cup, unit); }; // Compute band length using a formula common to all standards var evaluateBand = function(u, k, p, q) { return k * Math.floor((u + p) / q); }; // Look up cup name at index computed with given function var evaluateCup = function(cups, getIndex) { var cupIndex = Math.round(getIndex()); cupIndex = validateCupIndex(cupIndex, cups); return cups[cupIndex]; }; // Check if index is in range of cup list given. // Throw error otherwise var validateCupIndex = function(cupIndex, cups) { if (cupIndex < 0) { throw new RangeError('Cup size too small'); } else if (cupIndex > cups.length - 1) { throw new RangeError('Cup size too large'); } return cupIndex; }; // Compute overall bra size for European standard using the // euBand and euCup methods var euSize = function(measures) { var unit = 'cm'; return evaluateSize(measures, unit, euBand, euCup); }; // Compute band length for European standard var euBand = function(m) { return evaluateBand(m.u.scalar, 5, 5/2, 5); }; // Compute cup size for European standard var euCup = function(m) { var getCupIndex = function() { var b = m.b.scalar; var u = m.u.scalar; return Math.ceil((b - u - 11) / 2); }; return evaluateCup(euCupCodes, getCupIndex); }; // Compute overall bra size for French standard var frSize = function(measures) { var unit = 'cm'; return evaluateSize(measures, unit, frBand, euCup); }; // Compute band length for French standard. // Can be derived from European var frBand = function(m) { return euBand(m) + 15; }; // Compute overall bra size for Italian standard var itSize = function(measures) { var unit = 'cm'; return evaluateSize(measures, unit, itBand, itCup); }; // Compute band length for Italian standard var itBand = function(m) { var bandIndex = evaluateBand(m.u.scalar, 1, -57.5, 5); if (bandIndex < 0) { throw new RangeError('Underbust girth too small'); } else if (bandIndex > itBandCodes.length - 1) { throw new RangeError('Underbust girth too large'); } return itBandCodes[bandIndex]; }; // Compute cup size for Italian standard var itCup = function(m) { var getCupIndex = function() { var b = m.b.scalar; var u = m.u.scalar; return Math.ceil((b - u - 12.5) / 2.5); }; return evaluateCup(itCupCodes, getCupIndex); }; // Compute band length for UK and US var imperialBand = function(m) { return evaluateBand(m.u.scalar, -2, 4, -2); }; // Compute cup size for UK and US var imperialCup = function(m, band, cups) { var getCupIndex = function() { var diff = m.b.scalar - band; return diff + 1; }; return evaluateCup(cups, getCupIndex); }; // Compute overall bra size for UK standard var ukSize = function(measures) { var unit = 'in'; return evaluateSize(measures, unit, imperialBand, ukCup); }; // Compute cup size for UK standard var ukCup = function(m, band) { return imperialCup(m, band, ukCupCodes); }; // Compute overallbra size for US standard var usSize = function(measures) { var unit = 'in'; return evaluateSize(measures, unit, imperialBand, usCup); }; // Compute cup size for US standard var usCup = function(m, band) { return imperialCup(m, band, usCupCodes); }; // Compute bra size with algorithm used by bra calculator // on sophisticatedpair.com ("sophisticated" standard) var sophSize = function(measures, options) { var preference = options.preference; if (preference === undefined) { throw new TypeError('Please include a preference ("tight", "moderate", or "loose") in the options'); } var p = parseSophPreference(preference); var unit = 'in'; return evaluateSize(measures, unit, sophBand, sophCup, {preference: p}); }; // Parse preference for "sophisticated" standard var parseSophPreference = function(preference) { if (preference === 'tight') { return 1; } else if (preference === 'moderate') { return 2; } else if (preference === 'loose') { return 3; } else { throw new TypeError('Valid preferences are "tight", "moderate", and "loose".'); } }; // Compute band length for "sophisticated" standard var sophBand = function(m, options) { var u = Math.round(m.u.scalar); var uOdd = u % 2; var d; switch(options.preference) { case 1: if (uOdd) { d = -1; } else { d = 0; } break; case 2: if (uOdd) { d = 1; } else { d = 0; } break; case 3: if (uOdd) { d = 3; } else { d = 2; } break; default: d = 0; } return u + d; }; // Compute band length for "sophisticated" standard var sophCup = function(m, band, options) { var getIndex = function() { var u = Math.round(m.u.scalar); var b = Math.round(m.b.scalar); var uOdd = u % 2; var d; switch(options.preference) { case 1: d = -band; break; case 2: if (uOdd) { d = -u; } else { d = -band; } break; case 3: if (uOdd) { d = -band + 2; } else { d = -band + 1; } break; default: d = 0; } var index = b + d; return index; }; return evaluateCup(ukCupCodes, getIndex); }; // Public method computing bra size for given standard // and measurements // // Example usage: // bra.getSize('eu', '70 cm', '85 cm'); // returns { band: 70, cup: 'B', unit: 'cm' } var getSize = function(standard, underbust, bust, options) { var standards = { 'eu': euSize, 'fr': frSize, 'it': itSize, 'uk': ukSize, 'us': usSize, 'sophisticated': sophSize, }; if (standards[standard] === undefined) { throw new TypeError('Standard "' + standard + '" is not defined'); } var measures = new Measures(underbust, bust); var size = standards[standard](measures, options); return size; }; module.exports = { getSize: getSize, }; })();