final check in

This commit is contained in:
Martin Donnelly 2020-08-12 09:26:20 +01:00
parent 19fe4ce4a8
commit 0c7ac7e9ca
9 changed files with 868 additions and 279 deletions

55
.eslintrc.json Normal file
View File

@ -0,0 +1,55 @@
{
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module",
"ecmaFeatures": {
"jsx": false
}
},
"env": {
"browser": true,
"node": true,
"es2017": true
},
"rules": {
"arrow-spacing": "error",
"block-scoped-var": "error",
"block-spacing": "error",
"brace-style": ["error", "stroustrup", {}],
"camelcase": "error",
"comma-dangle": ["error", "never"],
"comma-spacing": ["error", { "before": false, "after": true }],
"comma-style": [1, "last"],
"consistent-this": [1, "_this"],
"curly": [1, "multi"],
"eol-last": 1,
"eqeqeq": 1,
"func-names": 1,
"indent": ["error", 2, { "SwitchCase": 1 }],
"lines-around-comment": ["error", { "beforeBlockComment": true, "allowArrayStart": true }],
"max-len": [1, 180, 2], // 2 spaces per tab, max 80 chars per line
"new-cap": 1,
"newline-before-return": "error",
"no-array-constructor": 1,
"no-inner-declarations": [1, "both"],
"no-mixed-spaces-and-tabs": 1,
"no-multi-spaces": 2,
"no-new-object": 1,
"no-shadow-restricted-names": 1,
"object-curly-spacing": ["error", "always"],
"padded-blocks": ["error", { "blocks": "never", "switches": "always" }],
"prefer-const": "error",
"prefer-template": "error",
"one-var": 0,
"quote-props": ["error", "always"],
"quotes": [1, "single"],
"radix": 1,
"semi": [1, "always"],
"space-before-blocks": [1, "always"],
"space-infix-ops": 1,
"vars-on-top": 1,
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1 }],
"spaced-comment": ["error", "always", { "markers": ["/"] }]
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
<changelist name="Uncommitted_changes_before_Update_at_12_08_2020,_09_02_[Default_Changelist]" date="1597219373714" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/Uncommitted_changes_before_Update_at_12_08_2020,_09_02_[Default_Changelist]/shelved.patch" />
<option name="DESCRIPTION" value="Uncommitted changes before Update at 12/08/2020, 09:02 [Default Changelist]" />
</changelist>

View File

@ -1,35 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BranchesTreeState">
<expand>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="GROUP_NODE:origin" type="e8cecc67:BranchNodeDescriptor" />
</path>
</expand>
<select>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="BRANCH:master" type="e8cecc67:BranchNodeDescriptor" />
</path>
</select>
</component>
<component name="ChangeListManager">
<list default="true" id="8f59754f-8b0b-4496-b8f6-b19be929e084" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/.eslintrc.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Buyer.js" beforeDir="false" afterPath="$PROJECT_DIR$/Buyer.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Seller.js" beforeDir="false" afterPath="$PROJECT_DIR$/Seller.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.js" beforeDir="false" afterPath="$PROJECT_DIR$/main.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/buyer.test.js" beforeDir="false" afterPath="$PROJECT_DIR$/tests/buyer.test.js" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
@ -47,6 +25,12 @@
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="JsFlowSettings">
<service-enabled>true</service-enabled>
<exe-path />
<other-services-enabled>true</other-services-enabled>
<auto-save>true</auto-save>
</component>
<component name="ProjectId" id="1fwjsJ2NtOTdTtAo0YfeKXnfbHz" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
@ -56,20 +40,29 @@
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="true" />
<property name="dart.analysis.tool.window.visible" value="false" />
<property name="javascript.nodejs.core.library.configured.version" value="12.18.0" />
<property name="javascript.nodejs.core.library.typings.version" value="12.12.54" />
<property name="js.linters.configure.manually.selectedeslint" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.standard" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.eslint" value="$USER_HOME$/.nvm/versions/node/v12.18.0/bin/node" />
<property name="node.js.path.for.package.standard" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.standard" value="" />
<property name="nodejs.jest.jest_package" value="$PROJECT_DIR$/node_modules/jest" />
<property name="nodejs_interpreter_path" value="$USER_HOME$/.nvm/versions/node/v12.18.0/bin/node" />
<property name="nodejs_package_manager_path" value="npm" />
<property name="settings.editor.selected.configurable" value="settings.javascript.linters.eslint" />
<property name="settings.editor.selected.configurable" value="settings.nodejs" />
</component>
<component name="RunManager" selected="Node.js.main.js">
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$" />
</key>
</component>
<component name="RunManager" selected="Jest.buyer.test.js">
<configuration name="Buyer" type="JavaScriptTestRunnerJest" temporary="true" nameIsGenerated="true">
<node-interpreter value="project" />
<node-interpreter value="$USER_HOME$/.nvm/versions/node/v12.18.0/bin/node" />
<node-options value="" />
<jest-package value="$PROJECT_DIR$/node_modules/jest" />
<working-dir value="$PROJECT_DIR$" />
@ -81,21 +74,8 @@
</test-names>
<method v="2" />
</configuration>
<configuration name="Seller" type="JavaScriptTestRunnerJest" temporary="true" nameIsGenerated="true">
<node-interpreter value="project" />
<node-options value="" />
<jest-package value="$PROJECT_DIR$/node_modules/jest" />
<working-dir value="$PROJECT_DIR$" />
<envs />
<scope-kind value="SUITE" />
<test-file value="$PROJECT_DIR$/tests/seller.test.js" />
<test-names>
<test-name value="Seller" />
</test-names>
<method v="2" />
</configuration>
<configuration name="buyer.test.js" type="JavaScriptTestRunnerJest" temporary="true" nameIsGenerated="true">
<node-interpreter value="project" />
<node-interpreter value="$USER_HOME$/.nvm/versions/node/v12.18.0/bin/node" />
<node-options value="" />
<jest-package value="$PROJECT_DIR$/node_modules/jest" />
<working-dir value="$PROJECT_DIR$" />
@ -104,15 +84,10 @@
<test-file value="$PROJECT_DIR$/tests/buyer.test.js" />
<method v="2" />
</configuration>
<configuration name="main.js" type="NodeJSConfigurationType" temporary="true" nameIsGenerated="true" path-to-js-file="$PROJECT_DIR$/main.js" working-dir="$PROJECT_DIR$">
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Node.js.main.js" />
<item itemvalue="Jest.buyer.test.js" />
<item itemvalue="Jest.Buyer" />
<item itemvalue="Jest.Seller" />
</list>
</recent_temporary>
</component>
@ -125,75 +100,79 @@
<option name="presentableId" value="Default" />
<updated>1597136254764</updated>
<workItem from="1597136255857" duration="11000" />
<workItem from="1597136289338" duration="7691000" />
<workItem from="1597154817386" duration="1288000" />
<workItem from="1597180540366" duration="3965000" />
<workItem from="1597136289338" duration="12012000" />
<workItem from="1597219344174" duration="1323000" />
</task>
<task id="LOCAL-00001" summary="stuff">
<created>1597176737162</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1597176737162</updated>
</task>
<option name="localTasksCounter" value="2" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State>
<option name="FILTERS">
<map>
<entry key="branch">
<value>
<list>
<option value="master" />
</list>
</value>
</entry>
</map>
</option>
</State>
</value>
</entry>
</map>
</option>
<component name="VcsManagerConfiguration">
<MESSAGE value="stuff" />
<option name="LAST_COMMIT_MESSAGE" value="stuff" />
</component>
<component name="WindowStateProjectService">
<state x="778" y="303" width="485" height="511" key="FileChooserDialogImpl" timestamp="1597154877477">
<screen x="0" y="0" width="2048" height="1121" />
<state x="607" y="460" width="598" height="545" key="#ESLint" timestamp="1597219880791">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="778" y="303" width="485" height="511" key="FileChooserDialogImpl/0.0.2048.1121@0.0.2048.1121" timestamp="1597154877477" />
<state width="2000" height="268" key="GridCell.Tab.0.bottom" timestamp="1597187407035">
<screen x="0" y="0" width="2048" height="1121" />
<state x="607" y="460" width="598" height="545" key="#ESLint/0.29.2560.1411@0.29.2560.1411" timestamp="1597219880791" />
<state x="1020" y="290" width="839" height="886" key="CommitChangelistDialog2" timestamp="1597176736967">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state width="2000" height="268" key="GridCell.Tab.0.bottom/0.0.2048.1121@0.0.2048.1121" timestamp="1597187407035" />
<state width="2463" height="519" key="GridCell.Tab.0.bottom/0.29.2560.1411@0.29.2560.1411" timestamp="1597146833789" />
<state width="2000" height="268" key="GridCell.Tab.0.center" timestamp="1597187407034">
<screen x="0" y="0" width="2048" height="1121" />
<state x="1020" y="290" width="839" height="886" key="CommitChangelistDialog2/0.29.2560.1411@0.29.2560.1411" timestamp="1597176736967" />
<state x="1085" y="461" width="429" height="542" key="FileChooserDialogImpl" timestamp="1597219688094">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state width="2000" height="268" key="GridCell.Tab.0.center/0.0.2048.1121@0.0.2048.1121" timestamp="1597187407034" />
<state width="2463" height="519" key="GridCell.Tab.0.center/0.29.2560.1411@0.29.2560.1411" timestamp="1597146833789" />
<state width="2000" height="268" key="GridCell.Tab.0.left" timestamp="1597187407034">
<screen x="0" y="0" width="2048" height="1121" />
<state x="1085" y="461" width="429" height="542" key="FileChooserDialogImpl/0.29.2560.1411@0.29.2560.1411" timestamp="1597219688094" />
<state width="1668" height="383" key="GridCell.Tab.0.bottom" timestamp="1597220628952">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state width="2000" height="268" key="GridCell.Tab.0.left/0.0.2048.1121@0.0.2048.1121" timestamp="1597187407034" />
<state width="2463" height="519" key="GridCell.Tab.0.left/0.29.2560.1411@0.29.2560.1411" timestamp="1597146833788" />
<state width="2000" height="268" key="GridCell.Tab.0.right" timestamp="1597187407035">
<screen x="0" y="0" width="2048" height="1121" />
<state width="1668" height="383" key="GridCell.Tab.0.bottom/0.29.2560.1411@0.29.2560.1411" timestamp="1597220628952" />
<state width="1668" height="383" key="GridCell.Tab.0.center" timestamp="1597220628952">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state width="2000" height="268" key="GridCell.Tab.0.right/0.0.2048.1121@0.0.2048.1121" timestamp="1597187407035" />
<state width="2463" height="519" key="GridCell.Tab.0.right/0.29.2560.1411@0.29.2560.1411" timestamp="1597146833789" />
<state x="200" y="98" width="1642" height="923" key="MergeDialog" timestamp="1597180616716">
<screen x="0" y="0" width="2048" height="1121" />
<state width="1668" height="383" key="GridCell.Tab.0.center/0.29.2560.1411@0.29.2560.1411" timestamp="1597220628952" />
<state width="1668" height="383" key="GridCell.Tab.0.left" timestamp="1597220628951">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="200" y="98" width="1642" height="923" key="MergeDialog/0.0.2048.1121@0.0.2048.1121" timestamp="1597180616716" />
<state x="611" y="381" key="SettingsEditor" timestamp="1597181517145">
<screen x="0" y="0" width="2048" height="1121" />
<state width="1668" height="383" key="GridCell.Tab.0.left/0.29.2560.1411@0.29.2560.1411" timestamp="1597220628951" />
<state width="1668" height="383" key="GridCell.Tab.0.right" timestamp="1597220628952">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="611" y="381" key="SettingsEditor/0.0.2048.1121@0.0.2048.1121" timestamp="1597181517145" />
<state x="814" y="475" width="413" height="169" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1597180559540">
<screen x="0" y="0" width="2048" height="1121" />
<state width="1668" height="383" key="GridCell.Tab.0.right/0.29.2560.1411@0.29.2560.1411" timestamp="1597220628952" />
<state x="0" y="155" width="2052" height="1155" key="MergeDialog" timestamp="1597219373633">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="814" y="475" width="413" height="169" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/0.0.2048.1121@0.0.2048.1121" timestamp="1597180559540" />
<state x="0" y="155" width="2052" height="1155" key="MergeDialog/0.29.2560.1411@0.29.2560.1411" timestamp="1597219373633" />
<state x="799" y="369" key="SettingsEditor" timestamp="1597219907473">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="799" y="369" key="SettingsEditor/0.29.2560.1411@0.29.2560.1411" timestamp="1597219907473" />
<state x="1037" y="470" width="804" height="525" key="Vcs.Push.Dialog.v2" timestamp="1597176739005">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="1037" y="470" width="804" height="525" key="Vcs.Push.Dialog.v2/0.29.2560.1411@0.29.2560.1411" timestamp="1597176739005" />
<state x="149" y="129" width="2179" height="1211" key="com.intellij.history.integration.ui.views.FileHistoryDialog" timestamp="1597220667049">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="149" y="129" width="2179" height="1211" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.29.2560.1411@0.29.2560.1411" timestamp="1597220667049" />
<state x="700" y="648" width="412" height="169" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2" timestamp="1597219354635">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="700" y="648" width="412" height="169" key="com.intellij.openapi.vcs.update.UpdateOrStatusOptionsDialogupdate-v2/0.29.2560.1411@0.29.2560.1411" timestamp="1597219354635" />
<state x="572" y="350" width="672" height="678" key="search.everywhere.popup" timestamp="1597220280258">
<screen x="0" y="29" width="2560" height="1411" />
</state>
<state x="572" y="350" width="672" height="678" key="search.everywhere.popup/0.29.2560.1411@0.29.2560.1411" timestamp="1597220280258" />
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/coding_challenge$buyer_test_js.info" NAME="buyer.test.js Coverage Results" MODIFIED="1597143325899" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="JestJavaScriptTestRunnerCoverage" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" />

176
Buyer.js
View File

@ -3,67 +3,66 @@ class Buyer {
this.market = market;
}
/**
* Build a list of the sellers
* @param product
* @returns {*}
*/
buildSellerList(product) {
const sellers = [];
this.market.sellers.forEach((seller, i) => {
if (seller.inventory.hasOwnProperty(product)) {
const price = seller.quote(product);
sellers.push({ 'id': seller.id, 'price': price, 'index': i, 'quantity': seller.inventory[product].quantity });
}
});
return sellers;
}
/**
* Build an order preference table for particular product
* @param product
*/
buildOrderPrefBestPrice(product) {
let sellers = [];
// build up the initial list
this.market.sellers.forEach((seller, i) => {
if (seller.inventory.hasOwnProperty(product)) {
const price = seller.quote(product);
sellers.push({id: seller.id, price: price, index: i, quantity: seller.inventory[product].quantity})
}
});
const sellers = this.buildSellerList(product);
// sort by best price
sellers.sort((a, b) => {
return a.price - b.price;
})
});
return sellers;
}
/**
* Sort the list based on Delivery delay
* @param product
* @returns {*}
*/
buildOrderPrefFastFill(product) {
let sellers = [];
// build up the initial list
this.market.sellers.forEach((seller, i) => {
if (seller.inventory.hasOwnProperty(product)) {
const price = seller.quote(product);
sellers.push({id: seller.id, price: price, index: i, quantity: seller.inventory[product].quantity, deliveryWait:seller.deliveryWait})
}
});
const sellers = this.buildSellerList(product);
// sort by best price
sellers.sort((a, b) => {
return a.deliveryWait - b.deliveryWait;
})
});
return sellers;
}
/**
* Sort the list based on item quantity
* @param product
* @returns {*}
*/
buildOrderPrefMostFill(product) {
let sellers = [];
// build up the initial list
this.market.sellers.forEach((seller, i) => {
if (seller.inventory.hasOwnProperty(product)) {
const price = seller.quote(product);
sellers.push({id: seller.id, price: price, index: i, quantity: seller.inventory[product].quantity, deliveryWait:seller.deliveryWait})
}
});
const sellers = this.buildSellerList(product);
// sort by best price
sellers.sort((a, b) => {
return b.quantity - a.quantity;
})
});
return sellers;
}
@ -79,12 +78,41 @@ class Buyer {
const price = seller.quote(product);
if (lowestPrice === null || lowestPrice > price) lowestPrice = price;
}
});
return lowestPrice || 0;
}
/**
* Do the actual purchases based on preference list
* @param preference
* @param product
* @param quantity
* @returns {number}
*/
doPurchases(preference, product, quantity) {
const sellerPreference = [...preference];
let total = 0;
let wantedQuantity = quantity;
const receipt = [];
while (sellerPreference.length > 0 && wantedQuantity > 0) {
const seller = sellerPreference.shift();
const r = this.market.sellers[seller.index].sell(product, wantedQuantity);
wantedQuantity = (wantedQuantity - r.boughtQuantity) < 0 ? 0 : (wantedQuantity - r.boughtQuantity);
receipt.push(r);
}
if (receipt.length > 1)
total = receipt.reduce((a, cv) => {
return (typeof a === 'number' ? a : a.cost) + cv.cost;
});
else if (receipt.length === 1) total = receipt[0].cost;
return total;
}
/**
* This method should optimise price when filling an order
@ -92,33 +120,11 @@ class Buyer {
* then the next cheapest seller should be used.
*/
fillWithBestPrices(product, quantity) {
const sellerPreference = this.buildOrderPrefBestPrice(product);
let total = 0;
let wantedQuantity = quantity;
let sellerPreference = this.buildOrderPrefBestPrice(product);
let receipt = [];
while (sellerPreference.length > 0 && wantedQuantity > 0) {
let seller = sellerPreference.shift();
let r = this.market.sellers[seller.index].sell(product, wantedQuantity);
wantedQuantity = (wantedQuantity - r.boughtQuantity) < 0 ? 0 : (wantedQuantity - r.boughtQuantity);
receipt.push(r);
return this.doPurchases(sellerPreference, product, quantity);
}
if (receipt.length > 1) {
total = receipt.reduce((a, cv) => {
return (typeof a === 'number' ? a : a.cost) + cv.cost;
});
} else if (receipt.length === 1) total = receipt[0].cost;
return total;
}
/**
* This method should optimise for sellers with the largest inventory when filling an order
* if the quantity is greater than any single seller can accomodate
@ -127,30 +133,9 @@ class Buyer {
* you should use the cheaper of the two.
*/
fillWithLargestSellers(product, quantity) {
let total = 0;
let wantedQuantity = quantity;
let sellerPreference = this.buildOrderPrefMostFill(product);
let receipt = [];
while (sellerPreference.length > 0 && wantedQuantity > 0) {
let seller = sellerPreference.shift();
let r = this.market.sellers[seller.index].sell(product, wantedQuantity);
wantedQuantity = (wantedQuantity - r.boughtQuantity) < 0 ? 0 : (wantedQuantity - r.boughtQuantity);
receipt.push(r);
}
if (receipt.length > 1) {
total = receipt.reduce((a, cv) => {
return (typeof a === 'number' ? a : a.cost) + cv.cost;
});
} else if (receipt.length === 1) total = receipt[0].cost;
return total;
const sellerPreference = this.buildOrderPrefMostFill(product);
return this.doPurchases(sellerPreference, product, quantity);
}
/**
@ -160,31 +145,10 @@ class Buyer {
* @returns {number}
*/
quicklyFill(product, quantity) {
let total = 0;
let wantedQuantity = quantity;
let sellerPreference = this.buildOrderPrefFastFill(product);
let receipt = [];
while (sellerPreference.length > 0 && wantedQuantity > 0) {
let seller = sellerPreference.shift();
let r = this.market.sellers[seller.index].sell(product, wantedQuantity);
wantedQuantity = (wantedQuantity - r.boughtQuantity) < 0 ? 0 : (wantedQuantity - r.boughtQuantity);
receipt.push(r);
}
if (receipt.length > 1) {
total = receipt.reduce((a, cv) => {
return (typeof a === 'number' ? a : a.cost) + cv.cost;
});
} else if (receipt.length === 1) total = receipt[0].cost;
return total;
const sellerPreference = this.buildOrderPrefFastFill(product);
return this.doPurchases(sellerPreference, product, quantity);
}
}
module.exports = {Buyer}
module.exports = { Buyer };

493
package-lock.json generated
View File

@ -767,6 +767,12 @@
"acorn-walk": "^7.1.1"
}
},
"acorn-jsx": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz",
"integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
"dev": true
},
"acorn-walk": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz",
@ -785,6 +791,12 @@
"uri-js": "^4.2.2"
}
},
"ansi-colors": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
"dev": true
},
"ansi-escapes": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz",
@ -882,6 +894,12 @@
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
"dev": true
},
"astral-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
"dev": true
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@ -1434,6 +1452,15 @@
"integrity": "sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg==",
"dev": true
},
"doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"dev": true,
"requires": {
"esutils": "^2.0.2"
}
},
"domexception": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz",
@ -1476,6 +1503,15 @@
"once": "^1.4.0"
}
},
"enquirer": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
"integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
"dev": true,
"requires": {
"ansi-colors": "^4.1.1"
}
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -1504,12 +1540,220 @@
"source-map": "~0.6.1"
}
},
"eslint": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.6.0.tgz",
"integrity": "sha512-QlAManNtqr7sozWm5TF4wIH9gmUm2hE3vNRUvyoYAa4y1l5/jxD/PQStEjBMQtCqZmSep8UxrcecI60hOpe61w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
"debug": "^4.0.1",
"doctrine": "^3.0.0",
"enquirer": "^2.3.5",
"eslint-scope": "^5.1.0",
"eslint-utils": "^2.1.0",
"eslint-visitor-keys": "^1.3.0",
"espree": "^7.2.0",
"esquery": "^1.2.0",
"esutils": "^2.0.2",
"file-entry-cache": "^5.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
"globals": "^12.1.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash": "^4.17.19",
"minimatch": "^3.0.4",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
"progress": "^2.0.0",
"regexpp": "^3.1.0",
"semver": "^7.2.1",
"strip-ansi": "^6.0.0",
"strip-json-comments": "^3.1.0",
"table": "^5.2.3",
"text-table": "^0.2.0",
"v8-compile-cache": "^2.0.3"
},
"dependencies": {
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"globals": {
"version": "12.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
"dev": true,
"requires": {
"type-fest": "^0.8.1"
}
},
"levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
"requires": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
}
},
"lodash": {
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"dev": true
},
"optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
"integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
"dev": true,
"requires": {
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
"type-check": "^0.4.0",
"word-wrap": "^1.2.3"
}
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true
},
"prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
"semver": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
"dev": true
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
"type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
"requires": {
"prelude-ls": "^1.2.1"
}
}
}
},
"eslint-scope": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
"integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"eslint-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.1.0"
}
},
"eslint-visitor-keys": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
"dev": true
},
"espree": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz",
"integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==",
"dev": true,
"requires": {
"acorn": "^7.3.1",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.3.0"
},
"dependencies": {
"acorn": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
"dev": true
}
}
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
},
"esquery": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
"integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
"dev": true,
"requires": {
"estraverse": "^5.1.0"
},
"dependencies": {
"estraverse": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
"dev": true
}
}
},
"esrecurse": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
"integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
"dev": true,
"requires": {
"estraverse": "^4.1.0"
}
},
"estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
@ -1738,6 +1982,15 @@
"bser": "2.1.1"
}
},
"file-entry-cache": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
"integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
"dev": true,
"requires": {
"flat-cache": "^2.0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@ -1757,6 +2010,34 @@
"path-exists": "^4.0.0"
}
},
"flat-cache": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
"integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
"dev": true,
"requires": {
"flatted": "^2.0.0",
"rimraf": "2.6.3",
"write": "1.0.3"
},
"dependencies": {
"rimraf": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
}
}
},
"flatted": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@ -1802,6 +2083,12 @@
"dev": true,
"optional": true
},
"functional-red-black-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
"gensync": {
"version": "1.0.0-beta.1",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz",
@ -1858,6 +2145,15 @@
"path-is-absolute": "^1.0.0"
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@ -1998,6 +2294,30 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"import-fresh": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
"integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
"dev": true,
"requires": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
},
"dependencies": {
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
}
}
},
"import-local": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz",
@ -2129,6 +2449,12 @@
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
"dev": true
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@ -2141,6 +2467,15 @@
"integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
"dev": true
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@ -2849,6 +3184,12 @@
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@ -3036,6 +3377,15 @@
}
}
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -3273,6 +3623,15 @@
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"requires": {
"callsites": "^3.0.0"
}
},
"parse-json": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
@ -3375,6 +3734,12 @@
"react-is": "^16.12.0"
}
},
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
"prompts": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz",
@ -3468,6 +3833,12 @@
"safe-regex": "^1.1.0"
}
},
"regexpp": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
"integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
"dev": true
},
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
@ -3881,6 +4252,49 @@
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true
},
"slice-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
"integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"astral-regex": "^1.0.0",
"is-fullwidth-code-point": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
}
}
},
"snapdragon": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@ -4200,6 +4614,12 @@
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
"dev": true
},
"strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
@ -4225,6 +4645,58 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true
},
"table": {
"version": "5.4.6",
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
"integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
"dev": true,
"requires": {
"ajv": "^6.10.2",
"lodash": "^4.17.14",
"slice-ansi": "^2.1.0",
"string-width": "^3.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
}
}
},
"terminal-link": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@ -4246,6 +4718,12 @@
"minimatch": "^3.0.4"
}
},
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"throat": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
@ -4455,6 +4933,12 @@
"dev": true,
"optional": true
},
"v8-compile-cache": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
"integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
"dev": true
},
"v8-to-istanbul": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz",
@ -4600,6 +5084,15 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"write": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
"integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
"dev": true,
"requires": {
"mkdirp": "^0.5.1"
}
},
"write-file-atomic": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",

View File

@ -10,8 +10,9 @@
"author": "",
"license": "ISC",
"devDependencies": {
"jest": "^26.0.1",
"expect": "^26.0.1"
"eslint": "^7.6.0",
"expect": "^26.0.1",
"jest": "^26.0.1"
},
"dependencies": {
"random-seed": "^0.3.0",

View File

@ -1,67 +1,63 @@
const expect = require("expect")
const {asda, costco, budgens} = require("../marketplace");
const {Market} = require("../Market");
const {Buyer} = require("../Buyer");
const expect = require('expect');
const { asda, costco, budgens } = require('../marketplace');
const { Market } = require('../Market');
const { Buyer } = require('../Buyer');
describe("Buyer", function () {
describe('Buyer', function () {
var market;
beforeEach(() => {
market = new Market([asda, budgens, costco]);
})
});
// getBestPrice
it("should return best price", () => {
let buyer = new Buyer(market);
it('should return best price', () => {
const buyer = new Buyer(market);
expect(buyer.getBestPrice('Apples')).toEqual(4.25);
});
it("should return best price that only 2 have", () => {
let buyer = new Buyer(market);
it('should return best price that only 2 have', () => {
const buyer = new Buyer(market);
expect(buyer.getBestPrice('Grapes')).toEqual(21);
});
it("should return best price that only 1 has", () => {
let buyer = new Buyer(market);
it('should return best price that only 1 has', () => {
const buyer = new Buyer(market);
expect(buyer.getBestPrice('Mangosteen')).toEqual(100.0);
});
it("should return 0 when fruit doesnt exist", () => {
let buyer = new Buyer(market);
it('should return 0 when fruit doesnt exist', () => {
const buyer = new Buyer(market);
expect(buyer.getBestPrice('Kumquat')).toEqual(0);
});
it("fill 10 apples", () => {
let buyer = new Buyer(market);
// Filling
it('fill 10 apples', () => {
const buyer = new Buyer(market);
expect(buyer.fillWithBestPrices('Apples', 10)).toEqual(42.5);
});
it("fill 50 apples", () => {
let buyer = new Buyer(market);
it('fill 50 apples', () => {
const buyer = new Buyer(market);
expect(buyer.fillWithBestPrices('Apples', 50)).toEqual(233.60268569487857);
});
it("unable to fill 10 Kumquat", () => {
let buyer = new Buyer(market);
it('unable to fill 10 Kumquat', () => {
const buyer = new Buyer(market);
expect(buyer.fillWithBestPrices('Kumquat', 10)).toEqual(0);
});
it("Large fill 50 apples", () => {
let buyer = new Buyer(market);
// Large fill
it('Large fill 50 apples', () => {
const buyer = new Buyer(market);
expect(buyer. fillWithLargestSellers('Apples', 50)).toEqual(312.5);
expect(buyer.fillWithLargestSellers('Apples', 50)).toEqual(312.5);
});
});