From 27ba5d9db652d9636f64299332423874cf6a26ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20K=C3=B6n=C3=B6nen?= Date: Sat, 7 Mar 2020 20:44:35 +0200 Subject: [PATCH 1/3] Add handling for items with a optimal fit of 1000 - skin-tight stuff * addresses issues #143 and #144 --- index1b.html | 862 +++++++++++++++++++++++++++++++++++++++ src/api/ProductModel.js | 4 +- src/api/sizeme-api.js | 19 +- src/common/SizingBar.jsx | 30 +- webpack.config.js | 1 + 5 files changed, 907 insertions(+), 9 deletions(-) create mode 100644 index1b.html diff --git a/index1b.html b/index1b.html new file mode 100644 index 0000000..5fade4c --- /dev/null +++ b/index1b.html @@ -0,0 +1,862 @@ + + + + T-SHIRT (PRODUCT-DB) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+ +
+
+ +
+

Default welcome msg!

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

SKIN-TIGHT BIKE SHIRT (PRODUCT-DB)

+
+ + + +

Be + the first to review this product

+ +

Availability: In stock

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

Quick Overview

+
T-shirt 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 a simple shirt 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 c0d35a5..98dd470 100644 --- a/src/api/ProductModel.js +++ b/src/api/ProductModel.js @@ -1137,12 +1137,14 @@ const getResult = (measurement, value, matchItem) => { }; const DEFAULT_OPTIMAL_FIT = 1070; +const DEFAULT_OPTIMAL_STRETCH = 5; export { humanMeasurementMap, fitRanges, getResult, - DEFAULT_OPTIMAL_FIT + DEFAULT_OPTIMAL_FIT, + DEFAULT_OPTIMAL_STRETCH, }; diff --git a/src/api/sizeme-api.js b/src/api/sizeme-api.js index 58335cc..2ff12e6 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 } from "./ProductModel"; +import SizeGuideModel, { DEFAULT_OPTIMAL_FIT, DEFAULT_OPTIMAL_STRETCH } from "./ProductModel"; import Optional from "optional-js"; import SizeSelector from "./SizeSelector"; import uiOptions from "./uiOptions"; @@ -363,7 +363,7 @@ function doMatch (fitRequest, token, useProfile) { function getRecommendedFit (fitResults, optimalFit) { const optFit = optimalFit ? optimalFit : DEFAULT_OPTIMAL_FIT; const maxDist = uiOptions.maxRecommendationDistance || 9999; - const [bestMatch] = fitResults + let [bestMatch] = fitResults .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) .reduce(([accSize, fit], [size, res]) => { const newFit = Math.abs(res.totalFit - optFit); @@ -373,6 +373,21 @@ function getRecommendedFit (fitResults, optimalFit) { return [accSize, fit]; } }, [null, 0]); + if (optFit == 1000) { + const optStretch = DEFAULT_OPTIMAL_STRETCH; + [bestMatch] = fitResults + .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) + .reduce(([accSize, fit], [size, res]) => { + let matchArr = Object.keys(res.matchMap).map((k) => res.matchMap[k]); + let maxStretch = Math.max.apply(Math, matchArr.map(function(o) { return o.componentStretch; })); + const newFit = (Math.abs(res.totalFit - optFit) * 100) + Math.abs(maxStretch - optStretch); + if (newFit <= (maxDist * 100) && (!accSize || newFit < fit)) { + return [size, newFit]; + } else { + return [accSize, fit]; + } + }, [null, 0]); + } return bestMatch; } diff --git a/src/common/SizingBar.jsx b/src/common/SizingBar.jsx index 57905c9..4ef3463 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, fitRanges } from "../api/ProductModel"; +import ProductModel, { DEFAULT_OPTIMAL_FIT, DEFAULT_OPTIMAL_STRETCH, fitRanges } from "../api/ProductModel"; import ReactTooltip from "react-tooltip"; import SizeSelector from "../api/SizeSelector"; @@ -121,9 +121,27 @@ class SizingBar extends React.Component { } } - getFitPosition (value) { - return Math.max(0, - (Math.min(value, this.sliderPosXMax) - this.sliderPosXMin) * this.sliderScale); + getFitPosition (value,matchMap) { + let { fitRecommendation } = this.props; + let newPos = Math.max(0, (Math.min(value, this.sliderPosXMax) - this.sliderPosXMin) * this.sliderScale); + if (fitRecommendation == 1000) { + let maxStretch = DEFAULT_OPTIMAL_STRETCH; + if (matchMap) { + let matchArr = Object.keys(matchMap).map((k) => matchMap[k]); + maxStretch = Math.max.apply(Math, matchArr.map(function(o) { return o.componentStretch; })); + if (value > 1000) { + newPos = Math.min(100, 60 + ((value - 1000) / 55 * 40)); + } else if (value == 1000) { + 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) { + newPos = Math.max(0, 20 - ((1000 - value) / 55 * 20)); + } + } else { + newPos = 50; + } + } + return newPos; } getFitRange () { @@ -157,9 +175,9 @@ class SizingBar extends React.Component { {t(`sizingBarRangeLabel.${fit.label}`)} ))} - {doShowFit && fitRecommendation > 1000 && = 1000 && } - {doShowFit && } ); diff --git a/webpack.config.js b/webpack.config.js index 44b6a68..eed3e76 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -71,6 +71,7 @@ const developmentConfig = () => merge([ parts.page({ template: "index.html" }), 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: "index2.html", filename: "index2.html" }), parts.page({ template: "index2r.html", filename: "index2r.html" }), parts.page({ template: "index3.html", filename: "index3.html" }), From 65fd540825d1a918286e54c9050a1316a4a68185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20K=C3=B6n=C3=B6nen?= Date: Mon, 9 Mar 2020 01:30:05 +0200 Subject: [PATCH 2/3] Code cleanup --- src/api/sizeme-api.js | 28 +++++++++++++++------------- src/common/SizingBar.jsx | 16 ++++++++-------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/api/sizeme-api.js b/src/api/sizeme-api.js index 2ff12e6..37a0e2e 100644 --- a/src/api/sizeme-api.js +++ b/src/api/sizeme-api.js @@ -363,23 +363,14 @@ function doMatch (fitRequest, token, useProfile) { function getRecommendedFit (fitResults, optimalFit) { const optFit = optimalFit ? optimalFit : DEFAULT_OPTIMAL_FIT; const maxDist = uiOptions.maxRecommendationDistance || 9999; - let [bestMatch] = fitResults - .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) - .reduce(([accSize, fit], [size, res]) => { - const newFit = Math.abs(res.totalFit - optFit); - if (newFit <= maxDist && (!accSize || newFit < fit)) { - return [size, newFit]; - } else { - return [accSize, fit]; - } - }, [null, 0]); - if (optFit == 1000) { + let [bestMatch] = []; + if (optFit === 1000) { const optStretch = DEFAULT_OPTIMAL_STRETCH; [bestMatch] = fitResults .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) .reduce(([accSize, fit], [size, res]) => { - let matchArr = Object.keys(res.matchMap).map((k) => res.matchMap[k]); - let maxStretch = Math.max.apply(Math, matchArr.map(function(o) { return o.componentStretch; })); + let matchArr = Object.values(res.matchMap); + let maxStretch = Math.max.apply(null, matchArr.map(o => o.componentStretch)); const newFit = (Math.abs(res.totalFit - optFit) * 100) + Math.abs(maxStretch - optStretch); if (newFit <= (maxDist * 100) && (!accSize || newFit < fit)) { return [size, newFit]; @@ -387,6 +378,17 @@ function getRecommendedFit (fitResults, optimalFit) { return [accSize, fit]; } }, [null, 0]); + } else { + [bestMatch] = fitResults + .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) + .reduce(([accSize, fit], [size, res]) => { + const newFit = Math.abs(res.totalFit - optFit); + if (newFit <= maxDist && (!accSize || newFit < fit)) { + return [size, newFit]; + } else { + return [accSize, fit]; + } + }, [null, 0]); } return bestMatch; } diff --git a/src/common/SizingBar.jsx b/src/common/SizingBar.jsx index 4ef3463..9d8a948 100644 --- a/src/common/SizingBar.jsx +++ b/src/common/SizingBar.jsx @@ -123,25 +123,25 @@ class SizingBar extends React.Component { getFitPosition (value,matchMap) { let { fitRecommendation } = this.props; - let newPos = Math.max(0, (Math.min(value, this.sliderPosXMax) - this.sliderPosXMin) * this.sliderScale); - if (fitRecommendation == 1000) { + if (fitRecommendation === 1000) { let maxStretch = DEFAULT_OPTIMAL_STRETCH; + let newPos = 50; if (matchMap) { - let matchArr = Object.keys(matchMap).map((k) => matchMap[k]); - maxStretch = Math.max.apply(Math, matchArr.map(function(o) { return o.componentStretch; })); + let matchArr = Object.values(matchMap); + maxStretch = Math.max.apply(null, matchArr.map(o => o.componentStretch)); if (value > 1000) { newPos = Math.min(100, 60 + ((value - 1000) / 55 * 40)); - } else if (value == 1000) { + } else if (value === 1000) { 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) { newPos = Math.max(0, 20 - ((1000 - value) / 55 * 20)); } - } else { - newPos = 50; } + return newPos; + } else { + return Math.max(0, (Math.min(value, this.sliderPosXMax) - this.sliderPosXMin) * this.sliderScale); } - return newPos; } getFitRange () { From 9f55956e0203862aa9fa35d05bbde5d7008d7f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20K=C3=B6n=C3=B6nen?= Date: Mon, 9 Mar 2020 11:01:45 +0200 Subject: [PATCH 3/3] Further cleanup --- src/api/sizeme-api.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/sizeme-api.js b/src/api/sizeme-api.js index 37a0e2e..9da6823 100644 --- a/src/api/sizeme-api.js +++ b/src/api/sizeme-api.js @@ -363,10 +363,9 @@ function doMatch (fitRequest, token, useProfile) { function getRecommendedFit (fitResults, optimalFit) { const optFit = optimalFit ? optimalFit : DEFAULT_OPTIMAL_FIT; const maxDist = uiOptions.maxRecommendationDistance || 9999; - let [bestMatch] = []; if (optFit === 1000) { const optStretch = DEFAULT_OPTIMAL_STRETCH; - [bestMatch] = fitResults + const [bestMatch] = fitResults .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) .reduce(([accSize, fit], [size, res]) => { let matchArr = Object.values(res.matchMap); @@ -378,8 +377,9 @@ function getRecommendedFit (fitResults, optimalFit) { return [accSize, fit]; } }, [null, 0]); + return bestMatch; } else { - [bestMatch] = fitResults + const [bestMatch] = fitResults .filter(([, res]) => res.totalFit >= 1000 && res.accuracy > 0) .reduce(([accSize, fit], [size, res]) => { const newFit = Math.abs(res.totalFit - optFit); @@ -389,8 +389,8 @@ function getRecommendedFit (fitResults, optimalFit) { return [accSize, fit]; } }, [null, 0]); + return bestMatch; } - return bestMatch; } function match (doSelectBestFit = true) {