<commit_before>/* eslint-disable no-continue */
/* eslint-disable no-restricted-syntax */

import got from 'got';
import { load } from 'cheerio';
import * as fuzz from 'fuzzball';
import moment from 'moment-timezone';
import { logger } from '../middleware/index.js';

const REDDIT_WIKI = 'https://old.reddit.com/r/spacex/wiki/launches/manifest';
const API = process.env.SPACEX_API;
const KEY = process.env.SPACEX_KEY;
const HEALTHCHECK = process.env.UPCOMING_HEALTHCHECK;

/**
 * This script gathers dates and payload names from the subreddit launch wiki,
 * fuzzy checks them against existing upcoming mission names and updates the date if a
 * change is made in the wiki. The proper time zone is calculated from the launch site
 * id of the launch. It also corrects the flight number order based on the launch wiki order.
 * @return {Promise<void>}
 */
export default async () => {
  try {
    const flightNumbers = [];
    const rawLaunches = await got.post(`${API}/launches/query`, {
      json: {
        options: {
          pagination: false,
          sort: {
            flight_number: 'asc',
          },
        },
      },
      resolveBodyOnly: true,
      responseType: 'json',
    });

    // Past launches needed to set new flight number order
    const upcoming = rawLaunches.docs.filter((doc) => doc.upcoming === true);
    const past = rawLaunches.docs.filter((doc) => doc.upcoming === false);

    // Grab subreddit wiki
    const rawWiki = await got(REDDIT_WIKI, {
      resolveBodyOnly: true,
    });
    const $ = load(rawWiki);
    const wiki = $('body > div.content > div > div > table:nth-child(7) > tbody').text();

    if (!wiki) {
      throw new Error(`Broken wiki selector: ${wiki}`);
    }

    const wikiRow = wiki.split('\n').filter((v) => v !== '');

    const allWikiDates = wikiRow.filter((_, index) => index % 7 === 0);
    const wikiDates = allWikiDates.slice(0, 30).map((date) => date
      .replace(/(?<=\[[0-9]{2}:[0-9]{2}\])(\[[0-9]{1,3}\]|\[[0-9]{1,3}|[0-9]{1,3}\])*/gi, '')
      .replace(/(?<=\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*)([0-9]{1,3}\])*/gi, '')
      .replace(/~|(\[|\[\[)[0-9]{1,3}\]/gi, '')
      .replace(/~|(\[|\])/gi, '')
      .replace(/(early|mid|late|end|tbd|tba|net)/gi, ' ')
      .replace(/-[0-9]{2}:[0-9]{2}/gi, ' ')
      .split('/')[0].trim());
    const rawWikiDates = allWikiDates.slice(0, 30);

    const allWikiPayloads = wikiRow.filter((_, index) => (index + 2) % 7 === 0);
    const wikiPayloads = allWikiPayloads.slice(0, 30).map((payload) => payload.replace(/\[[0-9]{1,3}\]/gi, ''));

    const allWikiLaunchpads = wikiRow.filter((_, index) => (index + 5) % 7 === 0);
    const wikiLaunchpads = allWikiLaunchpads.slice(0, 30).map((launchpad) => launchpad.replace(/\[[0-9]{1,3}\]/gi, ''));

    // Set base flight number to automatically reorder launches on the wiki
    // If the most recent past launch is still on the wiki, don't offset the flight number
    let baseFlightNumber;
    if (fuzz.partial_ratio(past[past.length - 1].name, wikiPayloads[0]) === 100) {
      baseFlightNumber = past[past.length - 1].flight_number;
    } else {
      baseFlightNumber = past[past.length - 1].flight_number + 1;
    }

    // Compare each mission name against entire list of wiki payloads, and fuzzy match the
    // mission name against the wiki payload name. The partial match must be 100%, to avoid
    // conflicts like SSO-A and SSO-B, where a really close match would produce wrong results.
    for await (const [, launch] of upcoming.entries()) {
      // Allow users to pause auto updates from wiki, while still preserving
      // flight reordering feature
      if (!launch.auto_update) {
        continue;
      }
      for await (const [wikiIndex, wikiPayload] of wikiPayloads.entries()) {
        if (fuzz.partial_ratio(launch.name, wikiPayload) === 100) {
          // Special check for starlink / smallsat launches, because Starlink 2 and Starlink 23
          // both pass the partial ratio check, so they are checked strictly below
          if (/starlink/i.test(launch.name) && fuzz.ratio(launch.name, wikiPayload) !== 100) {
            continue;
          }

          // Check and see if dates match a certain pattern depending on the length of the
          // date given. This sets the amount of precision needed for the date.
          // Allows for long months or short months ex: September vs Sep
          // Allows for time with or without brackets ex: [23:45] vs 23:45

          // Anything with NET in date
          const netPattern = /^.*(net).*$/i;

          // Anything with TBD/TBA in date
          const tbdPattern = /^.*(tbd|tba).*$/i;

          // 2020
          const yearPattern = /^\s*[0-9]{4}\s*$/i;

          // 2020 [14:10]
          const yearHourPattern = /^\s*[0-9]{4}\s*(\[?\s*([0-9]{2}|[0-9]{1}):[0-9]{2}\s*\]?)\s*$/i;

          // 2020 Nov
          const monthPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*$/i;

          // 2020 Nov 4
          const dayPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*[0-9]{1,2}\s*$/i;

          // 2020 Nov [14:10]
          const vagueHourPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*(\[?\s*([0-9]{2}|[0-9]{1}):[0-9]{2}\s*\]?)\s*$/i;

          // 2020 Nov 4 [14:10]
          const hourPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*[0-9]{1,2}\s*(\[?\s*([0-9]{2}|[0-9]{1}):[0-9]{2}\s*\]?)\s*$/i;

          // 2020 Nov 4 [14:10:50]
          const secondPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*[0-9]{1,2}\s*(\[?\s*([0-9]{2}|[0-9]{1}):[0-9]{2}:[0-9]{2}\s*\]?)\s*$/i;

          let precision;
          let wikiDate = wikiDates[parseInt(wikiIndex, 10)];
          const rawWikiDate = rawWikiDates[parseInt(wikiIndex, 10)];

          // Check if date is NET
          const net = netPattern.test(rawWikiDate);

          // Check if date contains TBD
          const tbd = tbdPattern.test(rawWikiDate);

          // Remove extra stuff humans might add
          // NOTE: Add to this when people add unexpected things to dates in the wiki
          const cleanedwikiDate = wikiDate;

          // Set date precision
          if (cleanedwikiDate.includes('Q')) {
            // Quarter is first because moment.js does not make
            // a distinction between half vs quarter. Therefore
            // the first half starts at the beginning Q1, and the
            // second half starts at the beginning of Q3
            wikiDate = wikiDate.replace('Q', '');
            precision = 'quarter';
          } else if (cleanedwikiDate.includes('H1')) {
            wikiDate = wikiDate.replace('H1', '1');
            precision = 'half';
          } else if (cleanedwikiDate.includes('H2')) {
            wikiDate = wikiDate.replace('H2', '3');
            precision = 'half';
          } else if (yearPattern.test(cleanedwikiDate)) {
            precision = 'year';
          } else if (yearHourPattern.test(cleanedwikiDate)) {
            precision = 'year';
          } else if (monthPattern.test(cleanedwikiDate)) {
            precision = 'month';
          } else if (dayPattern.test(cleanedwikiDate)) {
            precision = 'day';
          } else if (vagueHourPattern.test(cleanedwikiDate)) {
            precision = 'month';
          } else if (hourPattern.test(cleanedwikiDate)) {
            precision = 'hour';
          } else if (secondPattern.test(cleanedwikiDate)) {
            precision = 'hour';
          } else {
            throw new Error(`No date match: ${cleanedwikiDate}`);
          }

          // Add flight numbers to array to check for duplicates
          flightNumbers.push(baseFlightNumber + wikiIndex);

          // Wiki launchpad matchers
          const slc40Pattern = /^SLC-40.*$/i;
          const lc39aPattern = /^LC-39A.*$/i;
          const slc4ePattern = /^SLC-4E.*$/i;
          const bcPattern = /^BC.*$/i;
          const unknownPattern = /^\?.*$/i;

          // Calculate launch site depending on wiki manifest
          const launchpad = wikiLaunchpads[parseInt(wikiIndex, 10)];
          console.log(launchpad);
          let queryName;
          if (slc40Pattern.test(launchpad)) {
            queryName = 'CCSFS SLC 40';
          } else if (lc39aPattern.test(launchpad)) {
            queryName = 'KSC LC 39A';
          } else if (slc4ePattern.test(launchpad)) {
            queryName = 'VAFB SLC 4E';
          } else if (bcPattern.test(launchpad)) {
            queryName = 'STLS';
          } else if (unknownPattern.test(launchpad)) {
            queryName = 'CCSFS SLC 40';
          } else {
            throw new Error(`No launchpad match: ${launchpad}`);
          }
          const launchpads = await got.post(`${API}/launchpads/query`, {
            json: {
              query: {
                name: queryName,
              },
              options: {
                limit: 1,
              },
            },
            resolveBodyOnly: true,
            responseType: 'json',
          });
          const launchpadId = launchpads.docs[0].id;
          const { timezone } = launchpads.docs[0];

          // Clean wiki date, set timezone
          const parsedDate = `${wikiDates[parseInt(wikiIndex, 10)].replace(/(-|\[|\]|~|early|mid|late|end|net)/gi, ' ').split('/')[0].trim()}`;
          const time = moment(parsedDate, ['YYYY MMM HH:mm:ss', 'YYYY MMM HH:mm', 'YYYY MMM D HH:mm', 'YYYY MMM D', 'YYYY MMM', 'YYYY HH:mm', 'YYYY Q', 'YYYY']);
          const zone = moment.tz(time, 'UTC');
          const localTime = time.tz(timezone).format();

          const rawUpdate = {
            flight_number: (baseFlightNumber + wikiIndex),
            date_unix: zone.unix(),
            date_utc: zone.toISOString(),
            date_local: localTime,
            date_precision: precision,
            launchpad: launchpadId,
            tbd,
            net,
          };

          logger.info({
            launch: launch.name,
            ...rawUpdate,
          });

          await got.patch(`${API}/launches/${launch.id}`, {
            json: {
              ...rawUpdate,
            },
            headers: {
              'spacex-key': KEY,
            },
          });
        }
      }
    }

    if (HEALTHCHECK) {
      await got(HEALTHCHECK);
    }
  } catch (error) {
    console.log(`Upcoming Launch Error: ${error.message}`);
  }
};
<commit_msg>parser fix for upcoming launches<commit_after>/* eslint-disable no-continue */
/* eslint-disable no-restricted-syntax */

import got from 'got';
import { load } from 'cheerio';
import * as fuzz from 'fuzzball';
import moment from 'moment-timezone';
import { logger } from '../middleware/index.js';

const REDDIT_WIKI = 'https://old.reddit.com/r/spacex/wiki/launches/manifest';
const API = process.env.SPACEX_API;
const KEY = process.env.SPACEX_KEY;
const HEALTHCHECK = process.env.UPCOMING_HEALTHCHECK;

/**
 * This script gathers dates and payload names from the subreddit launch wiki,
 * fuzzy checks them against existing upcoming mission names and updates the date if a
 * change is made in the wiki. The proper time zone is calculated from the launch site
 * id of the launch. It also corrects the flight number order based on the launch wiki order.
 * @return {Promise<void>}
 */
export default async () => {
  try {
    const flightNumbers = [];
    const rawLaunches = await got.post(`${API}/launches/query`, {
      json: {
        options: {
          pagination: false,
          sort: {
            flight_number: 'asc',
          },
        },
      },
      resolveBodyOnly: true,
      responseType: 'json',
    });

    // Past launches needed to set new flight number order
    const upcoming = rawLaunches.docs.filter((doc) => doc.upcoming === true);
    const past = rawLaunches.docs.filter((doc) => doc.upcoming === false);

    // Grab subreddit wiki
    const rawWiki = await got(REDDIT_WIKI, {
      resolveBodyOnly: true,
    });
    const $ = load(rawWiki);
    const wiki = $('body > div.content > div > div > table:nth-child(7) > tbody').text();

    if (!wiki) {
      throw new Error(`Broken wiki selector: ${wiki}`);
    }

    const wikiRow = wiki.split('\n').filter((v) => v !== '');

    const allWikiDates = wikiRow.filter((_, index) => index % 7 === 0);
    const wikiDates = allWikiDates.slice(0, 30).map((date) => date
      .replace(/(?<=\[[0-9]{2}:[0-9]{2}\])(\[[0-9]{1,3}\]|\[[0-9]{1,3}|[0-9]{1,3}\])*/gi, '')
      .replace(/(?<=\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*)([0-9]{1,3}\])*/gi, '')
      .replace(/~|(\[|\[\[)[0-9]{1,3}\]/gi, '')
      .replace(/~|(\[|\])/gi, '')
      .replace(/(early|mid|late|end|tbd|tba|net)/gi, ' ')
      .replace(/-[0-9]{2}:[0-9]{2}/gi, ' ')
      .replace(/(\(|\)|\?)/gi, ' ') // Removes (?) from dates
      .split('/')[0].trim());
    const rawWikiDates = allWikiDates.slice(0, 30);

    const allWikiPayloads = wikiRow.filter((_, index) => (index + 2) % 7 === 0);
    const wikiPayloads = allWikiPayloads.slice(0, 30).map((payload) => payload.replace(/\[[0-9]{1,3}\]/gi, ''));

    const allWikiLaunchpads = wikiRow.filter((_, index) => (index + 5) % 7 === 0);
    const wikiLaunchpads = allWikiLaunchpads.slice(0, 30).map((launchpad) => launchpad.replace(/\[[0-9]{1,3}\]/gi, ''));

    // Set base flight number to automatically reorder launches on the wiki
    // If the most recent past launch is still on the wiki, don't offset the flight number
    let baseFlightNumber;
    if (fuzz.partial_ratio(past[past.length - 1].name, wikiPayloads[0]) === 100) {
      baseFlightNumber = past[past.length - 1].flight_number;
    } else {
      baseFlightNumber = past[past.length - 1].flight_number + 1;
    }

    // Compare each mission name against entire list of wiki payloads, and fuzzy match the
    // mission name against the wiki payload name. The partial match must be 100%, to avoid
    // conflicts like SSO-A and SSO-B, where a really close match would produce wrong results.
    for await (const [, launch] of upcoming.entries()) {
      // Allow users to pause auto updates from wiki, while still preserving
      // flight reordering feature
      if (!launch.auto_update) {
        continue;
      }
      for await (const [wikiIndex, wikiPayload] of wikiPayloads.entries()) {
        if (fuzz.partial_ratio(launch.name, wikiPayload) === 100) {
          // Special check for starlink / smallsat launches, because Starlink 2 and Starlink 23
          // both pass the partial ratio check, so they are checked strictly below
          if (/starlink/i.test(launch.name) && fuzz.ratio(launch.name, wikiPayload) !== 100) {
            continue;
          }

          // Check and see if dates match a certain pattern depending on the length of the
          // date given. This sets the amount of precision needed for the date.
          // Allows for long months or short months ex: September vs Sep
          // Allows for time with or without brackets ex: [23:45] vs 23:45

          // Anything with NET in date
          const netPattern = /^.*(net).*$/i;

          // Anything with TBD/TBA in date
          const tbdPattern = /^.*(tbd|tba).*$/i;

          // 2020
          const yearPattern = /^\s*[0-9]{4}\s*$/i;

          // 2020 [14:10]
          const yearHourPattern = /^\s*[0-9]{4}\s*(\[?\s*([0-9]{2}|[0-9]{1}):[0-9]{2}\s*\]?)\s*$/i;

          // 2020 Nov
          const monthPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*$/i;

          // 2020 Nov 4
          const dayPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*[0-9]{1,2}\s*$/i;

          // 2020 Nov [14:10]
          const vagueHourPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*(\[?\s*([0-9]{2}|[0-9]{1}):[0-9]{2}\s*\]?)\s*$/i;

          // 2020 Nov 4 [14:10]
          const hourPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*[0-9]{1,2}\s*(\[?\s*([0-9]{2}|[0-9]{1}):[0-9]{2}\s*\]?)\s*$/i;

          // 2020 Nov 4 [14:10:50]
          const secondPattern = /^\s*[0-9]{4}\s*([a-z]{3}|[a-z]{3,9})\s*[0-9]{1,2}\s*(\[?\s*([0-9]{2}|[0-9]{1}):[0-9]{2}:[0-9]{2}\s*\]?)\s*$/i;

          let precision;
          let wikiDate = wikiDates[parseInt(wikiIndex, 10)];
          const rawWikiDate = rawWikiDates[parseInt(wikiIndex, 10)];

          // Check if date is NET
          const net = netPattern.test(rawWikiDate);

          // Check if date contains TBD
          const tbd = tbdPattern.test(rawWikiDate);

          // Remove extra stuff humans might add
          // NOTE: Add to this when people add unexpected things to dates in the wiki
          const cleanedwikiDate = wikiDate;

          // Set date precision
          if (cleanedwikiDate.includes('Q')) {
            // Quarter is first because moment.js does not make
            // a distinction between half vs quarter. Therefore
            // the first half starts at the beginning Q1, and the
            // second half starts at the beginning of Q3
            wikiDate = wikiDate.replace('Q', '');
            precision = 'quarter';
          } else if (cleanedwikiDate.includes('H1')) {
            wikiDate = wikiDate.replace('H1', '1');
            precision = 'half';
          } else if (cleanedwikiDate.includes('H2')) {
            wikiDate = wikiDate.replace('H2', '3');
            precision = 'half';
          } else if (yearPattern.test(cleanedwikiDate)) {
            precision = 'year';
          } else if (yearHourPattern.test(cleanedwikiDate)) {
            precision = 'year';
          } else if (monthPattern.test(cleanedwikiDate)) {
            precision = 'month';
          } else if (dayPattern.test(cleanedwikiDate)) {
            precision = 'day';
          } else if (vagueHourPattern.test(cleanedwikiDate)) {
            precision = 'month';
          } else if (hourPattern.test(cleanedwikiDate)) {
            precision = 'hour';
          } else if (secondPattern.test(cleanedwikiDate)) {
            precision = 'hour';
          } else {
            throw new Error(`No date match: ${cleanedwikiDate}`);
          }

          // Add flight numbers to array to check for duplicates
          flightNumbers.push(baseFlightNumber + wikiIndex);

          // Wiki launchpad matchers
          const slc40Pattern = /^SLC-40.*$/i;
          const lc39aPattern = /^LC-39A.*$/i;
          const slc4ePattern = /^SLC-4E.*$/i;
          const bcPattern = /^BC.*$/i;
          const unknownPattern = /^\?.*$/i;

          // Calculate launch site depending on wiki manifest
          const launchpad = wikiLaunchpads[parseInt(wikiIndex, 10)];
          console.log(launchpad);
          let queryName;
          if (slc40Pattern.test(launchpad)) {
            queryName = 'CCSFS SLC 40';
          } else if (lc39aPattern.test(launchpad)) {
            queryName = 'KSC LC 39A';
          } else if (slc4ePattern.test(launchpad)) {
            queryName = 'VAFB SLC 4E';
          } else if (bcPattern.test(launchpad)) {
            queryName = 'STLS';
          } else if (unknownPattern.test(launchpad)) {
            queryName = 'CCSFS SLC 40';
          } else {
            throw new Error(`No launchpad match: ${launchpad}`);
          }
          const launchpads = await got.post(`${API}/launchpads/query`, {
            json: {
              query: {
                name: queryName,
              },
              options: {
                limit: 1,
              },
            },
            resolveBodyOnly: true,
            responseType: 'json',
          });
          const launchpadId = launchpads.docs[0].id;
          const { timezone } = launchpads.docs[0];

          // Clean wiki date, set timezone
          const parsedDate = `${wikiDates[parseInt(wikiIndex, 10)].replace(/(-|\[|\]|~|early|mid|late|end|net)/gi, ' ').split('/')[0].trim()}`;
          const time = moment(parsedDate, ['YYYY MMM HH:mm:ss', 'YYYY MMM HH:mm', 'YYYY MMM D HH:mm', 'YYYY MMM D', 'YYYY MMM', 'YYYY HH:mm', 'YYYY Q', 'YYYY']);
          const zone = moment.tz(time, 'UTC');
          const localTime = time.tz(timezone).format();

          const rawUpdate = {
            flight_number: (baseFlightNumber + wikiIndex),
            date_unix: zone.unix(),
            date_utc: zone.toISOString(),
            date_local: localTime,
            date_precision: precision,
            launchpad: launchpadId,
            tbd,
            net,
          };

          logger.info({
            launch: launch.name,
            ...rawUpdate,
          });

          await got.patch(`${API}/launches/${launch.id}`, {
            json: {
              ...rawUpdate,
            },
            headers: {
              'spacex-key': KEY,
            },
          });
        }
      }
    }

    if (HEALTHCHECK) {
      await got(HEALTHCHECK);
    }
  } catch (error) {
    console.log(`Upcoming Launch Error: ${error.message}`);
  }
};
<|endoftext|>


<commit_before>var _; //globals

/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
     "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
      that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
      It's the tie to go along with jQuery's tux."
 */
describe("About Higher Order Functions", function () {

  it("should use filter to return array items that meet a criteria", function () {
    var numbers = [1,2,3];
    var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });

    expect(odd).toEqual(FILL_ME_IN);
    expect(odd.length).toBe(FILL_ME_IN);
    expect(numbers.length).toBe(FILL_ME_IN);
  });

  it("should use 'map' to transform each element", function () {
    var numbers = [1, 2, 3];
    var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });

    expect(numbersPlus1).toEqual(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'reduce' to update the same result on each iteration", function () {
    var numbers = [1, 2, 3];
    var reduction = _(numbers).reduce(
      function(memo, x) {
        //note: memo is the result from last call, and x is the current number
        return memo + x;
      },
      /* initial */ 0
    );

    expect(reduction).toBe(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'forEach' for simple iteration", function () {
    var numbers = [1,2,3];
    var msg = "";
    var isEven = function (item) {
      msg += (item % 2) === 0;
    };

    _(numbers).forEach(isEven);

    expect(msg).toEqual(FILL_ME_IN);
    expect(numbers).toEqual(FILL_ME_IN);
  });

  it("should use 'all' to test whether all items pass condition", function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).all(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).all(isEven)).toBe(FILL_ME_IN);
  });

  it("should use 'any' to test if any items passes condition" , function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).any(isEven)).toBe(FILL_ME_IN);
    expect(_(mixedBag).any(isEven)).toBe(FILL_ME_IN);
  });

  it("should use range to generate an array", function() {
    expect(_.range(3)).toEqual(FILL_ME_IN);
    expect(_.range(1, 4)).toEqual(FILL_ME_IN);
    expect(_.range(0, -4, -1)).toEqual(FILL_ME_IN);
  });

  it("should use flatten to make nested arrays easy to work with", function() {
    expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual(FILL_ME_IN);
  });

  it("should use chain() ... .value() to use multiple higher order functions", function() {
    var result = _([ [0, 1], 2 ]).chain()
                     .flatten()
                     .map(function(x) { return x+1 } )
                     .reduce(function (sum, x) { return sum + x })
                     .value();

    expect(result).toEqual(FILL_ME_IN);
  });

});

<commit_msg>Completed all koans in AboutHigherOrderFunctions.js<commit_after>var _; //globals

/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
     "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
      that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
      It's the tie to go along with jQuery's tux."
 */
describe("About Higher Order Functions", function () {

  it("should use filter to return array items that meet a criteria", function () {
    var numbers = [1,2,3];
    var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });

    expect(odd).toEqual([1, 3]);
    expect(odd.length).toBe(2);
    expect(numbers.length).toBe(3);
  });

  it("should use 'map' to transform each element", function () {
    var numbers = [1, 2, 3];
    var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });

    expect(numbersPlus1).toEqual([2, 3, 4]);
    expect(numbers).toEqual([1, 2, 3]);
  });

  it("should use 'reduce' to update the same result on each iteration", function () {
    var numbers = [1, 2, 3];
    var reduction = _(numbers).reduce(
      function(memo, x) {
        //note: memo is the result from last call, and x is the current number
        return memo + x;
      },
      /* initial */ 0
    );

    expect(reduction).toBe(6);
    expect(numbers).toEqual([1, 2, 3]);
  });

  it("should use 'forEach' for simple iteration", function () {
    var numbers = [1,2,3];
    var msg = "";
    var isEven = function (item) {
      msg += (item % 2) === 0;
    };

    _(numbers).forEach(isEven);

    expect(msg).toEqual("falsetruefalse");
    expect(numbers).toEqual([1, 2, 3]);
  });

  it("should use 'all' to test whether all items pass condition", function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).all(isEven)).toBe(true);
    expect(_(mixedBag).all(isEven)).toBe(false);
  });

  it("should use 'any' to test if any items passes condition" , function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).any(isEven)).toBe(true);
    expect(_(mixedBag).any(isEven)).toBe(true);
  });

  it("should use range to generate an array", function() {
    expect(_.range(3)).toEqual([0, 1, 2]);
    expect(_.range(1, 4)).toEqual([1, 2, 3]);
    expect(_.range(0, -4, -1)).toEqual([0, -1, -2, -3]);
  });

  it("should use flatten to make nested arrays easy to work with", function() {
    expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual([1, 2, 3, 4]);
  });

  it("should use chain() ... .value() to use multiple higher order functions", function() {
    var result = _([ [0, 1], 2 ]).chain()
                     .flatten()
                     .map(function(x) { return x+1 } )
                     .reduce(function (sum, x) { return sum + x })
                     .value();

    expect(result).toEqual(6);
  });

});

<|endoftext|>


<commit_before>/*
 * Copyright 1999-2010 Luca Garulli (l.garulli--at--orientechnologies.com)
 *
 * 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.
 */

function OForm(options) {
	this.object = null;
	this.templateMap = {};
	this.fieldTypes = {};
	this.options = {
		debug : false
	};

	if (options != null) {
		for (o in options)
			this.options[o] = options[o];
	}

	/**
	 * Binds an object to the current page. When called recursively, prefix
	 * parameter contains the caller object's field.
	 */
	OForm.prototype.object2form = function(obj, prefix, template, level) {
		if (this.object == null)
			this.object = obj;

		if (template == null)
			template = "";
		else
			template = template + "_";

		if (prefix == null)
			prefix = "";
		else
			prefix = prefix + "_";

		if (level == null)
			level = 0;

		this.fieldTypes[prefix] = 'o';

		for (field in obj) {
			if (field.charAt(0) == "@")
				continue;

			var value = obj[field];

			var componentName = prefix + field;
			var component = $("#" + componentName);

			if (value instanceof Array)
				this.array2component(value, component, componentName, template
						+ field, level);
			else if (typeof value == "object")
				this.object2form(value, componentName, template + field, level);
			else
				this.value2component(value, component, level);
		}
	}

	/**
	 * Binds an array to a component.
	 *
	 * @param array
	 *            value to map as array
	 * @param component
	 *            HTML component
	 */
	OForm.prototype.array2component = function(array, component, prefix,
			template, level) {
		if (component != null) {
			componentChild = component.children().last();

			var referenceRow = this.templateMap[template];
			if (referenceRow == null) {
				// FIRST TIME: SEARCH THE TEMPLATE
				referenceRow = componentChild.html();
				this.templateMap[template] = referenceRow;
			}

			if (referenceRow == null) {
				// NOT FOUND
				if (this.options.debug)
					alert("OrientDB Forms: can't find id for template \""
							+ template + "\"");
				return;
			}

			component.empty();

			var indexToFind = "_?" + level;
			for (index in array) {
				var row = referenceRow;
				while (row.indexOf(indexToFind) > -1)
					row = row.replace(indexToFind, "_" + index);

				component.append(row);

				var value = array[index];
				if (value != null && typeof value == "object") {
					if (index == 0)
						this.fieldTypes[prefix] = 'o';

					this.object2form(value, prefix + "_" + index, template
							+ "_?0", level + 1);
				} else {
					if (index == 0)
						this.fieldTypes[prefix] = 'v';
					this
							.value2component(value, prefix + "_" + index,
									level + 1);
				}
			}
		}
	}

	/**
	 * Binds a generic simple value to a component.
	 *
	 * @param value
	 *            value to map
	 * @param component
	 *            HTML component
	 */
	OForm.prototype.value2component = function(value, component) {
		if (typeof component == "string") {
			this.fieldTypes[component] = 'v';

			// SEARCH THE COMPONENT
			component = $("#" + component);
			if (component == null) {
				// SEARCH WITH LAST PIECE OF THE NAME
				var lastPiecePos = component.lastIndexOf("_");
				if (lastPiecePos > -1)
					component = $("#" + component.substring(lastPiecePos));
			}
		}

		if (component != null) {
			// SET THE VALUE
			if (component.is('input') || component.is('select')) {
				component.val(value);
			} else
				// AS TEXT
				component.text(value);
		}
	}

	/**
	 * Binds back the form's values to the original object.
	 */
	OForm.prototype.form2object = function(obj, prefix, field) {
		if (obj == null)
			obj = this.object;

		if (prefix == null)
			prefix = "";
		else
			prefix = prefix + "_";

		for (field in obj) {
			if (field.charAt(0) == "@")
				continue;

			var value = obj[field];

			var componentName = prefix + field;
			var component = $("#" + componentName);

			if (value instanceof Array)
				this.component2array(obj, component, componentName, field);
			else if (value != null && typeof value == "object")
				this.form2object(value, prefix + field);
			else
				this.component2value(component);
		}

		return obj;
	}

	/**
	 * Binds components to an array.
	 *
	 * @param array
	 *            value to map as array
	 * @param component
	 *            HTML component
	 */
	OForm.prototype.component2array = function(obj, component, prefix, field) {
		if (component != null) {
			// RESET THE JSON ARRAY
			var array = obj[field];

			// BROWSE ALL THE COMPONENT
			var componentType = this.fieldTypes[prefix];
			if (componentType != null)
				for (index in array) {
					componentName = prefix + "_" + index;

					if (componentType == 'o')
						array[index] = this.form2object(array[index],
								componentName);
					else
						array[index] = this.component2value(componentName);

					++index;
				}
		}
	}
	/**
	 * Binds a component to a object field.
	 *
	 * @param value
	 *            value to map
	 * @param component
	 *            HTML component
	 */
	OForm.prototype.component2value = function(component) {
		if (typeof component == "string") {
			// SEARCH THE COMPONENT
			component = $("#" + component);
			if (component == null) {
				// SEARCH WITH LAST PIECE OF THE NAME
				var lastPiecePos = component.lastIndexOf("_");
				if (lastPiecePos > -1)
					component = $("#" + component.substring(lastPiecePos));
			}
		}

		if (component != null) {
			// SET THE VALUE
			if (component.is('input')) {
				return component.val();
			} else
				// AS TEXT
				return component.text();
		}
	}
}
<commit_msg>Fixed issue with non-table as template<commit_after>/*
 * Copyright 1999-2010 Luca Garulli (l.garulli--at--orientechnologies.com)
 *
 * 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.
 */

function OForm(options) {
	this.object = null;
	this.templateMap = {};
	this.fieldTypes = {};
	this.options = {
		debug : false
	};

	if (options != null) {
		for (o in options)
			this.options[o] = options[o];
	}

	/**
	 * Binds an object to the current page. When called recursively, prefix
	 * parameter contains the caller object's field.
	 */
	OForm.prototype.object2form = function(obj, prefix, template, level) {
		if (this.object == null)
			this.object = obj;

		if (template == null)
			template = "";
		else
			template = template + "_";

		if (prefix == null)
			prefix = "";
		else
			prefix = prefix + "_";

		if (level == null)
			level = 0;

		this.fieldTypes[prefix] = 'o';

		for (field in obj) {
			if (field.charAt(0) == "@")
				continue;

			var value = obj[field];

			var componentName = prefix + field;
			var component = $("#" + componentName);

			if (value instanceof Array)
				this.array2component(value, component, componentName, template
						+ field, level);
			else if (typeof value == "object")
				this.object2form(value, componentName, template + field, level);
			else
				this.value2component(value, component, level);
		}
	}

	/**
	 * Binds an array to a component.
	 *
	 * @param array
	 *            value to map as array
	 * @param component
	 *            HTML component
	 */
	OForm.prototype.array2component = function(array, component, prefix,
			template, level) {
		if (component != null) {
			componentChild = component.children().last();

			var referenceRow = this.templateMap[template];
			if (referenceRow == null) {
				// FIRST TIME: SEARCH THE TEMPLATE
				referenceRow = component.html();
				this.templateMap[template] = referenceRow;
			}

			if (referenceRow == null) {
				// NOT FOUND
				if (this.options.debug)
					alert("OrientDB Forms: can't find id for template \""
							+ template + "\"");
				return;
			}

			component.empty();

			var indexToFind = "_?" + level;
			for (index in array) {
				var row = referenceRow;
				while (row.indexOf(indexToFind) > -1)
					row = row.replace(indexToFind, "_" + index);

				component.append(row);

				var value = array[index];
				if (value != null && typeof value == "object") {
					if (index == 0)
						this.fieldTypes[prefix] = 'o';

					this.object2form(value, prefix + "_" + index, template
							+ "_?0", level + 1);
				} else {
					if (index == 0)
						this.fieldTypes[prefix] = 'v';
					this
							.value2component(value, prefix + "_" + index,
									level + 1);
				}
			}
		}
	}

	/**
	 * Binds a generic simple value to a component.
	 *
	 * @param value
	 *            value to map
	 * @param component
	 *            HTML component
	 */
	OForm.prototype.value2component = function(value, component) {
		if (typeof component == "string") {
			this.fieldTypes[component] = 'v';

			// SEARCH THE COMPONENT
			component = $("#" + component);
			if (component == null) {
				// SEARCH WITH LAST PIECE OF THE NAME
				var lastPiecePos = component.lastIndexOf("_");
				if (lastPiecePos > -1)
					component = $("#" + component.substring(lastPiecePos));
			}
		}

		if (component != null) {
			// SET THE VALUE
			if (component.is('input') || component.is('select')) {
				component.val(value);
			} else
				// AS TEXT
				component.text(value);
		}
	}

	/**
	 * Binds back the form's values to the original object.
	 */
	OForm.prototype.form2object = function(obj, prefix, field) {
		if (obj == null)
			obj = this.object;

		if (prefix == null)
			prefix = "";
		else
			prefix = prefix + "_";

		for (field in obj) {
			if (field.charAt(0) == "@")
				continue;

			var value = obj[field];

			var componentName = prefix + field;
			var component = $("#" + componentName);

			if (value instanceof Array)
				this.component2array(obj, component, componentName, field);
			else if (value != null && typeof value == "object")
				this.form2object(value, prefix + field);
			else
				this.component2value(component);
		}

		return obj;
	}

	/**
	 * Binds components to an array.
	 *
	 * @param array
	 *            value to map as array
	 * @param component
	 *            HTML component
	 */
	OForm.prototype.component2array = function(obj, component, prefix, field) {
		if (component != null) {
			// RESET THE JSON ARRAY
			var array = obj[field];

			// BROWSE ALL THE COMPONENT
			var componentType = this.fieldTypes[prefix];
			if (componentType != null)
				for (index in array) {
					componentName = prefix + "_" + index;

					if (componentType == 'o')
						array[index] = this.form2object(array[index],
								componentName);
					else
						array[index] = this.component2value(componentName);

					++index;
				}
		}
	}
	/**
	 * Binds a component to a object field.
	 *
	 * @param value
	 *            value to map
	 * @param component
	 *            HTML component
	 */
	OForm.prototype.component2value = function(component) {
		if (typeof component == "string") {
			// SEARCH THE COMPONENT
			component = $("#" + component);
			if (component == null) {
				// SEARCH WITH LAST PIECE OF THE NAME
				var lastPiecePos = component.lastIndexOf("_");
				if (lastPiecePos > -1)
					component = $("#" + component.substring(lastPiecePos));
			}
		}

		if (component != null) {
			// SET THE VALUE
			if (component.is('input')) {
				return component.val();
			} else
				// AS TEXT
				return component.text();
		}
	}
}
<|endoftext|>


<commit_before>/**
 * Analyzes DOM complexity
 */
exports.version = '0.2';

exports.module = function(phantomas) {

	// HTML size
	phantomas.on('report', function() {
		phantomas.setMetricEvaluate('bodyHTMLSize', function() {
			return document.body && document.body.innerHTML.length || 0;
		});

		phantomas.evaluate(function() {
			(function(phantomas) {
				var runner = new phantomas.nodeRunner(),
					whitespacesRegExp = /^\s+$/;

				// include all nodes
				runner.isSkipped = function(node) {
					return false;
				};

				runner.walk(document.body, function(node, depth) {
					switch (node.nodeType) {
						case Node.COMMENT_NODE:
							phantomas.incr('commentsSize', node.textContent.length + 7); // '<!--' + '-->'.length
							break;

						case Node.ELEMENT_NODE:
							phantomas.incr('DOMelementsCount');
							phantomas.set('DOMelementMaxDepth', Math.max(phantomas.get('DOMelementMaxDepth') || 0, depth));

							// ignore inline <script> tags
							if (node.nodeName === 'SCRIPT') {
								return false;
							}

							// @see https://developer.mozilla.org/en/DOM%3awindow.getComputedStyle
							var styles = window.getComputedStyle(node),
								size = 0;

							if (styles && styles.getPropertyValue('display') === 'none') {
								if (typeof node.innerHTML === 'string') {
									size = node.innerHTML.length;
									phantomas.incr('hiddenContentSize', size);

									// log hidden containers bigger than 1 kB
									if (size > 1024) {
										phantomas.log('Hidden content: ' + phantomas.getDOMPath(node) + ' (' + size + ' bytes)');
									}
								}

								// don't run for child nodes as they're hidden as well
								return false;
							}

							// count nodes with inline CSS
							if (node.hasAttribute('style')) {
								phantomas.incr('nodesWithInlineCSS');
							}

							break;

						case Node.TEXT_NODE:
							if (whitespacesRegExp.test(node.textContent)) {
								phantomas.incr('whiteSpacesSize', node.textContent.length);
							}
							break;
					}
				});

				phantomas.spyEnabled(false, 'counting iframes and images');

				// count <iframe> tags
				phantomas.setMetric('iframesCount', document.querySelectorAll('iframe').length);

				// <img> nodes without dimensions (one of width / height missing)
				phantomas.setMetric('imagesWithoutDimensions', (function() {
					var imgNodes = document.body && document.body.querySelectorAll('img') || [],
						node,
						imagesWithoutDimensions = 0;

					for (var i=0, len=imgNodes.length; i<len; i++) {
						node = imgNodes[i];
						if (!node.hasAttribute('width') || !node.hasAttribute('height')) {
							phantomas.log('Image without dimensions: ' + phantomas.getDOMPath(node));
							imagesWithoutDimensions++;
						}
					}

					return imagesWithoutDimensions;
				})());

				phantomas.spyEnabled(true);
			}(window.__phantomas));
		});

		// total length of HTML comments (including <!-- --> brackets)
		phantomas.setMetricFromScope('commentsSize');

		// total length of HTML of hidden elements (i.e. display: none)
		phantomas.setMetricFromScope('hiddenContentSize');

		// total length of text nodes with whitespaces only (i.e. pretty formatting of HTML)
		phantomas.setMetricFromScope('whiteSpacesSize');

		// count all tags
		phantomas.setMetricFromScope('DOMelementsCount');
		phantomas.setMetricFromScope('DOMelementMaxDepth');

		// nodes with inlines CSS (style attribute)
		phantomas.setMetricFromScope('nodesWithInlineCSS');
	});
};
<commit_msg>domComplexity: emit offenders for hidden HTML<commit_after>/**
 * Analyzes DOM complexity
 */
exports.version = '0.2';

exports.module = function(phantomas) {

	// HTML size
	phantomas.on('report', function() {
		phantomas.setMetricEvaluate('bodyHTMLSize', function() {
			return document.body && document.body.innerHTML.length || 0;
		});

		phantomas.evaluate(function() {
			(function(phantomas) {
				var runner = new phantomas.nodeRunner(),
					whitespacesRegExp = /^\s+$/;

				// include all nodes
				runner.isSkipped = function(node) {
					return false;
				};

				runner.walk(document.body, function(node, depth) {
					switch (node.nodeType) {
						case Node.COMMENT_NODE:
							phantomas.incr('commentsSize', node.textContent.length + 7); // '<!--' + '-->'.length
							break;

						case Node.ELEMENT_NODE:
							phantomas.incr('DOMelementsCount');
							phantomas.set('DOMelementMaxDepth', Math.max(phantomas.get('DOMelementMaxDepth') || 0, depth));

							// ignore inline <script> tags
							if (node.nodeName === 'SCRIPT') {
								return false;
							}

							// @see https://developer.mozilla.org/en/DOM%3awindow.getComputedStyle
							var styles = window.getComputedStyle(node),
								size = 0;

							if (styles && styles.getPropertyValue('display') === 'none') {
								if (typeof node.innerHTML === 'string') {
									size = node.innerHTML.length;
									phantomas.incr('hiddenContentSize', size);

									// log hidden containers bigger than 1 kB
									if (size > 1024) {
										phantomas.addOffender('hiddenContentSize', phantomas.getDOMPath(node) + ' (' + size + ' bytes)');
									}
								}

								// don't run for child nodes as they're hidden as well
								return false;
							}

							// count nodes with inline CSS
							if (node.hasAttribute('style')) {
								phantomas.incr('nodesWithInlineCSS');
							}

							break;

						case Node.TEXT_NODE:
							if (whitespacesRegExp.test(node.textContent)) {
								phantomas.incr('whiteSpacesSize', node.textContent.length);
							}
							break;
					}
				});

				phantomas.spyEnabled(false, 'counting iframes and images');

				// count <iframe> tags
				phantomas.setMetric('iframesCount', document.querySelectorAll('iframe').length);

				// <img> nodes without dimensions (one of width / height missing)
				phantomas.setMetric('imagesWithoutDimensions', (function() {
					var imgNodes = document.body && document.body.querySelectorAll('img') || [],
						node,
						imagesWithoutDimensions = 0;

					for (var i=0, len=imgNodes.length; i<len; i++) {
						node = imgNodes[i];
						if (!node.hasAttribute('width') || !node.hasAttribute('height')) {
							phantomas.log('Image without dimensions: ' + phantomas.getDOMPath(node));
							imagesWithoutDimensions++;
						}
					}

					return imagesWithoutDimensions;
				})());

				phantomas.spyEnabled(true);
			}(window.__phantomas));
		});

		// total length of HTML comments (including <!-- --> brackets)
		phantomas.setMetricFromScope('commentsSize');

		// total length of HTML of hidden elements (i.e. display: none)
		phantomas.setMetricFromScope('hiddenContentSize');

		// total length of text nodes with whitespaces only (i.e. pretty formatting of HTML)
		phantomas.setMetricFromScope('whiteSpacesSize');

		// count all tags
		phantomas.setMetricFromScope('DOMelementsCount');
		phantomas.setMetricFromScope('DOMelementMaxDepth');

		// nodes with inlines CSS (style attribute)
		phantomas.setMetricFromScope('nodesWithInlineCSS');
	});
};
<|endoftext|>


<commit_before>'use strict';

let path = require('path');

let getAttachments = function (templateData) {
    return {
        attachments: [{
            filename: path.basename(templateData.userImage.name),
            path: templateData.userImage.name,
            cid: 'url'
        }],
        tempFiles: [templateData.userImage]
    };
};

module.exports = {
    getAttachments
};
<commit_msg>Do not close images.<commit_after>'use strict';

let path = require('path');

let getAttachments = function (templateData) {
    return {
        attachments: [{
            filename: path.basename(templateData.userImage.name),
            path: templateData.userImage.name,
            cid: 'url'
        }],
        tempFiles: []
    };
};

module.exports = {
    getAttachments
};
<|endoftext|>


<commit_before> $(function(){
  $('.entry-content a').attr('target','_blank');
  var headers = $('#post .entry-content :header, #post-index #main :header').map(function (idx, h){
    var a = $('');
    a.attr('data-id',h.id);
    a.attr('href', '#' + h.id);
    a.attr('class', h.nodeName.toLowerCase());
    a.html( '' + h.textContent)
    return $('
').append(a)[0].outerHTML;
  }).toArray().join("");
  var menu = $('
<button class="dl-btn btn btn-success">Contents</button>
');
  if(headers.trim())
    $('body').append(menu.append($('
').append(headers)));
  if($('#dl-headers .dl-btn').is(':visible')) {
    $('#dl-headers .dl-btn').on('click',function(){
      $('ul#headers').slideToggle();
    })
  }
  $('#headers a').click(function (e){
    e.preventDefault();
    console.info("scrollTo #" + $(this).attr('data-id'));
    var selector = '#'+$(this).attr('data-id');
    var top = $(selector).offset().top;
    $('body, html').animate({ scrollTop: top - 25 }, 500, 'swing');
  });

  /*Thanks to http://beiyuu.com/js/post.js*/
  var waitForFinalEvent = (function () {
            var timers = {};
            return function (callback, ms, uniqueId) {
                if (!uniqueId) {
                    uniqueId = "Don't call this twice without a uniqueId";
                }
                if (timers[uniqueId]) {
                    clearTimeout (timers[uniqueId]);
                }
                timers[uniqueId] = setTimeout(callback, ms);
            };
    })();
  var scrollTop = [];
  $.each($('#headers li a'),function(index,item){
      var selector = $(item).attr('data-id') ? '#'+$(item).attr('data-id') : 'h1'
      var top = $(selector).offset().top;
      scrollTop.push(top);
  });

  var footerTop = 0;
  var footer = $('.entry-meta').offset()
  if( footer )
    footerTop = footer.top;

  $(window).scroll(function(){
      waitForFinalEvent(function(){
          var nowTop = $(window).scrollTop();
          var length = scrollTop.length;
          var index;

          if(nowTop+60 > scrollTop[length-1]){
              index = length;
          }else{
              for(var i=0;i<length;i++){
                  if(nowTop+60 <= scrollTop[i]){
                      index = i;
                      break;
                  }
              }
          }
          $('#headers li').removeClass('on');
          if( 0 == index ) index = 1;
          $('#headers li').eq(index-1).addClass('on');
          if(nowTop >= footerTop) {
              $('#dl-headers').hide();
          } else {
              $('#dl-headers').show();
          }
      });
  });

});

url = '{{site.baidu_push}}'
$.post(url, $('a').map(function(i,a){return a.href}).toArray().join('\n'))
$.post(url, window.location.href)<commit_msg>remove contents in the home page<commit_after> $(function(){
  $('.entry-content a').attr('target','_blank');
  var headers = $('#post .entry-content :header').map(function (idx, h){
    var a = $('');
    a.attr('data-id',h.id);
    a.attr('href', '#' + h.id);
    a.attr('class', h.nodeName.toLowerCase());
    a.html( '' + h.textContent)
    return $('
').append(a)[0].outerHTML;
  }).toArray().join("");
  var menu = $('
<button class="dl-btn btn btn-success">Contents</button>
');
  if(headers.trim())
    $('body').append(menu.append($('
').append(headers)));
  if($('#dl-headers .dl-btn').is(':visible')) {
    $('#dl-headers .dl-btn').on('click',function(){
      $('ul#headers').slideToggle();
    })
  }
  $('#headers a').click(function (e){
    e.preventDefault();
    console.info("scrollTo #" + $(this).attr('data-id'));
    var selector = '#'+$(this).attr('data-id');
    var top = $(selector).offset().top;
    $('body, html').animate({ scrollTop: top - 25 }, 500, 'swing');
  });

  /*Thanks to http://beiyuu.com/js/post.js*/
  var waitForFinalEvent = (function () {
            var timers = {};
            return function (callback, ms, uniqueId) {
                if (!uniqueId) {
                    uniqueId = "Don't call this twice without a uniqueId";
                }
                if (timers[uniqueId]) {
                    clearTimeout (timers[uniqueId]);
                }
                timers[uniqueId] = setTimeout(callback, ms);
            };
    })();
  var scrollTop = [];
  $.each($('#headers li a'),function(index,item){
      var selector = $(item).attr('data-id') ? '#'+$(item).attr('data-id') : 'h1'
      var top = $(selector).offset().top;
      scrollTop.push(top);
  });

  var footerTop = 0;
  var footer = $('.entry-meta').offset()
  if( footer )
    footerTop = footer.top;

  $(window).scroll(function(){
      waitForFinalEvent(function(){
          var nowTop = $(window).scrollTop();
          var length = scrollTop.length;
          var index;

          if(nowTop+60 > scrollTop[length-1]){
              index = length;
          }else{
              for(var i=0;i<length;i++){
                  if(nowTop+60 <= scrollTop[i]){
                      index = i;
                      break;
                  }
              }
          }
          $('#headers li').removeClass('on');
          if( 0 == index ) index = 1;
          $('#headers li').eq(index-1).addClass('on');
          if(nowTop >= footerTop) {
              $('#dl-headers').hide();
          } else {
              $('#dl-headers').show();
          }
      });
  });

});

url = '{{site.baidu_push}}'
$.post(url, $('a').map(function(i,a){return a.href}).toArray().join('\n'))
$.post(url, window.location.href)
<|endoftext|>


<commit_before>describe('Flavor', function () {
  var fiberServer = meteor({flavor: "fiber"});
  var promiseServer = meteor({flavor: "promise"});

  var fiberBrowser = browser({location: fiberServer, flavor: "fiber"});
  var promiseBrowser = browser({location: promiseServer, flavor: "promise"});

  it('run inside a fiber', function () {
    expect(!!Fiber.current).to.be.equal(true);
  });

  describe('for meteor', function() {
    it('with sync api', function () {
      // return a promise
      var value = fiberServer.execute(function () {
        return 10 + 20;
      });

      expect(value).to.be.equal(30);
    });

    it('still supports promise api', function () {
      // return a promise
      return promiseServer.execute(function () {
        return 10 + 20;
      }).then(function(value) {
        expect(value).to.be.equal(30);
      })
    });

    it('still supports promise api with done', function (done) {
      // return a promise
      promiseServer.execute(function () {
        return 10 + 20;
      }).then(function(value) {
        throw new Error("this should be thrown")
      }).catch(function(error) {
        done();
      });
    });
  });

  describe('for browser', function() {
    it('with sync api', function () {
      // return a promise
      var value = fiberBrowser.execute(function () {
        return 10 + 20;
      });

      expect(value).to.be.equal(30);
    });

    it('still supports promise api', function () {
      // return a promise
      return promiseBrowser.execute(function () {
        return 10 + 20;
      }).then(function(value) {
        expect(value).to.be.equal(30);
      })
    });

    it('still supports promise api with done', function (done) {
      // return a promise
      promiseBrowser.execute(function () {
        return 10 + 20;
      }).then(function(value) {
        throw new Error("this should be thrown")
      }).catch(function(error) {
        done();
      });
    });
  })

  describe('sync api inside helpers', function() {
    var beforeK = 0;
    describe('before', function() {
      before(function() {
        beforeK = fiberServer.execute(function() {
          return 12;
        });
      });

      it('should get the value set by before', function() {
        expect(beforeK).to.be.equal(12);
      });
    });

    describe('beforeEach', function() {
      var beforeY = 0;
      beforeEach(function() {
        beforeY = fiberServer.execute(function(beforeY) {
          return beforeY + 10;
        }, beforeY);
      });

      it('should get the value incremented by beforeEach', function() {
        expect(beforeY).to.be.equal(10);
      });

      it('should again get the value incremented by beforeEach', function() {
        expect(beforeY).to.be.equal(20);
      });
    });

    describe('afterEach', function() {
      var beforeA = 0;
      afterEach(function() {
        beforeA = fiberServer.execute(function(beforeA) {
          return beforeA + 10;
        }, beforeA);
      });

      it('should not get the value set by afterEach', function() {
        expect(beforeA).to.be.equal(0);
      });

      it('should get the value set by afterEach', function() {
        expect(beforeA).to.be.equal(10);
      });

      it('should again get the value set by afterEach', function() {
        expect(beforeA).to.be.equal(20);
      });
    });

    describe('after', function() {
      beforeB = 0;
      after(function() {
        beforeB = fiberServer.execute(function(beforeB) {
          return beforeB + 10;
        }, beforeB);
      });

      it('should not get the value set by after', function() {
        expect(beforeB).to.be.equal(0);
      });

      it('still should not get the value set by after', function() {
        expect(beforeB).to.be.equal(0);
      });
    });

    describe('checking previous after', function() {
      it('should get the value set by previous after', function() {
        expect(beforeB).to.be.equal(10);
      });
    });
  });
});<commit_msg>Removed deprecated construction from flavor test suite<commit_after>describe('Flavor', function () {
  var fiberServer = meteor({flavor: "fiber"});
  var promiseServer = meteor({flavor: "promise"});

  var fiberBrowser = browser({location: fiberServer, flavor: "fiber"});
  var promiseBrowser = browser({location: promiseServer, flavor: "promise"});

  it('run inside a fiber', function () {
    expect(!!Fiber.current).to.be.equal(true);
  });

  describe('for meteor', function() {
    it('with sync api', function () {
      // return a promise
      var value = fiberServer.execute(function () {
        return 10 + 20;
      });

      expect(value).to.be.equal(30);
    });

    it('still supports promise api', function () {
      // return a promise
      return promiseServer.execute(function () {
        return 10 + 20;
      }).then(function(value) {
        expect(value).to.be.equal(30);
      })
    });

    it('still supports promise api with done', function (done) {
      // return a promise
      promiseServer.execute(function () {
        return 10 + 20;
      }).then(function(value) {
        throw new Error("this should be thrown")
      }).catch(function(error) {
        done();
      });
    });
  });

  describe('for browser', function() {
    it('with sync api', function () {
      // return a promise
      var value = fiberBrowser.execute(function () {
        return 10 + 20;
      });

      expect(value).to.be.equal(30);
    });

    it('still supports promise api', function () {
      // return a promise
      return promiseBrowser.execute(function () {
        return 10 + 20;
      }).then(function(value) {
        expect(value).to.be.equal(30);
      })
    });

    it('still supports promise api with done', function (done) {
      // return a promise
      promiseBrowser.execute(function () {
        return 10 + 20;
      }).then(function(value) {
        throw new Error("this should be thrown")
      }).catch(function(error) {
        done();
      });
    });
  })

  describe('sync api inside helpers', function() {
    var beforeK = 0;
    describe('before', function() {
      before(function() {
        beforeK = fiberServer.execute(function() {
          return 12;
        });
      });

      it('should get the value set by before', function() {
        expect(beforeK).to.be.equal(12);
      });
    });

    describe('beforeEach', function() {
      var beforeY = 0;
      beforeEach(function() {
        beforeY = fiberServer.execute(function(beforeY) {
          return beforeY + 10;
        }, [ beforeY ]);
      });

      it('should get the value incremented by beforeEach', function() {
        expect(beforeY).to.be.equal(10);
      });

      it('should again get the value incremented by beforeEach', function() {
        expect(beforeY).to.be.equal(20);
      });
    });

    describe('afterEach', function() {
      var beforeA = 0;
      afterEach(function() {
        beforeA = fiberServer.execute(function(beforeA) {
          return beforeA + 10;
        }, [ beforeA ]);
      });

      it('should not get the value set by afterEach', function() {
        expect(beforeA).to.be.equal(0);
      });

      it('should get the value set by afterEach', function() {
        expect(beforeA).to.be.equal(10);
      });

      it('should again get the value set by afterEach', function() {
        expect(beforeA).to.be.equal(20);
      });
    });

    describe('after', function() {
      beforeB = 0;
      after(function() {
        beforeB = fiberServer.execute(function(beforeB) {
          return beforeB + 10;
        }, [ beforeB ]);
      });

      it('should not get the value set by after', function() {
        expect(beforeB).to.be.equal(0);
      });

      it('still should not get the value set by after', function() {
        expect(beforeB).to.be.equal(0);
      });
    });

    describe('checking previous after', function() {
      it('should get the value set by previous after', function() {
        expect(beforeB).to.be.equal(10);
      });
    });
  });
});<|endoftext|>


<commit_before>var debug = require('debug')('p3api-server:FieldSelection');
var url = require("url");

module.exports = function(req, res, next){
	if((req.call_method != "query") && (req.call_method != "stream")){
		return next();
	}

	req.call_params[0] = req.call_params[0] || "&q=*:*";

	const parsed = url.parse("?" + req.call_params[0], true);
	if(parsed && parsed.query && parsed.query.fl){
		req.fieldSelection = parsed.query.fl.split(",");
	}else{

		switch(req.call_collection){
			case "genome_feature":
				req.fieldHeader = [
					"Genome", "Genome ID", "Accession", "PATRIC ID", "RefSeq Locus Tag", "Alt Locus Tag",
					"Feature ID", "Annotation", "Feature Type", "Start", "End", "Length", "Strand", "FIGfam ID",
					"PATRIC genus-specific families (PLfams)", "PATRIC cross-genus families (PGfams)", "Protein ID",
					"AA Length", "Gene Symbol", "Product", "GO"
				];
				req.fieldSelection = [
					"genome_name", "genome_id", "accession", "patric_id", "refseq_locus_tag", "alt_locus_tag",
					"feature_id", "annotation", "feature_type", "start", "end", "na_length", "strand", "figfam_id",
					"plfam_id", "pgfam_id",
					"protein_id", "aa_length", "gene", "product", "go"
				];
				break;
			case "genome":
				req.fieldHeader = [
					"Genome ID", "Genome Name", "Organism Name", "NCBI Taxon ID", "Genome Status",
					"Strain", "Serovar", "Biovar", "Pathovar", "MLST", "Other Typing",
					"Culture Collection", "Type Strain",
					"Completion Date", "Publication",
					"BioProject Accession", "BioSample Accession", "Assembly Accession", "GenBank Accessions",
					"RefSeq Accessions",
					"Sequencing Centers", "Sequencing Status", "Sequencing Platform", "Sequencing Depth", "Assembly Method",
					"Chromosomes", "Plasmids", "Contigs", "Genome Length", "GC Content",
					"PATRIC CDS", "BRC1 CDS", "RefSeq CDS",
					"Isolation Site", "Isolation Source", "Isolation Comments", "Collection Date",
					"Isolation Country", "Geographic Location", "Latitude", "Longitude", "Altitude", "Depth", "Other Environmental",
					"Host Name", "Host Gender", "Host Age", "Host Health", "Body Sample Site", "Body Sample Subsite", "Other Clinical",
					"AntiMicrobial Resistance", "AntiMicrobial Resistance Evidence",
					"Gram Stain", "Cell Shape", "Motility", "Sporulation", "Temperature Range", "Optimal Temperature", "Salinity", "Oxygen Requirement",
					"Habitat",
					"Disease", "Comments", "Additional Metadata", "Date Inserted", "Date Modified"
				];
				req.fieldSelection = [
					"genome_id", "genome_name", "organism_name", "taxon_id", "genome_status",
					"strain", "serovar", "biovar", "pathovar", "mlst", "other_typing",
					"culture_collection", "type_strain",
					"completion_date", "publication",
					"bioproject_accession", "biosample_accession", "assembly_accession", "genbank_accessions",
					"refseq_accessions",
					"sequencing_centers", "sequencing_status", "sequencing_platform", "sequencing_depth", "assembly_method",
					"chromosomes", "plasmids", "contigs", "genome_length", "gc_content",
					"patric_cds", "brc1_cds", "refseq_cds",
					"isolation_site", "isolation_source", "isolation_comments", "collection_date",
					"isolation_country", "geographic_location", "latitude", "longitude", "altitude", "depth", "other_environmental",
					"host_name", "host_gender", "host_age", "host_health", "body_sample_site", "body_sample_subsite", "other_clinical",
					"antimicrobial_resistance", "antimicrobial_resistance_evidence",
					"gram_stain", "cell_shape", "motility", "sporulation", "temperature_range", "optimal_temperature", "salinity", "oxygen_requirement",
					"habitat",
					"disease", "comments", "additional_metadata", "date_inserted", "date_modified"
				];
				break;
			case "genome_sequence":
				req.fieldHeader = [
					"Genome ID", "Genome Name", "Sequence ID", "GI", "Accession", "Sequence Type", "Topology", "Description",
					"GC Content", "Length (bp)", "Release Date", "Version"
				];
				req.fieldSelection = [
					"genome_id", "genome_name", "sequence_id", "gi", "accession", "sequence_type", "topology", "description",
					"gc_content", "length", "release_date", "version"
				];
				break;
			case "genome_amr":
				req.fieldHeader = [
					"Taxon ID", "Genome ID", "Genome Name", "Antibiotic", "Resistant Phenotype",
					"Measurement", "Measurement Sign", "Measurement Value", "Measurement Unit",
					"Laboratory Typing Method", "Laboratory Typing Method Version", "Laboratory Typing Platform", "Vendor",
					"Testing Standard", "Testing Standard Year", "Source"
				];
				req.fieldSelection = [
					"taxon_id", "genome_id", "genome_name", "antibiotic", "resistant_phenotype",
					"measurement", "measurement_sign", "measurement_value", "measurement_unit",
					"laboratory_typing_method", "laboratory_typing_method_version", "laboratory_typing_platform", "vendor",
					"testing_standard", "testing_standard_year", "source"
				];
				break;
			case "sp_gene":
				req.fieldHeader = [
					"Evidence", "Property", "Source", "Genome Name", "PATRIC ID", "RefSeq Locus Tag", "Alt Locus Tag", "Source ID",
					"Source Organism", "Gene", "Product", "Function", "Classification", "PubMed", "Subject Coverage", "Query Coverage",
					"Identity", "E-value"
				];
				req.fieldSelection = [
					"evidence", "property", "source", "genome_name", "patric_id", "refseq_locus_tag", "alt_locus_tag", "source_id",
					"organism", "gene", "product", "function", "classification", "pmid", "subject_coverage", "query_coverage", "identity",
					"e_value"
				];
				break;
			case "sp_gene_ref":
				req.fieldHeader = [
					"Property", "Source", "Source ID", "Gene", "Organism", "Locus Tag", "Gene ID", "GI", "Product",
					"Function", "Classification", "PubMed"
				];
				req.fieldSelection = [
					"property", "source", "source_id", "gene_name", "organism", "locus_tag", "gene_id", "gi", "product",
					"function", "classification", "pmid"
				];
				break;
			case "transcriptomics_experiment":
				req.fieldHeader = [
					"Experiment ID", "Title", "Comparisons", "Genes", "PubMed", "Accession", "Organism", "Strain",
					"Gene Modification", "Experimental Condition", "Time Series", "Release Date", "Author", "PI", "Institution"
				];
				req.fieldSelection = [
					"eid", "title", "samples", "genes", "pmid", "accession", "organism", "strain", "mutant",
					"condition", "timeseries", "release_date", "author", "pi", "institution"
				];
				break;
			case "transcriptomics_sample":
				req.fieldHeader = [
					"Experiment ID", "Comparison ID", "Title", "Genes", "Significant genes(Log Ratio)",
					"Significant genes(Z Score)", "PubMed", "Accession", "Organism", "Strain", "Gene Modification", "Experiment Condition",
					"Time Point", "Release Date"
				];
				req.fieldSelection = [
					"eid", "pid", "expname", "genes", "sig_log_ratio", "sig_z_score", "pmid", "accession",
					"organism", "strain", "mutant", "condition", "timepoint", "release_date"
				];
				break;
			case "interaction":
			case "ppi":
				req.fieldHeader = [
					"Interactor A ID", "Interactor A Type", "Interactor A Desc",
					"Domain A", "Taxon ID A", "Genome ID A", "Genome Name A", "RefSeq Locus Tag A", "gene A",
					"Interactor B ID", "Interactor B Type", "Interactor B Desc",
					"Domain B", "Taxon ID B", "Genome ID B", "Genome Name B", "RefSeq Locus Tag B", "gene B",
					"Category", "Interaction Type", "Detection Method", "Evidence",
					"PMID", "Source DB", "Source ID", "Score"
				];
				req.fieldSelection = [
					"interactor_a", "interactor_type_a", "interactor_desc_a",
					"domain_a", "taxon_id_a", "genome_id_a", "genome_name_a", "refseq_locus_tag_a", "gene_a",
					"interactor_b", "interactor_type_b", "interactor_desc_b",
					"domain_b", "taxon_id_b", "genome_id_b", "genome_name_b", "refseq_locus_tag_b", "gene_b",
					"category", "interaction_type", "detection_method", "evidence",
					"pmid", "source_db", "source_id", "score"
				];
				break;
			default:
				break;
		}
	}

	next();
};
<commit_msg>remove brc1_cds column<commit_after>var debug = require('debug')('p3api-server:FieldSelection');
var url = require("url");

module.exports = function(req, res, next){
	if((req.call_method != "query") && (req.call_method != "stream")){
		return next();
	}

	req.call_params[0] = req.call_params[0] || "&q=*:*";

	const parsed = url.parse("?" + req.call_params[0], true);
	if(parsed && parsed.query && parsed.query.fl){
		req.fieldSelection = parsed.query.fl.split(",");
	}else{

		switch(req.call_collection){
			case "genome_feature":
				req.fieldHeader = [
					"Genome", "Genome ID", "Accession", "PATRIC ID", "RefSeq Locus Tag", "Alt Locus Tag",
					"Feature ID", "Annotation", "Feature Type", "Start", "End", "Length", "Strand", "FIGfam ID",
					"PATRIC genus-specific families (PLfams)", "PATRIC cross-genus families (PGfams)", "Protein ID",
					"AA Length", "Gene Symbol", "Product", "GO"
				];
				req.fieldSelection = [
					"genome_name", "genome_id", "accession", "patric_id", "refseq_locus_tag", "alt_locus_tag",
					"feature_id", "annotation", "feature_type", "start", "end", "na_length", "strand", "figfam_id",
					"plfam_id", "pgfam_id",
					"protein_id", "aa_length", "gene", "product", "go"
				];
				break;
			case "genome":
				req.fieldHeader = [
					"Genome ID", "Genome Name", "Organism Name", "NCBI Taxon ID", "Genome Status",
					"Strain", "Serovar", "Biovar", "Pathovar", "MLST", "Other Typing",
					"Culture Collection", "Type Strain",
					"Completion Date", "Publication",
					"BioProject Accession", "BioSample Accession", "Assembly Accession", "GenBank Accessions",
					"RefSeq Accessions",
					"Sequencing Centers", "Sequencing Status", "Sequencing Platform", "Sequencing Depth", "Assembly Method",
					"Chromosomes", "Plasmids", "Contigs", "Genome Length", "GC Content",
					"PATRIC CDS", "RefSeq CDS",
					"Isolation Site", "Isolation Source", "Isolation Comments", "Collection Date",
					"Isolation Country", "Geographic Location", "Latitude", "Longitude", "Altitude", "Depth", "Other Environmental",
					"Host Name", "Host Gender", "Host Age", "Host Health", "Body Sample Site", "Body Sample Subsite", "Other Clinical",
					"AntiMicrobial Resistance", "AntiMicrobial Resistance Evidence",
					"Gram Stain", "Cell Shape", "Motility", "Sporulation", "Temperature Range", "Optimal Temperature", "Salinity", "Oxygen Requirement",
					"Habitat",
					"Disease", "Comments", "Additional Metadata", "Date Inserted", "Date Modified"
				];
				req.fieldSelection = [
					"genome_id", "genome_name", "organism_name", "taxon_id", "genome_status",
					"strain", "serovar", "biovar", "pathovar", "mlst", "other_typing",
					"culture_collection", "type_strain",
					"completion_date", "publication",
					"bioproject_accession", "biosample_accession", "assembly_accession", "genbank_accessions",
					"refseq_accessions",
					"sequencing_centers", "sequencing_status", "sequencing_platform", "sequencing_depth", "assembly_method",
					"chromosomes", "plasmids", "contigs", "genome_length", "gc_content",
					"patric_cds", "refseq_cds",
					"isolation_site", "isolation_source", "isolation_comments", "collection_date",
					"isolation_country", "geographic_location", "latitude", "longitude", "altitude", "depth", "other_environmental",
					"host_name", "host_gender", "host_age", "host_health", "body_sample_site", "body_sample_subsite", "other_clinical",
					"antimicrobial_resistance", "antimicrobial_resistance_evidence",
					"gram_stain", "cell_shape", "motility", "sporulation", "temperature_range", "optimal_temperature", "salinity", "oxygen_requirement",
					"habitat",
					"disease", "comments", "additional_metadata", "date_inserted", "date_modified"
				];
				break;
			case "genome_sequence":
				req.fieldHeader = [
					"Genome ID", "Genome Name", "Sequence ID", "GI", "Accession", "Sequence Type", "Topology", "Description",
					"GC Content", "Length (bp)", "Release Date", "Version"
				];
				req.fieldSelection = [
					"genome_id", "genome_name", "sequence_id", "gi", "accession", "sequence_type", "topology", "description",
					"gc_content", "length", "release_date", "version"
				];
				break;
			case "genome_amr":
				req.fieldHeader = [
					"Taxon ID", "Genome ID", "Genome Name", "Antibiotic", "Resistant Phenotype",
					"Measurement", "Measurement Sign", "Measurement Value", "Measurement Unit",
					"Laboratory Typing Method", "Laboratory Typing Method Version", "Laboratory Typing Platform", "Vendor",
					"Testing Standard", "Testing Standard Year", "Source"
				];
				req.fieldSelection = [
					"taxon_id", "genome_id", "genome_name", "antibiotic", "resistant_phenotype",
					"measurement", "measurement_sign", "measurement_value", "measurement_unit",
					"laboratory_typing_method", "laboratory_typing_method_version", "laboratory_typing_platform", "vendor",
					"testing_standard", "testing_standard_year", "source"
				];
				break;
			case "sp_gene":
				req.fieldHeader = [
					"Evidence", "Property", "Source", "Genome Name", "PATRIC ID", "RefSeq Locus Tag", "Alt Locus Tag", "Source ID",
					"Source Organism", "Gene", "Product", "Function", "Classification", "PubMed", "Subject Coverage", "Query Coverage",
					"Identity", "E-value"
				];
				req.fieldSelection = [
					"evidence", "property", "source", "genome_name", "patric_id", "refseq_locus_tag", "alt_locus_tag", "source_id",
					"organism", "gene", "product", "function", "classification", "pmid", "subject_coverage", "query_coverage", "identity",
					"e_value"
				];
				break;
			case "sp_gene_ref":
				req.fieldHeader = [
					"Property", "Source", "Source ID", "Gene", "Organism", "Locus Tag", "Gene ID", "GI", "Product",
					"Function", "Classification", "PubMed"
				];
				req.fieldSelection = [
					"property", "source", "source_id", "gene_name", "organism", "locus_tag", "gene_id", "gi", "product",
					"function", "classification", "pmid"
				];
				break;
			case "transcriptomics_experiment":
				req.fieldHeader = [
					"Experiment ID", "Title", "Comparisons", "Genes", "PubMed", "Accession", "Organism", "Strain",
					"Gene Modification", "Experimental Condition", "Time Series", "Release Date", "Author", "PI", "Institution"
				];
				req.fieldSelection = [
					"eid", "title", "samples", "genes", "pmid", "accession", "organism", "strain", "mutant",
					"condition", "timeseries", "release_date", "author", "pi", "institution"
				];
				break;
			case "transcriptomics_sample":
				req.fieldHeader = [
					"Experiment ID", "Comparison ID", "Title", "Genes", "Significant genes(Log Ratio)",
					"Significant genes(Z Score)", "PubMed", "Accession", "Organism", "Strain", "Gene Modification", "Experiment Condition",
					"Time Point", "Release Date"
				];
				req.fieldSelection = [
					"eid", "pid", "expname", "genes", "sig_log_ratio", "sig_z_score", "pmid", "accession",
					"organism", "strain", "mutant", "condition", "timepoint", "release_date"
				];
				break;
			case "interaction":
			case "ppi":
				req.fieldHeader = [
					"Interactor A ID", "Interactor A Type", "Interactor A Desc",
					"Domain A", "Taxon ID A", "Genome ID A", "Genome Name A", "RefSeq Locus Tag A", "gene A",
					"Interactor B ID", "Interactor B Type", "Interactor B Desc",
					"Domain B", "Taxon ID B", "Genome ID B", "Genome Name B", "RefSeq Locus Tag B", "gene B",
					"Category", "Interaction Type", "Detection Method", "Evidence",
					"PMID", "Source DB", "Source ID", "Score"
				];
				req.fieldSelection = [
					"interactor_a", "interactor_type_a", "interactor_desc_a",
					"domain_a", "taxon_id_a", "genome_id_a", "genome_name_a", "refseq_locus_tag_a", "gene_a",
					"interactor_b", "interactor_type_b", "interactor_desc_b",
					"domain_b", "taxon_id_b", "genome_id_b", "genome_name_b", "refseq_locus_tag_b", "gene_b",
					"category", "interaction_type", "detection_method", "evidence",
					"pmid", "source_db", "source_id", "score"
				];
				break;
			default:
				break;
		}
	}

	next();
};
<|endoftext|>


<commit_before>var _; //globals

/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
     "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
      that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
      It's the tie to go along with jQuery's tux."
 */
describe("About Higher Order Functions", function () {

  it("should use filter to return array items that meet a criteria", function () {
    var numbers = [1,2,3];
    var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });

    expect(odd).toEqual([1,3]);
    expect(odd.length).toBe(2);
    expect(numbers.length).toBe(3);
  });

  it("should use 'map' to transform each element", function () {
    var numbers = [1, 2, 3];
    var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });

    expect(numbersPlus1).toEqual([2,3,4]);
    expect(numbers).toEqual([1,2,3]);
  });

  it("should use 'reduce' to update the same result on each iteration", function () {
    var numbers = [1, 2, 3];
    var reduction = _(numbers).reduce(
      function(memo, x) {
        //note: memo is the result from last call, and x is the current number
        return memo + x;
      },
      /* initial */ 0
    );

    expect(reduction).toBe(6);
    expect(numbers).toEqual([1,2,3]);
  });

  it("should use 'forEach' for simple iteration", function () {
    var numbers = [1,2,3];
    var msg = "";
    var isEven = function (item) {
      msg += (item % 2) === 0;
    };

    _(numbers).forEach(isEven);

    expect(msg).toEqual("falsetruefalse");
    expect(numbers).toEqual([1,2,3]);
  });

  it("should use 'all' to test whether all items pass condition", function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).all(isEven)).toBe(true);
    expect(_(mixedBag).all(isEven)).toBe(false);
  });

  it("should use 'any' to test if any items passes condition" , function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).any(isEven)).toBe(true);
    expect(_(mixedBag).any(isEven)).toBe(true);
  });

  it("should use range to generate an array", function() {
    expect(_.range(3)).toEqual([0,1,2]);
    expect(_.range(1, 4)).toEqual([1,2,3]);
    expect(_.range(0, -4, -1)).toEqual([0,-1,-2,-3]);
  });

  it("should use flatten to make nested arrays easy to work with", function() {
    expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual(FILL_ME_IN);
  });

  it("should use chain() ... .value() to use multiple higher order functions", function() {
    var result = _([ [0, 1], 2 ]).chain()
                     .flatten()
                     .map(function(x) { return x+1 } )
                     .reduce(function (sum, x) { return sum + x })
                     .value();

    expect(result).toEqual(FILL_ME_IN);
  });

});

<commit_msg>AboutHigherOrderFunctions.js: Completed "should use flatten to make nested arrays easy to work with" - flatten will combine nested arrays into one array - it is pure<commit_after>var _; //globals

/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
     "Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
      that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
      It's the tie to go along with jQuery's tux."
 */
describe("About Higher Order Functions", function () {

  it("should use filter to return array items that meet a criteria", function () {
    var numbers = [1,2,3];
    var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });

    expect(odd).toEqual([1,3]);
    expect(odd.length).toBe(2);
    expect(numbers.length).toBe(3);
  });

  it("should use 'map' to transform each element", function () {
    var numbers = [1, 2, 3];
    var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });

    expect(numbersPlus1).toEqual([2,3,4]);
    expect(numbers).toEqual([1,2,3]);
  });

  it("should use 'reduce' to update the same result on each iteration", function () {
    var numbers = [1, 2, 3];
    var reduction = _(numbers).reduce(
      function(memo, x) {
        //note: memo is the result from last call, and x is the current number
        return memo + x;
      },
      /* initial */ 0
    );

    expect(reduction).toBe(6);
    expect(numbers).toEqual([1,2,3]);
  });

  it("should use 'forEach' for simple iteration", function () {
    var numbers = [1,2,3];
    var msg = "";
    var isEven = function (item) {
      msg += (item % 2) === 0;
    };

    _(numbers).forEach(isEven);

    expect(msg).toEqual("falsetruefalse");
    expect(numbers).toEqual([1,2,3]);
  });

  it("should use 'all' to test whether all items pass condition", function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).all(isEven)).toBe(true);
    expect(_(mixedBag).all(isEven)).toBe(false);
  });

  it("should use 'any' to test if any items passes condition" , function () {
    var onlyEven = [2,4,6];
    var mixedBag = [2,4,5,6];

    var isEven = function(x) { return x % 2 === 0 };

    expect(_(onlyEven).any(isEven)).toBe(true);
    expect(_(mixedBag).any(isEven)).toBe(true);
  });

  it("should use range to generate an array", function() {
    expect(_.range(3)).toEqual([0,1,2]);
    expect(_.range(1, 4)).toEqual([1,2,3]);
    expect(_.range(0, -4, -1)).toEqual([0,-1,-2,-3]);
  });

  it("should use flatten to make nested arrays easy to work with", function() {
    expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual([1,2,3,4]);
  });

  it("should use chain() ... .value() to use multiple higher order functions", function() {
    var result = _([ [0, 1], 2 ]).chain()
                     .flatten()
                     .map(function(x) { return x+1 } )
                     .reduce(function (sum, x) { return sum + x })
                     .value();

    expect(result).toEqual(FILL_ME_IN);
  });

});

<|endoftext|>