diff --git a/src/main/java/org/opennars/web/HTTPServeFiles.java b/src/main/java/org/opennars/web/httpnar/HTTPServeFiles.java similarity index 99% rename from src/main/java/org/opennars/web/HTTPServeFiles.java rename to src/main/java/org/opennars/web/httpnar/HTTPServeFiles.java index 6a3200c9faa6d68c5ac76265c39849265eb30951..8451a7be1801b100a3c14b6ed39b3caf8134e002 100644 --- a/src/main/java/org/opennars/web/HTTPServeFiles.java +++ b/src/main/java/org/opennars/web/httpnar/HTTPServeFiles.java @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package org.opennars.web; +package org.opennars.web.httpnar; import java.io.File; import java.io.FileInputStream; diff --git a/src/main/java/org/opennars/web/HTTPServer.java b/src/main/java/org/opennars/web/httpnar/HTTPServer.java similarity index 99% rename from src/main/java/org/opennars/web/HTTPServer.java rename to src/main/java/org/opennars/web/httpnar/HTTPServer.java index 585cc5ee5f7b76bc289018c556dce2282af8c907..655edc979976c33cff773babcf2b21da5da94b97 100644 --- a/src/main/java/org/opennars/web/HTTPServer.java +++ b/src/main/java/org/opennars/web/httpnar/HTTPServer.java @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package org.opennars.web; +package org.opennars.web.httpnar; /* "Copyright (C) 2001,2005 by Jarno Elonen <elonen@iki.fi>\n"+ diff --git a/src/main/java/org/opennars/web/NARConnection.java b/src/main/java/org/opennars/web/httpnar/NARConnection.java similarity index 87% rename from src/main/java/org/opennars/web/NARConnection.java rename to src/main/java/org/opennars/web/httpnar/NARConnection.java index 605c582ca944ae272ae78f2bbe04aef47695b340..7ea69c022f22e834a3b885ad3420e03eb7b72d7d 100644 --- a/src/main/java/org/opennars/web/NARConnection.java +++ b/src/main/java/org/opennars/web/httpnar/NARConnection.java @@ -18,9 +18,10 @@ * and open the template in the editor. */ -package org.opennars.web; +package org.opennars.web.httpnar; -import org.opennars.main.NAR; +import org.opennars.interfaces.pub.Reasoner; +import org.opennars.main.Nar; import org.opennars.io.events.TextOutputHandler; import org.opennars.io.events.TextOutputHandler.LineOutput; @@ -29,17 +30,17 @@ import org.opennars.io.events.TextOutputHandler.LineOutput; * @author me */ abstract public class NARConnection implements LineOutput { - public final NAR nar; + public final Reasoner nar; protected final TextOutputHandler writer; int cycleIntervalMS; //private final TextReaction extraParser; - public NARConnection(NAR nar, int cycleIntervalMS) { + public NARConnection(Reasoner nar, int cycleIntervalMS) { this.nar = nar; this.cycleIntervalMS = cycleIntervalMS; - this.writer = new TextOutputHandler(nar, this); + this.writer = new TextOutputHandler((Nar) nar, this); } public void read(final String message) { diff --git a/src/main/java/org/opennars/web/NARServer.java b/src/main/java/org/opennars/web/httpnar/NARServer.java similarity index 94% rename from src/main/java/org/opennars/web/NARServer.java rename to src/main/java/org/opennars/web/httpnar/NARServer.java index db92394107727cfe35c0067574a1477fcae55d9b..fdf482f02b17b856b45e1d5ebfaa38e2550a798c 100644 --- a/src/main/java/org/opennars/web/NARServer.java +++ b/src/main/java/org/opennars/web/httpnar/NARServer.java @@ -12,19 +12,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package org.opennars.web; +package org.opennars.web.httpnar; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; -import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; -import org.opennars.main.NAR; import org.java_websocket.WebSocket; import org.java_websocket.WebSocketImpl; import org.java_websocket.handshake.ClientHandshake; import org.java_websocket.server.WebSocketServer; +import org.opennars.interfaces.pub.Reasoner; +import org.opennars.main.Nar; public class NARServer { @@ -43,6 +43,8 @@ public class NARServer { public void onStart() { } + public Reasoner nar; + @Override public void onOpen(final WebSocket conn, ClientHandshake handshake) { //this.sendToAll("new connection: " + handshake.getResourceDescriptor()); @@ -51,7 +53,10 @@ public class NARServer { if (WEBSOCKET_DEBUG) System.out.println("Connect: " + conn.getRemoteSocketAddress().getAddress().getHostAddress()); - final NARConnection n = new NARConnection(new NAR(), cycleIntervalMS) { + if(nar == null) { + nar = new Nar(); + } + final NARConnection n = new NARConnection(nar, cycleIntervalMS) { @Override public void println(String output) { conn.send(output); } diff --git a/src/main/java/org/opennars/web/multinar/NarNode.java b/src/main/java/org/opennars/web/multinar/NarNode.java new file mode 100644 index 0000000000000000000000000000000000000000..2bc3297ea0ac48489afcd0ef813fdd4228cbfeca --- /dev/null +++ b/src/main/java/org/opennars/web/multinar/NarNode.java @@ -0,0 +1,216 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package org.opennars.web.multinar; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.opennars.entity.Task; +import org.opennars.io.events.EventEmitter.EventObserver; +import org.opennars.io.events.Events; +import org.opennars.language.CompoundTerm; +import org.opennars.language.Term; +import org.opennars.main.Nar; + +public class NarNode extends Nar implements EventObserver { + + /* An extra event for received tasks*/ + public class EventReceivedTask {} + + /* The socket the Nar listens from */ + private DatagramSocket receiveSocket; + + /*** + * Create a Nar node that listens for received tasks from other NarNode instances + * + * @param listenPort + * @throws SocketException + * @throws UnknownHostException + */ + public NarNode(int listenPort) throws SocketException, UnknownHostException { + super(); + this.receiveSocket = new DatagramSocket(listenPort, InetAddress.getByName("127.0.0.1")); + this.event(this, true, Events.TaskAdd.class); + NarNode THIS = this; + new Thread() { + public void run() { + for(;;) { + try { + Task ret = THIS.receiveTask(); + if(ret != null) { + THIS.memory.event.emit(EventReceivedTask.class, new Object[]{ret}); + THIS.addInput(ret); + } + } catch (IOException ex) { + Logger.getLogger(NarNode.class.getName()).log(Level.SEVERE, null, ex); + } catch (ClassNotFoundException ex) { + Logger.getLogger(NarNode.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + }.start(); + } + + /** + * Input and derived tasks will be potentially sent + * + * @param event + * @param args + */ + @Override + public void event(Class event, Object[] args) { + if(event == Events.TaskAdd.class) { + Task t = (Task) args[0]; + try { + sendTask(t); + } catch (IOException ex) { + Logger.getLogger(NarNode.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + /** + * Send tasks that are above priority threshold and contain the optional mustContainTerm + * + * @param t + * @throws IOException + */ + private void sendTask(Task t) throws IOException { + ByteArrayOutputStream bStream = new ByteArrayOutputStream(); + ObjectOutput oo = new ObjectOutputStream(bStream); + oo.writeObject(t); + oo.close(); + byte[] serializedMessage = bStream.toByteArray(); + for(TargetNar target : targets) { + if(t.getPriority() > target.threshold) { + Term term = t.getTerm(); + boolean isCompound = (term instanceof CompoundTerm); + boolean searchTerm = target.mustContainTerm != null; + boolean atomicEqualsSearched = searchTerm && !isCompound && target.mustContainTerm.equals(term); + boolean compoundContainsSearched = searchTerm && isCompound && ((CompoundTerm) term).containsTermRecursively(target.mustContainTerm); + if(!searchTerm || atomicEqualsSearched || compoundContainsSearched) { + DatagramPacket packet = new DatagramPacket(serializedMessage, serializedMessage.length, target.targetAddress, target.targetPort); + target.sendSocket.send(packet); + System.out.println("task sent:" + t); + } + } + } + } + + public class TargetNar { + + /** + * The target Nar node, specifying under which conditions the current Nar node redirects tasks to it. + * + * @param targetIP + * @param targetPort + * @param threshold + * @param mustContainTerm + * @throws SocketException + * @throws UnknownHostException + */ + public TargetNar(final String targetIP, final int targetPort, final float threshold, Term mustContainTerm) throws SocketException, UnknownHostException { + this.targetAddress = InetAddress.getByName(targetIP); + this.sendSocket = new DatagramSocket(); + this.threshold = threshold; + this.targetPort = targetPort; + this.mustContainTerm = mustContainTerm; + } + final float threshold; + final DatagramSocket sendSocket; + final int targetPort; + final InetAddress targetAddress; + final Term mustContainTerm; + } + + private List<TargetNar> targets = new ArrayList<>(); + /** + * Add another target Nar node to redirect tasks to, and under which conditions. + * + * @param targetIP The target Nar node IP + * @param targetPort The target Nar node port + * @param taskThreshold The threshold the priority of the task has to have to redirect + * @param mustContainTerm The optional term that needs to be contained recursively in the task term + * @throws SocketException + * @throws UnknownHostException + */ + public void addRedirectionTo(final String targetIP, final int targetPort, final float taskThreshold, Term mustContainTerm) throws SocketException, UnknownHostException { + targets.add(new TargetNar(targetIP, targetPort, taskThreshold, mustContainTerm)); + } + + /*** + * NarNode's receiving a task + * + * @return + * @throws IOException + * @throws ClassNotFoundException + */ + private Task receiveTask() throws IOException, ClassNotFoundException { + byte[] recBytes = new byte[100000]; + DatagramPacket packet = new DatagramPacket(recBytes, recBytes.length); + receiveSocket.receive(packet); + ObjectInputStream iStream = new ObjectInputStream(new ByteArrayInputStream(recBytes)); + Task T = (Task) iStream.readObject(); + System.out.println("task received: " + T); + iStream.close(); + return T; + } + + + /** + * An example + * + * @param args + * @throws SocketException + * @throws UnknownHostException + * @throws IOException + * @throws InterruptedException + */ + public static void main(String[] args) throws SocketException, UnknownHostException, IOException, InterruptedException { + int nar1port = 64001; + int nar2port = 64002; + String localIP = "127.0.0.1"; + NarNode nar1 = new NarNode(nar1port); + NarNode nar2 = new NarNode(nar2port); + nar1.addRedirectionTo(localIP, nar2port, 0.5f, null); + //nar2.connectTo(localIP, nar1port, 0.5f); + nar2.event(new EventObserver() { + @Override + public void event(Class event, Object[] args) { + if(event == EventReceivedTask.class) { + Task task = (Task) args[0]; + System.out.println("received task event triggered for task: " + task); + System.out.println("success"); + } + } + }, true, EventReceivedTask.class); + nar1.addInput("<{task1} --> [great]>."); + Thread.sleep(5000); + System.exit(0); + } + +}