<commit_before>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {getIssues} from './issue';
import {Issue, IssueResult, LanguageResult, RepoResult} from './types';
import {languages} from './util';
import Table = require('cli-table');
import * as meow from 'meow';

function getRepoResults(repos: IssueResult[]) {
  const results = new Array<RepoResult>();
  const totals = {total: 0, p0: 0, p1: 0, p2: 0, pX: 0, outOfSLO: 0};
  repos.forEach(repo => {
    const counts = {
      total: 0,
      p0: 0,
      p1: 0,
      p2: 0,
      pX: 0,
      outOfSLO: 0,
      repo: repo.repo.repo,
      language: repo.repo.language
    };
    repo.issues.forEach(i => {
      if (isPullRequest(i)) {
        return;
      }
      counts.total++;
      totals.total++;

      if (isP0(i)) {
        counts.p0++;
        totals.p0++;
      } else if (isP1(i)) {
        counts.p1++;
        totals.p1++;
      } else if (isP2(i)) {
        counts.p2++;
        totals.p2++;
      }

      if (!isTriaged(i)) {
        counts.pX++;
        totals.pX++;
      }

      if (isOutOfSLO(i)) {
        counts.outOfSLO++;
        totals.outOfSLO++;
      }
    });
    results.push(counts);
  });
  return {repos: results, totals};
}

function getLanguageResults(repos: IssueResult[], api?: string) {
  const results = new Map<string, LanguageResult>();
  const issues = new Array<Issue>();
  repos.forEach(r => {
    r.issues.forEach(i => {
      i.language = r.repo.language;
      if (isPullRequest(i)) {
        return;
      }
      if (api && !isApi(i, api)) {
        return;
      }
      issues.push(i);
    });
  });
  languages.forEach(l => {
    results.set(
        l, {total: 0, p0: 0, p1: 0, p2: 0, pX: 0, outOfSLO: 0, language: l});
  });
  issues.forEach(i => {
    const counts = results.get(i.language)!;
    counts.total++;
    if (isP0(i)) {
      counts.p0++;
    } else if (isP1(i)) {
      counts.p1++;
    } else if (isP2(i)) {
      counts.p2++;
    }

    if (!isTriaged(i)) {
      counts.pX++;
    }

    if (isOutOfSLO(i)) {
      counts.outOfSLO++;
    }
  });
  return results;
}

/**
 * Determine if an issue has a `priority: ` label.
 * @param i Issue to analyze
 */
function hasPriority(i: Issue) {
  return hasLabel(i, 'priority: ');
}

/**
 * Determine if an issue has a `type: ` label.
 * @param i Issue to analyze
 */
function hasType(i: Issue) {
  return hasLabel(i, 'type: ');
}

/**
 * Determine if an issue has a `type: bug` label.
 * @param i Issue to analyze
 */
function isBug(i: Issue) {
  return hasLabel(i, 'type: bug');
}

function isP0(i: Issue) {
  return hasLabel(i, 'priority: p0');
}

function isP1(i: Issue) {
  return hasLabel(i, 'priority: p1');
}

function isP2(i: Issue) {
  return hasLabel(i, 'priority: p2');
}

function isAssigned(i: Issue) {
  return (i.assignee && i.assignee.length > 0) || i.assignees.length > 0;
}

export function isPullRequest(i: Issue) {
  return !!i.pull_request;
}

export function isApi(i: Issue, api: string) {
  for (const label of i.labels) {
    if (label.name.toLowerCase() === `api: ${api.toLowerCase()}`) {
      return true;
    }
  }
  // In node.js, we have separate repos for each API. We aren't looking for
  // a label, we're looking for a repo name.
  if (i.repo.indexOf('nodejs-') > -1) {
    const label = i.repo.split('-')[1];
    if (api.toLowerCase() === label.toLowerCase()) {
      return true;
    }
  }
  return false;
}

/**
 * Determine if an issue has been triaged. An issue is triaged if:
 * - It has a `priority` label OR
 * - It has a `type` label
 * - For `type: bug`, there must be a `priority` label
 * - For a P0 or P1 issue, it must have an asignee
 * - Pull requests don't count.
 * @param i Issue to analyze
 */
export function isTriaged(i: Issue) {
  if (isPullRequest(i)) {
    return true;
  }

  if (hasPriority(i)) {
    if (isP0(i) || isP1(i)) {
      return isAssigned(i);
    }
    return true;
  }

  if (hasType(i)) {
    if (isBug(i)) {
      return hasPriority(i);
    }
    return true;
  }

  return false;
}

/**
 * Check if there is a label that matches the given text.
 * @param issue Issue to analyze
 * @param label Label text to look for
 */
export function hasLabel(issue: Issue, label: string) {
  return issue.labels.filter(x => x.name.toLowerCase().indexOf(label) > -1)
             .length > 0;
}<commit_msg>fix: treat `status: investigating` as triaged (#36)<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {getIssues} from './issue';
import {Issue, IssueResult, LanguageResult, RepoResult} from './types';
import {languages} from './util';
import Table = require('cli-table');
import * as meow from 'meow';

function getRepoResults(repos: IssueResult[]) {
  const results = new Array<RepoResult>();
  const totals = {total: 0, p0: 0, p1: 0, p2: 0, pX: 0, outOfSLO: 0};
  repos.forEach(repo => {
    const counts = {
      total: 0,
      p0: 0,
      p1: 0,
      p2: 0,
      pX: 0,
      outOfSLO: 0,
      repo: repo.repo.repo,
      language: repo.repo.language
    };
    repo.issues.forEach(i => {
      if (isPullRequest(i)) {
        return;
      }
      counts.total++;
      totals.total++;

      if (isP0(i)) {
        counts.p0++;
        totals.p0++;
      } else if (isP1(i)) {
        counts.p1++;
        totals.p1++;
      } else if (isP2(i)) {
        counts.p2++;
        totals.p2++;
      }

      if (!isTriaged(i)) {
        counts.pX++;
        totals.pX++;
      }

      if (isOutOfSLO(i)) {
        counts.outOfSLO++;
        totals.outOfSLO++;
      }
    });
    results.push(counts);
  });
  return {repos: results, totals};
}

function getLanguageResults(repos: IssueResult[], api?: string) {
  const results = new Map<string, LanguageResult>();
  const issues = new Array<Issue>();
  repos.forEach(r => {
    r.issues.forEach(i => {
      i.language = r.repo.language;
      if (isPullRequest(i)) {
        return;
      }
      if (api && !isApi(i, api)) {
        return;
      }
      issues.push(i);
    });
  });
  languages.forEach(l => {
    results.set(
        l, {total: 0, p0: 0, p1: 0, p2: 0, pX: 0, outOfSLO: 0, language: l});
  });
  issues.forEach(i => {
    const counts = results.get(i.language)!;
    counts.total++;
    if (isP0(i)) {
      counts.p0++;
    } else if (isP1(i)) {
      counts.p1++;
    } else if (isP2(i)) {
      counts.p2++;
    }

    if (!isTriaged(i)) {
      counts.pX++;
    }

    if (isOutOfSLO(i)) {
      counts.outOfSLO++;
    }
  });
  return results;
}

/**
 * Determine if an issue has a `priority: ` label.
 * @param i Issue to analyze
 */
function hasPriority(i: Issue) {
  return hasLabel(i, 'priority: ');
}

/**
 * Determine if an issue has a `type: ` label.
 * @param i Issue to analyze
 */
function hasType(i: Issue) {
  return hasLabel(i, 'type: ');
}

/**
 * Determine if an issue has a `type: bug` label.
 * @param i Issue to analyze
 */
function isBug(i: Issue) {
  return hasLabel(i, 'type: bug');
}

function isP0(i: Issue) {
  return hasLabel(i, 'priority: p0');
}

function isP1(i: Issue) {
  return hasLabel(i, 'priority: p1');
}

function isP2(i: Issue) {
  return hasLabel(i, 'priority: p2');
}

function isAssigned(i: Issue) {
  return (i.assignee && i.assignee.length > 0) || i.assignees.length > 0;
}

export function isPullRequest(i: Issue) {
  return !!i.pull_request;
}

export function isApi(i: Issue, api: string) {
  for (const label of i.labels) {
    if (label.name.toLowerCase() === `api: ${api.toLowerCase()}`) {
      return true;
    }
  }
  // In node.js, we have separate repos for each API. We aren't looking for
  // a label, we're looking for a repo name.
  if (i.repo.indexOf('nodejs-') > -1) {
    const label = i.repo.split('-')[1];
    if (api.toLowerCase() === label.toLowerCase()) {
      return true;
    }
  }
  return false;
}

/**
 * Determine if an issue has been triaged. An issue is triaged if:
 * - It has a `priority` label OR
 * - It has a `type` label
 * - For `type: bug`, there must be a `priority` label
 * - For a P0 or P1 issue, it must have an asignee
 * - Pull requests don't count.
 * @param i Issue to analyze
 */
export function isTriaged(i: Issue) {
  if (isPullRequest(i)) {
    return true;
  }

  if (hasPriority(i)) {
    if (isP0(i) || isP1(i)) {
      return isAssigned(i);
    }
    return true;
  }

  if (hasType(i)) {
    if (isBug(i)) {
      return hasPriority(i);
    }
    return true;
  }

  if (hasLabel(i, 'status: investigating')) {
    return true;
  }

  return false;
}

/**
 * Check if there is a label that matches the given text.
 * @param issue Issue to analyze
 * @param label Label text to look for
 */
export function hasLabel(issue: Issue, label: string) {
  return issue.labels.filter(x => x.name.toLowerCase().indexOf(label) > -1)
             .length > 0;
}
{'fraction_non_alphanumeric': 0.15439093484419264, 'fraction_numerical': 0.013557264265479563, 'mean_word_length': 2.550646551724138, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 33, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, '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': '3332915', 'n_tokens_mistral': 3512, 'n_tokens_neox': 3438, 'n_words': 1026}