<commit_before>import _ from 'pluralize'
import { normalizeScore, normalizeReason, regex } from './helpers'

// Main rule wrapper with properties normalization
function rule (props) {
  props.score = normalizeScore(props.score)
  props.reason = normalizeReason(props.reason, props.count)
  return props
}

export function reuseTCPconnections ({ page, entries }) {
  const validReqs = entries.filter(entry =>
    entry.isValid && !entry.isRedirect
  )
  const values = validReqs.filter(entry =>
    !(entry.resHeaders.connection !== 'close')
  )
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'Persistent connections allow multiple HTTP requests use the same TCP connection, thus eliminates TCP handshakes and slow-start latency overhead. Leverage persistent connections whenever possible.',
    reason: `There ${_('is', count)} ${count} immediately terminated ${_('connection', count)}`,
    score: score,
    title: 'Reuse TCP connections',
    type: 'general',
    values: values.map(entry => entry.url.href),
    weight: 8
  })
}
export function cacheAssets ({ page, entries }) {
  const validReqs = entries.filter(entry =>
    entry.isValid && !entry.isRedirect
  )
  const values = validReqs.filter(({ isValid, isRedirect, resHeaders, url }) =>
    !resHeaders['cache-control'] && !resHeaders['expires']
  )
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'Reduce the load time of your page by storing commonly used files on your visitors browser.',
    reason: `There ${_('is', count)} ${_('resource', count, true)} without cache expiration time`,
    score: score,
    title: 'Cache resources on the client',
    type: 'general',
    values: values.map(val => val.url.href),
    weight: 8
  })
}

export function useCacheValidators ({ page, entries }) {
  const validReqs = entries.filter(entry =>
    entry.isValid && !entry.isRedirect
  )
  const values = validReqs.filter(({ resHeaders, url }) =>
    !resHeaders['last-modified'] && !resHeaders['etag']
  )
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'Specify the Last-Modified or Etag header to allow the client to check if the expired resource has been updated, if not data transfer can be omitted.',
    reason: `There ${_('is', count)} ${_('resource', count, true)} without Last-Modified or Etag header`,
    score: score,
    title: 'Specify cache validation mechanisms',
    type: 'general',
    values: values.map(val => val.url.href),
    weight: 5
  })
}

export function compressAssets ({ page, entries, ...opts }) {
  const { minSize = 256 } = opts
  const validReqs = entries.filter(entry =>
    entry.isValid && !entry.isRedirect
  )
  const values = validReqs.filter((entry) => {
    const headers = entry.resHeaders
    return (
      entry.content.size >= minSize &&
      regex.text.test(entry.content.mimeType) &&
      !regex.encoding.test(headers['content-encoding'])
    )
  })
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'Application resources should be transferred with the minimum number of bytes. Always apply the best compression method for each transferred asset.',
    reason: `There ${_('is', count)} ${_('resource', count, true)} without compression`,
    score: score,
    title: 'Compress resources during transfer',
    type: 'general',
    values: values.map(entry => entry.url.href),
    weight: 7
  })
}

export function reduceRedirects ({ page, entries, ...opts }) {
  const { penalty = 25 } = opts
  const values = entries.filter(entry => entry.isRedirect)
  const internalRedirects = values.filter(entry =>
      entry.status === 307 &&
      entry.statusText === 'Internal Redirect' &&
      entry.resHeaders['non-authoritative-reason']
  )
  const count = values.length
  const subCount = count - internalRedirects.length
  return rule({
    count: count,
    description: 'HTTP redirects impose high latency overhead. The optimal number of redirects is zero.',
    reason: `There ${_('is', values.length)} ${_('redirect', values.length, true)}`,
    score: 100 - (penalty * subCount),
    title: 'Minimize number of HTTP redirects',
    type: 'general',
    values: values.map((entry) =>
      `(${entry.status} ${entry.statusText || 'Redirect'}) ${entry.url.href} -> ${entry.redirectUrl || '-'}`
    ),
    weight: 7
  })
}

export function reduceDNSlookups ({ page, ...opts }) {
  const { limit = 4, penalty = 5 } = opts
  const { dns, dnsLookups } = page
  let score = 100
  if (dnsLookups > limit) {
    score -= penalty * (dnsLookups - limit)
  }
  return rule({
    count: dnsLookups,
    description: 'Making requests to a large number of different hosts can hurt performance.',
    score: score,
    title: 'Reduce DNS lookups',
    type: 'general',
    values: Object.keys(dns).map(key => `${key} (${dns[key]})`),
    weight: 4
  })
}

export function eliminateBrokenRequests ({ entries, ...opts }) {
  const { penalty = 10 } = opts
  const values = entries.filter(entry => entry.status >= 400)
  const count = values.length
  const score = 100 - (count * penalty)
  return rule({
    count: count,
    description: 'Avoid fetching content that does not exist.',
    reason: `There ${_('is', count)} ${_('resource', count, true)} that not exists`,
    score: score,
    title: 'Eliminate requests to non-existent or broken resources',
    type: 'general',
    values: values.map(entry => `(${entry.status}) ${entry.url.href}`),
    weight: 2
  })
}

export function useHttp2 ({ entries }) {
  const validReqs = entries.filter(entry => entry.isValid && !entry.isRedirect)
  const values = validReqs.filter(entry => !entry.isHttp2)
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'HTTP/2 enables more efficient use of network resources and reduced latency by enabling request and response multiplexing, header compression, prioritization, and more.',<commit_msg>Reduce weight of "eliminateBrokenRequests" rule<commit_after>import _ from 'pluralize'
import { normalizeScore, normalizeReason, regex } from './helpers'

// Main rule wrapper with properties normalization
function rule (props) {
  props.score = normalizeScore(props.score)
  props.reason = normalizeReason(props.reason, props.count)
  return props
}

export function reuseTCPconnections ({ page, entries }) {
  const validReqs = entries.filter(entry =>
    entry.isValid && !entry.isRedirect
  )
  const values = validReqs.filter(entry =>
    !(entry.resHeaders.connection !== 'close')
  )
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'Persistent connections allow multiple HTTP requests use the same TCP connection, thus eliminates TCP handshakes and slow-start latency overhead. Leverage persistent connections whenever possible.',
    reason: `There ${_('is', count)} ${count} immediately terminated ${_('connection', count)}`,
    score: score,
    title: 'Reuse TCP connections',
    type: 'general',
    values: values.map(entry => entry.url.href),
    weight: 8
  })
}
export function cacheAssets ({ page, entries }) {
  const validReqs = entries.filter(entry =>
    entry.isValid && !entry.isRedirect
  )
  const values = validReqs.filter(({ isValid, isRedirect, resHeaders, url }) =>
    !resHeaders['cache-control'] && !resHeaders['expires']
  )
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'Reduce the load time of your page by storing commonly used files on your visitors browser.',
    reason: `There ${_('is', count)} ${_('resource', count, true)} without cache expiration time`,
    score: score,
    title: 'Cache resources on the client',
    type: 'general',
    values: values.map(val => val.url.href),
    weight: 8
  })
}

export function useCacheValidators ({ page, entries }) {
  const validReqs = entries.filter(entry =>
    entry.isValid && !entry.isRedirect
  )
  const values = validReqs.filter(({ resHeaders, url }) =>
    !resHeaders['last-modified'] && !resHeaders['etag']
  )
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'Specify the Last-Modified or Etag header to allow the client to check if the expired resource has been updated, if not data transfer can be omitted.',
    reason: `There ${_('is', count)} ${_('resource', count, true)} without Last-Modified or Etag header`,
    score: score,
    title: 'Specify cache validation mechanisms',
    type: 'general',
    values: values.map(val => val.url.href),
    weight: 5
  })
}

export function compressAssets ({ page, entries, ...opts }) {
  const { minSize = 256 } = opts
  const validReqs = entries.filter(entry =>
    entry.isValid && !entry.isRedirect
  )
  const values = validReqs.filter((entry) => {
    const headers = entry.resHeaders
    return (
      entry.content.size >= minSize &&
      regex.text.test(entry.content.mimeType) &&
      !regex.encoding.test(headers['content-encoding'])
    )
  })
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'Application resources should be transferred with the minimum number of bytes. Always apply the best compression method for each transferred asset.',
    reason: `There ${_('is', count)} ${_('resource', count, true)} without compression`,
    score: score,
    title: 'Compress resources during transfer',
    type: 'general',
    values: values.map(entry => entry.url.href),
    weight: 7
  })
}

export function reduceRedirects ({ page, entries, ...opts }) {
  const { penalty = 25 } = opts
  const values = entries.filter(entry => entry.isRedirect)
  const internalRedirects = values.filter(entry =>
      entry.status === 307 &&
      entry.statusText === 'Internal Redirect' &&
      entry.resHeaders['non-authoritative-reason']
  )
  const count = values.length
  const subCount = count - internalRedirects.length
  return rule({
    count: count,
    description: 'HTTP redirects impose high latency overhead. The optimal number of redirects is zero.',
    reason: `There ${_('is', values.length)} ${_('redirect', values.length, true)}`,
    score: 100 - (penalty * subCount),
    title: 'Minimize number of HTTP redirects',
    type: 'general',
    values: values.map((entry) =>
      `(${entry.status} ${entry.statusText || 'Redirect'}) ${entry.url.href} -> ${entry.redirectUrl || '-'}`
    ),
    weight: 7
  })
}

export function reduceDNSlookups ({ page, ...opts }) {
  const { limit = 4, penalty = 5 } = opts
  const { dns, dnsLookups } = page
  let score = 100
  if (dnsLookups > limit) {
    score -= penalty * (dnsLookups - limit)
  }
  return rule({
    count: dnsLookups,
    description: 'Making requests to a large number of different hosts can hurt performance.',
    score: score,
    title: 'Reduce DNS lookups',
    type: 'general',
    values: Object.keys(dns).map(key => `${key} (${dns[key]})`),
    weight: 4
  })
}

export function eliminateBrokenRequests ({ entries, ...opts }) {
  const { penalty = 10 } = opts
  const values = entries.filter(entry => entry.status >= 400)
  const count = values.length
  const score = 100 - (count * penalty)
  return rule({
    count: count,
    description: 'Avoid fetching content that does not exist.',
    reason: `There ${_('is', count)} ${_('resource', count, true)} that not exists`,
    score: score,
    title: 'Eliminate requests to non-existent or broken resources',
    type: 'general',
    values: values.map(entry => `(${entry.status}) ${entry.url.href}`),
    weight: 1
  })
}

export function useHttp2 ({ entries }) {
  const validReqs = entries.filter(entry => entry.isValid && !entry.isRedirect)
  const values = validReqs.filter(entry => !entry.isHttp2)
  const count = values.length
  const score = 100 - Math.round(100 * (count / validReqs.length))
  return rule({
    count: count,
    description: 'HTTP/2 enables more efficient use of network resources and reduced latency by enabling request and response multiplexing, header compression, prioritization, and more.',
{'fraction_non_alphanumeric': 0.13419088454819755, 'fraction_numerical': 0.010163569953946324, 'mean_word_length': 3.6458871265215786, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 51, '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': '1971115', 'n_tokens_mistral': 3761, 'n_tokens_neox': 3619, 'n_words': 1173}