From 7085705aa1a2a4ea48578adbef3adb6cd681edd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20K=C3=B6n=C3=B6nen?= Date: Sun, 10 May 2020 11:10:14 +0300 Subject: [PATCH 1/3] Changed the stretched clothing recommendation engine * pant waist and hips measurements allow more stretch * based on Perfuro tests --- index1c.html | 870 +++++++++++++++++++++++++++++++++++++++ src/api/ProductModel.js | 14 + src/api/sizeme-api.js | 7 +- src/common/SizingBar.jsx | 7 +- webpack.config.js | 1 + 5 files changed, 893 insertions(+), 6 deletions(-) create mode 100644 index1c.html diff --git a/index1c.html b/index1c.html new file mode 100644 index 0000000..7e0c665 --- /dev/null +++ b/index1c.html @@ -0,0 +1,870 @@ + + + + SHORTS (PRODUCT-DB) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ +
+
+ +
+

Default welcome msg!

+ +
+ + +
+
+
+
+
+
+ +
+ +
+
+
+
+ +
+ + +
+ +
+
+

SKIN-TIGHT BIKE SHORTS (PRODUCT-DB)

+
+ + + +

Be + the first to review this product

+ +

Availability: In stock

+ + +
+ + €10.00 + +
+ + +
+

Quick Overview

+
Shorts with Product DB
+
+ + +
+ +
+
+
+
+ +
+
+
+ + + + + +

* Required Fields

+
+ +
+ + +
+ + €10.00 + +
+ +
+ + + +
+ + + +
+ +
+ +
+

+ T-SHIRT (PRODUCT-DB)

+

Double click on above image to view full + picture

+
+ Zoom Out +
+
+
+ Zoom In +
+ +
+

More Views

+
    +
  • + +
  • +
+
+
+ +
+
+ +
+ +
+
+

Details

+
+ Just simple shorts with measurements from the SizeMe Product Database +
+
+
+

Product Tags

+
+
+ +
+ +
+ +
+
+

Use spaces to separate tags. Use single quotes (') for phrases.

+ +
+
+
+ + + + + +
+ +
+
+ + + +
+
+ + + + + + + \ No newline at end of file diff --git a/src/api/ProductModel.js b/src/api/ProductModel.js index 2ff5127..ed32136 100644 --- a/src/api/ProductModel.js +++ b/src/api/ProductModel.js @@ -1227,6 +1227,19 @@ const getResult = (measurement, value, matchItem) => { }; }; +const stretchFactor = (measurement) => { + let factor = 1; + switch (measurement) { + case "pant_waist": + factor = 5; + break; + case "hips": + factor = 2; + break; + } + return factor; +}; + const DEFAULT_OPTIMAL_FIT = 1070; const DEFAULT_OPTIMAL_STRETCH = 5; @@ -1234,6 +1247,7 @@ export { humanMeasurementMap, fitRanges, getResult, + stretchFactor, DEFAULT_OPTIMAL_FIT, DEFAULT_OPTIMAL_STRETCH, }; diff --git a/src/api/sizeme-api.js b/src/api/sizeme-api.js index aaf3a97..9df6969 100644 --- a/src/api/sizeme-api.js +++ b/src/api/sizeme-api.js @@ -7,7 +7,7 @@ import { createStore, applyMiddleware } from "redux"; import thunkMiddleware from "redux-thunk"; import { createLogger } from "redux-logger"; import rootReducer from "./reducers"; -import SizeGuideModel, { DEFAULT_OPTIMAL_FIT, DEFAULT_OPTIMAL_STRETCH, humanMeasurementMap } from "./ProductModel"; +import SizeGuideModel, { DEFAULT_OPTIMAL_FIT, DEFAULT_OPTIMAL_STRETCH, humanMeasurementMap, stretchFactor } from "./ProductModel"; import Optional from "optional-js"; import SizeSelector from "./SizeSelector"; import uiOptions from "./uiOptions"; @@ -372,8 +372,9 @@ function getRecommendedFit (fitResults, optimalFit) { const [bestMatch] = fitResults .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) .reduce(([accSize, fit], [size, res]) => { - let matchArr = Object.values(res.matchMap); - let maxStretch = Math.max.apply(null, matchArr.map(o => o.componentStretch)); + let maxStretchArr = []; + Object.entries(res.matchMap).forEach(([oKey, oValue]) => { maxStretchArr.push( oValue.componentStretch / stretchFactor(oKey) );}); + let maxStretch = Math.max.apply(null, maxStretchArr); const newFit = (Math.abs(res.totalFit - optFit) * 100) + Math.abs(maxStretch - optStretch); if (newFit <= (maxDist * 100) && (!accSize || newFit < fit)) { return [size, newFit]; diff --git a/src/common/SizingBar.jsx b/src/common/SizingBar.jsx index 9d8a948..f6a50e4 100644 --- a/src/common/SizingBar.jsx +++ b/src/common/SizingBar.jsx @@ -3,7 +3,7 @@ import PropTypes from "prop-types"; import { connect } from "react-redux"; import { withTranslation } from "react-i18next"; import "./SizingBar.scss"; -import ProductModel, { DEFAULT_OPTIMAL_FIT, DEFAULT_OPTIMAL_STRETCH, fitRanges } from "../api/ProductModel"; +import ProductModel, { DEFAULT_OPTIMAL_FIT, DEFAULT_OPTIMAL_STRETCH, fitRanges, stretchFactor } from "../api/ProductModel"; import ReactTooltip from "react-tooltip"; import SizeSelector from "../api/SizeSelector"; @@ -127,8 +127,9 @@ class SizingBar extends React.Component { let maxStretch = DEFAULT_OPTIMAL_STRETCH; let newPos = 50; if (matchMap) { - let matchArr = Object.values(matchMap); - maxStretch = Math.max.apply(null, matchArr.map(o => o.componentStretch)); + let maxStretchArr = []; + Object.entries(matchMap).forEach(([oKey, oValue]) => { maxStretchArr.push( oValue.componentStretch / stretchFactor(oKey) );}); + maxStretch = Math.max.apply(null, maxStretchArr); if (value > 1000) { newPos = Math.min(100, 60 + ((value - 1000) / 55 * 40)); } else if (value === 1000) { diff --git a/webpack.config.js b/webpack.config.js index 5fa83f4..2b0038b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -72,6 +72,7 @@ const developmentConfig = () => merge([ parts.page({ template: "local.html", filename: "local.html" }), parts.page({ template: "index1.html", filename: "index1.html" }), parts.page({ template: "index1b.html", filename: "index1b.html" }), + parts.page({ template: "index1c.html", filename: "index1c.html" }), parts.page({ template: "index2.html", filename: "index2.html" }), parts.page({ template: "index2r.html", filename: "index2r.html" }), parts.page({ template: "index2kk.html", filename: "index2kk.html" }), From 50c73f628e5c7683c00377f532c12e36e70e48fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20K=C3=B6n=C3=B6nen?= Date: Mon, 11 May 2020 13:30:21 +0300 Subject: [PATCH 2/3] Adjusted factors by Perfuros request * sizing bar is not perfect when stretching stops (totalFit < 1000) * but there is a pant waist workaround that causes some issues with this --- src/api/ProductModel.js | 4 ++-- src/api/sizeme-api.js | 2 +- src/common/SizingBar.jsx | 13 ++++++++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/api/ProductModel.js b/src/api/ProductModel.js index ed32136..60bba58 100644 --- a/src/api/ProductModel.js +++ b/src/api/ProductModel.js @@ -1231,10 +1231,10 @@ const stretchFactor = (measurement) => { let factor = 1; switch (measurement) { case "pant_waist": - factor = 5; + factor = 10; break; case "hips": - factor = 2; + factor = 8; break; } return factor; diff --git a/src/api/sizeme-api.js b/src/api/sizeme-api.js index 9df6969..3be19a3 100644 --- a/src/api/sizeme-api.js +++ b/src/api/sizeme-api.js @@ -370,7 +370,7 @@ function getRecommendedFit (fitResults, optimalFit) { if (optFit === 1000) { const optStretch = DEFAULT_OPTIMAL_STRETCH; const [bestMatch] = fitResults - .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) + .filter(([, res]) => res.accuracy > 0) .reduce(([accSize, fit], [size, res]) => { let maxStretchArr = []; Object.entries(res.matchMap).forEach(([oKey, oValue]) => { maxStretchArr.push( oValue.componentStretch / stretchFactor(oKey) );}); diff --git a/src/common/SizingBar.jsx b/src/common/SizingBar.jsx index f6a50e4..35fee7c 100644 --- a/src/common/SizingBar.jsx +++ b/src/common/SizingBar.jsx @@ -125,17 +125,24 @@ class SizingBar extends React.Component { let { fitRecommendation } = this.props; if (fitRecommendation === 1000) { let maxStretch = DEFAULT_OPTIMAL_STRETCH; + let minStretchFactor = 1; let newPos = 50; if (matchMap) { let maxStretchArr = []; - Object.entries(matchMap).forEach(([oKey, oValue]) => { maxStretchArr.push( oValue.componentStretch / stretchFactor(oKey) );}); + let minStretchFactorArr = []; + Object.entries(matchMap).forEach(([oKey, oValue]) => { + maxStretchArr.push( oValue.componentStretch / stretchFactor(oKey) ); + minStretchFactorArr.push( stretchFactor(oKey) ); + }); maxStretch = Math.max.apply(null, maxStretchArr); + minStretchFactor = Math.min.apply(null, minStretchFactorArr); if (value > 1000) { newPos = Math.min(100, 60 + ((value - 1000) / 55 * 40)); - } else if (value === 1000) { + } else if ((value <= 1000) && (value > 990)) { const stretchBreakpoint = 2 * DEFAULT_OPTIMAL_STRETCH; newPos = (maxStretch > stretchBreakpoint) ? Math.max(20, 40 - ((maxStretch - stretchBreakpoint) / (100 - stretchBreakpoint) * 20)) : Math.max(40, 60 - (maxStretch / stretchBreakpoint * 20)); - } else if (value < 1000) { + if (minStretchFactor > 1) newPos = Math.max(0, Math.min(100, ((newPos - 50) * minStretchFactor) + 50)); + } else { newPos = Math.max(0, 20 - ((1000 - value) / 55 * 20)); } } From 53110a34cd7d4f66ed5362946bdcdb4652862f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20K=C3=B6n=C3=B6nen?= Date: Tue, 12 May 2020 09:27:16 +0300 Subject: [PATCH 3/3] Quick code clean up --- src/common/SizingBar.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/SizingBar.jsx b/src/common/SizingBar.jsx index 35fee7c..f1679e8 100644 --- a/src/common/SizingBar.jsx +++ b/src/common/SizingBar.jsx @@ -128,8 +128,8 @@ class SizingBar extends React.Component { let minStretchFactor = 1; let newPos = 50; if (matchMap) { - let maxStretchArr = []; - let minStretchFactorArr = []; + const maxStretchArr = []; + const minStretchFactorArr = []; Object.entries(matchMap).forEach(([oKey, oValue]) => { maxStretchArr.push( oValue.componentStretch / stretchFactor(oKey) ); minStretchFactorArr.push( stretchFactor(oKey) );