// Path: marketdata-common/src/main/java/com/handson/dto/Trade.java
// public class Trade {
// 
//     public final String code;
//     public final int quantity;
//     public final double nominal;
// 
//     public Trade(String code, int quantity, double nominal) {
//         this.code = code;
//         this.quantity = quantity;
//         this.nominal = nominal;
//     }
// 
//     public static Trade fromJson(String input) {
//         return new Gson().fromJson(input, Trade.class);
//     }
// 
// 
//     public String toJson() {
//         return new Gson().toJson(this);
//     }
// 
//     @Override
//     public String toString() {
//         return toJson();
//     }
// }
// 
// Path: marketdata-common/src/main/java/com/handson/dto/Vwap.java
// public class Vwap {
// 
//     public final String code;
//     public final double vwap;
//     public final double volume;
// 
//     public Vwap(String code) {
//         this.code = code;
//         this.vwap = 0;
//         this.volume = 0;
//     }
// 
//     public Vwap(String code, double vwap, double volume) {
//         this.code = code;
//         this.vwap = vwap;
//         this.volume = volume;
//     }
// 
//     public Vwap addTrade(Trade t) {
//         double volume = this.volume + t.quantity;
//         double vwap = (this.volume * this.vwap + t.nominal) / volume;
//         return new Vwap(t.code, vwap, volume);
//     }
// 
//     public static Vwap fromJson(String input) {
//         return new Gson().fromJson(input, Vwap.class);
//     }
// 
// 
//     public String toJson() {
//         return new Gson().toJson(this);
//     }
// 
//     @Override
//     public String toString() {
//         return toJson();
//     }
// }
// 
// Path: marketdata-common/src/main/java/com/handson/infra/EventStreamClient.java
// public interface EventStreamClient {
// 
//     Observable<String> readServerSideEvents();
// }
// 
// Path: marketdata-common/src/main/java/com/handson/infra/HttpRequest.java
// public class HttpRequest {
// 
//     private final Map<String, List<String>> parameters;
// 
//     public HttpRequest(Map<String, List<String>> parameters) {
//         this.parameters = parameters;
//     }
// 
//     public String getParameter(String name) {
//         if (parameters.get(name) == null) {
//             return null;
//         }
//         return parameters.get(name).get(0);
//     }
// }


import com.handson.dto.Trade;
import com.handson.dto.Vwap;
import com.handson.infra.EventStreamClient;
import com.handson.infra.HttpRequest;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import rx.observers.TestSubscriber;
import rx.schedulers.Schedulers;
import rx.schedulers.TestScheduler;
import rx.subjects.TestSubject;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
        // given
        TestSubscriber<Vwap> testSubscriber = new TestSubscriber<>();
        HttpRequest request = createRequest("code", "GOOGL");
        vwapServer.getEvents(request).subscribe(testSubscriber);
        // when
        tradeSourceSubject.onNext(new Trade("GOOGL", 10, 7058.673).toJson());
        tradeSourceSubject.onNext(new Trade("APPLE", 10, 981.8).toJson());
        scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
        // then
        List<Vwap> events = testSubscriber.getOnNextEvents();
        assertThat(events).hasSize(1);
        Vwap vwap = events.get(0);
        assertThat(vwap.code).isEqualTo("GOOGL");
        assertThat(vwap.vwap).isEqualTo(705.8673);
        assertThat(vwap.volume).isEqualTo(10);
    }

    /**
     * Test 11
     */
    @Test
    @Ignore
    public void should_add_all_google_trades_to_generate_vwap_events() {
        // given
        TestSubscriber<Vwap> testSubscriber = new TestSubscriber<>();
        HttpRequest request = createRequest("code", "GOOGL");
        vwapServer.getEvents(request).subscribe(testSubscriber);
        // when
        tradeSourceSubject.onNext(new Trade("GOOGL", 10, 7058).toJson());
        tradeSourceSubject.onNext(new Trade("GOOGL", 10, 7062).toJson());
// Path: marketdata-common/src/main/java/com/handson/dto/Trade.java
// public class Trade {
// 
//     public final String code;
//     public final int quantity;
//     public final double nominal;
// 
//     public Trade(String code, int quantity, double nominal) {
//         this.code = code;
//         this.quantity = quantity;
//         this.nominal = nominal;
//     }
// 
//     public static Trade fromJson(String input) {
//         return new Gson().fromJson(input, Trade.class);
//     }
// 
// 
//     public String toJson() {
//         return new Gson().toJson(this);
//     }
// 
//     @Override
//     public String toString() {
//         return toJson();
//     }
// }
// 
// Path: marketdata-common/src/main/java/com/handson/dto/Vwap.java
// public class Vwap {
// 
//     public final String code;
//     public final double vwap;
//     public final double volume;
// 
//     public Vwap(String code) {
//         this.code = code;
//         this.vwap = 0;
//         this.volume = 0;
//     }
// 
//     public Vwap(String code, double vwap, double volume) {
//         this.code = code;
//         this.vwap = vwap;
//         this.volume = volume;
//     }
// 
//     public Vwap addTrade(Trade t) {
//         double volume = this.volume + t.quantity;
//         double vwap = (this.volume * this.vwap + t.nominal) / volume;
//         return new Vwap(t.code, vwap, volume);
//     }
// 
//     public static Vwap fromJson(String input) {
//         return new Gson().fromJson(input, Vwap.class);
//     }
// 
// 
//     public String toJson() {
//         return new Gson().toJson(this);
//     }
// 
//     @Override
//     public String toString() {
//         return toJson();
//     }
// }
// 
// Path: marketdata-common/src/main/java/com/handson/infra/EventStreamClient.java
// public interface EventStreamClient {
// 
//     Observable<String> readServerSideEvents();
// }
// 
// Path: marketdata-common/src/main/java/com/handson/infra/HttpRequest.java
// public class HttpRequest {
// 
//     private final Map<String, List<String>> parameters;
// 
//     public HttpRequest(Map<String, List<String>> parameters) {
//         this.parameters = parameters;
//     }
// 
//     public String getParameter(String name) {
//         if (parameters.get(name) == null) {
//             return null;
//         }
//         return parameters.get(name).get(0);
//     }
// }


// Path: marketdata-web/src/test/java/com/handson/rx/VwapServerTest.java
import com.handson.dto.Trade;
import com.handson.dto.Vwap;
import com.handson.infra.EventStreamClient;
import com.handson.infra.HttpRequest;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import rx.observers.TestSubscriber;
import rx.schedulers.Schedulers;
import rx.schedulers.TestScheduler;
import rx.subjects.TestSubject;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

        // given
        TestSubscriber<Vwap> testSubscriber = new TestSubscriber<>();
        HttpRequest request = createRequest("code", "GOOGL");
        vwapServer.getEvents(request).subscribe(testSubscriber);
        // when
        tradeSourceSubject.onNext(new Trade("GOOGL", 10, 7058.673).toJson());
        tradeSourceSubject.onNext(new Trade("APPLE", 10, 981.8).toJson());
        scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
        // then
        List<Vwap> events = testSubscriber.getOnNextEvents();
        assertThat(events).hasSize(1);
        Vwap vwap = events.get(0);
        assertThat(vwap.code).isEqualTo("GOOGL");
        assertThat(vwap.vwap).isEqualTo(705.8673);
        assertThat(vwap.volume).isEqualTo(10);
    }

    /**
     * Test 11
     */
    @Test
    @Ignore
    public void should_add_all_google_trades_to_generate_vwap_events() {
        // given
        TestSubscriber<Vwap> testSubscriber = new TestSubscriber<>();
        HttpRequest request = createRequest("code", "GOOGL");
        vwapServer.getEvents(request).subscribe(testSubscriber);
        // when
        tradeSourceSubject.onNext(new Trade("GOOGL", 10, 7058).toJson());
        tradeSourceSubject.onNext(new Trade("GOOGL", 10, 7062).toJson());
        scheduler.advanceTimeBy(1, TimeUnit.SECONDS);