updte before bed
This commit is contained in:
parent
59e89318de
commit
19fe4ce4a8
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,4 @@
|
|||||||
|
<changelist name="Uncommitted_changes_before_Update_at_11_08_2020,_22_16_[Default_Changelist]" date="1597180616770" recycled="true" deleted="true">
|
||||||
|
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/Uncommitted_changes_before_Update_at_11_08_2020,_22_16_[Default_Changelist]/shelved.patch" />
|
||||||
|
<option name="DESCRIPTION" value="Uncommitted changes before Update at 11/08/2020, 22:16 [Default Changelist]" />
|
||||||
|
</changelist>
|
@ -1,10 +1,35 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<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">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="8f59754f-8b0b-4496-b8f6-b19be929e084" name="Default Changelist" comment="">
|
<list default="true" id="8f59754f-8b0b-4496-b8f6-b19be929e084" name="Default Changelist" comment="">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="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$/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$/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$/tests/buyer.test.js" beforeDir="false" afterPath="$PROJECT_DIR$/tests/buyer.test.js" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/tests/buyer.test.js" beforeDir="false" afterPath="$PROJECT_DIR$/tests/buyer.test.js" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
@ -32,12 +57,19 @@
|
|||||||
<property name="WebServerToolWindowFactoryState" value="true" />
|
<property name="WebServerToolWindowFactoryState" value="true" />
|
||||||
<property name="dart.analysis.tool.window.visible" value="false" />
|
<property name="dart.analysis.tool.window.visible" value="false" />
|
||||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
<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.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.jest.jest_package" value="$PROJECT_DIR$/node_modules/jest" />
|
||||||
<property name="settings.editor.selected.configurable" value="reference.settingsdialog.IDE.editor.colors" />
|
<property name="nodejs_package_manager_path" value="npm" />
|
||||||
|
<property name="settings.editor.selected.configurable" value="settings.javascript.linters.eslint" />
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="Jest.buyer.test.js">
|
<component name="RunManager" selected="Node.js.main.js">
|
||||||
<configuration name="Buyer" type="JavaScriptTestRunnerJest" temporary="true" nameIsGenerated="true">
|
<configuration name="Buyer" type="JavaScriptTestRunnerJest" temporary="true" nameIsGenerated="true">
|
||||||
<node-interpreter value="$USER_HOME$/.nvm/versions/node/v12.18.0/bin/node" />
|
<node-interpreter value="project" />
|
||||||
<node-options value="" />
|
<node-options value="" />
|
||||||
<jest-package value="$PROJECT_DIR$/node_modules/jest" />
|
<jest-package value="$PROJECT_DIR$/node_modules/jest" />
|
||||||
<working-dir value="$PROJECT_DIR$" />
|
<working-dir value="$PROJECT_DIR$" />
|
||||||
@ -49,8 +81,21 @@
|
|||||||
</test-names>
|
</test-names>
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</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">
|
<configuration name="buyer.test.js" type="JavaScriptTestRunnerJest" temporary="true" nameIsGenerated="true">
|
||||||
<node-interpreter value="$USER_HOME$/.nvm/versions/node/v12.18.0/bin/node" />
|
<node-interpreter value="project" />
|
||||||
<node-options value="" />
|
<node-options value="" />
|
||||||
<jest-package value="$PROJECT_DIR$/node_modules/jest" />
|
<jest-package value="$PROJECT_DIR$/node_modules/jest" />
|
||||||
<working-dir value="$PROJECT_DIR$" />
|
<working-dir value="$PROJECT_DIR$" />
|
||||||
@ -59,10 +104,15 @@
|
|||||||
<test-file value="$PROJECT_DIR$/tests/buyer.test.js" />
|
<test-file value="$PROJECT_DIR$/tests/buyer.test.js" />
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</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>
|
<recent_temporary>
|
||||||
<list>
|
<list>
|
||||||
|
<item itemvalue="Node.js.main.js" />
|
||||||
<item itemvalue="Jest.buyer.test.js" />
|
<item itemvalue="Jest.buyer.test.js" />
|
||||||
<item itemvalue="Jest.Buyer" />
|
<item itemvalue="Jest.Buyer" />
|
||||||
|
<item itemvalue="Jest.Seller" />
|
||||||
</list>
|
</list>
|
||||||
</recent_temporary>
|
</recent_temporary>
|
||||||
</component>
|
</component>
|
||||||
@ -75,38 +125,75 @@
|
|||||||
<option name="presentableId" value="Default" />
|
<option name="presentableId" value="Default" />
|
||||||
<updated>1597136254764</updated>
|
<updated>1597136254764</updated>
|
||||||
<workItem from="1597136255857" duration="11000" />
|
<workItem from="1597136255857" duration="11000" />
|
||||||
<workItem from="1597136289338" duration="11990000" />
|
<workItem from="1597136289338" duration="7691000" />
|
||||||
|
<workItem from="1597154817386" duration="1288000" />
|
||||||
|
<workItem from="1597180540366" duration="3965000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
<option name="version" value="3" />
|
<option name="version" value="3" />
|
||||||
</component>
|
</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>
|
||||||
<component name="WindowStateProjectService">
|
<component name="WindowStateProjectService">
|
||||||
<state x="1085" y="461" width="429" height="542" key="FileChooserDialogImpl" timestamp="1597154405421">
|
<state x="778" y="303" width="485" height="511" key="FileChooserDialogImpl" timestamp="1597154877477">
|
||||||
<screen x="0" y="29" width="2560" height="1411" />
|
<screen x="0" y="0" width="2048" height="1121" />
|
||||||
</state>
|
</state>
|
||||||
<state x="1085" y="461" width="429" height="542" key="FileChooserDialogImpl/0.29.2560.1411@0.29.2560.1411" timestamp="1597154405421" />
|
<state x="778" y="303" width="485" height="511" key="FileChooserDialogImpl/0.0.2048.1121@0.0.2048.1121" timestamp="1597154877477" />
|
||||||
<state width="2183" height="383" key="GridCell.Tab.0.bottom" timestamp="1597176719490">
|
<state width="2000" height="268" key="GridCell.Tab.0.bottom" timestamp="1597187407035">
|
||||||
<screen x="0" y="29" width="2560" height="1411" />
|
<screen x="0" y="0" width="2048" height="1121" />
|
||||||
</state>
|
</state>
|
||||||
<state width="2183" height="383" key="GridCell.Tab.0.bottom/0.29.2560.1411@0.29.2560.1411" timestamp="1597176719490" />
|
<state width="2000" height="268" key="GridCell.Tab.0.bottom/0.0.2048.1121@0.0.2048.1121" timestamp="1597187407035" />
|
||||||
<state width="2183" height="383" key="GridCell.Tab.0.center" timestamp="1597176719490">
|
<state width="2463" height="519" key="GridCell.Tab.0.bottom/0.29.2560.1411@0.29.2560.1411" timestamp="1597146833789" />
|
||||||
<screen x="0" y="29" width="2560" height="1411" />
|
<state width="2000" height="268" key="GridCell.Tab.0.center" timestamp="1597187407034">
|
||||||
|
<screen x="0" y="0" width="2048" height="1121" />
|
||||||
</state>
|
</state>
|
||||||
<state width="2183" height="383" key="GridCell.Tab.0.center/0.29.2560.1411@0.29.2560.1411" timestamp="1597176719490" />
|
<state width="2000" height="268" key="GridCell.Tab.0.center/0.0.2048.1121@0.0.2048.1121" timestamp="1597187407034" />
|
||||||
<state width="2183" height="383" key="GridCell.Tab.0.left" timestamp="1597176719489">
|
<state width="2463" height="519" key="GridCell.Tab.0.center/0.29.2560.1411@0.29.2560.1411" timestamp="1597146833789" />
|
||||||
<screen x="0" y="29" width="2560" height="1411" />
|
<state width="2000" height="268" key="GridCell.Tab.0.left" timestamp="1597187407034">
|
||||||
|
<screen x="0" y="0" width="2048" height="1121" />
|
||||||
</state>
|
</state>
|
||||||
<state width="2183" height="383" key="GridCell.Tab.0.left/0.29.2560.1411@0.29.2560.1411" timestamp="1597176719489" />
|
<state width="2000" height="268" key="GridCell.Tab.0.left/0.0.2048.1121@0.0.2048.1121" timestamp="1597187407034" />
|
||||||
<state width="2183" height="383" key="GridCell.Tab.0.right" timestamp="1597176719490">
|
<state width="2463" height="519" key="GridCell.Tab.0.left/0.29.2560.1411@0.29.2560.1411" timestamp="1597146833788" />
|
||||||
<screen x="0" y="29" width="2560" height="1411" />
|
<state width="2000" height="268" key="GridCell.Tab.0.right" timestamp="1597187407035">
|
||||||
|
<screen x="0" y="0" width="2048" height="1121" />
|
||||||
</state>
|
</state>
|
||||||
<state width="2183" height="383" key="GridCell.Tab.0.right/0.29.2560.1411@0.29.2560.1411" timestamp="1597176719490" />
|
<state width="2000" height="268" key="GridCell.Tab.0.right/0.0.2048.1121@0.0.2048.1121" timestamp="1597187407035" />
|
||||||
<state x="799" y="369" key="SettingsEditor" timestamp="1597155550499">
|
<state width="2463" height="519" key="GridCell.Tab.0.right/0.29.2560.1411@0.29.2560.1411" timestamp="1597146833789" />
|
||||||
<screen x="0" y="29" width="2560" height="1411" />
|
<state x="200" y="98" width="1642" height="923" key="MergeDialog" timestamp="1597180616716">
|
||||||
|
<screen x="0" y="0" width="2048" height="1121" />
|
||||||
</state>
|
</state>
|
||||||
<state x="799" y="369" key="SettingsEditor/0.29.2560.1411@0.29.2560.1411" timestamp="1597155550499" />
|
<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>
|
||||||
|
<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>
|
||||||
|
<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" />
|
||||||
</component>
|
</component>
|
||||||
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
<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" />
|
<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" />
|
||||||
|
233
Buyer.js
233
Buyer.js
@ -1,99 +1,190 @@
|
|||||||
class Buyer {
|
class Buyer {
|
||||||
constructor(market) {
|
constructor(market) {
|
||||||
this.market = market;
|
this.market = market;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an order preference table for particular product
|
* Build an order preference table for particular product
|
||||||
* @param product
|
* @param product
|
||||||
*/
|
*/
|
||||||
buildOrderPreference(product) {
|
buildOrderPrefBestPrice(product) {
|
||||||
let sellers = [];
|
let sellers = [];
|
||||||
|
|
||||||
// build up the initial list
|
// build up the initial list
|
||||||
this.market.sellers.forEach((seller, i) => {
|
this.market.sellers.forEach((seller, i) => {
|
||||||
if (seller.inventory.hasOwnProperty(product)) {
|
if (seller.inventory.hasOwnProperty(product)) {
|
||||||
const price = seller.quote(product);
|
const price = seller.quote(product);
|
||||||
sellers.push({id: seller.id, price: price, index: i, quantity:seller.inventory[product].quantity})
|
sellers.push({id: seller.id, price: price, index: i, quantity: seller.inventory[product].quantity})
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// sort by best price
|
// sort by best price
|
||||||
sellers.sort((a, b) => {
|
sellers.sort((a, b) => {
|
||||||
return a.price - b.price;
|
return a.price - b.price;
|
||||||
})
|
})
|
||||||
|
|
||||||
return sellers;
|
return sellers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method should get the best price for a given product
|
|
||||||
* across all sellers
|
|
||||||
*/
|
|
||||||
getBestPrice(product) {
|
|
||||||
let lowestPrice = null;
|
|
||||||
this.market.sellers.forEach(seller => {
|
|
||||||
if (seller.inventory.hasOwnProperty(product)) {
|
|
||||||
const price = seller.quote(product);
|
|
||||||
if (lowestPrice === null || lowestPrice > price) lowestPrice = price;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return lowestPrice || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
buildOrderPrefFastFill(product) {
|
||||||
* This method should optimise price when filling an order
|
let sellers = [];
|
||||||
* if the quantity is greater than any single seller can accomodate
|
|
||||||
* then the next cheapest seller should be used.
|
|
||||||
*/
|
|
||||||
fillWithBestPrices(product, quantity) {
|
|
||||||
|
|
||||||
let wantedQuantity = quantity;
|
// build up the initial list
|
||||||
let sellerPreference = this.buildOrderPreference(product);
|
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})
|
||||||
|
}
|
||||||
|
|
||||||
console.log(sellerPreference);
|
});
|
||||||
|
|
||||||
let reciept = [];
|
// sort by best price
|
||||||
|
sellers.sort((a, b) => {
|
||||||
|
return a.deliveryWait - b.deliveryWait;
|
||||||
|
})
|
||||||
|
|
||||||
while (sellerPreference.length > 0 && wantedQuantity > 0) {
|
return sellers;
|
||||||
|
}
|
||||||
|
|
||||||
let seller = sellerPreference.shift();
|
buildOrderPrefMostFill(product) {
|
||||||
|
let sellers = [];
|
||||||
|
|
||||||
let r = this.market.sellers[seller.index].sell(product, wantedQuantity);
|
// build up the initial list
|
||||||
wantedQuantity = (wantedQuantity - r.boughtQuantity) < 0 ? 0 : (wantedQuantity - r.boughtQuantity);
|
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})
|
||||||
|
}
|
||||||
|
|
||||||
reciept.push(r);
|
});
|
||||||
|
|
||||||
|
// sort by best price
|
||||||
|
sellers.sort((a, b) => {
|
||||||
|
return b.quantity - a.quantity;
|
||||||
|
})
|
||||||
|
|
||||||
|
return sellers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should get the best price for a given product
|
||||||
|
* across all sellers
|
||||||
|
*/
|
||||||
|
getBestPrice(product) {
|
||||||
|
let lowestPrice = null;
|
||||||
|
this.market.sellers.forEach(seller => {
|
||||||
|
if (seller.inventory.hasOwnProperty(product)) {
|
||||||
|
const price = seller.quote(product);
|
||||||
|
if (lowestPrice === null || lowestPrice > price) lowestPrice = price;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return lowestPrice || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should optimise price when filling an order
|
||||||
|
* if the quantity is greater than any single seller can accomodate
|
||||||
|
* then the next cheapest seller should be used.
|
||||||
|
*/
|
||||||
|
fillWithBestPrices(product, quantity) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
* then the next largest seller should be used.
|
||||||
|
* if multiple sellers have the same amount of inventory
|
||||||
|
* 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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(reciept);
|
/**
|
||||||
|
* This fulfils orders based on time to deliver
|
||||||
|
* @param product
|
||||||
|
* @param quantity
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
quicklyFill(product, quantity) {
|
||||||
|
let total = 0;
|
||||||
|
let wantedQuantity = quantity;
|
||||||
|
let sellerPreference = this.buildOrderPrefFastFill(product);
|
||||||
|
|
||||||
console.log(reciept.reduce((a, cv) => {
|
let receipt = [];
|
||||||
return a.cost + cv.cost;
|
|
||||||
})
|
|
||||||
|
|
||||||
|
while (sellerPreference.length > 0 && wantedQuantity > 0) {
|
||||||
|
|
||||||
);
|
let seller = sellerPreference.shift();
|
||||||
|
|
||||||
throw Error("Not Implemented");
|
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;
|
||||||
* 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
|
}
|
||||||
* then the next largest seller should be used.
|
|
||||||
* if multiple sellers have the same amount of inventory
|
|
||||||
* you should use the cheaper of the two.
|
|
||||||
*/
|
|
||||||
fillWithLargestSellers(product, quantity) {
|
|
||||||
throw Error("Not Implemented");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {Buyer}
|
module.exports = {Buyer}
|
||||||
|
@ -36,6 +36,7 @@ class Seller {
|
|||||||
const ec = getExpectedChange(this.random_generator);
|
const ec = getExpectedChange(this.random_generator);
|
||||||
const alpha = inventory.startingQuantity
|
const alpha = inventory.startingQuantity
|
||||||
const beta = inventory.quantity
|
const beta = inventory.quantity
|
||||||
|
// console.log(`${this.id} alpha: ${alpha} // beta: ${beta} // ec: ${ec}`);
|
||||||
const inv_based_change = Math.log10(beta / alpha) * (-v);
|
const inv_based_change = Math.log10(beta / alpha) * (-v);
|
||||||
const sentimentChange = inv_based_change + ((ec - 0.5)*v)
|
const sentimentChange = inv_based_change + ((ec - 0.5)*v)
|
||||||
return sentimentChange;
|
return sentimentChange;
|
||||||
@ -53,7 +54,6 @@ class Seller {
|
|||||||
|
|
||||||
|
|
||||||
tick() {
|
tick() {
|
||||||
console.log('tick', this);
|
|
||||||
for (let [product, value] of Object.entries(this.inventory)) {
|
for (let [product, value] of Object.entries(this.inventory)) {
|
||||||
let inventory = value;
|
let inventory = value;
|
||||||
const isReadyForDelivery = (inventory.priceHistory.length % this.deliveryWait) == 0;
|
const isReadyForDelivery = (inventory.priceHistory.length % this.deliveryWait) == 0;
|
||||||
|
4
main.js
4
main.js
@ -9,12 +9,12 @@ function main(){
|
|||||||
let product = "Apples";
|
let product = "Apples";
|
||||||
let quantity = 10;
|
let quantity = 10;
|
||||||
buyerFunctions(product, quantity, buyer);
|
buyerFunctions(product, quantity, buyer);
|
||||||
// observeMarket(market);
|
observeMarket(market);
|
||||||
};
|
};
|
||||||
|
|
||||||
function buyerFunctions(product, quantity, buyer){
|
function buyerFunctions(product, quantity, buyer){
|
||||||
console.log(`The best price for ${product} is ${buyer.getBestPrice(product)}`) ;
|
console.log(`The best price for ${product} is ${buyer.getBestPrice(product)}`) ;
|
||||||
console.log(`To completely fill a order of ${quantity} ${product} costs ${buyer.completelyFill(product,quantity)}`) ;
|
console.log(`To completely fill a order of ${quantity} ${product} costs ${buyer.fillWithBestPrices(product,quantity)}`) ;
|
||||||
console.log(`To buy as quickly as possible ${quantity} ${product} costs ${buyer.quicklyFill(product,quantity)}`) ;
|
console.log(`To buy as quickly as possible ${quantity} ${product} costs ${buyer.quicklyFill(product,quantity)}`) ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,19 +47,19 @@ describe("Buyer", function () {
|
|||||||
it("fill 50 apples", () => {
|
it("fill 50 apples", () => {
|
||||||
let buyer = new Buyer(market);
|
let buyer = new Buyer(market);
|
||||||
|
|
||||||
expect(buyer.fillWithBestPrices('Apples', 50)).toEqual(0);
|
expect(buyer.fillWithBestPrices('Apples', 50)).toEqual(233.60268569487857);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("fill 100 apples", () => {
|
it("unable to fill 10 Kumquat", () => {
|
||||||
let buyer = new Buyer(market);
|
let buyer = new Buyer(market);
|
||||||
|
|
||||||
expect(buyer.fillWithBestPrices('Apples', 100)).toEqual(0);
|
expect(buyer.fillWithBestPrices('Kumquat', 10)).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("fill 1000 apples", () => {
|
it("Large fill 50 apples", () => {
|
||||||
let buyer = new Buyer(market);
|
let buyer = new Buyer(market);
|
||||||
|
|
||||||
expect(buyer.fillWithBestPrices('Apples', 100)).toEqual(0);
|
expect(buyer. fillWithLargestSellers('Apples', 50)).toEqual(312.5);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user