<commit_before>import Events from 'events'
import Firebase from 'firebase'
import Moment from 'moment'
import URL from 'url'
import _ from 'underscore'

export default class StoryWatcher extends Events.EventEmitter {
  constructor (url) {
    super()
    this.maxNumOfStories = 20 // TODO: make it configurable
    this.fb = new Firebase(url)
    this.fbRefs = {}
    this.fbFuns = {}
  }
  onStoryChange (type, storyIds) {
    var self = this
    var count = 0

    storyIds.forEach(function (storyId) {
      var index = parseInt(storyId.key(), 10)
      var id = storyId.val()

      self.fb.child('item/' + id).once('value', function (storySnapshot) {
        var story = storySnapshot.val()
        if (!story) {
          self.emitError(type, new Error('Error loading ' + storySnapshot.key()))
          return
        }

        story.rank = index
        story.timeAgo = Moment.unix(story.time).fromNow()
        story.yurl = self.getYurl(story.id)
        if (_.isEmpty(story.url)) {
          story.url = story.yurl
        } else {
          story.host = URL.parse(story.url).hostname
        }

        self.emit(type, story)
      }, function (err) {
        self.emitError(type, err)
      })

      return ++count === self.maxNumOfStories
    })
  }
  getYurl (id) {
    return 'https://news.ycombinator.com/item?id=' + id
  }
  getChildName (type) {
    var child = ''
    if (type === 'top') {
      child = 'topstories'
    } else if (type === 'show') {
      child = 'showstories'
    } else if (type === 'ask') {
      child = 'askstories'
    } else {
      throw new Error('Unsupported watch type ' + type)
    }

    return child
  }
  watch (type, callback, errback) {
    if (callback != null) {
      this.on(type, callback)
    }

    if (errback != null) {
      this.on(type + '-error', errback)
    }

    this.fbRefs[type] = this.fb.child(this.getChildName(type))
    this.fbFuns[type] = this.fbRefs[type].on('value', this.onStoryChange.bind(this, type), function (err) {
      this.emitError(type, err)
    }.bind(this))<commit_msg>Use `limitToFirst` to limit max number of stories<commit_after>import Events from 'events'
import Firebase from 'firebase'
import Moment from 'moment'
import URL from 'url'
import _ from 'underscore'

export default class StoryWatcher extends Events.EventEmitter {
  constructor (url) {
    super()
    this.maxNumOfStories = 20 // TODO: make it configurable
    this.fb = new Firebase(url)
    this.fbRefs = {}
    this.fbFuns = {}
  }
  onStoryChange (type, storyIds) {
    var self = this

    storyIds.forEach(function (storyId) {
      var index = parseInt(storyId.key(), 10)
      var id = storyId.val()

      self.fb.child('item/' + id).once('value', function (storySnapshot) {
        var story = storySnapshot.val()
        if (!story) {
          self.emitError(type, new Error('Error loading ' + storySnapshot.key()))
          return
        }

        story.rank = index
        story.timeAgo = Moment.unix(story.time).fromNow()
        story.yurl = self.getYurl(story.id)
        if (_.isEmpty(story.url)) {
          story.url = story.yurl
        } else {
          story.host = URL.parse(story.url).hostname
        }

        self.emit(type, story)
      }, function (err) {
        self.emitError(type, err)
      })

      return false
    })
  }
  getYurl (id) {
    return 'https://news.ycombinator.com/item?id=' + id
  }
  getChildName (type) {
    var child = ''
    if (type === 'top') {
      child = 'topstories'
    } else if (type === 'show') {
      child = 'showstories'
    } else if (type === 'ask') {
      child = 'askstories'
    } else {
      throw new Error('Unsupported watch type ' + type)
    }

    return child
  }
  watch (type, callback, errback) {
    if (callback != null) {
      this.on(type, callback)
    }

    if (errback != null) {
      this.on(type + '-error', errback)
    }

    this.fbRefs[type] = this.fb.child(this.getChildName(type)).limitToFirst(this.maxNumOfStories)
    this.fbFuns[type] = this.fbRefs[type].on('value', this.onStoryChange.bind(this, type), function (err) {
      this.emitError(type, err)
    }.bind(this))
{'fraction_non_alphanumeric': 0.14082811747713048, 'fraction_numerical': 0.0021665864227250844, 'mean_word_length': 2.402948402948403, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, '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': '1434393', 'n_tokens_mistral': 1388, 'n_tokens_neox': 1356, 'n_words': 312}