<commit_before>const _ = require('underscore');
const async = require('async');
const jwt = require('jwt-simple');
const urlutil = require('url');
const env = require('../lib/environment');
const util = require('../lib/util');
const Badge = require('../models/badge');
const User = require('../models/user');
const BadgeInstance = require('../models/badge-instance');
const Program = require('../models/program');
const Issuer = require('../models/issuer');
const mongoose = require('mongoose');

function normalizeBadge(badge) {
  var badgeData = {
    name: badge.name,
    description: badge.description,
    prerequisites: badge.prerequisites,
    image: badge.absoluteUrl('image'),
    criteria: badge.criteria && badge.criteria.content,
    tags: badge.tags,
    categoryAward: badge.categoryAward,
    categoryRequirement: badge.categoryRequirement || undefined,
    categoryWeight: badge.categoryWeight || undefined,
    categories: badge.categories,
    ageRange: badge.ageRange,
    type: badge.type,
    activityType: badge.activityType,
    rubric: {
      items: badge.getRubricItems()
    }
  };

  if (badge.program && typeof(badge.program) == "object")
    badgeData.program = normalizeProgram(badge.program);
  else
    badgeData.program = badge.program;

  return badgeData;
}

function inflateBadge(badge, cb) {
  badge.populate('program', function(err) {
    if (err) return cb(err);
    badge.program.populate('issuer', function(err) {
      if (err) return cb(err);
      cb(null, badge);
    });
  });
}

function normalizeProgram(program) {
  if (!(program.issuer && typeof(program.issuer) == "object"))
    throw new Error("expected populated program issuer");

  var programData = [
    'shortname',
    'name',
    'description',
    'url',
    'contact',
    'startDate',
    'endDate',
    'phone',
  ].reduce(function (out, field) {
    return (out[field] = program[field], out);
  }, {});
  programData.imageUrl = program.absoluteUrl('image');
  programData.issuer = {
    name: program.issuer.name,
    url: program.issuer.url
  };

  return programData;
}

exports.jwtSecret = null;

/**
 * Get listing of all badges
 */

exports.badges = function badges(req, res) {
  var result = { status: 'ok', badges : {} };
  Badge.find(function (err, badges) {
    if (err)
      return res.send(500, { status: 'error', error: err });
    badges.filter(function (badge) {
      return !badge.doNotList;
    }).forEach(function (badge) {
      result.badges[badge.shortname] = normalizeBadge(badge);
    });
    return res.send(200, result);
  });
};

exports.badge = function badge(req, res) {
  inflateBadge(req.badge, function(err) {
    if (err)
      return res.json(500, { status: 'error', error: err });
    res.json(200, { status: 'ok', badge: normalizeBadge(req.badge) });
  });
};

function parseLimit(userLimit) {
  const DEFAULT_LIMIT = 10;
  const limit = parseInt(userLimit, 10);
  if (isNaN(userLimit))
    return DEFAULT_LIMIT;
  return userLimit;
}

exports.similarBadges = function similarBadges(req, res, next) {
  const badge = req.badge;
  const email = req.query.email;
  const limit = parseLimit(req.query.limit, 10);

  badge.getSimilar(email, function (err, badges) {
    if (err)
      return res.json(500, { status: 'error', error: err });

    if (limit > 0)
      badges = badges.slice(0, limit);

    return res.json(200, {
      status: 'ok',
      badges: badges.map(normalizeBadge)
    });
  });
};

exports.badgeRecommendations = function badgeRecommendations(req, res, next) {
  Badge
    .find({})
    .limit(10)
    .exec(function (err, badges) {
      if (err) return res.json(500, { status: 'error', error: err });
      return res.json(200, { status: 'ok', badges: badges.map(normalizeBadge) });
    });
};

exports.badgeClaimCodes = function badgeClaimCodes(req, res, next) {
  const badge = req.badge;
  const queryOpts = req.query;

  // theoretically this should never happen - this route should always
  // be preceded by middleware that finds the badge or 404s.
  if (!badge)
    return res.json(404, {status: 'error', reason: 'badge not found'});

  const options = {
    page: parseInt(queryOpts.page, 10) || 1,
    count: parseInt(queryOpts.count, 10) || 100,
    unclaimed: false,
  };

  if (queryOpts.count === '0' || queryOpts.limit === 'false')
    options.count = Infinity;

  const allCodes = badge.getClaimCodes({
    unclaimed: options.unclaimed
  });
  const someCodes = util.pager(allCodes, {
    page: options.page,
    count: options.count<commit_msg>Use `Badge.getRecommendations` in the api.<commit_after>const _ = require('underscore');
const async = require('async');
const jwt = require('jwt-simple');
const urlutil = require('url');
const env = require('../lib/environment');
const util = require('../lib/util');
const Badge = require('../models/badge');
const User = require('../models/user');
const BadgeInstance = require('../models/badge-instance');
const Program = require('../models/program');
const Issuer = require('../models/issuer');
const mongoose = require('mongoose');

function normalizeBadge(badge) {
  var badgeData = {
    name: badge.name,
    description: badge.description,
    prerequisites: badge.prerequisites,
    image: badge.absoluteUrl('image'),
    criteria: badge.criteria && badge.criteria.content,
    tags: badge.tags,
    categoryAward: badge.categoryAward,
    categoryRequirement: badge.categoryRequirement || undefined,
    categoryWeight: badge.categoryWeight || undefined,
    categories: badge.categories,
    ageRange: badge.ageRange,
    type: badge.type,
    activityType: badge.activityType,
    rubric: {
      items: badge.getRubricItems()
    }
  };

  if (badge.program && typeof(badge.program) == "object")
    badgeData.program = normalizeProgram(badge.program);
  else
    badgeData.program = badge.program;

  return badgeData;
}

function inflateBadge(badge, cb) {
  badge.populate('program', function(err) {
    if (err) return cb(err);
    badge.program.populate('issuer', function(err) {
      if (err) return cb(err);
      cb(null, badge);
    });
  });
}

function normalizeProgram(program) {
  if (!(program.issuer && typeof(program.issuer) == "object"))
    throw new Error("expected populated program issuer");

  var programData = [
    'shortname',
    'name',
    'description',
    'url',
    'contact',
    'startDate',
    'endDate',
    'phone',
  ].reduce(function (out, field) {
    return (out[field] = program[field], out);
  }, {});
  programData.imageUrl = program.absoluteUrl('image');
  programData.issuer = {
    name: program.issuer.name,
    url: program.issuer.url
  };

  return programData;
}

exports.jwtSecret = null;

/**
 * Get listing of all badges
 */

exports.badges = function badges(req, res) {
  var result = { status: 'ok', badges : {} };
  Badge.find(function (err, badges) {
    if (err)
      return res.send(500, { status: 'error', error: err });
    badges.filter(function (badge) {
      return !badge.doNotList;
    }).forEach(function (badge) {
      result.badges[badge.shortname] = normalizeBadge(badge);
    });
    return res.send(200, result);
  });
};

exports.badge = function badge(req, res) {
  inflateBadge(req.badge, function(err) {
    if (err)
      return res.json(500, { status: 'error', error: err });
    res.json(200, { status: 'ok', badge: normalizeBadge(req.badge) });
  });
};

function parseLimit(userLimit) {
  const DEFAULT_LIMIT = 10;
  const limit = parseInt(userLimit, 10);
  if (isNaN(userLimit))
    return DEFAULT_LIMIT;
  return userLimit;
}

exports.similarBadges = function similarBadges(req, res, next) {
  const badge = req.badge;
  const email = req.query.email;
  const limit = parseLimit(req.query.limit, 10);

  badge.getSimilar(email, function (err, badges) {
    if (err)
      return res.json(500, { status: 'error', error: err });

    if (limit > 0)
      badges = badges.slice(0, limit);

    return res.json(200, {
      status: 'ok',
      badges: badges.map(normalizeBadge)
    });
  });
};

exports.badgeRecommendations = function badgeRecommendations(req, res, next) {
  Badge.getRecommendations({
    email: req.authUser || req.query.email
  }, function (err, badges) {
    if (err) return res.json(500, {status: 'error', error: err });
    return res.json(200, {
      status: 'okay',
      badges: badges.map(normalizeBadge),
    });
  });
};

exports.badgeClaimCodes = function badgeClaimCodes(req, res, next) {
  const badge = req.badge;
  const queryOpts = req.query;

  // theoretically this should never happen - this route should always
  // be preceded by middleware that finds the badge or 404s.
  if (!badge)
    return res.json(404, {status: 'error', reason: 'badge not found'});

  const options = {
    page: parseInt(queryOpts.page, 10) || 1,
    count: parseInt(queryOpts.count, 10) || 100,
    unclaimed: false,
  };

  if (queryOpts.count === '0' || queryOpts.limit === 'false')
    options.count = Infinity;

  const allCodes = badge.getClaimCodes({
    unclaimed: options.unclaimed
  });
  const someCodes = util.pager(allCodes, {
    page: options.page,
    count: options.count
{'fraction_non_alphanumeric': 0.15293731539218905, 'fraction_numerical': 0.010502133245815556, 'mean_word_length': 3.5664335664335662, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6459046', 'n_tokens_mistral': 3130, 'n_tokens_neox': 2990, 'n_words': 692}