lodash#inRange TypeScript Examples

The following examples show how to use lodash#inRange. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From aqualink-app with MIT License 7 votes vote down vote up
filterHistoricalMonthlyMeanData = (
  historicalMonthlyMean: HistoricalMonthlyMeanData[],
  from?: string,
  to?: string
) => {
  if (!from || !to) {
    return historicalMonthlyMean;
  }

  const start = moment(from);
  const end = moment(to);

  const closestToStart = getHistoricalMonthlyMeanDataClosestToDate(
    historicalMonthlyMean,
    new Date(start.toISOString())
  )?.value;
  const closestToEnd = getHistoricalMonthlyMeanDataClosestToDate(
    historicalMonthlyMean,
    new Date(end.toISOString())
  )?.value;

  const closestToStartArray: HistoricalMonthlyMeanData[] = closestToStart
    ? [{ date: start.toISOString(), value: closestToStart }]
    : [];
  const closestToEndArray: HistoricalMonthlyMeanData[] = closestToEnd
    ? [{ date: end.toISOString(), value: closestToEnd }]
    : [];

  const filteredData = historicalMonthlyMean.filter((item) =>
    inRange(moment(item.date).valueOf(), start.valueOf(), end.valueOf() + 1)
  );

  return [...closestToStartArray, ...filteredData, ...closestToEndArray];
}
Example #2
Source File: range-selection.ts    From S2 with MIT License 6 votes vote down vote up
private handleRowSelected(
    startIndex: number,
    endIndex: number,
    cell: S2CellType<ViewMeta>,
  ) {
    // ROW_CELL类型 最后一个Level支持区间选择
    return this.spreadsheet.facet.layoutResult.rowNodes
      .filter(({ rowIndex }) => inRange(rowIndex, startIndex, endIndex + 1))
      .map((e) => ({
        id: e.id,
        colIndex: e.colIndex,
        rowIndex: e.rowIndex,
        type: cell.cellType,
      }));
  }
Example #3
Source File: range-selection.ts    From S2 with MIT License 6 votes vote down vote up
private handleColSelected(
    startIndex: number,
    endIndex: number,
    cell: S2CellType<ViewMeta>,
  ) {
    // COL_CELL类型 最后一个Level支持区间选择
    return this.spreadsheet.facet.layoutResult.colLeafNodes
      .filter(({ colIndex }) => inRange(colIndex, startIndex, endIndex + 1))
      .map((e) => ({
        id: e.id,
        colIndex: e.colIndex,
        rowIndex: e.rowIndex,
        type: cell.cellType,
      }));
  }
Example #4
Source File: bleachingAlert.ts    From aqualink-app with MIT License 6 votes vote down vote up
calculateAlertLevel = (
  maxMonthlyMean?: number | null,
  satelliteTemperature?: number | null,
  degreeHeatingDays?: number | null,
): number | undefined => {
  const hotSpot =
    satelliteTemperature &&
    maxMonthlyMean &&
    satelliteTemperature - maxMonthlyMean;

  switch (true) {
    case isNil(hotSpot):
      return undefined;

    case isNumber(hotSpot) && hotSpot <= 0:
      return 0;

    case isNumber(hotSpot) && hotSpot < 1:
      return 1;

    // Hotspot >=1 or nil past this point, start dhw checks.
    case isNil(degreeHeatingDays):
      return 0;

    case inRange(degreeHeatingDays!, 0, 4 * 7):
      return 2;

    case inRange(degreeHeatingDays!, 4 * 7, 8 * 7):
      return 3;

    case degreeHeatingDays! >= 8 * 7:
      return 4;

    default:
      return undefined;
  }
}
Example #5
Source File: helpers.ts    From aqualink-app with MIT License 6 votes vote down vote up
filterSofarData =
  (from?: string, to?: string) => (data?: ValueWithTimestamp[]) => {
    if (!from || !to || !data) {
      return data;
    }

    return data?.filter(({ timestamp }) =>
      inRange(
        moment(timestamp).valueOf(),
        moment(from).valueOf(),
        moment(to).valueOf() + 1
      )
    );
  }
Example #6
Source File: NumericField.tsx    From nextclade with MIT License 5 votes vote down vote up
export function NumericField({
  identifier,
  label,
  onValueChanged,
  value,
  min,
  max,
  disabled,
  title,
  ...props
}: NumericFieldProps) {
  const { t } = useTranslation()
  const [current, setCurrent] = useState(value.toString())
  useEffect(() => {
    setCurrent(value.toString())
  }, [value])

  const [error, setError] = useState<string | undefined>(undefined)

  const onChange = useCallback(
    (e: ChangeEvent<HTMLInputElement>) => {
      const str = e.target.value
      setCurrent(str)

      let num: number | undefined
      try {
        num = Number.parseInt(str, 10)
      } catch {} // eslint-disable-line no-empty

      if (num === undefined) {
        setError(t('Should be a number'))
        return
      }

      if (!inRange(num, min, max)) {
        setError(t('Should be in range from {{minimum}} to {{maximum}}', { minimum: min, maximum: max - 1 }))
      } else {
        setError(undefined)
        onValueChanged(num)
      }
    },
    [max, min, onValueChanged, t],
  )

  return (
    <FormGroup>
      <Label htmlFor={identifier} disabled={disabled} title={title}>
        <LabelText disabled={disabled}>{label}</LabelText>
        <ErrorText disabled={disabled}>{error}</ErrorText>
      </Label>
      <Input
        title={title}
        className={classNames(error && !disabled && 'border-danger', 'col-sm-3')}
        type="number"
        id={identifier}
        name={identifier}
        value={current}
        onChange={onChange}
        disabled={disabled}
        {...props}
      />
    </FormGroup>
  )
}
Example #7
Source File: ClipboardRenderer.tsx    From DittoPlusPlus with MIT License 4 votes vote down vote up
ClipboardRenderer = (props: PluginTypes.RenderProps) => {
  const [clipItems, updateClipItems] = useState<ClipItemDoc[]>([]);
  const [selectedIndex, updateSelectedIndex] = useState(0);
  const [imagesDir, updateImagesDir] = useState<string>('');
  const [searchText, updateSearchText] = useState('');
  const {pluginProcess} = props;
  const searchBarRef = useRef<HTMLInputElement>(null);
  const clipsListRef = useRef<HTMLDivElement>(null);

  const resetClips = () => {
    pluginProcess.send(Messages.GetAllClipItems, undefined, (err, clips) => {
      if (!err) {
        updateClipItems([...clips]);
      }
    });
  };

  const hideWindow = () => {
    setImmediate(() => {
      ipcRenderer.send(GlobalEvents.HideWindow);
    });
  };

  const onKeyPress = (event: KeyboardEvent) => {
    const {keyCode} = event;

    /* disable scrolling by arrow keys */
    if ([38, 40].includes(keyCode)) {
      event.preventDefault();
    }

    if (clipsListRef.current) {
      const {clipItemDimensions, searchBarDimensions} = dimensions;

      const clipRowHeight =
        clipItemDimensions.heightPx +
        clipItemDimensions.paddingTopPx +
        clipItemDimensions.paddingBottomPx;

      const searchBarHeight =
        searchBarDimensions.heightPx +
        searchBarDimensions.paddingTopPx +
        searchBarDimensions.paddingBottomPx;

      const viewHeight = clipsListRef.current.offsetHeight - searchBarHeight;
      const itemsVisibleN = Math.floor(viewHeight / clipRowHeight);

      const itemsScrolled = Math.floor(
        clipsListRef.current.scrollTop / clipRowHeight,
      );

      const isItemInViewPort = inRange(
        selectedIndex,
        itemsScrolled,
        itemsVisibleN + itemsScrolled + 1,
      );

      /* up key */
      if (keyCode === 38) {
        if (isItemInViewPort) {
          clipsListRef.current.scrollBy({
            top: -clipRowHeight,
          });
        } else {
          clipsListRef.current.scrollTop = (selectedIndex - 2) * clipRowHeight;
        }

        updateSelectedIndex((prevSelectedIndex) =>
          clamp(prevSelectedIndex - 1, 0, clipItems.length - 1),
        );
      }

      /* down key */
      if (keyCode === 40) {
        if (selectedIndex >= itemsVisibleN - 1 && isItemInViewPort) {
          clipsListRef.current.scrollBy({top: clipRowHeight});
        } else if (clipsListRef.current.scrollTop) {
          clipsListRef.current.scrollTop = selectedIndex * clipRowHeight;
        }

        updateSelectedIndex((prevSelectedIndex) =>
          clamp(prevSelectedIndex + 1, 0, clipItems.length - 1),
        );
      }
    }

    /* escape */
    if (keyCode === 27) {
      if (searchText) {
        resetClips();
      } else {
        hideWindow();
      }

      handleSearchUpdate('');
    }

    /* enter key */
    if (keyCode === 13) {
      handleClipItemSelected(clipItems[selectedIndex]);
    }

    /* key is alphanumeric */
    if (isAlphanumeric(keyCode)) {
      updateSelectedIndex(0);
      searchBarRef.current && searchBarRef.current.focus();
    }
  };

  useEventListener('keydown', onKeyPress);

  useEffect(() => {
    resetClips();

    pluginProcess.on(Events.NewClip, (clip: ClipItemDoc) => {
      updateClipItems((prevClipItems) => [clip, ...prevClipItems]);
    });

    pluginProcess.on(Events.ClipsInitialized, (clips: ClipItemDoc[]) => {
      updateClipItems([...clips]);
    });

    ipcRenderer.on(GlobalEvents.ShowWindow, () => {
      if (process.platform === 'linux') {
        setImmediate(() => {
          searchBarRef.current && searchBarRef.current.blur();
        });
      }
    });

    ipcRenderer.on(GlobalEvents.HideWindow, () => {
      handleSearchUpdate('');
    });

    pluginProcess.send(
      Messages.GetImagesDir,
      undefined,
      (_err: any, _imagesDir: string) => {
        updateImagesDir(_imagesDir);
      },
    );
  }, []);

  const handleClipItemSelected = (item: ClipItemDoc) => {
    pluginProcess.send(Messages.ClipItemSelected, item, (err, res) => {
      if (err) {
        throw err;
      }

      if (res) {
        updateClipItems([...res]);
      }
    });

    handleSearchUpdate('');
    hideWindow();
  };

  const onClickClipItem = (item: ClipItemDoc) => {
    handleClipItemSelected(item);
  };

  const handleSearchUpdate = (text: string) => {
    updateSearchText(text);
    updateSelectedIndex(0);
    clipsListRef.current && (clipsListRef.current.scrollTop = 0);

    if (text === '') {
      searchBarRef.current && searchBarRef.current.blur();
      resetClips();
    } else {
      pluginProcess.send(Messages.SearchClips, text, (err, clips) => {
        if (err) {
          throw err;
        }

        updateClipItems([...clips]);
      });
    }
  };

  const onSearchTextChanged = (
    event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>,
  ) => {
    const query = event.target.value;
    handleSearchUpdate(query);
  };

  const getClipItemVariant = (index: number): ClipItemVariants => {
    if (index === selectedIndex) {
      return 'selected';
    }

    if (index % 2 === 0) {
      return 'dark';
    } else {
      return 'light';
    }
  };

  return (
    <StyledContainer>
      <SimpleBar
        style={SimpleBarStyles}
        scrollableNodeProps={{ref: clipsListRef}}
      >
        {clipItems.map((item, index) => (
          <ClipItem
            key={`${index}_clipItem`}
            clipItem={item}
            imagesDir={imagesDir}
            searchText={searchText}
            variant={getClipItemVariant(index)}
            onClick={() => onClickClipItem(item)}
          />
        ))}
      </SimpleBar>
      <SearchBar
        id="clipboard-searchbar"
        placeholder="search"
        onChange={onSearchTextChanged}
        value={searchText}
        ref={searchBarRef}
      />
    </StyledContainer>
  );
}
Example #8
Source File: heatmap.service.ts    From office-hours with GNU General Public License v3.0 4 votes vote down vote up
// PRIVATE function that is public for testing purposes
  // Rewind through the last few weeks and for each time interval,
  // figure out how long wait time would have been if you had joined the queue at that time
  // Timezone should be IANA
  // Returns heatmap in the timezone (ie 3rd bucket is 3am in that timezone)
  _generateHeatMapWithReplay(
    questions: QuestionModel[],
    hourTimestamps: [number, number][],
    timezone: string,
    bucketSize: number,
    samplesPerBucket: number,
  ): Heatmap {
    const sampleInterval = bucketSize / samplesPerBucket;
    /*
    TEST: Question1 is  3:05 - 3:25
    // The next question is 3:21 - 3:49
    THe following question is 4:05 - 4:10
    
    Bucket = 60, Samples = 3, so timepoints are: 3:00, 3:20, 3:40.

    3:20 sample gets waittime of 5 minutes
    3:40 samples get waittimes of 9 minutes
    4:00 sample gets waittime of 0 minutes


    If i entered the queue at that time when should I have gotten help?
    Every interval of minutes for the past 5 weeks are aggregated (by taking the avg)
    
    analyze the buckets to find the closest time approximation

    look at question Q1 and the next question Q2
    for all sample timepoints between Q1.createdAt and Q2.createdAt:
       - sample = Q1.helpedAt - timepoint (if negative, then it's 0)

  */

    function dateToBucket(date: Date | number): number {
      // parse in zone to handle daylight savings by getting day/hour/minute within that IANA zone
      const cInZone = moment.tz(date, timezone);
      return Math.floor(
        (cInZone.day() * 24 * 60 + cInZone.hour() * 60 + cInZone.minute()) /
          bucketSize,
      );
    }
    const timepointBuckets: number[][] = [
      ...Array((24 * 7 * 60) / bucketSize),
    ].map(() => []);

    if (questions.length) {
      const startDate = questions[0].createdAt;
      const sunday = moment.tz(startDate, timezone).startOf('week').toDate();

      function getNextTimepointIndex(date: Date): number {
        return Math.floor(timeDiffInMins(date, sunday) / sampleInterval) + 1;
      }

      // Get the date of the sample timepoint immediately after the given date
      function getNextSampleTimepoint(date: Date): Date {
        const timepointIndex = getNextTimepointIndex(date);
        return new Date(
          sunday.getTime() + timepointIndex * sampleInterval * 60 * 1000,
        );
      }

      // Get all timepoints between the two dates
      function getSampleTimepointsInDateRange(
        date1: Date,
        date2: Date,
      ): Date[] {
        const ret = [];
        let curr = getNextSampleTimepoint(date1);
        while (curr.getTime() < date2.getTime()) {
          ret.push(curr);
          curr = getNextSampleTimepoint(curr);
        }
        return ret;
      }

      // Get the start time of the current bucket
      function lastBucketBoundary(date: Date): moment.Moment {
        const startOfWeek = moment.tz(date, timezone).startOf('week');
        const m = moment(date);
        return m.subtract(m.diff(startOfWeek, 'm') % bucketSize, 'm');
      }

      // go two questions at a time
      let isFirst = true;
      for (let i = 0; i < questions.length; i++) {
        const curr = questions[i];
        const next = questions[i + 1];
        const isLast = i === questions.length - 1;

        // get the timepoints in between
        let sampledTimepoints = getSampleTimepointsInDateRange(
          isFirst
            ? lastBucketBoundary(curr.createdAt)
                .subtract(1, 's') // so that we get the first timepoint
                .toDate()
            : curr.createdAt,
          isLast
            ? lastBucketBoundary(curr.helpedAt)
                .add(bucketSize, 'm') // to get the nextBucketBoundary
                .toDate()
            : next.createdAt,
        );
        sampledTimepoints = sampledTimepoints.filter((time) =>
          hourTimestamps.some(([start, end]) =>
            inRange(time.getTime(), start, end),
          ),
        );

        // Pad the first bucket with zeros to account for timepoints before the first
        if (sampledTimepoints.length > 0 && isFirst) {
          isFirst = false;
        }
        // When we would have hypothetically gotten help at this timepoint
        for (const c of sampledTimepoints) {
          let wait = 0;
          if (
            inRange(
              c.getTime(),
              curr.createdAt.getTime(),
              curr.helpedAt.getTime(),
            )
          ) {
            wait = (curr.helpedAt.getTime() - c.getTime()) / 60000;
          }

          const bucketIndex = dateToBucket(c);
          timepointBuckets[bucketIndex].push(wait);
        }
      }
    }

    // Were there ever office hours in this bucket?
    const wereHoursDuringBucket: boolean[] = [
      ...Array((24 * 7 * 60) / bucketSize),
    ];
    for (const [start, end] of hourTimestamps) {
      //prevents an office hour from [N, M] to register in multiple buckets
      for (const i of range(dateToBucket(start), dateToBucket(end - 1) + 1)) {
        wereHoursDuringBucket[i] = true;
      }
    }

    const h: Heatmap = timepointBuckets.map((samples, i) => {
      if (samples.length > 0) {
        return mean(samples);
      } else if (wereHoursDuringBucket[i]) {
        return 0;
      } else {
        return -1;
      }
    });
    return h;
  }