<commit_before>var Heroku = require('heroku-client')

function Sparoku() {
  // eek, for now keeping requests in memory. can go to redis later
  this.requests = []
  this.dynos = {}
  this.heroku = new Heroku({ token: process.env.HEROKU_API_TOKEN });
  this.colors = {
    off: 0,
    green: 1,
    yellow: 2,
    red: 3,
    blue: 4
  }
}

Sparoku.prototype = {
  update: function(device) {
    var status = {}
    var self = this

    this.requests.forEach(function(req) {
      if (!status[req.dyno]) {
        status[req.dyno] = { success: 0, error: 0 }
      }
      if (parseInt(req.status) >= 500) {
        status[req.dyno].error += 1
      }
      else {
        status[req.dyno].success += 1
      }
    })

    var update = Object.keys(self.dynos).map(function(dyno) {
      var color = self.getColor(dyno, status[dyno])
      return dyno + '=' + color
    })

    if (update.length > 0 && device) {
      var rawUpdate = update.reduce(function(prev, update) {
        return prev + ';' + update
      }) + ';'

      device.callFunction('update', rawUpdate, function(err, data) {
        if (err) {
          console.log('device update failed:')
          console.log(err)
        }
      });
      console.log(rawUpdate)
      this.requests = []
    }
  },

  refresh: function() {
    var self = this
    var url = '/apps/' + process.env.HEROKU_APP_NAME + '/dynos'
    this.heroku.get(url, function(err, dynos) {
      dynos.forEach(function(dyno) {
        var num = self.dynoNum(dyno.name)
        self.dynos[num] = dyno.state
      })
    })
  },

  process: function(log) {
    if (log.heroku && log.router  && log.dyno && log.status) {
      this.requests.push({
        dyno: this.dynoNum(log.dyno),
        status: log.status
      })
    }
  },

  dynoNum: function(dynoName) {
    return dynoName.replace(/\w+\./, "")
  },

  getColor: function(dyno, status) {
    switch(this.dynos[dyno]) {
      case 'idle':
        return this.colors.blue
      case 'starting':
        return this.colors.blue
      case 'crashed':
        return this.colors.red
      case 'up':
        if (!status) return this.colors.green
        var diff = status.success - status.error
        return (diff>0)? this.colors.green : this.colors.red
      // update about an unknown dyno, ignore and turn off the light
      default:
        return this.colors.off
    }
  }
}

module.exports = new Sparoku();
<commit_msg>remove dynos that stopped running (eg: user scaled down)<commit_after>var Heroku = require('heroku-client')

function Sparoku() {
  // eek, for now keeping requests in memory. can go to redis later
  this.requests = []
  this.dynos = {}
  this.heroku = new Heroku({ token: process.env.HEROKU_API_TOKEN });
  this.colors = {
    off: 0,
    green: 1,
    yellow: 2,
    red: 3,
    blue: 4
  }
}

Sparoku.prototype = {
  update: function(device) {
    var status = {}
    var self = this

    this.requests.forEach(function(req) {
      if (!status[req.dyno]) {
        status[req.dyno] = { success: 0, error: 0 }
      }
      if (parseInt(req.status) >= 500) {
        status[req.dyno].error += 1
      }
      else {
        status[req.dyno].success += 1
      }
    })

    var update = Object.keys(self.dynos).map(function(dyno) {
      var color = self.getColor(dyno, status[dyno])
      return dyno + '=' + color
    })

    if (update.length > 0 && device) {
      var rawUpdate = update.reduce(function(prev, update) {
        return prev + ';' + update
      }) + ';'

      device.callFunction('update', rawUpdate, function(err, data) {
        if (err) {
          console.log('device update failed:')
          console.log(err)
        }
      });
      console.log(rawUpdate)
      this.requests = []
    }
  },

  refresh: function() {
    var self = this
    var url = '/apps/' + process.env.HEROKU_APP_NAME + '/dynos'
    this.heroku.get(url, function(err, dynos) {
      var updated = {}
      dynos.forEach(function(dyno) {
        var num = self.dynoNum(dyno.name)
        self.dynos[num] = dyno.state
        updated[num] = true
      })

      // remove dynos that were not listed
      Object.keys(self.dynos).forEach(function (dyno) {
        if (!updated[dyno]) {
          self.dynos[dyno] = 'scaled_down'
        }
      })
    })
  },

  process: function(log) {
    if (log.heroku && log.router  && log.dyno && log.status) {
      this.requests.push({
        dyno: this.dynoNum(log.dyno),
        status: log.status
      })
    }
  },

  dynoNum: function(dynoName) {
    return dynoName.replace(/\w+\./, "")
  },

  getColor: function(dyno, status) {
    switch(this.dynos[dyno]) {
      case 'idle':
        return this.colors.blue
      case 'starting':
        return this.colors.blue
      case 'crashed':
        return this.colors.red
      case 'up':
        if (!status) return this.colors.green
        var diff = status.success - status.error
        return (diff>0)? this.colors.green : this.colors.red
      // update about an unknown dyno, ignore and turn off the light
      default:
        return this.colors.off
    }
  }
}

module.exports = new Sparoku();

{'fraction_non_alphanumeric': 0.14383294301327088, 'fraction_numerical': 0.00546448087431694, 'mean_word_length': 2.100423472474289, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '55464', 'n_tokens_mistral': 1749, 'n_tokens_neox': 1705, 'n_words': 372}