onCheckedChangeAuto(args: EventData) {
    const mySwitch = args.object as Switch;
    const isChecked = mySwitch.checked; // boolean
    if (isChecked === true) {
       appSettings.setBoolean("auto", true);
      this.auto = appSettings.getBoolean('auto');
    }
    else {
      appSettings.setBoolean("auto", false);
      this.auto = appSettings.getBoolean('auto');
    }
    }


onCheckedChangeSource(args: EventData) {
    const mySwitch = args.object as Switch;
    const isChecked = mySwitch.checked; // boolean
    if (isChecked === true) {
      appSettings.setBoolean("bgsource", true);
      this.bgSource = appSettings.getBoolean('bgsource');
    }
    else {
      appSettings.setBoolean("bgsource", false);
      this.bgSource = appSettings.getBoolean('bgsource');
    }
  }


sendDatatoNightscout6() {
    return new Promise((resolve, reject) => {
      this.getNSData().subscribe(g => {
        g.map(bol => {
          console.log(bol.http.toString() + "JJJJJJJ" + bol.secret.toString());
          this.slowo =
            this.slowo2 +
            "  " +
            bol.http.toString() +
            " " +
            bol.secret.toString();
        });
        console.log("as" + this.slowo);
        resolve(), reject();
      });
    });
  }


sendDatatoNightscout7() {
    return new Promise((resolve, reject) => {
      this.getNSData().subscribe(g => {
        g.map(bol => {
          console.log(
            bol.http.toString() + "66666666666" + bol.secret.toString()
          );
          this.nsUrl2 = bol.http.toString();
          this.nsKey2 = bol.hash.toString();
        });
        console.log("as" + this.nsUrl2);
        resolve(), reject();
      });
    });
  }


setNS(arg) {
    console.log("setttNS");
    console.log(arg.text);
    this.nsUrl = arg.text;
  }


setNSurl(arg) {
    console.log("setttNSUURRL");
    console.log(arg.text);
    this.nsKey = arg.text;
  }


getNSData(): Observable<
    Array<{ http: string; secret: string; hash: string }>
  > {
    return this.databaseService.NSconf().pipe(
      map(rows => {
        return rows.map(a => ({
          http: a[0],
          secret: a[1],
          hash: a[2]
        }));
      })
    );
  }


() => {
    const BGMUser = new BangumiUser('test', 'test');
    const P = (<jest.Mock<BangumiApiRequest>>BangumiApiRequest).mock.instances[0];

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    ///@ts-ignore
    const mockGet = <jest.Mock>P.get;

    it('getMeInfo(): 路径', async () => {
        mockGet.mockResolvedValue({});
        await BGMUser.getMeInfo();

        expect(mockGet.mock.calls[0][0]).toBe('/v0/me');
    });

    it('getUserInfo(): 替换请求路径', async () => {
        mockGet.mockResolvedValue({});
        await BGMUser.getUserInfo(1);

        expect(mockGet.mock.calls[0][0]).toBe('/user/1');
    });

    it('getUserCollectionsStatus(): 替换请求路径', async () => {
        mockGet.mockResolvedValue({});
        await BGMUser.getUserCollectionsStatus(1);

        expect(mockGet.mock.calls[0][0]).toBe('/user/1/collections/status');
    });

    it('getgetUserCollectionProgress(): 替换请求路径, 拼接 query', async () => {
        mockGet.mockResolvedValue({});
        await BGMUser.getUserCollectionProgress(1, 2);

        expect(mockGet.mock.calls[0][0]).toBe('/user/1/progress?subject_id=2');
    });

    beforeEach(() => {
        jest.clearAllMocks();
    });
}


async () => {
        mockGet.mockResolvedValue({});
        await BGMUser.getMeInfo();

        expect(mockGet.mock.calls[0][0]).toBe('/v0/me');
    }


async () => {
        mockGet.mockResolvedValue({});
        await BGMUser.getUserInfo(1);

        expect(mockGet.mock.calls[0][0]).toBe('/user/1');
    }


async () => {
        mockGet.mockResolvedValue({});
        await BGMUser.getUserCollectionsStatus(1);

        expect(mockGet.mock.calls[0][0]).toBe('/user/1/collections/status');
    }


async () => {
        mockGet.mockResolvedValue({});
        await BGMUser.getUserCollectionProgress(1, 2);

        expect(mockGet.mock.calls[0][0]).toBe('/user/1/progress?subject_id=2');
    }


() => {
        jest.clearAllMocks();
    }


@NgModule({
  declarations: [
    MyApp
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(FIREBASE_CONFIG),
    AngularFireDatabaseModule,
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    ShoppingListService,
    ToastService
  ]
})
export class AppModule {}


() => {
    it('should open and close the modal', async () => {
        const Element = () => {
            const { openModal } = useContext(ModalContext)
            const handleOpen = () => openModal('modal title', 'modal message')

            return (
                <div>
                    <button type="button" onClick={handleOpen}>
                        open modal
                    </button>
                </div>
            )
        }


async () => {
        const Element = () => {
            const { openModal } = useContext(ModalContext)
            const handleOpen = () => openModal('modal title', 'modal message')

            return (
                <div>
                    <button type="button" onClick={handleOpen}>
                        open modal
                    </button>
                </div>


() => {
            const { openModal } = useContext(ModalContext)
            const handleOpen = () => openModal('modal title', 'modal message')

            return (
                <div>
                    <button type="button" onClick={handleOpen}>
                        open modal
                    </button>
                </div>


() => openModal('modal title', 'modal message')


() => {
            expect(
                screen.queryByRole('heading', { name: /modal title/i })
            ).toBeInTheDocument()
            expect(screen.queryByText(/modal message/i)).toBeInTheDocument()
        }


() => {
            expect(
                screen.queryByRole('heading', { name: /modal title/i })
            ).not.toBeInTheDocument()
            expect(screen.queryByText(/modal message/i)).not.toBeInTheDocument()
        }


class Component extends Vue {}


function brushed() {
        let selected = null;
          selected =  x2.domain()
                    .filter(function(d) {
                         return (brush.extent()[0] <= x2(d)) && (x2(d) <= brush.extent()[1]);
                  });

        let start;
        let end;

        if (brush.extent()[0] != brush.extent()[1]) {
            start = selected[0];
            end = selected[selected.length - 1] + 1;
          } else {
            start = 0;
            end = data.length;
          }

        const updatedData = data.slice(start, end);

        update(updatedData);
        enter(updatedData);
        exit(updatedData);
        updateScale(updatedData);

    }


function updateScale(data) {
            const tickScale = d3.scale.pow().range([data.length / 10, 0]).domain([data.length, 0]).exponent(.5);

        let brushValue = brush.extent()[1] - brush.extent()[0];
        if (brushValue === 0) {
          brushValue = width;
        }

        const tickValueMultiplier = Math.ceil(Math.abs(tickScale(brushValue)));
        const filteredTickValues = data.filter(function(d, i) {return i % tickValueMultiplier === 0; }).map(function(d) { return d.date; });

        focus.select('.x.axis').call(xAxis.tickValues(filteredTickValues));
        focus.select('.y.axis').call(yAxis);
      }


function update(data) {
          x.domain(data.map(function(d) { return d.date; }));
          y.domain([0, d3.max(data, function(d) { return d.price; })]);

          const bars =  focus.selectAll('.bar')
              .data(data);
          bars
            .attr(
            {
              height: function (d, i) {
                return height - y(d.price);
              },
              width: function(d) {
                return x.rangeBand();
              },
              x: function(d) {

                return x(d.date);
              },
              y: function(d) {
                return y(d.price);
              }
            });

      }


function exit(data) {
        const bars =  focus.selectAll('.bar').data(data);
        bars.exit().remove();
      }


function enter(data) {
          x.domain(data.map(function(d) { return d.date; }));
          y.domain([0, d3.max(data, function(d) { return d.price; })]);

          const bars =  focus.selectAll('.bar')
              .data(data);
          bars.enter().append('rect')
            .classed('bar', true)
            .attr(
            {
              height: function (d, i) {
                return height - y(d.price);
              },
              width: function(d) {
                return x.rangeBand();
              },
              x: function(d) {

                return x(d.date);
              },
              y: function(d) {
                return y(d.price);
              }
            });
      }


@Component({
  selector: 'app-brushing-bar-graph',
  templateUrl: './brushing-bar-graph.component.html',
  styleUrls: ['./brushing-bar-graph.component.css']
})
export class BrushingBarGraphComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
    this.loadGraph();
  }

  loadGraph() {
    const data = [];

    for (let i = 0; i < 300; i++) {
      const datum = {} as any;
      datum.date = i;
      datum.price = Math.floor(Math.random() * 600);
      data.push(datum);
    }

    const margin = {top: 10, right: 10, bottom: 100, left: 40},
        margin2 = {top: 430, right: 10, bottom: 20, left: 40},
        width = 750 - margin.left - margin.right,
        height = 300 - margin.top - margin.bottom,
        height2 = 300 - margin2.top - margin2.bottom;

    const x = d3.scale.ordinal().rangeBands([0, width], .1),
        x2 = d3.scale.ordinal().rangeBands([0, width], .1),
        y = d3.scale.linear().range([height, 0]),
        y2 = d3.scale.linear().range([height2, 0]);

    const xAxis = d3.svg.axis().scale(x).orient('bottom'),
        xAxis2 = d3.svg.axis().scale(x2).orient('bottom').tickValues([]),
        yAxis = d3.svg.axis().scale(y).orient('left');

        x.domain(data.map(function(d) { return d.date; }));
        y.domain([0, d3.max(data, function(d) { return d.price; })]);
        x2.domain(x.domain());
        y2.domain(y.domain());

      const brush = d3.svg.brush()
                    .x(x2)
                    .on('brush', brushed);

    const svg = d3.select('.brushing-bar-graph').append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom);

    const focus = svg.append('g')
        .attr('class', 'focus')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    const context = svg.append('g')
        .attr('class', 'context')
        .attr('transform', 'translate(' + margin2.left + ',' + margin2.top + ')');

      focus.append('g')
          .attr('class', 'x axis')
          .attr('transform', 'translate(0,' + height + ')')
          .call(xAxis);

      focus.append('g')
          .attr('class', 'y axis')
          .call(yAxis);

      console.log(x(data[0].date));
       enter(data);
      updateScale(data);

      const subBars = context.selectAll('.subBar')
                                        .data(data);

      subBars.enter().append('rect')
          .classed('subBar', true)
          .attr(
          {
            height: function (d) {
              return height2 - y2(d.price);
            },
            width: function(d) { return x.rangeBand(); },
            x: function(d) {

              return x2(d.date);
            },
            y: function(d) {
              return y2(d.price);
            }
          });

      context.append('g')
          .attr('class', 'x axis')
          .attr('transform', 'translate(0,' + height2 + ')')
          .call(xAxis2);

      context.append('g')
          .attr('class', 'x brush')
          .call(brush)
        .selectAll('rect')
          .attr('y', -6)
          .attr('height', height2 + 7);

    function brushed() {
        let selected = null;
          selected =  x2.domain()
                    .filter(function(d) {
                         return (brush.extent()[0] <= x2(d)) && (x2(d) <= brush.extent()[1]);
                  });

        let start;
        let end;

        if (brush.extent()[0] != brush.extent()[1]) {
            start = selected[0];
            end = selected[selected.length - 1] + 1;
          } else {
            start = 0;
            end = data.length;
          }

        const updatedData = data.slice(start, end);

        update(updatedData);
        enter(updatedData);
        exit(updatedData);
        updateScale(updatedData);

    }

      function updateScale(data) {
            const tickScale = d3.scale.pow().range([data.length / 10, 0]).domain([data.length, 0]).exponent(.5);

        let brushValue = brush.extent()[1] - brush.extent()[0];
        if (brushValue === 0) {
          brushValue = width;
        }

        const tickValueMultiplier = Math.ceil(Math.abs(tickScale(brushValue)));
        const filteredTickValues = data.filter(function(d, i) {return i % tickValueMultiplier === 0; }).map(function(d) { return d.date; });

        focus.select('.x.axis').call(xAxis.tickValues(filteredTickValues));
        focus.select('.y.axis').call(yAxis);
      }

      function update(data) {
          x.domain(data.map(function(d) { return d.date; }));
          y.domain([0, d3.max(data, function(d) { return d.price; })]);

          const bars =  focus.selectAll('.bar')
              .data(data);
          bars
            .attr(
            {
              height: function (d, i) {
                return height - y(d.price);
              },
              width: function(d) {
                return x.rangeBand();
              },
              x: function(d) {

                return x(d.date);
              },
              y: function(d) {
                return y(d.price);
              }
            });

      }

      function exit(data) {
        const bars =  focus.selectAll('.bar').data(data);
        bars.exit().remove();
      }

      function enter(data) {
          x.domain(data.map(function(d) { return d.date; }));
          y.domain([0, d3.max(data, function(d) { return d.price; })]);

          const bars =  focus.selectAll('.bar')
              .data(data);
          bars.enter().append('rect')
            .classed('bar', true)
            .attr(
            {
              height: function (d, i) {
                return height - y(d.price);
              },
              width: function(d) {
                return x.rangeBand();
              },
              x: function(d) {

                return x(d.date);
              },
              y: function(d) {
                return y(d.price);
              }
            });
      }
  }

}


ngOnInit(): void {
    this.loadGraph();
  }


loadGraph() {
    const data = [];

    for (let i = 0; i < 300; i++) {
      const datum = {} as any;
      datum.date = i;
      datum.price = Math.floor(Math.random() * 600);
      data.push(datum);
    }

    const margin = {top: 10, right: 10, bottom: 100, left: 40},
        margin2 = {top: 430, right: 10, bottom: 20, left: 40},
        width = 750 - margin.left - margin.right,
        height = 300 - margin.top - margin.bottom,
        height2 = 300 - margin2.top - margin2.bottom;

    const x = d3.scale.ordinal().rangeBands([0, width], .1),
        x2 = d3.scale.ordinal().rangeBands([0, width], .1),
        y = d3.scale.linear().range([height, 0]),
        y2 = d3.scale.linear().range([height2, 0]);

    const xAxis = d3.svg.axis().scale(x).orient('bottom'),
        xAxis2 = d3.svg.axis().scale(x2).orient('bottom').tickValues([]),
        yAxis = d3.svg.axis().scale(y).orient('left');

        x.domain(data.map(function(d) { return d.date; }));
        y.domain([0, d3.max(data, function(d) { return d.price; })]);
        x2.domain(x.domain());
        y2.domain(y.domain());

      const brush = d3.svg.brush()
                    .x(x2)
                    .on('brush', brushed);

    const svg = d3.select('.brushing-bar-graph').append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom);

    const focus = svg.append('g')
        .attr('class', 'focus')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    const context = svg.append('g')
        .attr('class', 'context')
        .attr('transform', 'translate(' + margin2.left + ',' + margin2.top + ')');

      focus.append('g')
          .attr('class', 'x axis')
          .attr('transform', 'translate(0,' + height + ')')
          .call(xAxis);

      focus.append('g')
          .attr('class', 'y axis')
          .call(yAxis);

      console.log(x(data[0].date));
       enter(data);
      updateScale(data);

      const subBars = context.selectAll('.subBar')
                                        .data(data);

      subBars.enter().append('rect')
          .classed('subBar', true)
          .attr(
          {
            height: function (d) {
              return height2 - y2(d.price);
            },
            width: function(d) { return x.rangeBand(); },
            x: function(d) {

              return x2(d.date);
            },
            y: function(d) {
              return y2(d.price);
            }
          });

      context.append('g')
          .attr('class', 'x axis')
          .attr('transform', 'translate(0,' + height2 + ')')
          .call(xAxis2);

      context.append('g')
          .attr('class', 'x brush')
          .call(brush)
        .selectAll('rect')
          .attr('y', -6)
          .attr('height', height2 + 7);

    function brushed() {
        let selected = null;
          selected =  x2.domain()
                    .filter(function(d) {
                         return (brush.extent()[0] <= x2(d)) && (x2(d) <= brush.extent()[1]);
                  });

        let start;
        let end;

        if (brush.extent()[0] != brush.extent()[1]) {
            start = selected[0];
            end = selected[selected.length - 1] + 1;
          } else {
            start = 0;
            end = data.length;
          }

        const updatedData = data.slice(start, end);

        update(updatedData);
        enter(updatedData);
        exit(updatedData);
        updateScale(updatedData);

    }

      function updateScale(data) {
            const tickScale = d3.scale.pow().range([data.length / 10, 0]).domain([data.length, 0]).exponent(.5);

        let brushValue = brush.extent()[1] - brush.extent()[0];
        if (brushValue === 0) {
          brushValue = width;
        }

        const tickValueMultiplier = Math.ceil(Math.abs(tickScale(brushValue)));
        const filteredTickValues = data.filter(function(d, i) {return i % tickValueMultiplier === 0; }).map(function(d) { return d.date; });

        focus.select('.x.axis').call(xAxis.tickValues(filteredTickValues));
        focus.select('.y.axis').call(yAxis);
      }

      function update(data) {
          x.domain(data.map(function(d) { return d.date; }));
          y.domain([0, d3.max(data, function(d) { return d.price; })]);

          const bars =  focus.selectAll('.bar')
              .data(data);
          bars
            .attr(
            {
              height: function (d, i) {
                return height - y(d.price);
              },
              width: function(d) {
                return x.rangeBand();
              },
              x: function(d) {

                return x(d.date);
              },
              y: function(d) {
                return y(d.price);
              }
            });

      }

      function exit(data) {
        const bars =  focus.selectAll('.bar').data(data);
        bars.exit().remove();
      }

      function enter(data) {
          x.domain(data.map(function(d) { return d.date; }));
          y.domain([0, d3.max(data, function(d) { return d.price; })]);

          const bars =  focus.selectAll('.bar')
              .data(data);
          bars.enter().append('rect')
            .classed('bar', true)
            .attr(
            {
              height: function (d, i) {
                return height - y(d.price);
              },
              width: function(d) {
                return x.rangeBand();
              },
              x: function(d) {

                return x(d.date);
              },
              y: function(d) {
                return y(d.price);
              }
            });
      }
  }


/*****************************************************************************
    *   A rectangular in 2D space.
    *
    *   @author     Christopher Stock
    *   @version    0.0.2
    *****************************************************************************/
class LibRect2D extends LibShape2D
    {
        /*****************************************************************************
        *   Constructs a new rectangular.
        *
        *   @param  left    Left coordinate for this rect.
        *   @param  top     Top coordinate for this rect.
        *   @param  width   Width for the new rect.
        *   @param  height  Height for the new rect.
        *****************************************************************************/
        public constructor( left:number, top:number, width:number, height:number )
        {
            super( left, top, width, height );
        }

        /*****************************************************************************
        *   Checks if this rect contains the given point.
        *
        *   @param  x  The X coordinate of the point to check.
        *   @param  y  The Y coordinate of the point to check.
        *   @return    true if the point lies inside the rectangle.
        *              Otherwise false.
        *****************************************************************************/
        public containsPoint( x:number, y:number ):boolean
        {
            return (
                    x  >= this.anchor.x
                &&  x  <  this.anchor.x    + this.size.width
                &&  y  >= this.anchor.y
                &&  y  <  this.anchor.y     + this.size.height
            );
        }

        /*****************************************************************************
        *   Checks if the given rect intersects this rect.
        *
        *   @param  rect    The rect to check for intersection.
        *   @return         true if the rects collide.
        *                   Otherwise false.
        *****************************************************************************/
        public collidesWithRect( rect:LibRect2D ):boolean
        {
            return !(
                    this.anchor.x                          >= rect.anchor.x + rect.size.width
                ||  this.anchor.x  + this.size.width      <= rect.anchor.x
                ||  this.anchor.y                          >= rect.anchor.y + rect.size.height
                ||  this.anchor.y  + this.size.height     <= rect.anchor.y
            );
        }

        /*****************************************************************************
        *   Checks if the given rect equals with this rect.
        *
        *   @param  rect    The rect to check for equality.
        *   @return         true if the rects equal.
        *                   Otherwise false.
        *****************************************************************************/
        public equalsWithRect( rect:LibRect2D ):boolean
        {
            return (
                    this.anchor.x       ==  rect.anchor.x
                &&  this.size.width     ==  rect.size.width
                &&  this.anchor.y       ==  rect.anchor.y
                &&  this.size.height    ==  rect.size.height
            );
        }
    }


/*****************************************************************************
        *   Checks if this rect contains the given point.
        *
        *   @param  x  The X coordinate of the point to check.
        *   @param  y  The Y coordinate of the point to check.
        *   @return    true if the point lies inside the rectangle.
        *              Otherwise false.
        *****************************************************************************/
public containsPoint( x:number, y:number ):boolean
        {
            return (
                    x  >= this.anchor.x
                &&  x  <  this.anchor.x    + this.size.width
                &&  y  >= this.anchor.y
                &&  y  <  this.anchor.y     + this.size.height
            );
        }


/*****************************************************************************
        *   Checks if the given rect intersects this rect.
        *
        *   @param  rect    The rect to check for intersection.
        *   @return         true if the rects collide.
        *                   Otherwise false.
        *****************************************************************************/
public collidesWithRect( rect:LibRect2D ):boolean
        {
            return !(
                    this.anchor.x                          >= rect.anchor.x + rect.size.width
                ||  this.anchor.x  + this.size.width      <= rect.anchor.x
                ||  this.anchor.y                          >= rect.anchor.y + rect.size.height
                ||  this.anchor.y  + this.size.height     <= rect.anchor.y
            );
        }


/*****************************************************************************
        *   Checks if the given rect equals with this rect.
        *
        *   @param  rect    The rect to check for equality.
        *   @return         true if the rects equal.
        *                   Otherwise false.
        *****************************************************************************/
public equalsWithRect( rect:LibRect2D ):boolean
        {
            return (
                    this.anchor.x       ==  rect.anchor.x
                &&  this.size.width     ==  rect.size.width
                &&  this.anchor.y       ==  rect.anchor.y
                &&  this.size.height    ==  rect.size.height
            );
        }


(event: React.MouseEvent<HTMLAnchorElement>) => {
    event.preventDefault()

    if (this.props.disabled) {
      return
    }

    const uri = this.props.uri
    if (uri) {
      shell.openExternal(uri)
    }

    const onClick = this.props.onClick
    if (onClick) {
      onClick()
    }
  }


/**
 * A link component.
 *
 * Provide `children` elements for the title of the rendered hyperlink.
 */
export class LinkButton extends React.Component<ILinkButtonProps, {}> {
  public render() {
    const href = this.props.uri || ''
    const className = classNames('link-button-component', this.props.className)

    return (
      <a
        className={className}
        href={href}
        onClick={this.onClick}
        title={this.props.title}
        tabIndex={this.props.tabIndex}
      >
        {this.props.children}
      </a>
    )
  }

  private onClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
    event.preventDefault()

    if (this.props.disabled) {
      return
    }

    const uri = this.props.uri
    if (uri) {
      shell.openExternal(uri)
    }

    const onClick = this.props.onClick
    if (onClick) {
      onClick()
    }
  }
}


interface ILinkButtonProps {
  /** A URI to open on click. */
  readonly uri?: string

  /** A function to call on click. */
  readonly onClick?: () => void

  /** CSS classes attached to the component */
  readonly className?: string

  /** The tab index of the anchor element. */
  readonly tabIndex?: number

  /** Disable the link from being clicked */
  readonly disabled?: boolean

  /** title-text or tooltip for the link */
  readonly title?: string
}


public render() {
    const href = this.props.uri || ''
    const className = classNames('link-button-component', this.props.className)

    return (
      <a
        className={className}
        href={href}
        onClick={this.onClick}
        title={this.props.title}
        tabIndex={this.props.tabIndex}
      >
        {this.props.children}
      </a>
    )
  }


(asset: Asset): PoolFeeLD => {
  // special case for RUNE
  if (isRuneNativeAsset(asset)) {
    return FP.pipe(
      THOR.fees$(),
      liveData.map((fees) => ({ amount: fees.fast, asset: AssetRuneNative }))
    )
  } else {
    return FP.pipe(
      gasRateByChain$(asset.chain),
      liveData.map((gasRate) => getChainFeeByGasRate({ asset, gasRate })),
      // Map to an error if fee could not be found
      liveData.chain(liveData.fromOption(() => Error(`Could not find fee for ${asset.chain} chain`)))
    )
  }
}


(fees) => ({ amount: fees.fast, asset: AssetRuneNative })


(gasRate) => getChainFeeByGasRate({ asset, gasRate })


() => Error(`Could not find fee for ${asset.chain} chain`)


(sc:any) => {
      sumAbs += Math.abs(sc.difference);
    }


(a:any, b:any) => b.membership - a.membership


(element:any) => {
        let spotResult = this._getSpotRatio(p.find((item:any) => item.id === element.id), q.find((item:any) => item.id === element.id));
        sumSpotResults += spotResult;
				j++;
				if (j >= this._k){
          aux = sumSpotResults / this._k
          valaux = true;
				}
      }


(item:any) => item.id === element.id


(a:any, b:any) => (a.nonmembership > b.nonmembership) ? 1 : -1


(p: any )=> {
        colectiva.forEach((q:any) => {
          if(p.id === q.id){
            let spotc: any = {};
            spotc['id'] = p.id
            spotc['difference'] = (p.membership - q.membership) + this._alpha * (p.hesitation - q.hesitation);
            spotComparisons.push(spotc);
          }
        });
      }


(q:any) => {
          if(p.id === q.id){
            let spotc: any = {};
            spotc['id'] = p.id
            spotc['difference'] = (p.membership - q.membership) + this._alpha * (p.hesitation - q.hesitation);
            spotComparisons.push(spotc);
          }
        }


@Injectable({
  providedIn: 'root'
})

export class SimilarityMeasureService {

  _alpha = 0.5;
  _k = -1
  constructor() { }

  public _getSimilarity(individual: any, colectivo: any, k: number) {
    this._k = k;
    let ret = 0;
    if (this._k < 0) {
      this._k = individual.length;
    }
    let _result = this._getSimilarityExtended(individual, colectivo);
    ret = _result.level as number;
    return ret;
  }

  private _getSimilarityExtended(individual: any, colectiva: any) {

    let  spotComparisons = this._getSpotComparisons(individual, colectiva);

    let sumAbs = 0;
		let n = spotComparisons.length;
    spotComparisons.forEach((sc:any) => {
      sumAbs += Math.abs(sc.difference);
    });
    let grossLevel = 1 - sumAbs / n;

    let cdfMembership = this._approximateMembershipCDF(individual, colectiva)                           ;
		let cdfNonMembership = this._approximateNonMembershipCDF(individual, colectiva);

    let _result:any = {
      CDFMembership: 0,
      CDFNonMembership: 0,
      CDF: 0,
      grossLevel:0,
      level:0
    };
    _result['CDFMembership'] = cdfMembership;
    _result['CDFNonMembership'] = cdfNonMembership;
    _result['CDF'] = (cdfMembership + cdfNonMembership) / 2;
    _result['grossLevel'] = grossLevel;
    _result['level'] = grossLevel * _result.CDF;
    return _result;
  }

  private _approximateMembershipCDF(p: any, q: any){
    let ret = 0;

		let n = p.length;
		let j = 0;
		let sumSpotResults = 0;
    let aux = 0;
    let valaux = false;

			if (n == 0){
				return ret;
			}

		  let sortedP = p.slice().sort((a:any, b:any) => b.membership - a.membership);

      sortedP.forEach((element:any) => {
        let spotResult = this._getSpotRatio(p.find((item:any) => item.id === element.id), q.find((item:any) => item.id === element.id));
        sumSpotResults += spotResult;
				j++;
				if (j >= this._k){
          aux = sumSpotResults / this._k
          valaux = true;
				}
      });
			ret = sumSpotResults / this._k;
      if(valaux){
        ret = aux
      }
			return ret;
  }

  private _getSpotRatio(a:any, b:any){
			let r = 0.5;  //default value

			let a_mu = a.membership + this._alpha * a.hesitation;
			let a_nu = a.nonmembership + (1 - this._alpha) * a.hesitation;

			let b_mu = b.membership + this._alpha * b.hesitation;
			let b_nu = b.nonmembership + (1 - this._alpha) * b.hesitation;

			let o_mu = a.nonmembership + this._alpha * a.hesitation;
			let o_nu = a.membership +  (1 - this._alpha) * a.hesitation;

			let Aao = a_mu * o_nu - a_nu * o_mu;
			let Abo = b_mu * o_nu - b_nu * o_mu;

			if (Math.abs(Aao) > 0) {
				r = Abo / Aao;
				if (r > 0) {
					r = Math.min(1, r);
				} else {
					r = 0;
				}
			}
			return r;

  }

  private _approximateNonMembershipCDF(p: any, q:any){
    let ret = 0;

		let n = p.length;
		let j = 0;
		let sumSpotResults = 0;
    let aux = 0;
    let valaux = false;

			if (n == 0){
				return ret;
			}

		  let sortedP = p.slice().sort((a:any, b:any) => (a.nonmembership > b.nonmembership) ? 1 : -1);

      sortedP.forEach((element:any) => {
        let spotResult = this._getSpotRatio(p.find((item:any) => item.id === element.id), q.find((item:any) => item.id === element.id));
        sumSpotResults += spotResult;
				j++;
				if (j >= this._k){
          aux = sumSpotResults / this._k
          valaux = true;
				}
      });
			ret = sumSpotResults / this._k;
      if(valaux){
        ret = aux
      }
			return ret;
  }

  private _getSpotComparisons(individual: any, colectiva: any)
		{
			let spotComparisons: any = []
			individual.forEach((p: any )=> {
        colectiva.forEach((q:any) => {
          if(p.id === q.id){
            let spotc: any = {};
            spotc['id'] = p.id
            spotc['difference'] = (p.membership - q.membership) + this._alpha * (p.hesitation - q.hesitation);
            spotComparisons.push(spotc);
          }
        });
      });
			return spotComparisons;
		}

}


public _getSimilarity(individual: any, colectivo: any, k: number) {
    this._k = k;
    let ret = 0;
    if (this._k < 0) {
      this._k = individual.length;
    }
    let _result = this._getSimilarityExtended(individual, colectivo);
    ret = _result.level as number;
    return ret;
  }


private _getSimilarityExtended(individual: any, colectiva: any) {

    let  spotComparisons = this._getSpotComparisons(individual, colectiva);

    let sumAbs = 0;
		let n = spotComparisons.length;
    spotComparisons.forEach((sc:any) => {
      sumAbs += Math.abs(sc.difference);
    });
    let grossLevel = 1 - sumAbs / n;

    let cdfMembership = this._approximateMembershipCDF(individual, colectiva)                           ;
		let cdfNonMembership = this._approximateNonMembershipCDF(individual, colectiva);

    let _result:any = {
      CDFMembership: 0,
      CDFNonMembership: 0,
      CDF: 0,
      grossLevel:0,
      level:0
    };
    _result['CDFMembership'] = cdfMembership;
    _result['CDFNonMembership'] = cdfNonMembership;
    _result['CDF'] = (cdfMembership + cdfNonMembership) / 2;
    _result['grossLevel'] = grossLevel;
    _result['level'] = grossLevel * _result.CDF;
    return _result;
  }


private _approximateMembershipCDF(p: any, q: any){
    let ret = 0;

		let n = p.length;
		let j = 0;
		let sumSpotResults = 0;
    let aux = 0;
    let valaux = false;

			if (n == 0){
				return ret;
			}

		  let sortedP = p.slice().sort((a:any, b:any) => b.membership - a.membership);

      sortedP.forEach((element:any) => {
        let spotResult = this._getSpotRatio(p.find((item:any) => item.id === element.id), q.find((item:any) => item.id === element.id));
        sumSpotResults += spotResult;
				j++;
				if (j >= this._k){
          aux = sumSpotResults / this._k
          valaux = true;
				}
      });
			ret = sumSpotResults / this._k;
      if(valaux){
        ret = aux
      }
			return ret;
  }


private _getSpotRatio(a:any, b:any){
			let r = 0.5;  //default value

			let a_mu = a.membership + this._alpha * a.hesitation;
			let a_nu = a.nonmembership + (1 - this._alpha) * a.hesitation;

			let b_mu = b.membership + this._alpha * b.hesitation;
			let b_nu = b.nonmembership + (1 - this._alpha) * b.hesitation;

			let o_mu = a.nonmembership + this._alpha * a.hesitation;
			let o_nu = a.membership +  (1 - this._alpha) * a.hesitation;

			let Aao = a_mu * o_nu - a_nu * o_mu;
			let Abo = b_mu * o_nu - b_nu * o_mu;

			if (Math.abs(Aao) > 0) {
				r = Abo / Aao;
				if (r > 0) {
					r = Math.min(1, r);
				} else {
					r = 0;
				}
			}
			return r;

  }


private _approximateNonMembershipCDF(p: any, q:any){
    let ret = 0;

		let n = p.length;
		let j = 0;
		let sumSpotResults = 0;
    let aux = 0;
    let valaux = false;

			if (n == 0){
				return ret;
			}

		  let sortedP = p.slice().sort((a:any, b:any) => (a.nonmembership > b.nonmembership) ? 1 : -1);

      sortedP.forEach((element:any) => {
        let spotResult = this._getSpotRatio(p.find((item:any) => item.id === element.id), q.find((item:any) => item.id === element.id));
        sumSpotResults += spotResult;
				j++;
				if (j >= this._k){
          aux = sumSpotResults / this._k
          valaux = true;
				}
      });
			ret = sumSpotResults / this._k;
      if(valaux){
        ret = aux
      }
			return ret;
  }


private _getSpotComparisons(individual: any, colectiva: any)
		{
			let spotComparisons: any = []
			individual.forEach((p: any )=> {
        colectiva.forEach((q:any) => {
          if(p.id === q.id){
            let spotc: any = {};
            spotc['id'] = p.id
            spotc['difference'] = (p.membership - q.membership) + this._alpha * (p.hesitation - q.hesitation);
            spotComparisons.push(spotc);
          }
        });
      });
			return spotComparisons;
		}


() => this._isError


() => this._isCompleted


() => this._isPending


() => this._isImporting


() => this._isInProgress


() => this._isUnknown


(): StatusMetadata =>
    ({
      isError: this._isError,
      isCompleted: this._isCompleted,
      isPending: this._isPending,
      isImporting: this._isImporting,
      isInProgress: this._isInProgress,
      isUnknown: this._isUnknown,
      group: this.group,
    } as any)


() => this.label


() => this.group


() => this.simpleLabel


() => {
    return `${this.simpleLabel}${this.simpleLabel === this.toString() ? '' : this.toString()}`;
  }


() => {
    const result = this.label || super.toString();
    return this.group && !this._isUnknown ? `${result} (${this.group.getVerboseName()})` : result;
  }


export abstract class StatusEnum<SIMPLE_LABEL = StatusSimpleLabel> extends ObjectEnum<string> {
  protected readonly _isError: boolean;
  protected readonly _isCompleted: boolean;
  protected readonly _isPending: boolean;
  protected readonly _isImporting: boolean;
  protected readonly _isInProgress: boolean;
  protected readonly _isUnknown: boolean;

  protected readonly group: StatusGroup;
  protected readonly label: string;
  protected readonly simpleLabel: SIMPLE_LABEL | StatusSimpleLabel; // cache resolveSimpleLabel call

  protected constructor(
    value: string,
    label: string,
    {
      isError,
      isCompleted,
      isPending,
      isImporting,
      isInProgress,
      isUnknown,
      group,
    }: StatusMetadata = {},
  ) {
    super(value);
    if (label == null) {
      throw new Error('StatusEnum: requires label');
    }

    this._isError = isError || false;
    this._isCompleted = isCompleted || false;
    this._isPending = isPending || false;
    this._isImporting = isImporting || false;
    this._isInProgress = this._isPending || this._isImporting || isInProgress || false; // pending means expected progress

    const isKnown = isError || isCompleted || isPending || isImporting || isInProgress;

    if (isUnknown && isKnown) {
      throw new Error('StatusEnum: isUnknown flag should not include other metadata');
    }

    this._isUnknown = isUnknown;

    this.group = group;
    this.label = label;
    this.simpleLabel = this.resolveSimpleLabel();
  }

  isError = () => this._isError;

  isCompleted = () => this._isCompleted;

  isPending = () => this._isPending;

  isImporting = () => this._isImporting;

  isInProgress = () => this._isInProgress;

  isUnknown = () => this._isUnknown;

  getMetadata = (): StatusMetadata =>
    ({
      isError: this._isError,
      isCompleted: this._isCompleted,
      isPending: this._isPending,
      isImporting: this._isImporting,
      isInProgress: this._isInProgress,
      isUnknown: this._isUnknown,
      group: this.group,
    } as any);

  getLabel = () => this.label;

  getGroup = () => this.group;

  getSimpleLabel = () => this.simpleLabel;

  toString() {
    const result = this.label || super.toString();
    return this.group && !this._isUnknown ? `${result} (${this.group.toString()})` : result;
  }

  toSimpleSortString = () => {
    return `${this.simpleLabel}${this.simpleLabel === this.toString() ? '' : this.toString()}`;
  };

  toVerboseString = () => {
    const result = this.label || super.toString();
    return this.group && !this._isUnknown ? `${result} (${this.group.getVerboseName()})` : result;
  };

  protected resolveSimpleLabel(): SIMPLE_LABEL | StatusSimpleLabel {
    if (this._isError) {
      return StatusSimpleLabel.Error;
    }
    if (this._isCompleted) {
      return StatusSimpleLabel.Completed;
    }
    if (this._isPending) {
      return StatusSimpleLabel.Pending;
    }
    if (this._isImporting) {
      return StatusSimpleLabel.Importing;
    }
    if (this._isInProgress) {
      return StatusSimpleLabel.InProgress;
    }
    return StatusSimpleLabel.Other;
  }
}


export interface StatusMetadata {
  isError?: boolean;
  isCompleted?: boolean;
  isPending?: boolean;
  isImporting?: boolean;
  isInProgress?: boolean;
  isUnknown?: boolean;
  group?: StatusGroup;
}


toString() {
    const result = this.label || super.toString();
    return this.group && !this._isUnknown ? `${result} (${this.group.toString()})` : result;
  }


protected resolveSimpleLabel(): SIMPLE_LABEL | StatusSimpleLabel {
    if (this._isError) {
      return StatusSimpleLabel.Error;
    }
    if (this._isCompleted) {
      return StatusSimpleLabel.Completed;
    }
    if (this._isPending) {
      return StatusSimpleLabel.Pending;
    }
    if (this._isImporting) {
      return StatusSimpleLabel.Importing;
    }
    if (this._isInProgress) {
      return StatusSimpleLabel.InProgress;
    }
    return StatusSimpleLabel.Other;
  }


export interface BotSite {
    name: string;
    enabled: boolean;
    url: string;
    authorization: string;
    body: string;
}


export interface BaseConfig {
    client: {
        ID: string;
        TOKEN: string;
        INTENTS: any[];
        PARTIALS: PartialTypes[];
        CACHES: {
            [key: string]: number;
        };
    };

    DEVELOPERS: string[];

    infiniteFlight: {
        API_KEY: string;
    };

    api: {
        PORT: number;
        SECRET: string;
    };

    sharding: {
        SPAWN_DELAY: number;
        SPAWN_TIMEOUT: number;
        SERVERS_PER_SHARD: number;
    };

    clustering: {
        ENABLED: boolean;
        SHARD_COUNT: number;
        CALLBACK_URL: string;
        masterApi: {
            URL: string;
            TOKEN: string;
        };
    };

    jobs: {
        updateServerCount: {
            SCHEDULE: string;
            LOG: boolean;
        };
        notifyActiveInfiniteFlightUsers: {
            SCHEDULE: string;
            LOG: boolean;
        };
    };

    rateLimiting: {
        commands: {
            AMOUNT: number;
            INTERVAL: number;
        };
        triggers: {
            AMOUNT: number;
            INTERVAL: number;
        };
        reactions: {
            AMOUNT: number;
            INTERVAL: number;
        };
        buttons: {
            AMOUNT: number;
            INTERVAL: number;
        };
    };

    logging: {
        PRETTY: boolean;
        rateLimit: {
            MIN_TIMEOUT: number;
        };
    };

    modelConstants: {
        verifyInfiniteFlightUserIdTicket: {
            STALE_BY_MINUTES: number;
        };
    };

    development: {
        dummyMode: {
            ENABLED: boolean;
            WHITE_LIST: string[];
        };

        CHECK_PERMS: boolean;

        shardMode: {
            ENABLED: boolean;
            VALUE: ShardingManagerMode;
        };
    };

    BOT_SITES: BotSite[];
}


function _getImageSetProps(props: React.Props<{}>, markdownProps: IPageMarkdownProps): IPageImageSetProps | undefined {
  let imageSet: IImageProps[] | undefined;
  if (props && props.children) {
    // tslint:disable-next-line:no-any
    React.Children.forEach(props.children, (child: any) => {
      if (child && child.type === 'li') {
        const textContent = child.props.children;
        const { resources } = markdownProps;

        if (typeof textContent === 'string' && textContent.indexOf('image:') === 0 && resources && resources.images) {
          const imageProps = resources.images[textContent.substr(6).trim()];

          if (imageProps) {
            imageSet = imageSet || [];

            imageSet.push(imageProps);
          }
        }
      }
    });
  }

  if (imageSet) {
    return {
      images: imageSet
    };
  }
}


(child: any) => {
      if (child && child.type === 'li') {
        const textContent = child.props.children;
        const { resources } = markdownProps;

        if (typeof textContent === 'string' && textContent.indexOf('image:') === 0 && resources && resources.images) {
          const imageProps = resources.images[textContent.substr(6).trim()];

          if (imageProps) {
            imageSet = imageSet || [];

            imageSet.push(imageProps);
          }
        }
      }
    }


(markdownProps: IPageMarkdownProps): IMarkdownProps => ({
  options: {
    overrides: {
      h1: {
        component: PageHeader
      },
      h2: {
        component: PageHeader,
        props: { as: 'h2' }
      },
      h3: {
        component: PageHeader,
        props: { as: 'h3' }
      },
      code: {
        component: PageTag
      },
      p: {
        component: (props: React.HTMLAttributes<HTMLElement>) => {
          const { resources } = markdownProps;
          const textContent = props.children;

          if (typeof textContent === 'string' && resources) {
            if (textContent.indexOf('image:') === 0 && resources.images) {
              const imageProps = resources.images[textContent.substr(6).trim()];

              if (imageProps) {
                return <Image {...imageProps} />;
              }
            }
          }
          return <PageParagraph {...props} />;
        }
      },
      a: {
        component: Link
      },
      ul: {
        component: (props: React.HTMLAttributes<HTMLElement>) => {
          let imageSetProps = _getImageSetProps(props, markdownProps);

          if (imageSetProps) {
            return <PageImageSet {...imageSetProps} />;
          }
          return <ul {...props} />;
        }
      },
      img: {
        component: Image
      },
      button: {
        component: DefaultButton
      }
    }
  }
})


(props: React.HTMLAttributes<HTMLElement>) => {
          const { resources } = markdownProps;
          const textContent = props.children;

          if (typeof textContent === 'string' && resources) {
            if (textContent.indexOf('image:') === 0 && resources.images) {
              const imageProps = resources.images[textContent.substr(6).trim()];

              if (imageProps) {
                return <Image {...imageProps} />;
              }
            }
          }
          return <PageParagraph {...props} />;
        }


(props: React.HTMLAttributes<HTMLElement>) => {
          let imageSetProps = _getImageSetProps(props, markdownProps);

          if (imageSetProps) {
            return <PageImageSet {...imageSetProps} />;
          }
          return <ul {...props} />;
        }


(props: IPageMarkdownProps) => <Markdown {...getMarkdownProps(props)}>{props.children}</Markdown>;


export interface IPageMarkdownResources {
  images?: {
    [key: string]: IImageProps;
  };
}


export interface IPageMarkdownProps {
  resources?: IPageMarkdownResources;
  children: string;
}


export enum FeedbackTypeEnum {
  Bug = "Bug",
  Improvement = "Improvement",
}


() => {
    TestBed.configureTestingModule({
      imports: [NzInputNumberModule, FormsModule, ReactiveFormsModule],
      declarations: [NzTestInputNumberBasicComponent, NzTestInputNumberFormComponent]
    });
    TestBed.compileComponents();
  }


() => {
      fixture = TestBed.createComponent(NzTestInputNumberBasicComponent);
      fixture.detectChanges();
      testComponent = fixture.debugElement.componentInstance;
      inputNumber = fixture.debugElement.query(By.directive(NzInputNumberComponent));
      inputElement = inputNumber.nativeElement.querySelector('input');
      upArrowEvent = createKeyboardEvent('keydown', UP_ARROW, inputElement, 'ArrowUp');
      downArrowEvent = createKeyboardEvent('keydown', DOWN_ARROW, inputElement, 'ArrowDown');
      upArrowCtrlEvent = createKeyboardEvent('keydown', UP_ARROW, inputElement, 'ArrowUp', true);
      downArrowCtrlEvent = createKeyboardEvent('keydown', DOWN_ARROW, inputElement, 'ArrowDown', true);
      upArrowMetaEvent = createKeyboardEvent('keydown', UP_ARROW, inputElement, 'ArrowUp', false, true);
      downArrowMetaEvent = createKeyboardEvent('keydown', DOWN_ARROW, inputElement, 'ArrowDown', false, true);
      upArrowShiftEvent = createKeyboardEvent('keydown', UP_ARROW, inputElement, 'ArrowUp', false, false, true);
      downArrowShiftEvent = createKeyboardEvent('keydown', DOWN_ARROW, inputElement, 'ArrowDown', false, false, true);
      upHandler = inputNumber.nativeElement.querySelector('.ant-input-number-handler-up');
      downHandler = inputNumber.nativeElement.querySelector('.ant-input-number-handler-down');
    }


() => {
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).toContain('ant-input-number');
      expect(inputElement.getAttribute('placeholder')).toBe('placeholder');
    }


() => {
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).toContain('ng-untouched');
      dispatchFakeEvent(inputElement, 'focus');
      fixture.detectChanges();
      tick();
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).toContain('ng-untouched');
      expect(inputNumber.nativeElement.classList).toContain('ant-input-number-focused');
      dispatchFakeEvent(inputElement, 'blur');
      fixture.detectChanges();
      tick();
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).not.toContain('ant-input-number-focused');
      expect(inputNumber.nativeElement.classList).toContain('ng-touched');
    }


() => {
      testComponent.size = 'large';
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).toContain('ant-input-number-lg');
      testComponent.size = 'small';
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).toContain('ant-input-number-sm');
    }


() => {
      fixture.detectChanges();
      testComponent.autofocus = true;
      testComponent.nzInputNumberComponent.nzAutoFocus = true;
      testComponent.nzInputNumberComponent.ngAfterViewInit();
      fixture.detectChanges();
      expect(inputElement === document.activeElement).toBe(true);
      expect(inputElement.attributes.getNamedItem('autofocus')!.name).toBe('autofocus');
      testComponent.autofocus = false;
      fixture.detectChanges();
      expect(inputElement.attributes.getNamedItem('autofocus')).toBe(null);
    }


() => {
      fixture.detectChanges();
      testComponent.nzInputNumberComponent.focus();
      fixture.detectChanges();
      expect(inputElement === document.activeElement).toBe(true);
      testComponent.nzInputNumberComponent.blur();
      fixture.detectChanges();
      expect(inputElement === document.activeElement).toBe(false);
    }


() => {
      testComponent.value = 5;
      fixture.detectChanges();
      flush();
      expect(inputElement.value).toBe('5');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(0);
    }


() => {
      testComponent.nzInputNumberComponent.onModelChange('');
      fixture.detectChanges();
      expect(testComponent.value).toBe('');
    }


() => {
      testComponent.nzInputNumberComponent.onModelChange('NaN');
      fixture.detectChanges();
      expect(testComponent.value).toBe(undefined);
    }


() => {
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(1);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('0');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(2);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('-1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(3);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('-1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(3);
    }


() => {
      testComponent.nzInputNumberComponent.onModelChange('1.');
      fixture.detectChanges();
      expect(testComponent.value).toBe(undefined);
      expect(inputElement.value).toBe('1.');
    }


() => {
      testComponent.nzInputNumberComponent.onModelChange('1.');
      fixture.detectChanges();
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1);
    }


() => {
      testComponent.nzInputNumberComponent.onModelChange('1.');
      fixture.detectChanges();
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(-1);
    }


() => {
      expect(testComponent.nzInputNumberComponent.downStep('abc', 1)).toBe(-1);
      testComponent.min = -Infinity;
      fixture.detectChanges();
      expect(testComponent.nzInputNumberComponent.downStep('abc', 1)).toBe(-1);
    }


() => {
      expect(testComponent.nzInputNumberComponent.upStep('abc', 1)).toBe(-1);
      testComponent.min = -Infinity;
      fixture.detectChanges();
      expect(testComponent.nzInputNumberComponent.upStep('abc', 1)).toBe(1);
    }


() => {
      expect(testComponent.nzInputNumberComponent.getValidValue(undefined)).toBe(undefined);
    }


() => {
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(1);
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(1);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('0');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(2);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('-1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(3);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('-1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(3);
    }


() => {
      testComponent.precision = undefined;
      fixture.detectChanges();
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(1);
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(1);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('0');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(2);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('-1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(3);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputElement.value).toBe('-1');
      expect(testComponent.modelChange).toHaveBeenCalledTimes(3);
    }


() => {
      testComponent.nzInputNumberComponent.onModelChange('123');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1);
      expect(testComponent.modelChange).toHaveBeenCalledTimes(1);
      testComponent.nzInputNumberComponent.onModelChange('0');
      fixture.detectChanges();
      expect(testComponent.value).toBe(0);
      expect(testComponent.modelChange).toHaveBeenCalledTimes(2);
      expect(testComponent.value).toBe(0);
      testComponent.nzInputNumberComponent.onModelChange('-4');
      fixture.detectChanges();
      expect(testComponent.value).toBe(-1);
      expect(testComponent.modelChange).toHaveBeenCalledTimes(3);
    }


() => {
      testComponent.precision = undefined;
      testComponent.max = 10;
      fixture.detectChanges();
      testComponent.nzInputNumberComponent.onModelChange('0.999999');
      expect(testComponent.value).toBe(0.999999);
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1.999999);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.999999);
      testComponent.nzInputNumberComponent.onModelChange('1e-10');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1e-10);
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1.0000000001);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1e-10);
    }


() => {
      testComponent.nzInputNumberComponent.onModelChange('0.99');
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.99);
      testComponent.nzInputNumberComponent.onModelChange('0.993');
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.99);
      testComponent.nzInputNumberComponent.onModelChange('0.999');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1);
    }


() => {
      testComponent.nzInputNumberComponent.onModelChange('0.999');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1);

      testComponent.precisionMode = 'toFixed';
      testComponent.nzInputNumberComponent.onModelChange('0.991');
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.99);
      testComponent.nzInputNumberComponent.onModelChange('0.999');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1);
      testComponent.nzInputNumberComponent.onModelChange('1.0099');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1);

      testComponent.precisionMode = 'cut';
      testComponent.nzInputNumberComponent.onModelChange('0.991');
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.99);
      testComponent.nzInputNumberComponent.onModelChange('0.998');
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.99);

      testComponent.precisionMode = value => +Number(value).toFixed(2);
      testComponent.nzInputNumberComponent.onModelChange('0.991');
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.99);
      testComponent.nzInputNumberComponent.onModelChange('0.998');
      fixture.detectChanges();
      expect(testComponent.value).toBe(1);
    }


value => +Number(value).toFixed(2)


() => {
      testComponent.step = 2;
      testComponent.max = 10;
      fixture.detectChanges();
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(2);
      expect(testComponent.modelChange).toHaveBeenCalledTimes(1);
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(4);
      expect(testComponent.modelChange).toHaveBeenCalledTimes(2);
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(testComponent.value).toBe(2);
    }


() => {
      fixture.detectChanges();
      expect(testComponent.value).toBe(undefined);
      dispatchEvent(inputElement, upArrowEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(1);
      dispatchEvent(inputElement, downArrowEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(0);
      dispatchEvent(inputElement, downArrowEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(-1);
      dispatchEvent(inputElement, downArrowEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(-1);
    }


() => {
      fixture.detectChanges();
      expect(testComponent.value).toBe(undefined);
      dispatchEvent(inputElement, upArrowCtrlEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.1);
      dispatchEvent(inputElement, downArrowCtrlEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(0);
      dispatchEvent(inputElement, downArrowCtrlEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(-0.1);
    }


() => {
      fixture.detectChanges();
      expect(testComponent.value).toBe(undefined);
      dispatchEvent(inputElement, upArrowMetaEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(0.1);
      dispatchEvent(inputElement, downArrowMetaEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(0);
      dispatchEvent(inputElement, downArrowMetaEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(-0.1);
    }


() => {
      testComponent.max = 100;
      testComponent.min = -100;
      fixture.detectChanges();
      expect(testComponent.value).toBe(undefined);
      dispatchEvent(inputElement, upArrowShiftEvent);
      dispatchFakeEvent(inputElement, 'keyup');
      fixture.detectChanges();
      expect(testComponent.value).toBe(10);
      dispatchEvent(inputElement, downArrowShiftEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(0);
      dispatchEvent(inputElement, downArrowShiftEvent);
      fixture.detectChanges();
      expect(testComponent.value).toBe(-10);
    }


() => {
      const newFormatter = (v: number) => `${v} %`;
      const initValue = 1;
      const component = testComponent.nzInputNumberComponent;
      fixture.detectChanges();
      component.onModelChange(`${initValue}`);
      fixture.detectChanges();
      testComponent.formatter = newFormatter;
      fixture.detectChanges();
      expect(inputElement.value).toBe(newFormatter(initValue));
    }


(v: number) => `${v} %`


() => {
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).toContain('ant-input-number-focused');
      dispatchFakeEvent(inputElement, 'blur');
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).not.toContain('ant-input-number-focused');
      dispatchFakeEvent(downHandler, 'mousedown');
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).toContain('ant-input-number-focused');
      dispatchFakeEvent(inputElement, 'blur');
      fixture.detectChanges();
      expect(inputNumber.nativeElement.classList).not.toContain('ant-input-number-focused');
    }


() => {
    let fixture: ComponentFixture<NzTestInputNumberFormComponent>;
    let testComponent: NzTestInputNumberFormComponent;
    let inputNumber: DebugElement;
    let upHandler: HTMLElement;

    beforeEach(fakeAsync(() => {
      fixture = TestBed.createComponent(NzTestInputNumberFormComponent);
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
      testComponent = fixture.debugElement.componentInstance;
      inputNumber = fixture.debugElement.query(By.directive(NzInputNumberComponent));
      upHandler = inputNumber.nativeElement.querySelector('.ant-input-number-handler-up');
    }));
    it('should be in pristine, untouched, and valid states initially', fakeAsync(() => {
      flush();
      expect(testComponent.formGroup.valid).toBe(true);
      expect(testComponent.formGroup.pristine).toBe(true);
      expect(testComponent.formGroup.touched).toBe(false);
    }));
    it('should set disabled work', fakeAsync(() => {
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
      expect(testComponent.formGroup.get('inputNumber')!.value).toBe(1);
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
      expect(testComponent.formGroup.get('inputNumber')!.value).toBe(10);
      testComponent.disable();
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
      expect(testComponent.formGroup.get('inputNumber')!.value).toBe(10);
    }));
  }


() => {
      fixture = TestBed.createComponent(NzTestInputNumberFormComponent);
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
      testComponent = fixture.debugElement.componentInstance;
      inputNumber = fixture.debugElement.query(By.directive(NzInputNumberComponent));
      upHandler = inputNumber.nativeElement.querySelector('.ant-input-number-handler-up');
    }


() => {
      flush();
      expect(testComponent.formGroup.valid).toBe(true);
      expect(testComponent.formGroup.pristine).toBe(true);
      expect(testComponent.formGroup.touched).toBe(false);
    }


() => {
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
      expect(testComponent.formGroup.get('inputNumber')!.value).toBe(1);
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
      expect(testComponent.formGroup.get('inputNumber')!.value).toBe(10);
      testComponent.disable();
      dispatchFakeEvent(upHandler, 'mousedown');
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
      expect(testComponent.formGroup.get('inputNumber')!.value).toBe(10);
    }


(value: number) => (value !== null ? `${value}` : '')


(value: number) => value


@Component({
  template: `
    <nz-input-number
      [(ngModel)]="value"
      (ngModelChange)="modelChange($event)"
      [nzDisabled]="disabled"
      [nzAutoFocus]="autofocus"
      [nzSize]="size"
      [nzMin]="min"
      [nzMax]="max"
      [nzPlaceHolder]="placeholder"
      [nzStep]="step"
      [nzFormatter]="formatter"
      [nzParser]="parser"
      [nzPrecision]="precision"
      [nzPrecisionMode]="precisionMode"
    >
    </nz-input-number>
  `
})
export class NzTestInputNumberBasicComponent {
  @ViewChild(NzInputNumberComponent, { static: false }) nzInputNumberComponent: NzInputNumberComponent;
  value?: number | string;
  autofocus = false;
  disabled = false;
  min = -1;
  max = 1;
  size = 'default';
  placeholder = 'placeholder';
  step = 1;
  precision?: number = 2;
  precisionMode: 'cut' | 'toFixed' | ((value: number | string, precision?: number) => number);
  formatter = (value: number) => (value !== null ? `${value}` : '');
  parser = (value: number) => value;
  modelChange = jasmine.createSpy('change callback');
}


@Component({
  template: `
    <form [formGroup]="formGroup">
      <nz-input-number formControlName="inputNumber" nzMax="10" nzMin="-10"></nz-input-number>
    </form>
  `
})
export class NzTestInputNumberFormComponent {
  formGroup: FormGroup;

  constructor(private formBuilder: FormBuilder) {
    this.formGroup = this.formBuilder.group({
      inputNumber: [1]
    });
  }

  disable(): void {
    this.formGroup.disable();
  }
}


disable(): void {
    this.formGroup.disable();
  }


(value: any) => {
  if (value == null) {
    return value === undefined ? '[object Undefined]' : '[object Null]';
  }
  return toString.call(value);
}


(value: any) => {
  const type = typeof value;
  return value != null && (type == 'object' || type == 'function');
}


(object: any, remove: string[]) => {
  const newObj = { ...object };
  for (const n of remove) {
    delete newObj[n];
  }
  return newObj;
}


(value: any) => {
  if (!isObject(value)) {
    return false;
  }
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 9 which returns 'object' for typed arrays and other constructors.
  const tag = getTag(value);
  return ['[object Function]', '[object AsyncFunction]', '[object GeneratorFunction]', '[object Proxy]'].includes(tag);
}


// eslint-disable-next-line @typescript-eslint/no-redeclare -- intentional
export function CursorQueryArgsType<DTO>(
  DTOClass: Class<DTO>,
  opts: QueryArgsTypeOpts<DTO> = { ...DEFAULT_QUERY_OPTS, pagingStrategy: PagingStrategies.CURSOR },
): StaticCursorQueryArgsType<DTO> {
  const F = FilterType(DTOClass);
  const S = SortType(DTOClass);
  const P = CursorPagingType();

  @ArgsType()
  class QueryArgs implements Query<DTO> {
    static SortType = S;

    static FilterType = F;

    static PageType = P;

    @Field(() => P, {
      defaultValue: { first: opts.defaultResultSize ?? DEFAULT_QUERY_OPTS.defaultResultSize },
      description: 'Limit or page results.',
    })
    @ValidateNested()
    @Validate(PropertyMax, ['first', opts.maxResultsSize ?? DEFAULT_QUERY_OPTS.maxResultsSize])
    @Validate(PropertyMax, ['last', opts.maxResultsSize ?? DEFAULT_QUERY_OPTS.maxResultsSize])
    @Type(() => P)
    paging?: CursorPagingType;

    @Field(() => F, {
      defaultValue: !F.hasRequiredFilters ? opts.defaultFilter ?? DEFAULT_QUERY_OPTS.defaultFilter : undefined,
      description: 'Specify to filter the records returned.',
      nullable: false,
    })
    @ValidateNested()
    @Type(() => F)
    filter?: Filter<DTO>;

    @Field(() => [S], {
      defaultValue: opts.defaultSort ?? DEFAULT_QUERY_OPTS.defaultSort,
      description: 'Specify to sort results.',
    })
    @ValidateNested()
    @Type(() => S)
    sorting?: SortField<DTO>[];
  }
  return QueryArgs;
}


() => P


() => F


() => [S]


() => S


@ArgsType()
  class QueryArgs implements Query<DTO> {
    static SortType = S;

    static FilterType = F;

    static PageType = P;

    @Field(() => P, {
      defaultValue: { first: opts.defaultResultSize ?? DEFAULT_QUERY_OPTS.defaultResultSize },
      description: 'Limit or page results.',
    })
    @ValidateNested()
    @Validate(PropertyMax, ['first', opts.maxResultsSize ?? DEFAULT_QUERY_OPTS.maxResultsSize])
    @Validate(PropertyMax, ['last', opts.maxResultsSize ?? DEFAULT_QUERY_OPTS.maxResultsSize])
    @Type(() => P)
    paging?: CursorPagingType;

    @Field(() => F, {
      defaultValue: !F.hasRequiredFilters ? opts.defaultFilter ?? DEFAULT_QUERY_OPTS.defaultFilter : undefined,
      description: 'Specify to filter the records returned.',
      nullable: false,
    })
    @ValidateNested()
    @Type(() => F)
    filter?: Filter<DTO>;

    @Field(() => [S], {
      defaultValue: opts.defaultSort ?? DEFAULT_QUERY_OPTS.defaultSort,
      description: 'Specify to sort results.',
    })
    @ValidateNested()
    @Type(() => S)
    sorting?: SortField<DTO>[];
  }


export type StaticCursorQueryArgsType<DTO> = StaticQueryType<DTO, StaticCursorPagingType>;


export type CursorQueryArgsType<DTO> = QueryType<DTO, CursorPagingType>;


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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ WorklistComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(WorklistComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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


() => {
    TestBed.configureTestingModule({
      declarations: [ WorklistComponent ]
    })
    .compileComponents();
  }


() => {
    fixture = TestBed.createComponent(WorklistComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  }


/** 热力图的配置类型定义 */
export interface HeatmapOptions extends PlotOptions, HeatmapLayerOptions {
  /**
   * 具体的数据
   */
  source: HeatmapLayerSourceOptions;
}


() => {
      this.gameLaunched = true;
      this.apiClient.emit(stateApi.gameLaunched);
    }


(resolve) => {
      emit('sdk:getUserId');

      const handler = (id: string) => {
        resolve(id);
        RemoveEventHandler('sdk:setUserId', handler);
      };

      on('sdk:setUserId', handler);
    }


(id: string) => {
        resolve(id);
        RemoveEventHandler('sdk:setUserId', handler);
      }


@injectable()
export class AppStateService implements ApiContribution, AppContribution {
  getId() {
    return 'AppStateService';
  }

  public readonly onStateChange = new SingleEventEmitter<AppStates>();

  public readonly onServerDataStateChange = new SingleEventEmitter<ServerDataStates>();

  @inject(ApiClient)
  protected readonly apiClient: ApiClient;

  @inject(LogService)
  protected readonly logService: LogService;

  private userId: string = '';

  protected state: AppStates = AppStates.booting;
  protected serverDataState: ServerDataStates = ServerDataStates.checking;

  protected gameLaunched: boolean = false;

  async boot() {
    on('sdk:gameLaunched', () => {
      this.gameLaunched = true;
      this.apiClient.emit(stateApi.gameLaunched);
    });

    this.userId = await this.fetchUserId();

    this.logService.setUserId(this.userId);
  }

  getUserId(): string {
    return this.userId;
  }

  isGameLaunched() {
    return this.gameLaunched;
  }

  getState() {
    return this.state;
  }

  getServerDataState() {
    return this.serverDataState;
  }

  @handlesClientEvent(stateApi.ackState)
  onAckState() {
    this.ackState();

    this.apiClient.emit(stateApi.setUserId, this.userId);

    if (this.gameLaunched) {
      this.apiClient.emit(stateApi.gameLaunched);
    }
  };

  ackState() {
    this.apiClient.emit(stateApi.state, this.state);
  }

  ackServerDataState() {
    this.apiClient.emit(stateApi.serverDataState, this.serverDataState);
  }

  toState(newState: AppStates) {
    this.state = newState;
    this.onStateChange.emit(newState);
    this.ackState();
  }

  toServerDataState(newServerDataState: ServerDataStates) {
    this.serverDataState = newServerDataState;
    this.onServerDataStateChange.emit(newServerDataState);
    this.ackServerDataState();
  }

  private fetchUserId(): Promise<string> {
    return new Promise((resolve) => {
      emit('sdk:getUserId');

      const handler = (id: string) => {
        resolve(id);
        RemoveEventHandler('sdk:setUserId', handler);
      };

      on('sdk:setUserId', handler);
    });
  }
}


getId() {
    return 'AppStateService';
  }


async boot() {
    on('sdk:gameLaunched', () => {
      this.gameLaunched = true;
      this.apiClient.emit(stateApi.gameLaunched);
    });

    this.userId = await this.fetchUserId();

    this.logService.setUserId(this.userId);
  }


getUserId(): string {
    return this.userId;
  }


isGameLaunched() {
    return this.gameLaunched;
  }


getState() {
    return this.state;
  }


getServerDataState() {
    return this.serverDataState;
  }


@handlesClientEvent(stateApi.ackState)
  onAckState() {
    this.ackState();

    this.apiClient.emit(stateApi.setUserId, this.userId);

    if (this.gameLaunched) {
      this.apiClient.emit(stateApi.gameLaunched);
    }
  }


ackState() {
    this.apiClient.emit(stateApi.state, this.state);
  }


ackServerDataState() {
    this.apiClient.emit(stateApi.serverDataState, this.serverDataState);
  }


toState(newState: AppStates) {
    this.state = newState;
    this.onStateChange.emit(newState);
    this.ackState();
  }


toServerDataState(newServerDataState: ServerDataStates) {
    this.serverDataState = newServerDataState;
    this.onServerDataStateChange.emit(newServerDataState);
    this.ackServerDataState();
  }


private fetchUserId(): Promise<string> {
    return new Promise((resolve) => {
      emit('sdk:getUserId');

      const handler = (id: string) => {
        resolve(id);
        RemoveEventHandler('sdk:setUserId', handler);
      };

      on('sdk:setUserId', handler);
    });
  }


@EntityRepository(Task)
export class TaskRepository extends Repository<Task> {

    async getTasks(filterDto: GetTaskFilterDto, user:User ): Promise<Task[]> {
        const { status, search } = filterDto;
        const query = this.createQueryBuilder('task');

        query.where("task.userId = :userId" ,  { userId : user.id });

        if (status) {
            query.andWhere("task.status = :status", { status });
        }

        if (search) {
            query.andWhere("(task.title LIKE :search OR task.description LIKE :search) ", { search: `%${search}%`  });
        }

        const tasks = query.getMany();

        return tasks;

    }

    async createTask (createTaskDto: CreateTaskDto, user:User) : Promise<Task>{

        // this.create will mapp the dto
        let task = await this.create(createTaskDto);
        task.status = TaskStatus.OPEN;
        task.user = user;
        await task.save();

        delete task.user;

        return task;
    }
}


async getTasks(filterDto: GetTaskFilterDto, user:User ): Promise<Task[]> {
        const { status, search } = filterDto;
        const query = this.createQueryBuilder('task');

        query.where("task.userId = :userId" ,  { userId : user.id });

        if (status) {
            query.andWhere("task.status = :status", { status });
        }

        if (search) {
            query.andWhere("(task.title LIKE :search OR task.description LIKE :search) ", { search: `%${search}%`  });
        }

        const tasks = query.getMany();

        return tasks;

    }


async createTask (createTaskDto: CreateTaskDto, user:User) : Promise<Task>{

        // this.create will mapp the dto
        let task = await this.create(createTaskDto);
        task.status = TaskStatus.OPEN;
        task.user = user;
        await task.save();

        delete task.user;

        return task;
    }


() => {
  it('converts text decoration to figma compliant string', () => {
    expect(convertTextDecorationToFigma('none')).toBe('NONE');
    expect(convertTextDecorationToFigma('underline')).toBe('UNDERLINE');
    expect(convertTextDecorationToFigma('line-through')).toBe('STRIKETHROUGH');
    expect(convertTextDecorationToFigma('strikethrough')).toBe('STRIKETHROUGH');
  });
  it('converts non-compliant textDecoration to NONE', () => {
    expect(convertTextDecorationToFigma('something')).toBe('NONE');
  });
}


() => {
    expect(convertTextDecorationToFigma('none')).toBe('NONE');
    expect(convertTextDecorationToFigma('underline')).toBe('UNDERLINE');
    expect(convertTextDecorationToFigma('line-through')).toBe('STRIKETHROUGH');
    expect(convertTextDecorationToFigma('strikethrough')).toBe('STRIKETHROUGH');
  }


() => {
    expect(convertTextDecorationToFigma('something')).toBe('NONE');
  }


() => {
  it('converts text decoration to figma compliant string', () => {
    expect(convertFigmaToTextDecoration('NONE')).toBe('none');
    expect(convertFigmaToTextDecoration('UNDERLINE')).toBe('underline');
    expect(convertFigmaToTextDecoration('STRIKETHROUGH')).toBe('line-through');
  });
}


() => {
    expect(convertFigmaToTextDecoration('NONE')).toBe('none');
    expect(convertFigmaToTextDecoration('UNDERLINE')).toBe('underline');
    expect(convertFigmaToTextDecoration('STRIKETHROUGH')).toBe('line-through');
  }


(currentStep: string) => {
  waited++;
  switch (currentStep) {
    case "firstStep":
      return firstStep;
    case "createOrder":
      return verificationCodesStep;
    case "wait":
      return waitStep(waited);
    case "verify":
      return completedStep;
  }
}


(count: number) => ({
  type: "wait",
  url: `${BASE_API}/transaction/Wyre/${
    count > 60 ? "createOrder" : "wait"
  }/WyJuUGxEVGF2djFJaXR6MU9jZVNZTHVRLS0iLDEwMCwiRVVSIiwiQlRDIiwiY3JlZGl0Q2FyZCJd`,
})


export declare class VKontakteButton implements IShareButton {
    prop: ShareButtonProp;
    constructor(prop: ShareButtonProp);
    link(url: string, args?: ShareButtonArgs): string;
    count(): Observable<{}>;
}


link(url: string, args?: ShareButtonArgs): string;


count(): Observable<{}>;


function getFragmentHTML(fragment: DocumentFragment): string {
	return [...fragment.childNodes]
		// @ts-expect-error
		.map(n => n.outerHTML || n.textContent)
		.join('');
}


t => {
	const element =
;

	t.is(element.outerHTML, '
');
}


t => {
	const element = (

	);

	t.is(element.outerHTML, '

');
}


t => {
	const element = (

			{[
				0,
				1
			]}


t => {
	const element = 7;

	t.is(element.outerHTML, '7');
}


t => {
	const element = (
		<span>
			{1}
			{2}
			{3}
		</span>


t => {
	const element = test;

	t.is(element.outerHTML, 'test');
}


t => {
	const element = (
		<span>
			{'hello'} {'world'}
		</span>


t => {
	const element =
{document.createTextNode('Hello')}
;

	t.is(element.outerHTML, '
Hello
');
}


t => {
	const element = (
		<span>
			{true}
			{false}
		</span>


t => {
	const element = {null};

	t.is(element.outerHTML, '');
}


t => {
	const element = {undefined};

	t.is(element.outerHTML, '');
}


t => {
	const element = (
		<span>
			{0}
			{Number.NaN}
		</span>


t => {
	const firstElement = First;
	const secondElement = Second;
	const element = (

			{firstElement}
			{secondElement}


t => {
	const template = document.createElement('template');
	template.innerHTML = 'Hello, World! ';
	const fragment = template.content;
	const element =
{fragment}
;

	t.is(element.outerHTML, '
Hello, World!
');
}


t => {
	const createElementNSSpy = spy(document, 'createElementNS');

	const element = (
		<svg>
			<text x="20" y="20">
				Test
			</text>
		</svg>


t => {
	const createElementSpy = spy(document, 'createElement');
	const createElementNSSpy = spy(document, 'createElementNS');

	const element = (

Demo

			<svg>
				<text>Test</text>
			</svg>

	);

	t.truthy(element);
	t.true(createElementSpy.calledTwice);
	t.true(createElementNSSpy.calledTwice);

	t.deepEqual(createElementSpy.firstCall.args, ['h1']);
	t.deepEqual(createElementSpy.secondCall.args, ['div']);

	const xmlns = 'http://www.w3.org/2000/svg';
	t.deepEqual(createElementNSSpy.firstCall.args, [xmlns, 'text']);
	t.deepEqual(createElementNSSpy.secondCall.args, [xmlns, 'svg']);
	createElementSpy.restore();
	createElementNSSpy.restore();
}


t => {
	const setAttributeNS = spy(Element.prototype, 'setAttributeNS');

	const element = (
		<svg>
			<text id="text">Test</text>
			<use xlinkHref="#text" />
			<use xlink-invalid-attribute="#text" />
		</svg>


t => {
	const element = ;

	t.is(element.outerHTML, '');
}


t => {
	// @ts-expect-error
	const element = ;

	t.is(element.outerHTML, '');
}


t => {
	const style = {
		paddingTop: 10,
		width: 200,
		height: '200px',
		fontSize: 12
	};

	const element = ;

	t.is(
		element.outerHTML,
		''
	);
}


t => {
	const style = {
		'padding-top': 10,
		'font-size': 12
	};

	// @ts-expect-error
	const element = ;

	t.is(
		element.outerHTML,
		''
	);
}


t => {
	const style = {
		'--padding-top': 10,
		'--myCamelCaseVar': 'red'
	};

	// @ts-expect-error
	const element = ;

	t.is(
		element.outerHTML,
		''
	);
}


t => {
	const element = (
		<a href="video.mp4" id="a" referrerPolicy="no-referrer">
			Download
		</a>


t => {
	const element = Full name;

	t.is(element.outerHTML, 'Full name');
}


t => {
	const input = (
		<input disabled={false} />


t => {
	const element = (

			Download


t => {
	const element = (
		// @ts-expect-error
		<a href={undefined} title={null}>
			Download
		</a>


t => {
	const element = Download;

	t.is(element.outerHTML, 'Download');
}


t => {
	const element =
{''}
;

	t.is(element.outerHTML, '
<script>alert();</script>
');
}


t => {
	const element = (
		<div dangerouslySetInnerHTML={{__html: '<script>alert();</script>'}}


t => {
	const addEventListener = spy(EventTarget.prototype, 'addEventListener');

	const handleClick = function () {};
	const element = (
		<a href="#" onClick={handleClick}>
			Download
		</a>


t => {
	const addEventListener = spy(EventTarget.prototype, 'addEventListener');

	const handler = function () {};
	const element = (
		<a href="#" onremote-input={handler} on-remote-input={handler}>
			Download
		</a>


t => {
	const createDocumentFragment = spy(document, 'createDocumentFragment');

	const fragment = <>test</>;

	const fragmentHTML = getFragmentHTML(fragment);

	t.is(fragmentHTML, 'test');
	t.true(createDocumentFragment.calledOnce);
	t.deepEqual(createDocumentFragment.firstCall.args, []);
}


t => {
	const fragment = (
		<>

test

		</>
	);

	const fragmentHTML = getFragmentHTML(fragment);

	t.is(fragmentHTML, '
test
');
}


t => {
	const fragment = (
		<>

heading
 text
		</>
	);

	const fragmentHTML = getFragmentHTML(fragment);

	t.is(fragmentHTML, '
heading
 text');
}


t => {
	const element = (

			<>

heading
 text
			</>
			outside fragment


t => {
	const Icon = () => <i/>;

	const element = <Icon />;

	t.is(element.outerHTML, '<i></i>');
}


() => <i/>;


t => {
	const Icon = () => Gummy bears;

	const element = <Icon />;

	t.is(element.outerHTML, 'Gummy bears');
}


() => <i className


t => {
	const Icon = () => Gummy bears;

	// @ts-expect-error
	const element = <Icon className="yellow"> and lollipops</Icon>;

	t.is(
		element.outerHTML,
		'Gummy bears and lollipops'
	);
}


n => n.outerHTML || n.textContent


export class pairEntityData{
toCurrency: any;
pairedCurrency: any;

}


(a, b) => a.performanceImpact - b.performanceImpact


(options: RuleEvaluationOptions) => {
		for (let rule of this.rules) {
			const message = rule.evaluate(options)
			if (message) return message
		}
	}


(options: BulkRuleEvaluationOptions) => {
		this.rules.forEach(rule => rule.evaluateBulk(options))
	}


rule => rule.evaluateBulk(options)


export class RuleEvaluator {
	private readonly rules: Rule[]
	constructor(rules: RuleDefinition[]) {
		this.rules = parseRules(rules).sort(
			(a, b) => a.performanceImpact - b.performanceImpact
		)
	}

	evaluate = (options: RuleEvaluationOptions) => {
		for (let rule of this.rules) {
			const message = rule.evaluate(options)
			if (message) return message
		}
	}

	bulkEvaluate = (options: BulkRuleEvaluationOptions) => {
		this.rules.forEach(rule => rule.evaluateBulk(options))
	}
}


() => {
  it('should render correctly', () => {
    const props: Props = { game: testGame };
    const component = shallow(<GameInfo {...props} />);
    expect(component).toMatchSnapshot();
  });
}


() => {
    const props: Props = { game: testGame };
    const component = shallow(<GameInfo {...props} />);
    expect(component).toMatchSnapshot();
  }


function Sender() {
    const [emittedPhoton, setEmittedPhoton] = useState<React.ReactNode>(null);
    const [passingPhoton, setPassingPhoton] = useState<React.ReactNode>(null);
    const [polarizedPhoton, setPolarizedPhoton] = useState<React.ReactNode>(null);

    function handlePhotonEmission(photon: React.ReactNode) {
        setEmittedPhoton(photon);
    }

    function handleEmittedPhotonTransported(photon: React.ReactNode) {
        setEmittedPhoton(null);
        setPassingPhoton(photon);
    }

    function handlePhotonPassed(photon: React.ReactNode) {
        setPassingPhoton(null);
        setPolarizedPhoton(photon)
    }

    function handlePolarizedPhotonTransported(photon: React.ReactNode) {
        console.log((photon as any).props.qbit.polarization);

        setPolarizedPhoton(null);
    }

    return (

                <OpticalFiber pathD="M 0 200 v -200" photon={polarizedPhoton} onAnimationEnd={handlePolarizedPhotonTransported}></OpticalFiber>

                <PolarizationWheel passingPhoton={passingPhoton} onPhotonPassed={handlePhotonPassed}/>

                <OpticalFiber pathD="M 0 200 v -200" photon={emittedPhoton} onAnimationEnd={handleEmittedPhotonTransported}></OpticalFiber>

                <PhotonSource onPhotonEmission={handlePhotonEmission} />

    );
}


function handlePhotonEmission(photon: React.ReactNode) {
        setEmittedPhoton(photon);
    }


function handleEmittedPhotonTransported(photon: React.ReactNode) {
        setEmittedPhoton(null);
        setPassingPhoton(photon);
    }


function handlePhotonPassed(photon: React.ReactNode) {
        setPassingPhoton(null);
        setPolarizedPhoton(photon)
    }


function handlePolarizedPhotonTransported(photon: React.ReactNode) {
        console.log((photon as any).props.qbit.polarization);

        setPolarizedPhoton(null);
    }


(last, current) => last + current.length


job => {
        switch (job.type) {
          case 'string':
            this.#offset += this.encodeString(dataView, job);
            break;
          case 'float32':
            this.#offset += this.encodeValue(dataView, dataView.setFloat32, job);
            break;
          case 'float64':
            this.#offset += this.encodeValue(dataView, dataView.setFloat64, job);
            break;
          case 'int8':
            this.#offset += this.encodeValue(dataView, dataView.setInt8, job);
            break;
          case 'int16':
            this.#offset += this.encodeValue(dataView, dataView.setInt16, job);
            break;
          case 'int32':
            this.#offset += this.encodeValue(dataView, dataView.setInt32, job);
            break;
          case 'uint8':
            this.#offset += this.encodeValue(dataView, dataView.setUint8, job);
            break;
          case 'uint16':
            this.#offset += this.encodeValue(dataView, dataView.setUint16, job);
            break;
          case 'uint32':
            this.#offset += this.encodeValue(dataView, dataView.setUint32, job);
            break;
          default:
            throw new Error(`Unrecognized type '${job.type}'`)
        }
      }


/** @internal */
interface BufferJob {
  type: BufferContentType,
  value: number | string,
  length: number,
  encoding?: BufferStringEncoding,
  littleEndian?: boolean
}


export interface BufferCodecConstructorOptions {
  buffer?: ArrayBuffer,
  encoding?: BufferStringEncoding
}


/**
   * Creates a new BufferCodec instance from given buffer
   * @param {Buffer | ArrayBuffer} buffer Either ArrayBuffer or Buffer
   * @returns {BufferCodec} A new instance of BufferCodec
   */
static from(buffer: Buffer | ArrayBuffer): BufferCodec {
    if (buffer && buffer.byteLength > 0) {
      if (buffer instanceof ArrayBuffer) {
        return new BufferCodec({ buffer });
      } else {
        const arrayBuffer = new ArrayBuffer(buffer.length);
        const view = new Uint8Array(arrayBuffer);

        for (let i = 0; i < buffer.length; ++i) {
          view[i] = buffer[i];
        }

        return new BufferCodec({ buffer: arrayBuffer });
      }
    } else {
      throw new Error("Received malformed data.");
    }
  }


/**
   * Sets string encoding
   * @param encoding {BufferStringEncoding} String encoding (either 'utf8' or 'utf16')
   * @returns {BufferCodec} Current instance of BufferCodec
   */
setEncoding(encoding: BufferStringEncoding): BufferCodec {
    if (encoding !== 'utf16' && encoding !== 'utf8') {
      throw new Error(`Unsupported encoding '${encoding}'. Only UTF-8 and UTF-16 are currently supported.`);
    }

    this.#encoding = encoding;

    return this;
  }


/**
   * Encode all queued values and return resulting buffer
   * @returns {ArrayBuffer} Encoded buffer
   */
result(): ArrayBuffer {
    this.#offset = 0;

    const bufferLength = this.#jobs.reduce((last, current) => last + current.length, 0);
    const buffer = new ArrayBuffer(bufferLength);
    const dataView = new DataView(buffer);

    if (this.#jobs.length > 0) {
      this.#jobs.forEach(job => {
        switch (job.type) {
          case 'string':
            this.#offset += this.encodeString(dataView, job);
            break;
          case 'float32':
            this.#offset += this.encodeValue(dataView, dataView.setFloat32, job);
            break;
          case 'float64':
            this.#offset += this.encodeValue(dataView, dataView.setFloat64, job);
            break;
          case 'int8':
            this.#offset += this.encodeValue(dataView, dataView.setInt8, job);
            break;
          case 'int16':
            this.#offset += this.encodeValue(dataView, dataView.setInt16, job);
            break;
          case 'int32':
            this.#offset += this.encodeValue(dataView, dataView.setInt32, job);
            break;
          case 'uint8':
            this.#offset += this.encodeValue(dataView, dataView.setUint8, job);
            break;
          case 'uint16':
            this.#offset += this.encodeValue(dataView, dataView.setUint16, job);
            break;
          case 'uint32':
            this.#offset += this.encodeValue(dataView, dataView.setUint32, job);
            break;
          default:
            throw new Error(`Unrecognized type '${job.type}'`)
        }
      });
    }

    this.#jobs = [];

    return dataView.buffer;
  }


/**
   * Decode a single value from current offset
   * @param options {BufferTypeOptions} Value decoding options
   * @returns Decoded value
   */
decode(options: BufferTypeOptions): any {
    const dataView = this.#dataView!;

    let itemValue;

    switch (options.type) {
      case 'int8':
        itemValue = dataView.getInt8(this.#offset);
        this.#offset += 1;
        break;
      case 'uint8':
        itemValue = dataView.getUint8(this.#offset);
        this.#offset += 1;
        break;
      case 'int16':
        itemValue = dataView.getInt16(this.#offset, options.littleEndian);
        this.#offset += 2;
        break;
      case 'uint16':
        itemValue = dataView.getUint16(this.#offset, options.littleEndian);
        this.#offset += 2;
        break;
      case 'int32':
        itemValue = dataView.getInt32(this.#offset, options.littleEndian);
        this.#offset += 4;
        break;
      case 'uint32':
        itemValue = dataView.getUint32(this.#offset, options.littleEndian);
        this.#offset += 4;
        break;
      case 'float32':
        itemValue = dataView.getFloat32(this.#offset, options.littleEndian);
        this.#offset += 4;
        break;
      case 'float64':
        itemValue = dataView.getFloat64(this.#offset, options.littleEndian);
        this.#offset += 8;
        break;
      case 'string':
        const [ decodedString, length ] = this.decodeString(dataView, options.encoding || this.#encoding);
        itemValue = decodedString;
        this.#offset += length;
        break;
      default:
        throw new Error(`Type '${options.type}' is not supported.`);
    }

    return itemValue;
  }


/**
   * Decode the whole buffer using provided template
   * @param template {BufferTemplate | BufferTemplate[]} Template to use for buffer decoding
   * @returns {any} Decoded object
   */
parse(template: BufferTemplate | BufferTemplate[]): any {
    return BufferStrategy.decode(template, this);
  }


/**
   * Encodes a string value
   * @param value {string} String to encode
   * @param encoding {BufferStringEncoding} String encoding (either 'utf8' or 'utf16'). This parameter takes precedence over the general encoding property set on BufferCodec instance
   * @returns {BufferCodec} Current instance of BufferCodec
   */
string(value: string, encoding: BufferStringEncoding = this.#encoding): BufferCodec {
    this.#jobs.push({
      type: 'string',
      length: (encoding === 'utf16' ? value.length * 2 : value.length) + 1,
      encoding: encoding,
      value
    });

    return this;
  }


/**
   * Encode a signed 8-bit number
   * @param value 8-bit numeric value
   * @returns {BufferCodec} Current instance of BufferCodec
   */
int8(value: number): BufferCodec {
    this.#jobs.push({
      value,
      type: 'int8',
      length: 1
    });

    return this;
  }


/**
   * Encode an unsigned 8-bit number
   * @param value 8-bit numeric value
   * @returns {BufferCodec} Current instance of BufferCodec
   */
uint8(value: number): BufferCodec {
    this.#jobs.push({
      value,
      type: 'uint8',
      length: 1
    });

    return this;
  }


/**
   * Encode a signed 16-bit number
   * @param value 16-bit numeric value
   * @returns {BufferCodec} Current instance of BufferCodec
   */
int16(value: number, littleEndian: boolean = false): BufferCodec {
    this.#jobs.push({
      value,
      type: 'int16',
      length: 2,
      littleEndian
    });

    return this;
  }


/**
   * Encode an unsigned 16-bit number
   * @param value 16-bit numeric value
   * @returns {BufferCodec} Current instance of BufferCodec
   */
uint16(value: number, littleEndian: boolean = false): BufferCodec {
    this.#jobs.push({
      value,
      type: 'uint16',
      length: 2,
      littleEndian
    });

    return this;
  }


/**
   * Encode a signed 32-bit number
   * @param value 32-bit numeric value
   * @returns {BufferCodec} Current instance of BufferCodec
   */
int32(value: number, littleEndian: boolean = false): BufferCodec {
    this.#jobs.push({
      value,
      type: 'int32',
      length: 4,
      littleEndian
    });

    return this;
  }


/**
   * Encode an unsigned 32-bit number
   * @param value 32-bit numeric value
   * @returns {BufferCodec} Current instance of BufferCodec
   */
uint32(value: number, littleEndian: boolean = false): BufferCodec {
    this.#jobs.push({
      value,
      type: 'uint32',
      length: 4,
      littleEndian
    });

    return this;
  }


/**
   * Encode a 32-bit float
   * @param value 32-bit numeric value
   * @returns {BufferCodec} Current instance of BufferCodec
   */
float32(value: number, littleEndian: boolean = false): BufferCodec {
    this.#jobs.push({
      value,
      type: 'float32',
      length: 4,
      littleEndian
    });

    return this;
  }


/**
   * Encode a 64-bit float
   * @param value 64-bit numeric value
   * @returns {BufferCodec} Current instance of BufferCodec
   */
float64(value: number, littleEndian: boolean = false): BufferCodec {
    this.#jobs.push({
      value,
      type: 'float64',
      length: 8,
      littleEndian
    });

    return this;
  }