<commit_before><template>
    <div class="app-container">
        <div class="css-root">
            <h1 v-if="planet" class="css-planet-monitor">Obi-Wan currently on {{planet.name}}</h1>

            <section class="css-scrollable-list">
              <ul class="css-slots">
                <li :style="{ color: isSithHere(slot) ? 'red': '' }" v-for="slot in slots" class="css-slot" track-by="$index">
                  <h3 v-if="slot && slot.name">{{slot.name}}</h3>
                  <h6 v-if="slot && slot.homeworld">Homeworld: {{slot.homeworld.name}}</h6>
                </li>
              </ul>

              <div class="css-scroll-buttons">
                <button :class="buttonUpClass" @click.prevent="scrollUp"></button>
                <button :class="buttonDownClass" @click.prevent="scrollDown"></button>
              </div>
            </section>
      </div>
    </div>
</template>

<script>

import _ from 'lodash';

const SCROLL_UP = "scroll_up";
const SCROLL_DOWN = "scroll_down";
const NUM_SLOTS = 5;

let xhrRequests = [];

function cancelRequests() {
  for (var i=0; i < xhrRequests.length; i++) {
    xhrRequests.shift().abort();
  }
}

export default {
    name: "App",
    data() {
        return {
            planet: null,
            slots: _.fill(Array(NUM_SLOTS), null),
            isLoading: false,
            isSithOnWorld: false,
            isFirst: true,
            isLast: true
        };
    },
    events: {
        "planet-changed": function(planet){
           this.planet = planet;
           this.checkIfSithHomeworld();
        }
    },
    ready() {
        this.fillSlots(SCROLL_DOWN, 3616, 0);
        new WebSocket(`ws://${window.location.host}/ws`)
            .onmessage = (event) => {
                this.$dispatch("planet-changed", JSON.parse(event.data));
            };
    },
    computed: {
        canScrollUp() {
          return !this.isFirst && !this.isSithOnWorld && !this.isLoading;
        },
        canScrollDown() {
          return !this.isLast && !this.isSithOnWorld && !this.isLoading;
        },
        buttonUpClass() {
          return ['css-button-up', this.canScrollUp ? '' : 'css-button-disabled']; 
        },
        buttonDownClass() {
          return ['css-button-down', this.canScrollDown ? '' : 'css-button-disabled']; 
        }
    },
    methods: {
       
        fillSlots(direction, nextId, index) {

          if (!nextId || this.isLoading) {
            return;
          }

          this.isLoading = true;

          this.$http.get("/sith/" + nextId, sith => {

            this.isLoading = false;
            this.slots.splice(index, 1, sith);

            if (direction === SCROLL_UP) {
              nextId = sith.master;
              index -= 1;
            } else {
              nextId = sith.apprentice;
              index += 1;
            }

            this.isFirst = direction === SCROLL_UP && !nextId;
            this.isLast = direction === SCROLL_DOWN && !nextId;

            this.checkIfSithHomeworld();

            if (nextId && this.slots[index] === null) {
              this.fillSlots(direction, nextId, index);
            }

          }, {
            beforeSend(req) {
              xhrRequests.push(req);
            }
          });
        },

        scrollUp () {

          if (!this.canScrollUp) {
            return;
          }

          cancelRequests();

          let newSlots = this.slots.slice(0, 3);

          const firstSlot = newSlots[0];
          const nextId = firstSlot ? firstSlot.master : 0;

          newSlots.splice(0, 0, null);
          newSlots.splice(1, 0, null);

          this.slots = newSlots.slice();
          this.fillSlots(SCROLL_UP, nextId, 1);

        },

        scrollDown() {
          if (!this.canScrollDown) {
            return;
          }

          cancelRequests();

          let newSlots = this.slots.slice(2);
          const lastSlot = newSlots[newSlots.length - 1];
          const nextId = lastSlot ? lastSlot.apprentice : 0;

          newSlots.splice(4, 0, null);
          newSlots.splice(5, 0, null);

          this.slots = newSlots.slice();
          this.fillSlots(SCROLL_DOWN, nextId, 3);
        },

        checkIfSithHomeworld() {
          this.isSithOnWorld = _.some(this.slots, slot => {
            return this.isSithHere(slot);
          });
          if (this.isSithOnWorld) {
            cancelRequests();
          }
        },
        isSithHere(slot) {
            return slot && this.planet && this.planet.id === slot.homeworld.id;<commit_msg>Added comments<commit_after><template>
    <div class="app-container">
        <div class="css-root">
            <h1 v-if="planet" class="css-planet-monitor">Obi-Wan currently on {{planet.name}}</h1>

            <section class="css-scrollable-list">
              <ul class="css-slots">
                <li :style="{ color: isSithHere(slot) ? 'red': '' }" v-for="slot in slots" class="css-slot" track-by="$index">
                  <h3 v-if="slot && slot.name">{{slot.name}}</h3>
                  <h6 v-if="slot && slot.homeworld">Homeworld: {{slot.homeworld.name}}</h6>
                </li>
              </ul>

              <div class="css-scroll-buttons">
                <button :class="buttonUpClass" @click.prevent="scrollUp"></button>
                <button :class="buttonDownClass" @click.prevent="scrollDown"></button>
              </div>
            </section>
      </div>
    </div>
</template>

<script>

import _ from 'lodash';

const SCROLL_UP = "scroll_up";
const SCROLL_DOWN = "scroll_down";
const NUM_SLOTS = 5;
const FIRST_SITH_ID = 3616; // Palpatine!

let xhrRequests = [];

function abortRequests() {
  for (var i=0; i < xhrRequests.length; i++) {
    xhrRequests.shift().abort();
  }
}

export default {
    name: "App",
    data() {
        return {
            planet: null,
            slots: _.fill(Array(NUM_SLOTS), null),
            isLoading: false,
            isSithHomeworld: false,
            isFirst: true,
            isLast: true
        };
    },
    events: {
        "planet-changed": function(planet){
           this.planet = planet;
           this.checkIfSithHomeworld();
        }
    },
    ready() {
        // open websocket to get current planet
        new WebSocket(`ws://${window.location.host}/ws`)
            .onmessage = (event) => {
                this.$dispatch("planet-changed", JSON.parse(event.data));
            };
        // start filling up slots
        this.fillSlots(SCROLL_DOWN, FIRST_SITH_ID, 0);
    },
    computed: {
        canScrollUp() {
          return !this.isFirst && !this.isSithHomeworld && !this.isLoading;
        },
        canScrollDown() {
          return !this.isLast && !this.isSithHomeworld && !this.isLoading;
        },
        buttonUpClass() {
          return ['css-button-up', this.canScrollUp ? '' : 'css-button-disabled']; 
        },
        buttonDownClass() {
          return ['css-button-down', this.canScrollDown ? '' : 'css-button-disabled']; 
        }
    },
    methods: {
       
        // recursively fill any empty slots, until we fill the board
        // or get to the first or last sith
        fillSlots(direction, nextId, index) {

          if (!nextId || this.isLoading) {
            return;
          }

          this.isLoading = true;

          this.$http.get("/sith/" + nextId, sith => {

            this.isLoading = false;
            this.slots.splice(index, 1, sith);

            if (direction === SCROLL_UP) {
              nextId = sith.master;
              index -= 1;
            } else {
              nextId = sith.apprentice;
              index += 1;
            }

            this.isFirst = direction === SCROLL_UP && !nextId;
            this.isLast = direction === SCROLL_DOWN && !nextId;

            this.checkIfSithHomeworld();

            if (nextId && this.slots[index] === null) {
              this.fillSlots(direction, nextId, index);
            }

          }, {
            beforeSend(req) {
              xhrRequests.push(req);
            }
          });
        },

        scrollUp () {

          if (!this.canScrollUp) {
            return;
          }

          abortRequests();

          let newSlots = this.slots.slice(0, 3);

          const firstSlot = newSlots[0];
          const nextId = firstSlot ? firstSlot.master : 0;

          newSlots.splice(0, 0, null);
          newSlots.splice(1, 0, null);

          this.slots = newSlots.slice();
          this.fillSlots(SCROLL_UP, nextId, 1);

        },

        scrollDown() {
          if (!this.canScrollDown) {
            return;
          }

          abortRequests();

          let newSlots = this.slots.slice(2);
          const lastSlot = newSlots[newSlots.length - 1];
          const nextId = lastSlot ? lastSlot.apprentice : 0;

          newSlots.splice(4, 0, null);
          newSlots.splice(5, 0, null);

          this.slots = newSlots.slice();
          this.fillSlots(SCROLL_DOWN, nextId, 3);
        },

        checkIfSithHomeworld() {
          // check if sith lives here, if so then cancel any ongoing requests.
          this.isSithHomeworld = _.some(this.slots, slot => {
            return this.isSithHere(slot);
          });
          if (this.isSithHomeworld) {
            abortRequests();
          }
        },
        isSithHere(slot) {
            return slot && this.planet && this.planet.id === slot.homeworld.id;
{'fraction_non_alphanumeric': 0.1423117709437964, 'fraction_numerical': 0.006998939554612937, 'mean_word_length': 1.6226362625139044, 'pattern_counts': {'":': 2, '<': 55, '<?xml version=': 0, '>': 59, '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': '2295244', 'n_tokens_mistral': 2963, 'n_tokens_neox': 2868, 'n_words': 536}