Late night addition of semantic networks
This commit is contained in:
parent
da5bcc30c7
commit
7c7a055a4a
@ -18,6 +18,10 @@
|
|||||||
<script src="modules/agentController.js"></script>
|
<script src="modules/agentController.js"></script>
|
||||||
<script src="modules/agent.js"></script>
|
<script src="modules/agent.js"></script>
|
||||||
<script src="modules/products.js"></script>
|
<script src="modules/products.js"></script>
|
||||||
|
<script src="modules/knowledge.js"></script>
|
||||||
|
<script src="modules/configuration.js"></script>
|
||||||
|
<script src="modules/utilities.js"></script>
|
||||||
|
<script src="modules/shop.js"></script>
|
||||||
|
|
||||||
<!-- Main script file -->
|
<!-- Main script file -->
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export const UnitsInGroupCount = 6
|
const UnitsInGroupCount = 6
|
||||||
export const RowsOfGroupsCount = 6
|
const RowsOfGroupsCount = 6
|
||||||
export const ColumnsOfGroupsCount = 3
|
const ColumnsOfGroupsCount = 3
|
||||||
export const StorageCenterLocation = { x: 7, y: 8, w: UnitsInGroupCount, h: 1 }
|
const StorageCenterLocation = { x: 7, y: 8, w: UnitsInGroupCount, h: 1 }
|
||||||
|
|
||||||
export const UnitsCount = ((ColumnsOfGroupsCount * RowsOfGroupsCount) * UnitsInGroupCount
|
const UnitsCount = ((ColumnsOfGroupsCount * RowsOfGroupsCount) * UnitsInGroupCount
|
||||||
- StorageCenterLocation.w * StorageCenterLocation.h)
|
- StorageCenterLocation.w * StorageCenterLocation.h)
|
||||||
|
106
src/modules/knowledge.js
Normal file
106
src/modules/knowledge.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
function flattenToUnique(array, view = x => x) {
|
||||||
|
return array.reduce((set, value) => {
|
||||||
|
const v = view(value)
|
||||||
|
console.log(v)
|
||||||
|
v && v.forEach(cat => set.add(cat))
|
||||||
|
return set
|
||||||
|
}, new Set())
|
||||||
|
}
|
||||||
|
|
||||||
|
class SemanticNetwork {
|
||||||
|
/**
|
||||||
|
* @param {string} definition
|
||||||
|
*/
|
||||||
|
constructor(definition) {
|
||||||
|
/**
|
||||||
|
* @param {string} stmt
|
||||||
|
* @returns {[{ name: string; categories: string[]; locations: string[] }]}
|
||||||
|
*/
|
||||||
|
function parseStatement(stmt) {
|
||||||
|
const [name, ...keywords] = stmt.split(':').map(x => x.trim())
|
||||||
|
const o = { name }
|
||||||
|
for (const keyword of keywords) {
|
||||||
|
const command = keyword[0]
|
||||||
|
const items = keyword.slice(1).split(',').map(x => x.trim()).filter(x => x.length > 0)
|
||||||
|
switch (command) {
|
||||||
|
case 'c': o.categories = items; break
|
||||||
|
case 'p': o.locations = items; break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = definition.split('\n').filter(x => x.trim().length > 0)
|
||||||
|
.map(parseStatement)
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllNames() {
|
||||||
|
return this.data.map(({ name }) => name)
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllCategories() {
|
||||||
|
return flattenToUnique(this.data, ({ categories }) => categories)
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllLocations() {
|
||||||
|
return flattenToUnique(this.data, ({ locations }) => locations)
|
||||||
|
}
|
||||||
|
|
||||||
|
findByName(nameToFind) {
|
||||||
|
return this.data.find(({ name }) => name === nameToFind)
|
||||||
|
}
|
||||||
|
|
||||||
|
findAllByCategory(categoryToFind) {
|
||||||
|
return this.data.filter(({ categories }) => categories.indexOf(categoryToFind) >= 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
findAllByLocation(locationToFind) {
|
||||||
|
return this.data.filter(({ locations }) => locations.indexOf(locationToFind) >= 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AgentSemanticNetwork extends SemanticNetwork {}
|
||||||
|
|
||||||
|
class Arrangement {
|
||||||
|
constructor() {
|
||||||
|
this.products = [...Array(UnitsCount)].map(() => ({
|
||||||
|
product: '',
|
||||||
|
count: 0,
|
||||||
|
icon: ''
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Knowledge {
|
||||||
|
static semanticNetwork
|
||||||
|
static agentSemanticNetwork
|
||||||
|
static arrangement
|
||||||
|
|
||||||
|
constructor(definition) {
|
||||||
|
Knowledge.fullSemanticNetwork = new SemanticNetwork(definition)
|
||||||
|
Knowledge.agentSemanticNetwork = new AgentSemanticNetwork(definition)
|
||||||
|
Knowledge.arrangement = new Arrangement()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
keywords:
|
||||||
|
p - powiązane pomieszczenia / miejsca
|
||||||
|
c - category
|
||||||
|
*/
|
||||||
|
new Knowledge(`
|
||||||
|
Piłka :c sport,rozrywka, piłka nożna
|
||||||
|
Kubek klubowy :c sport,rozrywka,piłka nożna :p kuchnia
|
||||||
|
Waga łazienkowa :c zdrowie,agd,elektronika :p łazienka
|
||||||
|
Czajnik elektryczny :c agd,elektronika,zdrowie :p kuchnia
|
||||||
|
Widelec :c agd,jedzenie,zastawa kuchenna :p kuchnia
|
||||||
|
Łyżka :c agd,jedzenie,zastawa kuchenna :p kuchnia
|
||||||
|
Nóż stołowy :c agd,jedzenie,zastawa kuchenna :p kuchnia
|
||||||
|
Nóż kuchenny :c agd,gotowanie,przyrząd kuchenny :p kuchnia
|
||||||
|
Deska do krojenia :cagd,gotowanie,przyrząd kuchenny :p kuchnia
|
||||||
|
Gąbki kuchenne :c agd,gotowanie,sprzątanie :p kuchnia
|
||||||
|
Worki na śmieci :c agd,gotowanie,sprzątanie :p kuchnia
|
||||||
|
Miska :c agd,jedzenie,gotowanie,zastawa kuchenna :p kuchnia
|
||||||
|
Laptop :c elektronika,gaming :p biuro,szkoła
|
||||||
|
Telefon :c elektronika :p biuro,szkoła
|
||||||
|
`)
|
@ -1,22 +1,19 @@
|
|||||||
import { fromTable } from './utilities'
|
|
||||||
import { RowsOfGroupsCount, StorageCenterLocation, UnitsCount } from './configuration'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zwraca koordynaty półek przy danym kafelku ścieżki
|
* Zwraca koordynaty półek przy danym kafelku ścieżki
|
||||||
* @param {number} gridX
|
* @param {number} gridX
|
||||||
* @param {number} gridY
|
* @param {number} gridY
|
||||||
* @returns {{x:number;y:number}[]} Koordynaty sąsiednich półek do kafelka
|
* @returns {{x:number;y:number}[]} Koordynaty sąsiednich półek do kafelka
|
||||||
*/
|
*/
|
||||||
export function nearbyStorageUnitsCoords(gridX, gridY) {
|
function nearbyStorageUnitsCoords(gridX, gridY) {
|
||||||
function outsideOfStorageCenter(v) {
|
function outsideOfStorageCenter(v) {
|
||||||
const { x, y, w, h } = StorageCenterLocation
|
const { x, y, w, h } = StorageCenterLocation
|
||||||
return v.x <= x || v.x >= x + w || v.y <= y || v.y >= y + h
|
return v.x <= x || v.x >= x + w || v.y <= y || v.y >= y + h
|
||||||
}
|
}
|
||||||
return (gridX % UnitsInGroupCount == 0
|
return (gridX % UnitsInGroupCount == 0
|
||||||
? (gridY % 3 == 1
|
? (gridY % 3 == 1
|
||||||
? /* skrzyżowanie */ [[-1, -1], [-1, 1], [1, -1], [1,1]]
|
? /* skrzyżowanie */[[-1, -1], [-1, 1], [1, -1], [1, 1]]
|
||||||
: /* korytarz góra-dół */ [[-1, 0], [1, 0]])
|
: /* korytarz góra-dół */[[-1, 0], [1, 0]])
|
||||||
: /* korytarz lewo-prawo */ [[0, -1], [0, 1]])
|
: /* korytarz lewo-prawo */[[0, -1], [0, 1]])
|
||||||
.map(([xoff, yoff]) => ({ x: gridX + xoff, y: yGrid + yoff }))
|
.map(([xoff, yoff]) => ({ x: gridX + xoff, y: yGrid + yoff }))
|
||||||
.filter(outsideOfStorageCenter)
|
.filter(outsideOfStorageCenter)
|
||||||
}
|
}
|
||||||
@ -27,25 +24,19 @@ export function nearbyStorageUnitsCoords(gridX, gridY) {
|
|||||||
* @param {number} gridY
|
* @param {number} gridY
|
||||||
* @returns {{x:number;y:number}[]} Indeksy sąsiednich półek do kafelka
|
* @returns {{x:number;y:number}[]} Indeksy sąsiednich półek do kafelka
|
||||||
*/
|
*/
|
||||||
export function nearbyStorageUnitsIndexes(gridX, gridY) {
|
function nearbyStorageUnitsIndexes(gridX, gridY) {
|
||||||
return nearbyStorageUnitsCoords(gridX, gridY)
|
return nearbyStorageUnitsCoords(gridX, gridY)
|
||||||
.map(({ x, y }) => x * UnitsCount + y * UnitsCount * RowsOfGroupsCount)
|
.map(({ x, y }) => x * UnitsCount + y * UnitsCount * RowsOfGroupsCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Shop {
|
function ensureArray(maybeArray) {
|
||||||
constructor() {
|
return Array.isArray(maybeArray) ? maybeArray : []
|
||||||
// pełna lista wszystkich możliwych produktów dostępnych w sklepie,
|
}
|
||||||
// w formacie [{ name: '', category: '', ... }, { name: '', category: '', ...}, ...]
|
|
||||||
// kolejność przedmiotów jest niezmienna, przez co można przechowywać ich indeksy zamiast referencji
|
|
||||||
this.products = fromTable(
|
|
||||||
['name', 'category', 'intrest', '', 'icon'],
|
|
||||||
/* 0 */ ['Lodówka', 'AGD', 0.4, '', '<path-to-icon>']
|
|
||||||
)
|
|
||||||
|
|
||||||
this.productPlacement = [...Array(UnitsCount)].map(_ => ({
|
class Shop {
|
||||||
productId: null,
|
constructor(semanticNetwork) {
|
||||||
count: 0,
|
this.semanticNetwork = semanticNetwork
|
||||||
}))
|
this.products = [...Array(UnitsCount)].map(x => ({ name: '', count: 0 }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,7 +48,24 @@ class Shop {
|
|||||||
return nearbyStorageUnitsIndexes(gridX, gridY)
|
return nearbyStorageUnitsIndexes(gridX, gridY)
|
||||||
.map(i => this.productPlacement[i])
|
.map(i => this.productPlacement[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
productsSimilarityScore(name1, name2) {
|
||||||
|
const [ o1, o2 ] = [name1, name2].map(name => this.semanticNetwork.findByName(name))
|
||||||
|
if (!o1 || !o2)
|
||||||
|
throw new Error("names should be in semantic network!")
|
||||||
|
|
||||||
|
function calcScore(p) {
|
||||||
|
if (!o1[p] || !o2[p])
|
||||||
|
return 0
|
||||||
|
|
||||||
|
const set = new Set([...o1[p], ...o2[p]])
|
||||||
|
const matching = o1[p].reduce((s, v) => s + (o2[p].indexOf(v) >= 0 ? 1 : 0), 0)
|
||||||
|
return matching / [...set].lengthsss
|
||||||
|
}
|
||||||
|
|
||||||
|
const [ l, c ] = [calcScore('locations'), calcScore('categories')]
|
||||||
|
return l <= Number.EPSILON ? c * 0.7 : l * 0.65 + c * 0.35 // TODO: maybe find better formula? needs testing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const shop = new Shop()
|
const shop = new Shop(semanticNetwork)
|
||||||
export default shop
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* @param {...any[]} rows
|
* @param {...any[]} rows
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function fromTable(header, ...rows) {
|
function fromTable(header, ...rows) {
|
||||||
function tupleToRecord(names, array) {
|
function tupleToRecord(names, array) {
|
||||||
return names.reduce((p, v, i) => ({ ...p, [v]: array[i] }), {})
|
return names.reduce((p, v, i) => ({ ...p, [v]: array[i] }), {})
|
||||||
}
|
}
|
||||||
@ -18,6 +18,6 @@ export function fromTable(header, ...rows) {
|
|||||||
* @param {number} lo Minimum return value
|
* @param {number} lo Minimum return value
|
||||||
* @param {number} hi Maximum return value
|
* @param {number} hi Maximum return value
|
||||||
* */
|
* */
|
||||||
export function clamp(v, lo, hi) {
|
function clamp(v, lo, hi) {
|
||||||
return v <= lo ? lo : v >= hi ? hi : v
|
return v <= lo ? lo : v >= hi ? hi : v
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user