<commit_before>import Vue from 'vue'
import Vuetable from './components/Vuetable.vue'
import VuetablePagination from './components/VuetablePagination.vue'
import VuetablePaginationDropdown from './components/VuetablePaginationDropdown.vue'
import VuetablePaginationInfo from './components/VuetablePaginationInfo.vue'

let E_SERVER_ERROR = 'Error communicating with the server'

Vue.component('custom-actions', {
  template: [
    '
',
      '<button class="ui red button" @click="onClick(\'view-item\', rowData)"></button>',
      '<button class="ui blue button" @click="onClick(\'edit-item\', rowData)"></button>',
      '<button class="ui green button" @click="onClick(\'delete-item\', rowData)"></button>',
    '
'
  ].join(''),
  props: {
    rowData: {
      type: Object,
      required: true
    }
  },
  methods: {
    onClick: function(action, data) {
      console.log('actions: on-click', data.name)
      sweetAlert(action, data.name)
    },
  }
})

Vue.component('my-detail-row', {
  template: [
    '
',
      '
',
        'Name: ',
        '{{rowData.name}}',
      '
',
      '
',
        'Email: ',
        '{{rowData.email}}',
      '
',
      '
',
        'Nickname: ',
        '{{rowData.nickname}}',
      '
',
      '
',
        'Birthdate: ',
        '{{rowData.birthdate}}',
      '
',
      '
',
        'Gender: ',
        '{{rowData.gender}}',
      '
',
    '
'
  ].join(''),
  props: {
    rowData: {
      type: Object,
      required: true
    }
  },
  methods: {
    onClick: function(event) {
      console.log('my-detail-row: on-click', event.target)
    }
  },
})

let tableColumns = [
    {
        name: 'id',
        title: '',
        dataClass: 'center aligned',
        callback: 'showDetailRow'
    },
    {
      name: 'name',
      title: 'Full Name',
      sortField: 'name'
    },
    {
        name: 'email',
        sortField: 'email',
        visible: true
    },
    {
        name: 'nickname',
        sortField: 'nickname',
        callback: 'allCap'
    },
    {
        name: 'birthdate',
        sortField: 'birthdate',
        callback: 'formatDate|D/MM/Y'
    },
    {
        name: 'gender',
        sortField: 'gender',
        titleClass: 'center aligned',
        dataClass: 'center aligned',
        callback: 'gender'
    },
    {
      name: '__component:custom-actions',
      dataClass: 'center aligned'
    }
]

let vm = new Vue({
  el: '#app',
  components: {
    Vuetable,
    VuetablePagination,
    VuetablePaginationDropdown,
    VuetablePaginationInfo,
  },
  data: {
    loading: '',
    searchFor: '',
    moreParams: {},
    fields: tableColumns,
    sortOrder: [{
        field: 'name',
        direction: 'asc',
    }],
    multiSort: true,
    paginationComponent: 'vuetable-pagination',
    perPage: 10,
    paginationInfoTemplate: 'Showing record: {from} to {to} from {total} item(s)',
  },
  watch: {
    'perPage' (val, oldVal) {
      this.$nextTick(function() {
        this.$refs.vuetable.refresh()
      })
    },
    'paginationComponent' (val, oldVal) {
      this.$nextTick(function() {
        this.$refs.pagination.setPaginationData(this.$refs.vuetable.tablePagination)
      })
    }
  },
  methods: {
    transform: function(data) {
      let transformed = {}
      transformed.pagination = {
        total: data.total,
        per_page: data.per_page,
        current_page: data.current_page,
        last_page: data.last_page,
        next_page_url: data.next_page_url,
        prev_page_url: data.prev_page_url,
        from: data.from,
        to: data.to
      }

      transformed.data = []
      data = data.data
      for (let i = 0; i < data.length; i++) {
        transformed['data'].push({
          id: data[i].id,
          name: data[i].name,
          nickname: data[i].nickname,
          email: data[i].email,
          birthdate: data[i].birthdate,
          gender: data[i].gender,
          address: data[i].address.line1 + ' ' + data[i].address.line2 + ' ' + data[i].address.zipcode
        })
      }

      return transformed
    },
    showSettingsModal () {
      $('#settingsModal').modal({
        detachable: false,
        onVisible: function() {
          $('.ui.checkbox').checkbox()
        }
      }).modal('show')
    },
    showLoader: function() {
      this.loading = 'loading'
    },
    hideLoader: function() {
      this.loading = ''
    },
    getFieldTitle: function(field) {
      if (field.title !== '') return field.title

      if (field.name.slice(0, 2) === '__') {
        return field.name.indexOf(':') >= 0
          ? field.name.split(':')[1]
          : fiel.name.replace('__', '')
      }
    },
    allCap (value) {
      return value.toUpperCase()
    },
    formatDate (value, fmt) {
      if (value === null) return ''
      fmt = (typeof(fmt) === 'undefined') ? 'D MMM YYYY' : fmt
      return moment(value, 'YYYY-MM-DD').format(fmt)
    },
    gender (value) {
      return value === 'M'
        ? 'Male'
        : 'Female'
    },
    showDetailRow: function(value) {
      let icon = this.$refs.vuetable.isVisibleDetailRow(value) ? 'down' : 'right'
      return [
        '',
            '',
        ''
      ].join('')
    },
    setFilter: function() {
      this.moreParams = {
        'filter': this.searchFor
      }
      this.$nextTick(function() {
        this.$refs.vuetable.refresh()
      })
    },
    resetFilter: function() {
      this.searchFor = ''
      this.setFilter()
    },
    preg_quote: function( str ) {
      // http://kevin.vanzonneveld.net
      // +   original by: booeyOH
      // +   improved by: Ates Goral (http://magnetiq.com)
      // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
      // +   bugfixed by: Onno Marsman
      // *     example 1: preg_quote("$40");
      // *     returns 1: '\$40'
      // *     example 2: preg_quote("*RRRING* Hello?");
      // *     returns 2: '\*RRRING\* Hello\?'
      // *     example 3: preg_quote("\\.+*?[^]$(){}=!<>|:");
      // *     returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:'

      return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
    },
    highlight: function(needle, haystack) {
      return haystack.replace(
        new RegExp('(' + this.preg_quote(needle) + ')', 'ig'),
        '$1'
      )
    },
    rowClassCB: function(data, index) {
      return (index % 2) === 0 ? 'odd' : 'even'
    },
    onCellClicked (data, field, event) {
      console.log('cellClicked', field.name)
      if (field.name !== '__actions') {
        this.$refs.vuetable.toggleDetailRow(data.id)
      }
    },
    onCellDoubleClicked (data, field, event) {
      console.log('cellDoubleClicked:', field.name)
    },
    onLoadSuccess (response) {
      // set pagination data to pagination-info component
      this.$refs.paginationInfo.setPaginationData(response.data)

      let data = response.data.data
      if (this.searchFor !== '') {
        for (let n in data) {
          data[n].name = this.highlight(this.searchFor, data[n].name)
          data[n].email = this.highlight(this.searchFor, data[n].email)
        }
      }
    },
    onLoadError (response) {
      if (response.status == 400) {
        sweetAlert('Something\'s Wrong!', response.data.message, 'error')
      } else {
        sweetAlert('Oops', E_SERVER_ERROR, 'error')
      }
    },
    onPaginationData (tablePagination) {
      this.$refs.paginationInfo.setPaginationData(tablePagination)
      this.$refs.pagination.setPaginationData(tablePagination)
    },
    onChangePage (page) {
      this.$refs.vuetable.changePage(page)
    },
    registerEvents () {
      let self = this
      this.$on('vuetable:action', (action, data) => {
        self.onActions(action, data)
      })
      this.$on('vuetable:cell-clicked', (data, field, event) => {
        self.onCellClicked(data, field, event)
      })
      this.$on('vuetable:cell-dblclicked', (data, field, event) => {
        self.onCellDoubleClicked(data, field, event)
      })
      this.$on('vuetable:load-success', (response) => {
        self.onLoadSuccess(response)
      })
      this.$on('vuetable:load-error', (response) => {
        self.onLoadError(response)
      })
    }
  },
  created () {
    this.registerEvents()
  }
})
<commit_msg>fix typo and indent<commit_after>import Vue from 'vue'
import Vuetable from './components/Vuetable.vue'
import VuetablePagination from './components/VuetablePagination.vue'
import VuetablePaginationDropdown from './components/VuetablePaginationDropdown.vue'
import VuetablePaginationInfo from './components/VuetablePaginationInfo.vue'

let E_SERVER_ERROR = 'Error communicating with the server'

Vue.component('custom-actions', {
  template: [
    '
',
      '<button class="ui red button" @click="onClick(\'view-item\', rowData)"></button>',
      '<button class="ui blue button" @click="onClick(\'edit-item\', rowData)"></button>',
      '<button class="ui green button" @click="onClick(\'delete-item\', rowData)"></button>',
    '
'
  ].join(''),
  props: {
    rowData: {
      type: Object,
      required: true
    }
  },
  methods: {
    onClick: function(action, data) {
      console.log('actions: on-click', data.name)
      sweetAlert(action, data.name)
    },
  }
})

Vue.component('my-detail-row', {
  template: [
    '
',
      '
',
        'Name: ',
        '{{rowData.name}}',
      '
',
      '
',
        'Email: ',
        '{{rowData.email}}',
      '
',
      '
',
        'Nickname: ',
        '{{rowData.nickname}}',
      '
',
      '
',
        'Birthdate: ',
        '{{rowData.birthdate}}',
      '
',
      '
',
        'Gender: ',
        '{{rowData.gender}}',
      '
',
    '
'
  ].join(''),
  props: {
    rowData: {
      type: Object,
      required: true
    }
  },
  methods: {
    onClick: function(event) {
      console.log('my-detail-row: on-click', event.target)
    }
  },
})

let tableColumns = [
  '__sequence',
  '__checkbox:id',
  {
    name: 'id',
    title: '',
    dataClass: 'center aligned',
    callback: 'showDetailRow'
  },
  {
    name: 'name',
    title: 'Full Name',
    sortField: 'name'
  },
  {
    name: 'email',
    sortField: 'email',
    visible: true
  },
  {
    name: 'nickname',
    sortField: 'nickname',
    callback: 'allCap'
  },
  {
    name: 'birthdate',
    sortField: 'birthdate',
    callback: 'formatDate|D/MM/Y'
  },
  {
    name: 'gender',
    sortField: 'gender',
    titleClass: 'center aligned',
    dataClass: 'center aligned',
    callback: 'gender'
  },
  {
    name: '__component:custom-actions',
    dataClass: 'center aligned'
  }
]

let vm = new Vue({
  el: '#app',
  components: {
    Vuetable,
    VuetablePagination,
    VuetablePaginationDropdown,
    VuetablePaginationInfo,
  },
  data: {
    loading: '',
    searchFor: '',
    moreParams: {},
    fields: tableColumns,
    sortOrder: [{
        field: 'name',
        direction: 'asc',
    }],
    multiSort: true,
    paginationComponent: 'vuetable-pagination',
    perPage: 10,
    paginationInfoTemplate: 'Showing record: {from} to {to} from {total} item(s)',
  },
  watch: {
    'perPage' (val, oldVal) {
      this.$nextTick(function() {
        this.$refs.vuetable.refresh()
      })
    },
    'paginationComponent' (val, oldVal) {
      this.$nextTick(function() {
        this.$refs.pagination.setPaginationData(this.$refs.vuetable.tablePagination)
      })
    }
  },
  methods: {
    transform: function(data) {
      let transformed = {}
      transformed.pagination = {
        total: data.total,
        per_page: data.per_page,
        current_page: data.current_page,
        last_page: data.last_page,
        next_page_url: data.next_page_url,
        prev_page_url: data.prev_page_url,
        from: data.from,
        to: data.to
      }

      transformed.data = []
      data = data.data
      for (let i = 0; i < data.length; i++) {
        transformed['data'].push({
          id: data[i].id,
          name: data[i].name,
          nickname: data[i].nickname,
          email: data[i].email,
          birthdate: data[i].birthdate,
          gender: data[i].gender,
          address: data[i].address.line1 + ' ' + data[i].address.line2 + ' ' + data[i].address.zipcode
        })
      }

      return transformed
    },
    showSettingsModal () {
      $('#settingsModal').modal({
        detachable: false,
        onVisible: function() {
          $('.ui.checkbox').checkbox()
        }
      }).modal('show')
    },
    showLoader: function() {
      this.loading = 'loading'
    },
    hideLoader: function() {
      this.loading = ''
    },
    getFieldTitle: function(field) {
      if (field.title !== '') return field.title

      if (field.name.slice(0, 2) === '__') {
        return field.name.indexOf(':') >= 0
          ? field.name.split(':')[1]
          : field.name.replace('__', '')
      }
    },
    allCap (value) {
      return value.toUpperCase()
    },
    formatDate (value, fmt) {
      if (value === null) return ''
      fmt = (typeof(fmt) === 'undefined') ? 'D MMM YYYY' : fmt
      return moment(value, 'YYYY-MM-DD').format(fmt)
    },
    gender (value) {
      return value === 'M'
        ? 'Male'
        : 'Female'
    },
    showDetailRow: function(value) {
      let icon = this.$refs.vuetable.isVisibleDetailRow(value) ? 'down' : 'right'
      return [
        '',
            '',
        ''
      ].join('')
    },
    setFilter: function() {
      this.moreParams = {
        'filter': this.searchFor
      }
      this.$nextTick(function() {
        this.$refs.vuetable.refresh()
      })
    },
    resetFilter: function() {
      this.searchFor = ''
      this.setFilter()
    },
    preg_quote: function( str ) {
      // http://kevin.vanzonneveld.net
      // +   original by: booeyOH
      // +   improved by: Ates Goral (http://magnetiq.com)
      // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
      // +   bugfixed by: Onno Marsman
      // *     example 1: preg_quote("$40");
      // *     returns 1: '\$40'
      // *     example 2: preg_quote("*RRRING* Hello?");
      // *     returns 2: '\*RRRING\* Hello\?'
      // *     example 3: preg_quote("\\.+*?[^]$(){}=!<>|:");
      // *     returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:'

      return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
    },
    highlight: function(needle, haystack) {
      return haystack.replace(
        new RegExp('(' + this.preg_quote(needle) + ')', 'ig'),
        '$1'
      )
    },
    rowClassCB: function(data, index) {
      return (index % 2) === 0 ? 'odd' : 'even'
    },
    onCellClicked (data, field, event) {
      console.log('cellClicked', field.name)
      if (field.name !== '__actions') {
        this.$refs.vuetable.toggleDetailRow(data.id)
      }
    },
    onCellDoubleClicked (data, field, event) {
      console.log('cellDoubleClicked:', field.name)
    },
    onLoadSuccess (response) {
      // set pagination data to pagination-info component
      this.$refs.paginationInfo.setPaginationData(response.data)

      let data = response.data.data
      if (this.searchFor !== '') {
        for (let n in data) {
          data[n].name = this.highlight(this.searchFor, data[n].name)
          data[n].email = this.highlight(this.searchFor, data[n].email)
        }
      }
    },
    onLoadError (response) {
      if (response.status == 400) {
        sweetAlert('Something\'s Wrong!', response.data.message, 'error')
      } else {
        sweetAlert('Oops', E_SERVER_ERROR, 'error')
      }
    },
    onPaginationData (tablePagination) {
      this.$refs.paginationInfo.setPaginationData(tablePagination)
      this.$refs.pagination.setPaginationData(tablePagination)
    },
    onChangePage (page) {
      this.$refs.vuetable.changePage(page)
    },
    registerEvents () {
      let self = this
      this.$on('vuetable:action', (action, data) => {
        self.onActions(action, data)
      })
      this.$on('vuetable:cell-clicked', (data, field, event) => {
        self.onCellClicked(data, field, event)
      })
      this.$on('vuetable:cell-dblclicked', (data, field, event) => {
        self.onCellDoubleClicked(data, field, event)
      })
      this.$on('vuetable:load-success', (response) => {
        self.onLoadSuccess(response)
      })
      this.$on('vuetable:load-error', (response) => {
        self.onLoadError(response)
      })
    }
  },
  created () {
    this.registerEvents()
  }
})
<|endoftext|>


<commit_before>function draw(){
    if(settings[2]){/* clear? */
        buffer.clearRect(
            0,
            0,
            width,
            height
        );
    }

    /* get player movement */
    player_dx = 0;
    if(key_left){
        player_dx += x / 20;
    }
    if(key_right){
        player_dx -= x / 20;
    }

    /* update player position */
    player_position += player_dx;

    /* make sure player stays in bounds */
    if(player_position > x / 1.5){
        player_position = x / 1.5;

    }else if(player_position < -x / 1.5){
        player_position = -x / 1.5;
    }

    /* draw ground grass */
    buffer.fillStyle = '#131';
    buffer.fillRect(
        0,
        y,
        width,
        y
    );

    /* move player forward by moving splits closer */
    i = splits.length - 1;
    do{
        splits[i][2] -= .05;

        /* if splits reach player, reset splits */
        if(splits[i][2] < 0){
            splits[i][2] = 25;
            split_state[1] = 1;
        }
    }while(i--);

    /* if it is time to reset split */
    if(split_state[1]){
        /* reset player position to start of new section */
        player_position = 0;

        /* switch split */
        split_state[1] = 0;
        split_state[0] = !split_state[0];
    }

    buffer.fillStyle = split_state[0] ? '#323232' : '#646464';

    /* precalculate left wall split position */
    var precalc = (splits[0][0] * (1 / splits[0][2])) + x;

    /* draw left wall extra bit */
    if(player_position > 0){
        buffer.fillRect(
            0,
            0,
            1 + (player_position >= precalc ? precalc : player_position),
            height
        );
    }

    /* draw left wall closer than split */
    if(player_position < precalc){
        buffer.beginPath();
        buffer.moveTo(
            player_position,
            y - x
        );
        buffer.lineTo(
            precalc,
            (splits[0][1] * (1 / splits[0][2])) + y
        );
        buffer.lineTo(
            precalc,
            (splits[1][1] * (1 / splits[1][2])) + y
        );
        buffer.lineTo(
            player_position,
            y + x
        );
        buffer.closePath();
        buffer.fill();
    }

    /* draw left wall further than split */
    buffer.fillStyle = split_state[0] ? '#646464' : '#323232';
    buffer.beginPath();
    buffer.moveTo(
        precalc,
        (splits[0][1] * (1 / splits[0][2])) + y
    );
    buffer.lineTo(
        x,
        y
    );
    buffer.lineTo(
        precalc,
        (splits[1][1] * (1 / splits[1][2])) + y
    );
    buffer.closePath();
    buffer.fill();

    buffer.fillStyle = split_state[0] ? '#646464' : '#323232';

    /* precalculate right wall split position */
    precalc = (splits[2][0] * (1 / splits[2][2])) + x;

    /* draw right wall extra bit */
    if(player_position < 0){
        buffer.fillRect(
            width + player_position < precalc ? precalc - 1 : width + player_position - 1,
            0,
            -player_position,
            height
        );
    }

    /* draw right wall closer than split */
    if(width + player_position > precalc){
        buffer.beginPath();
        buffer.moveTo(
            width + player_position,
            y - x
        );
        buffer.lineTo(
            precalc,
            (splits[2][1] * (1 / splits[2][2])) + y
        );
        buffer.lineTo(
            precalc,
            (splits[3][1] * (1 / splits[3][2])) + y
        );
        buffer.lineTo(
            width + player_position,
            y + x
        );
        buffer.closePath();
        buffer.fill();
    }

    /* draw right wall further than split */
    buffer.fillStyle = split_state[0] ? '#323232' : '#646464';

    buffer.beginPath();
    buffer.moveTo(
        precalc,
        (splits[2][1] * (1 / splits[2][2])) + y
    );
    buffer.lineTo(
        x,
        y
    );
    buffer.lineTo(
        precalc,
        (splits[3][1] * (1 / splits[3][2])) + y
    );
    buffer.closePath();
    buffer.fill();

    if(settings[2]){/* clear? */
        canvas.clearRect(
            0,
            0,
            width,
            height
        );
    }
    canvas.drawImage(
        get('buffer'),
        0,
        0
    );
}

function get(i){
    return document.getElementById(i);
}

function resize(){
    if(mode > 0){
        width = window.innerWidth;
        get('buffer').width = width;
        get('canvas').width = width;

        height = window.innerHeight;
        get('buffer').height = height;
        get('canvas').height = height;

        x = width / 2;
        y = height / 2;
    }
}

function random_number(i){
    return Math.floor(Math.random() * i);
}

function save(){
    i = 1;
    do{
        j = [
            'audio-volume',
            'ms-per-frame'
        ][i];
        if(isNaN(get(j).value) || get(j).value === [1, 25][i]){
            ls.removeItem('fractalrunner-' + i);
            settings[i] = [1, 25][i];
            get(j).value = settings[i];

        }else{
            settings[i] = parseFloat(get(j).value);
            ls.setItem(
                'fractalrunner-' + i,
                settings[i]
            );
        }
    }while(i--);

    settings[2] = get('clear').checked;
    if(settings[2]){
        ls.removeItem('fractalrunner-2');

    }else{
        ls.setItem(
            'fractalrunner-2',
            0
        );
    }

    i = 1;
    do{
        if(get(['movement-keys', 'restart-key'][i]).value === ['AD', 'H'][i]){
            ls.removeItem('fractalrunner-' + (i + 3));
            settings[i + 3] = ['AD', 'H'][i];

        }else{
            settings[i + 3] = get(['movement-keys', 'restart-key'][i]).value;
            ls.setItem(
                'fractalrunner-' + (i + 3),
                settings[i + 3]
            );
        }
    }while(i--);
}

function setmode(newmode, newgame){
    clearInterval(interval);

    split_state = [0, 0];

    mode = newmode;

    /* new game mode */
    if(mode > 0){
        if(newgame){
            save();
        }

        splits = [
            [-50, -50, 25],
            [-50,  50, 25],
            [ 50, -50, 25],
            [ 50,  50, 25]
        ];

        if(newgame){
            get('page').innerHTML = '<canvas id=canvas></canvas>';

            buffer = get('buffer').getContext('2d');
            canvas = get('canvas').getContext('2d');

            resize();
        }

        interval = setInterval('draw()', settings[1]);/* milliseconds per frame */

    /* main menu mode */
    }else{
        buffer = 0;
        canvas = 0;

        get('page').innerHTML = '

Fractal Runner

Walled Corridor

<input disabled size=3 style=border:0 type=text value=ESC>Main Menu
<input id=movement-keys maxlength=2 size=3 type=text value='
            + settings[3] + '>Move ←→
<input id=restart-key maxlength=1 size=3 type=text value='
            + settings[4] + '>Restart

<input id=audio-volume max=1 min=0 step=.01 type=range value='
            + settings[0] + '>Audio
<input '
            + (settings[2] ? 'checked ' : '') + 'id=clear type=checkbox>Clear
Reset Settings
Hack

<input id=ms-per-frame size=1 type=text value='
            + settings[1] + '>ms/Frame

';
    }
}

var buffer = 0;
var canvas = 0;
var height = 0;
var i = 0;
var interval = 0;
var j = 0;
var key_left = 0;
var key_right = 0;
var ls = window.localStorage;
var player_dx = 0;
var player_position = 0;
var mode = 0;
var split_state = [];
var splits = [];
var settings = [
    ls.getItem('fractalrunner-0') === null ? 1 : parseFloat(ls.getItem('fractalrunner-0')),/* audio volume */
    ls.getItem('fractalrunner-1') === null ? 25 : parseFloat(ls.getItem('fractalrunner-1')),/* milliseconds per frame */
    ls.getItem('fractalrunner-2') === null,/* clear? */
    ls.getItem('fractalrunner-3') === null ? 'AD' : ls.getItem('fractalrunner-3'),/* movement keys */
    ls.getItem('fractalrunner-4') === null ? 'H' : ls.getItem('fractalrunner-4')/* restart key */
];
var width = 0;
var x = 0;
var y = 0;

setmode(0, 1);

window.onkeydown = function(e){
    if(mode > 0){
        i = window.event ? event : e;
        i = i.charCode ? i.charCode : i.keyCode;
        if(String.fromCharCode(i) === settings[3][0]){
            key_left = 1;

        }else if(String.fromCharCode(i) === settings[3][1]){
            key_right = 1;

        /* new game */
        }else if(String.fromCharCode(i) === settings[4]){
            setmode(mode, 0);

        /* return to main menu */
        }else if(i===27){/* ESC */
            setmode(0, 1);

        }
    }
};

window.onkeyup = function(e){
    i = window.event ? event : e;
    i = i.charCode ? i.charCode : i.keyCode;
    if(String.fromCharCode(i) === settings[3][0]){
        key_left = 0;

    }else if(String.fromCharCode(i) === settings[3][1]){
        key_right = 0;
    }
};

window.onresize = resize;
<commit_msg>improved formatting<commit_after>function draw(){
    if(settings[2]){// clear?
        buffer.clearRect(
            0,
            0,
            width,
            height
        );
    }

    // get player movement
    player_dx = 0;
    if(key_left){
        player_dx += x / 20;
    }
    if(key_right){
        player_dx -= x / 20;
    }

    // update player position
    player_position += player_dx;

    // make sure player stays in bounds
    if(player_position > x / 1.5){
        player_position = x / 1.5;

    }else if(player_position < -x / 1.5){
        player_position = -x / 1.5;
    }

    // draw ground grass
    buffer.fillStyle = '#131';
    buffer.fillRect(
        0,
        y,
        width,
        y
    );

    // move player forward by moving splits closer
    i = splits.length - 1;
    do{
        splits[i][2] -= .05;

        // if splits reach player, reset splits
        if(splits[i][2] < 0){
            splits[i][2] = 25;
            split_state[1] = 1;
        }
    }while(i--);

    // if it is time to reset split
    if(split_state[1]){
        // reset player position to start of new section
        player_position = 0;

        // switch split
        split_state[1] = 0;
        split_state[0] = !split_state[0];
    }

    buffer.fillStyle = split_state[0] ? '#323232' : '#646464';

    // precalculate left wall split position
    var precalc = (splits[0][0] * (1 / splits[0][2])) + x;

    // draw left wall extra bit
    if(player_position > 0){
        buffer.fillRect(
            0,
            0,
            1 + (player_position >= precalc ? precalc : player_position),
            height
        );
    }

    // draw left wall closer than split
    if(player_position < precalc){
        buffer.beginPath();
        buffer.moveTo(
            player_position,
            y - x
        );
        buffer.lineTo(
            precalc,
            (splits[0][1] * (1 / splits[0][2])) + y
        );
        buffer.lineTo(
            precalc,
            (splits[1][1] * (1 / splits[1][2])) + y
        );
        buffer.lineTo(
            player_position,
            y + x
        );
        buffer.closePath();
        buffer.fill();
    }

    // draw left wall further than split
    buffer.fillStyle = split_state[0] ? '#646464' : '#323232';
    buffer.beginPath();
    buffer.moveTo(
        precalc,
        (splits[0][1] * (1 / splits[0][2])) + y
    );
    buffer.lineTo(
        x,
        y
    );
    buffer.lineTo(
        precalc,
        (splits[1][1] * (1 / splits[1][2])) + y
    );
    buffer.closePath();
    buffer.fill();

    buffer.fillStyle = split_state[0] ? '#646464' : '#323232';

    // precalculate right wall split position
    precalc = (splits[2][0] * (1 / splits[2][2])) + x;

    // draw right wall extra bit
    if(player_position < 0){
        buffer.fillRect(
            width + player_position < precalc ? precalc - 1 : width + player_position - 1,
            0,
            -player_position,
            height
        );
    }

    // draw right wall closer than split
    if(width + player_position > precalc){
        buffer.beginPath();
        buffer.moveTo(
            width + player_position,
            y - x
        );
        buffer.lineTo(
            precalc,
            (splits[2][1] * (1 / splits[2][2])) + y
        );
        buffer.lineTo(
            precalc,
            (splits[3][1] * (1 / splits[3][2])) + y
        );
        buffer.lineTo(
            width + player_position,
            y + x
        );
        buffer.closePath();
        buffer.fill();
    }

    // draw right wall further than split
    buffer.fillStyle = split_state[0] ? '#323232' : '#646464';

    buffer.beginPath();
    buffer.moveTo(
        precalc,
        (splits[2][1] * (1 / splits[2][2])) + y
    );
    buffer.lineTo(
        x,
        y
    );
    buffer.lineTo(
        precalc,
        (splits[3][1] * (1 / splits[3][2])) + y
    );
    buffer.closePath();
    buffer.fill();

    if(settings[2]){// clear?
        canvas.clearRect(
            0,
            0,
            width,
            height
        );
    }
    canvas.drawImage(
        get('buffer'),
        0,
        0
    );
}

function get(i){
    return document.getElementById(i);
}

function resize(){
    if(mode > 0){
        width = window.innerWidth;
        get('buffer').width = width;
        get('canvas').width = width;

        height = window.innerHeight;
        get('buffer').height = height;
        get('canvas').height = height;

        x = width / 2;
        y = height / 2;
    }
}

function random_number(i){
    return Math.floor(Math.random() * i);
}

function save(){
    i = 1;
    do{
        j = [
            'audio-volume',
            'ms-per-frame'
        ][i];
        if(isNaN(get(j).value) || get(j).value === [1, 25][i]){
            ls.removeItem('fractalrunner-' + i);
            settings[i] = [1, 25][i];
            get(j).value = settings[i];

        }else{
            settings[i] = parseFloat(get(j).value);
            ls.setItem(
                'fractalrunner-' + i,
                settings[i]
            );
        }
    }while(i--);

    settings[2] = get('clear').checked;
    if(settings[2]){
        ls.removeItem('fractalrunner-2');

    }else{
        ls.setItem(
            'fractalrunner-2',
            0
        );
    }

    i = 1;
    do{
        if(get(['movement-keys', 'restart-key'][i]).value === ['AD', 'H'][i]){
            ls.removeItem('fractalrunner-' + (i + 3));
            settings[i + 3] = ['AD', 'H'][i];

        }else{
            settings[i + 3] = get(['movement-keys', 'restart-key'][i]).value;
            ls.setItem(
                'fractalrunner-' + (i + 3),
                settings[i + 3]
            );
        }
    }while(i--);
}

function setmode(newmode, newgame){
    clearInterval(interval);

    split_state = [0, 0];

    mode = newmode;

    // new game mode
    if(mode > 0){
        if(newgame){
            save();
        }

        splits = [
            [-50, -50, 25],
            [-50,  50, 25],
            [ 50, -50, 25],
            [ 50,  50, 25]
        ];

        if(newgame){
            get('page').innerHTML = '<canvas id=canvas></canvas>';

            buffer = get('buffer').getContext('2d');
            canvas = get('canvas').getContext('2d');

            resize();
        }

        interval = setInterval('draw()', settings[1]);// milliseconds per frame

    // main menu mode
    }else{
        buffer = 0;
        canvas = 0;

        get('page').innerHTML = '

Fractal Runner

Walled Corridor

<input disabled size=3 style=border:0 value=ESC>Main Menu
<input id=movement-keys maxlength=2 size=3 value='
            + settings[3] + '>Move ←→
<input id=restart-key maxlength=1 size=3 value='
            + settings[4] + '>Restart

<input id=audio-volume max=1 min=0 step=.01 type=range value='
            + settings[0] + '>Audio
<input '
            + (settings[2] ? 'checked ' : '') + 'id=clear type=checkbox>Clear
Reset Settings
Hack

<input id=ms-per-frame size=1 value='
            + settings[1] + '>ms/Frame

';
    }
}

var buffer = 0;
var canvas = 0;
var height = 0;
var i = 0;
var interval = 0;
var j = 0;
var key_left = 0;
var key_right = 0;
var ls = window.localStorage;
var player_dx = 0;
var player_position = 0;
var mode = 0;
var split_state = [];
var splits = [];
var settings = [
    ls.getItem('fractalrunner-0') === null ?    1 : parseFloat(ls.getItem('fractalrunner-0')),// audio volume
    ls.getItem('fractalrunner-1') === null ?   25 : parseFloat(ls.getItem('fractalrunner-1')),// milliseconds per frame
    ls.getItem('fractalrunner-2') === null,// clear?
    ls.getItem('fractalrunner-3') === null ? 'AD' : ls.getItem('fractalrunner-3'),// movement keys
    ls.getItem('fractalrunner-4') === null ?  'H' : ls.getItem('fractalrunner-4')// restart key
];
var width = 0;
var x = 0;
var y = 0;

setmode(0, 1);

window.onkeydown = function(e){
    if(mode > 0){
        i = window.event ? event : e;
        i = i.charCode ? i.charCode : i.keyCode;
        if(String.fromCharCode(i) === settings[3][0]){
            key_left = 1;

        }else if(String.fromCharCode(i) === settings[3][1]){
            key_right = 1;

        // new game
        }else if(String.fromCharCode(i) === settings[4]){
            setmode(mode, 0);

        // return to main menu
        }else if(i===27){// ESC
            setmode(0, 1);

        }
    }
};

window.onkeyup = function(e){
    i = window.event ? event : e;
    i = i.charCode ? i.charCode : i.keyCode;
    if(String.fromCharCode(i) === settings[3][0]){
        key_left = 0;

    }else if(String.fromCharCode(i) === settings[3][1]){
        key_right = 0;
    }
};

window.onresize = resize;
<|endoftext|>


<commit_before>require('dotenv').load();

const craftai = require('craft-ai').createClient;
const fs = require('fs');
const path = require('path');
const process = require('process');

var utils = require('./utils');

const ROOM1 = 'BEDROOM_1';
const ROOM2 = 'LIVING_ROOM';
const ROOM3 = 'RESTROOM';

const GENERATOR_FILTER = [ROOM1, ROOM2, ROOM3];
const GENERATOR_NAME = 'smarthome';

const LOCAL_FILE_PATH1 = path.join(__dirname, `../data/twor_${ROOM1}.json`);
const LOCAL_FILE_PATH2 = path.join(__dirname, `../data/twor_${ROOM2}.json`);
const LOCAL_FILE_PATH3 = path.join(__dirname, `../data/twor_${ROOM3}.json`);

// 0 - Create the craft client
const CRAFT_CLIENT = craftai(process.env.CRAFT_TOKEN);

// 1 - Retrieve the prepared data
utils.readData(LOCAL_FILE_PATH1)
  .then((context) => {
    const agentName = ROOM1;
    // 2 - Cleanup the mess (agent's name can't be duplicate)
    return CRAFT_CLIENT.deleteAgent(agentName)
      // 3 - Create the agent 1
      .then(() => {
        console.log(`Creating agent ${agentName}.`);
        return CRAFT_CLIENT.createAgent({
          context: {
            movement: {
              type: 'continuous'
            },
            light: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day'
            }
          },
          output: ['light'],
          time_quantum: 15 * 60 // 15 min
        }, agentName);
      })
      // 4 - Send the dataset's operations
      .then(() => {
        console.log(`Adding context operations for agent ${agentName}...`);
        return CRAFT_CLIENT.addAgentContextOperations(agentName, context);
      })
      .then(() => {
        console.log(`Computing the decision model for agent ${agentName} (this may take a little while)...`);
        // 5 - Compute decision from the decision tree in order to automate the light
        // Download the tree
        return CRAFT_CLIENT.getAgentDecisionTree(agentName, context[context.length - 1].timestamp, 2);
      })
      .then((tree) => {
        console.log('Decision tree computed!');
        // 6 - Get decisions
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 0
            },
            new craftai.Time('2010-01-04T01:30:00+09:00')
          );
          console.log(`Decision taken:\n- The light is ${d.output.light.predicted_value} when there is no movement at 1:30AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 0
            },
            new craftai.Time('2010-01-04T08:58:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is no movement at 8:58AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 0
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is no movement at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T17:03:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 5:03PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T20:55:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 8:55PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T22:07:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 10:07PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 10
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is a lot of movement at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 10
            },
            new craftai.Time('2010-01-04T02:17:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is a lot of movement at 2:17AM.`);
        }
      })
      .then(() => {
        const deleteBulkPayload = [
          { id: ROOM1 },
          { id: ROOM2 },
          { id: ROOM3 }
        ];
        return CRAFT_CLIENT.deleteAgentBulk(deleteBulkPayload);
      })
      // 7 - Create Agent 1, 2 and 3
      .then(() => utils.readData(LOCAL_FILE_PATH1))
      .then((context_1) => {
        operations_agent_1 = utils.prepareData(context_1, ROOM1);
        return utils.readData(LOCAL_FILE_PATH2);
      })
      .then((context_2) => {
        operations_agent_2 = utils.prepareData(context_2, ROOM2);
        return utils.readData(LOCAL_FILE_PATH3);
      })
      .then((context_3) => {
        operations_agent_3 = utils.prepareData(context_3, ROOM3);
        const configuration = {
          context: {
            movement: {
              type: 'continuous'
            },
            stateChange: {
              type: 'enum'
            },
            room: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day'
            }
          },
          output: ['stateChange'],
          time_quantum: 15 * 60 // 15 min
        };
        const createBulkPayload = [
          { id: ROOM1, configuration: configuration },
          { id: ROOM2, configuration: configuration },
          { id: ROOM3, configuration: configuration }
        ];
        console.log(`Creating agents ${ROOM1}, ${ROOM2} and ${ROOM3}.`);
        return CRAFT_CLIENT.createAgentBulk(createBulkPayload)
      })
      .then(() => {
        const contextOperationBulkPayload = [
          { id: ROOM1, operations: operations_agent_1 },
          { id: ROOM2, operations: operations_agent_2 },
          { id: ROOM3, operations: operations_agent_3 }
        ];
        console.log(`Adding context operations for agents ${ROOM1}, ${ROOM2} and ${ROOM3}.`);
        return CRAFT_CLIENT.addAgentContextOperationsBulk(contextOperationBulkPayload)
      })
      .then(() => {
        const GENERATOR_CONFIGURATION = {
          context: {
            stateChange: {
              type: 'enum'
            },
            room: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day',
              is_generated: true
            }
          },
          output: [
            "stateChange"
          ],
          learning_period: 1500000,
          tree_max_operations: 15000,
          operations_as_events: true,
          filter: GENERATOR_FILTER
        };
        console.log(`Creating generator ${GENERATOR_NAME}.`);
        // 8 - Create generator
        return CRAFT_CLIENT.createGenerator(GENERATOR_CONFIGURATION, GENERATOR_NAME);
      })
      .then(() => {
        console.log(`Computing the decision model for generator ${GENERATOR_NAME} (this may take a little while)...`);
        // 9 - Compute decision from the decision tree in order to automate the light
        // Download the tree
        return CRAFT_CLIENT.getGeneratorDecisionTree(GENERATOR_NAME, context[context.length - 1].timestamp);
      })
      .then((tree) => {
        console.log('Generator decision tree computed!');
        // 10 - Get decisions
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM1
            },
            new craftai.Time('2010-01-04T01:30:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the bedroom at 1:30AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM2
            },
            new craftai.Time('2010-01-04T08:58:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the living room at 8:58AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM3
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the restroom at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM1
            },
            new craftai.Time('2010-01-08T02:17:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the bedroom at 2:17AM.`);
        }
      })
  })
  .catch((error) => {
    console.log('Error!', error);
    process.exit(1);
  });
<commit_msg>Update src/main.js<commit_after>require('dotenv').load();

const craftai = require('craft-ai').createClient;
const fs = require('fs');
const path = require('path');
const process = require('process');

var utils = require('./utils');

const ROOM1 = 'BEDROOM_1';
const ROOM2 = 'LIVING_ROOM';
const ROOM3 = 'RESTROOM';

const GENERATOR_FILTER = [ROOM1, ROOM2, ROOM3];
const GENERATOR_NAME = 'smarthome';

const LOCAL_FILE_PATH1 = path.join(__dirname, `../data/twor_${ROOM1}.json`);
const LOCAL_FILE_PATH2 = path.join(__dirname, `../data/twor_${ROOM2}.json`);
const LOCAL_FILE_PATH3 = path.join(__dirname, `../data/twor_${ROOM3}.json`);

// 0 - Create the craft client
const CRAFT_CLIENT = craftai(process.env.CRAFT_TOKEN);

// 1 - Retrieve the prepared data
utils.readData(LOCAL_FILE_PATH1)
  .then((context) => {
    const agentName = ROOM1;
    // 2 - Cleanup the mess (agent's name can't be duplicate)
    return CRAFT_CLIENT.deleteAgent(agentName)
      // 3 - Create the agent 1
      .then(() => {
        console.log(`Creating agent ${agentName}.`);
        return CRAFT_CLIENT.createAgent({
          context: {
            movement: {
              type: 'continuous'
            },
            light: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day'
            }
          },
          output: ['light'],
          time_quantum: 15 * 60 // 15 min
        }, agentName);
      })
      // 4 - Send the dataset's operations
      .then(() => {
        console.log(`Adding context operations for agent ${agentName}...`);
        return CRAFT_CLIENT.addAgentContextOperations(agentName, context);
      })
      .then(() => {
        console.log(`Computing the decision model for agent ${agentName} (this may take a little while)...`);
        // 5 - Compute decision from the decision tree in order to automate the light
        // Download the tree
        return CRAFT_CLIENT.getAgentDecisionTree(agentName, context[context.length - 1].timestamp, 2);
      })
      .then((tree) => {
        console.log('Decision tree computed!');
        // 6 - Get decisions
        const d1 = craftai.interpreter.decide(
          tree,
          {
            movement: 0
          },
          new craftai.Time('2010-01-04T01:30:00+09:00')
        );
        console.log(`Decision taken:\n- The light is ${d1.output.light.predicted_value} when there is no movement at 1:30AM.`);
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 0
            },
            new craftai.Time('2010-01-04T08:58:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is no movement at 8:58AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 0
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is no movement at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T17:03:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 5:03PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T20:55:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 8:55PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T22:07:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 10:07PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 10
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is a lot of movement at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 10
            },
            new craftai.Time('2010-01-04T02:17:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is a lot of movement at 2:17AM.`);
        }
      })
      .then(() => {
        const deleteBulkPayload = [
          { id: ROOM1 },
          { id: ROOM2 },
          { id: ROOM3 }
        ];
        return CRAFT_CLIENT.deleteAgentBulk(deleteBulkPayload);
      })
      // 7 - Create Agent 1, 2 and 3
      .then(() => utils.readData(LOCAL_FILE_PATH1))
      .then((context_1) => {
        operations_agent_1 = utils.prepareData(context_1, ROOM1);
        return utils.readData(LOCAL_FILE_PATH2);
      })
      .then((context_2) => {
        operations_agent_2 = utils.prepareData(context_2, ROOM2);
        return utils.readData(LOCAL_FILE_PATH3);
      })
      .then((context_3) => {
        operations_agent_3 = utils.prepareData(context_3, ROOM3);
        const configuration = {
          context: {
            movement: {
              type: 'continuous'
            },
            stateChange: {
              type: 'enum'
            },
            room: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day'
            }
          },
          output: ['stateChange'],
          time_quantum: 15 * 60 // 15 min
        };
        const createBulkPayload = [
          { id: ROOM1, configuration: configuration },
          { id: ROOM2, configuration: configuration },
          { id: ROOM3, configuration: configuration }
        ];
        console.log(`Creating agents ${ROOM1}, ${ROOM2} and ${ROOM3}.`);
        return CRAFT_CLIENT.createAgentBulk(createBulkPayload)
      })
      .then(() => {
        const contextOperationBulkPayload = [
          { id: ROOM1, operations: operations_agent_1 },
          { id: ROOM2, operations: operations_agent_2 },
          { id: ROOM3, operations: operations_agent_3 }
        ];
        console.log(`Adding context operations for agents ${ROOM1}, ${ROOM2} and ${ROOM3}.`);
        return CRAFT_CLIENT.addAgentContextOperationsBulk(contextOperationBulkPayload)
      })
      .then(() => {
        const GENERATOR_CONFIGURATION = {
          context: {
            stateChange: {
              type: 'enum'
            },
            room: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day',
              is_generated: true
            }
          },
          output: [
            "stateChange"
          ],
          learning_period: 1500000,
          tree_max_operations: 15000,
          operations_as_events: true,
          filter: GENERATOR_FILTER
        };
        console.log(`Creating generator ${GENERATOR_NAME}.`);
        // 8 - Create generator
        return CRAFT_CLIENT.createGenerator(GENERATOR_CONFIGURATION, GENERATOR_NAME);
      })
      .then(() => {
        console.log(`Computing the decision model for generator ${GENERATOR_NAME} (this may take a little while)...`);
        // 9 - Compute decision from the decision tree in order to automate the light
        // Download the tree
        return CRAFT_CLIENT.getGeneratorDecisionTree(GENERATOR_NAME, context[context.length - 1].timestamp);
      })
      .then((tree) => {
        console.log('Generator decision tree computed!');
        // 10 - Get decisions
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM1
            },
            new craftai.Time('2010-01-04T01:30:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the bedroom at 1:30AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM2
            },
            new craftai.Time('2010-01-04T08:58:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the living room at 8:58AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM3
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the restroom at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM1
            },
            new craftai.Time('2010-01-08T02:17:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the bedroom at 2:17AM.`);
        }
      })
  })
  .catch((error) => {
    console.log('Error!', error);
    process.exit(1);
  });
<|endoftext|>


<commit_before>/**
 * This class collects anonymous data from the game and sends it to
 * a web server that catalogs everything. No personal information or
 * image is sent, just the current captured emotion (e.g. happy, sad, etc).
 */

var FTG = FTG || {};

FTG.Collector = function() {
	var COLLECT_INTERVAL 	= 500; 	// time, in milliseconds, to wait between logging entries.
	var SEND_INTERVAL 		= 5000;	// time, in milliseconds, to wait until data is send to the server

	var mLastTimeCollected = 0;
	var mLastTimeSent = 0;
	var mTimeGameStarted = 0;
	var mDebugConsole;
	var mServerURL = '../backend/';
	var mData = [];

	var isTimeToCollect = function() {
		return (getTimestamp() - mLastTimeCollected) >= COLLECT_INTERVAL;
	};

	var isTimeToSendData = function() {
		return (getTimestamp() - mLastTimeSent) >= SEND_INTERVAL;
	}

	var getTimestamp = function() {
		return (new Date()).getTime();
	};

	var init = function() {
		var aContainer;

		aContainer = document.getElementById('container'); // TODO: get this from config

		if(aContainer) {
			mDebugConsole = document.createElement('span');
			mDebugConsole.id = 'collector-console';
			mDebugConsole.style.position = 'absolute';
			mDebugConsole.style.bottom = '-20px';
			mDebugConsole.style.right = '20px';
			mDebugConsole.innerHTML = 'Waiting for camera setup';
			aContainer.appendChild(mDebugConsole);
		}
	};

	init();

	// Adds a new entry to the data log.
	this.log = function(theData, theForce) {
		// Collect only if it is time to do it
		if(isTimeToCollect() || theForce) {
			mData.push({t: getTimestamp(), d: JSON.stringify(theData)});

			if(!theForce) {
				mLastTimeCollected = getTimestamp();
			}
		}
	};

	// Send current recorded data to the server
	this.send = function(theUid, theGameId, theForce) {
		var aXmlRequest,
			aData;

		if(isTimeToSendData() || theForce) {
			if(mData.length < 0) {
				return;
			}

			mLastTimeSent = getTimestamp();

		    aData = new FormData();
			aData.append('uid', theUid);
			aData.append('game', theGameId);
			aData.append('data', JSON.stringify(mData));

		    aXmlRequest = new XMLHttpRequest();
	        aXmlRequest.onreadystatechange = function() {
	            if(aXmlRequest.readyState == 4 && aXmlRequest.status == 200) {
					console.log('[Collector] Data sent!', aXmlRequest.responseText);
	            }
	        };

	        aXmlRequest.open('post', mServerURL);
	        aXmlRequest.send(aData);

			// Clear the current data buffer
			this.clear();
		}
	};

	// Clear any data stored until now.
	this.clear = function() {
		mData.length = 0;
	};

	// Informs the data collector that the game has started.
	this.markGameStarted = function() {
		mTimeGameStarted = getTimestamp();
	};

	// Update the data collector internal functions (e.g. debug panel)
	this.update = function() {
		mDebugConsole.innerHTML = 'Subject ID: XYZ
Time: ' + (getTimestamp() - mTimeGameStarted);
	};
};
<commit_msg>Data collector debug console is more useful now.<commit_after>/**
 * This class collects anonymous data from the game and sends it to
 * a web server that catalogs everything. No personal information or
 * image is sent, just the current captured emotion (e.g. happy, sad, etc).
 */

var FTG = FTG || {};

FTG.Collector = function() {
	var COLLECT_INTERVAL 	= 500; 	// time, in milliseconds, to wait between logging entries.
	var SEND_INTERVAL 		= 5000;	// time, in milliseconds, to wait until data is send to the server

	var mLastTimeCollected = 0;
	var mLastTimeSent = 0;
	var mTimeGameStarted = 0;
	var mDebugConsole;
	var mUid;
	var mServerURL = '../backend/';
	var mData = [];

	var isTimeToCollect = function() {
		return (getTimestamp() - mLastTimeCollected) >= COLLECT_INTERVAL;
	};

	var isTimeToSendData = function() {
		return (getTimestamp() - mLastTimeSent) >= SEND_INTERVAL;
	}

	var getTimestamp = function() {
		return (new Date()).getTime();
	};

	// From: http://stackoverflow.com/a/847196/29827
	var formaTime = function(theTimestamp) {
		var aDate,
			aMinutes,
			aSeconds;

		aDate = new Date(theTimestamp);
		aMinutes = '0' + aDate.getMinutes();
		aSeconds = '0' + aDate.getSeconds();

		// Will display time in 10:30:23 format
		return aMinutes.substr(-2) + ':' + aSeconds.substr(-2);
	};

	// Get variables in the game URL (the ones like ?var=value&var2=value)
	var getURLParamByName = function(theName) {
		var aRegex;

        theName = theName.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
        aRegex = new RegExp('[\\?&]' + theName + '=([^&#]*)'),
        aResults = aRegex.exec(location.search);

        return aResults === null ? '' : decodeURIComponent(aResults[1].replace(/\+/g, ' '));
    };

	var init = function() {
		var aContainer;

		// Get the user ID from the URL
		mUid = getURLParamByName('id');

		if(mUid == '') {
			alert('Oops! There is no Uid?');
		}

		aContainer = document.getElementById('container'); // TODO: get this from config

		if(aContainer) {
			mDebugConsole = document.createElement('span');
			mDebugConsole.id = 'collector-console';
			mDebugConsole.style.position = 'absolute';
			mDebugConsole.style.bottom = '-80px';
			mDebugConsole.style.right = '20px';
			mDebugConsole.innerHTML = 'Waiting for game start. Subject ID: ' + mUid;
			aContainer.appendChild(mDebugConsole);
		}
	};

	init();

	// Adds a new entry to the data log.
	this.log = function(theData, theForce) {
		// Collect only if it is time to do it
		if(isTimeToCollect() || theForce) {
			mData.push({t: getTimestamp(), d: JSON.stringify(theData)});

			if(!theForce) {
				mLastTimeCollected = getTimestamp();
			}
		}
	};

	// Send current recorded data to the server
	this.send = function(theUid, theGameId, theForce) {
		var aXmlRequest,
			aData;

		if(isTimeToSendData() || theForce) {
			if(mData.length < 0) {
				return;
			}

			mLastTimeSent = getTimestamp();

		    aData = new FormData();
			aData.append('uid', theUid);
			aData.append('game', theGameId);
			aData.append('data', JSON.stringify(mData));

		    aXmlRequest = new XMLHttpRequest();
	        aXmlRequest.onreadystatechange = function() {
	            if(aXmlRequest.readyState == 4 && aXmlRequest.status == 200) {
					console.log('[Collector] Data sent!', aXmlRequest.responseText);
	            }
	        };

	        aXmlRequest.open('post', mServerURL);
	        aXmlRequest.send(aData);

			// Clear the current data buffer
			this.clear();
		}
	};

	// Clear any data stored until now.
	this.clear = function() {
		mData.length = 0;
	};

	// Informs the data collector that the game has started.
	this.markGameStarted = function() {
		mTimeGameStarted = getTimestamp();
	};

	// Update the data collector internal functions (e.g. debug panel)
	this.update = function() {
		mDebugConsole.innerHTML = 'Subject ID: ' + mUid + '
Time: ' + formaTime(getTimestamp() - mTimeGameStarted);
	};
};
<|endoftext|>


<commit_before>import React from 'react';
import classnames from 'classnames';
import YASQE from '../../node_modules/yasgui-yasqe/dist/yasqe.bundled.js';
require('../../node_modules/yasgui-yasqe/dist/yasqe.css');

class RequestForm extends React.Component {
  constructor() {
    super();

    this._handleClick = this._handleClick.bind(this);
  }

  _handleClick() {
    if(!this.props.isLoading) {
      let request = this.refs.request.getDOMNode().value;
      if(request !== "") {
        this.props.makeRequest(request);
      }
    }
  }

  componentDidMount() {
    YASQE.fromTextArea(this.refs.request.getDOMNode());
  }

  render() {
    let buttonClassNames = classnames({
      loading: this.props.isLoading,
      disabled: this.props.isLoading,
      ui: true,
      primary: true,
      button: true,
      fluid: true,
      massive: true
    });
    return (

          <textarea disabled={this.props.isLoading} ref="request" />

        <button className={buttonClassNames} onClick={this._handleClick}>Send request</button>

    );
  }
}

export default RequestForm;
<commit_msg>Removed useless import<commit_after>import React from 'react';
import classnames from 'classnames';
import YASQE from '../../node_modules/yasgui-yasqe/dist/yasqe.bundled.js';

class RequestForm extends React.Component {
  constructor() {
    super();

    this._handleClick = this._handleClick.bind(this);
  }

  _handleClick() {
    if(!this.props.isLoading) {
      let request = this.refs.request.getDOMNode().value;
      if(request !== "") {
        this.props.makeRequest(request);
      }
    }
  }

  componentDidMount() {
    YASQE.fromTextArea(this.refs.request.getDOMNode());
  }

  render() {
    let buttonClassNames = classnames({
      loading: this.props.isLoading,
      disabled: this.props.isLoading,
      ui: true,
      primary: true,
      button: true,
      fluid: true,
      massive: true
    });
    return (

          <textarea disabled={this.props.isLoading} ref="request" />

        <button className={buttonClassNames} onClick={this._handleClick}>Send request</button>

    );
  }
}

export default RequestForm;
<|endoftext|>


<commit_before>"use strict";
const express = require("express");
const app = express();
const jwt = require("express-jwt");
const fs = require("fs");
const path = require("path");
const secret = fs.readFileSync(path.resolve("ookla-extracts.pem"));

app.use(jwt({ secret, algorithms: ["RS256"] }));

app.get("/", (req, res) => {
  res.send(`JWT VERIFIED! PAYLOAD: \n ${JSON.stringify(req.user)}`);
});

app.listen(8000);
<commit_msg>allow env var for public key<commit_after>"use strict";
const express = require("express");
const app = express();
const jwt = require("express-jwt");
const fs = require("fs");
const path = require("path");
const keypath = path.resolve("ookla-extracts.pem");

let secret;
fs.access(keypath, fs.constants.R_OK, (err) => {
  secret = err ? secret = fs.readFileSync(keypath) : process.env.PUBLIC_KEY;
});

app.use(jwt({ secret, algorithms: ["RS256"] }));

app.get("/", (req, res) => {
  res.send(`JWT VERIFIED! PAYLOAD: \n ${JSON.stringify(req.user)}`);
});

app.listen(8000);
<|endoftext|>


<commit_before>( function() {
  'use strict'

  var GE;

  var Layout = {
    focusedColumn : null,
    dragging : null,
    columns : [],
    defaultColumnSize : 500,
    resizeHandleSize  : 8,
    columnID : 0,
    isFullScreen: false,
    _textBGOpacity : 0,
    __fullScreenColumn__: null,
    fullScreenColumn: null,
    getFocusedColumn: function( allowFullScreen ) {
      if( allowFullScreen ) {
        if( Layout.fullScreenColumn === null ) {
          return Layout.columns[ Layout.focusedColumn ]
        }else{
          return Layout.__fullScreenColumn__
        }
      }else{
        return Layout.columns[ Layout.focusedColumn ]
      }
    },
    textBGOpacity : function( v ) {
      this._textBGOpacity = v
      var color = 'rgba( 0, 0, 0, '+v+' )'
      $.injectCSS({ '.CodeMirror-lines pre': {background:color} })
    },
    createBoundariesForInitialLayout : function() {
      var windowWidth = $( window ).width(),
          width0 = windowWidth * .75,
          width1 = windowWidth * .25

      Layout.columns[0].setWidth( width0 )
      Layout.columns[1].setWidth( width1 )

      Layout.resizeColumns()
    },
    init : function( _GE ) {
      GE = _GE
      $( '#contentCell' ).empty()

      this.addColumn({ fullScreen:false, type:'code', autofocus:true })
      // var opacityDiv = $('#opacity')
      //
      // opacityDiv.css({
      //   background:'transparent',
      //   position:'relative',
      //   width:150,
      //   height:18,
      //   display:'inline-block',
      //   top:5,
      // })
      // opacityDiv.p = new Interface.Panel({ container:opacityDiv })
      //
      // $( opacityDiv.p.canvas ).css({ width:150, height: 18, zIndex:1  })
      // opacityDiv.p.add(
      //   new Interface.Slider({
      //     isVertical:false,
      //     bounds:[0,0,.95,.95],
      //     value:0,
      //     max:.8,
      //     target:Gibber.Environment.Layout, key:'textBGOpacity',
      //     label:'text bg opacity',
      //     background:'#000',
      //     fill:'#333',
      //     stroke:'#999'
      // }))

      window.Columns = this.columns

      $( window ).resize( this.onResizeWindow )
      $.subscribe( '/layout/resizeWindow', function( e,dict ) { Layout.resize( dict.w, dict.h ) } )

      this.__fullScreenColumn__ = GE.Layout.addColumn({ type:'code' })
      var w = $( window ).width(), h = $( window ).height()
      this.__fullScreenColumn__.header.hide()
      this.__fullScreenColumn__.toggleResizeHandle()
      this.__fullScreenColumn__.element.css({ display:'none', width: w, height: h, top:0, left:0 })
      this.__fullScreenColumn__.bodyElement.css({ width: w, height: h })
      this.__fullScreenColumn__.editor.setSize( w,h )
      this.__fullScreenColumn__.isFullScreen = true
      this.__fullScreenColumn__.editor._handlers.focus.length = 0

      GE.Layout.columns.splice( GE.Layout.columns.indexOf( this.__fullScreenColumn__ ) )
    },

    onResizeWindow : (function() {
      var w = 0, h = 0, handler = function( e ) {
        var _w = $( window ).width(), _h = $( window ).height()
        if( w !== _w || h !== _h ) {
          $.publish('/layout/resizeWindow', { w:_w, h:_h } )
          w = _w
          h = _h

          if( Layout.isFullScreen ) {
            $.publish( '/layout/contentResize', { w: $( window ).width(), h:$( window ).height(), offset:0 } )
          }else{
            var height = $( window ).height()  - $( 'thead' ).height() - $('tfoot').height()
            $.publish( '/layout/contentResize', { w: $( window ).width(), h:height, offset: $('thead').height() } )
          }
        }
      }

      return handler
    })(),

    resize : function( w,h ) {
      $( 'table' ).height( $( window ).height() )
      Layout.resizeColumns( w,h )
    },

    fullScreen : function() {
      Layout.isFullScreen = !Layout.isFullScreen
      for( var i = 0; i < Layout.columns.length; i++ ) {
        if( Layout.columns[i] ) Layout.columns[i].toggle()
      }
      //Layout.toggleHeader()
      //Layout.toggleFooter()
      $( 'thead' ).toggle()
      $( 'tfoot' ).toggle()

      if( Layout.isFullScreen ) {
        $( 'tbody' ).css({ height:'100%', width:'100%', margin:0 })
        $( '#contentCell' ).height( $( window ).height() )
        $.publish( '/layout/contentResize', { w: $( window ).width(), h:$( window ).height(), offset:0 } )
      }else{
        var height = $( window ).height()  - $( 'thead' ).height() - $('tfoot').height()
        $( 'tbody' ).css({ height:height, width:'100%', margin:0 })
        $( '#contentCell' ).height( height )
        $.publish( '/layout/contentResize', { w: $( window ).width(), h:height, offset: $('thead').height() } )
      }
    },

    emsToPixels : function( ems, element ) {
      var pixelsPerEm = Number(getComputedStyle( element, "").fontSize.match(/(\d*(\.\d*)?)px/)[1])

      return pixelsPerEm * ems
    },

    toggleHeader : function( onOrOff ) {
      if(typeof onOrOff !== 'undefined') {
        if( onOrOff ) {
          $( 'thead' ).show()
        } else {
          $( 'thead' ).hide()
        }
      }else{
        $.publish('/layout/toggleHeader', {} )

        $( 'thead' ).toggle()
      }
    },

    toggleFooter : function( onOrOff ) {
      if(typeof onOrOff !== 'undefined') {
        if( onOrOff ) {
          $( 'tfoot' ).show()
        } else {
          $( 'tfoot' ).hide()
        }
      }else{
        $.publish('/layout/toggleFooter', {} )

        $( 'tfoot' ).toggle()
      }
    },

    toggleAllResizeHandles : function() { $( '.resizeHandle' ).toggle() },

    toggleAllColumns : function() {
      for( var i = 0; i < GE.Layout.columns.length; i++ ) {
        if( GE.Layout.columns[i] !== null )
          GE.Layout.columns[ i ].toggle()
      }
    },

    toggle : function() {
      this.toggleHeader()
      this.toggleFooter()
      this.toggleAllColumns()
    },

    addColumn : function( options ) {
      return new this.Column( options, this )
    },

    load : function( name ) {
      var layout = GE.Storage.values.layouts[ name ];

      this.removeAllColumns()

      for( var i = 0; i < layout.columns.length; i++) {
        // this.addColumn( false, layout.columns[i].width, GE.modes[ layout.columns[i].mode ] )
        this.addColumn({ width:layout.columns[ i ].width, fullScreen:false, mode:layout.columns[i].mode, type:'code' })
        this.columns[i].editor.setValue( layout.columns[i].value )
      }
    },

    save : function() {
      var name = window.prompt("Enter name for layout");

      var layout = {
        header: $( '#header' ).css( 'display' ) === 'none' ? false : true,
        footer: $( '#footer' ).css( 'display' ) === 'none' ? false : true,
        columns: []
      }

      for( var i = 0; i < this.columns.length; i++ ) {
        if( this.columns[i] === null ) return

        layout.columns.push({
          width: $( this.columns[i].element ).width(),
          value: this.columns[i].editor.getValue(),
          mode: $( this.columns[i].modeSelect ).find(':selected').index()//this.columns[i].editor.mode//this.columns[i].modeIndex % GE.modes.length,
        })
      }

      GE.Storage.values.layouts[ name ] = layout
      GE.Storage.save()
    },

    getColumnByID : function( id ) {
      for( var i = 0; i < this.columns.length; i++ ) {
        var col = this.columns[ i ]

        if( col === null ) continue;

        if( col.id === id ) {
          return col;
        }
      }
      return null;
    },

    removeAllColumns : function() {
      for( var i = this.columns.length - 1; i >= 0; i-- ) {
        var col = this.columns[ i ]

        if( col === null ) continue;

        col.element.remove()
      }
      this.columns.length = 0
    },

    removeColumn : function( columnNumber ) {
      var col = this.getColumnByID( columnNumber )

      if( col === null ) return

      if( col.element ) col.element.remove()

      this.columns[ this.columns.indexOf( col ) ] = null
      // this.columns.splice( this.columns.indexOf( col ), 1 )

      this.resizeColumns()
    },

    handleResizeEventForColumn : function(_col) {
      ( function() {
        var col = _col,
        columnResizeHandler = function(e) {
          var newWidthCandidate = e.pageX - col.element.position().left
          col.width = newWidthCandidate > 300 ? newWidthCandidate : 300
          col.element.width( col.width )

          if( col.onresize ) col.onresize( col.width )

          GE.Layout.resizeColumns()
        },
        columnResizeEndHandler = function(e) {
          $( window ).unbind( "mousemove", columnResizeHandler );
          $( window ).unbind( "mouseup", columnResizeEndHandler );
          $( "body ").css( "-webkit-user-select", "text" );
        };

        col.resizeHandle.on( 'mousedown', function(e) {
          $( "body" ).css( "-webkit-user-select", "none" );

          $( window ).on( 'mousemove', columnResizeHandler )

          $( window ).on( 'mouseup',  columnResizeEndHandler )
        })
      })()
    },
    setColumnBodyHeight : function( col ) {
      var headerHeight = $('thead').height(),
          columnHeight = $(window).height() - headerHeight - $('tfoot').height() - col.header.outerHeight()

      col.bodyElement.css({ height: columnHeight })
    },

    resizeColumns : function( windowWidth, windowHeight ) {
      if( isNaN(windowHeight) ) windowHeight = $( window ).height()

      var totalWidth   = 0, // also used to determine x coordinate of each column
          headerHeight = $('thead').height(),
          columnHeight = windowHeight - headerHeight - $('tfoot').height()

      for( var i = 0; i < this.columns.length; i++ ) {
        if( this.columns[ i ] === null ) continue

        this.columns[ i ].element.css({
          top:headerHeight,
          left: totalWidth,
          height: $(window).height() - headerHeight - $('tfoot').height()
        })

        var colHeight = columnHeight - this.columns[i].header.outerHeight()
        $( this.columns[ i ].bodyElement ).css({
          width : this.columns[i].width - this.resizeHandleSize,
          height: colHeight
        })
        // console.log( this.columns[i].bodyElement.width() )
        $( this.columns[ i ].header ).width( this.columns[i].width - this.resizeHandleSize )

        if( this.columns[ i ].editor ) {
          this.columns[ i ].editor.setSize( null, colHeight )
        }

        totalWidth += this.columns[ i ].width
      }

      $( '#contentCell' ).width( $( window ).width() )
    },

    scrollToColumnNumber : function( columnNumber ) { },
  }

  Gibber.Environment.Layout = window.Layout = Layout
})()<commit_msg>fixed bug in determining initial column widths<commit_after>( function() {
  'use strict'

  var GE;

  var Layout = {
    focusedColumn : null,
    dragging : null,
    columns : [],
    defaultColumnSize : 500,
    resizeHandleSize  : 8,
    minColumnWidth: 300,
    columnID : 0,
    isFullScreen: false,
    _textBGOpacity : 0,
    __fullScreenColumn__: null,
    fullScreenColumn: null,
    getFocusedColumn: function( allowFullScreen ) {
      if( allowFullScreen ) {
        if( Layout.fullScreenColumn === null ) {
          return Layout.columns[ Layout.focusedColumn ]
        }else{
          return Layout.__fullScreenColumn__
        }
      }else{
        return Layout.columns[ Layout.focusedColumn ]
      }
    },
    textBGOpacity : function( v ) {
      this._textBGOpacity = v
      var color = 'rgba( 0, 0, 0, '+v+' )'
      $.injectCSS({ '.CodeMirror-lines pre': {background:color} })
    },
    createBoundariesForInitialLayout : function() {
      var windowWidth = $( window ).width(),
          width0 = windowWidth * .75,
          width1 = windowWidth * .25

      if( width1 < Layout.minColumnWidth ) {
        var diff = Layout.minColumnWidth - width1
        width1 = Layout.minColumnWidth
        width0 -= diff
      }

      Layout.columns[0].setWidth( width0 )
      Layout.columns[1].setWidth( width1 )

      Layout.resizeColumns()
    },
    init : function( _GE ) {
      GE = _GE
      $( '#contentCell' ).empty()

      this.addColumn({ fullScreen:false, type:'code', autofocus:true })
      // var opacityDiv = $('#opacity')
      //
      // opacityDiv.css({
      //   background:'transparent',
      //   position:'relative',
      //   width:150,
      //   height:18,
      //   display:'inline-block',
      //   top:5,
      // })
      // opacityDiv.p = new Interface.Panel({ container:opacityDiv })
      //
      // $( opacityDiv.p.canvas ).css({ width:150, height: 18, zIndex:1  })
      // opacityDiv.p.add(
      //   new Interface.Slider({
      //     isVertical:false,
      //     bounds:[0,0,.95,.95],
      //     value:0,
      //     max:.8,
      //     target:Gibber.Environment.Layout, key:'textBGOpacity',
      //     label:'text bg opacity',
      //     background:'#000',
      //     fill:'#333',
      //     stroke:'#999'
      // }))

      window.Columns = this.columns

      $( window ).resize( this.onResizeWindow )
      $.subscribe( '/layout/resizeWindow', function( e,dict ) { Layout.resize( dict.w, dict.h ) } )

      this.__fullScreenColumn__ = GE.Layout.addColumn({ type:'code' })
      var w = $( window ).width(), h = $( window ).height()
      this.__fullScreenColumn__.header.hide()
      this.__fullScreenColumn__.toggleResizeHandle()
      this.__fullScreenColumn__.element.css({ display:'none', width: w, height: h, top:0, left:0 })
      this.__fullScreenColumn__.bodyElement.css({ width: w, height: h })
      this.__fullScreenColumn__.editor.setSize( w,h )
      this.__fullScreenColumn__.isFullScreen = true
      this.__fullScreenColumn__.editor._handlers.focus.length = 0

      GE.Layout.columns.splice( GE.Layout.columns.indexOf( this.__fullScreenColumn__ ) )
    },

    onResizeWindow : (function() {
      var w = 0, h = 0, handler = function( e ) {
        var _w = $( window ).width(), _h = $( window ).height()
        if( w !== _w || h !== _h ) {
          $.publish('/layout/resizeWindow', { w:_w, h:_h } )
          w = _w
          h = _h

          if( Layout.isFullScreen ) {
            $.publish( '/layout/contentResize', { w: $( window ).width(), h:$( window ).height(), offset:0 } )
          }else{
            var height = $( window ).height()  - $( 'thead' ).height() - $('tfoot').height()
            $.publish( '/layout/contentResize', { w: $( window ).width(), h:height, offset: $('thead').height() } )
          }
        }
      }

      return handler
    })(),

    resize : function( w,h ) {
      $( 'table' ).height( $( window ).height() )
      Layout.resizeColumns( w,h )
    },

    fullScreen : function() {
      Layout.isFullScreen = !Layout.isFullScreen
      for( var i = 0; i < Layout.columns.length; i++ ) {
        if( Layout.columns[i] ) Layout.columns[i].toggle()
      }
      //Layout.toggleHeader()
      //Layout.toggleFooter()
      $( 'thead' ).toggle()
      $( 'tfoot' ).toggle()

      if( Layout.isFullScreen ) {
        $( 'tbody' ).css({ height:'100%', width:'100%', margin:0 })
        $( '#contentCell' ).height( $( window ).height() )
        $.publish( '/layout/contentResize', { w: $( window ).width(), h:$( window ).height(), offset:0 } )
      }else{
        var height = $( window ).height()  - $( 'thead' ).height() - $('tfoot').height()
        $( 'tbody' ).css({ height:height, width:'100%', margin:0 })
        $( '#contentCell' ).height( height )
        $.publish( '/layout/contentResize', { w: $( window ).width(), h:height, offset: $('thead').height() } )
      }
    },

    emsToPixels : function( ems, element ) {
      var pixelsPerEm = Number(getComputedStyle( element, "").fontSize.match(/(\d*(\.\d*)?)px/)[1])

      return pixelsPerEm * ems
    },

    toggleHeader : function( onOrOff ) {
      if(typeof onOrOff !== 'undefined') {
        if( onOrOff ) {
          $( 'thead' ).show()
        } else {
          $( 'thead' ).hide()
        }
      }else{
        $.publish('/layout/toggleHeader', {} )

        $( 'thead' ).toggle()
      }
    },

    toggleFooter : function( onOrOff ) {
      if(typeof onOrOff !== 'undefined') {
        if( onOrOff ) {
          $( 'tfoot' ).show()
        } else {
          $( 'tfoot' ).hide()
        }
      }else{
        $.publish('/layout/toggleFooter', {} )

        $( 'tfoot' ).toggle()
      }
    },

    toggleAllResizeHandles : function() { $( '.resizeHandle' ).toggle() },

    toggleAllColumns : function() {
      for( var i = 0; i < GE.Layout.columns.length; i++ ) {
        if( GE.Layout.columns[i] !== null )
          GE.Layout.columns[ i ].toggle()
      }
    },

    toggle : function() {
      this.toggleHeader()
      this.toggleFooter()
      this.toggleAllColumns()
    },

    addColumn : function( options ) {
      return new this.Column( options, this )
    },

    load : function( name ) {
      var layout = GE.Storage.values.layouts[ name ];

      this.removeAllColumns()

      for( var i = 0; i < layout.columns.length; i++) {
        // this.addColumn( false, layout.columns[i].width, GE.modes[ layout.columns[i].mode ] )
        this.addColumn({ width:layout.columns[ i ].width, fullScreen:false, mode:layout.columns[i].mode, type:'code' })
        this.columns[i].editor.setValue( layout.columns[i].value )
      }
    },

    save : function() {
      var name = window.prompt("Enter name for layout");

      var layout = {
        header: $( '#header' ).css( 'display' ) === 'none' ? false : true,
        footer: $( '#footer' ).css( 'display' ) === 'none' ? false : true,
        columns: []
      }

      for( var i = 0; i < this.columns.length; i++ ) {
        if( this.columns[i] === null ) return

        layout.columns.push({
          width: $( this.columns[i].element ).width(),
          value: this.columns[i].editor.getValue(),
          mode: $( this.columns[i].modeSelect ).find(':selected').index()//this.columns[i].editor.mode//this.columns[i].modeIndex % GE.modes.length,
        })
      }

      GE.Storage.values.layouts[ name ] = layout
      GE.Storage.save()
    },

    getColumnByID : function( id ) {
      for( var i = 0; i < this.columns.length; i++ ) {
        var col = this.columns[ i ]

        if( col === null ) continue;

        if( col.id === id ) {
          return col;
        }
      }
      return null;
    },

    removeAllColumns : function() {
      for( var i = this.columns.length - 1; i >= 0; i-- ) {
        var col = this.columns[ i ]

        if( col === null ) continue;

        col.element.remove()
      }
      this.columns.length = 0
    },

    removeColumn : function( columnNumber ) {
      var col = this.getColumnByID( columnNumber )

      if( col === null ) return

      if( col.element ) col.element.remove()

      this.columns[ this.columns.indexOf( col ) ] = null
      // this.columns.splice( this.columns.indexOf( col ), 1 )

      this.resizeColumns()
    },

    handleResizeEventForColumn : function(_col) {
      ( function() {
        var col = _col,
        columnResizeHandler = function(e) {
          var newWidthCandidate = e.pageX - col.element.position().left
          col.width = newWidthCandidate > Layout.minColumnWidth ? newWidthCandidate : Layout.minColumnWidth
          col.element.width( col.width )

          if( col.onresize ) col.onresize( col.width )

          GE.Layout.resizeColumns()
        },
        columnResizeEndHandler = function(e) {
          $( window ).unbind( "mousemove", columnResizeHandler );
          $( window ).unbind( "mouseup", columnResizeEndHandler );
          $( "body ").css( "-webkit-user-select", "text" );
        };

        col.resizeHandle.on( 'mousedown', function(e) {
          $( "body" ).css( "-webkit-user-select", "none" );

          $( window ).on( 'mousemove', columnResizeHandler )

          $( window ).on( 'mouseup',  columnResizeEndHandler )
        })
      })()
    },
    setColumnBodyHeight : function( col ) {
      var headerHeight = $('thead').height(),
          columnHeight = $(window).height() - headerHeight - $('tfoot').height() - col.header.outerHeight()

      col.bodyElement.css({ height: columnHeight })
    },

    resizeColumns : function( windowWidth, windowHeight ) {
      if( isNaN(windowHeight) ) windowHeight = $( window ).height()

      var totalWidth   = 0, // also used to determine x coordinate of each column
          headerHeight = $('thead').height(),
          columnHeight = windowHeight - headerHeight - $('tfoot').height()

      for( var i = 0; i < this.columns.length; i++ ) {
        if( this.columns[ i ] === null ) continue

        this.columns[ i ].element.css({
          top:headerHeight,
          left: totalWidth,
          height: $(window).height() - headerHeight - $('tfoot').height()
        })

        var colHeight = columnHeight - this.columns[i].header.outerHeight()
        $( this.columns[ i ].bodyElement ).css({
          width : this.columns[i].width - this.resizeHandleSize,
          height: colHeight
        })
        // console.log( this.columns[i].bodyElement.width() )
        $( this.columns[ i ].header ).width( this.columns[i].width - this.resizeHandleSize )

        if( this.columns[ i ].editor ) {
          this.columns[ i ].editor.setSize( null, colHeight )
        }

        totalWidth += this.columns[ i ].width
      }

      $( '#contentCell' ).width( $( window ).width() )
    },

    scrollToColumnNumber : function( columnNumber ) { },
  }

  Gibber.Environment.Layout = window.Layout = Layout
})()<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import withStyles from 'isomorphic-style-loader/withStyles';
// eslint-disable-next-line css-modules/no-unused-class
import s from './Toast.css';
import ToastContents from './ToastContents';

class Toast extends React.Component {
  static propTypes = {
    id: PropTypes.string,
    onClose: PropTypes.func,
  };

  static defaultProps = {
    id: null,
    onClose: null,
  };

  static contextTypes = {
    intl: PropTypes.object,
    insertCss: PropTypes.func,
  };

  static childContextTypes = {
    intl: PropTypes.object,
    insertCss: PropTypes.func,
  };

  getChildContext() {
    return this.context;
  }

  componentDidMount() {
    this.addLayer();
    this.renderLayer();
  }

  componentDidUpdate() {
    this.renderLayer();
  }

  componentWillUnmount() {
    this.removeLayer();
  }

  onClose() {
    const { onClose } = this.props;
    this.removeLayer();
    if (onClose) {
      onClose();
    }
  }

  addLayer() {
    const { id } = this.props;

    const element = document.createElement('div');
    if (id) {
      element.id = id;
    }
    element.className = s.container;
    const appElements = document.querySelectorAll('#app');
    let beforeElement;
    if (appElements.length > 0) {
      beforeElement = appElements[0];
    } else {
      beforeElement = document.body.firstChild;
    }
    if (beforeElement) {
      this.element = beforeElement.parentNode.insertBefore(
        element,
        beforeElement,
      );
    }
  }

  removeLayer() {
    if (this.element) {
      ReactDOM.unmountComponentAtNode(this.element);
      this.element.parentNode.removeChild(this.element);
      this.element = undefined;
    }
  }

  renderLayer() {
    if (this.element) {
      this.element.className = s.container;
      const contents = (
        <ToastContents
          {...this.props}
          intl={this.context.intl}
          store={this.context.store}
          insertCss={this.context.insertCss}
          onClose={() => this.onClose()}
        />
      );
      ReactDOM.render(contents, this.element);
    }
  }

  render() {
    return ;
  }
}

export default withStyles(s)(Toast);
<commit_msg>fixed context in toast component<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import withStyles from 'isomorphic-style-loader/withStyles';
import StyleContext from 'isomorphic-style-loader/StyleContext';
import { IntlProvider } from 'react-intl';
import { Provider as ReduxProvider } from 'react-redux';

// eslint-disable-next-line css-modules/no-unused-class
import s from './Toast.css';
import ToastContents from './ToastContents';

class Toast extends React.Component {
  static propTypes = {
    id: PropTypes.string,
    onClose: PropTypes.func,
  };

  static defaultProps = {
    id: null,
    onClose: null,
  };

  static contextTypes = {
    intl: IntlProvider.childContextTypes.intl,
    insertCss: PropTypes.func,
    store: PropTypes.shape({
      subscribe: PropTypes.func.isRequired,
      dispatch: PropTypes.func.isRequired,
      getState: PropTypes.func.isRequired,
    }),
  };

  static childContextTypes = {
    intl: IntlProvider.childContextTypes.intl,
    insertCss: PropTypes.func,
    store: PropTypes.shape({
      subscribe: PropTypes.func.isRequired,
      dispatch: PropTypes.func.isRequired,
      getState: PropTypes.func.isRequired,
    }),
  };

  getChildContext() {
    return this.context;
  }

  componentDidMount() {
    this.addLayer();
    this.renderLayer();
  }

  componentDidUpdate() {
    this.renderLayer();
  }

  componentWillUnmount() {
    this.removeLayer();
  }

  onClose() {
    const { onClose } = this.props;
    this.removeLayer();
    if (onClose) {
      onClose();
    }
  }

  addLayer() {
    const { id } = this.props;

    const element = document.createElement('div');
    if (id) {
      element.id = id;
    }
    element.className = s.container;
    const appElements = document.querySelectorAll('#app');
    let beforeElement;
    if (appElements.length > 0) {
      [beforeElement] = appElements;
    } else {
      beforeElement = document.body.firstChild;
    }
    if (beforeElement) {
      this.element = beforeElement.parentNode.insertBefore(
        element,
        beforeElement,
      );
    }
  }

  removeLayer() {
    if (this.element) {
      ReactDOM.unmountComponentAtNode(this.element);
      this.element.parentNode.removeChild(this.element);
      this.element = undefined;
    }
  }

  renderLayer() {
    if (this.element) {
      this.element.className = s.container;
      const { insertCss, intl, store } = this.context; // TODO change to a single provider
      const contents = (

      );
      ReactDOM.render(contents, this.element);
    }
  }

  render() {
    return ;
  }
}

export default withStyles(s)(Toast);
<|endoftext|>


<commit_before>import RQL from "react-relay/lib/RelayQL"
import RelayQuery from "react-relay/lib/RelayQuery"
import RelayMetaRoute from "react-relay/lib/RelayMetaRoute"
import RelayStore from "react-relay/lib/RelayStore"
import RelayStoreData from "react-relay/lib/RelayStoreData"
import RelayDefaultNetworkLayer from "react-relay/lib/RelayDefaultNetworkLayer"
import RelayNetworkLayer from "react-relay/lib/RelayNetworkLayer"
import RelayMutation from "react-relay/lib/RelayMutation"

import GraphQL from "react-relay/lib/GraphQL"
import GraphQLStoreQueryResolver from "react-relay/lib/GraphQLStoreQueryResolver"
import GraphQLFragmentPointer from "react-relay/lib/GraphQLFragmentPointer"

import curry from "./util/curry"

const storeData = RelayStoreData.getDefaultInstance()

export const RelayQL = RQL

export function setEndpoint(endpoint) {
  RelayNetworkLayer.injectNetworkLayer(new RelayDefaultNetworkLayer(endpoint))
}

export const query = curry((q, variables) => {
  return (fragment) => {
    const baseQuery =
      new GraphQL.Query(
        q.fieldName,
        (q.calls[0] && q.calls[0].value) || null,
        q.fields,
        [fragment],
        q.metadata,
        q.name
      )

    const rootQuery =
      RelayQuery.Root.create(
        baseQuery,
        RelayMetaRoute.get(q.name),
        variables || {}
      )

    return {
      root: rootQuery,
      base: baseQuery,
      variables
    }
  }
})

export const observe = curry((q, opts, fragment, onValue) => {
  const {root, base: {name}, variables} = q(fragment)
  const options = opts || {}

  let resolver = null,
      request  = null

  request = options.forceFetch === true ?
    RelayStore.forceFetch({[name]: root}, handleStatusChange) :
    RelayStore.primeCache({[name]: root}, handleStatusChange)

  return function unsubscribe() {
    if (request) {
      request.abort()
      request = null
    }
    if (resolver) {
      resolver.reset()
      resolver = null
    }
  }

  function handleStatusChange(status) {
    if (status.ready) {
      // get fragment pointers from query
      const fp =
        GraphQLFragmentPointer.createForRoot(
          storeData.getQueuedStore(),
          root
        )

      const relayFragment =
        RelayQuery.Fragment.create(
          fragment,
          RelayMetaRoute.get(name),
          variables
        )

      const graphqlFP =
        relayFragmentToGraphQLFP(fp, relayFragment)

      const handleUpdate = () => {
        if (resolver) {
          const val = resolver.resolve(graphqlFP)
          onValue(val)
        }
      }

      resolver = new GraphQLStoreQueryResolver(graphqlFP, handleUpdate)
      handleUpdate()
    }
    // TODO: error handling
  }

  function relayFragmentToGraphQLFP(rootFP, relayFragment) {
    const ids = getFragmentIds(rootFP, relayFragment)
    return new GraphQLFragmentPointer(ids, relayFragment)
  }

  function getFragmentIds(fp, relayFragment) {
    const fid = relayFragment.getConcreteFragmentID()
    if (relayFragment.isPlural()) {
      return fp.reduce((acc, it) => [...acc, ...it[fid].getDataIDs()], [])
    } else {
      return fp[fid].getDataID()
    }
  }
})

class ReleiMutation extends RelayMutation {
  constructor(opts) {
    super({})
    this.releiOpts = opts
  }
  getMutation() {
    return this.releiOpts.mutation
  }
  getVariables() {
    return this.releiOpts.variables
  }
  getFatQuery() {
    return this.releiOpts.fatQuery
  }
  getConfigs() {
    return this.releiOpts.configs(this.releiOpts.ctx)
  }
}

class ReleiOptimisticMutation extends ReleiMutation {
  constructor(mutation, opts) {
    super(mutation, opts)
  }
  getOptimisticResponse() {
    return this.releiOpts.optimisticResponse
  }
}

export const mutate = curry((opts, ctx, variables) => {
  const {mutation, fatQuery, configs, optimisticResponse} = opts
  if (!(mutation && fatQuery && configs)) {
    throw new Error(
      "Mandatory options missing! The following options must be given:\n"
      + "  * mutation\n"
      + "  * fatQuery\n"
      + "  * configs"
    )
  }
  const options = {...opts, ctx, variables}
  const releiMutation = optimisticResponse ?
    new ReleiOptimisticMutation(options) :
    new ReleiMutation(options)

  RelayStore.update(releiMutation)
})

<commit_msg>Use optimisticResponse as a function<commit_after>import RQL from "react-relay/lib/RelayQL"
import RelayQuery from "react-relay/lib/RelayQuery"
import RelayMetaRoute from "react-relay/lib/RelayMetaRoute"
import RelayStore from "react-relay/lib/RelayStore"
import RelayStoreData from "react-relay/lib/RelayStoreData"
import RelayDefaultNetworkLayer from "react-relay/lib/RelayDefaultNetworkLayer"
import RelayNetworkLayer from "react-relay/lib/RelayNetworkLayer"
import RelayMutation from "react-relay/lib/RelayMutation"

import GraphQL from "react-relay/lib/GraphQL"
import GraphQLStoreQueryResolver from "react-relay/lib/GraphQLStoreQueryResolver"
import GraphQLFragmentPointer from "react-relay/lib/GraphQLFragmentPointer"

import curry from "./util/curry"

const storeData = RelayStoreData.getDefaultInstance()

export const RelayQL = RQL

export function setEndpoint(endpoint) {
  RelayNetworkLayer.injectNetworkLayer(new RelayDefaultNetworkLayer(endpoint))
}

export const query = curry((q, variables) => {
  return (fragment) => {
    const baseQuery =
      new GraphQL.Query(
        q.fieldName,
        (q.calls[0] && q.calls[0].value) || null,
        q.fields,
        [fragment],
        q.metadata,
        q.name
      )

    const rootQuery =
      RelayQuery.Root.create(
        baseQuery,
        RelayMetaRoute.get(q.name),
        variables || {}
      )

    return {
      root: rootQuery,
      base: baseQuery,
      variables
    }
  }
})

export const observe = curry((q, opts, fragment, onValue) => {
  const {root, base: {name}, variables} = q(fragment)
  const options = opts || {}

  let resolver = null,
      request  = null

  request = options.forceFetch === true ?
    RelayStore.forceFetch({[name]: root}, handleStatusChange) :
    RelayStore.primeCache({[name]: root}, handleStatusChange)

  return function unsubscribe() {
    if (request) {
      request.abort()
      request = null
    }
    if (resolver) {
      resolver.reset()
      resolver = null
    }
  }

  function handleStatusChange(status) {
    if (status.ready) {
      // get fragment pointers from query
      const fp =
        GraphQLFragmentPointer.createForRoot(
          storeData.getQueuedStore(),
          root
        )

      const relayFragment =
        RelayQuery.Fragment.create(
          fragment,
          RelayMetaRoute.get(name),
          variables
        )

      const graphqlFP =
        relayFragmentToGraphQLFP(fp, relayFragment)

      const handleUpdate = () => {
        if (resolver) {
          const val = resolver.resolve(graphqlFP)
          onValue(val)
        }
      }

      resolver = new GraphQLStoreQueryResolver(graphqlFP, handleUpdate)
      handleUpdate()
    }
    // TODO: error handling
  }

  function relayFragmentToGraphQLFP(rootFP, relayFragment) {
    const ids = getFragmentIds(rootFP, relayFragment)
    return new GraphQLFragmentPointer(ids, relayFragment)
  }

  function getFragmentIds(fp, relayFragment) {
    const fid = relayFragment.getConcreteFragmentID()
    if (relayFragment.isPlural()) {
      return fp.reduce((acc, it) => [...acc, ...it[fid].getDataIDs()], [])
    } else {
      return fp[fid].getDataID()
    }
  }
})

class ReleiMutation extends RelayMutation {
  constructor(opts) {
    super({})
    this.releiOpts = opts
  }
  getMutation() {
    return this.releiOpts.mutation
  }
  getVariables() {
    return this.releiOpts.variables
  }
  getFatQuery() {
    return this.releiOpts.fatQuery
  }
  getConfigs() {
    const {ctx, variables} = this.releiOpts
    return this.releiOpts.configs(ctx, variables)
  }
}

class ReleiOptimisticMutation extends ReleiMutation {
  constructor(mutation, opts) {
    super(mutation, opts)
  }
  getOptimisticResponse() {
    const {ctx, variables} = this.releiOpts
    return this.releiOpts.optimisticResponse(ctx, variables)
  }
}

export const mutate = curry((opts, ctx, variables) => {
  const {mutation, fatQuery, configs, optimisticResponse} = opts
  if (!(mutation && fatQuery && configs)) {
    throw new Error(
      "Mandatory options missing! The following options must be given:\n"
      + "  * mutation\n"
      + "  * fatQuery\n"
      + "  * configs"
    )
  }
  const options = {...opts, ctx, variables}
  const releiMutation = optimisticResponse ?
    new ReleiOptimisticMutation(options) :
    new ReleiMutation(options)

  RelayStore.update(releiMutation)
})

<|endoftext|>