<commit_before>// @flow
import React, { Component } from "react";
import * as time from "d3-time";
import MultiSeriesChart from "./MultiSeriesChart";
import type { FetcherComponentProps } from "./fetcher";

const months = [
  "Jan",
  "Feb",
  "Mar",
  "Apr",
  "May",
  "Jun",
  "Jul",
  "Aug",
  "Sep",
  "Oct",
  "Nov",
  "Dec"
];

function dateMonthCounts(histograms) {
  const keys = Object.keys(histograms);

  const [min, max] = [
    Math.min(...keys.map(k => new Date(histograms[k][0].value))),
    Math.max(...keys.map(k => new Date(histograms[k].slice(-1)[0].value)))
  ];

  const r = [time.timeMonth(min), ...time.timeMonths(min, max)];

  const counts = {};
  r.forEach(d => {
    counts[d] = keys.reduce((acc, next) => ({ ...acc, [next]: 0 }), {
      value: `${months[d.getMonth()]} ${d.getFullYear()}`
    });
  });

  keys.forEach(k =>
    histograms[k].forEach(v => {
      counts[time.timeMonth(new Date(v.value))][k] += v.count;
    })
  );

  return r.map(d => counts[d]);
}

function termCounts(buckets, terms) {
  const keys = Object.keys(buckets);
  const counts = {};
  terms.forEach(t => {
    counts[t.value] = keys.reduce((acc, next) => ({ ...acc, [next]: 0 }), {
      value: t.value
    });
  });

  keys.forEach(k => buckets[k].forEach(v => (counts[v.value][k] += v.count)));

  return terms.map(t => counts[t.value]);
}

function createRequest(filters) {
  const queryString = Object.keys(filters)
    .map(filterName =>
      filters[filterName]
        .map(val => `filter=${encodeURIComponent(`${filterName}=${val}`)}`)
        .join("&")
    )
    .filter(f => !!f)
    .join("&");

  return "/api/summary?" + queryString;
}

type AppState = {
  filters: {
    inspection_type: Array<string>,
    cuisine: Array<string>,
    boro: Array<string>
  }
};

export default class App extends Component {
  props: FetcherComponentProps;
  state: AppState = {
    filters: {
      inspection_type: [],
      cuisine: [],
      boro: []
    }
  };

  filterChange = (filter: string, e: any) => {<commit_msg>filter out series that do no have any results when determining range<commit_after>// @flow
import React, { Component } from "react";
import * as time from "d3-time";
import MultiSeriesChart from "./MultiSeriesChart";
import type { FetcherComponentProps } from "./fetcher";

const months = [
  "Jan",
  "Feb",
  "Mar",
  "Apr",
  "May",
  "Jun",
  "Jul",
  "Aug",
  "Sep",
  "Oct",
  "Nov",
  "Dec"
];

type Term = {
  value: string,
  count: number
};

type Buckets = {
  [string]: Array<Term>
};

export function dateMonthCounts(buckets: Buckets) {
  const keys = Object.keys(buckets);

  // find the min and max date in each series - this will give us
  // the min/max for the combined data. Note that the series are sorted
  // by date, so we only need to check the first and last elements of each
  // series
  const [min, max] = [
    Math.min(
      ...keys
        // filter out keys for empty series
        .filter(k => buckets[k].length > 0)
        // map each key to the first element of it series
        .map(k => new Date(buckets[k][0].value))
    ),
    Math.max(
      ...keys
        // filter out keys where the array has no elements
        .filter(k => buckets[k].length > 0)
        // map each key to the last element element of its series
        .map(k => new Date(buckets[k].slice(-1)[0].value))
    )
  ];

  // create a range of month buckets
  const r = [time.timeMonth(min), ...time.timeMonths(min, max)];

  // initialize each bucket to zero
  const counts = {};
  r.forEach(d => {
    counts[d] = keys.reduce((acc, next) => ({ ...acc, [next]: 0 }), {
      value: `${months[d.getMonth()]} ${d.getFullYear()}`
    });
  });

  // for each date in each series - determine the bucket to which it belongs and
  // add its count to the bucket count
  keys.forEach(k =>
    buckets[k].forEach(b => {
      counts[time.timeMonth(new Date(b.value))][k] += b.count;
    })
  );

  return r.map(d => counts[d]);
}

export function termCounts(buckets: Buckets, terms: Array<Term>) {
  const keys = Object.keys(buckets);
  const counts = {};
  terms.forEach(t => {
    counts[t.value] = keys.reduce((acc, next) => ({ ...acc, [next]: 0 }), {
      value: t.value
    });
  });

  keys.forEach(k => buckets[k].forEach(v => (counts[v.value][k] += v.count)));

  return terms.map(t => counts[t.value]);
}

export function createRequest(filters: Filters) {
  const queryString = Object.keys(filters)
    .map(filterName =>
      filters[filterName]
        .map(val => `filter=${encodeURIComponent(`${filterName}=${val}`)}`)
        .join("&")
    )
    .filter(f => !!f)
    .join("&");

  return "/api/summary?" + queryString;
}

type Filters = {
  inspection_type: Array<string>,
  cuisine: Array<string>,
  boro: Array<string>
};

type AppState = {
  filters: Filters
};

export default class App extends Component {
  props: FetcherComponentProps;
  state: AppState = {
    filters: {
      inspection_type: [],
      cuisine: [],
      boro: []
    }
  };

  filterChange = (filter: string, e: any) => {
{'fraction_non_alphanumeric': 0.1832377940304408, 'fraction_numerical': 0.0027673453251630758, 'mean_word_length': 2.8953040800615857, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3700241', 'n_tokens_mistral': 1768, 'n_tokens_neox': 1733, 'n_words': 434}