"use strict"; import path from 'path'; import brain from 'brain.js'; import haversine from 'haversine-distance'; import { normalise, clamp } from '../../../common/Math.mjs'; import GetFromUrl from '../Helpers/GetFromUrl.mjs'; class AIWrapper { constructor() { this.setup_complete = false; this.map_bounds = null; this.index = null; this.Config = null; this.gateways = new Map(); } async setup({ bounds, index, Config }) { this.map_bounds = bounds; this.index = index; this.Config = Config; console.log("Loading models"); // WebGL isn't available inside WebWorkers yet :-( for(let gateway of this.index.index) { let net = new brain.NeuralNetwork(); net.fromJSON( // TODO: Move this to the UI thread & do it only once? await GetFromUrl(`${path.dirname(self.location.href)}/${path.dirname(this.Config.ai_index_file)}/${gateway.filename}`) ); this.gateways.set( gateway.id, net ); } console.log("Model setup complete."); this.setup_complete = true; } predict_row(lat) { if(!this.setup_complete) throw new Error("Error: Can't do predictions until the setup is complete."); let result = [], stats = { rssi_min: Infinity, rssi_max: -Infinity }; for(let lng = this.map_bounds.west; lng < this.map_bounds.east; lng += this.Config.step.lng) { let max_predicted_rssi = -Infinity; for(let [gateway_id, ai] of this.gateways) { let distance_from_gateway = haversine( { latitude: lat, longitude: lng }, this.gateways.get(gateway_id) ); max_predicted_rssi = Math.max( max_predicted_rssi, ai.run({ latitude: normalise(lat, { min: -90, max: +90 }, { min: 0, max: 1 } ), longitude: normalise(lng, { min: -180, max: +180 }, { min: 0, max: 1 } ), distance: clamp( normalise(distance_from_gateway, { min: 0, max: 20000 }, { min: 0, max: 1 } ), 0, 1) }) ); } max_predicted_rssi = normalise(max_predicted_rssi, { min: 0, max: 1 }, { min: this.index.properties.rssi_min, max: this.index.properties.rssi_max } ); if(max_predicted_rssi > stats.rssi_max) stats.rssi_max = max_predicted_rssi; if(max_predicted_rssi < stats.rssi_min) stats.rssi_min = max_predicted_rssi; result.push(max_predicted_rssi); } return { result, stats }; } } export default AIWrapper;