From dccf1508877e34bdf8b2e59d360a6a92ff87c884 Mon Sep 17 00:00:00 2001 From: s452693 Date: Mon, 3 May 2021 20:53:11 +0200 Subject: [PATCH 1/5] ikony produktow --- cozrobic.txt | 6 +++++ src/logic/product.js | 58 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 cozrobic.txt diff --git a/cozrobic.txt b/cozrobic.txt new file mode 100644 index 0000000..0d086b0 --- /dev/null +++ b/cozrobic.txt @@ -0,0 +1,6 @@ +> tablica na ilość produktów +> znalezienie fontu z ikonami +> funkcja do wypełniania tej tablicy (usunąć losowanie wartości z drawProducts() ) +> funckja do odbierania ilości produktów od robota +> funkcja do usuwania losowej ilości produktów +> funkcja do zamieniania miejscami produktów na półkach (5% szansy) \ No newline at end of file diff --git a/src/logic/product.js b/src/logic/product.js index 2491bd1..5e4b2da 100644 --- a/src/logic/product.js +++ b/src/logic/product.js @@ -26,51 +26,71 @@ class Product { static get REGISTRY() { // in alphabetical order + //baby, camp, cat, car, cleaning, cloathes, cocktail, dog, electronic, glas, haunting + //kitchen, moving, newborn, swimming, winter, toilet, religion, party + //40 return { empty: new Product('', ''), airFrashener: new Product('airFrashener', 'fa-wind'), apple: new Product('apple', 'fa-apple-alt'), babyAccessories: new Product('babyAccessories','fa-baby-carriage'), bacon: new Product('bacon', 'fa-bacon'), + bandAid: new Product('bandAid', 'fa-band-aid'), + basketballBall: new Product('basketballBall', 'fa-basketball-ball'), beer: new Product('beer','fa-beer'), + bell: new Product('bell','fa-bell'), bicycle: new Product('bicycle','fa-bicycle'), bone: new Product('bone', 'fa-bone'), book: new Product('book', 'fa-book'), bread: new Product('bread', 'fa-bread-slice'), - bread: new Product('bread','fa-bread-slice'), cake: new Product('cake', 'fa-birthday-cake'), + calculator: new Product('calculator', 'fa-calculator'), + calendar: new Product('calendar', 'fa-calendar'), + camera: new Product('camera','fa-camera'), campAccessories: new Product('campAccessories','fa-campground'), candyCane: new Product('candy cane', 'fa-candy-cane'), carrot: new Product('carrot', 'fa-carrot'), - carrot: new Product('carrot','fa-carrot'), catAccessories: new Product('catAccessories','fa-cat'), - camera: new Product('camera','fa-camera'), carAccessories: new Product('carAccessories','fa-car'), + cigarettes: new Product('cigarettes', 'fa-smoking'), + chair: new Product('chair', 'fa-chair'), + charger: new Product('charger', 'fa-battery-half'), + cheese: new Product('cheese', 'fa-cheese'), + chess: new Product('chess', 'fa-chess'), cleaningSupplies: new Product('cleaningSupplies', 'fa-broom'), + cloathesAccessories: new Product('cloathesAccessories','fa-glasses'), cocktailSupplies: new Product('cocktailSupplies','fa-cocktail'), coffee: new Product('cofee','fa-coffee'), + contactLenses: new Product('contactLenses', 'fa-eye'), cookie: new Product('cookie','fa-cookie'), + couch: new Product('couch', 'fa-couch'), coughSyrop: new Product('coughSyrop', 'fa-lungs'), - cheese: new Product('cheese', 'fa-cheese'), - cloathesAccessories: new Product('cloathesAccessories','fa-glasses'), cookie: new Product('cookie', 'fa-cookie'), dictionary: new Product('dictionary', 'fa-language'), dogAccessories: new Product('dogAccessories','fa-dog'), drinks: new Product('drinks', 'fa-glass-whiskey'), - drone:new Product('drone','fa-plane'), + drone: new Product('drone','fa-plane'), + drum: new Product('drum', 'fa-drum'), + envelope: new Product('envelope', 'fa-envelope'), egg: new Product('egg','fa-egg'), electronicAccessories: new Product('electronicAccessories','fa-bolt'), eraser: new Product('eraser','fa-eraser'), extinguisher: new Product('extinguisher','fa-fire'), firstAid: new Product('firstAid','fa-first-aid'), fish: new Product('fish','fa-fish'), + gamepad: new Product('gamepad', 'fa-gamepad'), + giftWrapping: new Product('giftWrapping', 'fa-gift'), glassAccessories: new Product('glassAccessories','fa-wine-glass'), gps: new Product('gps','fa-street-view'), + guitar: new Product('guitar','fa-guitar'), hamburger: new Product('hamburger', 'fa-hamburger'), + hammer: new Product('hammer', 'fa-hammer'), + halloweenAccessories: new Product('halloweenAccessories', 'fa-ghost'), hauntingAccessories: new Product('hauntingAccessories','fa-binoculars'), + headphones: new Product('headphones','fa-headphones'), highlighter: new Product('highlighter','fa-highlighter'), - hotdog: new Product('hotdog','fa-hotdog'), homeSecurity: new Product('homeSecurity','fa-key'), + hotdog: new Product('hotdog','fa-hotdog'), icecream: new Product('icecream','fa-ice-cream'), insecticide: new Product('insecticide','fa-spider'), jewelry: new Product('jewelry','fa-gem'), @@ -78,32 +98,52 @@ class Product { kitchenSupplies: new Product('kitchenSupplies', 'fa-blender'), laptop: new Product('laptop', 'fa-laptop'), lemon: new Product('lemon','fa-lemon'), + lightbulb: new Product('lightbulb', 'fa-lightbulb'), + microphone: new Product('microphone', 'fa-microphone'), + mask: new Product('mask', 'fa-head-side-mask'), + monitor: new Product('monitor', 'fa-desktop'), movingAccessories: new Product('movingAccessories','fa-boxes'), newbornAccessorries: new Product('newbornAccessorries','fa-baby-carriage'), newspaper: new Product('newspaper','fa-newspaper'), paintBrush: new Product('paintBrush','fa-paint-brush'), + paintRoller: new Product('paintRoller', 'fa-paint-roller'), paper: new Product('paper','fa-paperclip'), partyAccessories: new Product('partyAccessories','fa-glass-cheers'), + pen: new Product('pen','fa-pen'), pepper: new Product('pepper','fa-pepper-hot'), + personalSafetyAccessories: new Product('personalSafetyAccessories','fa-fingerprint'), + piggyBank: new Product('piggyBank', 'fa-piggy-bank'), pills: new Product('pills','fa-pills'), pizza: new Product('pizza','fa-pizza-slice'), plants: new Product('plants','fa-seedling'), printer: new Product('printer','fa-print'), - pen: new Product('pen','fa-pen'), - personalSafetyAccessories: new Product('personalSafetyAccessories','fa-fingerprint'), + puzzle: new Product('puzzle', 'fa-puzzle-piece'), religionAccessories: new Product('religionAccessories','fa-pray'), + ruler: new Product('ruler', 'fa-ruler'), runningAccessories: new Product('runningAccessories','fa-running'), + sanitizer: new Product('sanitizer', 'fa-spray-can'), + scissors: new Product('scissors', 'fa-cut'), + seeds: new Product('seeds', 'fa-seedling'), skatingAccessories: new Product('skatingAccessories','fa-skating'), skiingAccessories: new Product('skiingAccessories','fa-skiing'), soap: new Product('soap','fa-pump-soap'), spaAccessories: new Product('spaAccessories','fa-spa'), sportCloathes: new Product('sportCloathes','fa-futbol'), + stamp: new Product('stamp', 'fa-stamp'), + suitcase: new Product('suitcase', 'fa-suitcase-rolling'), summerHoliday: new Product('summerHoliday','fa-umbrella-beach'), sunscreen: new Product('sunscreen','fa-sun'), swimmingAccessories: new Product('swimmingAccessories','fa-swimmer'), + thermometer: new Product('thermometer', 'fa-thermometer'), toiletSupplies: new Product('toiletSupplies','fa-toilet-paper'), tools: new Product('tools','fa-wrench'), + toothpaste: new Product('toothpaste', 'fa-tooth'), toys: new Product('toys','fa-horse'), + trashBin: new Product('trashBin', 'fa-trash'), + tv: new Product('tv', 'fa-tv'), + umbrella: new Product('umbrella', 'fa-umbrella'), + vinyl: new Product('vinyl', 'fa-record-vinyl'), + volleyballBall: new Product('volleyballBall', 'fa-volleyball-ball'), wine: new Product('wine','fa-wine-bottle'), winterCloathes: new Product('winterCloathes','fa-mitten'), winterHoliday: new Product('winterHoliday','fa-tree') From 84ef4a52902abbbbc8770b16f47a8c07b0dab6af Mon Sep 17 00:00:00 2001 From: Marcin Czerniak Date: Sun, 20 Jun 2021 00:25:32 +0200 Subject: [PATCH 2/5] chore: Introduction to agent resetting --- src/configuration.js | 1 + src/logic/agent.js | 9 +++++++++ src/view/agentController.js | 24 +++++++++++++++++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/configuration.js b/src/configuration.js index 9cdc0aa..f78287f 100644 --- a/src/configuration.js +++ b/src/configuration.js @@ -9,3 +9,4 @@ const UnitsCount = ((ColumnsOfGroupsCount * RowsOfGroupsCount) * UnitsInGroupCou const AgentMoveSpeed = 60 /* 1 - slowest, 89 - fastest */ const AgentRotationSpeed = 60 /* 1 - slowest, 89 - fastest */ const AgentWaitTime = 500 /* in miliseconds */ +const AgentStartPosition = { x: 6, y: 0 } diff --git a/src/logic/agent.js b/src/logic/agent.js index 260d520..6e06873 100644 --- a/src/logic/agent.js +++ b/src/logic/agent.js @@ -57,4 +57,13 @@ class Agent extends AgentController { this.ownedProductAmount = amount; this.ownedProduct = product; } + + /** + * Cancel all agent actions, teleport to start position + */ + reset() { + this.cancelAllActions(); + + this.position = AgentStartPosition; + } } \ No newline at end of file diff --git a/src/view/agentController.js b/src/view/agentController.js index 23afc88..e3fda06 100644 --- a/src/view/agentController.js +++ b/src/view/agentController.js @@ -16,7 +16,7 @@ class AgentController { this.currentAction = this.actions.STATIONARY; // Pozycja i rotacja - this.position = { x: 6, y: 0 }; + this.position = AgentStartPosition; this.rotation = { z: 0 }; this.update(); } @@ -95,6 +95,8 @@ class AgentController { return new Promise((resolve, reject) => { const cycle = () => { + if (this.currentAction == this.actions.STATIONARY) return resolve(); + let { speed } = this; speed *= (actionCost - 1) * 4 + 1; @@ -259,13 +261,17 @@ class AgentController { } findPathTo(dx, dy, sx, sy) { - if (Grid.instance.getGrid()[dx][dy] == GRID_FIELD_TYPE.SHELF || Grid.instance.getGrid()[dx][dy] == GRID_FIELD_TYPE.STORAGE) { + const position = { x: sx, y: sy }; + const rotation = this.rotation.z; + + if (Grid.instance.getGrid()[dx][dy] == GRID_FIELD_TYPE.SHELF || + Grid.instance.getGrid()[dx][dy] == GRID_FIELD_TYPE.STORAGE) { if (Grid.instance.getGrid()[dx][dy - 1] == GRID_FIELD_TYPE.PATH) { - return Pathfinding.search({ position: { x: sx, y: sy }, rotation: this.rotation.z }, { position: { x: dx, y: dy - 1 }, rotation: 180 }); + return Pathfinding.search({ position, rotation }, { position: { x: dx, y: dy - 1 }, rotation: 180 }); } - return Pathfinding.search({ position: { x: sx, y: sy }, rotation: this.rotation.z }, { position: { x: dx, y: dy + 1 }, rotation: 0 }); + return Pathfinding.search({ position, rotation }, { position: { x: dx, y: dy + 1 }, rotation: 0 }); } - return Pathfinding.search({ position: { x: sx, y: sy }, rotation: this.rotation.z }, { position: { x: dx, y: dy }, rotation: this.rotation.z }); + return Pathfinding.search({ position, rotation }, { position: { x: dx, y: dy }, rotation }); } clearCanvas() { @@ -288,4 +294,12 @@ class AgentController { this.ctx.closePath(); this.ctx.stroke(); } + + cancelAllActions() { + this.ownedProduct = Product.REGISTRY.empty; + this.ownedProductAmount = 0; + this.currentPath = []; + this.currentAction = this.actions.STATIONARY; + this.currentPathIndex = 0; + } } \ No newline at end of file From 59945fb8dee604d701a808b08fcb8de0560d8ed6 Mon Sep 17 00:00:00 2001 From: s452693 Date: Sun, 20 Jun 2021 16:56:42 +0200 Subject: [PATCH 3/5] neural_networks --- src/cyfry/1.png | Bin 0 -> 246 bytes src/cyfry/2.png | Bin 0 -> 381 bytes src/cyfry/3.png | Bin 0 -> 577 bytes src/cyfry/4.png | Bin 0 -> 455 bytes src/cyfry/5.png | Bin 0 -> 367 bytes src/cyfry/6.png | Bin 0 -> 346 bytes src/cyfry/7.png | Bin 0 -> 337 bytes src/cyfry/8.png | Bin 0 -> 619 bytes src/cyfry/9.png | Bin 0 -> 541 bytes src/neural_network.py | 150 ++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 150 insertions(+) create mode 100644 src/cyfry/1.png create mode 100644 src/cyfry/2.png create mode 100644 src/cyfry/3.png create mode 100644 src/cyfry/4.png create mode 100644 src/cyfry/5.png create mode 100644 src/cyfry/6.png create mode 100644 src/cyfry/7.png create mode 100644 src/cyfry/8.png create mode 100644 src/cyfry/9.png create mode 100644 src/neural_network.py diff --git a/src/cyfry/1.png b/src/cyfry/1.png new file mode 100644 index 0000000000000000000000000000000000000000..ef3fe8a2ec010d1dfded7ef5449e9f996b025b32 GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1enu-ntcF~r0B?X=Up42m2siP{@jqBpR3Zw!jw z)cjW^rd-+hSc>pHR}0?*j8{LqnHAmG*((s!7rkL?nqb@QrK_}hHr^FoHf70_q?z&= zd^5HFKMY#7_CuEQ?O*-Vj9MOO_Xi)Bn0A(#``f*x*RpQfTIOXWY{buiN oFX^7Oj5cA9T{ykqWs-~D&oYxoXBzA00-eR+>FVdQ&MBb@06QgHfB*mh literal 0 HcmV?d00001 diff --git a/src/cyfry/2.png b/src/cyfry/2.png new file mode 100644 index 0000000000000000000000000000000000000000..98f8b7f51d4bb05594db2185694bb1fed9090114 GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1engOI0-V~B_M+i4dCn-zH477AN5nY!QuCY zW8DL`U5rn+d&&p&FrItuyx-cd`Gq=*%WIowj&UV5J@-Y+V$;`bz29WP`Q$^_w%m!y z;h~~eYaDv2Vy-K2EiG?~P!>(sZ1c}3TFtBcY{R;2D{beAr4d`&m!1?$s{GOEJke*G zz^2s5GrQJ>C{Nb8v&~nR`Q)KQi8Cg?BAN$ut~RyG)m6S*^e*vLfRUDB%43UVysFN& zq91LGYVYr^oVQY~H`?i3?`DQ%HmrYJua_>B&C}x%tX~})_cO?_Qa#4G+iR;BT zwdpb~e+uqJ9KNGC?Z}Qc&az{UFTU^p+adkogM^{s{*<2Erzopr078wIY5)KL literal 0 HcmV?d00001 diff --git a/src/cyfry/3.png b/src/cyfry/3.png new file mode 100644 index 0000000000000000000000000000000000000000..0b3fa344692486d71f493bf80a90eaab0fd3ec82 GIT binary patch literal 577 zcmV-H0>1r;P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!T6%Mz(nN-P!&IwBk+VNe#VYPI@VEWBVu3Wb7HCW$Ag1B}_c~A6K*yHXM zCX-3(mE#lQH;&5}7D^k9hAYOGH;&$3<2d{AHK#%v3oc*(h5NGEtglZ;hOjy0zUZ=w z$K!OC8div)lv}^x8V9Few)_Y~Yh8LeonWPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!TamC=Tl;PIB~6k9s;a_>A5_7*uF+$MrIWeM zA!)Ateh=5{6*JRt5nR&An*~W3f5cQ(g&+t9pT=gvFbvTH5Cj2^$0OYDcg&1o7QEeV z;5g1NGYkXDvcxX{nx=uaZNW56%uImeG2(K$JZF&AbX~{YbXJ#CQ54wib{KtQ+ctW1 zzHl8u%0l~rBuUU;d*J&%c%Fw@M)0Jo_*-_C>yOJEF5xY>2u;(_qr*+`a5%vEe8z|l x7eOM{zk4v60lRe-d7gLuU5XJKFMjF+JOCLVmvVHoW3vDN002ovPDHLkV1j33yRiTO literal 0 HcmV?d00001 diff --git a/src/cyfry/5.png b/src/cyfry/5.png new file mode 100644 index 0000000000000000000000000000000000000000..107cfd03aac17176bb7b05cd2c2282c2b778a01b GIT binary patch literal 367 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1en1B<7NV~B_M+i4ehn-v7w7XErPd+`f4tFFmb zP1-vc^Ai5PP2_oKlc9Ia(dM`)(3g zULwsnwPc4#lJ2p>C6k0^1oeG>U3^5TR(k6i0a-EELXJZZJ{+8^-N&_hRhL)N0^dFp zEuGVoiZUx!7WZXU=v_Bx&zyB_-D{VXvjiNpeAoZ_sv;|Le)qgBm2CpNI)J?fM^?@bYh%MDGwtw66cc)I$ztaD0e0sxXIhARL7 literal 0 HcmV?d00001 diff --git a/src/cyfry/7.png b/src/cyfry/7.png new file mode 100644 index 0000000000000000000000000000000000000000..8262a0fce08516c47e545283e0478b2d1040e436 GIT binary patch literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1en@R_HJV~B_M+bORFT?|CrCa-niEOB5DS;w;U zg5$NBJO4%W|Gx3@^h`sQ6VE-0iX%PwKTZ6cyr(g1TB>L4^`(gtOP;fcofWLTKYd&7 zX`AzxK68JsXiKzMwMy%<$;rFPe$0*2B~zpe>T?)bJ~x&p7D%pO_4bu$`L0-e-NZLa zcj@z49~LD}?0KxQw%VyJ%$h?o>g|Et7aN(kFFek7r_C~b+mtO|cJOE>zFszc8t?Rl z*ZI!030fOSyS+J(BC(Zua^e*}r>V!9ttOlj`a5?4-Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!Thd*e!C$a5$u2@fd|_2`$UA zJDrYfJ06dAqtVcc&*!ro#}O*5)oRX7#^W)yzCp2H+G@3^mq&Xn_WM0tE*GltwA*dy z_xn_PQ7VBp&sH-=Ww}PhHif@OyW?XLgY$2nM|?* zU7(ng8il5m=FUR?;LdL7>nWGZ!R>aFW!&y!d7)aZ$~rO_3}Cn0$#yX#YBfOO09;B_ z;D*9*!(|Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!T72H$NzAG#Zb7wOWl@c2Dn}`NUK~X!w}KaoMc&S#o*V(UBDq*Dmo!pNr4Z4TcDr2~!J{QaIBCD% zf0V0UC!#Hs5r$z&t|NTwv`EvGO8WethY&>(h)o+dn+;{&Ln*`qc03-#ZnuLZNhr(H zYPG1u!wOM0o6V>OAdV#}$q~B__`Xjy9_e4(`FsX(9OX||WHcIq*r=%na6BI2a=Adg zUWeQ5M%fDTk3+(0wJLpMTnHJB(1U%Y;(VhLPp{Y0e=?Du=B f>GRkByaB!ew6ck=U6d-`00000NkvXXu0mjf`%LJI literal 0 HcmV?d00001 diff --git a/src/neural_network.py b/src/neural_network.py new file mode 100644 index 0000000..a474cca --- /dev/null +++ b/src/neural_network.py @@ -0,0 +1,150 @@ + +from emnist import list_datasets +from emnist import extract_test_samples +from emnist import extract_training_samples +import numpy as np +import torch +from torch import nn +from torch import optim +import scipy.special +from matplotlib.pyplot import imshow +import glob +import imageio + +dig_train_images, dig_train_labels = extract_training_samples('digits') +dig_test_images, dig_test_labels = extract_test_samples('digits') +let_train_images, let_train_labels = extract_training_samples('letters') +let_test_images, let_test_labels = extract_test_samples('letters') +#print(dig_train_images.shape) + +#def plotdigit(image): +# img = np.reshape(image, (-1, 28)) +# imshow(img, cmap='Greys', vmin=0, vmax=255) +print(dig_train_images.shape) +""" +dig_train_images = dig_train_images / 255 +dig_test_images = dig_test_images / 255 +let_train_images = let_train_images / 255 +let_test_images = let_test_images / 255 + +dig_train_images = [torch.tensor(image, dtype=torch.float32) for image in dig_train_images] +""" +#print(dig_train_images[0]) +dig_train_images = dig_train_images.reshape(len(dig_train_images),28*28) +d_train = dig_train_images[:1000] +d_labels = dig_train_labels[:1000] + +dig_test_images = dig_test_images.reshape(len(dig_test_images),28*28) +d_test = dig_test_images[:600] +d_labelstest = dig_test_labels[:600] + +print(d_test.shape) +print(d_labelstest) +#print(dig_train_images[0]) +#print(dig_train_images.shape) + + +class NeuralNetwork: + def __init__(self, inputNodes, hiddenNodes, outputNodes, learningGrade): + self.inodes = inputNodes + self.hnodes = hiddenNodes + self.onodes = outputNodes + + self.weights = (np.random.rand(self.hnodes, self.inodes) - 0.5) + self.hidden = (np.random.rand(self.onodes, self.hnodes) - 0.5) + + #print( 'Matrix1 \n', self.weights) + #print( 'Matrix2 \n', self.hidden) + + self.lr = learningGrade + + self.activationFunction = lambda x: scipy.special.expit(x) + + pass + + def train(self, inputsList, targetsList): + + inputs = np.array(inputsList,ndmin=2).T + targets = np.array(targetsList,ndmin=2).T + + #forward pass + hiddenInputs = np.dot(self.weights, inputs) + 2 + hiddenOutputs = self.activationFunction(hiddenInputs) + + finalInputs = np.dot(self.hidden, hiddenOutputs) + 1 + finalOutputs = self.activationFunction(finalInputs) + + outputErrors = targets - finalOutputs + #print(outputErrors.shape) + x =self.weights.T + #print(x.shape) + hiddenErrors = np.dot(self.hidden.T, outputErrors) + + #print('OutputErrors', outputErrors.shape) + #print('finalOutputs',finalOutputs.shape) + #print(x.shape) + self.hidden += self.lr * np.dot((outputErrors * finalOutputs * (1.0 - finalOutputs)) , np.transpose(hiddenOutputs)) + self.weights += self.lr * np.dot((hiddenErrors * hiddenOutputs * (1.0 - hiddenOutputs)) , np.transpose(inputs)) + + + pass + + def query(self, inputsList): + + inputs = np.array(inputsList, ndmin=2).T + + + hiddenInputs = np.dot(self.weights, inputs) + hiddenOutputs = self.activationFunction(hiddenInputs) + + finalInputs = np.dot(self.hidden, hiddenOutputs) + finalOutputs = self.activationFunction(finalInputs) + + return finalOutputs + + + +""" + def getAccurancy(predictons,Y): + print(predictons,Y) + return np.sum(predictons=Y)/Y.size + + def getPredictions(A2): + return np.argmax(A2,0) +""" + + +#n = NeuralNetwork(inputNodes=3, hiddenNodes=5, outputNodes=2, learningGrade=0.2) +n = NeuralNetwork(inputNodes=784, hiddenNodes=200, outputNodes=10, learningGrade=0.1) + +def trainNetwork(n): + epochs = 10 + outputNodes = 10 + for e in range(epochs): + m=0 + print('Epoch', e+1) + + for record in d_train: + inputs = (np.asfarray(record[0:])/255 * 0.99) + 0.01 + #print(inputs.shape) + + targets = np.zeros(outputNodes) + 0.01 + targets[d_labels[m]] = 0.99 + #print(targets) + n.train(inputs,targets) + + m+=1 + pass + pass + + +trainNetwork(n) + +record = d_test[0] +#print('Label', d_labelstest[0]) +inputs = np.asfarray(record[0:])/ 255 * 0.99 + 0.01 +#print(n.query(inputs)) + + + + From 9ca08c7afbbf7f7b058a88b905310b36f3e5a7cf Mon Sep 17 00:00:00 2001 From: s452693 Date: Sun, 20 Jun 2021 17:59:01 +0200 Subject: [PATCH 4/5] neural_networks2 --- src/neural_network.py | 60 ++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/src/neural_network.py b/src/neural_network.py index a474cca..0a7f88d 100644 --- a/src/neural_network.py +++ b/src/neural_network.py @@ -15,20 +15,10 @@ dig_train_images, dig_train_labels = extract_training_samples('digits') dig_test_images, dig_test_labels = extract_test_samples('digits') let_train_images, let_train_labels = extract_training_samples('letters') let_test_images, let_test_labels = extract_test_samples('letters') -#print(dig_train_images.shape) -#def plotdigit(image): -# img = np.reshape(image, (-1, 28)) -# imshow(img, cmap='Greys', vmin=0, vmax=255) -print(dig_train_images.shape) -""" -dig_train_images = dig_train_images / 255 -dig_test_images = dig_test_images / 255 -let_train_images = let_train_images / 255 -let_test_images = let_test_images / 255 -dig_train_images = [torch.tensor(image, dtype=torch.float32) for image in dig_train_images] -""" + + #print(dig_train_images[0]) dig_train_images = dig_train_images.reshape(len(dig_train_images),28*28) d_train = dig_train_images[:1000] @@ -45,13 +35,16 @@ print(d_labelstest) class NeuralNetwork: - def __init__(self, inputNodes, hiddenNodes, outputNodes, learningGrade): + def __init__(self, inputNodes, hiddenNodes, outputNodes, learningGrade, fileWeight, fileHidden): self.inodes = inputNodes self.hnodes = hiddenNodes self.onodes = outputNodes - self.weights = (np.random.rand(self.hnodes, self.inodes) - 0.5) - self.hidden = (np.random.rand(self.onodes, self.hnodes) - 0.5) + """te pierwsze dwa użyj przy nauce, potem zostaw cały czas te 2""" + #self.weights = (np.random.rand(self.hnodes, self.inodes) - 0.5) + #self.hidden = (np.random.rand(self.onodes, self.hnodes) - 0.5) + self.weights = np.load(fileWeight) + self.hidden = np.load(fileHidden) #print( 'Matrix1 \n', self.weights) #print( 'Matrix2 \n', self.hidden) @@ -89,6 +82,10 @@ class NeuralNetwork: pass + def saveTraining(self, fileWeight, fileHidden): + np.save(fileWeight, self.weights) + np.save(fileHidden, self.hidden) + def query(self, inputsList): inputs = np.array(inputsList, ndmin=2).T @@ -102,29 +99,20 @@ class NeuralNetwork: return finalOutputs - - -""" - def getAccurancy(predictons,Y): - print(predictons,Y) - return np.sum(predictons=Y)/Y.size - - def getPredictions(A2): - return np.argmax(A2,0) -""" - -#n = NeuralNetwork(inputNodes=3, hiddenNodes=5, outputNodes=2, learningGrade=0.2) -n = NeuralNetwork(inputNodes=784, hiddenNodes=200, outputNodes=10, learningGrade=0.1) -def trainNetwork(n): +""" dodaj tablicę literek""" +#n = NeuralNetwork(inputNodes=3, hiddenNodes=5, outputNodes=2, learningGrade=0.2) +digitNetwork = NeuralNetwork(inputNodes=784, hiddenNodes=200, outputNodes=10, learningGrade=0.1, fileWeight="Dweights.npy", fileHidden="Dhidden.npy") + +def trainNetwork(n, fWeight, fHidden, trainingSamples): epochs = 10 outputNodes = 10 for e in range(epochs): m=0 print('Epoch', e+1) - for record in d_train: + for record in trainingSamples: inputs = (np.asfarray(record[0:])/255 * 0.99) + 0.01 #print(inputs.shape) @@ -136,15 +124,17 @@ def trainNetwork(n): m+=1 pass pass + n.saveTraining(fileWeight=fWeight, fileHidden=fHidden) -trainNetwork(n) -record = d_test[0] +##################################### ODPALANIE TRAINING +#trainNetwork(digitNetwork, "Dweights.npy", "Dhidden.npy", d_train) + +#record = d_test[0] #print('Label', d_labelstest[0]) -inputs = np.asfarray(record[0:])/ 255 * 0.99 + 0.01 +#inputs = np.asfarray(record[0:])/ 255 * 0.99 + 0.01 #print(n.query(inputs)) - - +#testing \ No newline at end of file From 4a1015fb5b6416e681d3a4ecee24e2d06526a302 Mon Sep 17 00:00:00 2001 From: Marcin Czerniak Date: Sun, 20 Jun 2021 19:53:17 +0200 Subject: [PATCH 5/5] chore: Priority quest pathfinding, orders window --- src/index.html | 25 +- src/logic/agent.js | 61 ++- src/logic/heap.js | 869 ++++++++++++++++++++++++++++++++++++ src/logic/pathfinding.js | 68 +-- src/logic/product.js | 3 - src/logic/shelf.js | 12 +- src/logic/time.js | 4 +- src/main.js | 3 +- src/styles.css | 108 +++++ src/view/agentController.js | 34 +- src/view/grid.js | 70 ++- src/view/ordersView.js | 101 +++++ 12 files changed, 1285 insertions(+), 73 deletions(-) create mode 100644 src/logic/heap.js create mode 100644 src/view/ordersView.js diff --git a/src/index.html b/src/index.html index 8def0ba..9571bf5 100644 --- a/src/index.html +++ b/src/index.html @@ -17,6 +17,7 @@ + @@ -26,6 +27,7 @@ + @@ -49,7 +51,9 @@
-
+
+ +
logo
@@ -301,5 +305,24 @@
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+ +
+ + +
+
+
diff --git a/src/logic/agent.js b/src/logic/agent.js index 9c4ed69..5ca2fa5 100644 --- a/src/logic/agent.js +++ b/src/logic/agent.js @@ -8,16 +8,21 @@ class Agent extends AgentController { Agent.instance = this; const cycle = async () => { - const jobRequest = Products.instance.getJobRequest(); - if (jobRequest) { - await this.takeFromStore(jobRequest.product, jobRequest.amount); - await this.deliver(jobRequest.x, jobRequest.y); - } else { - await waitFor(1000); + try { + const jobRequest = Products.instance.getJobRequest(); + if (jobRequest) { + await this.takeFromStore(jobRequest.product, jobRequest.amount); + await this.deliver(jobRequest.x, jobRequest.y); + } else { + await waitFor(1000); + } + + await waitFor(this.waitTime); + + cycle(); + } catch (e) { + console.log(e); } - - await waitFor(this.waitTime); - cycle(); }; setTimeout(() => cycle(), 2000); @@ -38,12 +43,16 @@ class Agent extends AgentController { * @param {number} y Współrzędna y */ async deliver(x, y) { - await this.moveTo(x, y); - await waitFor(this.waitTime); - Products.instance.exchange(x, y, this.ownedProduct, 50); + try { + await this.moveTo(x, y); + await this.waitFor(this.waitTime); + Products.instance.exchange(x, y, this.ownedProduct, 50); - this.ownedProductAmount = 0; - this.ownedProduct = null; + this.ownedProductAmount = 0; + this.ownedProduct = null; + } catch (e) { + throw e; + } } /** @@ -51,10 +60,26 @@ class Agent extends AgentController { * @param {*} product */ async takeFromStore(product, amount) { - await this.moveTo(9, 8); - await waitFor(this.waitTime); - this.ownedProductAmount = amount; - this.ownedProduct = product; + try { + await this.moveTo(8, 8); + await this.waitFor(this.waitTime); + this.ownedProductAmount = amount; + this.ownedProduct = product; + } catch (e) { + throw e; + } + } + + async deliverToOrders() { + try { + await this.moveTo(x, y); + await this.waitFor(this.waitTime); + + this.ownedProductAmount = 0; + this.ownedProduct = null; + } catch (e) { + throw e; + } } /** diff --git a/src/logic/heap.js b/src/logic/heap.js new file mode 100644 index 0000000..0b50bda --- /dev/null +++ b/src/logic/heap.js @@ -0,0 +1,869 @@ +/** + * Heap + * @type {Class} + */ +var Heap = /** @class */ (function () { + /** + * Heap instance constructor. + * @param {Function} compare Optional comparison function, defaults to Heap.minComparator + */ + function Heap(compare) { + var _this = this; + if (compare === void 0) { compare = Heap.minComparator; } + this.compare = compare; + this.heapArray = []; + this._limit = 0; + /** + * Alias of add + */ + this.offer = this.add; + /** + * Alias of peek + */ + this.element = this.peek; + /** + * Alias of pop + */ + this.poll = this.pop; + /** + * Returns the inverse to the comparison function. + * @return {Function} + */ + this._invertedCompare = function (a, b) { + return -1 * _this.compare(a, b); + }; + } + /* + Static methods + */ + /** + * Gets children indices for given index. + * @param {Number} idx Parent index + * @return {Array(Number)} Array of children indices + */ + Heap.getChildrenIndexOf = function (idx) { + return [idx * 2 + 1, idx * 2 + 2]; + }; + /** + * Gets parent index for given index. + * @param {Number} idx Children index + * @return {Number | undefined} Parent index, -1 if idx is 0 + */ + Heap.getParentIndexOf = function (idx) { + if (idx <= 0) { + return -1; + } + var whichChildren = idx % 2 ? 1 : 2; + return Math.floor((idx - whichChildren) / 2); + }; + /** + * Gets sibling index for given index. + * @param {Number} idx Children index + * @return {Number | undefined} Sibling index, -1 if idx is 0 + */ + Heap.getSiblingIndexOf = function (idx) { + if (idx <= 0) { + return -1; + } + var whichChildren = idx % 2 ? 1 : -1; + return idx + whichChildren; + }; + /** + * Min heap comparison function, default. + * @param {any} a First element + * @param {any} b Second element + * @return {Number} 0 if they're equal, positive if `a` goes up, negative if `b` goes up + */ + Heap.minComparator = function (a, b) { + if (a > b) { + return 1; + } + else if (a < b) { + return -1; + } + else { + return 0; + } + }; + /** + * Max heap comparison function. + * @param {any} a First element + * @param {any} b Second element + * @return {Number} 0 if they're equal, positive if `a` goes up, negative if `b` goes up + */ + Heap.maxComparator = function (a, b) { + if (b > a) { + return 1; + } + else if (b < a) { + return -1; + } + else { + return 0; + } + }; + /** + * Min number heap comparison function, default. + * @param {Number} a First element + * @param {Number} b Second element + * @return {Number} 0 if they're equal, positive if `a` goes up, negative if `b` goes up + */ + Heap.minComparatorNumber = function (a, b) { + return a - b; + }; + /** + * Max number heap comparison function. + * @param {Number} a First element + * @param {Number} b Second element + * @return {Number} 0 if they're equal, positive if `a` goes up, negative if `b` goes up + */ + Heap.maxComparatorNumber = function (a, b) { + return b - a; + }; + /** + * Default equality function. + * @param {any} a First element + * @param {any} b Second element + * @return {Boolean} True if equal, false otherwise + */ + Heap.defaultIsEqual = function (a, b) { + return a === b; + }; + /** + * Prints a heap. + * @param {Heap} heap Heap to be printed + * @returns {String} + */ + Heap.print = function (heap) { + function deep(i) { + var pi = Heap.getParentIndexOf(i); + return Math.floor(Math.log2(pi + 1)); + } + function repeat(str, times) { + var out = ''; + for (; times > 0; --times) { + out += str; + } + return out; + } + var node = 0; + var lines = []; + var maxLines = deep(heap.length - 1) + 2; + var maxLength = 0; + while (node < heap.length) { + var i = deep(node) + 1; + if (node === 0) { + i = 0; + } + // Text representation + var nodeText = String(heap.get(node)); + if (nodeText.length > maxLength) { + maxLength = nodeText.length; + } + // Add to line + lines[i] = lines[i] || []; + lines[i].push(nodeText); + node += 1; + } + return lines + .map(function (line, i) { + var times = Math.pow(2, maxLines - i) - 1; + return (repeat(' ', Math.floor(times / 2) * maxLength) + + line + .map(function (el) { + // centered + var half = (maxLength - el.length) / 2; + return repeat(' ', Math.ceil(half)) + el + repeat(' ', Math.floor(half)); + }) + .join(repeat(' ', times * maxLength))); + }) + .join('\n'); + }; + /* + Python style + */ + /** + * Converts an array into an array-heap, in place + * @param {Array} arr Array to be modified + * @param {Function} compare Optional compare function + * @return {Heap} For convenience, it returns a Heap instance + */ + Heap.heapify = function (arr, compare) { + var heap = new Heap(compare); + heap.heapArray = arr; + heap.init(); + return heap; + }; + /** + * Extract the peek of an array-heap + * @param {Array} heapArr Array to be modified, should be a heap + * @param {Function} compare Optional compare function + * @return {any} Returns the extracted peek + */ + Heap.heappop = function (heapArr, compare) { + var heap = new Heap(compare); + heap.heapArray = heapArr; + return heap.pop(); + }; + /** + * Pushes a item into an array-heap + * @param {Array} heapArr Array to be modified, should be a heap + * @param {any} item Item to push + * @param {Function} compare Optional compare function + */ + Heap.heappush = function (heapArr, item, compare) { + var heap = new Heap(compare); + heap.heapArray = heapArr; + heap.push(item); + }; + /** + * Push followed by pop, faster + * @param {Array} heapArr Array to be modified, should be a heap + * @param {any} item Item to push + * @param {Function} compare Optional compare function + * @return {any} Returns the extracted peek + */ + Heap.heappushpop = function (heapArr, item, compare) { + var heap = new Heap(compare); + heap.heapArray = heapArr; + return heap.pushpop(item); + }; + /** + * Replace peek with item + * @param {Array} heapArr Array to be modified, should be a heap + * @param {any} item Item as replacement + * @param {Function} compare Optional compare function + * @return {any} Returns the extracted peek + */ + Heap.heapreplace = function (heapArr, item, compare) { + var heap = new Heap(compare); + heap.heapArray = heapArr; + return heap.replace(item); + }; + /** + * Return the `n` most valuable elements of a heap-like Array + * @param {Array} heapArr Array, should be an array-heap + * @param {number} n Max number of elements + * @param {Function} compare Optional compare function + * @return {any} Elements + */ + Heap.heaptop = function (heapArr, n, compare) { + if (n === void 0) { n = 1; } + var heap = new Heap(compare); + heap.heapArray = heapArr; + return heap.top(n); + }; + /** + * Return the `n` least valuable elements of a heap-like Array + * @param {Array} heapArr Array, should be an array-heap + * @param {number} n Max number of elements + * @param {Function} compare Optional compare function + * @return {any} Elements + */ + Heap.heapbottom = function (heapArr, n, compare) { + if (n === void 0) { n = 1; } + var heap = new Heap(compare); + heap.heapArray = heapArr; + return heap.bottom(n); + }; + /** + * Return the `n` most valuable elements of an iterable + * @param {number} n Max number of elements + * @param {Iterable} Iterable Iterable list of elements + * @param {Function} compare Optional compare function + * @return {any} Elements + */ + Heap.nlargest = function (n, iterable, compare) { + var heap = new Heap(compare); + heap.heapArray = __spreadArrays(iterable); + heap.init(); + return heap.top(n); + }; + /** + * Return the `n` least valuable elements of an iterable + * @param {number} n Max number of elements + * @param {Iterable} Iterable Iterable list of elements + * @param {Function} compare Optional compare function + * @return {any} Elements + */ + Heap.nsmallest = function (n, iterable, compare) { + var heap = new Heap(compare); + heap.heapArray = __spreadArrays(iterable); + heap.init(); + return heap.bottom(n); + }; + /* + Instance methods + */ + /** + * Adds an element to the heap. Aliases: `offer`. + * Same as: push(element) + * @param {any} element Element to be added + * @return {Boolean} true + */ + Heap.prototype.add = function (element) { + this._sortNodeUp(this.heapArray.push(element) - 1); + this._applyLimit(); + return true; + }; + /** + * Adds an array of elements to the heap. + * Similar as: push(element, element, ...). + * @param {Array} elements Elements to be added + * @return {Boolean} true + */ + Heap.prototype.addAll = function (elements) { + var _a; + var i = this.length; + (_a = this.heapArray).push.apply(_a, elements); + for (var l = this.length; i < l; ++i) { + this._sortNodeUp(i); + } + this._applyLimit(); + return true; + }; + /** + * Return the bottom (lowest value) N elements of the heap. + * + * @param {Number} n Number of elements. + * @return {Array} Array of length <= N. + */ + Heap.prototype.bottom = function (n) { + if (n === void 0) { n = 1; } + if (this.heapArray.length === 0 || n <= 0) { + // Nothing to do + return []; + } + else if (this.heapArray.length === 1) { + // Just the peek + return [this.heapArray[0]]; + } + else if (n >= this.heapArray.length) { + // The whole heap + return __spreadArrays(this.heapArray); + } + else { + // Some elements + var result = this._bottomN_push(~~n); + return result; + } + }; + /** + * Check if the heap is sorted, useful for testing purposes. + * @return {Undefined | Element} Returns an element if something wrong is found, otherwise it's undefined + */ + Heap.prototype.check = function () { + var _this = this; + return this.heapArray.find(function (el, j) { return !!_this.getChildrenOf(j).find(function (ch) { return _this.compare(el, ch) > 0; }); }); + }; + /** + * Remove all of the elements from this heap. + */ + Heap.prototype.clear = function () { + this.heapArray = []; + }; + /** + * Clone this heap + * @return {Heap} + */ + Heap.prototype.clone = function () { + var cloned = new Heap(this.comparator()); + cloned.heapArray = this.toArray(); + cloned._limit = this._limit; + return cloned; + }; + /** + * Returns the comparison function. + * @return {Function} + */ + Heap.prototype.comparator = function () { + return this.compare; + }; + /** + * Returns true if this queue contains the specified element. + * @param {any} o Element to be found + * @param {Function} fn Optional comparison function, receives (element, needle) + * @return {Boolean} + */ + Heap.prototype.contains = function (o, fn) { + if (fn === void 0) { fn = Heap.defaultIsEqual; } + return this.heapArray.findIndex(function (el) { return fn(el, o); }) >= 0; + }; + /** + * Initialise a heap, sorting nodes + * @param {Array} array Optional initial state array + */ + Heap.prototype.init = function (array) { + if (array) { + this.heapArray = __spreadArrays(array); + } + for (var i = Math.floor(this.heapArray.length); i >= 0; --i) { + this._sortNodeDown(i); + } + this._applyLimit(); + }; + /** + * Test if the heap has no elements. + * @return {Boolean} True if no elements on the heap + */ + Heap.prototype.isEmpty = function () { + return this.length === 0; + }; + /** + * Get the leafs of the tree (no children nodes) + */ + Heap.prototype.leafs = function () { + if (this.heapArray.length === 0) { + return []; + } + var pi = Heap.getParentIndexOf(this.heapArray.length - 1); + return this.heapArray.slice(pi + 1); + }; + Object.defineProperty(Heap.prototype, "length", { + /** + * Length of the heap. + * @return {Number} + */ + get: function () { + return this.heapArray.length; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Heap.prototype, "limit", { + /** + * Get length limit of the heap. + * @return {Number} + */ + get: function () { + return this._limit; + }, + /** + * Set length limit of the heap. + * @return {Number} + */ + set: function (_l) { + this._limit = ~~_l; + this._applyLimit(); + }, + enumerable: false, + configurable: true + }); + /** + * Top node. Aliases: `element`. + * Same as: `top(1)[0]` + * @return {any} Top node + */ + Heap.prototype.peek = function () { + return this.heapArray[0]; + }; + /** + * Extract the top node (root). Aliases: `poll`. + * @return {any} Extracted top node, undefined if empty + */ + Heap.prototype.pop = function () { + var last = this.heapArray.pop(); + if (this.length > 0 && last !== undefined) { + return this.replace(last); + } + return last; + }; + /** + * Pushes element(s) to the heap. + * @param {...any} elements Elements to insert + * @return {Boolean} True if elements are present + */ + Heap.prototype.push = function () { + var elements = []; + for (var _i = 0; _i < arguments.length; _i++) { + elements[_i] = arguments[_i]; + } + if (elements.length < 1) { + return false; + } + else if (elements.length === 1) { + return this.add(elements[0]); + } + else { + return this.addAll(elements); + } + }; + /** + * Same as push & pop in sequence, but faster + * @param {any} element Element to insert + * @return {any} Extracted top node + */ + Heap.prototype.pushpop = function (element) { + var _a; + if (this.compare(this.heapArray[0], element) < 0) { + _a = [this.heapArray[0], element], element = _a[0], this.heapArray[0] = _a[1]; + this._sortNodeDown(0); + } + return element; + }; + /** + * Remove an element from the heap. + * @param {any} o Element to be found + * @param {Function} fn Optional function to compare + * @return {Boolean} True if the heap was modified + */ + Heap.prototype.remove = function (o, fn) { + if (fn === void 0) { fn = Heap.defaultIsEqual; } + if (this.length > 0) { + if (o === undefined) { + this.pop(); + return true; + } + else { + var idx = this.heapArray.findIndex(function (el) { return fn(el, o); }); + if (idx >= 0) { + if (idx === 0) { + this.pop(); + } + else if (idx === this.length - 1) { + this.heapArray.pop(); + } + else { + this.heapArray.splice(idx, 1, this.heapArray.pop()); + this._sortNodeUp(idx); + this._sortNodeDown(idx); + } + return true; + } + } + } + return false; + }; + /** + * Pop the current peek value, and add the new item. + * @param {any} element Element to replace peek + * @return {any} Old peek + */ + Heap.prototype.replace = function (element) { + var peek = this.heapArray[0]; + this.heapArray[0] = element; + this._sortNodeDown(0); + return peek; + }; + /** + * Size of the heap + * @return {Number} + */ + Heap.prototype.size = function () { + return this.length; + }; + /** + * Return the top (highest value) N elements of the heap. + * + * @param {Number} n Number of elements. + * @return {Array} Array of length <= N. + */ + Heap.prototype.top = function (n) { + if (n === void 0) { n = 1; } + if (this.heapArray.length === 0 || n <= 0) { + // Nothing to do + return []; + } + else if (this.heapArray.length === 1 || n === 1) { + // Just the peek + return [this.heapArray[0]]; + } + else if (n >= this.heapArray.length) { + // The whole peek + return __spreadArrays(this.heapArray); + } + else { + // Some elements + var result = this._topN_push(~~n); + return result; + } + }; + /** + * Clone the heap's internal array + * @return {Array} + */ + Heap.prototype.toArray = function () { + return __spreadArrays(this.heapArray); + }; + /** + * String output, call to Array.prototype.toString() + * @return {String} + */ + Heap.prototype.toString = function () { + return this.heapArray.toString(); + }; + /** + * Get the element at the given index. + * @param {Number} i Index to get + * @return {any} Element at that index + */ + Heap.prototype.get = function (i) { + return this.heapArray[i]; + }; + /** + * Get the elements of these node's children + * @param {Number} idx Node index + * @return {Array(any)} Children elements + */ + Heap.prototype.getChildrenOf = function (idx) { + var _this = this; + return Heap.getChildrenIndexOf(idx) + .map(function (i) { return _this.heapArray[i]; }) + .filter(function (e) { return e !== undefined; }); + }; + /** + * Get the element of this node's parent + * @param {Number} idx Node index + * @return {any} Parent element + */ + Heap.prototype.getParentOf = function (idx) { + var pi = Heap.getParentIndexOf(idx); + return this.heapArray[pi]; + }; + /** + * Iterator interface + */ + Heap.prototype[Symbol.iterator] = function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!this.length) return [3 /*break*/, 2]; + return [4 /*yield*/, this.pop()]; + case 1: + _a.sent(); + return [3 /*break*/, 0]; + case 2: return [2 /*return*/]; + } + }); + }; + /** + * Returns an iterator. To comply with Java interface. + */ + Heap.prototype.iterator = function () { + return this; + }; + /** + * Limit heap size if needed + */ + Heap.prototype._applyLimit = function () { + if (this._limit && this._limit < this.heapArray.length) { + var rm = this.heapArray.length - this._limit; + // It's much faster than splice + while (rm) { + this.heapArray.pop(); + --rm; + } + } + }; + /** + * Return the bottom (lowest value) N elements of the heap, without corner cases, unsorted + * + * @param {Number} n Number of elements. + * @return {Array} Array of length <= N. + */ + Heap.prototype._bottomN_push = function (n) { + // Use an inverted heap + var bottomHeap = new Heap(this.compare); + bottomHeap.limit = n; + bottomHeap.heapArray = this.heapArray.slice(-n); + bottomHeap.init(); + var startAt = this.heapArray.length - 1 - n; + var parentStartAt = Heap.getParentIndexOf(startAt); + var indices = []; + for (var i = startAt; i > parentStartAt; --i) { + indices.push(i); + } + var arr = this.heapArray; + while (indices.length) { + var i = indices.shift(); + if (this.compare(arr[i], bottomHeap.peek()) > 0) { + bottomHeap.replace(arr[i]); + if (i % 2) { + indices.push(Heap.getParentIndexOf(i)); + } + } + } + return bottomHeap.toArray(); + }; + /** + * Move a node to a new index, switching places + * @param {Number} j First node index + * @param {Number} k Another node index + */ + Heap.prototype._moveNode = function (j, k) { + var _a; + _a = [this.heapArray[k], this.heapArray[j]], this.heapArray[j] = _a[0], this.heapArray[k] = _a[1]; + }; + /** + * Move a node down the tree (to the leaves) to find a place where the heap is sorted. + * @param {Number} i Index of the node + */ + Heap.prototype._sortNodeDown = function (i) { + var _this = this; + var moveIt = i < this.heapArray.length - 1; + var self = this.heapArray[i]; + var getPotentialParent = function (best, j) { + if (_this.heapArray.length > j && _this.compare(_this.heapArray[j], _this.heapArray[best]) < 0) { + best = j; + } + return best; + }; + while (moveIt) { + var childrenIdx = Heap.getChildrenIndexOf(i); + var bestChildIndex = childrenIdx.reduce(getPotentialParent, childrenIdx[0]); + var bestChild = this.heapArray[bestChildIndex]; + if (typeof bestChild !== 'undefined' && this.compare(self, bestChild) > 0) { + this._moveNode(i, bestChildIndex); + i = bestChildIndex; + } + else { + moveIt = false; + } + } + }; + /** + * Move a node up the tree (to the root) to find a place where the heap is sorted. + * @param {Number} i Index of the node + */ + Heap.prototype._sortNodeUp = function (i) { + var moveIt = i > 0; + while (moveIt) { + var pi = Heap.getParentIndexOf(i); + if (pi >= 0 && this.compare(this.heapArray[pi], this.heapArray[i]) > 0) { + this._moveNode(i, pi); + i = pi; + } + else { + moveIt = false; + } + } + }; + /** + * Return the top (highest value) N elements of the heap, without corner cases, unsorted + * Implementation: push. + * + * @param {Number} n Number of elements. + * @return {Array} Array of length <= N. + */ + Heap.prototype._topN_push = function (n) { + // Use an inverted heap + var topHeap = new Heap(this._invertedCompare); + topHeap.limit = n; + var indices = [0]; + var arr = this.heapArray; + while (indices.length) { + var i = indices.shift(); + if (i < arr.length) { + if (topHeap.length < n) { + topHeap.push(arr[i]); + indices.push.apply(indices, Heap.getChildrenIndexOf(i)); + } + else if (this.compare(arr[i], topHeap.peek()) < 0) { + topHeap.replace(arr[i]); + indices.push.apply(indices, Heap.getChildrenIndexOf(i)); + } + } + } + return topHeap.toArray(); + }; + /** + * Return the top (highest value) N elements of the heap, without corner cases, unsorted + * Implementation: init + push. + * + * @param {Number} n Number of elements. + * @return {Array} Array of length <= N. + */ + Heap.prototype._topN_fill = function (n) { + // Use an inverted heap + var heapArray = this.heapArray; + var topHeap = new Heap(this._invertedCompare); + topHeap.limit = n; + topHeap.heapArray = heapArray.slice(0, n); + topHeap.init(); + var branch = Heap.getParentIndexOf(n - 1) + 1; + var indices = []; + for (var i = branch; i < n; ++i) { + indices.push.apply(indices, Heap.getChildrenIndexOf(i).filter(function (l) { return l < heapArray.length; })); + } + if ((n - 1) % 2) { + indices.push(n); + } + while (indices.length) { + var i = indices.shift(); + if (i < heapArray.length) { + if (this.compare(heapArray[i], topHeap.peek()) < 0) { + topHeap.replace(heapArray[i]); + indices.push.apply(indices, Heap.getChildrenIndexOf(i)); + } + } + } + return topHeap.toArray(); + }; + /** + * Return the top (highest value) N elements of the heap, without corner cases, unsorted + * Implementation: heap. + * + * @param {Number} n Number of elements. + * @return {Array} Array of length <= N. + */ + Heap.prototype._topN_heap = function (n) { + var topHeap = this.clone(); + var result = []; + for (var i = 0; i < n; ++i) { + result.push(topHeap.pop()); + } + return result; + }; + /** + * Return index of the top element + * @param list + */ + Heap.prototype._topIdxOf = function (list) { + if (!list.length) { + return -1; + } + var idx = 0; + var top = list[idx]; + for (var i = 1; i < list.length; ++i) { + var comp = this.compare(list[i], top); + if (comp < 0) { + idx = i; + top = list[i]; + } + } + return idx; + }; + /** + * Return the top element + * @param list + */ + Heap.prototype._topOf = function () { + var list = []; + for (var _i = 0; _i < arguments.length; _i++) { + list[_i] = arguments[_i]; + } + var heap = new Heap(this.compare); + heap.init(list); + return heap.peek(); + }; + /** + * Swap identical elements compared by comparator function + */ + Heap.prototype.swap = function(el, cmp) { + if (!cmp) { + cmp = Heap.defaultIsEqual; + } + this.remove(el, cmp); + this.push(el); + }; + /** + * Find element in heap + */ + Heap.prototype.getElement = function(o, cmp) { + if (!cmp) { + cmp = Heap.defaultIsEqual; + } + return this.heapArray.find(function (el) { return cmp(el, o); }); + }; + return Heap; +}()); diff --git a/src/logic/pathfinding.js b/src/logic/pathfinding.js index 817df29..6929827 100644 --- a/src/logic/pathfinding.js +++ b/src/logic/pathfinding.js @@ -10,13 +10,16 @@ const PATHFINDING_ACTION = Enum('ROTATE', 'MOVE') - class Pathfinding { static search(state, expectedState) { return Pathfinding.graphSearch({ state }, { state: expectedState }) } - static graphSearch(node, expectedNode, fringe = [], explored = []) { + static priorityComparator(a, b) { + return a.totalCost - b.totalCost; + } + + static graphSearch(node, expectedNode, fringe = new Heap(Pathfinding.priorityComparator), explored = []) { fringe.push(node); while(true) { @@ -24,44 +27,47 @@ class Pathfinding { return false; } - const elem = fringe.shift(); + const elem = fringe.pop(); - if (Pathfinding.reached(elem.state, expectedNode.state)) { + if (Pathfinding.isEqual(elem.state, expectedNode.state)) { return Pathfinding.buildPath(node, elem); } explored.push(elem); for (const successor of this.successor(elem)) { - if (!Pathfinding.isNodeInArr(successor, explored) && !Pathfinding.isNodeInArr(successor, fringe)) { - Pathfinding.insertWithPriority(successor, fringe); - } else if (Pathfinding.isNodeInArr(successor, fringe)) { - const index = Pathfinding.findIndexOf(successor, fringe); - if (successor.totalCost < fringe[index].totalCost) { - fringe.splice(index, 1, successor); - } + const isExplored = Pathfinding.isNodeInArr(successor, explored); + const elementFromFringe = fringe.getElement(successor, Pathfinding.isNodesEqual); + const isInFringe = !(elementFromFringe === undefined); + + if (!isExplored && !isInFringe) { + fringe.push(successor); + } else if (isInFringe && elementFromFringe.totalCost > successor.totalCost) { + fringe.swap(successor, Pathfinding.isNodesEqual); } } + + // debugger; } } static isNodeInArr(node, arr) { - return !arr.every(n => !Pathfinding.reached(n.state, node.state)) + return !arr.every(n => !Pathfinding.isEqual(n.state, node.state)) } - static findIndexOf(node, arr) { - return arr.findIndex(n => Pathfinding.reached(n.state, node.state)); - } + // static findIndexOf(node, arr) { + // return arr.findIndex(n => Pathfinding.isEqual(n.state, node.state)); + // } - static insertWithPriority(node, arr) { - for (const [i, n] of arr.entries()) { - if (node.totalCost < n.totalCost) { - arr.splice(i, 0, node); - return; - } - } - arr.push(node); - } + // static insertWithPriority(node, arr) { + // for (const [i, n] of arr.entries()) { + // if (node.totalCost < n.totalCost) { + // arr.splice(i, 0, node); + // return; + // } + // } + // arr.push(node); + // } static successor(node) { const list = []; @@ -105,7 +111,7 @@ class Pathfinding { const result = []; let currentElement = expectedNode; - while(!Pathfinding.reached(currentElement.state, node.state)) { + while(!Pathfinding.isEqual(currentElement.state, node.state)) { result.unshift(currentElement); currentElement = currentElement.parent; } @@ -113,12 +119,16 @@ class Pathfinding { return result; } - static getManhattanDistance(node, expectedNode) { - return Math.abs(node.state.position.x - expectedNode.state.position.x) + Math.abs(node.state.position.y - expectedNode.state.position.y); + // static getManhattanDistance(node, expectedNode) { + // return Math.abs(node.state.position.x - expectedNode.state.position.x) + Math.abs(node.state.position.y - expectedNode.state.position.y); + // } + + static isEqual(state, expectedState) { + return state.rotation == expectedState.rotation && state.position.x == expectedState.position.x && state.position.y == expectedState.position.y; } - static reached(state, expectedState) { - return state.rotation == expectedState.rotation && state.position.x == expectedState.position.x && state.position.y == expectedState.position.y; + static isNodesEqual(node, expectedNode) { + return Pathfinding.isEqual(node.state, expectedNode.state); } static getVectorFromRotation(rotation) { diff --git a/src/logic/product.js b/src/logic/product.js index a3f56f3..e8055a6 100644 --- a/src/logic/product.js +++ b/src/logic/product.js @@ -23,7 +23,6 @@ class Product { equals(other) { return this.name === other.name; } -<<<<<<< HEAD static get REGISTRY() { // in alphabetical order @@ -154,6 +153,4 @@ class Product { static RANDOM_FROM_REGISTRY() { return Product.REGISTRY[Object.keys(Product.REGISTRY).filter(p => p !== 'empty')[Math.floor(Math.random() * (Object.keys(Product.REGISTRY).length - 1))]]; } -======= ->>>>>>> 4bd5bbdc0a26639410a6634debaff60c8a484593 } \ No newline at end of file diff --git a/src/logic/shelf.js b/src/logic/shelf.js index e7ffbdf..4d0991f 100644 --- a/src/logic/shelf.js +++ b/src/logic/shelf.js @@ -1,10 +1,10 @@ const SHELF_TYPE = Object.freeze({ - FRIDGE_SHELF: 'FRIDGE_SHELF', - LARGE_SHELF: 'LARGE_SHELF', - BASKET_SHELF: 'BASKET_SHELF', - DISCOUNT_SHELF: 'DISCOUNT_SHELF', - STANDARD_SHELF: 'STANDARD_SHELF', - FREESTANDING_SHELF: 'FREESTANDING_SHELF', + FRIDGE_SHELF: 'lodowka', + LARGE_SHELF: 'gabarytowa', + BASKET_SHELF: 'kosze', + DISCOUNT_SHELF: 'przecena', + STANDARD_SHELF: 'standardowa', + FREESTANDING_SHELF: 'wolnostojaca', }); class Shelf { diff --git a/src/logic/time.js b/src/logic/time.js index 263baf2..dd497d2 100644 --- a/src/logic/time.js +++ b/src/logic/time.js @@ -60,11 +60,13 @@ class Time { async addDays(days) { await Products.instance.next(days); Products.instance.update(); - const ul = document.querySelector('ul#history'); this.setDay(this.day += Number(days)); + const ul = document.querySelector('ul#history'); const li = document.createElement('li'); li.innerHTML = `${this.day}: ${nice(Products.instance.max_similarity)}`; ul.appendChild(li); + + Agent.instance.reset(); } } \ No newline at end of file diff --git a/src/main.js b/src/main.js index fa24462..922f442 100644 --- a/src/main.js +++ b/src/main.js @@ -12,7 +12,8 @@ window.addEventListener('DOMContentLoaded', async () => { const timeController = new TimeController(); const floor = new Floor(floorCanvas); const grid = new Grid(gridCanvas); - const agent = new Agent(agentCanvas); + new Agent(agentCanvas); + new OrdersView(); await Knowledge.load() const products = new Products(productsCanvas); diff --git a/src/styles.css b/src/styles.css index d529899..ed881bb 100644 --- a/src/styles.css +++ b/src/styles.css @@ -28,6 +28,7 @@ main { width: 100%; top: 50%; transform: translateY(-50%); + z-index: 1; } /* ######################################## */ @@ -48,6 +49,10 @@ main { flex: 1; } +.header-line:first-of-type { + justify-content: flex-end; +} + .header-line fieldset { display: flex; gap: 5px; @@ -84,6 +89,21 @@ main { outline: 0; } +button { + background: transparent; + color: #3498db; + border: 1px solid #3498db; + border-radius: 5px; + padding: 10px 20px; + font-family: 'Montserrat', sans-serif; + font-size: 16px; + cursor: pointer; +} + +button:hover { + background-color: #0A0A0A; +} + .logs-label { margin: 0 20px 30px 10px; } @@ -169,3 +189,91 @@ main { #products i { font-size: 20px; } + +/* ######################################## */ +/* # Orders window styling # */ +/* ######################################## */ + +.orders-window { + position: absolute; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.8); + z-index: 2; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + display: none; +} + +.close::after { + position: absolute; + top: 0; + right: 0; + content: "\2716"; + font-size: 30px; + color: white; + line-height: 100px; + text-align: center; + cursor: pointer; + display: flex; + width: 60px; + height: 60px; + justify-content: center; + align-items: center; +} + +.orders-window canvas { + width: 100px; + height: 100px; + border: 1px solid black; + background-color: white; +} + +.line { + display: flex; +} + +.line.gaps > *:not(:first-child) { + margin-left: 10px; +} + +.line .incrementals div { + width: 50px; + height: 50px; + display: flex; + justify-content: center; + align-items: center; + font-size: 30px; +} + +.line .incrementals { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: -0.25em; +} + +.incrementals div { + border: 1px solid #3498db; + cursor: pointer; + border-radius: 5px; +} + +.incrementals div:hover { + border: 1px solid #217bb8; +} + +.response { + width: 100%; + flex-grow: 1; + display: flex; + align-items: center; + border-radius: 5px; + border: 1px solid #3498db; + background-color: black; +} \ No newline at end of file diff --git a/src/view/agentController.js b/src/view/agentController.js index 92a98c6..27e9b9c 100644 --- a/src/view/agentController.js +++ b/src/view/agentController.js @@ -1,11 +1,13 @@ class AgentController { constructor(canvas) { // Inicjalizacja + this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.setCanvasSize(canvas); this.ownedProduct = null; this.ownedProductAmount = 0; + this.isDestroyed = false; // Akcje this.actions = { @@ -59,10 +61,18 @@ class AgentController { if (nearestPoint) { if (nearestPoint.action == PATHFINDING_ACTION.MOVE) { - await this.moveInLine(nearestPoint.state.position, nearestPoint.actionCost); + try { + await this.moveInLine(nearestPoint.state.position, nearestPoint.actionCost); + } catch (e) { + return reject(); + } } if (nearestPoint.action == PATHFINDING_ACTION.ROTATE) { - await this.rotate({ z: nearestPoint.state.rotation }, nearestPoint.actionCost); + try { + await this.rotate({ z: nearestPoint.state.rotation }, nearestPoint.actionCost); + } catch (e) { + return reject(); + } } nearestPoint = this.currentPath[++this.currentPathIndex]; @@ -96,6 +106,7 @@ class AgentController { return new Promise((resolve, reject) => { const cycle = () => { if (this.currentAction == this.actions.STATIONARY) return resolve(); + if (this.isDestroyed) return reject(); let { speed } = this; speed *= (actionCost - 1) * 4 + 1; @@ -127,6 +138,11 @@ class AgentController { }); } + async waitFor() { + await waitFor(this.waitTime); + if (this.isDestroyed) throw new Error(); + } + /** * * @param {{ x: number, y: number }} position @@ -176,6 +192,8 @@ class AgentController { })(); const cycle = () => { + if (this.isDestroyed) return reject(); + this.currentAction = this.actions.IN_ROTATION; const oldZRotation = this.rotation.z; @@ -297,11 +315,13 @@ class AgentController { this.ctx.stroke(); } + destroy() { + this.isDestroyed = true; + this.update = () => {}; + } + cancelAllActions() { - this.ownedProduct = Product.REGISTRY.empty; - this.ownedProductAmount = 0; - this.currentPath = []; - this.currentAction = this.actions.STATIONARY; - this.currentPathIndex = 0; + Agent.instance.destroy(); + Agent.instance = new Agent(this.canvas); } } \ No newline at end of file diff --git a/src/view/grid.js b/src/view/grid.js index f90b7cd..6429919 100644 --- a/src/view/grid.js +++ b/src/view/grid.js @@ -1,7 +1,8 @@ const GRID_FIELD_TYPE = Object.freeze({ PATH: 'PATH', SHELF: 'SHELF', - STORAGE: 'STORAGE' + STORAGE: 'STORAGE', + ORDERS: 'ORDERS' }); class Grid { @@ -22,6 +23,7 @@ class Grid { this.drawCostMap(); this.drawShelfs(); this.drawStorages(); + this.drawOrders(); Grid.instance = this; } @@ -52,7 +54,7 @@ class Grid { [...fact(1), GRID_FIELD_TYPE.PATH, ...fact(2), GRID_FIELD_TYPE.PATH, ...fact(2), GRID_FIELD_TYPE.PATH] ); - const lastLine = [...fact(6), GRID_FIELD_TYPE.PATH, ...fact(6, GRID_FIELD_TYPE.STORAGE), GRID_FIELD_TYPE.PATH, ...fact(6)]; + const lastLine = [...fact(6), GRID_FIELD_TYPE.PATH, ...fact(3, GRID_FIELD_TYPE.STORAGE), ...fact(3, GRID_FIELD_TYPE.ORDERS), GRID_FIELD_TYPE.PATH, ...fact(6)]; for (let i = 0; i < 20; i++) { this.grid[i] = [...this.grid[i], lastLine[i]]; } @@ -128,6 +130,35 @@ class Grid { } } + drawOrders () { + let isFirstOfType = true; + let isLastOfType = false; + + let firstX; + for (let [x, line] of this.grid.entries()) { + for (let [y, type] of line.entries()) { + if (type === GRID_FIELD_TYPE.ORDERS) { + if (this.grid[x + 1] && this.grid[x + 1][y] !== GRID_FIELD_TYPE.ORDERS) { + isLastOfType = true; + } + + if (isFirstOfType) { + isFirstOfType = false; + firstX = x; + this.orders(x * 100, y * 100, 100, 100, true, false, true, true); + } else if (isLastOfType) { + isLastOfType = false; + isFirstOfType = true; + this.orders(x * 100, y * 100, 100, 100, true, true, true, false); + this.ordersLabel(firstX * 100, y * 100, (x - firstX + 1) * 100, 100); + } else { + this.orders(x * 100, y * 100, 100, 100, true, false, true, false); + } + } + } + } + } + storeLabel(x, y, w, h) { let fontSize = 40; this.ctx.font = `${fontSize}px Montserrat`; @@ -136,21 +167,46 @@ class Grid { this.ctx.fillText("STORE", x + (w/2), y + (h/2) + 15); } + ordersLabel(x, y, w, h) { + let fontSize = 40; + this.ctx.font = `${fontSize}px Montserrat`; + this.ctx.textAlign = "center"; + this.ctx.fillStyle = '#3498db'; + this.ctx.fillText("ORDERS", x + (w/2), y + (h/2) + 15); + } + shelf (shelf, x, y, w, h) { this.ctx.strokeStyle = '#ffffff'; this.ctx.lineWidth = 5; this.ctx.strokeRect(x, y, w, h); this.drawFixIfOnEdge(x, y, w, h); - var img = new Image(); - img.src = `img/shelves/${shelf.type}.svg`; - img.onload = () => { - this.ctx.drawImage(img, x, y, w, h); + const descriptors = Object.getOwnPropertyDescriptors(SHELF_TYPE); + let imageSource = null; + for (const key of Object.keys(descriptors)) { + if (descriptors[key].value === shelf.type) { + imageSource = key; + } + } + if (imageSource && shelf.type !== SHELF_TYPE.STANDARD_SHELF) { + var img = new Image(); + img.src = `img/shelves/${imageSource}.svg`; + img.onload = () => { + this.ctx.drawImage(img, x, y, w, h); + } } } storage (x, y, w, h, hasTop, hasRight, hasBottom, hasLeft) { - this.ctx.strokeStyle = '#ffff00'; + this.connectedSquare (x, y, w, h, hasTop, hasRight, hasBottom, hasLeft, '#ffff00'); + } + + orders (x, y, w, h, hasTop, hasRight, hasBottom, hasLeft) { + this.connectedSquare (x, y, w, h, hasTop, hasRight, hasBottom, hasLeft, '#3498db'); + } + + connectedSquare (x, y, w, h, hasTop, hasRight, hasBottom, hasLeft, color) { + this.ctx.strokeStyle = color; this.ctx.lineWidth = 5; if (hasTop) { this.ctx.beginPath(); diff --git a/src/view/ordersView.js b/src/view/ordersView.js new file mode 100644 index 0000000..a862dd9 --- /dev/null +++ b/src/view/ordersView.js @@ -0,0 +1,101 @@ +class OrdersView { + + constructor() { + OrdersView.instance = this; + + this.addMultipleCanvases(10); + } + + order() { + const formData = new FormData(); + Promise.all( + [...document.querySelectorAll('.orders-window .canvases canvas')].map((canv, index) => { + return new Promise((resolve, reject) => { + canv.toBlob(blob => { + formData.append(`file-${index}`, blob,`file-${index}.png`); + resolve(); + }); + }); + }) + ).then(async () => { + const response = await fetch('/api/neural', { + method: 'POST', + body: formData + }); + //const json = await response.json(); + console.log(await response.text()); + }); + } + + clear() { + [...document.querySelectorAll('.orders-window .canvases canvas')].forEach(canv => { + canv.getContext('2d').clearRect(0, 0, 100, 100); + }); + } + + openWindow() { + document.querySelector('.orders-window').style.display = 'flex'; + } + + closeWindow() { + document.querySelector('.orders-window').style.display = 'none'; + } + + addMultipleCanvases(amount) { + for (let i = 0; i < amount; i++) { + this.addCanvas(); + } + } + + addCanvas() { + const canv = document.createElement('canvas'); + this.initializeDrawingOnCanvas(canv); + document.querySelector('.orders-window .canvases').append(canv); + } + + removeCanvas() { + const c = document.querySelector('.orders-window .canvases'); + c.removeChild(c.lastChild); + } + + initializeDrawingOnCanvas(canvas) { + const ctx = canvas.getContext("2d"); + let coord = { x: 0, y: 0 }; + + document.addEventListener("mousedown", start); + document.addEventListener("mouseup", stop); + window.addEventListener("resize", resize); + + resize(); + + function resize() { + ctx.canvas.width = 100; + ctx.canvas.height = 100; + } + + function reposition(event) { + coord.x = event.clientX - canvas.offsetLeft; + coord.y = event.clientY - canvas.offsetTop; + } + + function start(event) { + document.addEventListener("mousemove", draw); + reposition(event); + } + + function stop() { + document.removeEventListener("mousemove", draw); + } + + function draw(event) { + ctx.beginPath(); + ctx.lineWidth = 5; + ctx.lineCap = "round"; + ctx.strokeStyle = "#000000"; + ctx.moveTo(coord.x, coord.y); + reposition(event); + ctx.lineTo(coord.x, coord.y); + ctx.stroke(); + } + } +} \ No newline at end of file