<commit_before>
// ===== actions.jsx =====

var actions = Reflux.createActions({
  receivedPlanetUpdate: {}, // Sent by WebSocket when it gets an update
  requestCursor: {}, // Sent by UI when it wants to see a particular lord
  releaseCursor: {}, // Sent by UI when it doesn't anymore
  loadSithLord: {asyncResult: true}, // Sent by internal code when it knows the URL to load a cursor frm
});

var activeRequests = {};

// Actually load a cursor from the network using a URL
actions.loadSithLord.listen(function(cursor, url) {
  if(cursor in activeRequests)
    return; // Don't load a URL twice
  var promise = jQuery.get(url);
  promise.then(function(data) {
    delete activeRequests[cursor];
    actions.loadSithLord.completed(cursor, data);
  });
  activeRequests[cursor] = promise;
});

// Requirement: abort requests if a cursor is released
actions.releaseCursor.listen(function(cursor){
  if(activeRequests[cursor]){
    activeRequests[cursor].abort();
    delete activeRequests[cursor];
  }
});

// ===== store.jsx =====

var requestedCursors = {};

actions.requestCursor.listen(function(cursor){
  if(!(cursor in requestedCursors))
    requestedCursors[cursor] = 0;
  requestedCursors[cursor] += 1;
  checkRequestedCursors();
});

actions.releaseCursor.preEmit = function(cursor) {
  requestedCursors[cursor] -= 1;
  if(requestedCursors[cursor] == 0)
    delete requestedCursors[cursor];
};

// Check to see if we can load cursors that were requested prior, but
// we weren't able to load immediately
function checkRequestedCursors() {
  _.each(requestedCursors, function(value, cursor) {
    cursor = parseInt(cursor);

    if(cursor in store.data.sithLords)
      return; // Cursor was already loaded

    // We've loaded the lord before this one, so we can use its apprentice URL
    if(cursor-1 in store.data.sithLords && store.data.sithLords[cursor-1].loadState == 'done'){
      var url = store.data.sithLords[cursor-1].apprentice.url;
      if(url)
        actions.loadSithLord(cursor, url);
    }

    // We've loaded the lord after this one, so we can use its master URL
    if(cursor+1 in store.data.sithLords && store.data.sithLords[cursor+1].loadState == 'done'){
      var url = store.data.sithLords[cursor+1].master.url;
      if(url)
        actions.loadSithLord(cursor, url);
    }
  });
}

// The store has the info that the UI wants in it
var store = Reflux.createStore({
  init() {
    this.listenToMany(actions);
    this.data = {
      currentPlanet: {id: null, name: 'Unknown'},
      sithLords: {},
    };
  },
  getInitialState() {
    return this.data;
  },
  // Update current planet
  onReceivedPlanetUpdate(newData){
    this.data.currentPlanet = newData;
    this.trigger(this.data);
  },
  // When load starts, insert a "Loading..." item
  onLoadSithLord(cursor, url) {
    this.data.sithLords[cursor] = {
      loadState: 'loading'
    };
    this.trigger(this.data);
  },
  // When load completed, insert the new data.
  onLoadSithLordCompleted(cursor, data) {
    this.data.sithLords[cursor] = data;
    this.data.sithLords[cursor].loadState = 'done';
    delete activeRequests[cursor];
    this.trigger(this.data);
    checkRequestedCursors(); // Check to see if this load completing lets us load something else too
  },
  // Requirement: obliterate data when a cursor is released
  onReleaseCursor(cursor) {
    if(!requestedCursors[cursor]){
      if(cursor in this.data.sithLords) {
        delete this.data.sithLords[cursor];
        this.trigger(this.data);
      }
    }
  },

  // Utility functions that can be called by the UI

  hasMoreApprentices() {
    var maxCursor = _(this.data.sithLords).keys().max();
    if(maxCursor in this.data.sithLords){
      var lastLord = this.data.sithLords[maxCursor];
      if(lastLord.loadState == 'loading')
        return true; // Strange case but demo seemed to allow it
      else
        return !!lastLord.apprentice.url;
    }
    else {
      return false; // Edge case: false with no data
    }
  },
  hasMoreMasters() {
    var minCursor = _(this.data.sithLords).keys().min();
    if(minCursor in this.data.sithLords){
      var firstLord = this.data.sithLords[minCursor];
      if(firstLord.loadState == 'loading')
        return true; // Strange case but demo seemed to allow it
      else
        return !!firstLord.master.url;
    }
    else {
      return false; // Edge case: false with no data
    }
  },
  currentPlanetHasLord() {
    return _.any(this.data.sithLords, (lord) => {
      return lord.loadState == 'done' && (lord.homeworld.id == this.data.currentPlanet.id);
    })
  },

});

// ===== components.jsx =====


// Componenet to manage each lord's row
var Entry = React.createClass({
  mixins: [Reflux.connect(store)],

  propTypes: {
    cursor: React.PropTypes.number.isRequired,
  },
<commit_msg>Don't allow scrolling if first/last Sith lords are loading<commit_after>
// ===== actions.jsx =====

var actions = Reflux.createActions({
  receivedPlanetUpdate: {}, // Sent by WebSocket when it gets an update
  requestCursor: {}, // Sent by UI when it wants to see a particular lord
  releaseCursor: {}, // Sent by UI when it doesn't anymore
  loadSithLord: {asyncResult: true}, // Sent by internal code when it knows the URL to load a cursor frm
});

var activeRequests = {};

// Actually load a cursor from the network using a URL
actions.loadSithLord.listen(function(cursor, url) {
  if(cursor in activeRequests)
    return; // Don't load a URL twice
  var promise = jQuery.get(url);
  promise.then(function(data) {
    delete activeRequests[cursor];
    actions.loadSithLord.completed(cursor, data);
  });
  activeRequests[cursor] = promise;
});

// Requirement: abort requests if a cursor is released
actions.releaseCursor.listen(function(cursor){
  if(activeRequests[cursor]){
    activeRequests[cursor].abort();
    delete activeRequests[cursor];
  }
});

// ===== store.jsx =====

var requestedCursors = {};

actions.requestCursor.listen(function(cursor){
  if(!(cursor in requestedCursors))
    requestedCursors[cursor] = 0;
  requestedCursors[cursor] += 1;
  checkRequestedCursors();
});

actions.releaseCursor.preEmit = function(cursor) {
  requestedCursors[cursor] -= 1;
  if(requestedCursors[cursor] == 0)
    delete requestedCursors[cursor];
};

// Check to see if we can load cursors that were requested prior, but
// we weren't able to load immediately
function checkRequestedCursors() {
  _.each(requestedCursors, function(value, cursor) {
    cursor = parseInt(cursor);

    if(cursor in store.data.sithLords)
      return; // Cursor was already loaded

    // We've loaded the lord before this one, so we can use its apprentice URL
    if(cursor-1 in store.data.sithLords && store.data.sithLords[cursor-1].loadState == 'done'){
      var url = store.data.sithLords[cursor-1].apprentice.url;
      if(url)
        actions.loadSithLord(cursor, url);
    }

    // We've loaded the lord after this one, so we can use its master URL
    if(cursor+1 in store.data.sithLords && store.data.sithLords[cursor+1].loadState == 'done'){
      var url = store.data.sithLords[cursor+1].master.url;
      if(url)
        actions.loadSithLord(cursor, url);
    }
  });
}

// The store has the info that the UI wants in it
var store = Reflux.createStore({
  init() {
    this.listenToMany(actions);
    this.data = {
      currentPlanet: {id: null, name: 'Unknown'},
      sithLords: {},
    };
  },
  getInitialState() {
    return this.data;
  },
  // Update current planet
  onReceivedPlanetUpdate(newData){
    this.data.currentPlanet = newData;
    this.trigger(this.data);
  },
  // When load starts, insert a "Loading..." item
  onLoadSithLord(cursor, url) {
    this.data.sithLords[cursor] = {
      loadState: 'loading'
    };
    this.trigger(this.data);
  },
  // When load completed, insert the new data.
  onLoadSithLordCompleted(cursor, data) {
    this.data.sithLords[cursor] = data;
    this.data.sithLords[cursor].loadState = 'done';
    delete activeRequests[cursor];
    this.trigger(this.data);
    checkRequestedCursors(); // Check to see if this load completing lets us load something else too
  },
  // Requirement: obliterate data when a cursor is released
  onReleaseCursor(cursor) {
    if(!requestedCursors[cursor]){
      if(cursor in this.data.sithLords) {
        delete this.data.sithLords[cursor];
        this.trigger(this.data);
      }
    }
  },

  // Utility functions that can be called by the UI

  hasMoreApprentices() {
    var maxCursor = _(this.data.sithLords).keys().max();
    if(maxCursor in this.data.sithLords){
      var lastLord = this.data.sithLords[maxCursor];
      if(lastLord.loadState == 'loading')
        return false;
      else
        return !!lastLord.apprentice.url;
    }
    else {
      return false; // Edge case: false with no data
    }
  },
  hasMoreMasters() {
    var minCursor = _(this.data.sithLords).keys().min();
    if(minCursor in this.data.sithLords){
      var firstLord = this.data.sithLords[minCursor];
      if(firstLord.loadState == 'loading')
        return false;
      else
        return !!firstLord.master.url;
    }
    else {
      return false; // Edge case: false with no data
    }
  },
  currentPlanetHasLord() {
    return _.any(this.data.sithLords, (lord) => {
      return lord.loadState == 'done' && (lord.homeworld.id == this.data.currentPlanet.id);
    })
  },

});

// ===== components.jsx =====


// Componenet to manage each lord's row
var Entry = React.createClass({
  mixins: [Reflux.connect(store)],

  propTypes: {
    cursor: React.PropTypes.number.isRequired,
  },

{'fraction_non_alphanumeric': 0.13066583307283527, 'fraction_numerical': 0.002083984578514119, 'mean_word_length': 3.2207563764291995, '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': '6314379', 'n_tokens_mistral': 3122, 'n_tokens_neox': 3056, 'n_words': 780}