diff --git a/book.iml b/book.iml
index 32c73e0..a61edf0 100644
--- a/book.iml
+++ b/book.iml
@@ -17,8 +17,16 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/project.clj b/project.clj
index ca08dd6..7c979d4 100644
--- a/project.clj
+++ b/project.clj
@@ -3,7 +3,8 @@
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
- :dependencies [[org.clojure/clojure "1.9.0"]]
+ :dependencies [[org.clojure/clojure "1.9.0"]
+ [org.clojure/core.async "0.4.474"]]
:java-source-paths ["src/java"]
:main ^:skip-aot book.core
:target-path "target/%s"
diff --git a/src/book/core.clj b/src/book/core.clj
index 010c43e..2090939 100644
--- a/src/book/core.clj
+++ b/src/book/core.clj
@@ -1,5 +1,80 @@
-(ns book.core)
+(ns book.core
+ (:require [book.match :refer [sell?
+ create-buy-book
+ create-sell-book
+ match-order-in-book]]
+ [book.util :refer :all]
+ [book.order] ;; for spec side effect
+ [clojure.edn :as edn]
+ [clojure.core.async :refer [chan go >!! !! trades-channel trades))
+ (when leftover-order (>!! new-book-order-channel leftover-order))
+ (recur (!! trades-channel trades))
+ (when leftover-order (>!! new-book-order-channel leftover-order))
+ (recur ( " trades-channel))
+ (go (print-chan "order > " new-book-order-channel))
+ (go (process-orders master-book incoming-order-channel trades-channel new-book-order-channel))
+ (loop [order (read-order)]
+ (if (some? order)
+ (do
+ (let [order-with-id (add-id-to-order order)]
+ (>!! incoming-order-channel order-with-id)
+ (println "\n\norder accepted with id: " (:book.order/id order-with-id))))
+
+ (println "invalid order"))
+ (recur (read-order))))
diff --git a/src/book/match.clj b/src/book/match.clj
index 5598b78..699c414 100644
--- a/src/book/match.clj
+++ b/src/book/match.clj
@@ -1,17 +1,9 @@
(ns book.match
- (:import [book.PersistentSortedList])
- (:require [book.order]
+ (:require [book.util :refer [sorted-list-by]]
[clojure.spec.alpha :as s]
- [clojure.edn :as edn])
- (:gen-class))
+ [clojure.edn :as edn]))
-(defn sorted-list [& keys]
- (book.PersistentSortedList/create (seq keys)))
-
-(defn sorted-list-by [comparator & keys]
- (book.PersistentSortedList/create comparator (seq keys)))
-
;; Let say a book is two collections. The first called
;; sell-book contains all the sell orders. The second
@@ -95,9 +87,9 @@
(when (pos? leftover-quantity)
(assoc order :quantity leftover-quantity))))
-(defn match-order-in-book [sell-book order]
- (let [trades (create-trades order sell-book)
- new-book (compute-new-book-after-trades sell-book trades)
+(defn match-order-in-book [book order]
+ (let [trades (create-trades order book)
+ new-book (compute-new-book-after-trades book trades)
new-buy-order (leftover-order order trades)]
[trades new-book new-buy-order]))
@@ -112,7 +104,7 @@
;
;(defn -main
; [& args]
-; (let [order (-> args first edn/read-string)]
+; (let [order (-> a+rgs first edn/read-string)]
; (if (not (s/valid? :book.order/order order))
; (println "invalid order :( ")
; (println (place-order book order)))))
diff --git a/src/book/util.clj b/src/book/util.clj
new file mode 100644
index 0000000..de87dd7
--- /dev/null
+++ b/src/book/util.clj
@@ -0,0 +1,9 @@
+(ns book.util
+ (:import [book.PersistentSortedList]))
+
+(defn sorted-list [& keys]
+ (book.PersistentSortedList/create (seq keys)))
+
+(defn sorted-list-by [comparator & keys]
+ (book.PersistentSortedList/create comparator (seq keys)))
+
diff --git a/src/java/book/PersistentSortedList.java b/src/java/book/PersistentSortedList.java
index e52f1e8..6ec5220 100644
--- a/src/java/book/PersistentSortedList.java
+++ b/src/java/book/PersistentSortedList.java
@@ -3,10 +3,18 @@ package book;
import clojure.lang.*;
import java.util.*;
-public class PersistentSortedList extends ASeq implements IPersistentList, IReduce, List, Counted{
+//IPersistentVector, Iterable,
+// List,
+// RandomAccess, Comparable,
+// Serializable, IHashEq
+
+public class PersistentSortedList extends Obj implements Iterable, RandomAccess, Comparable,
+ IHashEq, IPersistentList, IReduce, ISeq,
+ List, Counted{
final private PersistentTreeMap impl;
final private int _count;
static public final PersistentSortedList EMPTY = new PersistentSortedList(null, PersistentTreeMap.EMPTY, 0);
+ private int _hasheq = 0;
public static PersistentSortedList create(ISeq items){
PersistentSortedList ret = EMPTY;
@@ -42,6 +50,24 @@ public class PersistentSortedList extends ASeq implements IPersistentList, IRedu
return new PersistentSortedList(meta(), impl.assoc(o, newList), _count + 1);
}
+ @Override
+ public IPersistentCollection empty() {
+ return PersistentSortedList.EMPTY;
+ }
+
+ @Override
+ public boolean equiv(Object obj) {
+ if(!(obj instanceof Sequential || obj instanceof List))
+ return false;
+ ISeq ms = RT.seq(obj);
+ for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next()){
+ if(ms == null || !Util.equiv(s.first(), ms.first())){
+ return false;
+ }
+ }
+ return ms == null;
+ }
+
@Override
public Object peek() {
if(_count == 0){
@@ -70,7 +96,7 @@ public class PersistentSortedList extends ASeq implements IPersistentList, IRedu
@Override
public Object reduce(IFn f) {
Object ret = first();
- for(ISeq s = next(); s != null; s = s.next()) {
+ for(ISeq s = (ISeq) next(); s != null; s = s.next()) {
ret = f.invoke(ret, s.first());
if (RT.isReduced(ret)) return ((IDeref)ret).deref();
}
@@ -80,7 +106,7 @@ public class PersistentSortedList extends ASeq implements IPersistentList, IRedu
@Override
public Object reduce(IFn f, Object start) {
Object ret = f.invoke(start, first());
- for(ISeq s = next(); s != null; s = s.next()) {
+ for(PersistentSortedList s = next(); s != null; s = s.next()) {
if (RT.isReduced(ret)) return ((IDeref)ret).deref();
ret = f.invoke(ret, s.first());
}
@@ -88,12 +114,10 @@ public class PersistentSortedList extends ASeq implements IPersistentList, IRedu
return ret;
}
- @Override
public Object first() {
return peek();
}
- @Override
public PersistentSortedList next() {
if(_count == 0){
return null;
@@ -109,6 +133,18 @@ public class PersistentSortedList extends ASeq implements IPersistentList, IRedu
return new PersistentSortedList(meta(), nextImpl, _count - 1);
}
+ // Things that i did not want to implement.
+
+ private List reify(){
+ return Collections.unmodifiableList(new ArrayList(this));
+ }
+
+ @Override
+ public ISeq more() {
+ ISeq s = next();
+ return s == null ? PersistentSortedList.EMPTY : s;
+ }
+
@Override
public Obj withMeta(IPersistentMap meta) {
if(meta != meta()){
@@ -116,5 +152,151 @@ public class PersistentSortedList extends ASeq implements IPersistentList, IRedu
}
return this;
}
+
+ @Override
+ public int hasheq() {
+ if(_hasheq == 0){
+ _hasheq = Murmur3.hashOrdered(this);
+ }
+ return _hasheq;
+ }
+
+ @Override
+ public ISeq seq() {
+ return count() == 0 ? null : (ISeq) this;
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ return 0;
+ }
+
+ @Override
+ public int size() {
+ return count();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return seq() == null;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return impl.containsKey(o);
+ }
+
+ @Override
+ public Object[] toArray() {
+ return RT.seqToArray(seq());
+ }
+
+ @Override
+ public boolean add(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(int i, Collection collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object get(int index) {
+ return RT.nth(this, index);
+ }
+
+ @Override
+ public Object set(int i, Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(int i, Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object remove(int i) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ // TODO: make this function fast by using the underlying sorted set. This function should be constant.
+ ISeq s = seq();
+ for(int i = 0; s != null; s = s.next(), i++) {
+ if(Util.equiv(s.first(), o)){
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ // TODO: make this function fast by using the underlying sorted set. This function should be constant.
+ return reify().lastIndexOf(o);
+ }
+
+ @Override
+ public ListIterator listIterator() {
+ return reify().listIterator();
+ }
+
+ @Override
+ public ListIterator listIterator(int index) {
+ return reify().listIterator(index);
+ }
+
+ @Override
+ public List subList(int fromIndex, int toIndex) {
+ return reify().subList(fromIndex, toIndex);
+ }
+
+ @Override
+ public boolean retainAll(Collection collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection collection) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean containsAll(Collection collection) {
+ for(Object o : collection) {
+ if(!contains(o)){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public Object[] toArray(Object[] objects) {
+ return RT.seqToPassedArray(seq(), objects);
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new SeqIterator(this);
+ }
}
diff --git a/test/book/test_PersistentSortedList.clj b/test/book/test_PersistentSortedList.clj
index 08c9031..b6cbf55 100644
--- a/test/book/test_PersistentSortedList.clj
+++ b/test/book/test_PersistentSortedList.clj
@@ -1,10 +1,14 @@
(ns book.test-PersistentSortedList
(:require [clojure.test :refer :all]
- [book.match :refer [sorted-list sorted-list-by]]))
+ [book.util :refer [sorted-list sorted-list-by]]))
(deftest test-match-buy-order-in-sell-book
+ (testing "constructing"
+ (is (empty? (map nil? (sorted-list)))))
+ ;; The following are tests that fails...
+ ;(is (empty? (vec (sorted-list)))))
(testing "Test ordering."
(is (= (sorted-list 1 2 3) (sorted-list 3 2 1)))
(is (= (sorted-list 1 2 2 3) (sorted-list 3 2 1 2))))
@@ -16,7 +20,8 @@
(is (= (rest (sorted-list 1 2 3)) (sorted-list 2 3)))
(is (= (rest (sorted-list 1 2 3 2)) (sorted-list 2 2 3)))
(is (= (rest (sorted-list 1)) (list)))
- (is (= (rest (sorted-list)) (list))))
+ (is (empty? (rest (sorted-list))))
+ (is (= (str (type (rest (sorted-list)))) "class book.PersistentSortedList")))
(testing "next"
(is (= (next (sorted-list 1 2 3)) (sorted-list 2 3)))
(is (= (next (sorted-list 1 2 3 2)) (sorted-list 2 2 3)))