() => {
      type GetTodos = {
        type: 'GET_TODOS';
      };

      type GetTodo = {
        type: 'GET_TODO';
      };

      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodos = this.s.fetch<GetTodos>('GET_TODOS', {
          run: (a, state) => {
            // we need to introduce the delay to "enable" switchMap
            return of({
              type: 'TODOS',
              payload: { user: state.user, todos: 'some todos' }
            }).pipe(delay(1));
          },

          onError: (a, e: any) => null
        });

        @Effect()
        loadTodosWithOperator = this.s.actions.pipe(
          ofType<GetTodos>('GET_TODOS'),
          withLatestFrom(this.s.store),
          fetch({
            run: (action, state) => {
              return of({
                type: 'TODOS',
                payload: { user: state.user, todos: 'some todos' }
              }).pipe(delay(1));
            }
          })
        );

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of(
          { type: 'GET_TODOS', payload: {} },
          { type: 'GET_TODOS', payload: {} }
        );

        expect(await readAll(TestBed.get(TodoEffects).loadTodos)).toEqual([
          { type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } },
          { type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } }
        ]);

        done();
      });

      it('should work with an operator', async done => {
        actions = of(
          { type: 'GET_TODOS', payload: {} },
          { type: 'GET_TODOS', payload: {} }
        );

        expect(
          await readAll(TestBed.get(TodoEffects).loadTodosWithOperator)
        ).toEqual([
          { type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } },
          { type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } }
        ]);

        done();
      });
    }


(a, state) => {
            // we need to introduce the delay to "enable" switchMap
            return of({
              type: 'TODOS',
              payload: { user: state.user, todos: 'some todos' }
            }).pipe(delay(1));
          }


(a, e: any) => null


(action, state) => {
              return of({
                type: 'TODOS',
                payload: { user: state.user, todos: 'some todos' }
              }).pipe(delay(1));
            }


() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      }


async done => {
        actions = of(
          { type: 'GET_TODOS', payload: {} },
          { type: 'GET_TODOS', payload: {} }
        );

        expect(await readAll(TestBed.get(TodoEffects).loadTodos)).toEqual([
          { type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } },
          { type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } }
        ]);

        done();
      }


async done => {
        actions = of(
          { type: 'GET_TODOS', payload: {} },
          { type: 'GET_TODOS', payload: {} }
        );

        expect(
          await readAll(TestBed.get(TodoEffects).loadTodosWithOperator)
        ).toEqual([
          { type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } },
          { type: 'TODOS', payload: { user: 'bob', todos: 'some todos' } }
        ]);

        done();
      }


() => {
      type GetTodo = {
        type: 'GET_TODO';
        payload: { id: string };
      };

      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.fetch<GetTodo>('GET_TODO', {
          id: (a, state) => a.payload.id,
          run: (a, state) =>
            of({ type: 'TODO', payload: a.payload }).pipe(delay(1)),
          onError: (a, e: any) => null
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of(
          { type: 'GET_TODO', payload: { id: 1, value: '1' } },
          { type: 'GET_TODO', payload: { id: 2, value: '2a' } },
          { type: 'GET_TODO', payload: { id: 2, value: '2b' } }
        );

        expect(await readAll(TestBed.get(TodoEffects).loadTodo)).toEqual([
          { type: 'TODO', payload: { id: 1, value: '1' } },
          { type: 'TODO', payload: { id: 2, value: '2b' } }
        ]);

        done();
      });
    }


(a, state) => a.payload.id


(a, state) =>
            of({ type: 'TODO', payload: a.payload }).pipe(delay(1))


async done => {
        actions = of(
          { type: 'GET_TODO', payload: { id: 1, value: '1' } },
          { type: 'GET_TODO', payload: { id: 2, value: '2a' } },
          { type: 'GET_TODO', payload: { id: 2, value: '2b' } }
        );

        expect(await readAll(TestBed.get(TodoEffects).loadTodo)).toEqual([
          { type: 'TODO', payload: { id: 1, value: '1' } },
          { type: 'TODO', payload: { id: 2, value: '2b' } }
        ]);

        done();
      }


() => {
    beforeEach(() => {
      TestBed.configureTestingModule({ providers: [DataPersistence] });
    });

    describe('successful', () => {
      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => ({
            type: 'TODO_UPDATED',
            payload: { user: state.user, newTitle: a.payload.newTitle }
          }),
          onError: (a, e: any) => null
        });

        @Effect()
        loadTodoWithOperator = this.s.actions.pipe(
          ofType<UpdateTodo>('UPDATE_TODO'),
          withLatestFrom(this.s.store),
          pessimisticUpdate({
            run: (a, state) => ({
              type: 'TODO_UPDATED',
              payload: { user: state.user, newTitle: a.payload.newTitle }
            }),
            onError: (a, e: any) => null
          })
        );

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        expect(await readAll(TestBed.get(TodoEffects).loadTodo)).toEqual([
          {
            type: 'TODO_UPDATED',
            payload: { user: 'bob', newTitle: 'newTitle' }
          }
        ]);

        done();
      });

      it('should work with an operator', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        expect(
          await readAll(TestBed.get(TodoEffects).loadTodoWithOperator)
        ).toEqual([
          {
            type: 'TODO_UPDATED',
            payload: { user: 'bob', newTitle: 'newTitle' }
          }
        ]);

        done();
      });
    });

    describe('`run` throws an error', () => {
      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            throw new Error('boom');
          },

          onError: (a, e: any) => ({
            type: 'ERROR',
            payload: { error: e }
          })
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('ERROR');
        expect(a.payload.error.message).toEqual('boom');

        done();
      });
    });

    describe('`run` returns an observable that errors', () => {
      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            return throwError('boom');
          },

          onError: (a, e: any) => ({
            type: 'ERROR',
            payload: { error: e }
          })
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('ERROR');
        expect(a.payload.error).toEqual('boom');

        done();
      });
    });
  }


() => {
      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => ({
            type: 'TODO_UPDATED',
            payload: { user: state.user, newTitle: a.payload.newTitle }
          }),
          onError: (a, e: any) => null
        });

        @Effect()
        loadTodoWithOperator = this.s.actions.pipe(
          ofType<UpdateTodo>('UPDATE_TODO'),
          withLatestFrom(this.s.store),
          pessimisticUpdate({
            run: (a, state) => ({
              type: 'TODO_UPDATED',
              payload: { user: state.user, newTitle: a.payload.newTitle }
            }),
            onError: (a, e: any) => null
          })
        );

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        expect(await readAll(TestBed.get(TodoEffects).loadTodo)).toEqual([
          {
            type: 'TODO_UPDATED',
            payload: { user: 'bob', newTitle: 'newTitle' }
          }
        ]);

        done();
      });

      it('should work with an operator', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        expect(
          await readAll(TestBed.get(TodoEffects).loadTodoWithOperator)
        ).toEqual([
          {
            type: 'TODO_UPDATED',
            payload: { user: 'bob', newTitle: 'newTitle' }
          }
        ]);

        done();
      });
    }


(a, state) => ({
            type: 'TODO_UPDATED',
            payload: { user: state.user, newTitle: a.payload.newTitle }
          })


(a, state) => ({
              type: 'TODO_UPDATED',
              payload: { user: state.user, newTitle: a.payload.newTitle }
            })


async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        expect(await readAll(TestBed.get(TodoEffects).loadTodo)).toEqual([
          {
            type: 'TODO_UPDATED',
            payload: { user: 'bob', newTitle: 'newTitle' }
          }
        ]);

        done();
      }


async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        expect(
          await readAll(TestBed.get(TodoEffects).loadTodoWithOperator)
        ).toEqual([
          {
            type: 'TODO_UPDATED',
            payload: { user: 'bob', newTitle: 'newTitle' }
          }
        ]);

        done();
      }


() => {
      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            throw new Error('boom');
          },

          onError: (a, e: any) => ({
            type: 'ERROR',
            payload: { error: e }
          })
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('ERROR');
        expect(a.payload.error.message).toEqual('boom');

        done();
      });
    }


(a, state) => {
            throw new Error('boom');
          }


(a, e: any) => ({
            type: 'ERROR',
            payload: { error: e }
          })


async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('ERROR');
        expect(a.payload.error.message).toEqual('boom');

        done();
      }


() => {
      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            return throwError('boom');
          },

          onError: (a, e: any) => ({
            type: 'ERROR',
            payload: { error: e }
          })
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('ERROR');
        expect(a.payload.error).toEqual('boom');

        done();
      });
    }


(a, state) => {
            return throwError('boom');
          }


async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('ERROR');
        expect(a.payload.error).toEqual('boom');

        done();
      }


() => {
    beforeEach(() => {
      TestBed.configureTestingModule({ providers: [DataPersistence] });
    });

    describe('`run` throws an error', () => {
      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.optimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            throw new Error('boom');
          },

          undoAction: (a, e: any) => ({
            type: 'UNDO_UPDATE_TODO',
            payload: a.payload
          })
        });

        @Effect()
        loadTodoWithOperator = this.s.actions.pipe(
          ofType<UpdateTodo>('UPDATE_TODO'),
          withLatestFrom(this.s.store),
          optimisticUpdate({
            run: (a, state) => {
              throw new Error('boom');
            },

            undoAction: (a, e: any) => ({
              type: 'UNDO_UPDATE_TODO',
              payload: a.payload
            })
          })
        );

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('UNDO_UPDATE_TODO');
        expect(a.payload.newTitle).toEqual('newTitle');

        done();
      });

      it('should work with an operator', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(
          TestBed.get(TodoEffects).loadTodoWithOperator
        );

        expect(a.type).toEqual('UNDO_UPDATE_TODO');
        expect(a.payload.newTitle).toEqual('newTitle');

        done();
      });
    });
  }


() => {
      @Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.optimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            throw new Error('boom');
          },

          undoAction: (a, e: any) => ({
            type: 'UNDO_UPDATE_TODO',
            payload: a.payload
          })
        });

        @Effect()
        loadTodoWithOperator = this.s.actions.pipe(
          ofType<UpdateTodo>('UPDATE_TODO'),
          withLatestFrom(this.s.store),
          optimisticUpdate({
            run: (a, state) => {
              throw new Error('boom');
            },

            undoAction: (a, e: any) => ({
              type: 'UNDO_UPDATE_TODO',
              payload: a.payload
            })
          })
        );

        constructor(private s: DataPersistence<TodosState>) {}
      }

      function userReducer() {
        return 'bob';
      }

      let actions: Observable<any>;

      beforeEach(() => {
        actions = new Subject<any>();
        TestBed.configureTestingModule({
          providers: [TodoEffects, provideMockActions(() => actions)],
          imports: [StoreModule.forRoot({ user: userReducer })]
        });
      });

      it('should work', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('UNDO_UPDATE_TODO');
        expect(a.payload.newTitle).toEqual('newTitle');

        done();
      });

      it('should work with an operator', async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(
          TestBed.get(TodoEffects).loadTodoWithOperator
        );

        expect(a.type).toEqual('UNDO_UPDATE_TODO');
        expect(a.payload.newTitle).toEqual('newTitle');

        done();
      });
    }


(a, e: any) => ({
            type: 'UNDO_UPDATE_TODO',
            payload: a.payload
          })


(a, state) => {
              throw new Error('boom');
            }


(a, e: any) => ({
              type: 'UNDO_UPDATE_TODO',
              payload: a.payload
            })


async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(TestBed.get(TodoEffects).loadTodo);

        expect(a.type).toEqual('UNDO_UPDATE_TODO');
        expect(a.payload.newTitle).toEqual('newTitle');

        done();
      }


async done => {
        actions = of({
          type: 'UPDATE_TODO',
          payload: { newTitle: 'newTitle' }
        });

        const [a]: any = await readAll(
          TestBed.get(TodoEffects).loadTodoWithOperator
        );

        expect(a.type).toEqual('UNDO_UPDATE_TODO');
        expect(a.payload.newTitle).toEqual('newTitle');

        done();
      }


@Component({
  template: `
    ROOT[<router-outlet></router-outlet>]
  `
})
class RootCmp {}


@Component({
  template: `
    Todo [
    <div *ngIf="(todo | async) as t">ID {{ t.id }} User {{ t.user }}</div>
    ]
  `
})
class TodoComponent {
  todo = this.store.select('todos', 'selected');
  constructor(private store: Store<TodosState>) {}
}


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.navigation(TodoComponent, {
          run: (a, state) => {
            return {
              type: 'TODO_LOADED',
              payload: { id: a.params['id'], user: state.user }
            };
          },
          onError: () => null
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.navigation(TodoComponent, {
          run: (a, state) => {
            if (a.params['id'] === '123') {
              throw new Error('boom');
            } else {
              return {
                type: 'TODO_LOADED',
                payload: { id: a.params['id'], user: state.user }
              };
            }
          },
          onError: (a, e) => ({ type: 'ERROR', payload: { error: e } })
        });
        constructor(private s: DataPersistence<TodosState>) {}
      }


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.navigation(TodoComponent, {
          run: (a, state) => {
            if (a.params['id'] === '123') {
              return throwError('boom');
            } else {
              return {
                type: 'TODO_LOADED',
                payload: { id: a.params['id'], user: state.user }
              };
            }
          },
          onError: (a, e) => ({ type: 'ERROR', payload: { error: e } })
        });
        constructor(private s: DataPersistence<TodosState>) {}
      }


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodos = this.s.fetch<GetTodos>('GET_TODOS', {
          run: (a, state) => {
            // we need to introduce the delay to "enable" switchMap
            return of({
              type: 'TODOS',
              payload: { user: state.user, todos: 'some todos' }
            }).pipe(delay(1));
          },

          onError: (a, e: any) => null
        });

        @Effect()
        loadTodosWithOperator = this.s.actions.pipe(
          ofType<GetTodos>('GET_TODOS'),
          withLatestFrom(this.s.store),
          fetch({
            run: (action, state) => {
              return of({
                type: 'TODOS',
                payload: { user: state.user, todos: 'some todos' }
              }).pipe(delay(1));
            }
          })
        );

        constructor(private s: DataPersistence<TodosState>) {}
      }


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.fetch<GetTodo>('GET_TODO', {
          id: (a, state) => a.payload.id,
          run: (a, state) =>
            of({ type: 'TODO', payload: a.payload }).pipe(delay(1)),
          onError: (a, e: any) => null
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => ({
            type: 'TODO_UPDATED',
            payload: { user: state.user, newTitle: a.payload.newTitle }
          }),
          onError: (a, e: any) => null
        });

        @Effect()
        loadTodoWithOperator = this.s.actions.pipe(
          ofType<UpdateTodo>('UPDATE_TODO'),
          withLatestFrom(this.s.store),
          pessimisticUpdate({
            run: (a, state) => ({
              type: 'TODO_UPDATED',
              payload: { user: state.user, newTitle: a.payload.newTitle }
            }),
            onError: (a, e: any) => null
          })
        );

        constructor(private s: DataPersistence<TodosState>) {}
      }


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            throw new Error('boom');
          },

          onError: (a, e: any) => ({
            type: 'ERROR',
            payload: { error: e }
          })
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.pessimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            return throwError('boom');
          },

          onError: (a, e: any) => ({
            type: 'ERROR',
            payload: { error: e }
          })
        });

        constructor(private s: DataPersistence<TodosState>) {}
      }


@Injectable()
      class TodoEffects {
        @Effect()
        loadTodo = this.s.optimisticUpdate<UpdateTodo>('UPDATE_TODO', {
          run: (a, state) => {
            throw new Error('boom');
          },

          undoAction: (a, e: any) => ({
            type: 'UNDO_UPDATE_TODO',
            payload: a.payload
          })
        });

        @Effect()
        loadTodoWithOperator = this.s.actions.pipe(
          ofType<UpdateTodo>('UPDATE_TODO'),
          withLatestFrom(this.s.store),
          optimisticUpdate({
            run: (a, state) => {
              throw new Error('boom');
            },

            undoAction: (a, e: any) => ({
              type: 'UNDO_UPDATE_TODO',
              payload: a.payload
            })
          })
        );

        constructor(private s: DataPersistence<TodosState>) {}
      }


// interfaces
type Todo = {
  id: number;
  user: string;
};


type Todos = {
  selected: Todo;
};


type TodosState = {
  todos: Todos;
  user: string;
};


// actions
type TodoLoaded = {
  type: 'TODO_LOADED';
  payload: Todo;
};


type UpdateTodo = {
  type: 'UPDATE_TODO';
  payload: { newTitle: string };
};


type Action = TodoLoaded;


type GetTodos = {
        type: 'GET_TODOS';
      };


type GetTodo = {
        type: 'GET_TODO';
      };


type GetTodo = {
        type: 'GET_TODO';
        payload: { id: string };
      };


()=>{
        this.mcserivce.findAll().subscribe(
          data => this.mclist=data

        )
      }


data => this.mclist=data


@Component({
  selector: 'app-mc-service-list',
  templateUrl: './mc-service-list.component.html',
  styleUrls: ['./mc-service-list.component.scss']
})
export class McServiceListComponent implements OnInit {

  mclist:MasterCeremony[];

  constructor(private mcserivce:McService,private route:Router) {

  }

  ngOnInit() {

      setTimeout(()=>{
        this.mcserivce.findAll().subscribe(
          data => this.mclist=data

        )
      },500)
    }

  public onSelect(mc){
    this.route.navigate(['mc-details',mc.name]);
  }

}


ngOnInit() {

      setTimeout(()=>{
        this.mcserivce.findAll().subscribe(
          data => this.mclist=data

        )
      },500)
    }


public onSelect(mc){
    this.route.navigate(['mc-details',mc.name]);
  }


export default class VideoChatBubble extends React.Component<VideoChatBubbleProps, VideoChatBubbleState> {

    readonly state = {
        fullscreen: false,
        level: 0,
        intervalId: 0
    };

    private readonly videoRef: RefObject<Video>;

    constructor(props: VideoChatBubbleProps) {
        super(props);
        this.videoRef = React.createRef<Video>();
    }

    componentDidUpdate(prevProps: VideoChatBubbleProps, prevState: VideoChatBubbleState) {
        if (prevProps.stream !== this.props.stream) {
            return true;
        } else {
            return false;
        }
    }

    private toggleFullScreen() {
        this.setState({
            fullscreen: !this.state.fullscreen
        })
    }

    render() {

        const { stream, index } = this.props;
        const { fullscreen } = this.state;

        const video = <Video ref={this.videoRef} className={fullscreen ? 'video-fullscreen' : 'bubble-video'} stream={stream}
            key="small" id={fullscreen ? '' : 'small' + index} muted={this.props.muted}/>;

        return (

 this.toggleFullScreen()}


interface VideoChatBubbleProps {
    stream: Promise<MediaStream>
    className?: string
    index: number
    muted: boolean
}


interface VideoChatBubbleState {
    fullscreen: boolean
    level: number
    intervalId?: number
}


componentDidUpdate(prevProps: VideoChatBubbleProps, prevState: VideoChatBubbleState) {
        if (prevProps.stream !== this.props.stream) {
            return true;
        } else {
            return false;
        }
    }


private toggleFullScreen() {
        this.setState({
            fullscreen: !this.state.fullscreen
        })
    }


render() {

        const { stream, index } = this.props;
        const { fullscreen } = this.state;

        const video = <Video ref={this.videoRef} className={fullscreen ? 'video-fullscreen' : 'bubble-video'} stream={stream}
            key="small" id={fullscreen ? '' : 'small' + index} muted={this.props.muted}/>;

        return (

 this.toggleFullScreen()}


fullscreen ? <FaCompress


function Session(props: SessionsData){
    return (
        <Link className={styles.program} to={`/workshops/${props.id}`}


function Sessions(props: {data: [SessionsData]}){
    const sessions = props.data.filter(s => s.format === "workshop")
    const orderedSession = sessions.sort(
        (a,b) => {
            if (a.length < b.length) {
                return 1
            }
            return -1
        })

    return <> {
        orderedSession.map(s => <Session {...s}/>)
    } </>
}


export function Workshop() {
    const {data} = useFetch<ProgramData>("https://sleepingpill.javazone.no/public/allSessions/javazone_2021")

    return <div className={styles.container}>
        {!!data && <Sessions data={data.sessions}/>}
    </div>
}


speaker => speaker.name


s => s.format === "workshop"


(a,b) => {
            if (a.length < b.length) {
                return 1
            }
            return -1
        }


s => <Session {...s}/>


@NgModule({
    imports: [
        ComponentsModule,
        FormsModule,
        BrowserModule,
    ],
    declarations: [
    ]
})
export class ViewsModule { }


export interface QlikConfigInterface {
    useWss: boolean;
    address: string;
    port: number;
}


export default function SignIn(props: Props) {
  const {title, type} = props

  return(
    <Root>
      <Step active={true} completed={false}>
        <StepIcon icon={
<LockIcon />
} />
        <StepLabel>
          {title ? title : 'Please sign in.'}
        </StepLabel>
      </Step>

      <SignInForm type={type} />
    </Root>
  )
}


type Props = {
  title?: string
  type?: 'service' | 'workspace'
}


(mark: Mark): ComponentType<any> => {
  return markToReact[mark.type.name];
}


(Base: typeof BackendUser) => {
  class User extends Routable(Base) {
    ['constructor']!: typeof User;

    @consume() static Session: ReturnType<typeof Session>;
    @consume() static Home: typeof Home;
    @consume() static Common: typeof Common;

    @route('/sign-up') @view() static SignUp() {
      const {Session, Home} = this;

      if (Session.user) {
        Home.Main.redirect();
        return null;
      }

      const user = new (this.fork())();

      return <user.SignUp />;
    }

    @view() SignUp() {
      const {Home, Common} = this.constructor;

      const [inviteToken, setInviteToken] = useState('');

      const [handleSignUp, isSigningUp, signingUpError] = useAsyncCallback(async () => {
        await this.signUp({inviteToken});
        Home.Main.reload();
      }, [inviteToken]);

      return (
        <Common.Layout title="Sign up" width="400px">

Sign Up

          {signingUpError && <Common.ErrorMessage error={signingUpError} />}

          <form
            onSubmit={(event)


async () => {
        await this.signUp({inviteToken});
        Home.Main.reload();
      }


async () => {
        await this.signIn();
        Home.Main.reload();
      }


async () => {
        return await this.generateInviteToken();
      }


class User extends Routable(Base) {
    ['constructor']!: typeof User;

    @consume() static Session: ReturnType<typeof Session>;
    @consume() static Home: typeof Home;
    @consume() static Common: typeof Common;

    @route('/sign-up') @view() static SignUp() {
      const {Session, Home} = this;

      if (Session.user) {
        Home.Main.redirect();
        return null;
      }

      const user = new (this.fork())();

      return <user.SignUp />;
    }

    @view() SignUp() {
      const {Home, Common} = this.constructor;

      const [inviteToken, setInviteToken] = useState('');

      const [handleSignUp, isSigningUp, signingUpError] = useAsyncCallback(async () => {
        await this.signUp({inviteToken});
        Home.Main.reload();
      }, [inviteToken]);

      return (
        <Common.Layout title="Sign up" width="400px">

Sign Up

          {signingUpError && <Common.ErrorMessage error={signingUpError} />}

          <form
            onSubmit={(event)


@route('/sign-up') @view() static SignUp() {
      const {Session, Home} = this;

      if (Session.user) {
        Home.Main.redirect();
        return null;
      }

      const user = new (this.fork())();

      return <user.SignUp />;
    }


@view() SignUp() {
      const {Home, Common} = this.constructor;

      const [inviteToken, setInviteToken] = useState('');

      const [handleSignUp, isSigningUp, signingUpError] = useAsyncCallback(async () => {
        await this.signUp({inviteToken});
        Home.Main.reload();
      }, [inviteToken]);

      return (
        <Common.Layout title="Sign up" width="400px">

Sign Up

          {signingUpError && <Common.ErrorMessage error={signingUpError} />}

          <form
            onSubmit={(event)


export interface DateRange {
  start?: string | Date;
  end?: string | Date;
}


export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);

    return { ...initialProps };
  }

  render() {
    return (
      <Html lang="en">
        <Head>
          {isProduction && (
            <>
              <script
                async
                src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GA_TRACKING_ID}`}


static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);

    return { ...initialProps };
  }


render() {
    return (
      <Html lang="en">
        <Head>
          {isProduction && (
            <>
              <script
                async
                src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GA_TRACKING_ID}`}


params => params.has('tabLink')


params => params.get('tabLink')


@Component({
  selector: 'app-home-container',
  templateUrl: './home-container.component.html',
  styleUrls: ['./home-container.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class HomeContainerComponent implements OnInit {

  topMenus$: Observable<TopMenu[]>;

  selectedTabLink$: Observable<string>;

  ngOnInit(): void {
    this.topMenus$ = this.service.getTabs();

    this.selectedTabLink$ = this.activatedRoute.firstChild.paramMap.pipe(
      filter(params => params.has('tabLink')),
      map(params => params.get('tabLink'))
    );
  }

  handleTabSelected(topMenu: TopMenu) {
    this.router.navigate(['home', topMenu.link]);
  }

  constructor(
    private router: Router, // 路由服务，用于路由跳转
    private service: HomeService,
    private activatedRoute: ActivatedRoute // 当前激活路由，用于路由参数获取
  ) { }
}


ngOnInit(): void {
    this.topMenus$ = this.service.getTabs();

    this.selectedTabLink$ = this.activatedRoute.firstChild.paramMap.pipe(
      filter(params => params.has('tabLink')),
      map(params => params.get('tabLink'))
    );
  }


handleTabSelected(topMenu: TopMenu) {
    this.router.navigate(['home', topMenu.link]);
  }


() => {
  beforeEach(() => cy.visit('/'));

  it('should display welcome message', () => {
    // Custom command example, see `../support/commands.ts` file
    cy.login('my-email@something.com', 'myPassword');

    // Function helper example, see `../support/app.po.ts` file
    getGreeting().contains('Welcome four-fours');
  });
}


() => cy.visit('/')


() => {
    // Custom command example, see `../support/commands.ts` file
    cy.login('my-email@something.com', 'myPassword');

    // Function helper example, see `../support/app.po.ts` file
    getGreeting().contains('Welcome four-fours');
  }


@Component({
  computed: {...mapState({activeAccount: 'account', app: 'app'})},
  components: {
    LineChart,
    TransactionList,
  },
})
export class MonitorDashBoardTs extends Vue {
  app: AppInfo
  activeAccount: StoreAccount
  updateAnimation = ''
  networkStatusList = networkStatusConfig
  page = 1
  formatNumber = formatNumber

  get wallet() {
    return this.activeAccount.wallet
  }

  get NetworkProperties() {
    return this.app.networkProperties
  }
}


<T>(
    promises: Iterable<Promise<T>>
): Subscription<T[], T> =>
    fromPromise(Promise.all(promises)).transform(mapcat((x: T[]) => x))


(x: T[]) => x


() => {
  let component: TestPage;
  let fixture: ComponentFixture<TestPage>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [TestPage],
      imports: [IonicModule.forRoot()]
    }).compileComponents();

    fixture = TestBed.createComponent(TestPage);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }));

  it('should create', () => {
    expect(component).toBeTruthy();
  });
}


() => {
    TestBed.configureTestingModule({
      declarations: [TestPage],
      imports: [IonicModule.forRoot()]
    }).compileComponents();

    fixture = TestBed.createComponent(TestPage);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }


/* ----------------------------------------------------------------------------
 * Helper functions
 * ------------------------------------------------------------------------- */
/**
 * Compute whether the header is hidden
 *
 * If the user scrolls past a certain threshold, the header can be hidden when
 * scrolling down, and shown when scrolling up.
 *
 * @param options - Options
 *
 * @returns Toggle observable
 */
function isHidden({ viewport$ }: WatchOptions): Observable<boolean> {
  if (!feature("header.autohide"))
    return of(false)

  /* Compute direction and turning point */
  const direction$ = viewport$
    .pipe(
      map(({ offset: { y } }) => y),
      bufferCount(2, 1),
      map(([a, b]) => [a < b, b] as const),
      distinctUntilKeyChanged(0)
    )

  /* Compute whether header should be hidden */
  const hidden$ = combineLatest([viewport$, direction$])
    .pipe(
      filter(([{ offset }, [, y]]) => Math.abs(y - offset.y) > 100),
      map(([, [direction]]) => direction),
      distinctUntilChanged()
    )

  /* Compute threshold for hiding */
  const search$ = watchToggle("search")
  return combineLatest([viewport$, search$])
    .pipe(
      map(([{ offset }, search]) => offset.y > 400 && !search),
      distinctUntilChanged(),
      switchMap(active => active ? hidden$ : of(false)),
      startWith(false)
    )
}


/* ----------------------------------------------------------------------------
 * Functions
 * ------------------------------------------------------------------------- */
/**
 * Watch header
 *
 * @param el - Header element
 * @param options - Options
 *
 * @returns Header observable
 */
export function watchHeader(
  el: HTMLElement, options: WatchOptions
): Observable<Header> {
  return defer(() => {
    const styles = getComputedStyle(el)
    return of(
      styles.position === "sticky" ||
      styles.position === "-webkit-sticky"
    )
  })
    .pipe(
      combineLatestWith(watchElementSize(el), isHidden(options)),
      map(([sticky, { height }, hidden]) => ({
        height: sticky ? height : 0,
        sticky,
        hidden
      })),
      distinctUntilChanged((a, b) => (
        a.sticky === b.sticky &&
        a.height === b.height &&
        a.hidden === b.hidden
      )),
      shareReplay(1)
    )
}


/**
 * Mount header
 *
 * This function manages the different states of the header, i.e. whether it's
 * hidden or rendered with a shadow. This depends heavily on the main area.
 *
 * @param el - Header element
 * @param options - Options
 *
 * @returns Header component observable
 */
export function mountHeader(
  el: HTMLElement, { header$, main$ }: MountOptions
): Observable<Component<Header>> {
  return defer(() => {
    const push$ = new Subject<Main>()
    push$
      .pipe(
        distinctUntilKeyChanged("active"),
        combineLatestWith(header$)
      )
        .subscribe(([{ active }, { hidden }]) => {
          if (active)
            el.setAttribute("data-md-state", hidden ? "hidden" : "shadow")
          else
            el.removeAttribute("data-md-state")
        })

    /* Link to main area */
    main$.subscribe(push$)

    /* Create and return component */
    return header$
      .pipe(
        takeUntil(push$.pipe(takeLast(1))),
        map(state => ({ ref: el, ...state }))
      )
  })
}


({ offset: { y } }) => y


([a, b]) => [a < b, b] as const


([{ offset }, [, y]]) => Math.abs(y - offset.y) > 100


([, [direction]]) => direction


([{ offset }, search]) => offset.y > 400 && !search


active => active ? hidden$ : of(false)


() => {
    const styles = getComputedStyle(el)
    return of(
      styles.position === "sticky" ||
      styles.position === "-webkit-sticky"
    )
  }


([sticky, { height }, hidden]) => ({
        height: sticky ? height : 0,
        sticky,
        hidden
      })


(a, b) => (
        a.sticky === b.sticky &&
        a.height === b.height &&
        a.hidden === b.hidden
      )


() => {
    const push$ = new Subject<Main>()
    push$
      .pipe(
        distinctUntilKeyChanged("active"),
        combineLatestWith(header$)
      )
        .subscribe(([{ active }, { hidden }]) => {
          if (active)
            el.setAttribute("data-md-state", hidden ? "hidden" : "shadow")
          else
            el.removeAttribute("data-md-state")
        })

    /* Link to main area */
    main$.subscribe(push$)

    /* Create and return component */
    return header$
      .pipe(
        takeUntil(push$.pipe(takeLast(1))),
        map(state => ({ ref: el, ...state }))
      )
  }


([{ active }, { hidden }]) => {
          if (active)
            el.setAttribute("data-md-state", hidden ? "hidden" : "shadow")
          else
            el.removeAttribute("data-md-state")
        }


state => ({ ref: el, ...state })


/* ----------------------------------------------------------------------------
 * Types
 * ------------------------------------------------------------------------- */
/**
 * Header
 */
export interface Header {
  height: number                       /* Header visible height */
  sticky: boolean                      /* Header stickyness */
  hidden: boolean                      /* Header is hidden */
}


/* ----------------------------------------------------------------------------
 * Helper types
 * ------------------------------------------------------------------------- */
/**
 * Watch options
 */
interface WatchOptions {
  viewport$: Observable<Viewport>      /* Viewport observable */
}


/**
 * Mount options
 */
interface MountOptions {
  viewport$: Observable<Viewport>      /* Viewport observable */
  header$: Observable<Header>          /* Header observable */
  main$: Observable<Main>              /* Main area observable */
}


async fn() {
    const res = createMockResponse();
    res.body = "hello";
    const expected = {
      status: 200,
      message: "OK",
      headers: new Headers({
        "cache-control": "max-age=0",
        "content-type": "text/plain; charset=utf-8",
        "content-length": "5",
      }),
      body: "hello",
    };

    assertEquals(res.inspect(), expected);
  }


highScores => highScores.map(e => HighscoreDto.fromEntity(e))


e => HighscoreDto.fromEntity(e)


@Injectable()
export class HighscoresRepository {
  private entity: string = "high_scores";

  constructor(
    @InjectRepository(HighScoreEntity)
    private readonly repo: Repository<HighScoreEntity>,
  ) {}

  public async allBySeasonIdRaw(
    seasonId: string,
    currentSeasonId: string,
    limit: number = 0,
  ) {
    const take = limit ? limit : seasonId === currentSeasonId ? 50 : 20;
    // Using joins to fetch logotypeUrl that related to the bots team.
    const highScores = await this.repo
      .createQueryBuilder(this.entity)
      .select(this.entity)
      .where("highScores.seasonId = :seasonId", { seasonId: seasonId })
      .leftJoinAndSelect(
        BotRegistrationsEntity,
        "bot",
        "high_scores.botName = bot.botName",
      )
      .leftJoinAndSelect(TeamsEntity, "teams", "bot.team = teams.id")
      .orderBy("score", "DESC")
      .limit(take)
      .execute();

    return highScores;
  }

  public getBotScore(botName: string) {
    return this.repo
      .find({
        where: [{ botName }],
      })
      .then(highScores => highScores.map(e => HighscoreDto.fromEntity(e)));
  }

  public async getBestBotScore(botName: string, seasonId: string) {
    return await this.repo
      .createQueryBuilder(this.entity)
      .select(this.entity)
      .where(
        "high_scores.botName = :botName AND high_scores.seasonId = :seasonId",
        {
          botName,
          seasonId,
        },
      )
      .getOne();
  }

  public async updateBestBotScore(
    botName: string,
    seasonId: string,
    score: number,
  ) {
    await this.repo
      .createQueryBuilder()
      .update(this.entity)
      .set({ score })
      .where("botName = :botName AND seasonId = :seasonId", {
        botName,
        seasonId,
      })
      .execute();
  }

  public async create(dto: HighscoreDto): Promise<HighscoreDto> {
    return this.repo.save(dto);
  }

  public async delete(botName: string) {
    return await this.repo
      .createQueryBuilder()
      .delete()
      .from(this.entity)
      .where("botName = :botName", { botName })
      .execute();
  }
}


public async allBySeasonIdRaw(
    seasonId: string,
    currentSeasonId: string,
    limit: number = 0,
  ) {
    const take = limit ? limit : seasonId === currentSeasonId ? 50 : 20;
    // Using joins to fetch logotypeUrl that related to the bots team.
    const highScores = await this.repo
      .createQueryBuilder(this.entity)
      .select(this.entity)
      .where("highScores.seasonId = :seasonId", { seasonId: seasonId })
      .leftJoinAndSelect(
        BotRegistrationsEntity,
        "bot",
        "high_scores.botName = bot.botName",
      )
      .leftJoinAndSelect(TeamsEntity, "teams", "bot.team = teams.id")
      .orderBy("score", "DESC")
      .limit(take)
      .execute();

    return highScores;
  }


public getBotScore(botName: string) {
    return this.repo
      .find({
        where: [{ botName }],
      })
      .then(highScores => highScores.map(e => HighscoreDto.fromEntity(e)));
  }


public async getBestBotScore(botName: string, seasonId: string) {
    return await this.repo
      .createQueryBuilder(this.entity)
      .select(this.entity)
      .where(
        "high_scores.botName = :botName AND high_scores.seasonId = :seasonId",
        {
          botName,
          seasonId,
        },
      )
      .getOne();
  }


public async updateBestBotScore(
    botName: string,
    seasonId: string,
    score: number,
  ) {
    await this.repo
      .createQueryBuilder()
      .update(this.entity)
      .set({ score })
      .where("botName = :botName AND seasonId = :seasonId", {
        botName,
        seasonId,
      })
      .execute();
  }


public async create(dto: HighscoreDto): Promise<HighscoreDto> {
    return this.repo.save(dto);
  }


public async delete(botName: string) {
    return await this.repo
      .createQueryBuilder()
      .delete()
      .from(this.entity)
      .where("botName = :botName", { botName })
      .execute();
  }


filter => ({
  type: SET_PREVIOUS_QUERIES_FILTER,
  payload: { filter }
})


(value: any) =>
          isUndefined(value) || isUndefined(value.isValid)
            ? {
              isValid: !isUndefined(value),
              value
            }
            : value


(value, index) => (
          <Component
            defaultValue={value}


(index: number) => {
    return (value: RawParam): void => {
      this.setState(
        ({ values }: State) => ({
          values: values.map((svalue, sindex) =>
            (sindex === index)
              ? value
              : svalue
        )}),
        () => {
          const { values } = this.state;
          const { onChange } = this.props;

          onChange && onChange({
            isValid: values.reduce((result: boolean, { isValid }) => result && isValid, true),
            value: values.map(({ value }) => value)
          });
        }
      );
    };
  }


(value: RawParam): void => {
      this.setState(
        ({ values }: State) => ({
          values: values.map((svalue, sindex) =>
            (sindex === index)
              ? value
              : svalue
        )}),
        () => {
          const { values } = this.state;
          const { onChange } = this.props;

          onChange && onChange({
            isValid: values.reduce((result: boolean, { isValid }) => result && isValid, true),
            value: values.map(({ value }) => value)
          });
        }
      );
    }


({ values }: State) => ({
          values: values.map((svalue, sindex) =>
            (sindex === index)
              ? value
              : svalue
        )})


(svalue, sindex) =>
            (sindex === index)
              ? value
              : svalue


() => {
          const { values } = this.state;
          const { onChange } = this.props;

          onChange && onChange({
            isValid: values.reduce((result: boolean, { isValid }) => result && isValid, true),
            value: values.map(({ value }) => value)
          });
        }


(): void => {
    this.setState(({ values }: State, { type: { sub } }: Props) => {
      const value = getInitValue(sub as TypeDef);

      return {
        values: values.concat({
          isValid: !isUndefined(value),
          value
        })
      };
    });
  }


({ values }: State, { type: { sub } }: Props) => {
      const value = getInitValue(sub as TypeDef);

      return {
        values: values.concat({
          isValid: !isUndefined(value),
          value
        })
      };
    }


(): void => {
    this.setState(({ values }: State) => ({
      values: values.slice(0, values.length - 1)
    }));
  }


({ values }: State) => ({
      values: values.slice(0, values.length - 1)
    })


class Vector extends React.PureComponent<Props, State> {
  state: State = {
    Component: null,
    values: []
  };

  static getDerivedStateFromProps ({ defaultValue: { value = [] }, isDisabled, type: { sub, type } }: Props, prevState: State): Partial<State> | null {
    if (type === prevState.type) {
      return null;
    }

    const values: Array<RawParam> = isDisabled || prevState.values.length === 0
      ? value.map((value: any) =>
          isUndefined(value) || isUndefined(value.isValid)
            ? {
              isValid: !isUndefined(value),
              value
            }
            : value
        )
      : prevState.values;

    return {
      Component: findComponent(sub as TypeDef),
      type,
      values
    };
  }

  render () {
    const { className, isDisabled, onEnter, style, type, withLabel } = this.props;
    const { Component, values } = this.state;
    const subType = type.sub as TypeDef;

    if (!Component) {
      return null;
    }

    return (
      <Bare
        className={className}
        style={style}
      >
        {values.map((value, index) => (
          <Component
            defaultValue={value}
            isDisabled={isDisabled}
            key={index}
            label={`${index}: ${subType.type}`}
            onChange={this.onChange(index)}
            onEnter={onEnter}
            type={subType}
            withLabel={withLabel}
          />
        ))}


type Props = BareProps & WithTranslation;


type State = {
  Component: React.ComponentType<BareProps> | null,
  type?: string,
  values: Array<RawParam>
};


static getDerivedStateFromProps ({ defaultValue: { value = [] }, isDisabled, type: { sub, type } }: Props, prevState: State): Partial<State> | null {
    if (type === prevState.type) {
      return null;
    }

    const values: Array<RawParam> = isDisabled || prevState.values.length === 0
      ? value.map((value: any) =>
          isUndefined(value) || isUndefined(value.isValid)
            ? {
              isValid: !isUndefined(value),
              value
            }
            : value
        )
      : prevState.values;

    return {
      Component: findComponent(sub as TypeDef),
      type,
      values
    };
  }


render () {
    const { className, isDisabled, onEnter, style, type, withLabel } = this.props;
    const { Component, values } = this.state;
    const subType = type.sub as TypeDef;

    if (!Component) {
      return null;
    }

    return (
      <Bare
        className={className}
        style={style}
      >
        {values.map((value, index) => (
          <Component
            defaultValue={value}
            isDisabled={isDisabled}
            key={index}
            label={`${index}: ${subType.type}`}
            onChange={this.onChange(index)}
            onEnter={onEnter}
            type={subType}
            withLabel={withLabel}
          />
        ))}


t('Add item')


t('Remove item')


export declare class HttpRequest {
    private httpClient;
    constructor(baseURL: string);
    get(path: string, params?: any, opts?: AxiosRequestConfig): Promise<{
        result: any;
        status: number;
    }>;
    post(path: string, body?: any, opts?: AxiosRequestConfig): Promise<{
        result: any;
        status: number;
    }>;
    request(method: Method, path: string, params?: any, opts?: AxiosRequestConfig): Promise<{
        result: any;
        status: number;
    }>;
}


get(path: string, params?: any, opts?: AxiosRequestConfig): Promise<{
        result: any;
        status: number;
    }>;


post(path: string, body?: any, opts?: AxiosRequestConfig): Promise<{
        result: any;
        status: number;
    }>;


request(method: Method, path: string, params?: any, opts?: AxiosRequestConfig): Promise<{
        result: any;
        status: number;
    }>;


function sortNoop (): number {
  return 0;
}


function sortLinks (a: SortOption, b: SortOption): number {
  return !!a.isUnreachable !== !!b.isUnreachable
    ? a.isUnreachable
      ? 1
      : -1
    : 0;
}


function expandLinked (input: LinkOption[]): LinkOption[] {
  const valueRelay = input.map(({ value }) => value);

  return input.reduce((result: LinkOption[], entry): LinkOption[] => {
    result.push(entry);

    return entry.linked
      ? result.concat(
        expandLinked(entry.linked).map((child): LinkOption => {
          child.genesisHashRelay = entry.genesisHash;
          child.isChild = true;
          child.valueRelay = valueRelay;

          return child;
        })
      )
      : result;
  }, []);
}


function expandEndpoint (t: TFunction, { dnslink, genesisHash, homepage, info, isChild, isDisabled, isUnreachable, linked, paraId, providers, teleport, text }: EndpointOption, firstOnly: boolean, withSort: boolean): LinkOption[] {
  const base = {
    genesisHash,
    homepage,
    info,
    isChild,
    isDisabled,
    isUnreachable,
    paraId,
    teleport,
    text
  };

  const result = Object
    .entries(providers)
    .filter((_, index) => !firstOnly || index === 0)
    .map(([host, value], index): LinkOption => ({
      ...base,
      dnslink: index === 0 ? dnslink : undefined,
      isLightClient: value.startsWith('light://'),
      isRelay: false,
      textBy: value.startsWith('light://')
        ? t('lightclient.experimental', 'light client (experimental)', { ns: 'apps-config' })
        : t('rpc.hosted.via', 'via {{host}}', { ns: 'apps-config', replace: { host } }),
      value
    }));

  if (linked) {
    const last = result[result.length - 1];
    const options: LinkOption[] = [];

    linked
      .sort(withSort ? sortLinks : sortNoop)
      .filter(({ paraId }) => paraId)
      .forEach((o) =>
        options.push(...expandEndpoint(t, o, firstOnly, withSort))
      );

    last.isRelay = true;
    last.linked = options;
  }

  return expandLinked(result);
}


export function expandEndpoints (t: TFunction, input: EndpointOption[], firstOnly: boolean, withSort: boolean): LinkOption[] {
  return input
    .sort(withSort ? sortLinks : sortNoop)
    .reduce((all: LinkOption[], e) =>
      all.concat(expandEndpoint(t, e, firstOnly, withSort)), []);
}


(result: LinkOption[], entry): LinkOption[] => {
    result.push(entry);

    return entry.linked
      ? result.concat(
        expandLinked(entry.linked).map((child): LinkOption => {
          child.genesisHashRelay = entry.genesisHash;
          child.isChild = true;
          child.valueRelay = valueRelay;

          return child;
        })
      )
      : result;
  }


(child): LinkOption => {
          child.genesisHashRelay = entry.genesisHash;
          child.isChild = true;
          child.valueRelay = valueRelay;

          return child;
        }


(_, index) => !firstOnly || index === 0


([host, value], index): LinkOption => ({
      ...base,
      dnslink: index === 0 ? dnslink : undefined,
      isLightClient: value.startsWith('light://'),
      isRelay: false,
      textBy: value.startsWith('light://')
        ? t('lightclient.experimental', 'light client (experimental)', { ns: 'apps-config' })
        : t('rpc.hosted.via', 'via {{host}}', { ns: 'apps-config', replace: { host } }),
      value
    })


({ paraId }) => paraId


(o) =>
        options.push(...expandEndpoint(t, o, firstOnly, withSort))


(all: LinkOption[], e) =>
      all.concat(expandEndpoint(t, e, firstOnly, withSort))


interface SortOption {
  isUnreachable?: boolean;
}


(t) => {
        if (t.name === 'rlpx') {
          t.options.bootnodes = t.options.bootnodes || this.common.bootstrapNodes()
          return new RlpxServer({ config: this, ...t.options })
        } else {
          return new Libp2pServer({ config: this, ...t.options })
        }
      }


export class Config {
  // Initialize Common with an explicit 'chainstart' HF set until
  // hardfork awareness is implemented within the library
  // Also a fix for https://github.com/ethereumjs/ethereumjs-vm/issues/757
  public static readonly COMMON_DEFAULT = new Common({ chain: 'mainnet', hardfork: 'chainstart' })
  public static readonly SYNCMODE_DEFAULT = 'full'
  public static readonly LIGHTSERV_DEFAULT = false
  public static readonly DATADIR_DEFAULT = `./datadir`
  public static readonly TRANSPORTS_DEFAULT = ['rlpx:port=30303', 'libp2p']
  public static readonly RPC_DEFAULT = false
  public static readonly RPCPORT_DEFAULT = 8545
  public static readonly RPCADDR_DEFAULT = 'localhost'
  public static readonly LOGLEVEL_DEFAULT = 'info'
  public static readonly MINPEERS_DEFAULT = 2
  public static readonly MAXPEERS_DEFAULT = 25

  public readonly common: Common
  public readonly logger: Logger
  public readonly syncmode: string
  public readonly vm?: VM
  public readonly lightserv: boolean
  public readonly datadir: string
  public readonly transports: string[]
  public readonly rpc: boolean
  public readonly rpcport: number
  public readonly rpcaddr: string
  public readonly loglevel: string
  public readonly minPeers: number
  public readonly maxPeers: number

  public readonly servers: (RlpxServer | Libp2pServer)[] = []

  constructor(options: ConfigOptions = {}) {
    // TODO: map chainParams (and lib/util.parseParams) to new Common format
    this.common = options.common ?? Config.COMMON_DEFAULT
    this.syncmode = options.syncmode ?? Config.SYNCMODE_DEFAULT
    this.vm = options.vm
    this.lightserv = options.lightserv ?? Config.LIGHTSERV_DEFAULT
    this.transports = options.transports ?? Config.TRANSPORTS_DEFAULT
    this.datadir = options.datadir ?? Config.DATADIR_DEFAULT
    this.rpc = options.rpc ?? Config.RPC_DEFAULT
    this.rpcport = options.rpcport ?? Config.RPCPORT_DEFAULT
    this.rpcaddr = options.rpcaddr ?? Config.RPCADDR_DEFAULT
    this.loglevel = options.loglevel ?? Config.LOGLEVEL_DEFAULT
    this.minPeers = options.minPeers ?? Config.MINPEERS_DEFAULT
    this.maxPeers = options.maxPeers ?? Config.MAXPEERS_DEFAULT

    if (options.logger) {
      if (options.loglevel) {
        throw new Error('Config initialization with both logger and loglevel options not allowed')
      }

      // Logger option takes precedence
      this.logger = options.logger
    } else {
      this.logger = getLogger({ loglevel: this.loglevel })
    }

    if (options.servers) {
      if (options.transports) {
        throw new Error(
          'Config initialization with both servers and transports options not allowed'
        )
      }

      // Servers option takes precedence
      this.servers = options.servers
    } else {
      // Otherwise parse transports from transports option
      this.servers = parseTransports(this.transports).map((t) => {
        if (t.name === 'rlpx') {
          t.options.bootnodes = t.options.bootnodes || this.common.bootstrapNodes()
          return new RlpxServer({ config: this, ...t.options })
        } else {
          return new Libp2pServer({ config: this, ...t.options })
        }
      })
    }
  }

  /**
   * Returns the directory for storing the client chain data
   * based on syncmode and selected chain (subdirectory of 'datadir')
   */
  getChainDataDirectory(): string {
    const networkDirName = this.common.chainName()
    const chainDataDirName = this.syncmode === 'light' ? 'lightchain' : 'chain'

    const dataDir = `${this.datadir}/${networkDirName}/${chainDataDirName}`
    return dataDir
  }

  /**
   * Returns the directory for storing the client state data
   * based selected chain (subdirectory of 'datadir')
   */
  getStateDataDirectory(): string {
    const networkDirName = this.common.chainName()

    const dataDir = `${this.datadir}/${networkDirName}/state`
    return dataDir
  }
}


export interface ConfigOptions {
  /**
   * Specify the chain and hardfork by passing a Common instance.
   *
   * Default: chain 'mainnet' and hardfork 'chainstart'
   */
  common?: Common

  /**
   * Synchronization mode ('full' or 'light')
   *
   * Default: 'full'
   */
  syncmode?: string

  /**
   * Provide a custom VM instance to process blocks
   *
   * Default: VM instance created by client
   */
  vm?: VM

  /**
   * Serve light peer requests
   *
   * Default: `false`
   */
  lightserv?: boolean

  /**
   * Root data directory for the blockchain
   */
  datadir?: string

  /**
   * Network transports ('rlpx' and/or 'libp2p')
   *
   * Default: `['rlpx:port=30303', 'libp2p']`
   */
  transports?: string[]

  /**
   * Transport servers (RLPx or Libp2p)
   * Use `transports` option, only used for testing purposes
   *
   * Default: servers created from `transports` option
   */
  servers?: (RlpxServer | Libp2pServer)[]

  /**
   * Enable the JSON-RPC server
   *
   * Default: false
   */
  rpc?: boolean

  /**
   * HTTP-RPC server listening port
   *
   * Default: 8545
   */
  rpcport?: number

  /**
   * HTTP-RPC server listening interface
   */
  rpcaddr?: string

  /**
   * Logging verbosity
   *
   * Choices: ['debug', 'info', 'warn', 'error', 'off']
   * Default: 'info'
   */
  loglevel?: string

  /**
   * A custom winston logger can be provided
   * if setting logging verbosity is not sufficient
   *
   * Default: Logger with loglevel 'info'
   */
  logger?: Logger

  /**
   * Number of peers needed before syncing
   *
   * Default: `2`
   */
  minPeers?: number

  /**
   * Maximum peers allowed
   *
   * Default: `25`
   */
  maxPeers?: number
}


/**
   * Returns the directory for storing the client chain data
   * based on syncmode and selected chain (subdirectory of 'datadir')
   */
getChainDataDirectory(): string {
    const networkDirName = this.common.chainName()
    const chainDataDirName = this.syncmode === 'light' ? 'lightchain' : 'chain'

    const dataDir = `${this.datadir}/${networkDirName}/${chainDataDirName}`
    return dataDir
  }


/**
   * Returns the directory for storing the client state data
   * based selected chain (subdirectory of 'datadir')
   */
getStateDataDirectory(): string {
    const networkDirName = this.common.chainName()

    const dataDir = `${this.datadir}/${networkDirName}/state`
    return dataDir
  }


@Component({
  selector: 'ng-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'angular';
}


// 时间复杂度：O(n)
// 空间复杂度：O(1)
export function climbStairs(n: number): number {
  console.time('爬楼梯');
  if(n <= 2) return n;
  let step0 = 1;
  let step1 = 1;
  for(let i = 2; i <= n; i++) {
    const temp = step0;
    step0 = step1;
    step1 = step0 + temp;
  }
  console.timeEnd('爬楼梯');
  return step1;
}


export class Setup {

    @ApiProperty()
    game_id: number;

    @ApiPropertyOptional()
    variant_id: number;

    @ApiProperty()
    selector_value: number;

    @ApiProperty()
    name: string;
}


_ => Promise.resolve({ data: {} })


t => {
    const obj: any = {};
    const found: any = 1;
    const wanted: any = 1;
    const notWanted: any = 1;
    const fn: (stuff: any) => void = () => {};
    const expectedError: Error = new Error();
    const eventEmitter: EventEmitter = new EventEmitter();
    const pattern: RegExp | string | { [key: string]: RegExp } = 'pattern';

    const message = 'message';
    const extra = {
        todo: false,
        skip: 'skip',
        diagnostic: true,
        extra_stuff: false,
    };

    t.ok(obj, message, extra);
    t.ok(obj, message);
    t.ok(obj);
    t.true(obj);
    t.assert(obj);

    t.notOk(obj, message, extra);
    t.notOk(obj, message);
    t.notOk(obj);
    t.false(obj);
    t.assertNot(obj);

    t.error(expectedError, message, extra);
    t.error(expectedError, message);
    t.error(expectedError);
    t.ifErr(expectedError);
    t.ifError(expectedError);

    t.emits(eventEmitter, 'event', message, extra);
    t.emits(eventEmitter, 'event', message);
    t.emits(eventEmitter, 'event');

    t.matchSnapshot(found, message, extra);
    t.matchSnapshot(found, message);
    t.matchSnapshot(found);

    t.throws(fn, expectedError, message, extra);
    t.throws(fn, expectedError, message);
    t.throws(fn, expectedError);
    t.throws(fn, message);
    t.throws(fn, expectedError, extra);
    t.throws();
    t.throw(fn, message);

    t.doesNotThrow(fn, message, extra);
    t.doesNotThrow(fn, message);
    t.doesNotThrow(fn);
    t.doesNotThrow();
    t.notThrow(fn, message);

    t.expectUncaughtException(fn, expectedError, message, extra);
    t.expectUncaughtException(fn, expectedError, message);
    t.expectUncaughtException(fn, expectedError);
    t.expectUncaughtException(fn);

    t.equal(found, wanted, message, extra);
    t.equal(found, wanted, message);
    t.equal(found, wanted);
    t.equals(found, wanted);
    t.isEqual(found, wanted);
    t.is(found, wanted);
    t.strictEqual(found, wanted);
    t.strictEquals(found, wanted);
    t.strictIs(found, wanted);
    t.isStrict(found, wanted);
    t.isStrictly(found, wanted);

    t.notEqual(found, notWanted, message, extra);
    t.notEqual(found, notWanted, message);
    t.notEqual(found, notWanted);
    t.inequal(found, notWanted);
    t.notEqual(found, notWanted);
    t.notEquals(found, notWanted);
    t.notStrictEqual(found, notWanted);
    t.notStrictEquals(found, notWanted);
    t.isNotEqual(found, notWanted);
    t.isNot(found, notWanted);
    t.doesNotEqual(found, notWanted);
    t.isInequal(found, notWanted);

    t.same(found, wanted, message, extra);
    t.same(found, wanted, message);
    t.same(found, wanted);
    t.equivalent(found, wanted);
    t.looseEqual(found, wanted);
    t.looseEquals(found, wanted);
    t.deepEqual(found, wanted);
    t.deepEquals(found, wanted);
    t.isLoose(found, wanted);
    t.looseIs(found, wanted);

    t.notSame(found, notWanted, message, extra);
    t.notSame(found, notWanted, message);
    t.notSame(found, notWanted);
    t.inequivalent(found, notWanted);
    t.looseInequal(found, notWanted);
    t.notDeep(found, notWanted);
    t.deepInequal(found, notWanted);
    t.notLoose(found, notWanted);
    t.looseNot(found, notWanted);

    t.strictSame(found, wanted, message, extra);
    t.strictSame(found, wanted, message);
    t.strictSame(found, wanted);
    t.strictEquivalent(found, wanted);
    t.strictDeepEqual(found, wanted);
    t.sameStrict(found, wanted);
    t.deepIs(found, wanted);
    t.isDeeply(found, wanted);
    t.isDeep(found, wanted);
    t.strictDeepEquals(found, wanted);

    t.strictNotSame(found, notWanted, message, extra);
    t.strictNotSame(found, notWanted, message);
    t.strictNotSame(found, notWanted);
    t.strictInequivalent(found, notWanted);
    t.strictDeepInequal(found, notWanted);
    t.notSameStrict(found, notWanted);
    t.deepNot(found, notWanted);
    t.notDeeply(found, notWanted);
    t.strictDeepInequals(found, notWanted);
    t.notStrictSame(found, notWanted);

    t.hasStrict(found, pattern, message, extra);
    t.hasStrict(found, pattern, message);
    t.hasStrict(found, pattern);

    t.match(found, pattern, message, extra);
    t.match(found, pattern, message);
    t.match(found, pattern);
    t.has(found, pattern);
    t.hasFields(found, pattern);
    t.matches(found, pattern);
    t.similar(found, pattern);
    t.like(found, pattern);
    t.isLike(found, pattern);
    t.includes(found, pattern);
    t.include(found, pattern);
    t.contains(found, pattern);

    t.notMatch(found, pattern, message, extra);
    t.notMatch(found, pattern, message);
    t.notMatch(found, pattern);
    t.dissimilar(found, pattern);
    t.unsimilar(found, pattern);
    t.notSimilar(found, pattern);
    t.unlike(found, pattern);
    t.isUnlike(found, pattern);
    t.notLike(found, pattern);
    t.isNotLike(found, pattern);
    t.doesNotHave(found, pattern);
    t.isNotSimilar(found, pattern);
    t.isDissimilar(found, pattern);

    t.type(new Date(), 'object', message, extra);
    t.type(new Date(), 'object', message);
    t.type(new Date(), 'object');
    t.isa(new Date(), 'Date');
    t.isA(new Date(), Date);
}


async t => {
    const wanted: any = 1;
    const expectedError: Error = new Error();

    const message = 'message';
    const extra = {
        todo: false,
        skip: 'skip',
        diagnostic: true,
        extra_stuff: false,
    };
    const promise: Promise<any> = Promise.resolve(1);
    const promiseProvider: () => Promise<void> = () => Promise.resolve();

    await t.rejects(promise, expectedError, message, extra);
    await t.rejects(promise, expectedError, message);
    await t.rejects(promise, expectedError);
    await t.rejects(promise, message, extra);
    await t.rejects(promise, message);
    await t.rejects(promise);
    await t.rejects(promiseProvider, expectedError, message, extra);
    await t.rejects(promiseProvider, expectedError, message);
    await t.rejects(promiseProvider, expectedError);
    await t.rejects(promiseProvider, message, extra);
    await t.rejects(promiseProvider, message);
    await t.rejects(promiseProvider);

    await t.resolves(promise, message, extra);
    await t.resolves(promise, message);
    await t.resolves(promise);
    await t.resolves(promiseProvider, message, extra);
    await t.resolves(promiseProvider, message);
    await t.resolves(promiseProvider);

    await t.resolveMatch(promise, wanted, message, extra);
    await t.resolveMatch(promise, wanted, message);
    await t.resolveMatch(promise, wanted);
    await t.resolveMatch(promiseProvider, wanted, message, extra);
    await t.resolveMatch(promiseProvider, wanted, message);
    await t.resolveMatch(promiseProvider, wanted);

    await t.resolveMatchSnapshot(promise, message, extra);
    await t.resolveMatchSnapshot(promise, message);
    await t.resolveMatchSnapshot(promise);
    await t.resolveMatchSnapshot(promiseProvider, message, extra);
    await t.resolveMatchSnapshot(promiseProvider, message);
    await t.resolveMatchSnapshot(promiseProvider);
}


t => {
    t.pass();
}


t => {
    const cwd = t.testdir({
        'demo.jpg': Buffer.from('a jpg'),
        'package.json': JSON.stringify({
            name: 'pj',
        }),
        src: {
            'index.js': 'yay',
            hardlinked: t.fixture('link', '../target'),
            softlinked: t.fixture('symlink', '../target'),
        },
        target: {},
    });
    t.notEqual(cwd, topLevelDir);
    t.equals(cwd, t.testdirName);
}


t => {
    // fairly infrequent vs testdir() sugar
    t.fixture('dir', {});
    t.fixture('file', 'content');
    t.fixture('file', Buffer.from('content'));

    // much more common, as sugar does not exist
    t.fixture('link', 'target');
    t.fixture('symlink', 'target');
}


() => {
      this.emit(Events.ADBREAK_STATE_PLAYING);
    }


() => {
      if (this.currentAdBreak) {
        this.emit(Events.ADBREAK_STATE_TIMEUPDATE, {
          currentTime: this.currentAdBreak.freewheelSlot.getPlayheadTime(),
        } as IAdBreakTimeUpdateEventData);
      }
    }


() => {
      this.emit(Events.ADBREAK_STATE_BUFFERING);
    }


cuepoint => {
      if (cuepoint === AdBreakType.PREROLL) {
        this.adContext.addTemporalSlot('preroll', this.sdk.ADUNIT_PREROLL, 0);
      } else if (cuepoint === AdBreakType.POSTROLL) {
        this.adContext.addTemporalSlot(
          'postroll',
          this.sdk.ADUNIT_POSTROLL,
          freewheel.duration,
        );
      } else {
        const time = cuepoint as number;
        this.adContext.addTemporalSlot(
          `midroll-${time}`,
          this.sdk.ADUNIT_MIDROLL,
          time,
        );
      }
    }


(slot, index) =>
          ({
            sequenceIndex: index,
            id: slot.getCustomId(),
            type: slot.getAdUnit(),
            startsAt: slot.getTimePosition(),
            duration: slot.getTotalDuration(),
            hasBeenWatched: false,
            maxAds: slot.getAdCount(),
            freewheelSlot: slot,
          } as IFWAdBreak)


adBreak =>
        adBreak.type === AdBreakType.MIDROLL &&
        adBreak.startsAt <= currentTime &&
        adBreak.startsAt > this.prevCurrentTime &&
        !adBreak.hasBeenWatched


adBreak =>
        adBreak.type === AdBreakType.POSTROLL && !adBreak.hasBeenWatched


interface IFWAdBreak extends IAdBreak {
  maxAds: number;
  freewheelSlot?: any;
}


public onControllerPlay(next: NextHook) {
    if (!this.adsRequested) {
      this.emit(Events.ADBREAK_STATE_PLAY);
      this.adContext.submitRequest();
      return;
    }

    if (this.currentAdBreak) {
      this.emit(Events.ADBREAK_STATE_PLAY);
      this.mediaElement.play();
      return;
    }

    next();
  }


public onControllerPause(next: NextHook) {
    if (this.currentAdBreak) {
      this.emit(Events.ADBREAK_STATE_PAUSE);
      this.mediaElement.pause();
      return;
    }

    next();
  }


public onControllerSetVolume(next: NextHook, volume: number) {
    this.mediaElement.volume = volume;
    this.mediaElement.muted = volume === 0;
    next();
  }


public onControllerSeekTo(next: NextHook) {
    if (this.currentAdBreak) {
      return;
    }

    next();
  }


public createMediaElement() {
    this.mediaElement = document.createElement('video');
    this.mediaElement.style.width = '100%';
    this.mediaElement.style.height = '100%';

    this.mediaElement.addEventListener('playing', () => {
      this.emit(Events.ADBREAK_STATE_PLAYING);
    });

    this.mediaElement.addEventListener('timeupdate', () => {
      if (this.currentAdBreak) {
        this.emit(Events.ADBREAK_STATE_TIMEUPDATE, {
          currentTime: this.currentAdBreak.freewheelSlot.getPlayheadTime(),
        } as IAdBreakTimeUpdateEventData);
      }
    });

    this.mediaElement.addEventListener('waiting', () => {
      this.emit(Events.ADBREAK_STATE_BUFFERING);
    });

    this.adContainer.appendChild(this.mediaElement);
  }


private onInstanceInitialized() {
    this.adContainer = document.createElement('div');
    this.adContainer.style.position = 'absolute';
    this.adContainer.style.left = '0px';
    this.adContainer.style.right = '0px';
    this.adContainer.style.top = '0px';
    this.adContainer.style.bottom = '0px';
    this.adContainer.style.display = 'none';
    this.adContainer.id = 'fwAdsContainer';
    this.instance.adsContainer.appendChild(this.adContainer);

    // Create ads specific media element.
    this.createMediaElement();

    const { AdManager }: { AdManager: any } = this.sdk;
    this.adManager = new AdManager();
    this.adContext = this.adManager.newContext();

    this.adContext.addEventListener(
      this.sdk.EVENT_REQUEST_COMPLETE,
      this.onAdRequestComplete.bind(this),
    );
    this.adContext.addEventListener(
      this.sdk.EVENT_SLOT_STARTED,
      this.onSlotStarted.bind(this),
    );
    this.adContext.addEventListener(
      this.sdk.EVENT_SLOT_ENDED,
      this.onSlotEnded.bind(this),
    );
    this.adContext.addEventListener(
      this.sdk.EVENT_AD_IMPRESSION,
      this.onAdImpression.bind(this),
    );
    this.adContext.addEventListener(
      this.sdk.EVENT_AD_IMPRESSION_END,
      this.onAdImpressionEnd.bind(this),
    );

    const freewheel = this.instance.config.freewheel;
    this.adManager.setNetwork(freewheel.network);
    this.adManager.setServer(freewheel.server);
    this.adContext.setVideoAsset(
      freewheel.videoAsset,
      freewheel.duration,
      freewheel.network,
    );
    this.adContext.setSiteSection(freewheel.siteSection);
    this.adContext.setProfile(freewheel.profile);

    freewheel.cuepoints.forEach(cuepoint => {
      if (cuepoint === AdBreakType.PREROLL) {
        this.adContext.addTemporalSlot('preroll', this.sdk.ADUNIT_PREROLL, 0);
      } else if (cuepoint === AdBreakType.POSTROLL) {
        this.adContext.addTemporalSlot(
          'postroll',
          this.sdk.ADUNIT_POSTROLL,
          freewheel.duration,
        );
      } else {
        const time = cuepoint as number;
        this.adContext.addTemporalSlot(
          `midroll-${time}`,
          this.sdk.ADUNIT_MIDROLL,
          time,
        );
      }
    });

    this.adContext.registerVideoDisplayBase(this.adContainer.id);
  }


public onAdRequestComplete(event) {
    this.adsRequested = true;

    if (event.success) {
      const slots = this.adContext.getTemporalSlots();
      this.adBreaks = slots.map(
        (slot, index) =>
          ({
            sequenceIndex: index,
            id: slot.getCustomId(),
            type: slot.getAdUnit(),
            startsAt: slot.getTimePosition(),
            duration: slot.getTotalDuration(),
            hasBeenWatched: false,
            maxAds: slot.getAdCount(),
            freewheelSlot: slot,
          } as IFWAdBreak),
      );
    }

    this.emit(Events.ADBREAKS, {
      adBreaks: this.adBreaks,
    } as IAdBreaksEventData);

    const preroll: IFWAdBreak = find(this.adBreaks, {
      type: AdBreakType.PREROLL,
    });
    if (preroll && !this.shouldSkipPreroll()) {
      this.playAdBreak(preroll);
    } else {
      this.instance.media.play();
    }
  }


public adClick() {
    if (!this.currentAd) {
      return;
    }

    this.currentAd.freewheelAdInstance
      .getRendererController()
      .processEvent({ name: this.sdk.EVENT_AD_CLICK });
  }


private onSlotStarted(event) {
    const slot: any = event.slot;

    const adBreak = this.slotToAdBreak(slot);
    this.currentAdBreak = adBreak;

    this.emit(Events.ADBREAK_STARTED, {
      adBreak,
    } as IAdBreakEventData);

    this.instance.media.pause();
  }


private onSlotEnded(event) {
    const slot: any = event.slot;

    const adBreak = this.slotToAdBreak(slot);
    adBreak.hasBeenWatched = true;

    this.currentAdBreak = null;

    this.emit(Events.ADBREAK_ENDED, {
      adBreak,
    } as IAdBreakEventData);

    if (adBreak.type !== AdBreakType.POSTROLL) {
      this.instance.media.play();
    }

    this.adContainer.style.display = 'none';
  }


private onAdImpression(event) {
    this.adSequenceIndex = 0;

    this.currentAd = {
      sequenceIndex: this.adSequenceIndex,
      freewheelAdInstance: event.adInstance,
    };

    this.emit(Events.AD_STARTED, {
      adBreak: this.currentAdBreak,
      ad: this.currentAd,
    } as IAdEventData);
  }


private onAdImpressionEnd(event) {
    const ad = this.currentAd;

    this.currentAd = null;

    this.emit(Events.AD_ENDED, {
      adBreak: this.currentAdBreak,
      ad,
    } as IAdEventData);

    this.adSequenceIndex += 1;
  }


private onPlayerTimeUpdate({ currentTime }: ITimeUpdateEventData) {
    const midroll: IFWAdBreak = find(
      this.adBreaks,
      adBreak =>
        adBreak.type === AdBreakType.MIDROLL &&
        adBreak.startsAt <= currentTime &&
        adBreak.startsAt > this.prevCurrentTime &&
        !adBreak.hasBeenWatched,
    );

    if (midroll) {
      this.playAdBreak(midroll);
    }

    this.prevCurrentTime = currentTime;
  }


private onPlayerEnded() {
    const postroll: IFWAdBreak = find(
      this.adBreaks,
      adBreak =>
        adBreak.type === AdBreakType.POSTROLL && !adBreak.hasBeenWatched,
    );

    if (postroll) {
      this.playAdBreak(postroll);
    }
  }


private slotToAdBreak(slot: any): IFWAdBreak {
    return find<IFWAdBreak>(this.adBreaks, {
      id: slot.getCustomId(),
    });
  }


private playAdBreak(adBreak: IFWAdBreak) {
    try {
      adBreak.freewheelSlot.play();
    } catch (error) {
      this.instance.media.play();
    }
    this.adContainer.style.display = 'block';
  }


private shouldSkipPreroll() {
    return this.instance.config.startPosition > 0;
  }


params => {
      if (params['term']) {
        this.help = params['term'];
        //automat ponizsze zakomentowac
        this.doSearch(this.help);
      }
    }


term => this.onSearch(term)


() => this.loading = true


term => this.itunes.search2(term)


() => this.loading = false


// https://codecraft.tv/courses/angular/http/http-with-promises/
@Component({
  selector: 'app-tune',
  templateUrl: './app-tune.component.html',
  styleUrls: ['./app-tune.component.scss'],
})
export class AppTuneComponent implements OnInit {
  private loading = false;
  // private results: SearchItem[];
  private results: Observable<SearchItem[]>;
  private searchField: FormControl;
  private help = '';
  constructor(private itunes: SearchService, private router: Router, private route: ActivatedRoute, private cd: ChangeDetectorRef) {
    this.route.params.subscribe( params => {
      if (params['term']) {
        this.help = params['term'];
        //automat ponizsze zakomentowac
        this.doSearch(this.help);
      }
    });
  }

  ngOnInit() {
    this.searchField = new FormControl();
    this.searchField.setValue(this.help);

   //automat
    // this.search();
  }
  ngOnDestroy(){
    this.itunes.clear();
  }

  search() {
    this.cd.reattach();
    this.results = this.searchField.valueChanges
      .debounceTime(400)
      .distinctUntilChanged()
      .do(term => this.onSearch(term))
      .do( () => this.loading = true)
      .switchMap( term => this.itunes.search2(term))
      .do( () => this.loading = false );
  }

  doSearch(term: string) {
    this.loading = true;
    this.itunes.search(term).then(() => this.loading = false);
  }

  doSearch2(term: string) {
    this.itunes.search2(term);
  }
  goHome() {
    this.router.navigate(['']);

  }
  goTune() {
    this.router.navigate(['tune']);
  }
  onSearch(term: string) {
    this.router.navigate(['tune', {term: term}]);
  }
}


ngOnInit() {
    this.searchField = new FormControl();
    this.searchField.setValue(this.help);

   //automat
    // this.search();
  }


ngOnDestroy(){
    this.itunes.clear();
  }


search() {
    this.cd.reattach();
    this.results = this.searchField.valueChanges
      .debounceTime(400)
      .distinctUntilChanged()
      .do(term => this.onSearch(term))
      .do( () => this.loading = true)
      .switchMap( term => this.itunes.search2(term))
      .do( () => this.loading = false );
  }


doSearch(term: string) {
    this.loading = true;
    this.itunes.search(term).then(() => this.loading = false);
  }


doSearch2(term: string) {
    this.itunes.search2(term);
  }


goHome() {
    this.router.navigate(['']);

  }


goTune() {
    this.router.navigate(['tune']);
  }


onSearch(term: string) {
    this.router.navigate(['tune', {term: term}]);
  }


props => (
  <svg
    width="24"


function getURI(message: Message) {
    var url = getURL(message);
    var uri = url.split('https://open.spotify.com/track/')[1].split('?')[0];
    return `spotify:track:${uri}`;
}


function getURL(message: Message) {
    var spotifyRegex = /https?:\/\/open\.spotify\.com\/track\/\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi;
    return message.content.match(spotifyRegex)[0];
}


async function enqueueTrack(reaction: MessageReaction, api: SpotifyWebApi) {
    var accessToken = api.getAccessToken();
    return (
        WebApiRequest.builder(accessToken)
            .withPath('/v1/me/player/queue')
            .withHeaders({ 'Content-Type': 'application/json' })
            .withQueryParameters({
                uri: getURI(reaction.message)
            })
            .build()
            .execute(HttpManager.post, null)
    );
}


async () => enqueueTrack(reaction, api)


(appendToObject: JQuery) => {

        var nSeries: number = (!this.xData ? 0 : this.xData.length);
        var s: StyleChart = this.getStyle();
        var margin: Margin = Style.getMargins(s);

        // Set the ranges
        var xScale: d3.scale.Linear<number,number> = d3.scale.linear().range([0, margin.widthExMargins]);
        var yScale: d3.scale.Linear<number,number> = d3.scale.linear().range([margin.heightExMargins, 0]);

        // Define the axes
        var xAxis = d3.svg.axis().scale(xScale)
            .orient("bottom").ticks(5);
        if(this.gridVerticalStrokeWidth != null && this.gridVerticalStrokeWidth > 0){
            xAxis.innerTickSize(-margin.heightExMargins);     //used as grid line
        }

        var yAxis = d3.svg.axis().scale(yScale)
            .orient("left").ticks(5);
        if(this.gridHorizontalStrokeWidth != null && this.gridHorizontalStrokeWidth > 0){
            yAxis.innerTickSize(-margin.widthExMargins);      //used as grid line
        }

        if(this.suppressAxisHorizontal === true) xAxis.tickValues([]);

        if(this.suppressAxisVertical === true) yAxis.tickValues([]);

        var data: any[] = [];
        for(var i=0; i<this.xData.length; i++ ){
            var obj = {};
            for( var j=0; j<this.labels.length; j++ ){
                obj[this.labels[j]] = this.yData[j][i];
                obj['xValue'] = this.xData[i];
            }
            data.push(obj);
        }

        var area = d3.svg.area()
            .x(function(d: any) { return xScale(d.xValue); })
            .y0(function(d: any) { return yScale(d.y0); })
            .y1(function(d: any) { return yScale(d.y0 + d.y); });

        var stack = d3.layout.stack()
            .values(function(d: any) { return d.values; });

        var svg = d3.select("#" + appendToObject.attr("id")).append("svg")
            .attr("width", margin.widthExMargins + margin.left + margin.right)
            .attr("height", margin.heightExMargins + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        var color: any = d3.scale.category20();
        color.domain(d3.keys(data[0]).filter(function (key) {
            return key !== "xValue";
        }));

        var browsers = stack(color.domain().map(function (name) {
            return {
                name: name,
                values: data.map(function (d) {
                    return {xValue: d.xValue, y: d[name] * 1};
                })
            };
        }));

        // Find the value of the day with highest total value
        var maxX = d3.max(data, function (d) {
            var vals = d3.keys(d).map(function (key) {
                return key !== "xValue" ? d[key] : 0
            });
            return d3.sum(vals);
        });

        // Set domains for axes
        xScale.domain(d3.extent(data, function (d) {
            return d.xValue;
        }));

        yScale.domain([0, maxX]);

        var browser = svg.selectAll(".browser")
            .data(browsers)
            .enter().append("g")
            .attr("class", "browser");

        var tempLabels = this.labels;

        var defaultColor: Ordinal<string,string> = d3.scale.category20();
        browser.append("path")
            .attr("class", "area")
            .attr("data-legend",function(d: any) { return d.name})
            .attr("d", function (d: any) {
                return area(d.values);
            })
            .style("fill", function(d: any){
                if(s && s.getSeriesColor(tempLabels.indexOf(d.name))){
                    return s.getSeriesColor(tempLabels.indexOf(d.name));
                } else{
                    return defaultColor(String(tempLabels.indexOf(d.name)))
                }
            })
            .style({"stroke-width": "0px"});

        //Add the x axis:
        var xAxisNode = svg.append("g")
            .attr("class", "x axis")
            .style("stroke","#000")
            .style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
            .style("fill","none")
            .attr("transform", "translate(0," + margin.heightExMargins + ")")
            .call(xAxis);
        xAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");

        //Add the y axis
        var yAxisNode = svg.append("g")
            .attr("class", "y axis")
            .style("stroke","#000")
            .style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
            .style("fill","none")
            .call(yAxis);
        yAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");

        //Add title (if present)
        if (this.title) {
            var titleStyle: StyleText;
            if(this.style) titleStyle = this.style.getTitleStyle();
            Chart.appendTitle(svg, this.title, margin, titleStyle);
        }

        //Append the legend
        var legend: any = svg.append("g")
            .attr("class","legend")
            .attr("transform","translate(40,40)")
            .style("font-size","12px")
            .call(Legend.legendFn);
    }


/*
 *
 *  * Copyright 2016 Skymind,Inc.
 *  *
 *  *    Licensed under the Apache License, Version 2.0 (the "License");
 *  *    you may not use this file except in compliance with the License.
 *  *    You may obtain a copy of the License at
 *  *
 *  *        http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  *    Unless required by applicable law or agreed to in writing, software
 *  *    distributed under the License is distributed on an "AS IS" BASIS,
 *  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *    See the License for the specific language governing permissions and
 *  *    limitations under the License.
 *
 */
/// <reference path="../../api/Component.ts" />
/// <reference path="../../api/Renderable.ts" />
/// <reference path="../../typedefs/d3.d.ts" />
/// <reference path="../../util/TSUtils.ts" />
/// <reference path="Chart.ts" />
/// <reference path="Legend.ts" />
class ChartStackedArea extends Chart implements Renderable {
    private xData: number[];
    private yData: number[][];
    private labels: string[];

    constructor(jsonStr: string){
        super(ComponentType.ChartStackedArea, jsonStr);

        var json = JSON.parse(jsonStr);
        if(!json["componentType"]) json = json[ComponentType[ComponentType.ChartStackedArea]];

        this.xData = json['x'];
        this.yData = json['y'];
        this.labels = json['labels'];
    }

    render = (appendToObject: JQuery) => {

        var nSeries: number = (!this.xData ? 0 : this.xData.length);
        var s: StyleChart = this.getStyle();
        var margin: Margin = Style.getMargins(s);

        // Set the ranges
        var xScale: d3.scale.Linear<number,number> = d3.scale.linear().range([0, margin.widthExMargins]);
        var yScale: d3.scale.Linear<number,number> = d3.scale.linear().range([margin.heightExMargins, 0]);

        // Define the axes
        var xAxis = d3.svg.axis().scale(xScale)
            .orient("bottom").ticks(5);
        if(this.gridVerticalStrokeWidth != null && this.gridVerticalStrokeWidth > 0){
            xAxis.innerTickSize(-margin.heightExMargins);     //used as grid line
        }

        var yAxis = d3.svg.axis().scale(yScale)
            .orient("left").ticks(5);
        if(this.gridHorizontalStrokeWidth != null && this.gridHorizontalStrokeWidth > 0){
            yAxis.innerTickSize(-margin.widthExMargins);      //used as grid line
        }

        if(this.suppressAxisHorizontal === true) xAxis.tickValues([]);

        if(this.suppressAxisVertical === true) yAxis.tickValues([]);

        var data: any[] = [];
        for(var i=0; i<this.xData.length; i++ ){
            var obj = {};
            for( var j=0; j<this.labels.length; j++ ){
                obj[this.labels[j]] = this.yData[j][i];
                obj['xValue'] = this.xData[i];
            }
            data.push(obj);
        }

        var area = d3.svg.area()
            .x(function(d: any) { return xScale(d.xValue); })
            .y0(function(d: any) { return yScale(d.y0); })
            .y1(function(d: any) { return yScale(d.y0 + d.y); });

        var stack = d3.layout.stack()
            .values(function(d: any) { return d.values; });

        var svg = d3.select("#" + appendToObject.attr("id")).append("svg")
            .attr("width", margin.widthExMargins + margin.left + margin.right)
            .attr("height", margin.heightExMargins + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        var color: any = d3.scale.category20();
        color.domain(d3.keys(data[0]).filter(function (key) {
            return key !== "xValue";
        }));

        var browsers = stack(color.domain().map(function (name) {
            return {
                name: name,
                values: data.map(function (d) {
                    return {xValue: d.xValue, y: d[name] * 1};
                })
            };
        }));

        // Find the value of the day with highest total value
        var maxX = d3.max(data, function (d) {
            var vals = d3.keys(d).map(function (key) {
                return key !== "xValue" ? d[key] : 0
            });
            return d3.sum(vals);
        });

        // Set domains for axes
        xScale.domain(d3.extent(data, function (d) {
            return d.xValue;
        }));

        yScale.domain([0, maxX]);

        var browser = svg.selectAll(".browser")
            .data(browsers)
            .enter().append("g")
            .attr("class", "browser");

        var tempLabels = this.labels;

        var defaultColor: Ordinal<string,string> = d3.scale.category20();
        browser.append("path")
            .attr("class", "area")
            .attr("data-legend",function(d: any) { return d.name})
            .attr("d", function (d: any) {
                return area(d.values);
            })
            .style("fill", function(d: any){
                if(s && s.getSeriesColor(tempLabels.indexOf(d.name))){
                    return s.getSeriesColor(tempLabels.indexOf(d.name));
                } else{
                    return defaultColor(String(tempLabels.indexOf(d.name)))
                }
            })
            .style({"stroke-width": "0px"});

        //Add the x axis:
        var xAxisNode = svg.append("g")
            .attr("class", "x axis")
            .style("stroke","#000")
            .style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
            .style("fill","none")
            .attr("transform", "translate(0," + margin.heightExMargins + ")")
            .call(xAxis);
        xAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");

        //Add the y axis
        var yAxisNode = svg.append("g")
            .attr("class", "y axis")
            .style("stroke","#000")
            .style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
            .style("fill","none")
            .call(yAxis);
        yAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");

        //Add title (if present)
        if (this.title) {
            var titleStyle: StyleText;
            if(this.style) titleStyle = this.style.getTitleStyle();
            Chart.appendTitle(svg, this.title, margin, titleStyle);
        }

        //Append the legend
        var legend: any = svg.append("g")
            .attr("class","legend")
            .attr("transform","translate(40,40)")
            .style("font-size","12px")
            .call(Legend.legendFn);
    }
}