const connections = [
"Wieża kościelna-Boisko", "Wieża kościelna-Duży klon", "Duży klon-Boisko",
"Duży klon-Las", "Duży klon-Ogród Fabienne", "Ogród Fabienne-Las",
"Ogród Fabienne-Pastwisko", "Pastwisko-Duży dąb", "Duży dąb-Rzeźnia",
"Rzeźnia-Wysoka topola", "Wysoka topola-Boisko", "Wysoka topola-Pałac",
"Pałac-Duża sosna", "Duża sosna-Gospodarstw Jacques'a", "Gospodarstw Jacques'a-Głóg",
"Duża sosna-Głóg", "Głóg-Ogród Gillesa", "Duża sosna-Ogród Gillesa",
"Ogród Gillesa-Duży dąb", "Ogród Gillesa-Rzeźnia", "Pałac-Rzeźnia"
]
function storageFor(name) {
let storage = Object.create(null)
storage["schowki na jedzenie"] = ["schowek w dębie", "schowek na łące", "schowek pod żywopłotem"]
storage["schowek w dębie"] = "Dziura na trzecią dużą gałęzią od dołu. Kilka kawałków chleba i trochę szyszek."
storage["shcowek na łące"] = "Zakopany pod pokrzywami (strona południowa). Zdechły wąż."
storage["schowek pod żywopłotem"] = "Środek żywopłotu w ogrodzie Gillesa. Oznaczony rozgałęzionym patykiem. Dwie butelki piwa."
storage["wrogowie"] = ["Pies Jacques'a", "Rzeźnik", "Ta jednonoga kawka", "Chłopiec z wiatrówką"]
if (name == "Wieża kościelna" || name == "Głóg" || name == "Pałac")
storage["events on 2017-12-21"] = "Głęboki śnieg. Śmieci rzeźnika mogą się przewrócić. Przegoniliśmy kruki z Saint-Vulbas."
let hash = 0
for (let i = 0; i < name.length; i++) hash += name.charCodeAt(i)
for (let y = 1985; y <= 2018; y++) {
storage[`chicks in ${y}`] = hash % 6
hash = Math.abs((hash << 2) ^ (hash + y))
}
if (name == "Duży dąb") storage.scalpel = "Ogród Gillesa"
else if (name == "Ogród Gillesa") storage.scalpel = "Las"
else if (name == "Woods") storage.scalpel = "Pałac"
else if (name == "Pałac" || name == "Rzeźnia") storage.scalpel = "Rzeźnia"
else storage.scalpel = "Duży dąb"
for (let prop of Object.keys(storage)) storage[prop] = JSON.stringify(storage[prop])
return storage
}
class Network {
constructor(connections, storageFor) {
let reachable = Object.create(null)
for (let [from, to] of connections.map(conn => conn.split("-"))) {
;(reachable[from] || (reachable[from] = [])).push(to)
;(reachable[to] || (reachable[to] = [])).push(from)
}
this.nodes = Object.create(null)
for (let name of Object.keys(reachable))
this.nodes[name] = new Node(name, reachable[name], this, storageFor(name))
this.types = Object.create(null)
}
defineRequestType(name, handler) {
this.types[name] = handler
}
everywhere(f) {
for (let node of Object.values(this.nodes)) f(node)
}
}
const $storage = Symbol("storage"), $network = Symbol("network")
function ser(value) {
return value == null ? null : JSON.parse(JSON.stringify(value))
}
class Node {
constructor(name, neighbors, network, storage) {
this.name = name
this.neighbors = neighbors
this[$network] = network
this.state = Object.create(null)
this[$storage] = storage
}
send(to, type, message, callback) {
let toNode = this[$network].nodes[to]
if (!toNode || !this.neighbors.includes(to))
return callback(new Error(`Nie ma dostępu do ${to} z ${this.name}`))
let handler = this[$network].types[type]
if (!handler)
return callback(new Error("Nieznany typ żądania " + type))
if (Math.random() > 0.03) setTimeout(() => {
try {
handler(toNode, ser(message), this.name, (error, response) => {
setTimeout(() => callback(error, ser(response)), 10)
})
} catch(e) {
callback(e)
}
}, 10 + Math.floor(Math.random() * 10))
}
readStorage(name, callback) {
let value = this[$storage][name]
setTimeout(() => callback(value && JSON.parse(value)), 20)
}
writeStorage(name, value, callback) {
setTimeout(() => {
this[$storage][name] = JSON.stringify(value)
callback()
}, 20)
}
}
if (typeof __sandbox != "undefined") {
__sandbox.handleDeps = false
__sandbox.notify.onLoad = () => {
// Sztuczka opóźniająca wszystkie funkcje aż wszystkie węzły
// podziałają przez 500 ms, aby dać im szansę na
// rozesłanie informacji po sieci.
let waitFor = Date.now() + 500
function wrapWaiting(f) {
return function(...args) {
let wait = waitFor - Date.now()
if (wait <= 0) return f(...args)
return new Promise(ok => setTimeout(ok, wait)).then(() => f(...args))
}
}
for (let n of ["routeRequest", "findInStorage", "chicks"])
window[n] = wrapWaiting(window[n])
}
}
if (typeof window != "undefined") {
window.require = name => {
if (name != "./crow-tech") throw new Error("Gniazda wron mogą żądać tylko \"./crow-tech\"")
return exports
}
} else if (typeof module != "undefined" && module.exports) {
module.exports = exports
}
let network = new Network(connections, storageFor)
export const bigOak = network.nodes["Duży dąb"]
export const topola = network.nodes["Wysoka topola"]
export const everywhere = network.everywhere.bind(network)
export const defineRequestType = network.defineRequestType.bind(network)
import { bigOak, defineRequestType, everywhere, topola} from './crow-tech.js';
class Timeout extends Error {}
function request(nest, target, type, content) {
return new Promise((resolve, reject) => {
let done = false;
function attempt(n) {
nest.send(target, type, content, (failed, value) => {
done = true;
if(failed) reject(failed);
else resolve(value);
});
setTimeout(() => {
if (done) return;
else if (n < 3) attempt(n + 1);
else reject(new Timeout("Czas minął."));
}, 250);
}
attempt(1);
})
}
function requestType(name, handler) {
defineRequestType(name, (nest, content, source, callback) => {
try {
Promise.resolve(handler(nest, content, source))
.then(response => callback(null, response),
failure => callback(failure));
} catch (exception) {
callback(exception);
}
});
}
requestType("connections", (nest, {name, neighbors}, source) => {
let connections = nest.state.connections;
if(JSON.stringify(connections.get(name)) == JSON.stringify(neighbors)) return;
connections.set(name, neighbors);
broadcastConnections(nest, name, source);
});
function broadcastConnections(nest, name, exceptFor = null) {
for(let neighbor of nest.neighbors) {
if(neighbor == exceptFor) continue;
request(nest, neighbor, "connections", {
name,
neighbors: nest.state.connections.get(name)
});
}
}
everywhere(nest => {
nest.state.connections = new Map;
nest.state.connections.set(nest.name, nest.neighbors);
broadcastConnections(nest, nest.name);
})
function findRoute(from, to, connections) {
let work = [{at: from, via: null}];
for (let i = 0; i < work.length; i++) {
let {at, via} = work[i];
for(let next of connections.get(at) || []) {
if(next == to) return via;
if(!work.some(w => w.at == next)) {
work.push({at: next, via: via || next});
}
}
}
return null;
}
function routeRequest(nest, target, type, content) {
if(nest.neighbors.includes(target)) {
return request(nest, target, type, content);
} else {
let via = findRoute(nest.name, target, nest.state.connections);
if(!via) throw new Error(`No route to ${target}`);
return request(nest, via, "route", {target, type, content});
}
}
requestType("route", (nest, {target, type, content}) => {
return routeRequest(nest, target, type, content);
})
Hej, chciałbym skorzystać z nowo napisanego typu żądania "route", ale niestety po wywołaniu
bigOak.send("Pastwisko", "route", "test", response => console.log(response))
zwraca mi błąd "Error: No route to undefined" a więc jest tu jakiś problem z pobieraniem danych z nest. Jest to przykład z książki i po przepisaniu 1 w 1 oraz drobnych modyfikacjach nadal nie wiem jak poprawnie wywołać to żądanie. Czy ktoś może mi pomóc rozwiązać ten problem? Wiem że kod jest bardzo rozbudowany, ale próbowałem już wszystkich pomysłów