/**
   * groupBy the mod of 5, thus the values into those who can starting at 0-4 respectively into
   * groups
   *
   * <p>Must reason about the logic that is going on here.
   */
  public static void groupedObserv() {

    Observable.fromIterable(ints)
        // Function<Input, Output>;
        .groupBy(
            (Function<Integer, Integer>)
                new Function<Integer, Integer>() {
                  @Override
                  public Integer apply(Integer integer) throws Exception {
                    return integer % 5;
                  }
                })
        .flatMap(
            new Function<GroupedObservable<Integer, Integer>, ObservableSource<?>>() {
              @Override
              public ObservableSource<?> apply( // each group is now a stream
                  GroupedObservable<Integer, Integer> integerIntegerGroupedObservable)
                  throws Exception {
                return integerIntegerGroupedObservable.toList().toObservable();
              }
            })
        .toList() // to list is important as it is the Single<List<Object>>
        .subscribe(
            new Consumer<List<Object>>() {
              @Override
              public void accept(List<Object> objects) throws Exception {
                for (Object o : objects) {
                  System.out.println(o.toString());
                }
              }
            });
  }
  @OnClick(R.id.btn_start_operation)
  public void startOperation() {

    _logs.clear();
    _log("Button Clicked");

    Observable.fromIterable(
            Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l")) //
        .flatMap(
            s1 -> {
              _log(s1 + "start");

              if (s1.equalsIgnoreCase("b") && _attempt < 5) {
                _attempt++;
                return Observable.error(
                    new Throwable("b can't be processed (" + (_attempt - 1) + ")"));
              }

              if (s1.equalsIgnoreCase("c") || s1.equalsIgnoreCase("f")) {
                return Observable.just(s1);
              } else {
                return Observable.timer(2, TimeUnit.SECONDS).map(l -> s1);
              }
            })
        .retryWhen(source -> source.delay(8, TimeUnit.SECONDS))
        .doOnNext(s -> _log(s + "stop"))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe();
  }