<commit_before>'use strict'

var miss = require('mississippi')
var getMetadata = require('tfk-arkiv-metadatagenerator')
var p360 = require('p360')
var config = require('../config')

var addContact = miss.through(function (chunck, encoding, callback) {
  var item = JSON.parse(chunck)

  console.log(item._id + ': add-private-person')

  var i = 0
  item.contacts.forEach(function (contact) {
    console.log(item._id + ': add-private-person: ' + contact.fullName)

    // If contact exist skip step
    //if (contact.exists === true) {
    //  console.log(item._id + ': add-private-person: ' + contact.fullName + ': Did not update private person')
    //  i++
    //  if (item.contacts.length === i) {
    //    return callback(null, JSON.stringify(item))
    //  }
    //  return
    //}

    var addPrivatePerson = {
      generator: 'add-private-person',
      firstName: contact.firstName,
      middleName: contact.middleName,
      lastName: contact.lastName,
      personalIdNumber: contact.personalIdNumber,
      email: contact.email,
      phone: contact.phone,
      streetAddress: contact.address,
      zipCode: contact.zip,
      zipPlace: contact.city,
      area: 'Telemark'
    }

    var options = getMetadata(addPrivatePerson)
    options.p360 = config.p360

    p360(options, function (err, data) {
      if (err) {
        console.error(JSON.stringify(err))
        return callback(err)
      } else {
        i++
        console.log(item._id + ': add-private-person: ' + contact.fullName + ': Updated or created private person')
        if (item.contacts.length === i) {
          return callback(null, JSON.stringify(item))
        }
      }
    })
  })
})

module.exports = addContact
<commit_msg>Fixed standard style<commit_after>'use strict'

var miss = require('mississippi')
var getMetadata = require('tfk-arkiv-metadatagenerator')
var p360 = require('p360')
var config = require('../config')

var addContact = miss.through(function (chunck, encoding, callback) {
  var item = JSON.parse(chunck)

  console.log(item._id + ': add-private-person')

  var i = 0
  item.contacts.forEach(function (contact) {
    console.log(item._id + ': add-private-person: ' + contact.fullName)

    // If contact exist skip step
    // if (contact.exists === true) {
    //  console.log(item._id + ': add-private-person: ' + contact.fullName + ': Did not update private person')
    //  i++
    //  if (item.contacts.length === i) {
    //    return callback(null, JSON.stringify(item))
    //  }
    //  return
    // }

    var addPrivatePerson = {
      generator: 'add-private-person',
      firstName: contact.firstName,
      middleName: contact.middleName,
      lastName: contact.lastName,
      personalIdNumber: contact.personalIdNumber,
      email: contact.email,
      phone: contact.phone,
      streetAddress: contact.address,
      zipCode: contact.zip,
      zipPlace: contact.city,
      area: 'Telemark'
    }

    var options = getMetadata(addPrivatePerson)
    options.p360 = config.p360

    p360(options, function (err, data) {
      if (err) {
        console.error(JSON.stringify(err))
        return callback(err)
      } else {
        i++
        console.log(item._id + ': add-private-person: ' + contact.fullName + ': Updated or created private person')
        if (item.contacts.length === i) {
          return callback(null, JSON.stringify(item))
        }
      }
    })
  })
})

module.exports = addContact
<|endoftext|>


<commit_before>
/**
 * Specify which app this should run; either 'topics' or 'sources'.
 */
export const APP_NAME = 'topics';

/**
 * Specify which app this should run; either 'dev' or 'prod'.
 */
export const APP_MODE = 'prod';

/**
 * Specify a version number
 */
export const VERSION = '0.4.1';
<commit_msg>switch back to dev mode<commit_after>
/**
 * Specify which app this should run; either 'topics' or 'sources'.
 */
export const APP_NAME = 'topics';

/**
 * Specify which app this should run; either 'dev' or 'prod'.
 */
export const APP_MODE = 'dev';

/**
 * Specify a version number
 */
export const VERSION = '0.4.1';
<|endoftext|>


<commit_before>/**
 * Config
 *
 * Loads config for `rnpm` to use by projects.
 *
 * In order to override default settings, simply mirror them under `rnpm` key in your
 * package.json.
 *
 * In order to make `rnpm` ignore certain targets, simply set them to `false`. Otherwise,
 * there will be warnings.
 *
 * It optionally accepts packageName - when it's present, config will be loaded from node_modules/packageName
 */

const fs = require('fs');
const path = require('path');
const glob = require('glob');

const androidConfig = require('./android/config');
const iosConfig = require('./ios/config');

const getAssetsInFolder = (folder) => {
  return glob.sync(path.join(folder, '**'), {
    nodir: true,
  });
};

/**
 * Gets rnpm config from reading it from JSON (for now)
 */
const getRNPMConfig = function getRNPMConfig(folder) {
  const pjsonPath = path.join(folder, './package.json');

  if (!fs.existsSync(pjsonPath)) {
    return null;
  }

  const pjson = require(pjsonPath);

  return pjson.rnpm || {};
};

/**
 * Returns project config for current working directory
 */
exports.getProjectConfig = function getProjectConfig() {
  const folder = process.cwd();
  const rnpm = getRNPMConfig(folder);

  if (!rnpm) {
    return null;
  }

  return Object.assign({}, rnpm, {
    ios: iosConfig.projectConfig(folder, rnpm.ios || {}),
    android: androidConfig.projectConfig(folder, rnpm.android || {}),
  });
};

/**
 * Returns dependency config for a dependency located under node_modules/<package_name>
 */
exports.getDependencyConfig = function getDependencyConfig(packageName) {
  const folder = path.join(process.cwd(), 'node_modules', packageName);
  const rnpm = getRNPMConfig(folder);

  if (!rnpm) {
    return null;
  }

  return Object.assign({}, rnpm, {
    ios: iosConfig.dependencyConfig(folder, rnpm.ios || {}),
    android: androidConfig.dependencyConfig(folder, rnpm.android || {}),
    assets: (rnpm.assets || [])
      .map(assetsFolder => path.join(folder, assetsFolder))
      .reduce((assets, assetsFolder) => {
        return assets.concat(getAssetsInFolder(assetsFolder));
      }, []),
  });
};
<commit_msg>Theres no ignore option<commit_after>/**
 * Config
 *
 * Loads config for `rnpm` to use by projects.
 *
 * In order to override default settings, simply mirror them under `rnpm` key in your
 * package.json.
 *
 * It optionally accepts packageName - when it's present, config will be loaded from node_modules/packageName
 */

const fs = require('fs');
const path = require('path');
const glob = require('glob');

const androidConfig = require('./android/config');
const iosConfig = require('./ios/config');

const getAssetsInFolder = (folder) => {
  return glob.sync(path.join(folder, '**'), {
    nodir: true,
  });
};

/**
 * Gets rnpm config from reading it from JSON (for now)
 */
const getRNPMConfig = function getRNPMConfig(folder) {
  const pjsonPath = path.join(folder, './package.json');

  if (!fs.existsSync(pjsonPath)) {
    return null;
  }

  const pjson = require(pjsonPath);

  return pjson.rnpm || {};
};

/**
 * Returns project config for current working directory
 */
exports.getProjectConfig = function getProjectConfig() {
  const folder = process.cwd();
  const rnpm = getRNPMConfig(folder);

  if (!rnpm) {
    return null;
  }

  return Object.assign({}, rnpm, {
    ios: iosConfig.projectConfig(folder, rnpm.ios || {}),
    android: androidConfig.projectConfig(folder, rnpm.android || {}),
  });
};

/**
 * Returns dependency config for a dependency located under node_modules/<package_name>
 */
exports.getDependencyConfig = function getDependencyConfig(packageName) {
  const folder = path.join(process.cwd(), 'node_modules', packageName);
  const rnpm = getRNPMConfig(folder);

  if (!rnpm) {
    return null;
  }

  return Object.assign({}, rnpm, {
    ios: iosConfig.dependencyConfig(folder, rnpm.ios || {}),
    android: androidConfig.dependencyConfig(folder, rnpm.android || {}),
    assets: (rnpm.assets || [])
      .map(assetsFolder => path.join(folder, assetsFolder))
      .reduce((assets, assetsFolder) => {
        return assets.concat(getAssetsInFolder(assetsFolder));
      }, []),
  });
};
<|endoftext|>


<commit_before>import React from 'react'
import styled, { css } from 'styled-components'
import {
  Box,
  Text,
  Sheet,
  Container,
  Link as A,
  LargeButton
} from '@hackclub/design-system'
import { Link } from 'gatsby'
import { Headline, Featline, Lead } from 'components/Content'
import { Section, SectionTitle, Cols, theme } from './style'
import range from 'lodash/range'
import includes from 'lodash/includes'

const cta = {
  chevronRight: true,
  scale: true,
  fontSize: [3, 4]
}
const CTA = styled(LargeButton.withComponent(Link)).attrs(cta)`
  background-image: ${theme.gradient(
    theme.colors.yellow,
    theme.colors.primary
  )};
`

const Calendar = styled.div`
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-row-gap: 4px;

  span {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3px;
  }
`

const CalDay = styled(Text.span).attrs({ color: 'smoke', bold: true })`
  line-height: 1;
  font-weight: ${theme.bold};
  user-select: none;

  &:nth-child(6),
  &:nth-child(7) {
    color: ${theme.colors.muted};
  }
`
const CalDate = styled(Text.span).attrs({ color: 'muted' })`
  line-height: 1.25;

  ${props =>
    props.active
      ? css`
          color: ${theme.colors.white};
          background-color: ${theme.colors.red};
        `
      : css`
          user-select: none;
        `}
  ${props =>
    props.first &&
    css`
      border-radius: ${theme.pill} 0 0 ${theme.pill};
      font-weight: ${theme.bold};
    `}
  ${props =>
    props.last &&
    css`
      border-radius: 0 ${theme.pill} ${theme.pill} 0;
    `}
`
const active = i => (i >= 1 && i <= 5) || (i >= 15 && i <= 19) || i >= 29
const first = i => includes([1, 15, 29], i)
const last = i => includes([5, 19], i)

export default () => [

    <Container maxWidth={61.25} px={3}>
      <SectionTitle>Registration</SectionTitle>
      <Cols cols="2fr 1fr" gap={[4, 5]}>

          <Headline color="white" mb={3}>
            3 sessions. Pick yours.
          </Headline>
          <Lead mb={4}>
            We’re running three identical weeks of Hack Camp. Join us July
            1–5th, 15–19th, or July 29th–August 2nd. Camp runs 9am–5pm
            (weekdays).
          </Lead>
          <CTA to="/camp/register">Register now</CTA>

        <Sheet bg={theme.colors.darkless}>
          <Text color="white" bold fontSize={3} mt={-1} mb={1}>
            July 2019
          </Text>
          <Calendar>
            {'M T W T F S S'.split(' ').map((i, n) => (
              <CalDay children={i} key={i + n} />
            ))}
            {range(1, 32).map(i => (
              <CalDate
                active={active(i)}
                first={first(i)}
                last={last(i)}
                children={i}
                key={i}
              />
            ))}
            {range(1, 5).map(i => (
              <CalDate
                active={i <= 2}
                last={i === 2}
                children={i}
                key={i + i}
              />
            ))}
          </Calendar>
        </Sheet>
      </Cols>
      <Cols mt={[5, 6]}>

          <Featline>Tuition is $500.</Featline>
          <Lead color="muted">
            Need-based financial aid is available for Camp—let us know in your
            registration.
          </Lead>

          <Featline>Lunch is included.</Featline>
          <Lead color="muted">I hope it’s tasty!</Lead>

          <Featline>I don’t know how to code!</Featline>
          <Lead color="muted">
            Perfect! Hack Camp was built with beginners in mind. You’ll be up to
            speed in no time.
          </Lead>

          <Featline>I already know how to code.</Featline>
          <Lead color="muted">
            There’s always more to learn—why not surround yourself with awesome
            makers and doers with similar interests?
          </Lead>

          <Featline>What do I need to bring?</Featline>
          <Lead color="muted">
            You should bring your laptop & a thirst for knowledge. Let us know
            if you don’t have a laptop and we’ll do our best to accomodate you.
          </Lead>

          <Featline>Have any questions?</Featline>
          <Lead color="muted">
            Please reach out! We can be reached anytime at{' '}

              summer@hackclub.com

            .
          </Lead>

      </Cols>
    </Container>

]
<commit_msg>Update FAQ<commit_after>import React from 'react'
import styled, { css } from 'styled-components'
import {
  Box,
  Text,
  Sheet,
  Container,
  Link as A,
  LargeButton
} from '@hackclub/design-system'
import { Link } from 'gatsby'
import { Headline, Featline, Lead } from 'components/Content'
import { Section, SectionTitle, Cols, theme } from './style'
import range from 'lodash/range'
import includes from 'lodash/includes'

const cta = {
  chevronRight: true,
  scale: true,
  fontSize: [3, 4]
}
const CTA = styled(LargeButton.withComponent(Link)).attrs(cta)`
  background-image: ${theme.gradient(
    theme.colors.yellow,
    theme.colors.primary
  )};
`

const Calendar = styled.div`
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-row-gap: 4px;

  span {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3px;
  }
`

const CalDay = styled(Text.span).attrs({ color: 'smoke', bold: true })`
  line-height: 1;
  font-weight: ${theme.bold};
  user-select: none;

  &:nth-child(6),
  &:nth-child(7) {
    color: ${theme.colors.muted};
  }
`
const CalDate = styled(Text.span).attrs({ color: 'muted' })`
  line-height: 1.25;

  ${props =>
    props.active
      ? css`
          color: ${theme.colors.white};
          background-color: ${theme.colors.red};
        `
      : css`
          user-select: none;
        `}
  ${props =>
    props.first &&
    css`
      border-radius: ${theme.pill} 0 0 ${theme.pill};
      font-weight: ${theme.bold};
    `}
  ${props =>
    props.last &&
    css`
      border-radius: 0 ${theme.pill} ${theme.pill} 0;
    `}
`
const active = i => (i >= 1 && i <= 5) || (i >= 15 && i <= 19) || i >= 29
const first = i => includes([1, 15, 29], i)
const last = i => includes([5, 19], i)

export default () => [

    <Container maxWidth={61.25} px={3}>
      <SectionTitle>Registration</SectionTitle>
      <Cols cols="2fr 1fr" gap={[4, 5]}>

          <Headline color="white" mb={3}>
            3 sessions. Pick yours.
          </Headline>
          <Lead mb={4}>
            We’re running three identical weeks of Hack Camp. Join us July
            1–5th, 15–19th, or July 29th–August 2nd. Camp runs 9am–5pm
            (weekdays).
          </Lead>
          <CTA to="/camp/register">Register now</CTA>

        <Sheet bg={theme.colors.darkless}>
          <Text color="white" bold fontSize={3} mt={-1} mb={1}>
            July 2019
          </Text>
          <Calendar>
            {'M T W T F S S'.split(' ').map((i, n) => (
              <CalDay children={i} key={i + n} />
            ))}
            {range(1, 32).map(i => (
              <CalDate
                active={active(i)}
                first={first(i)}
                last={last(i)}
                children={i}
                key={i}
              />
            ))}
            {range(1, 5).map(i => (
              <CalDate
                active={i <= 2}
                last={i === 2}
                children={i}
                key={i + i}
              />
            ))}
          </Calendar>
        </Sheet>
      </Cols>
      <Cols mt={[5, 6]}>

          <Featline>Tuition is $500.</Featline>
          <Lead color="muted">
            Need-based financial aid is available for Camp—let us know in your
            registration.
          </Lead>

          <Featline>What food is included?</Featline>
          <Lead color="muted">
            Lunch is! We’ll serve a healthy lunch & snacks every day at Camp.
          </Lead>

          <Featline>I know nothing about code!</Featline>
          <Lead color="muted">
            Perfect! You’ll be up to speed in no time. We made this with
            beginners in mind.
          </Lead>

          <Featline>What if I can already code?</Featline>
          <Lead color="muted">
            We will cover lots of stuff you don’t know yet—I guarantee it!
          </Lead>

          <Featline>What do I need to bring?</Featline>
          <Lead color="muted">
            A laptop and an open mind. We can help with the laptop. The mind
            thing is on you.
          </Lead>

          <Featline>Have any questions?</Featline>
          <Lead color="muted">
            Please reach out! We can be reached anytime at{' '}

              summer@hackclub.com

            .
          </Lead>

      </Cols>
    </Container>

]
<|endoftext|>


<commit_before>export const FILTERS_KEY = 'filters';

const filters = [
  {
    id: 'noPayment',
    label: 'Free',
  },
  {
    id: 'babyChange',
    label: 'Baby Changing',
  },
  {
    id: 'accessible',
    label: 'Accessible',
  },
  {
    id: 'allGender',
    label: 'Gender Neutral',
  },
  {
    id: 'radar',
    label: 'Radar Key',
  },
  {
    id: 'automatic',
    label: 'Automatic',
  },
];

const messages = {
  created: 'Thank you, toilet added!',
  updated: 'Thank you, details updated!',
  removed: 'Thank you, toilet removed!',
};

const title = 'The Great British Toilet Map';

export default {
  viewport: {
    mobile: 567,
  },
  filters,
  messages,
  analyticsId:
    process.env.NODE_ENV === 'production' ? 'UA-52513593-1' : 'UA-111111111-1',
  initialZoom: 16,
  minZoom: 12,
  maxZoom: 18,
  editMinZoom: 16,
  fallbackLocation: {
    // Trafalgar Square. Because.
    lat: 51.507351,
    lng: -0.127758,
  },
  getSettings(namespace) {
    return JSON.parse(localStorage.getItem(namespace) || '{}');
  },
  getSetting(namespace, key, defaultVal) {
    const val = this.getSettings(namespace)[key];

    return val === undefined ? defaultVal : val;
  },
  setSetting(namespace, key, val) {
    var settings = this.getSettings(namespace);
    settings[key] = val;
    localStorage.setItem(namespace, JSON.stringify(settings));
  },
  setSettings(namespace, obj = {}) {
    localStorage.setItem(
      namespace,
      JSON.stringify({
        ...this.getSettings(namespace),
        ...obj,
      })
    );
  },
  getTitle(appendText) {
    if (appendText) {
      return `${title}: ${appendText}`;
    }

    return title;
  },
};
<commit_msg>fix: decrease minZoom<commit_after>export const FILTERS_KEY = 'filters';

const filters = [
  {
    id: 'noPayment',
    label: 'Free',
  },
  {
    id: 'babyChange',
    label: 'Baby Changing',
  },
  {
    id: 'accessible',
    label: 'Accessible',
  },
  {
    id: 'allGender',
    label: 'Gender Neutral',
  },
  {
    id: 'radar',
    label: 'Radar Key',
  },
  {
    id: 'automatic',
    label: 'Automatic',
  },
];

const messages = {
  created: 'Thank you, toilet added!',
  updated: 'Thank you, details updated!',
  removed: 'Thank you, toilet removed!',
};

const title = 'The Great British Toilet Map';

export default {
  viewport: {
    mobile: 567,
  },
  filters,
  messages,
  analyticsId:
    process.env.NODE_ENV === 'production' ? 'UA-52513593-1' : 'UA-111111111-1',
  initialZoom: 16,
  minZoom: 11,
  maxZoom: 18,
  editMinZoom: 16,
  fallbackLocation: {
    // Trafalgar Square. Because.
    lat: 51.507351,
    lng: -0.127758,
  },
  getSettings(namespace) {
    return JSON.parse(localStorage.getItem(namespace) || '{}');
  },
  getSetting(namespace, key, defaultVal) {
    const val = this.getSettings(namespace)[key];

    return val === undefined ? defaultVal : val;
  },
  setSetting(namespace, key, val) {
    var settings = this.getSettings(namespace);
    settings[key] = val;
    localStorage.setItem(namespace, JSON.stringify(settings));
  },
  setSettings(namespace, obj = {}) {
    localStorage.setItem(
      namespace,
      JSON.stringify({
        ...this.getSettings(namespace),
        ...obj,
      })
    );
  },
  getTitle(appendText) {
    if (appendText) {
      return `${title}: ${appendText}`;
    }

    return title;
  },
};
<|endoftext|>


<commit_before>require('babel-polyfill')

const environment = {
  development: {
    isProduction: false,
    wsFullUrl: 'ws://localhost:3030'
  },
  production: {
    isProduction: true,
    wsFullUrl: 'wss://api.portalen.t-fk.no'
  }
}[process.env.NODE_ENV || 'development']

module.exports = Object.assign({
  jwtSecret: process.env.JWT_SECRET || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
  piwikURL: process.env.PIWIK_URL || 'https://piwik.service.t-fk.no',
  piwikSiteID: process.env.PIWIK_SITE_ID || 1,
  host: process.env.HOST || 'localhost',
  port: process.env.PORT || 3000,
  publicUrl: process.env.PUBLIC_URL || 'http://localhost:3000',
  apiHost: process.env.APIHOST || 'localhost',
  apiPort: process.env.APIPORT || 3030,
  originUrl: process.env.ORIGIN_URL || 'http://localhost:3000/authstatus',
  authServiceUrl: process.env.AUTH_SERVICE_URL || 'https://sso.router.t-fk.win',
  databaseUri: process.env.DATABASE_URI || 'mongodb://localhost:27017/tfk_portalen',
  sessionSecret: process.env.SESSION_SECRET || 'the-password-must-be-at-least-32-characters-long',
  sessionTimeoutDays: process.env.SESSION_TIMEOUT || 7,
  sessionStorageUrl: process.env.SESSION_STORAGE_URL || 'https://tmp.storage.micro.t-fk.no',
  tokenSecret: process.env.TOKEN_SECRET || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
  encryptorSecret: process.env.ENCRYPTOR_SECRET || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
  wsProtocol: process.env.WSPROTOCOL || 'ws',
  tasks: {
    key: process.env.PORTALEN_TASKS_JWT_KEY || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
    url: process.env.PORTALEN_TASKS_SERVICE_URL || 'https://tasks.portalen.no'
  },
  apiTimeout: 10000,
  api: {
    links: process.env.API_LINKS || '/api/links?roles={rolesJoined}',
    userRoles: process.env.API_ROLES_USER || '/api/roles/map?company={company}',
    roles: process.env.API_ROLES || '/api/roles/list',
    shortcuts: process.env.API_SHORTCUTS || '/api/shortcuts?roles={rolesJoined}',
    tasks: process.env.API_TASKS || null,
    content: process.env.API_CONTENT || '/api/content/{userId}?roles={rolesJoined}',
    search: process.env.API_SEARCH || 'https://search.portalen.t-fk.no/api/search',
    jwtSecret: process.env.API_JWT_SECRET || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
    defaults: {
      company: process.env.DEFAULTS_COMPANY || 'Sentraladministrasjonen',
      mail: process.env.DEFAULTS_MAIL || 'post@tfk.no',
      roles: ['alle', 'administrasjonen', 'sentraladministrasjonen']
    }
  },
  feedback: {
    url: process.env.FEEDBACK_URL || 'https://api.github.com/repos/telemark/portalen-forside/issues',
    token: process.env.FEEDBACK_TOKEN || 'github token'
  },
  app: {
    title: 'Forsiden',
    description: 'Din start på arbeidsdagen',
    head: {
      titleTemplate: 'Forsiden: %s',
      meta: [
        {name: 'description', content: 'Din start på arbeidsdagen'},
        {charset: 'utf-8'},
        {property: 'og:site_name', content: 'Forsiden'},
        {property: 'og:image', content: ''},
        {property: 'og:locale', content: 'nb_NO'},
        {property: 'og:title', content: 'Portalen'},
        {property: 'og:description', content: 'Din start på arbeidsdagen'},
        {property: 'og:card', content: 'summary'},
        {property: 'og:site', content: '@telemark'},
        {property: 'og:creator', content: '@telemark'},
        {property: 'og:image:width', content: '200'},
        {property: 'og:image:height', content: '200'}
      ]
    }
  }
}, environment)
<commit_msg>Changes default<commit_after>require('babel-polyfill')

const environment = {
  development: {
    isProduction: false,
    wsFullUrl: 'ws://localhost:3030'
  },
  production: {
    isProduction: true,
    wsFullUrl: 'wss://api.portalen.t-fk.no'
  }
}[process.env.NODE_ENV || 'development']

module.exports = Object.assign({
  jwtSecret: process.env.JWT_SECRET || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
  piwikURL: process.env.PIWIK_URL || 'https://piwik.service.t-fk.no',
  piwikSiteID: process.env.PIWIK_SITE_ID || 1,
  host: process.env.HOST || 'localhost',
  port: process.env.PORT || 3000,
  publicUrl: process.env.PUBLIC_URL || 'http://localhost:3000',
  apiHost: process.env.APIHOST || 'localhost',
  apiPort: process.env.APIPORT || 3030,
  originUrl: process.env.ORIGIN_URL || 'http://localhost:3000/authstatus',
  authServiceUrl: process.env.AUTH_SERVICE_URL || 'https://auth.demo.t-fk.win/login',
  databaseUri: process.env.DATABASE_URI || 'mongodb://localhost:27017/tfk_portalen',
  sessionSecret: process.env.SESSION_SECRET || 'the-password-must-be-at-least-32-characters-long',
  sessionTimeoutDays: process.env.SESSION_TIMEOUT || 7,
  sessionStorageUrl: process.env.SESSION_STORAGE_URL || 'https://tmp.storage.micro.t-fk.no',
  tokenSecret: process.env.TOKEN_SECRET || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
  encryptorSecret: process.env.ENCRYPTOR_SECRET || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
  wsProtocol: process.env.WSPROTOCOL || 'ws',
  tasks: {
    key: process.env.PORTALEN_TASKS_JWT_KEY || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
    url: process.env.PORTALEN_TASKS_SERVICE_URL || 'https://tasks.portalen.no'
  },
  apiTimeout: 10000,
  api: {
    links: process.env.API_LINKS || '/api/links?roles={rolesJoined}',
    userRoles: process.env.API_ROLES_USER || '/api/roles/map?company={company}',
    roles: process.env.API_ROLES || '/api/roles/list',
    shortcuts: process.env.API_SHORTCUTS || '/api/shortcuts?roles={rolesJoined}',
    tasks: process.env.API_TASKS || null,
    content: process.env.API_CONTENT || '/api/content/{userId}?roles={rolesJoined}',
    search: process.env.API_SEARCH || 'https://search.portalen.t-fk.no/api/search',
    jwtSecret: process.env.API_JWT_SECRET || 'Louie Louie, oh no, I got to go Louie Louie, oh no, I got to go',
    defaults: {
      company: process.env.DEFAULTS_COMPANY || 'Sentraladministrasjonen',
      mail: process.env.DEFAULTS_MAIL || 'post@tfk.no',
      roles: ['alle', 'administrasjonen', 'sentraladministrasjonen']
    }
  },
  feedback: {
    url: process.env.FEEDBACK_URL || 'https://api.github.com/repos/telemark/portalen-forside/issues',
    token: process.env.FEEDBACK_TOKEN || 'github token'
  },
  app: {
    title: 'Forsiden',
    description: 'Din start på arbeidsdagen',
    head: {
      titleTemplate: 'Forsiden: %s',
      meta: [
        {name: 'description', content: 'Din start på arbeidsdagen'},
        {charset: 'utf-8'},
        {property: 'og:site_name', content: 'Forsiden'},
        {property: 'og:image', content: ''},
        {property: 'og:locale', content: 'nb_NO'},
        {property: 'og:title', content: 'Portalen'},
        {property: 'og:description', content: 'Din start på arbeidsdagen'},
        {property: 'og:card', content: 'summary'},
        {property: 'og:site', content: '@telemark'},
        {property: 'og:creator', content: '@telemark'},
        {property: 'og:image:width', content: '200'},
        {property: 'og:image:height', content: '200'}
      ]
    }
  }
}, environment)
<|endoftext|>


<commit_before>define([
    './view-mvvm',
    './view-window',
    './view-attr',
    './view-action',
    './view-children',
    './view-listen',
    './view-render',
    './view-resize',
    './view-trigger'
], function (mvvm, subwindow, attr, action, children, listen, render, resize, trigger) {

    return function (app) {
        var $ = app.core.$;
        var _ = app.core._;
        var noop = $.noop;

        /**
         * 选项
         * @typedef ViewOptions
         * @property {boolean} [autoAction=false] - 自动绑定Action事件
         *   当在模板中使用如下写法时
         *   ```html
         *   <button data-action="add">添加</button>
         *   ```
         *   如果该属性为 `true` 将自动查找该视图的 `addHandler` 方法作为该按钮点击事件的处理函数
         *
         * @property {boolean} [autoRender=true] - 自动渲染. 视图一初始化就进行渲染
         * @property {number} [_place=0] - 插入位置（0：append，1：prepend）
         * @property {string|object} [host] - 父元素，可以是选择器或jQuery对象
         * @property {boolean} [autoResize=false] - 自适应窗口变化. 该属性设为true后当窗口大小变化时会自动调用`resize`方法，因此需要重写该方法
         * @property {boolean} [autoCreateSubview=true] - 在视图渲染时，自动创建子视图，需设置 views 属性
         * @property {boolean} [activeView=null] - 设置在switchable中默认活动的视图
         * @property {boolean} [autoST=false] -自动设置触发器. 该属性为true后，会广播 `setTriggers` 消息可将该视图的工具条由defaultToolbarTpl 指定注入到其他widget，需要额外设置 `toolbar` 项指定该视图的注入到的widget名称
         * @property {string} [toolbar='toolbar'] - 触发器放置的 widget name
         * @property {string} [defaultToolbarTpl='.tpl-toolbar'] - 触发器默认模板的选择器
         * @property {object} [windowOptions=false] - 设置当视图单独位于窗口中时，窗口的选项
         * @property {object} [sharedModel=null] - 视图没有自己的视图模型，来源于该属性共享的视图模型
         * @property {array} [sharedModelProp=null] - 共享视图模型的属性集合
         *   ```
         *   [['destPropName', 'originPropName'], 'propName2']
         *   ```
         * @property {string} [langClass=null] - 视图所属的 language class 在模板中，可通过`data.lang.xxx` 来访问特定的语言文本
         * @property {boolean} [bindEmptyModel=false] - 当视图模型没赋值时 是否也进行绑定
         * @property {string} [activeView=null] - 初始活动的子视图名称
         */

        /** @lends veronica.View# */
        var base = {

            /**
             * 该视图的默认参数
             * @type {object}
             * @default
             */
            defaults: {},

            /**
             * 配置该视图的子视图 **`重写`**
             * @type {function}
             * @default
             * @example
             *   aspect: function(){
             *     this.after('initAttr', function(){
             *         this.param = { test: 'A' }
             *     });
             *     this.before // ...
             *   }
             */
            aspect: noop,

            /**
             * **`重写`** 视图的自定义初始化代码
             * @type {function}
             * @default
             */
            init: noop,

            /**
             * **`重写`** 混入其他视图方法
             * @type {function}
             * @returns {array}
             * @example
             *   mixins: function () {
             *       return [editHelper];
             *   }
             */
            mixins: noop,

            /**
             * **`重写`** 自定义销毁，通常用于释放视图使用的全局资源
             * @type {function}
             * @example
             *   _customDestory: function () {
             *     $(window).off('resize', this.resizeHanlder);
             *   }
             */
            _customDestory: noop,

            _defaults: {
                autoAction: false,

                autoResize: false,
                /**
                 * @deprecated
                 * @private
                 */
                lazyTemplate: false,
                langClass: null
            },

            /**
             * 视图初始化
             * @function
             * @inner
             * @listens View#initialize
             */
            initialize: function (options) {

                var me = this;

                options || (options = {});

                /**
                 * 视图的配置参数
                 * @name options
                 * @memberOf View#
                 * @type {ViewOptions}
                 * @todo 这里参数默认值合并使用了深拷贝，大多数时候其实没必要，目前实际测试速度影响暂时不大
                 */
                this.options = $.extend(true, this._defaults, this.defaults, options);

                /**
                 * 默认绑定视图对象到函数上下文的函数
                 * @name binds
                 * @memberOf View#
                 */
                this.binds = ['resize'];

                this._windows = {};  // 子窗口集合
                this._views = {};  // 子视图集合
                this._delayEvents = [];
                this._attributes = {};
                this.state = {};  // 视图状态

                this.baseModel = _.isFunction(this.staticModel) ? this._invoke('staticModel') : this.staticModel;
                this.viewModel = {};  // 该视图的视图模型
                this._activeViewName = null;
                this._name = options._name;

                // 将方法绑定到当前视图
                if (this.binds) {
                    this.binds.unshift(this);
                    _.bindAll.apply(_, this.binds);
                }

                // 混入AOP方法
                app.core.util.extend(this, app.core.aspect);

                // 应用mixins
                this._applyMixins();

                this.$el.addClass('ver-view');

                this._invoke('_loadPlugin');

                this._invoke('aspect');

                this._invoke('_defaultListen');

                this._invoke('_autoResize');

                this._invoke('_resetParentWnd');

                this._invoke('_initModel');

                // 初始化自定义属性
                this._invoke('initAttr');

                this._invoke('subscribe');  // 初始化广播监听

                this._invoke('_autoAction');

                this._invoke('init');

                this.trigger('init');

                // 渲染
                this.options.autoRender && this.render();
            },
            _applyMixins: function () {
                //TODO: 这里应将同名的属性或方法进行合并
                var me = this;
                _.each(this._invoke('mixins'), function (mixin) {
                    _.each(mixin, function (value, key) {
                        if (me[key] == null) {
                            me[key] = value;
                        }
                    });
                });
            },

            _invoke: function (methodName, isWithDefaultParams) {
                var args = _.toArray(arguments);
                var sliceLen = args.length >= 2 ? 2 : 1;
                if (isWithDefaultParams == null) { isWithDefaultParams = true; }

                if (isWithDefaultParams) {
                    args = args.concat([app, _, $]);
                }

                var method = methodName;
                if (_.isString(methodName)) {
                    method = this[methodName];
                }

                return method && method.apply(this, args.slice(sliceLen));
            },
            /**
              * 显示该视图
              * @function
              */
            show: function () {
                var me = this;
                this.$el.show(false, function () {
                    if (me.options.autoResize) {
                        me.resize();
                    }
                });
            },
            /**
              * 隐藏该视图
              * @function
              */
            hide: function () {
                this.$el.hide(false);
            },

            _destroy: function () {
                // 清理在全局注册的事件处理器
                this.options.autoResize && $(window).off('resize', this.resize);

                this._invoke('_destroyWindow', false);

                // 销毁该视图的所有子视图
                this._invoke('_destroyView', false);

                // 销毁第三方组件
                this._invoke('_customDestory');

                // 清除引用
                this.viewModel = null;

                this.options.sandbox.log('destroyed');
            },
            /**
             * 销毁该视图
             */
            destroy: function () {
                this._destroy();
            }
        };

        /**
         * @classdesc 视图
         * @class veronica.View
         * @augments Backbone.View
         */
        app.view.base = base;

        mvvm(app);
        subwindow(app);
        attr(app);
        action(app);
        children(app);
        listen(app);
        render(app);
        resize(app);
        trigger(app);
    };
});
<commit_msg>fixed bug<commit_after>define([
    './view-mvvm',
    './view-window',
    './view-attr',
    './view-action',
    './view-children',
    './view-listen',
    './view-render',
    './view-resize',
    './view-trigger'
], function (mvvm, subwindow, attr, action, children, listen, render, resize, trigger) {

    return function (app) {
        var $ = app.core.$;
        var _ = app.core._;
        var noop = $.noop;

        /**
         * 选项
         * @typedef ViewOptions
         * @property {boolean} [autoAction=false] - 自动绑定Action事件
         *   当在模板中使用如下写法时
         *   ```html
         *   <button data-action="add">添加</button>
         *   ```
         *   如果该属性为 `true` 将自动查找该视图的 `addHandler` 方法作为该按钮点击事件的处理函数
         *
         * @property {boolean} [autoRender=true] - 自动渲染. 视图一初始化就进行渲染
         * @property {number} [_place=0] - 插入位置（0：append，1：prepend）
         * @property {string|object} [host] - 父元素，可以是选择器或jQuery对象
         * @property {boolean} [autoResize=false] - 自适应窗口变化. 该属性设为true后当窗口大小变化时会自动调用`resize`方法，因此需要重写该方法
         * @property {boolean} [autoCreateSubview=true] - 在视图渲染时，自动创建子视图，需设置 views 属性
         * @property {boolean} [activeView=null] - 设置在switchable中默认活动的视图
         * @property {boolean} [autoST=false] -自动设置触发器. 该属性为true后，会广播 `setTriggers` 消息可将该视图的工具条由defaultToolbarTpl 指定注入到其他widget，需要额外设置 `toolbar` 项指定该视图的注入到的widget名称
         * @property {string} [toolbar='toolbar'] - 触发器放置的 widget name
         * @property {string} [defaultToolbarTpl='.tpl-toolbar'] - 触发器默认模板的选择器
         * @property {object} [windowOptions=false] - 设置当视图单独位于窗口中时，窗口的选项
         * @property {object} [sharedModel=null] - 视图没有自己的视图模型，来源于该属性共享的视图模型
         * @property {array} [sharedModelProp=null] - 共享视图模型的属性集合
         *   ```
         *   [['destPropName', 'originPropName'], 'propName2']
         *   ```
         * @property {string} [langClass=null] - 视图所属的 language class 在模板中，可通过`data.lang.xxx` 来访问特定的语言文本
         * @property {boolean} [bindEmptyModel=false] - 当视图模型没赋值时 是否也进行绑定
         * @property {string} [activeView=null] - 初始活动的子视图名称
         */

        /** @lends veronica.View# */
        var base = {

            /**
             * 该视图的默认参数
             * @type {object}
             * @default
             */
            defaults: {},

            /**
             * 配置该视图的子视图 **`重写`**
             * @type {function}
             * @default
             * @example
             *   aspect: function(){
             *     this.after('initAttr', function(){
             *         this.param = { test: 'A' }
             *     });
             *     this.before // ...
             *   }
             */
            aspect: noop,

            /**
             * **`重写`** 视图的自定义初始化代码
             * @type {function}
             * @default
             */
            init: noop,

            /**
             * **`重写`** 混入其他视图方法
             * @type {function}
             * @returns {array}
             * @example
             *   mixins: function () {
             *       return [editHelper];
             *   }
             */
            mixins: noop,

            /**
             * **`重写`** 自定义销毁，通常用于释放视图使用的全局资源
             * @type {function}
             * @example
             *   _customDestory: function () {
             *     $(window).off('resize', this.resizeHanlder);
             *   }
             */
            _customDestory: noop,

            _defaults: {
                autoAction: false,

                autoResize: false,
                /**
                 * @deprecated
                 * @private
                 */
                lazyTemplate: false,
                langClass: null
            },

            /**
             * 视图初始化
             * @function
             * @inner
             * @listens View#initialize
             */
            initialize: function (options) {

                var me = this;

                options || (options = {});

                /**
                 * 视图的配置参数
                 * @name options
                 * @memberOf View#
                 * @type {ViewOptions}
                 * @todo 这里参数默认值合并使用了深拷贝，大多数时候其实没必要，目前实际测试速度影响暂时不大
                 */
                this.options = $.extend(true, {}, this._defaults, this.defaults, options);

                /**
                 * 默认绑定视图对象到函数上下文的函数
                 * @name binds
                 * @memberOf View#
                 */
                this.binds = ['resize'];

                this._windows = {};  // 子窗口集合
                this._views = {};  // 子视图集合
                this._delayEvents = [];
                this._attributes = {};
                this.state = {};  // 视图状态

                this.baseModel = _.isFunction(this.staticModel) ? this._invoke('staticModel') : this.staticModel;
                this.viewModel = {};  // 该视图的视图模型
                this._activeViewName = null;
                this._name = options._name;

                // 将方法绑定到当前视图
                if (this.binds) {
                    this.binds.unshift(this);
                    _.bindAll.apply(_, this.binds);
                }

                // 混入AOP方法
                app.core.util.extend(this, app.core.aspect);

                // 应用mixins
                this._applyMixins();

                this.$el.addClass('ver-view');

                this._invoke('_loadPlugin');

                this._invoke('aspect');

                this._invoke('_defaultListen');

                this._invoke('_autoResize');

                this._invoke('_resetParentWnd');

                this._invoke('_initModel');

                // 初始化自定义属性
                this._invoke('initAttr');

                this._invoke('subscribe');  // 初始化广播监听

                this._invoke('_autoAction');

                this._invoke('init');

                this.trigger('init');

                // 渲染
                this.options.autoRender && this.render();
            },
            _applyMixins: function () {
                //TODO: 这里应将同名的属性或方法进行合并
                var me = this;
                _.each(this._invoke('mixins'), function (mixin) {
                    _.each(mixin, function (value, key) {
                        if (me[key] == null) {
                            me[key] = value;
                        }
                    });
                });
            },

            _invoke: function (methodName, isWithDefaultParams) {
                var args = _.toArray(arguments);
                var sliceLen = args.length >= 2 ? 2 : 1;
                if (isWithDefaultParams == null) { isWithDefaultParams = true; }

                if (isWithDefaultParams) {
                    args = args.concat([app, _, $]);
                }

                var method = methodName;
                if (_.isString(methodName)) {
                    method = this[methodName];
                }

                return method && method.apply(this, args.slice(sliceLen));
            },
            /**
              * 显示该视图
              * @function
              */
            show: function () {
                var me = this;
                this.$el.show(false, function () {
                    if (me.options.autoResize) {
                        me.resize();
                    }
                });
            },
            /**
              * 隐藏该视图
              * @function
              */
            hide: function () {
                this.$el.hide(false);
            },

            _destroy: function () {
                // 清理在全局注册的事件处理器
                this.options.autoResize && $(window).off('resize', this.resize);

                this._invoke('_destroyWindow', false);

                // 销毁该视图的所有子视图
                this._invoke('_destroyView', false);

                // 销毁第三方组件
                this._invoke('_customDestory');

                // 清除引用
                this.viewModel = null;

                this.options.sandbox.log('destroyed');
            },
            /**
             * 销毁该视图
             */
            destroy: function () {
                this._destroy();
            }
        };

        /**
         * @classdesc 视图
         * @class veronica.View
         * @augments Backbone.View
         */
        app.view.base = base;

        mvvm(app);
        subwindow(app);
        attr(app);
        action(app);
        children(app);
        listen(app);
        render(app);
        resize(app);
        trigger(app);
    };
});
<|endoftext|>


<commit_before>import rc from 'rc'

export default rc('david', {
  brains: {
    cacheTime: 86400000
  },
  github: {
    api: {
      version: '3.0.0',
      protocol: 'https',
      host: 'api.github.com',
      timeout: 5000
    },
    protocol: 'https',
    host: 'github.com',
    oauth: {
      clientId: null,
      secret: null
    },
    token: null
  },
  npm: {
    hostname: 'https://www.npmjs.com',
    options: {
      registry: 'http://registry.npmjs.org'
    },
    feed: 'https://skimdb.npmjs.com/registry'
  },
  site: {
    hostname: 'http://localhost:1337'
  },
  db: {
    path: 'data'
  },
  nsp: {
    syncAdvisoriesInterval: 3600000
  },
  public: {
    siteUrl: 'http://localhost:1337',
    apiUrl: 'http://localhost:1337',
    githubUrl: 'https://github.com',
    github: {
      protocol: 'https',
      host: 'github.com',
      oauth: {
        clientId: null
      }
    },
    google: {
      trackingId: ''
    }
  }
})
<commit_msg>Update config.js<commit_after>import rc from 'rc'

export default rc('david', {
  brains: {
    cacheTime: 86400000
  },
  github: {
    api: {
      version: '3.0.0',
      protocol: 'https',
      host: 'api.github.com',
      timeout: 5000,
      caFile: null
    },
    protocol: 'https',
    host: 'github.com',
    oauth: {
      clientId: null,
      secret: null
    },
    token: null
  },
  npm: {
    hostname: 'https://www.npmjs.com',
    options: {
      registry: 'http://registry.npmjs.org'
    },
    feed: 'https://skimdb.npmjs.com/registry'
  },
  site: {
    hostname: 'http://localhost:1337'
  },
  db: {
    path: 'data'
  },
  nsp: {
    syncAdvisoriesInterval: 3600000
  },
  public: {
    siteUrl: 'http://localhost:1337',
    apiUrl: 'http://localhost:1337',
    githubUrl: 'https://github.com',
    github: {
      protocol: 'https',
      host: 'github.com',
      oauth: {
        clientId: null
      }
    },
    google: {
      trackingId: ''
    }
  }
})
<|endoftext|>


<commit_before>export default {

  "storage": {
    "name": "filesystem",
    "directory": "/workspace/testStorage"
  },

  "port": 4321,

  /*
  * 'register': set availability of user-registration
  * 'public': make everything publicly available
  * 'remove': make it possible to remove, unpublish or overwrite packages *** not implemented yet
  */
  "auth": {
    "users": {
      "canPublish": true,
      "canAccess": true
    },
    "register": true,
    "public": false,
    "remove": true
  },

  "ssl": {
    "enabled": false,
    "key": "",
    "cert": ""
  }
}<commit_msg>'remove' is implemented now<commit_after>export default {

  "storage": {
    "name": "filesystem",
    "directory": "/workspace/testStorage"
  },

  "port": 4321,

  /*
  * 'register': set availability of user-registration
  * 'public': make everything publicly available
  * 'remove': make it possible to remove, unpublish or overwrite packages
  */
  "auth": {
    "users": {
      "canPublish": true,
      "canAccess": true
    },
    "register": true,
    "public": false,
    "remove": true
  },

  "ssl": {
    "enabled": false,
    "key": "",
    "cert": ""
  }
}<|endoftext|>


<commit_before>/**
 * @fileOverview
 * Generate basic webpack config.
 */

function genBasicConfig () {
  return {
    entry: 'index.js',
    output: {
      path: '.',
      filename: 'bundle.js'
    },
    module: {
      rules: [
        { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: ['env']}}, exclude: /(node_modules|bower_components)/ },
        { test: /\.jsx$/, use: { loader: 'babel-loader', options: { presets: ['env', 'react']}}},
        { test: /\.json$/, use: 'json-loader' },
        { test: /\.css$/, use: [{ loader: "style-loader" }, { loader: "css-loader" }]},
        { test: /\.vue$/, use: 'vue-loader' }
      ]
    }
  }
}

exports.genBasicConfig = genBasicConfig
<commit_msg>Fixed webpack path bug.<commit_after>/**
 * @fileOverview
 * Generate basic webpack config.
 */
const path = require('path')

function genBasicConfig () {
  return {
    entry: path.resolve('index.js'),
    output: {
      path: path.resolve('.'),
      filename: 'bundle.js'
    },
    context: path.resolve(__dirname, '../'),
    module: {
      rules: [
        { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: ['env']}}, exclude: /(node_modules|bower_components)/ },
        { test: /\.jsx$/, use: { loader: 'babel-loader', options: { presets: ['env', 'react']}}},
        { test: /\.json$/, use: 'json-loader' },
        { test: /\.css$/, use: [{ loader: "style-loader" }, { loader: "css-loader" }]},
        { test: /\.vue$/, use: 'vue-loader' }
      ]
    }
  }
}

exports.genBasicConfig = genBasicConfig
<|endoftext|>


<commit_before>// ==UserScript==
// @name vultaire.net CookieBot
// @namespace http://vultaire.net/gmscripts
// @description A very simple clickslave and AI bot for Cookie Clicker.
// @include http://orteil.dashnet.org/cookieclicker/*
// @version 0.20
// ==/UserScript==

// Changes:
//
// 0.20: Tweaked auto-purchase logic so it makes smarter decisions
//   end-game.  (The stock 5 minute decision period breaks down at
//   about 90+ antimatter condensers, and likely much sooner w/o
//   prestige.)
//
// 0.19: Minor fix: since Object.cps can supposedly be either a direct
//   value or a function, using Object.storedCps in calculations
//   instead.
//
// 0.18: Bug fix... now the last change should actually work.
//
// 0.17: Added special case upgrade purchases where the cookie buffer
//   is ignored for particularly high-value purchases, such as kitten
//   and heavenly chip related upgrades.
//
// 0.16: Added new auto-purchase logic: uses a simple algorithm for
//   deciding a purchase based upon the ratio of cookies-per-minute
//   gain against the cost of the upgrade.
//
// 0.15: Fixed the purchase rule list: it now gets re-initialized
//   after resetting.
//
// 0.14: Updated soft reset to consider total cookies made across all
//   resets.
//
// 0.13: Changed "hold buffer" lower bound to 1 billion CPS.
//
// 0.12: Added a tweak: the cookie "hold buffer" only takes effect if
//   you are making at least a million cookies per second.
//
// 0.11: Fixed auto-soft-reset comparison.
//
// 0.10: Added auto-soft-reset when enough cookies have been made to
//   double the end-game income.  (Based upon current max multiplier
//   of 470% @ 0 prestige and 570% at 4+ prestige.)
//
// 0.9: Minor fix on a check for a possibly defined variable; should
//   work in Chrome again.  (I don't *think* it was affecting FireFox,
//   but not sure.)
//
// 0.8: Embarassing error.  Put the click parameter in the wrong
//   place.  Oops.
//
// 0.7: PhantomJS testing support: can effectively parameterize
//   startup by injecting a variable before loading the main script.
//   Added single parameter, phantomJsClickRate, for controlling the
//   autoclick rate.
//
// 0.6: Fixed cookies-on-hand logic: CPS variable reflected Frenzy; we
//   don't want that.
//
// 0.5: Added minimum cookies-on-hand buffer for gaming the Golden
//   Cookies.

var CookieBot = function () {
    var autoClicker = null;
    var realConfirm = window.confirm;

    function injectScript(src) {
        var text = document.createTextNode(src);
        var script = document.createElement("script");
        script.appendChild(text);
        document.body.appendChild(script);
    }

    function hijackFunctions() {
        hijackConfirm();
        hijackGameParticlesAdd();
    }

    function hijackConfirm() {
        // Automatically hit "yes" for any confirm dialogs.
        // In order to work with TamperMonkey, need to inject into the
        // page directly; can't just override.
        injectScript([
            "window.confirm = function (message) {",
            "    console.log('Automatically hitting \"yes\" for: ' + message);",
            "    return true;",
            "}",
        ].join(""))
    }

    function hijackGameParticlesAdd() {
        var fn = Game.particlesAdd;
        Game.particlesAdd = function (text, el) {
            console.log("Popup: " + text)
            return fn(text, el);
        }
    }

    function enableAutoClick() {
        if (autoClicker === null) {
            var clickInterval = 200;
            if (typeof phantomJsClickRate !== "undefined") {
                console.log("PhantomJS click rate detected; setting to "
                            + phantomJsClickRate + " clicks per second.");
                clickInterval = 1000 / phantomJsClickRate;
            }
            autoClicker = setInterval(Game.ClickCookie, clickInterval);
        }
    }
    function disableAutoClick() {
        if (autoClicker !== null) {
            clearInterval(autoClicker);
            autoClicker = null;
        }
    }

    var objectShoppingOrder = null;

    function initPurchaseRules() {
        objectShoppingOrder = [
            // Syntax: [object, buy-up-to]
            // i.e. if I have 20 cursors and buy-up-to is 50, I buy 30 cursors.
            // If buy-up-to is null, means to just keep buying.
            ["Cursor", 5],
            ["Grandma", 3],
            ["Farm", 3],
            ["Cursor", 20],
            ["Factory", 3],
            ["Mine", 3],
            ["Cursor", 50],
            ["Grandma", 10],
            ["Farm", 10],
            ["Shipment", 5],
            ["Factory", 10],
            ["Mine", 10],
            ["Shipment", 10],
            ["Alchemy lab", 5],
            ["Portal", 10],
            ["Alchemy lab", 10],
            ["Time machine", 20],
            ["Cursor", 100],
            ["Antimatter condenser", 30],
            ["Grandma", 50],
            ["Cursor", 130],
            ["Antimatter condenser", 40],
            ["Farm", 50],
            ["Factory", 50],
            ["Mine", 50],
            ["Shipment", 50],
            ["Cursor", 150],
            ["Antimatter condenser", 50],
            ["Alchemy lab", 50],
            ["Portal", 50],
            ["Time machine", 30],
            ["Cursor", 200],
            ["Antimatter condenser", 60],
            ["Grandma", 128],
            ["Farm", 128],
            ["Factory", 100],
            ["Mine", 100],
            ["Shipment", 100],
            ["Alchemy lab", 100],
            ["Portal", 100],
            ["Time machine", 50],
            ["Antimatter condenser", 70],
            ["Grandma", 150],
            ["Time machine", 80],
            ["Antimatter condenser", 80],
            ["Grandma", 175],
            ["Time machine", 100],
            ["Antimatter condenser", 90],
            ["Grandma", 200],
            ["Antimatter condenser", null],
        ];
    }

    function hasGetLucky() {
        return Game.UpgradesById.filter(function (u) {
            return u.name === "Get lucky";
        })[0].bought;
    }

    function cookiesToHold() {
        // Computes an adjustment factor, such that Golden Cookies are
        // as effective as possible.

        // Early game, this just gets in the way, so skip unless our
        // CPS is at a certain level.  Let's say... 1 billion.
        if (Game.cookiesPs < 1000000000) {
            return 0;
        }

        // Get base cookies-per-second, i.e. accomodating for any Frenzy.
        var realCps = Game.cookiesPs;
        if (Game.frenzy > 0) {
            realCps /= Game.frenzyPower;
        }

        // Compute potential CPS multiplier for Lucky.
        var multiplier = 60 * 20;  // Represents 20 minutes of cookies
        if (hasGetLucky()) {
            multiplier *= 7;  // Potential stacked multiplier with "Get Lucky" upgrade.
        }

        var bonusCookies = realCps * multiplier;
        var bonusCap = bonusCookies * 10;
        return bonusCap;
    }

    var neverBuy = ["Elder Covenant"];
    var buyEarly = [
        "Kitten helpers",
        "Kitten workers",
        "Kitten engineers",
        "Kitten overseers",
        "Heavenly chip secret",
        "Heavenly cookie stand",
        "Heavenly bakery",
        "Heavenly confectionery",
        "Heavenly key",
    ];

    function autoBuyPriorityUpgrades() {
        var bought = false;
        Game.UpgradesInStore.filter(function (upgrade) {
            return upgrade.unlocked && (buyEarly.indexOf(upgrade.name) !== -1);
        }).map(function (upgrade) {
            if (!bought && (Game.cookies >= upgrade.basePrice)) {
                bought = true;
                upgrade.buy();
                console.log("Purchased " + upgrade.name
                            + " for " + Beautify(upgrade.basePrice));
            }
        });
        return bought;
    }

    function autoBuyGeneralUpgrades() {
        var bought = false;
        Game.UpgradesInStore.filter(function (upgrade) {
            return upgrade.unlocked && (neverBuy.indexOf(upgrade.name) === -1);
        }).map(function (upgrade) {
            if (!bought && (Game.cookies - cookiesToHold() >= upgrade.basePrice)) {
                bought = true;
                upgrade.buy();
                console.log("Purchased " + upgrade.name
                            + " for " + Beautify(upgrade.basePrice));
            }
        });
        return bought;
    }

    function autoBuyUpgrades() {
        if (!autoBuyPriorityUpgrades()) {
            autoBuyGeneralUpgrades();
        }
    }

    function pricePerCps(o) {
        // Returns price/CPS ratio.
        return o.price/o.storedCps;
    }
    function autoBuyObjects() {
        var minutes;
        var condensers = Game.Objects['Antimatter condenser'].amount;
        if (condensers < 1) {
            minutes = 5;      // Decent early game setting
        } else if (condensers < 100) {
            minutes = 60;     // Once condensers are in play, they're
                              // basically the best.  Give plenty of
                              // time for purchasing them.
        } else {
            minutes = 60*24;  // Essentially: pick the best gain/cost
                              // regardless of time.
        }
        var cookiesInFiveMinutes = Game.cookies + (Game.cookiesPs * 60 * minutes);
        var candidates = Game.ObjectsById.sort(function (a, b) {
            return pricePerCps(a) - pricePerCps(b);
        }).filter(function (o) {
            return cookiesInFiveMinutes > o.price + cookiesToHold();
        });
        // candidates.map(function (o) {
        //     console.log("Candidate: " + o.name
        //                 + " (" + pricePerCps(o) + " price/CPS)");
        // });
        if (candidates.length > 0) {
            var object = candidates[0];
            if (Game.cookies - cookiesToHold() >= object.price) {
                object.buy();
                console.log(">>> Purchased " + object.name
                            + " for " + Beautify(object.price)
                            + ", current count: " + object.amount);
            } // else {
            //     console.log("Waiting on " + object.name
            //                 + ", price: " + Beautify(object.price)
            //                 + ", price/CPS: " + pricePerCps(object)
            //                 + ", will buy at: "
            //                 + Beautify(object.price + cookiesToHold()));
            // }
        }
    }

    function buyObjectsByRules() {
        while (true) {
            var name = objectShoppingOrder[0][0];
            var target = objectShoppingOrder[0][1];
            var object = Game.ObjectsById.filter(function (object) {
                return object.name === name;
            })[0];
            var price;
            if (target === null || object.amount < target) {
                if (Game.cookies - cookiesToHold() >= object.price) {
                    object.buy();
                    console.log("Purchased " + object.name
                                + " for " + Beautify(object.price)
                                + ", current count: " + object.amount);
                } else {
                    // Don't do anything this time.
                }
                return;
            }
            objectShoppingOrder.shift();
        }
    }
    function clickGoldenCookies() {
        if (Game.goldenCookie.life > 0) {
            Game.goldenCookie.click();
        }
    }
    function autoSoftReset() {
        // Exceptions go here...  i.e. don't auto-reset unless you
        // have purchased these items...  For now: don't bother.

        // Begin check for whether we can double our end-game income
        // by resetting.

        var currentPrestige = Game.prestige['Heavenly chips'];
        var base = 470;   // Using 100 (instead of 1.00) as 100%
        // Adjust for cookie requirements which require prestige;
        // these will be available on subsequent runs through.
        base += (25 * Math.min(4, currentPrestige));
        current = base + (2*currentPrestige);  // Current raw multiplier

        // Next: 2*current
        // Next base: 570 (for sure)
        // next: 570 + 2p = 2(current)
        //       2(285 + p) = 2(current)
        //          285 + p = current
        //                p = current - 285
        var targetPrestige = current - 285;
        if (Game.HowMuchPrestige(Game.cookiesEarned + Game.cookiesReset)
            >= targetPrestige) {
            Game.Reset();
            initPurchaseRules();
        }
    }
    function tick() {
        autoBuyUpgrades();
        autoBuyObjects();
        //buyObjectsByRules();
        clickGoldenCookies();
        autoSoftReset();
    }
    function init() {
        hijackFunctions();
        enableAutoClick();
        initPurchaseRules();
        setInterval(tick, 500);
    }
    return {
        init: init,
        enableAutoClick: enableAutoClick,
        disableAutoClick: disableAutoClick,
        cookiesToHold: cookiesToHold,
    };
}();

function bootStrap() {
    // Since not everything gets loaded right away... wait a bit.
    if (Game.ClickCookie) {
        CookieBot.init();
    } else {
        setTimeout(bootStrap, 200);
    }
}

bootStrap();
<commit_msg>0.21 - lots of achievement-related improvements<commit_after>// ==UserScript==
// @name vultaire.net CookieBot
// @namespace http://vultaire.net/gmscripts
// @description A very simple clickslave and AI bot for Cookie Clicker.
// @include http://orteil.dashnet.org/cookieclicker/*
// @version 0.21
// ==/UserScript==

// Changes:
//
// 0.21:
//
//   - Added logic to get the "Neverclick" achievement.  This will slow
//     down the early game significantly until the first million
//     cookies are made, but again, since this is a bot it likely
//     won't be such a big deal.  (This could also be made as a
//     special case requiring prestige, but I opted against this for
//     slightly simpler code.)
//
//   - Moved autoclick init into the neverclick achievement handler.
//
//   - Added logic for getting the "Cookie-dunker" achievement.  This
//     is done by resizing the left-hand canvas where the big cookie
//     and milk are drawn, avoiding the need to resize the actual
//     browser.  This is about the best that can be done w/o having
//     the AI simply cheat and award itself the achievement.
//
//   - Added logic for getting the "Just wrong" achievement; kicks in
//     after you have 10 grandmas.
//
//   - Added logic for getting the "Elder calm" achievement, while in
//     general not buying the elder covenant upgrade.
//
//   - Tweaked interval to be fast enough to get "Uncanny clicker".
//     According to current code, Uncanny Clicker is won basically
//     when the player exceeds 15 clicks per second (66.7 ms per
//     click).  I went for a round number: 50 ms per click.
//
// 0.20: Tweaked auto-purchase logic so it makes smarter decisions
//   end-game.  (The stock 5 minute decision period breaks down at
//   about 90+ antimatter condensers, and likely much sooner w/o
//   prestige.)
//
// 0.19: Minor fix: since Object.cps can supposedly be either a direct
//   value or a function, using Object.storedCps in calculations
//   instead.
//
// 0.18: Bug fix... now the last change should actually work.
//
// 0.17: Added special case upgrade purchases where the cookie buffer
//   is ignored for particularly high-value purchases, such as kitten
//   and heavenly chip related upgrades.
//
// 0.16: Added new auto-purchase logic: uses a simple algorithm for
//   deciding a purchase based upon the ratio of cookies-per-minute
//   gain against the cost of the upgrade.
//
// 0.15: Fixed the purchase rule list: it now gets re-initialized
//   after resetting.
//
// 0.14: Updated soft reset to consider total cookies made across all
//   resets.
//
// 0.13: Changed "hold buffer" lower bound to 1 billion CPS.
//
// 0.12: Added a tweak: the cookie "hold buffer" only takes effect if
//   you are making at least a million cookies per second.
//
// 0.11: Fixed auto-soft-reset comparison.
//
// 0.10: Added auto-soft-reset when enough cookies have been made to
//   double the end-game income.  (Based upon current max multiplier
//   of 470% @ 0 prestige and 570% at 4+ prestige.)
//
// 0.9: Minor fix on a check for a possibly defined variable; should
//   work in Chrome again.  (I don't *think* it was affecting FireFox,
//   but not sure.)
//
// 0.8: Embarassing error.  Put the click parameter in the wrong
//   place.  Oops.
//
// 0.7: PhantomJS testing support: can effectively parameterize
//   startup by injecting a variable before loading the main script.
//   Added single parameter, phantomJsClickRate, for controlling the
//   autoclick rate.
//
// 0.6: Fixed cookies-on-hand logic: CPS variable reflected Frenzy; we
//   don't want that.
//
// 0.5: Added minimum cookies-on-hand buffer for gaming the Golden
//   Cookies.

var CookieBot = function () {
    var autoClicker = null;
    var realConfirm = window.confirm;

    function injectScript(src) {
        var text = document.createTextNode(src);
        var script = document.createElement("script");
        script.appendChild(text);
        document.body.appendChild(script);
    }

    function hijackFunctions() {
        hijackConfirm();
        hijackGameParticlesAdd();
    }

    function hijackConfirm() {
        // Automatically hit "yes" for any confirm dialogs.
        // In order to work with TamperMonkey, need to inject into the
        // page directly; can't just override.
        injectScript([
            "window.confirm = function (message) {",
            "    console.log('Automatically hitting \"yes\" for: ' + message);",
            "    return true;",
            "}",
        ].join(""))
    }

    function hijackGameParticlesAdd() {
        var fn = Game.particlesAdd;
        Game.particlesAdd = function (text, el) {
            console.log("Popup: " + text)
            return fn(text, el);
        }
    }

    function enableAutoClick() {
        if (autoClicker === null) {
            var clickInterval = 50;
            if (typeof phantomJsClickRate !== "undefined") {
                console.log("PhantomJS click rate detected; setting to "
                            + phantomJsClickRate + " clicks per second.");
                clickInterval = 1000 / phantomJsClickRate;
            }
            autoClicker = setInterval(Game.ClickCookie, clickInterval);
        }
    }
    function disableAutoClick() {
        if (autoClicker !== null) {
            clearInterval(autoClicker);
            autoClicker = null;
        }
    }

    function cookiesToHold() {
        // Computes an adjustment factor, such that Golden Cookies are
        // as effective as possible.

        // Early game, this just gets in the way, so skip unless our
        // CPS is at a certain level.  Let's say... 1 billion.
        if (Game.cookiesPs < 1000000000) {
            return 0;
        }

        // Get base cookies-per-second, i.e. accomodating for any Frenzy.
        var realCps = Game.cookiesPs;
        if (Game.frenzy > 0) {
            realCps /= Game.frenzyPower;
        }

        // Compute potential CPS multiplier for Lucky.
        var multiplier = 60 * 20;  // Represents 20 minutes of cookies
        if (Game.Upgrades["Get lucky"].bought) {
            multiplier *= 7;  // Potential stacked multiplier with "Get Lucky" upgrade.
        }

        var bonusCookies = realCps * multiplier;
        var bonusCap = bonusCookies * 10;
        return bonusCap;
    }

    var neverBuy = ["Elder Covenant"];
    var buyEarly = [
        "Kitten helpers",
        "Kitten workers",
        "Kitten engineers",
        "Kitten overseers",
        "Heavenly chip secret",
        "Heavenly cookie stand",
        "Heavenly bakery",
        "Heavenly confectionery",
        "Heavenly key",
    ];

    function autoBuyPriorityUpgrades() {
        var bought = false;
        Game.UpgradesInStore.filter(function (upgrade) {
            return upgrade.unlocked && (buyEarly.indexOf(upgrade.name) !== -1);
        }).map(function (upgrade) {
            if (!bought && (Game.cookies >= upgrade.basePrice)) {
                bought = true;
                upgrade.buy();
                console.log("Purchased " + upgrade.name
                            + " for " + Beautify(upgrade.basePrice));
            }
        });
        return bought;
    }

    function autoBuyGeneralUpgrades() {
        var bought = false;
        Game.UpgradesInStore.filter(function (upgrade) {
            return upgrade.unlocked && (neverBuy.indexOf(upgrade.name) === -1);
        }).map(function (upgrade) {
            if (!bought && (Game.cookies - cookiesToHold() >= upgrade.basePrice)) {
                bought = true;
                upgrade.buy();
                console.log("Purchased " + upgrade.name
                            + " for " + Beautify(upgrade.basePrice));
            }
        });
        return bought;
    }

    function autoBuyUpgrades() {
        if (!autoBuyPriorityUpgrades()) {
            autoBuyGeneralUpgrades();
        }
    }

    function pricePerCps(o) {
        // Returns price/CPS ratio.
        return o.price/o.storedCps;
    }
    function autoBuyObjects() {
        var minutes;
        var condensers = Game.Objects['Antimatter condenser'].amount;
        if (condensers < 1) {
            minutes = 5;      // Decent early game setting
        } else if (condensers < 100) {
            minutes = 60;     // Once condensers are in play, they're
                              // basically the best.  Give plenty of
                              // time for purchasing them.
        } else {
            minutes = 60*24;  // Essentially: pick the best gain/cost
                              // regardless of time.
        }
        var cookiesInFiveMinutes = Game.cookies + (Game.cookiesPs * 60 * minutes);
        var candidates = Game.ObjectsById.sort(function (a, b) {
            return pricePerCps(a) - pricePerCps(b);
        }).filter(function (o) {
            return cookiesInFiveMinutes > o.price + cookiesToHold();
        });
        // candidates.map(function (o) {
        //     console.log("Candidate: " + o.name
        //                 + " (" + pricePerCps(o) + " price/CPS)");
        // });
        if (candidates.length > 0) {
            var object = candidates[0];
            if (Game.cookies - cookiesToHold() >= object.price) {
                object.buy();
                console.log(">>> Purchased " + object.name
                            + " for " + Beautify(object.price)
                            + ", current count: " + object.amount);
            } // else {
            //     console.log("Waiting on " + object.name
            //                 + ", price: " + Beautify(object.price)
            //                 + ", price/CPS: " + pricePerCps(object)
            //                 + ", will buy at: "
            //                 + Beautify(object.price + cookiesToHold()));
            // }
        }
    }

    function clickGoldenCookies() {
        if (Game.goldenCookie.life > 0) {
            Game.goldenCookie.click();
        }
    }
    function autoSoftReset() {
        // Exceptions go here...  i.e. don't auto-reset unless you
        // have purchased these items...  For now: don't bother.

        // Begin check for whether we can double our end-game income
        // by resetting.

        var currentPrestige = Game.prestige['Heavenly chips'];
        var base = 470;   // Using 100 (instead of 1.00) as 100%
        // Adjust for cookie requirements which require prestige;
        // these will be available on subsequent runs through.
        base += (25 * Math.min(4, currentPrestige));
        current = base + (2*currentPrestige);  // Current raw multiplier

        // Next: 2*current
        // Next base: 570 (for sure)
        // next: 570 + 2p = 2(current)
        //       2(285 + p) = 2(current)
        //          285 + p = current
        //                p = current - 285
        var targetPrestige = current - 285;
        if (Game.HowMuchPrestige(Game.cookiesEarned + Game.cookiesReset)
            >= targetPrestige) {
            if (! Game.Achievements['Neverclick'].won) {
                disableAutoClick();
            }
            Game.Reset();
        }
    }
    var clickToFifteen = null;
    function autoNeverClick() {
        if (!Game.Achievements['Neverclick'].won) {
            if (Game.cookieClicks < 15 &&
                clickToFifteen === null) {
                // Click up to 15, then stop.

                var interval = 50;
                function clicker() {
                    Game.ClickCookie();
                    if (Game.cookieClicks < 15) {
                        clickToFifteen = setTimeout(clicker, interval);
                    } else {
                        clickToFifteen = null;
                        if (Game.cookies >= 15) {
                            Game.Objects["Cursor"].buy();
                        }
                    }
                }
                clickToFifteen = setTimeout(clicker, interval);
            } else if (Game.cookieClicks > 15) {
                // Too many clicks to try Neverclick; just enable.
                enableAutoClick();
            }
        } else {
            enableAutoClick();
        }
    }

    var undunkCookie = null;
    function autoCookieDunker() {
        if ((!Game.Achievements["Cookie-dunker"].won)
            && Game.milkProgress > 3.0
            && undunkCookie === null) {
            /*
              Achievement basically won if:
              - More than 10% milk.
              - If 16 pixels or more of the big cookie are submerged below the milk line

              No cross-platform way to resize window it seems, at least at quick glance.

              Canvas can be resized...  This is the closest it seems we can get.

             */

            // Game.milkHd at high milk % will be around 35%... meaning 65% of canvas height.
            // Exact formula to calculate:
            // .4y + 128 - 16 > my
            // .4y + 112 > my
            // (.4y + 112)/y > m
            // .4 + 112/y > m
            // 112/y > m - .4
            // 112 > y(m - .4)
            // 112/(m-.4) > y
            // y < 112/(m-.4)
            // Where:
            //   y: canvas height
            //   m: milk height

            var milkHeightPct = (1-Game.milkHd);
            var dunkHeight = 112/(milkHeightPct-.4);
            dunkHeight -= 1;  // Ensure that we set our height below
                              // the threshold for dunking.

            var oldHeight = Game.LeftBackground.canvas.height;
            Game.LeftBackground.canvas.height = dunkHeight;
            function undunk() {
                Game.LeftBackground.canvas.height = oldHeight;
            }
            // This may take some time to register; wait 10 seconds.
            undunkCookie = setInterval(undunk, 10000);
        }
    }

    function autoElderCalm() {
        var elderCovenant = Game.Upgrades["Elder Covenant"];
        if ((!Game.Achievements["Elder calm"].won)
            && elderCovenant.unlocked
            && Game.cookies >= elderCovenant.basePrice) {

            elderCovenant.buy();
        }
    }

    function autoJustWrong() {
        if ((!Game.Achievements["Just wrong"].won)
            && Game.Objects["Grandma"].amount > 10) {

            Game.Objects["Grandma"].sell();
        }
    }

    function autoAchieve() {
        autoNeverClick();
        autoCookieDunker();
        autoElderCalm();
        autoJustWrong();
    }

    function tick() {
        autoBuyUpgrades();
        autoBuyObjects();
        //buyObjectsByRules();
        clickGoldenCookies();
        autoAchieve();
        autoSoftReset();
    }

    function init() {
        hijackFunctions();
        setInterval(tick, 500);
    }

    return {
        init: init,
        enableAutoClick: enableAutoClick,
        disableAutoClick: disableAutoClick,
        cookiesToHold: cookiesToHold,
    };
}();

function bootStrap() {
    // Since not everything gets loaded right away... wait a bit.
    if (Game.ClickCookie) {
        CookieBot.init();
    } else {
        setTimeout(bootStrap, 200);
    }
}

bootStrap();
<|endoftext|>


<commit_before>/**
 * Copyright 2015 CANAL+ Group
 *
 * 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
 *
 *     http://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.
 */

export default {
  /**
   * Default audio track configuration, if none is set by the user.
   * Here in french for legacy reasons.
   */
  DEFAULT_AUDIO_TRACK: {
    language: "fra",
    audioDescription: false,
  },

  /**
   * Default text track configuration, if none is set by the user.
   */
  DEFAULT_TEXT_TRACK: null,

  /*
   * Default buffer goal in seconds
   */
  DEFAULT_WANTED_BUFFER_AHEAD: 30,

  /*
   * Default max buffer size ahead of the current position in seconds.
   */
  DEFAULT_MAX_BUFFER_AHEAD: Infinity,

  /*
   * Default max buffer size ahead of the current position in seconds.
   */
  DEFAULT_MAX_BUFFER_BEHIND: Infinity,

  DEFAULT_INITIAL_BITRATES: {
    audio: 0,
    video: 0,
    other: 0,
  },

  DEFAULT_MAX_BITRATES: {
    audio: Infinity,
    video: Infinity,
    other: Infinity,
  },

  /**
   * buffer threshold ratio used as a lower bound
   * margin to find the suitable representation
   */
  DEFAULT_ADAPTIVE_BUFFER_THRESHOLD: 0.3,

  /**
   * Delay after which, if the page is hidden, the user is considered inactive
   * on the current video. Allow to enforce specific optimizations when the
   * page is not shown.
   * @see DEFAULT_THROTTLE_WHEN_HIDDEN
   */
  INACTIVITY_DELAY: 60 * 1000,

  /**
   * If true, if the player is in a "hidden" state for a delay specified by the
   * INACTIVITY DELAY config property, we throttle automatically to the video
   * representation with the lowest bitrate.
   */
  DEFAULT_THROTTLE_WHEN_HIDDEN: true,

  /**
   * If true, the video representations you can switch to in adaptive mode
   * are limited by the video element's width.
   */
  DEFAULT_LIMIT_VIDEO_WIDTH: true,

  /**
   * Default initial live gap considered if no presentation delay has been
   * suggested, in seconds.
   *
   * TODO this is never used, as every transport techno has a default
   * suggested presentation delay.
   */
  DEFAULT_LIVE_GAP: 15,

  /**
   * Default value for a manifest's suggested presentation delay if not
   * specified in the manifest.
   *
   * TODO this should not be in a manifest as it does not reflect what is
   * given server-side.
   */
  DEFAULT_SUGGESTED_PRESENTATION_DELAY: {
    SMOOTH: 20,
    DASH: 15,
  },

  /**
   * Maximum time, in seconds, the player should automatically skip when stalled
   * because of a discontinuity in the downloaded range.
   */
  DISCONTINUITY_THRESHOLD: 1,

  /**
   * Time before the end of a video (in seconds) at which the player should
   * automatically stop.
   * It happens often that the video gets stuck 100 to 300 ms before the end,
   * especially on IE11 and Edge
   */
  END_OF_PLAY: 0.5,

  /**
   * Ratio used to know if an already loaded segment should be re-buffered.
   * We re-load the given segment if the current one times that ratio is
   * inferior to the new one.
   */
  BITRATE_REBUFFERING_RATIO: 1.5,

  BUFFER_GC_GAPS: {
    /**
     * _Low_ gap (from current position) from which the buffer will be _garbage
     * collected_ (read removed from the buffer).
     */
    CALM: 240,

    /**
     * _High_ gap (from current position) from which the buffer will be _garbage
     * collected_ (read removed from the buffer) if the low one does not clean
     * up any buffer.
     */
    BEEFY: 30,
  },

/**
 * The default number of times a pipeline request will be re-performed when
 * on error which justify a retry.
 * @type Number
 */
  DEFAULT_MAX_PIPELINES_RETRY_ON_ERROR: 4,

  // time changes interval in milliseconds
  SAMPLING_INTERVAL_MEDIASOURCE: 1000,
  SAMPLING_INTERVAL_NO_MEDIASOURCE: 500,

  /**
   * Minimum number of bytes sampled before we trust the estimate.
   * If we have not sampled much data, our estimate may not be accurate
   * enough to trust.
   * If bytesSampled_ is less than minTotalBytes_, we use defaultEstimate_.
   * This specific value is based on experimentation.
   * TODO re-calibrate for rx-player usecases?
   * @type {Number}
   */
  ABR_MINIMUM_TOTAL_BYTES: 128e3,

  /**
   * Minimum number of bytes, under which samples are discarded.
   * Our models do not include latency information, so connection startup time
   * (time to first byte) is considered part of the download time.
   * Because of this, we should ignore very small downloads which would cause our
   * estimate to be too low.
   * This specific value is based on experimentation.
   * TODO re-calibrate for rx-player usecases?
   * @type {Number}
   */
  ABR_MINIMUM_CHUNK_SIZE: 16e3,

  ABR_STARVATION_GAP: 5,
};
<commit_msg>config: add documentation<commit_after>/**
 * Copyright 2015 CANAL+ Group
 *
 * 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
 *
 *     http://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.
 */

export default {
  /**
   * Default audio track configuration, if none is set by the user.
   * Here in french for legacy reasons.
   */
  DEFAULT_AUDIO_TRACK: {
    language: "fra",
    audioDescription: false,
  },

  /**
   * Default text track configuration, if none is set by the user.
   */
  DEFAULT_TEXT_TRACK: null,

  /*
   * Default buffer goal in seconds
   */
  DEFAULT_WANTED_BUFFER_AHEAD: 30,

  /*
   * Default max buffer size ahead of the current position in seconds.
   * Set to Infinity for no limit.
   */
  DEFAULT_MAX_BUFFER_AHEAD: Infinity,

  /*
   * Default max buffer size ahead of the current position in seconds.
   * Set to Infinity for no limit.
   */
  DEFAULT_MAX_BUFFER_BEHIND: Infinity,

  /**
   * Default bitrate ceils initially set as the first content begins.
   *
   * If no track is found with a bitrate inferior or equal to the
   * bitrate there, the one with the lowest bitrate will be taken instead.
   *
   * Set to 0 for the lowest bitrate, Infinity for the highest.
   *
   * These values are only useful for the first content played, as consecutive
   * play will always take the last set one.
   */
  DEFAULT_INITIAL_BITRATES: {
    audio: 0,
    video: 0,
    other: 0, // tracks which are not audio/video
  },

  /**
   * Default bitrate ceil initially set to dictate the maximum bitrate the
   * ABR manager can automatically switch to.
   *
   * If no track is found with a quality inferior or equal to the
   * bitrate there, the lowest bitrate will be taken instead.
   *
   * Set to Infinity to discard any limit in the ABR strategy.
   */
  DEFAULT_MAX_BITRATES: {
    audio: Infinity,
    video: Infinity,
    other: Infinity, // tracks which are not audio/video
  },

  /**
   * buffer threshold ratio used as a lower bound
   * margin to find the suitable representation
   */
  DEFAULT_ADAPTIVE_BUFFER_THRESHOLD: 0.3,

  /**
   * Delay after which, if the page is hidden, the user is considered inactive
   * on the current video. Allow to enforce specific optimizations when the
   * page is not shown.
   * @see DEFAULT_THROTTLE_WHEN_HIDDEN
   */
  INACTIVITY_DELAY: 60 * 1000,

  /**
   * If true, if the player is in a "hidden" state for a delay specified by the
   * INACTIVITY DELAY config property, we throttle automatically to the video
   * representation with the lowest bitrate.
   */
  DEFAULT_THROTTLE_WHEN_HIDDEN: true,

  /**
   * If true, the video representations you can switch to in adaptive mode
   * are limited by the video element's width.
   */
  DEFAULT_LIMIT_VIDEO_WIDTH: true,

  /**
   * Default initial live gap considered if no presentation delay has been
   * suggested, in seconds.
   *
   * TODO this is never used, as every transport techno has a default
   * suggested presentation delay.
   */
  DEFAULT_LIVE_GAP: 15,

  /**
   * Default value for a manifest's suggested presentation delay if not
   * specified in the manifest.
   *
   * TODO this should not be in a manifest as it does not reflect what is
   * given server-side.
   */
  DEFAULT_SUGGESTED_PRESENTATION_DELAY: {
    SMOOTH: 20,
    DASH: 15,
  },

  /**
   * Maximum time, in seconds, the player should automatically skip when stalled
   * because of a discontinuity in the downloaded range.
   */
  DISCONTINUITY_THRESHOLD: 1,

  /**
   * Time before the end of a video (in seconds) at which the player should
   * automatically stop.
   * It happens often that the video gets stuck 100 to 300 ms before the end,
   * especially on IE11 and Edge
   */
  END_OF_PLAY: 0.5,

  /**
   * Ratio used to know if an already loaded segment should be re-buffered.
   * We re-load the given segment if the current one times that ratio is
   * inferior to the new one.
   */
  BITRATE_REBUFFERING_RATIO: 1.5,

  /**
   * Those are used when a "QuotaExceededError" error is received after
   * appending a new segment in the source buffer.
   *
   * This error can arise when the browser's buffer is considered full.
   * In this case, the player goes into manual garbage collection (GC) mode.
   */
  BUFFER_GC_GAPS: {
    /**
     * _Low_ gap (from current position) from which the buffer will be _garbage
     * collected_ (read removed from the buffer) when a QuotaExceededError is
     * received.
     * In seconds.
     * @type {Number}
     */
    CALM: 240,

    /**
     * _High_ gap (from current position) from which the buffer will be _garbage
     * collected_ (read removed from the buffer) when a QuotaExceededError is
     * received, if the low one does not clean up any buffer.
     * In seconds.
     * @type {Number}
     */
    BEEFY: 30,
  },

  /**
   * The default number of times a pipeline request will be re-performed when
   * on error which justify a retry.
   * @type Number
   */
  DEFAULT_MAX_PIPELINES_RETRY_ON_ERROR: 4,

  // time changes interval in milliseconds
  SAMPLING_INTERVAL_MEDIASOURCE: 1000,
  SAMPLING_INTERVAL_NO_MEDIASOURCE: 500,

  /**
   * Minimum number of bytes sampled before we trust the estimate.
   * If we have not sampled much data, our estimate may not be accurate
   * enough to trust.
   * If bytesSampled_ is less than minTotalBytes_, we use defaultEstimate_.
   * This specific value is based on experimentation.
   * @type {Number}
   */
  ABR_MINIMUM_TOTAL_BYTES: 128e3,

  /**
   * Minimum number of bytes, under which samples are discarded.
   * Our models do not include latency information, so connection startup time
   * (time to first byte) is considered part of the download time.
   * Because of this, we should ignore very small downloads which would cause our
   * estimate to be too low.
   * This specific value is based on experimentation.
   * @type {Number}
   */
  ABR_MINIMUM_CHUNK_SIZE: 16e3,

  /**
   * If a SourceBuffer has less than this amount of seconds ahead of the current
   * position in its buffer, the ABR manager will go into starvation mode.
   *
   * Under this mode, the time the next important request take will be checked
   * multiple times to detect when/if it takes too much time.
   * If the request is considered too long, the bitrate will be hastily
   * re-calculated from this single request.
   * @type {Number}
   */
  ABR_STARVATION_GAP: 5,
};
<|endoftext|>


<commit_before>module.exports = {
  token: process.env.TOKEN || '1234567890abcdef',
  settings: {
    webHook: {
      port: process.env.PORT || 443,
      host: process.env.HOST || '0.0.0.0'
    }
  },
  telegram: {
    port: 443,
    host: process.env.URL || 'https://rollrobot.herokuapp.com'
  },
  botan: {
    token: process.env.TOKEN || '1234abcd-12ab-12ab-12ab-1234567890ab'
  }
};
<commit_msg>:bug: Fix Botan token variable name<commit_after>module.exports = {
  token: process.env.TOKEN || '1234567890abcdef',
  settings: {
    webHook: {
      port: process.env.PORT || 443,
      host: process.env.HOST || '0.0.0.0'
    }
  },
  telegram: {
    port: 443,
    host: process.env.URL || 'https://rollrobot.herokuapp.com'
  },
  botan: {
    token: process.env.BOTAN || '1234abcd-12ab-12ab-12ab-1234567890ab'
  }
};
<|endoftext|>


<commit_before>module.exports = {

    // apply the env to a config object
    applyConfig : function (env, config, prefix) {

        Object.keys(env).forEach(function(key){
            if (key.indexOf(prefix) === 0) {
                var val = env[key];

                // strip off the prexif and then tokenize by '_'
                key = key.substring(prefix.length+1);// +1 for the _

                var parts = key.split('_');

                // set the value
                var place = config;

                parts.forEach(function (part, i) {
                    // if this is the last value in the path then just set it ...
                    if (i === parts.length - 1) {
                        place[part] = val;
                    } else {

                        // if an object for this part does not exist then create one
                        if (!place[part]) {
                            place[part] = {};
                        }

                        // move onto the next part...
                        place = place[part];
                    }
                });
            }
        });
    },

    // get a list of env vars to use to override these slots
    showVars : function (config, prefix) {
        var path = prefix;
        var that = this;
        Object.keys(config).forEach(function(prop){
            if (config[prop] instanceof Object) {
                that.showVars(config[prop], prefix+'_'+prop)
            } else {
                console.log(prefix+'_'+prop+'='+config[prop]);
            }
        });
    },

    // get the config for the module.  This is the result of applying all environment
    // variable to the config.yaml file for this module.
    config : function (configFile) {

        var yaml = require('js-yaml');
        var fs = require('fs');

        // if none is specified then assume /config.yaml
        if (configFile === undefined) {
            configFile = 'config.yaml';
        }

        // parse the YAML
        var conf = yaml.safeLoad(fs.readFileSync(configFile, 'utf-8'));

        // each project should have an application.name property
        var appName = conf.application.name;

        // apply the config
        this.applyConfig(process.env, conf, appName);

        return conf;
    }
};<commit_msg>Fix Sonar violations.<commit_after>module.exports = {

    // apply the env to a config object
    applyConfig : function (env, config, prefix) {

        Object.keys(env).forEach(function(key){
            if (key.indexOf(prefix) === 0) {
                var val = env[key];

                // Strip off the prefix and then tokenize by '_'.
                // Add 1 to prefix length for the '_' character.
                key = key.substring(prefix.length + 1);

                var parts = key.split('_');

                // set the value
                var place = config;

                parts.forEach(function (part, i) {
                    // if this is the last value in the path then just set it ...
                    if (i === parts.length - 1) {
                        place[part] = val;
                    } else {

                        // if an object for this part does not exist then create one
                        if (!place[part]) {
                            place[part] = {};
                        }

                        // move onto the next part...
                        place = place[part];
                    }
                });
            }
        });
    },

    // get a list of env vars to use to override these slots
    showVars : function (config, prefix) {
        var that = this;
        Object.keys(config).forEach(function(prop){
            if (config[prop] instanceof Object) {
                that.showVars(config[prop], prefix+'_'+prop);
            } else {
                console.log(prefix+'_'+prop+'='+config[prop]);
            }
        });
    },

    // get the config for the module.  This is the result of applying all environment
    // variable to the config.yaml file for this module.
    config : function (configFile) {

        var yaml = require('js-yaml');
        var fs = require('fs');

        // if none is specified then assume /config.yaml
        if (configFile === undefined) {
            configFile = 'config.yaml';
        }

        // parse the YAML
        var conf = yaml.safeLoad(fs.readFileSync(configFile, 'utf-8'));

        // each project should have an application.name property
        var appName = conf.application.name;

        // apply the config
        this.applyConfig(process.env, conf, appName);

        return conf;
    }
};
<|endoftext|>


<commit_before>// @flow

const Node = require('../../node')
const repl = require('repl')

module.exports = {
  command: 'repl',
  describe: 'start the aleph repl\n',
  handler: (opts: {directory: string}) => {
    const {directory} = opts

    repl.start('א > ')
  }
}
<commit_msg>More params, accept --dirInfo<commit_after>// @flow

const Node = require('../../node')
const Repl = require('repl')
const PeerId = require('peer-id')
const PeerInfo = require('peer-info')
const Identity = require('../../identity')
//const config = require('./config')

import type { MediachainNodeOptions } from '../../node'

module.exports = {
  command: 'repl',
  describe: 'start the aleph repl\n',
  builder: (yargs: Function) => {
    return yargs
      .option('dirInfo', {
        'alias': 'd',
        'type': 'string',
        'describe': 'directory to connect to',
        'demand': false
      })
      .help()
  },
  handler: (opts: {dirInfo: string}) => {
    const {dirInfo} = opts

    const options = bootstrap()
    const node = new Node(options)

    if(dirInfo !== undefined){
      // FIXME: this needs to actually parse the address
      node.setDirectory(dirInfo)
    }

    repl = Repl.start({
      'prompt': 'א > ',
      'useColors': true,
      'ignoreUndefined': true
    })
    repl.context.node = node
  }
}

function bootstrap(): MediachainNodeOptions {
  const options = {
    peerId: Identity.generateIdentity(),
    dirInfo: 'aleph client node'
  }

  return options
}
<|endoftext|>


<commit_before>function handleExternalScript () {
  const container = Docsify.dom.getNode('#main')
  const scripts = Docsify.dom.findAll(container, 'script')

  for (let i = scripts.length; i--;) {
    const script = scripts[i]

    if (script && script.src) {
      const newScript = document.createElement('script')

      ;['src', 'async', 'defer'].forEach(attribute => {
        newScript[attribute] = script[attribute]
      })

      script.parentNode.insertBefore(newScript, script)
      script.parentNode.removeChild(script)
    }
  }
}

const install = function (hook) {
  hook.doneEach(handleExternalScript)
}

window.$docsify.plugins = [].concat(install, window.$docsify.plugins)
<commit_msg>fix(external-script): script attrs<commit_after>function handleExternalScript () {
  const container = Docsify.dom.getNode('#main')
  const scripts = Docsify.dom.findAll(container, 'script')

  for (let i = scripts.length; i--;) {
    const script = scripts[i]

    if (script && script.src) {
      const newScript = document.createElement('script')

      Array.prototype.slice.call(script.attributes).forEach(attribute => {
        newScript[attribute.name] = attribute.value
      })

      script.parentNode.insertBefore(newScript, script)
      script.parentNode.removeChild(script)
    }
  }
}

const install = function (hook) {
  hook.doneEach(handleExternalScript)
}

window.$docsify.plugins = [].concat(install, window.$docsify.plugins)
<|endoftext|>