<commit_before>(function(name, definition) {

  // Important NOTE
  // In browsers, binary types must use a 3rd party Buffer implementation,
  // the recommended one is from https://github.com/feross/buffer

  if (typeof module != 'undefined') {
    var Buffer = require('buffer/').Buffer;
    // CommonJS - NodeJS
    module.exports = definition(Buffer);
  } else if (typeof define == 'function' && typeof define.amd == 'object') {
    // AMD - RequireJS(Buffer class must be exposed as AMD)
    define(['Buffer'], definition);
  } else {
    // Global - Browser(Buffer class should exists globally)
    this[name] = definition(this.Buffer);
  }

}('mod', function(Buffer) {

  if (typeof Buffer === 'undefined') {
    throw new Error('Cannot continue without a binary Buffer implementation')
  }

  function deserializeMap(m) {
    var items = {};
    var keys = Object.keys(m);
    for (var k in keys) {
      var key = keys[k];
      items[key] = Translator.toFlatJSON(m[key]);
    }
    return items;
  }

  function serializeMap(m) {
    var items = {'M': {}};
    var keys = Object.keys(m);
    for (var k in keys) {
      var key = keys[k];
      items['M'][key] = Translator.toDynamoDBJSON(m[key]);
    }
    return items;
  }

  var Deserializers = {
       'S': function(v) { return String(v); },
       'N': function(v) { return typeof v === 'string' ? v : Number(v); },
       'B': function(v) { return new Buffer(v, 'utf8'); },
    'BOOL': function(v) { return v ? true : false; },
    'NULL': function(v) { return null; },
      'SS': function(v) { return v.map(function(it) { return String(it); }); },
      'NS': function(v) { return v.map(function(it) { return typeof it === 'string' ? it : Number(it); }); },
      'BS': function(v) { return v.map(function(it) { return new Buffer(it, 'utf8'); }); },
       'L': function(v) { return v.map(function(it) { return Translator.toFlatJSON(it); }); },
       'M': function(v) { return deserializeMap(v); }
  };

  var Serializers = {
     'undefined': function(v) { return {'NULL': null}; },
          'null': function(v) { return {'NULL': null}; },
       'boolean': function(v) { return {'BOOL': v}; },
        'number': function(v) { return {'N': String(v)}; },
        'string': function(v) { return {'S': v}; },
         'array': function(v) {
            // check if every element is Number => NS
            // check if every element is String => SS
            // check if every element is Binary => BS
            // else => L
            var numbers = v.filter(function(it) { return Translator.getJSTypeOf(it) === 'number'; });
            var strings = v.filter(function(it) { return Translator.getJSTypeOf(it) === 'string'; });
            var buffers = v.filter(function(it) { return Buffer.isBuffer(it); });
            // check if only numbers
            if (numbers.length === v.length) {
              return {'NS': numbers};
            } else if (strings.length === v.length) {
              return {'SS': strings};
            } else if (buffers.length === v.length) {
              return {'BS': buffers};
            } else {
              return {'L': v.map(function(it) { return Translator.toDynamoDBJSON(it); })};
            }
         },
    'uint8array': function(v) { return {'B': v}; },
        'object': function(v) { return Buffer.isBuffer(v) ? {'B': v} : serializeMap(v); }
  };

  var Translator = {
    /**
     * Convert to flat JSON from DynamoDB json
     *
     * @param {mixed} input - DynamoDB JSON value
     */
    toFlatJSON: function(input) {
      if (typeof input !== 'object') {
        throw new Error('Invalid input, only objects are allowed');
      }
      var keys = Object.keys(input);
      if (keys.length === 0) {
        throw new Error('Invalid input, object has no attributes');
      }
      var typeSymbol = keys[0];
      if (typeSymbol in Deserializers) {
        return Deserializers[typeSymbol](input[typeSymbol]);
      } else {
        throw new Error('Unsupported deserialzier type: ' + typeSymbol);
      }
      return result;
    },
    /**
     * Convert to DynamoDB json from flat JSON
     *
     * @param {mixed} input - flat JSON value
     */
    toDynamoDBJSON: function(input) {
      var tof = Translator.getJSTypeOf(input);
      if (tof in Serializers) {
        return Serializers[tof](input);
      } else {
        throw new Error('Type is not supported');
      }
    },
    getJSTypeOf: function(val) {
      return Object.prototype.toString.call(val).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
    }
  };

  return Translator;
}));<commit_msg>replace for..in loop by reduce function<commit_after>(function(name, definition) {

  // Important NOTE
  // In browsers, binary types must use a 3rd party Buffer implementation,
  // the recommended one is from https://github.com/feross/buffer

  if (typeof module != 'undefined') {
    var Buffer = require('buffer/').Buffer;
    // CommonJS - NodeJS
    module.exports = definition(Buffer);
  } else if (typeof define == 'function' && typeof define.amd == 'object') {
    // AMD - RequireJS(Buffer class must be exposed as AMD)
    define(['Buffer'], definition);
  } else {
    // Global - Browser(Buffer class should exists globally)
    this[name] = definition(this.Buffer);
  }

}('mod', function(Buffer) {

  if (typeof Buffer === 'undefined') {
    throw new Error('Cannot continue without a binary Buffer implementation')
  }

  function deserializeMap(m) {
    var items = {};
    var keys = Object.keys(m);
    items = keys.reduce(function(object, key) {
      object[key] = Translator.toFlatJSON(m[key]);
      return object;
    }, {});
    return items;
  }

  function serializeMap(m) {
    var items = {'M': {}};
    var keys = Object.keys(m);
    items['M'] = keys.reduce(function(object, key) {
      object[key] = Translator.toDynamoDBJSON(m[key]);
      return object;
    }, {});
    return items;
  }

  var Deserializers = {
       'S': function(v) { return String(v); },
       'N': function(v) { return typeof v === 'string' ? v : Number(v); },
       'B': function(v) { return new Buffer(v, 'utf8'); },
    'BOOL': function(v) { return v ? true : false; },
    'NULL': function(v) { return null; },
      'SS': function(v) { return v.map(function(it) { return String(it); }); },
      'NS': function(v) { return v.map(function(it) { return typeof it === 'string' ? it : Number(it); }); },
      'BS': function(v) { return v.map(function(it) { return new Buffer(it, 'utf8'); }); },
       'L': function(v) { return v.map(function(it) { return Translator.toFlatJSON(it); }); },
       'M': function(v) { return deserializeMap(v); }
  };

  var Serializers = {
     'undefined': function(v) { return {'NULL': null}; },
          'null': function(v) { return {'NULL': null}; },
       'boolean': function(v) { return {'BOOL': v}; },
        'number': function(v) { return {'N': String(v)}; },
        'string': function(v) { return {'S': v}; },
         'array': function(v) {
            // check if every element is Number => NS
            // check if every element is String => SS
            // check if every element is Binary => BS
            // else => L
            var numbers = v.filter(function(it) { return Translator.getJSTypeOf(it) === 'number'; });
            var strings = v.filter(function(it) { return Translator.getJSTypeOf(it) === 'string'; });
            var buffers = v.filter(function(it) { return Buffer.isBuffer(it); });
            // check if only numbers
            if (numbers.length === v.length) {
              return {'NS': numbers};
            } else if (strings.length === v.length) {
              return {'SS': strings};
            } else if (buffers.length === v.length) {
              return {'BS': buffers};
            } else {
              return {'L': v.map(function(it) { return Translator.toDynamoDBJSON(it); })};
            }
         },
    'uint8array': function(v) { return {'B': v}; },
        'object': function(v) { return Buffer.isBuffer(v) ? {'B': v} : serializeMap(v); }
  };

  var Translator = {
    /**
     * Convert to flat JSON from DynamoDB json
     *
     * @param {mixed} input - DynamoDB JSON value
     */
    toFlatJSON: function(input) {
      if (typeof input !== 'object') {
        throw new Error('Invalid input, only objects are allowed');
      }
      var keys = Object.keys(input);
      if (keys.length === 0) {
        throw new Error('Invalid input, object has no attributes');
      }
      var typeSymbol = keys[0];
      if (typeSymbol in Deserializers) {
        return Deserializers[typeSymbol](input[typeSymbol]);
      } else {
        throw new Error('Unsupported deserialzier type: ' + typeSymbol);
      }
      return result;
    },
    /**
     * Convert to DynamoDB json from flat JSON
     *
     * @param {mixed} input - flat JSON value
     */
    toDynamoDBJSON: function(input) {
      var tof = Translator.getJSTypeOf(input);
      if (tof in Serializers) {
        return Serializers[tof](input);
      } else {
        throw new Error('Type is not supported');
      }
    },
    getJSTypeOf: function(val) {
      return Object.prototype.toString.call(val).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
    }
  };

  return Translator;
}));<|endoftext|>


<commit_before>// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import Element from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
import VueResource from 'vue-resource'
import moment from 'moment'

import App from './App'

Vue.use(Element)
Vue.use(VueResource)

Vue.filter('toKm', function (value) {
  value = value / 1000
  return Math.round(value * 100) / 100
})

Vue.filter('toHHMM', function (value) {
  let h = Math.trunc(value / 3600)
  let m = Math.trunc((value % 3600) / 60)
  if (h === 0) {
    return m
  } else if (m === 0) {
    return h + ' h 00'
  } else {
    return h + ' h ' + m
  }
})

Vue.filter('formatDate', function (value) {
  if (value === '0001-01-01T00:00:00Z') {
    return '-'
  } else if (value) {
    return moment(String(value)).format('DD/MM HH:mm')
  }
})

Vue.http.options.root = 'http://127.0.0.1:8042/teams/1'
/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})
<commit_msg>fix: url API<commit_after>// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import Element from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
import VueResource from 'vue-resource'
import moment from 'moment'

import App from './App'

Vue.use(Element)
Vue.use(VueResource)

Vue.filter('toKm', function (value) {
  value = value / 1000
  return Math.round(value * 100) / 100
})

Vue.filter('toHHMM', function (value) {
  let h = Math.trunc(value / 3600)
  let m = Math.trunc((value % 3600) / 60)
  if (h === 0) {
    return m
  } else if (m === 0) {
    return h + ' h 00'
  } else {
    return h + ' h ' + m
  }
})

Vue.filter('formatDate', function (value) {
  if (value === '0001-01-01T00:00:00Z') {
    return '-'
  } else if (value) {
    return moment(String(value)).format('DD/MM HH:mm')
  }
})

Vue.http.options.root = 'https://oxfam.xee.com/teams/1'
/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})
<|endoftext|>


<commit_before>var audioContext = new AudioContext();
var clicked = false;
var chunks = [];
var osc = audioContext.createOscillator();
var dest = audioContext.createMediaStreamDestination();
var mediaRecorder = new MediaRecorder(dest.stream);
osc.connect(dest);

var varCounter = 0;
var varName = function (osc, list) {
     if (varCounter < list.length) {
        osc.frequency.value = list[varCounter];
        varCounter++;
     } else {
        clearInterval(varName);
        mediaRecorder.requestData();
        mediaRecorder.stop();
        osc.stop();
        varCounter = 0;
        osc = audioContext.createOscillator();
        dest = audioContext.createMediaStreamDestination();
        mediaRecorder = new MediaRecorder(dest.stream);
        osc.connect(dest);
     }
};

var Selection = {
  axis_x:0, // valeur par default
  axis_y:0, // default value

  playData: function () {
  //  let data = $('#file-content').innerText;
  var data = Array.prototype.map.call(document.querySelectorAll("tr"), function (tr) {
    return Array.prototype.map.call(tr.querySelectorAll('td'), function (td) {
      return td.innerHTML;
    });
  });
    data.shift();
    let tab = data // data.split('\n').map(line => line.split(','));

    let grid2 = tab[0].map((col, i) => tab.map((row) => row[i]));
    grid2.shift()
    const floatTab = grid2.map(line => line.map(cell => parseFloat(cell)));

    music32FloatArray(floatTab[Selection.axis_y]);
  },

  setNewIndexY: function(button) {
    Selection.axis_y = button.target.getAttribute('index');
  },
};

function music32FloatArray (floatList) {
  // Horn Sound.
  //venigi.getJson("horn.json").then(tables => {
  //  var real = new Float32Array(tables.real);
  //  var imag = new Float32Array(real.length);
  const tables = HornRealImg;
  var c = tables.real.length;
  var real = new Float32Array(c);
  var imag = new Float32Array(c);
  for (var i = 0; i < c; i++) {
    real[i] = tables.real[i];
    imag[i] = tables.imag[i];
  }

  var hornTable = audioContext.createPeriodicWave(real, imag);

  osc.setPeriodicWave(hornTable);

  mediaRecorder = new MediaRecorder(audioContext.destination);
  osc.connect(audioContext.destination);
  osc.frequency.value = floatList[varCounter];
  mediaRecorder.start();
  osc.start(0);

  setInterval(() => varName(osc, floatList), 500);
  //}) ;
}

function playData(e) {
  if (!clicked) {
    Selection.playData();
    e.target.value = "Stop recording";
    clicked = true;
 } else {
 clicked = false;
       clearInterval(varName);
        mediaRecorder.requestData();
        mediaRecorder.stop();
        osc.stop();
        varCounter = 0;
        osc = audioContext.createOscillator();
        dest = audioContext.createMediaStreamDestination();
        mediaRecorder = new MediaRecorder(dest.stream);
        osc.connect(dest);
       }
}

mediaRecorder.ondataavailable = function(evt) {
  // push each chunk (blobs) in an array
  chunks.push(evt.data);
};

mediaRecorder.onstop = function(evt) {
  // Make blob out of our blobs, and open it.
  var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
  saveBlob(blob, "test.ogg");

  //  var audioTag = document.createElement('audio');
  //  document.querySelector("audio").src = URL.createObjectURL(blob);
};

$('#play-input').addEventListener("click", playData);<commit_msg>cleaned<commit_after>var audioContext = new AudioContext();
var clicked = false;
var chunks = [];
var osc = audioContext.createOscillator();
var dest = audioContext.createMediaStreamDestination();
var mediaRecorder = new MediaRecorder(dest.stream);
osc.connect(dest);

var varCounter = 0;
var varName = function (osc, list) {
     if (varCounter < list.length) {
        osc.frequency.value = list[varCounter];
        varCounter++;
     } else {
        clearInterval(varName);
        mediaRecorder.requestData();
        mediaRecorder.stop();
        osc.stop();
        varCounter = 0;
        osc = audioContext.createOscillator();
        dest = audioContext.createMediaStreamDestination();
        mediaRecorder = new MediaRecorder(dest.stream);
        osc.connect(dest);
mediaRecorder.ondataavailable = function(evt) {
  // push each chunk (blobs) in an array
  chunks.push(evt.data);
};

mediaRecorder.onstop = function(evt) {
  // Make blob out of our blobs, and open it.
  var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
  saveBlob(blob, "test.ogg");

  //  var audioTag = document.createElement('audio');
  //  document.querySelector("audio").src = URL.createObjectURL(blob);
};
     }
};

var Selection = {
  axis_x:0, // valeur par default
  axis_y:0, // default value

  playData: function () {
  //  let data = $('#file-content').innerText;
  var data = Array.prototype.map.call(document.querySelectorAll("tr"), function (tr) {
    return Array.prototype.map.call(tr.querySelectorAll('td'), function (td) {
      return td.innerHTML;
    });
  });
    data.shift();
    let tab = data // data.split('\n').map(line => line.split(','));

    let grid2 = tab[0].map((col, i) => tab.map((row) => row[i]));
    grid2.shift()
    const floatTab = grid2.map(line => line.map(cell => parseFloat(cell)));

    music32FloatArray(floatTab[Selection.axis_y]);
  },

  setNewIndexY: function(button) {
    Selection.axis_y = button.target.getAttribute('index');
  },
};

function music32FloatArray (floatList) {
  // Horn Sound.
  //venigi.getJson("horn.json").then(tables => {
  //  var real = new Float32Array(tables.real);
  //  var imag = new Float32Array(real.length);
  const tables = HornRealImg;
  var c = tables.real.length;
  var real = new Float32Array(c);
  var imag = new Float32Array(c);
  for (var i = 0; i < c; i++) {
    real[i] = tables.real[i];
    imag[i] = tables.imag[i];
  }

  var hornTable = audioContext.createPeriodicWave(real, imag);

  osc.setPeriodicWave(hornTable);

//  mediaRecorder = new MediaRecorder(audioContext.destination);
  osc.connect(audioContext.destination);
  osc.frequency.value = floatList[varCounter];
  mediaRecorder.start();
  osc.start(0);

  setInterval(() => varName(osc, floatList), 500);
  //}) ;
}

function playData(e) {
  if (!clicked) {
    Selection.playData();
    e.target.value = "Stop recording";
    clicked = true;
 } else {
 clicked = false;
       clearInterval(varName);
        mediaRecorder.requestData();
        mediaRecorder.stop();
        osc.stop();
        varCounter = 0;
        osc = audioContext.createOscillator();
        dest = audioContext.createMediaStreamDestination();
        mediaRecorder = new MediaRecorder(dest.stream);
        osc.connect(dest);
mediaRecorder.ondataavailable = function(evt) {
  // push each chunk (blobs) in an array
  chunks.push(evt.data);
};

mediaRecorder.onstop = function(evt) {
  // Make blob out of our blobs, and open it.
  var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
  saveBlob(blob, "test.ogg");

  //  var audioTag = document.createElement('audio');
  //  document.querySelector("audio").src = URL.createObjectURL(blob);
};

       }
}

mediaRecorder.ondataavailable = function(evt) {
  // push each chunk (blobs) in an array
  chunks.push(evt.data);
};

mediaRecorder.onstop = function(evt) {
  // Make blob out of our blobs, and open it.
  var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
  saveBlob(blob, "test.ogg");

  //  var audioTag = document.createElement('audio');
  //  document.querySelector("audio").src = URL.createObjectURL(blob);
};

$('#play-input').addEventListener("click", playData);<|endoftext|>


<commit_before>var assert = require('assert')

// Monitor the reachability of islanders in order to suggest the shape of a new
// government. The `Shaper.update` method is invoked with a islander id and a
// reachability status. `Shaper.update` returns either a new government to
// appoint or `null`. Once `Shaper.update` returns a new government to appoint
// the `Shaper` object is used up and should be replaced.

// We determine reachability elsewhere so that the `Shaper.update` method is
// only ever called with a true or false value for reachable. For the purposes
// of `Shaper` reachability is defined as follows.

// * A islander is reachable if the islander responds to pings and has
// acclimated.
// * A islander is unreachable if the islander does not respond to pings.

// If the islander responds to pings, but has not acclimated, it is neither
// reachable nor unreachable and we don't want to hear about it.

// Notes:

// Could think harder about priorities as they relate to healing. Wouldn't want
// to starve the recovery of the cluster by performing arrivals only, when newly
// acclimated islanders could join the legislature and preserve the republic.

// Note that we currently favor impeachment because the minority updates the
// constituents. A non-functioning minority member would keep all of its
// constituents in the dark.

// We favor filling empty seats in government as soon as they are detected.

// We favor shrinking the government as soon as it becomes obvious that the
// government size is less than the population of the island.

// All this assuming an external mechanism for tracking pings that will
// calculate when a particular islander is reachable or unreachable. After
// `update` returns a reshape operation, the `Shaper` object is consumed. At
// that point you should no longer call `Shaper`. Put a dummy shape object in
// its place.

// A new `Shaper` object should then be created when a new government is
// created.

// I'm imagining that the unreachability of an islander will be remembered so
// that when a new government is created the unreachability can replayed. Causes
// me to muse about whether it should be possible for a islander to become
// reachable again, whether we should continue to ping the islander, or if we
// simply surrender.

// In the case of collapse when we switch to paxos, it seems that we'll keep on
// trying and trying such that we could recover from a network outage in the
// case of paxos.

// TODO Try to recall what you need to do to grow correctly. Who is supposed to
// be in that quorum?

// TODO Work into the words above that filling seats is urgent, but not
// expanding the government to the desired government size.

// TODO Stop saying "quorum" when you mean "seats filled."

//
class Shaper {
    constructor (parliamentSize, government, recovered) {
        this._parliamentSize = government.majority.length * 2 - 1
        this._shouldExpand = parliamentSize != this._parliamentSize
        this._government = government
        this._seen = {}
        this._expandable = []
        this._arriving = []
        this.decided = false
        this._governments = []
        this.outbox = {}
        this._representative = null
        this._shouldNaturalize = this._government.majority.length +
            this._government.minority.length +
            this._government.constituents.length != this._government.acclimated.length
        this._shouldRecover(recovered) || this._shouldContract()
    }

    _shouldRecover (recovered) {
        if (recovered) {
            this._governments.push({
                quorum: this._government.majority,
                government: {
                    majority: this._government.majority,
                    minority: this._government.minority
                }
            })
        }
    }

    _shouldContract () {
        if (
            this._government.promise != '0/0' &&
            this._government.majority.length + this._government.minority.length != this._parliamentSize
        ) {
            var majority = this._government.majority.slice()
            var minority = this._government.minority.slice()
            minority.unshift(majority.pop())
            var demote = minority.pop()
            this._governments.push({
                quorum: this._government.majority,
                government: {
                    majority: majority,
                    minority: minority,
                    demote: demote
                }
            })
        }
    }

    unreachable (unreachable) {
        if (this.decided) {
            return null
        }

        var id = this._government.arrived.id[unreachable]
        assert(id != null, 'unable to determine unreachable id')

        // Depart any unreachable islanders.
        return this._governments.shift() || {
            quorum: this._government.majority,
            government: {
                majority: this._government.majority,
                minority: this._government.minority.filter(function ($id) { return $id != id }),
                departed: id
            }
        }
    }

    acclimate (promise) {
        if (this.decided) {
            return null
        }

        var government = this._government

        var id = government.arrived.id[promise]
        assert(id != null, 'unable to determine acclimate id')

        assert(!~government.acclimated.indexOf(id), 'already acclimated')

        return this._governments.shift() || {
            quorum: this._government.majority,
            government: {
                majority: this._government.majority,
                minority: this._government.minority,
                acclimate: id
            }
        }
    }

    // `Shaper.update` determines if a new government should be created that has a
    // new shape. Note that embark and arrive takes place is elsewhere.

    //
    acclimated (id) {
        if (this.decided) {
            return null
        }

        // We're not going to return an expanded government until we get two
        // expandable entries so if we have a contraction it will go the first time
        // acclimated is called.
        if (~this._government.majority.indexOf(id)) {
            // Majority members are not our responsibility. They trigger their own
            // collapse.
        } else if (this._shouldExpand && !~this._government.minority.indexOf(id)) {
            this._expandable.push(id)
            // TODO Is the quorum the new majority or the old majority?
            // TODO Think about growth commit race conditions again.

            //
            if (this._expandable.length == 2) {
                // We should expand and we have islanders who can be appointed to
                // the government so let's grow the government.
                var majority = this._government.majority.slice()
                var minority = this._government.minority.slice()
                var promote = [ this._expandable.shift(), this._expandable.shift() ]
                minority.push.apply(minority, promote)
                majority.push(minority.shift())
                return {
                    quorum: majority,
                    government: {
                        majority: majority,
                        minority: minority,
                        promote: promote
                    }
                }
            }
        }

        return this._governments.shift() || this._arrival() || null
    }

    arrived (id) {
        assert(this._arriving.length > 0 && id == this._arriving[0].id)
        this._arriving.shift()
    }

    // TODO This seems really broken to me. (It is not. Read the following
    // description and then the description in body of `embark` and then amalgamate
    // the two of them.)
    //
    // Looks broken, doesn't it? Updating the cookie and properties of an existing
    // record makes think that there is a race condition where the leader is going
    // to have a different version of the arrival message from the other majority
    // members if `embark` is called and the arrival is the `0` entry in the array.
    //
    // However, we're not using the entry in the array. Our arrival government is
    // an object created in `_arrival`. Calling `embark` for the `0` arrival is a
    // missed update if `_arrival` has been called to create an arrival government
    // from the entry. If the call to `embark` provided a different cookie, it's a
    // miss. The wrong cookie will arrive. We'll have to wait for the arrival and
    // subsequent departure followed by that higher-level departure detection that
    // will trigger a restart.
    //
    // The notes below still stand. The make sense having re-read them.
    //
    embark (arrival) {
        // We do not going to reject a duplicate embarkation for a particular id.
        //
        // Here is a race condition and how it will shake itself out.
        //
        // We could be in the middle of arriving a particular islander id when the
        // islander crashed restarts and submits a new cookie. We will update the
        // cookie here, but that's not going to be the same as the cookie that got
        // written into the log.
        //
        // We can make it a general case that if the cookies mismatch
        // every one is very disappointed. Thus, we can catch this on sync.
        for (var i = 0, I = this._arriving.length; i < I; i++) {
            if (this._arriving[i].id == arrival.id) {
                break
            }
        }
        if (i == this._arriving.length) {
            this._arriving.push(arrival)
        } else {
            this._arriving[i].properties = arrival.properties
            this._arriving[i].cookie = arrival.cookie
            this._arriving[i].acclimated = arrival.acclimated
        }

        // Do nothing if our container indicates that a decision has been reached.
        return this.decided ? null : this._arrival()
    }

    // Generate an arrival government if we have an arrival available.

    //
    _arrival () {
        if (this._arriving.length) {
            var arrival = this._arriving[0]
            return {
                quorum: this._government.majority,
                government: {
                    majority: this._government.majority,
                    minority: this._government.minority,
                    arrive: {
                        id: arrival.id,
                        properties: arrival.properties,
                        cookie: arrival.cookie
                    },
                    acclimate: arrival.acclimated ? arrival.id : null
                }
            }
        }
        return null
    }

    static null = {
        unreachable: function () { return null },
        acclimate: function () { return null },
        _arriving: []
    }
}

module.exports = Shaper
<commit_msg>Convert `var` to `const` and `let` in Proposer.<commit_after>const assert = require('assert')

// Monitor the reachability of islanders in order to suggest the shape of a new
// government. The `Shaper.update` method is invoked with a islander id and a
// reachability status. `Shaper.update` returns either a new government to
// appoint or `null`. Once `Shaper.update` returns a new government to appoint
// the `Shaper` object is used up and should be replaced.

// We determine reachability elsewhere so that the `Shaper.update` method is
// only ever called with a true or false value for reachable. For the purposes
// of `Shaper` reachability is defined as follows.

// * A islander is reachable if the islander responds to pings and has
// acclimated.
// * A islander is unreachable if the islander does not respond to pings.

// If the islander responds to pings, but has not acclimated, it is neither
// reachable nor unreachable and we don't want to hear about it.

// Notes:

// Could think harder about priorities as they relate to healing. Wouldn't want
// to starve the recovery of the cluster by performing arrivals only, when newly
// acclimated islanders could join the legislature and preserve the republic.

// Note that we currently favor impeachment because the minority updates the
// constituents. A non-functioning minority member would keep all of its
// constituents in the dark.

// We favor filling empty seats in government as soon as they are detected.

// We favor shrinking the government as soon as it becomes obvious that the
// government size is less than the population of the island.

// All this assuming an external mechanism for tracking pings that will
// calculate when a particular islander is reachable or unreachable. After
// `update` returns a reshape operation, the `Shaper` object is consumed. At
// that point you should no longer call `Shaper`. Put a dummy shape object in
// its place.

// A new `Shaper` object should then be created when a new government is
// created.

// I'm imagining that the unreachability of an islander will be remembered so
// that when a new government is created the unreachability can replayed. Causes
// me to muse about whether it should be possible for a islander to become
// reachable again, whether we should continue to ping the islander, or if we
// simply surrender.

// In the case of collapse when we switch to paxos, it seems that we'll keep on
// trying and trying such that we could recover from a network outage in the
// case of paxos.

// TODO Try to recall what you need to do to grow correctly. Who is supposed to
// be in that quorum?

// TODO Work into the words above that filling seats is urgent, but not
// expanding the government to the desired government size.

// TODO Stop saying "quorum" when you mean "seats filled."

//
class Shaper {
    constructor (parliamentSize, government, recovered) {
        this._parliamentSize = government.majority.length * 2 - 1
        this._shouldExpand = parliamentSize != this._parliamentSize
        this._government = government
        this._seen = {}
        this._expandable = []
        this._arriving = []
        this.decided = false
        this._governments = []
        this.outbox = {}
        this._representative = null
        this._shouldNaturalize = this._government.majority.length +
            this._government.minority.length +
            this._government.constituents.length != this._government.acclimated.length
        this._shouldRecover(recovered) || this._shouldContract()
    }

    _shouldRecover (recovered) {
        if (recovered) {
            this._governments.push({
                quorum: this._government.majority,
                government: {
                    majority: this._government.majority,
                    minority: this._government.minority
                }
            })
        }
    }

    _shouldContract () {
        if (
            this._government.promise != '0/0' &&
            this._government.majority.length + this._government.minority.length != this._parliamentSize
        ) {
            const majority = this._government.majority.slice()
            const minority = this._government.minority.slice()
            minority.unshift(majority.pop())
            const demote = minority.pop()
            this._governments.push({
                quorum: this._government.majority,
                government: {
                    majority: majority,
                    minority: minority,
                    demote: demote
                }
            })
        }
    }

    unreachable (unreachable) {
        if (this.decided) {
            return null
        }

        const id = this._government.arrived.id[unreachable]
        assert(id != null, 'unable to determine unreachable id')

        // Depart any unreachable islanders.
        return this._governments.shift() || {
            quorum: this._government.majority,
            government: {
                majority: this._government.majority,
                minority: this._government.minority.filter(function ($id) { return $id != id }),
                departed: id
            }
        }
    }

    acclimate (promise) {
        if (this.decided) {
            return null
        }

        const government = this._government

        const id = government.arrived.id[promise]
        assert(id != null, 'unable to determine acclimate id')

        assert(!~government.acclimated.indexOf(id), 'already acclimated')

        return this._governments.shift() || {
            quorum: this._government.majority,
            government: {
                majority: this._government.majority,
                minority: this._government.minority,
                acclimate: id
            }
        }
    }

    // `Shaper.update` determines if a new government should be created that has a
    // new shape. Note that embark and arrive takes place is elsewhere.

    //
    acclimated (id) {
        if (this.decided) {
            return null
        }

        // We're not going to return an expanded government until we get two
        // expandable entries so if we have a contraction it will go the first time
        // acclimated is called.
        if (~this._government.majority.indexOf(id)) {
            // Majority members are not our responsibility. They trigger their own
            // collapse.
        } else if (this._shouldExpand && !~this._government.minority.indexOf(id)) {
            this._expandable.push(id)
            // TODO Is the quorum the new majority or the old majority?
            // TODO Think about growth commit race conditions again.

            //
            if (this._expandable.length == 2) {
                // We should expand and we have islanders who can be appointed to
                // the government so let's grow the government.
                const majority = this._government.majority.slice()
                const minority = this._government.minority.slice()
                const promote = [ this._expandable.shift(), this._expandable.shift() ]
                minority.push.apply(minority, promote)
                majority.push(minority.shift())
                return {
                    quorum: majority,
                    government: {
                        majority: majority,
                        minority: minority,
                        promote: promote
                    }
                }
            }
        }

        return this._governments.shift() || this._arrival() || null
    }

    arrived (id) {
        assert(this._arriving.length > 0 && id == this._arriving[0].id)
        this._arriving.shift()
    }

    // TODO This seems really broken to me. (It is not. Read the following
    // description and then the description in body of `embark` and then amalgamate
    // the two of them.)
    //
    // Looks broken, doesn't it? Updating the cookie and properties of an existing
    // record makes think that there is a race condition where the leader is going
    // to have a different version of the arrival message from the other majority
    // members if `embark` is called and the arrival is the `0` entry in the array.
    //
    // However, we're not using the entry in the array. Our arrival government is
    // an object created in `_arrival`. Calling `embark` for the `0` arrival is a
    // missed update if `_arrival` has been called to create an arrival government
    // from the entry. If the call to `embark` provided a different cookie, it's a
    // miss. The wrong cookie will arrive. We'll have to wait for the arrival and
    // subsequent departure followed by that higher-level departure detection that
    // will trigger a restart.
    //
    // The notes below still stand. The make sense having re-read them.
    //
    embark (arrival) {
        // We do not going to reject a duplicate embarkation for a particular id.
        //
        // Here is a race condition and how it will shake itself out.
        //
        // We could be in the middle of arriving a particular islander id when the
        // islander crashed restarts and submits a new cookie. We will update the
        // cookie here, but that's not going to be the same as the cookie that got
        // written into the log.
        //
        // We can make it a general case that if the cookies mismatch
        // every one is very disappointed. Thus, we can catch this on sync.
        let i, I
        for (i = 0, I = this._arriving.length; i < I; i++) {
            if (this._arriving[i].id == arrival.id) {
                break
            }
        }
        if (i == this._arriving.length) {
            this._arriving.push(arrival)
        } else {
            this._arriving[i].properties = arrival.properties
            this._arriving[i].cookie = arrival.cookie
            this._arriving[i].acclimated = arrival.acclimated
        }

        // Do nothing if our container indicates that a decision has been reached.
        return this.decided ? null : this._arrival()
    }

    // Generate an arrival government if we have an arrival available.

    //
    _arrival () {
        if (this._arriving.length) {
            const arrival = this._arriving[0]
            return {
                quorum: this._government.majority,
                government: {
                    majority: this._government.majority,
                    minority: this._government.minority,
                    arrive: {
                        id: arrival.id,
                        properties: arrival.properties,
                        cookie: arrival.cookie
                    },
                    acclimate: arrival.acclimated ? arrival.id : null
                }
            }
        }
        return null
    }

    static null = {
        unreachable: function () { return null },
        acclimate: function () { return null },
        _arriving: []
    }
}

module.exports = Shaper
<|endoftext|>


<commit_before>// Credits to http://simonsarris.com/blog/510-making-html5-canvas-useful
function Shape(x, y, w, h, fill) {
  this.x = x || 0;
  this.y = y || 0;
  this.w = w || 1;
  this.h = h || 1;
  this.fill = fill || '#AAAAAA';
}

Shape.prototype.draw = function(ctx) {
  ctx.fillStyle = this.fill;
  ctx.fillRect(this.x, this.y, this.w, this.h);
}

Shape.prototype.contains = function(mx, my) {
  return  (this.x <= mx) && (this.x + this.w >= mx) &&
          (this.y <= my) && (this.y + this.h >= my);
}

Shape.prototype.border = function (mx, my) {
  //Checks if within border
  if ((this.y + 2 >= my) && (this.y - 4 <= my)) {
    console.log("Top");
    return Shape.prototype.borderenum.TOP;
  } else if ((this.x + 2 >= mx) && (this.x - 4 <= mx)) {
    console.log("Left");
    return Shape.prototype.borderenum.LEFT;
  } else if ((this.x + this.w + 2 >= mx) && (this.x + this.w - 4 <= mx)) {
    console.log("Right");
    return Shape.prototype.borderenum.RIGHT;
  } else if ((this.y + this.h + 2 >= my) && (this.y + this.h - 4 <= my)) {
    console.log("Bottom");
    return Shape.prototype.borderenum.BOTTOM;
  } else {
    return false;
  }
}

Shape.prototype.borderenum = {
  TOP : 0,
  LEFT : 1,
  RIGHT : 2,
  BOTTOM : 3

}

function CanvasState(frame) {
  // **** First some setup! ****

  this.frame = frame;
  this.width = frame.width;
  this.height = frame.height;
  this.ctx = frame.getContext('2d');
  // This complicates things a little but but fixes mouse co-ordinate problems
  // when there's a border or padding. See getMouse for more detail
  var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
  if (document.defaultView && document.defaultView.getComputedStyle) {
    this.stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(frame, null)['paddingLeft'], 10)      || 0;
    this.stylePaddingTop  = parseInt(document.defaultView.getComputedStyle(frame, null)['paddingTop'], 10)       || 0;
    this.styleBorderLeft  = parseInt(document.defaultView.getComputedStyle(frame, null)['borderLeftWidth'], 10)  || 0;
    this.styleBorderTop   = parseInt(document.defaultView.getComputedStyle(frame, null)['borderTopWidth'], 10)   || 0;
  }
  // Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
  // They will mess up mouse coordinates and this fixes that
  var html = document.body.parentNode;
  this.htmlTop = html.offsetTop;
  this.htmlLeft = html.offsetLeft;

  // **** Keep track of state! ****

  this.valid = false; // when set to false, the frame will redraw everything
  this.shapes = [];  // the collection of things to be drawn
  this.dragging = false; // Keep track of when we are dragging
  this.enlarging = false;
  // the current selected object. In the future we could turn this into an array for multiple selection
  this.selection = null;
  this.dragoffx = 0; // See mousedown and mousemove events for explanation
  this.dragoffy = 0;

  // **** Then events! ****

  // This is an example of a closure!
  // Right here "this" means the CanvasState. But we are making events on the Canvas itself,
  // and when the events are fired on the frame the variable "this" is going to mean the frame!
  // Since we still want to use this particular CanvasState in the events we have to save a reference to it.
  // This is our reference!
  var myState = this;

  //fixes a problem where double clicking causes text to get selected on the frame
  frame.addEventListener('selectstart', function(e) { e.preventDefault(); return false; }, false);
  // Up, down, and move are for dragging
  frame.addEventListener('mousedown', function(e) {
    var mouse = myState.getMouse(e);
    var mx = mouse.x;
    var my = mouse.y;
    var shapes = myState.shapes;
    var l = shapes.length;
    for (var i = l-1; i >= 0; i--) {
      var border = shapes[i].border(mx, my);
      if (shapes[i].contains(mx, my) || border) {
        var mySel = shapes[i];
        // Keep track of where in the object we clicked
        // so we can move it smoothly (see mousemove)
        myState.dragoffx = mx - mySel.x;
        myState.dragoffy = my - mySel.y;
        myState.dragging = true;
        myState.selection = mySel; /* Sets which border to enlarge. */
        if (border) {
          myState.enlarging = border;
        }
        myState.valid = false;
        return;
      }
    }
    // havent returned means we have failed to select anything.
    // If there was an object selected, we deselect it
    if (myState.selection) {
      myState.selection = null;
      myState.valid = false; // Need to clear the old selection border
    }

  }, true);
  frame.addEventListener('mousemove', function(e) {
    if (myState.enlarging) {
      console.log("Test");
      var mouse = myState.getMouse(e);
      myState.selection.w += 1;
      myState.selection.h += 1;
      myState.valid = false; // Something's dragging so we must redraw
    }
    else if (myState.dragging){
      var mouse = myState.getMouse(e);
      // We don't want to drag the object by its top-left corner, we want to drag it
      // from where we clicked. Thats why we saved the offset and use it here
      myState.selection.x = mouse.x - myState.dragoffx;
      myState.selection.y = mouse.y - myState.dragoffy;
      myState.valid = false; // Something's dragging so we must redraw
    }
  }, true);
  frame.addEventListener('mouseup', function(e) {
    myState.dragging = false;
    myState.enlarging = false;
  }, true);
  // double click for making new shapes
  frame.addEventListener('dblclick', function(e) {
    var mouse = myState.getMouse(e);
    myState.addShape(new Shape(mouse.x - 10, mouse.y - 10, 20, 20, 'rgba(0,255,0,.6)'));
  }, true);

  // **** Options! ****
  myState.valid = false;
  this.selectionColor = '#CC0000';
  this.selectionWidth = 2;
  this.interval = 30;
  setInterval(function() { myState.draw(); }, myState.interval);
}

CanvasState.prototype.addShape = function(shape) {
  this.shapes.push(shape);
  this.valid = false;
}

CanvasState.prototype.clear = function() {
  this.ctx.clearRect(0, 0, this.width, this.height);
}

// While draw is called as often as the INTERVAL variable demands,
// It only ever does something if the frame gets invalidated by our code
CanvasState.prototype.draw = function() {
  // if our state is invalid, redraw and validate!
  if (!this.valid) {
    var ctx = this.ctx;
    var shapes = this.shapes;
    this.clear();

    // ** Add stuff you want drawn in the background all the time here **

    // draw all shapes
    var l = shapes.length;
    for (var i = 0; i < l; i++) {
      var shape = shapes[i];
      // We can skip the drawing of elements that have moved off the screen:
      if (shape.x > this.width || shape.y > this.height ||
          shape.x + shape.w < 0 || shape.y + shape.h < 0) continue;
      shapes[i].draw(ctx);
    }

    // draw selection
    // right now this is just a stroke along the edge of the selected Shape
    if (this.selection != null) {
      ctx.strokeStyle = this.selectionColor;
      ctx.lineWidth = this.selectionWidth;
      var mySel = this.selection;
      ctx.strokeRect(mySel.x,mySel.y,mySel.w,mySel.h);

      /* Handles corners. */
      ctx.fillStyle="#000000";
      ctx.fillRect(mySel.x - 2, mySel.y - 2, 5, 5);
      ctx.fillRect(mySel.x - 3 + mySel.w, mySel.y - 2, 5, 5);
      ctx.fillRect(mySel.x - 2, mySel.y - 2 + mySel.h, 5, 5);
      ctx.fillRect(mySel.x - 3 + mySel.w, mySel.y - 2 + mySel.h, 5, 5);
    }

    // ** Add stuff you want drawn on top all the time here **

    this.valid = true;
  }
}

// Creates an object with x and y defined, set to the mouse position relative to the state's frame
// If you wanna be super-correct this can be tricky, we have to worry about padding and borders
CanvasState.prototype.getMouse = function(e) {
  var element = this.frame, offsetX = 0, offsetY = 0, mx, my;

  // Compute the total offset
  if (element.offsetParent !== undefined) {
    do {
      offsetX += element.offsetLeft;
      offsetY += element.offsetTop;
    } while ((element = element.offsetParent));
  }

  // Add padding and border style widths to offset
  // Also add the <html> offsets in case there's a position:fixed bar
  offsetX += this.stylePaddingLeft + this.styleBorderLeft + this.htmlLeft;
  offsetY += this.stylePaddingTop + this.styleBorderTop + this.htmlTop;

  mx = e.pageX - offsetX;
  my = e.pageY - offsetY;

  // We return a simple javascript object (a hash) with x and y defined
  return {x: mx, y: my};
}

document.addEventListener("DOMContentLoaded", function(event) {
  var s = new CanvasState(document.getElementById('frame'));
});

<commit_msg>Added scaling right<commit_after>// Credits to http://simonsarris.com/blog/510-making-html5-canvas-useful
function Shape(x, y, w, h, fill) {
  this.x = x || 0;
  this.y = y || 0;
  this.w = w || 1;
  this.h = h || 1;
  this.fill = fill || '#AAAAAA';
}

Shape.prototype.draw = function(ctx) {
  ctx.fillStyle = this.fill;
  ctx.fillRect(this.x, this.y, this.w, this.h);
}

Shape.prototype.contains = function(mx, my) {
  return  (this.x <= mx) && (this.x + this.w >= mx) &&
          (this.y <= my) && (this.y + this.h >= my);
}

Shape.prototype.border = function (mx, my) {
  //Checks if within border
  if ((this.y + 2 >= my) && (this.y - 4 <= my)) {
    console.log("Top");
    return Shape.prototype.borderenum.TOP;
  } else if ((this.x + 2 >= mx) && (this.x - 4 <= mx)) {
    console.log("Left");
    return Shape.prototype.borderenum.LEFT;
  } else if ((this.x + this.w + 2 >= mx) && (this.x + this.w - 4 <= mx)) {
    console.log("Right");
    return Shape.prototype.borderenum.RIGHT;
  } else if ((this.y + this.h + 2 >= my) && (this.y + this.h - 4 <= my)) {
    console.log("Bottom");
    return Shape.prototype.borderenum.BOTTOM;
  } else {
    return false;
  }
}

Shape.prototype.borderenum = {
  TOP : 0,
  LEFT : 1,
  RIGHT : 2,
  BOTTOM : 3

}

function CanvasState(frame) {
  // **** First some setup! ****

  this.frame = frame;
  this.width = frame.width;
  this.height = frame.height;
  this.ctx = frame.getContext('2d');
  // This complicates things a little but but fixes mouse co-ordinate problems
  // when there's a border or padding. See getMouse for more detail
  var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
  if (document.defaultView && document.defaultView.getComputedStyle) {
    this.stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(frame, null)['paddingLeft'], 10)      || 0;
    this.stylePaddingTop  = parseInt(document.defaultView.getComputedStyle(frame, null)['paddingTop'], 10)       || 0;
    this.styleBorderLeft  = parseInt(document.defaultView.getComputedStyle(frame, null)['borderLeftWidth'], 10)  || 0;
    this.styleBorderTop   = parseInt(document.defaultView.getComputedStyle(frame, null)['borderTopWidth'], 10)   || 0;
  }
  // Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
  // They will mess up mouse coordinates and this fixes that
  var html = document.body.parentNode;
  this.htmlTop = html.offsetTop;
  this.htmlLeft = html.offsetLeft;

  // **** Keep track of state! ****

  this.valid = false; // when set to false, the frame will redraw everything
  this.shapes = [];  // the collection of things to be drawn
  this.dragging = false; // Keep track of when we are dragging
  this.enlarging = false;
  // the current selected object. In the future we could turn this into an array for multiple selection
  this.selection = null;
  this.dragoffx = 0; // See mousedown and mousemove events for explanation
  this.dragoffy = 0;

  // **** Then events! ****

  // This is an example of a closure!
  // Right here "this" means the CanvasState. But we are making events on the Canvas itself,
  // and when the events are fired on the frame the variable "this" is going to mean the frame!
  // Since we still want to use this particular CanvasState in the events we have to save a reference to it.
  // This is our reference!
  var myState = this;

  //fixes a problem where double clicking causes text to get selected on the frame
  frame.addEventListener('selectstart', function(e) { e.preventDefault(); return false; }, false);
  // Up, down, and move are for dragging
  frame.addEventListener('mousedown', function(e) {
    var mouse = myState.getMouse(e);
    var mx = mouse.x;
    var my = mouse.y;
    var shapes = myState.shapes;
    var l = shapes.length;
    for (var i = l-1; i >= 0; i--) {
      var border = shapes[i].border(mx, my);
      if (shapes[i].contains(mx, my) || border) {
        var mySel = shapes[i];
        // Keep track of where in the object we clicked
        // so we can move it smoothly (see mousemove)
        myState.dragoffx = mx - mySel.x;
        myState.dragoffy = my - mySel.y;
        myState.dragging = true;
        myState.selection = mySel; /* Sets which border to enlarge. */
        if (border) {
          myState.enlarging = border;
        }
        myState.valid = false;
        return;
      }
    }
    // havent returned means we have failed to select anything.
    // If there was an object selected, we deselect it
    if (myState.selection) {
      myState.selection = null;
      myState.valid = false; // Need to clear the old selection border
    }

  }, true);
  frame.addEventListener('mousemove', function(e) {
    if (myState.enlarging == Shape.prototype.borderenum.RIGHT) {
      console.log("Test");
      var mouse = myState.getMouse(e);
      myState.selection.w = mouse.x - myState.selection.x;
      myState.valid = false; // Something's dragging so we must redraw
    }
    else if (myState.dragging){
      var mouse = myState.getMouse(e);
      // We don't want to drag the object by its top-left corner, we want to drag it
      // from where we clicked. Thats why we saved the offset and use it here
      myState.selection.x = mouse.x - myState.dragoffx;
      myState.selection.y = mouse.y - myState.dragoffy;
      myState.valid = false; // Something's dragging so we must redraw
    }
  }, true);
  frame.addEventListener('mouseup', function(e) {
    myState.dragging = false;
    myState.enlarging = false;
  }, true);
  // double click for making new shapes
  frame.addEventListener('dblclick', function(e) {
    var mouse = myState.getMouse(e);
    myState.addShape(new Shape(mouse.x - 10, mouse.y - 10, 20, 20, 'rgba(0,255,0,.6)'));
  }, true);

  // **** Options! ****
  myState.valid = false;
  this.selectionColor = '#CC0000';
  this.selectionWidth = 2;
  this.interval = 30;
  setInterval(function() { myState.draw(); }, myState.interval);
}

CanvasState.prototype.addShape = function(shape) {
  this.shapes.push(shape);
  this.valid = false;
}

CanvasState.prototype.clear = function() {
  this.ctx.clearRect(0, 0, this.width, this.height);
}

// While draw is called as often as the INTERVAL variable demands,
// It only ever does something if the frame gets invalidated by our code
CanvasState.prototype.draw = function() {
  // if our state is invalid, redraw and validate!
  if (!this.valid) {
    var ctx = this.ctx;
    var shapes = this.shapes;
    this.clear();

    // ** Add stuff you want drawn in the background all the time here **

    // draw all shapes
    var l = shapes.length;
    for (var i = 0; i < l; i++) {
      var shape = shapes[i];
      // We can skip the drawing of elements that have moved off the screen:
      if (shape.x > this.width || shape.y > this.height ||
          shape.x + shape.w < 0 || shape.y + shape.h < 0) continue;
      shapes[i].draw(ctx);
    }

    // draw selection
    // right now this is just a stroke along the edge of the selected Shape
    if (this.selection != null) {
      ctx.strokeStyle = this.selectionColor;
      ctx.lineWidth = this.selectionWidth;
      var mySel = this.selection;
      ctx.strokeRect(mySel.x,mySel.y,mySel.w,mySel.h);

      /* Handles corners. */
      ctx.fillStyle="#000000";
      ctx.fillRect(mySel.x - 2, mySel.y - 2, 5, 5);
      ctx.fillRect(mySel.x - 3 + mySel.w, mySel.y - 2, 5, 5);
      ctx.fillRect(mySel.x - 2, mySel.y - 2 + mySel.h, 5, 5);
      ctx.fillRect(mySel.x - 3 + mySel.w, mySel.y - 2 + mySel.h, 5, 5);
    }

    // ** Add stuff you want drawn on top all the time here **

    this.valid = true;
  }
}

// Creates an object with x and y defined, set to the mouse position relative to the state's frame
// If you wanna be super-correct this can be tricky, we have to worry about padding and borders
CanvasState.prototype.getMouse = function(e) {
  var element = this.frame, offsetX = 0, offsetY = 0, mx, my;

  // Compute the total offset
  if (element.offsetParent !== undefined) {
    do {
      offsetX += element.offsetLeft;
      offsetY += element.offsetTop;
    } while ((element = element.offsetParent));
  }

  // Add padding and border style widths to offset
  // Also add the <html> offsets in case there's a position:fixed bar
  offsetX += this.stylePaddingLeft + this.styleBorderLeft + this.htmlLeft;
  offsetY += this.stylePaddingTop + this.styleBorderTop + this.htmlTop;

  mx = e.pageX - offsetX;
  my = e.pageY - offsetY;

  // We return a simple javascript object (a hash) with x and y defined
  return {x: mx, y: my};
}

document.addEventListener("DOMContentLoaded", function(event) {
  var s = new CanvasState(document.getElementById('frame'));
});

<|endoftext|>


<commit_before>var h = 360,
		s = 0,
		b = 100,
		a = 100;

var h2 = 12,
		s2 = 40,
		b2 = 23,
		a2 = 100;

var h3 = 0,
		s3 = 0,
		b3 = 15,
		a3 = 100,
		a3Wipe = 40;

// vars for line
var eX, eY, // position
		eX2, eY2,
		eW = 2; // width

// for bounces on wall
var bounces = 0,
		bouncesMax,
		bouncesTotal = 0; // current total amount of bounces

// for conversion from polar to cartesian coordinates.
// basically getting x and y from an angle and a radius.
// angle: 0 to 360 ... duh
var angle,
		radius ; // sets the speed

var quadrant;

var wall;	// which wall? t,r,b,l?

// for Dot
var dot = [];

// for saving position of corner of triangle
var tWallPosX = [],
		tWallPosY = [],
		triangle = [];

// for filling whole document
var w = window,
		wX = w.innerWidth,
		wY = w.innerHeight;

/*
* only executed once
*/
function setup(){
	createCanvas(wX, wY);
	// createCanvas(1600/2, 900/2);

	// change color mode to hsl
	colorMode(HSB, 360, 100, 100, 100);

	// start line at...
	eX = random(0,width);
	eY = 0;
	angle = radians(random(1,179));
	radius = 20; //speed of line drawing
	bouncesMax = 4;

	// rectangle/background
	background(h3, s3, b3);
}

/*
* this will be executed all the time
*/
function draw(){
	// translate from angle: polar to cartesian coordianates
	eX += cartesianX(radius,angle);
	eY += cartesianY(radius,angle);

	// DRAW LINE
	stroke(h,s,b,a);
	strokeWeight(eW);
	line(eX,eY, eX2,eY2);

	// quadrants:
	// 1: 0° - 90°
	// 2: 90° - 180°
	// 3: 180° - 270°
	// 4: 270° - 360°
	if (angle >= radians(0) && angle < radians(90)) {
		quadrant = 1;
	}
	else if (angle >= radians(90) && angle < radians(180)) {
		quadrant = 2;
	}
	else if (angle >= radians(180) && angle < radians(270)) {
		quadrant = 3;
	}
	else if (angle >= radians(270) && angle < radians(360)) {
		quadrant = 4;
	}

	// wall sides
	if (eY < 0) {
		wall = 1;
	}
	else if (eX > width) {
		wall = 2;
	}
	else if (eY > height) {
		wall = 3;
	}
	else if (eX < 0) {
		wall = 4;
	}

	// if bounce from specific wall from specific angle
	// 0° - 90°
	if (quadrant === 1 && wall === 2) { // right
		angle += radians(90);
		bounces++;
		eX = width;
	}
	else if (quadrant === 1 && wall === 3) { // bottom
		angle -= radians(90);
		bounces++;
		eY = height;
	}
	// 90° - 180°
	else if (quadrant === 2 && wall === 3) { // bottom
		angle += radians(90);
		bounces++;
		eY = height;
	}
	else if (quadrant === 2 && wall === 4) { // left
		angle -= radians(90);
		bounces++;
		eX = 0;
	}
	// 180° - 270°
	else if (quadrant === 3 && wall === 4) { // left
		angle += radians(90);
		bounces++;
		eX = 0;
	}
	else if (quadrant === 3 && wall === 1) { // top
		angle -= radians(90);
		bounces++;
		eY = 0;
	}
	// 270° - 360°
	else if (quadrant === 4 && wall === 1) { // top
		angle += radians(90);
		bounces++;
		eY = 0;
	}
	else if (quadrant === 4 && wall === 2) { // right
		angle -= radians(90);
		bounces++;
		eX = width;
	}

	// stay in 360°
	if (angle >= radians(360)) {
		angle -= radians(360);
	}
	else if (angle < radians(0)) {
		angle += radians(360);
	}

	if (frameCount === 1) {
		dot[bouncesTotal] = new Dot();
		dot[bouncesTotal].show();
	}
	// if specific amount of bouncing, reset position
	if (bounces > bouncesMax) {
		noStroke();
		// eX = random(0,width);
		// eY = 0;
		angle = radians(random(0,180));
		bounces = 0; // reset bounces counter
		frameCount = 1;
	}

	// if at wall-bounce, add thing
	if (eX === width || eY === height || eX === 0 || eY === 0) {

		// save position at wall
		tWallPosX[bouncesTotal] = eX;
		tWallPosY[bouncesTotal] = eY;

		// create new Dot at wall
		dot[bouncesTotal] = new Dot();
		dot[bouncesTotal].show();
		triangle[bouncesTotal] = new Triangle();

		// draw triangle, start at third bounce
		if (bouncesTotal >= 2) {
			triangle[bouncesTotal].show();
		}

		// add count
		bouncesTotal++;
	}

	// fadeout effect
	background(h3, s3, b3, 1);

	// get last coordinate for drawing a line
	eX2 = eX;
	eY2 = eY;

	console.log(bouncesTotal);
}

/*
* custom functions
*/
// create cartesian coordinates
function cartesianX(radius,angle) {
	var x = radius*cos(angle);

	return x;
}

function cartesianY(radius,angle) {
	var y = radius*sin(angle);

	return y;
}

/*
* Classes
*/
// Dot constructor
var Dot = function() {
	this.x = eX;
	this.y = eY;
	// this.width = eW;
	// this.color = color(h,s,b,a);
};

// show method
Dot.prototype.show = function() {
	noStroke();
	// fill(this.color);
	// ellipse(this.x,this.y, this.width*5,this.width*5);
};

// Triangle constructor
var Triangle = function() {
	this.x1 = tWallPosX[bouncesTotal];
	this.y1 = tWallPosY[bouncesTotal];
	this.x2 = tWallPosX[bouncesTotal-2];
	this.y2 = tWallPosY[bouncesTotal-2];

	// this.colorFill = color(h2,s2,b2,10);
	this.colorStroke = color(h,s,b,a);
};

Triangle.prototype.show = function() {
	stroke(this.colorStroke);
	// noFill();
	// noStroke();
	// fill(this.colorFill);

	// triangle(
	// 	this.x1,this.y1,
	// 	this.x2,this.y2,
	// 	this.x3,this.y3
	// );
line(
		this.x1,this.y1,
		this.x2,this.y2
	);
};<commit_msg>add jitter effect for angle and strokeWidth<commit_after>var h = 360,
		s = 0,
		b = 100,
		a = 100;

var h2 = 12,
		s2 = 40,
		b2 = 23,
		a2 = 100;

var h3 = 0,
		s3 = 0,
		b3 = 15,
		a3 = 100,
		a3Wipe = 40;

// vars for line
var eX, eY, // position
		eX2, eY2,
		eW = 1; // width

// for bounces on wall
var bounces = 0,
		bouncesMax,
		bouncesTotal = 0; // current total amount of bounces

// for conversion from polar to cartesian coordinates.
// basically getting x and y from an angle and a radius.
// angle: 0 to 360 ... duh
var angle,
		radius ; // sets the speed

var angleOff = 0.0;

var quadrant;

var wall;	// which wall? t,r,b,l?

// for Dot
var dot = [];

// for saving position of corner of triangle
var tWallPosX = [],
		tWallPosY = [],
		triangle = [];

// for filling whole document
var w = window,
		wX = w.innerWidth,
		wY = w.innerHeight;

/*
* only executed once
*/
function setup(){
	createCanvas(wX, wY);
	// createCanvas(1600/2, 900/2);

	// change color mode to hsl
	colorMode(HSB, 360, 100, 100, 100);

	// start line at...
	eX = random(0,width);
	eY = 0;
	angle = radians(random(1,179));
	radius = 20; //speed of line drawing
	bouncesMax = 4;

	// rectangle/background
	background(h3, s3, b3);
}

/*
* this will be executed all the time
*/
function draw(){
	// angleOff += 0.01;
	// var nOff = noise(angleOff)*10;

	eW = random(0,1);
	angle += radians(random(-1,1));

	// translate from angle: polar to cartesian coordianates
	eX += cartesianX(radius,angle);
	eY += cartesianY(radius,angle);

	// DRAW LINE
	stroke(h,s,b,a);
	strokeWeight(eW);
	line(eX,eY, eX2,eY2);

	// quadrants:
	// 1: 0° - 90°
	// 2: 90° - 180°
	// 3: 180° - 270°
	// 4: 270° - 360°
	if (angle >= radians(0) && angle < radians(90)) {
		quadrant = 1;
	}
	else if (angle >= radians(90) && angle < radians(180)) {
		quadrant = 2;
	}
	else if (angle >= radians(180) && angle < radians(270)) {
		quadrant = 3;
	}
	else if (angle >= radians(270) && angle < radians(360)) {
		quadrant = 4;
	}

	// wall sides
	if (eY < 0) {
		wall = 1;
	}
	else if (eX > width) {
		wall = 2;
	}
	else if (eY > height) {
		wall = 3;
	}
	else if (eX < 0) {
		wall = 4;
	}

	// if bounce from specific wall from specific angle
	// 0° - 90°
	if (quadrant === 1 && wall === 2) { // right
		angle += radians(90);
		bounces++;
		eX = width;
	}
	else if (quadrant === 1 && wall === 3) { // bottom
		angle -= radians(90);
		bounces++;
		eY = height;
	}
	// 90° - 180°
	else if (quadrant === 2 && wall === 3) { // bottom
		angle += radians(90);
		bounces++;
		eY = height;
	}
	else if (quadrant === 2 && wall === 4) { // left
		angle -= radians(90);
		bounces++;
		eX = 0;
	}
	// 180° - 270°
	else if (quadrant === 3 && wall === 4) { // left
		angle += radians(90);
		bounces++;
		eX = 0;
	}
	else if (quadrant === 3 && wall === 1) { // top
		angle -= radians(90);
		bounces++;
		eY = 0;
	}
	// 270° - 360°
	else if (quadrant === 4 && wall === 1) { // top
		angle += radians(90);
		bounces++;
		eY = 0;
	}
	else if (quadrant === 4 && wall === 2) { // right
		angle -= radians(90);
		bounces++;
		eX = width;
	}

	// stay in 360°
	if (angle >= radians(360)) {
		angle -= radians(360);
	}
	else if (angle < radians(0)) {
		angle += radians(360);
	}

	if (frameCount === 1) {
		dot[bouncesTotal] = new Dot();
		dot[bouncesTotal].show();
	}
	// if specific amount of bouncing, reset position
	if (bounces > bouncesMax) {
		noStroke();
		// eX = random(0,width);
		// eY = 0;
		angle = radians(random(0,180));
		bounces = 0; // reset bounces counter
		frameCount = 1;
	}

	// if at wall-bounce, add thing
	if (eX === width || eY === height || eX === 0 || eY === 0) {

		// save position at wall
		tWallPosX[bouncesTotal] = eX;
		tWallPosY[bouncesTotal] = eY;

		// create new Dot at wall
		dot[bouncesTotal] = new Dot();
		dot[bouncesTotal].show();
		triangle[bouncesTotal] = new Triangle();

		// draw triangle, start at third bounce
		if (bouncesTotal >= 2) {
			triangle[bouncesTotal].show();
		}

		// add count
		bouncesTotal++;
	}

	// fadeout effect
	background(h3, s3, b3, 1);

	// get last coordinate for drawing a line
	eX2 = eX;
	eY2 = eY;

	console.log(angle);
}

/*
* custom functions
*/
// create cartesian coordinates
function cartesianX(radius,angle) {
	var x = radius*cos(angle);

	return x;
}

function cartesianY(radius,angle) {
	var y = radius*sin(angle);

	return y;
}

/*
* Classes
*/
// Dot constructor
var Dot = function() {
	this.x = eX;
	this.y = eY;
	// this.width = eW;
	// this.color = color(h,s,b,a);
};

// show method
Dot.prototype.show = function() {
	noStroke();
	// fill(this.color);
	// ellipse(this.x,this.y, this.width*5,this.width*5);
};

// Triangle constructor
var Triangle = function() {
	this.x1 = tWallPosX[bouncesTotal];
	this.y1 = tWallPosY[bouncesTotal];
	this.x2 = tWallPosX[bouncesTotal-2];
	this.y2 = tWallPosY[bouncesTotal-2];

	// this.colorFill = color(h2,s2,b2,10);
	this.colorStroke = color(h,s,b,a);
};

Triangle.prototype.show = function() {
	stroke(this.colorStroke);
	// noFill();
	// noStroke();
	// fill(this.colorFill);

	// triangle(
	// 	this.x1,this.y1,
	// 	this.x2,this.y2,
	// 	this.x3,this.y3
	// );
line(
		this.x1,this.y1,
		this.x2,this.y2
	);
};<|endoftext|>


<commit_before>angular.module('ui.bootstrap-slider', [])
    .directive('slider', ['$parse', '$timeout', '$rootScope', function ($parse, $timeout, $rootScope) {
        return {
            restrict: 'AE',
            replace: true,
            template: '
<input class="slider-input" type="text" style="width:100%" />
',
            require: 'ngModel',
            scope: {
                max: "=",
                min: "=",
                step: "=",
                value: "=",
                ngModel: '=',
                ngDisabled: '=',
                range: '=',
                sliderid: '=',
                ticks: '=',
                ticksLabels: '=',
                ticksSnapBounds: '=',
                ticksPositions: '=',
                scale: '=',
                formatter: '&',
                onStartSlide: '&',
                onStopSlide: '&',
                onSlide: '&'
            },
            link: function ($scope, element, attrs, ngModelCtrl, $compile) {
                var ngModelDeregisterFn, ngDisabledDeregisterFn;

                initSlider();

                function initSlider() {
                    var options = {};

                    function setOption(key, value, defaultValue) {
                        options[key] = value || defaultValue;
                    }

                    function setFloatOption(key, value, defaultValue) {
                        options[key] = value || value === 0 ? parseFloat(value) : defaultValue;
                    }

                    function setBooleanOption(key, value, defaultValue) {
                        options[key] = value ? value + '' === 'true' : defaultValue;
                    }

                    function getArrayOrValue(value) {
                        return (angular.isString(value) && value.indexOf("[") === 0) ? angular.fromJson(value) : value;
                    }

                    setOption('id', $scope.sliderid);
                    setOption('orientation', attrs.orientation, 'horizontal');
                    setOption('selection', attrs.selection, 'before');
                    setOption('handle', attrs.handle, 'round');
                    setOption('tooltip', attrs.sliderTooltip || attrs.tooltip, 'show');
                    setOption('tooltip_position', attrs.sliderTooltipPosition, 'top');
                    setOption('tooltipseparator', attrs.tooltipseparator, ':');
                    setOption('ticks', $scope.ticks);
                    setOption('ticks_labels', $scope.ticksLabels);
                    setOption('ticks_snap_bounds', $scope.ticksSnapBounds);
                    setOption('ticks_positions', $scope.ticksPositions);
                    setOption('scale', $scope.scale, 'linear');

                    setFloatOption('min', $scope.min, 0);
                    setFloatOption('max', $scope.max, 10);
                    setFloatOption('step', $scope.step, 1);
                    var strNbr = options.step + '';
                    var decimals = strNbr.substring(strNbr.lastIndexOf('.') + 1);
                    setFloatOption('precision', attrs.precision, decimals);

                    setBooleanOption('tooltip_split', attrs.tooltipsplit, false);
                    setBooleanOption('enabled', attrs.enabled, true);
                    setBooleanOption('naturalarrowkeys', attrs.naturalarrowkeys, false);
                    setBooleanOption('reversed', attrs.reversed, false);

                    setBooleanOption('range', $scope.range, false);
                    if (options.range) {
                        if (angular.isArray($scope.value)) {
                            options.value = $scope.value;
                        }
                        else if (angular.isString($scope.value)) {
                            options.value = getArrayOrValue($scope.value);
                            if (!angular.isArray(options.value)) {
                                var value = parseFloat($scope.value);
                                if (isNaN(value)) value = 5;

                                if (value < $scope.min) {
                                    value = $scope.min;
                                    options.value = [value, options.max];
                                }
                                else if (value > $scope.max) {
                                    value = $scope.max;
                                    options.value = [options.min, value];
                                }
                                else {
                                    options.value = [options.min, options.max];
                                }
                            }
                        }
                        else {
                            options.value = [options.min, options.max]; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
                        }
                        $scope.ngModel = options.value; // needed, otherwise turns value into [null, ##]
                    }
                    else {
                        setFloatOption('value', $scope.value, 5);
                    }

                    if ($scope.formatter) options.formatter = $scope.$eval($scope.formatter);

                    // check if slider jQuery plugin exists
                    if ('$' in window && $.fn.slider) {
                        // adding methods to jQuery slider plugin prototype
                        $.fn.slider.constructor.prototype.disable = function () {
                            this.picker.off();
                        };
                        $.fn.slider.constructor.prototype.enable = function () {
                            this.picker.on();
                        };
                    }

                    // destroy previous slider to reset all options
                    if (element[0].__slider)
                        element[0].__slider.destroy();

                    var slider = new Slider(element[0].getElementsByClassName('slider-input')[0], options);
                    element[0].__slider = slider;

                    // everything that needs slider element
                    var updateEvent = getArrayOrValue(attrs.updateevent);
                    if (angular.isString(updateEvent)) {
                        // if only single event name in string
                        updateEvent = [updateEvent];
                    }
                    else {
                        // default to slide event
                        updateEvent = ['slide'];
                    }
                    angular.forEach(updateEvent, function (sliderEvent) {
                        slider.on(sliderEvent, function (ev) {
                            ngModelCtrl.$setViewValue(ev);
                            $timeout(function () {
                                $scope.$apply();
                            });
                        });
                    });
                    slider.on('change', function (ev) {
                        ngModelCtrl.$setViewValue(ev.newValue);
                        $timeout(function () {
                            $scope.$apply();
                        });
                    });

                    // Event listeners
                    var sliderEvents = {
                        slideStart: 'onStartSlide',
                        slide: 'onSlide',
                        slideStop: 'onStopSlide'
                    };
                    angular.forEach(sliderEvents, function (sliderEventAttr, sliderEvent) {
                        var fn = $parse(attrs[sliderEventAttr]);
                        slider.on(sliderEvent, function (ev) {
                            if ($scope[sliderEventAttr]) {

                                var callback = function () {
                                    fn($scope.$parent, { $event: ev, value: ev });
                                }

                                if ($rootScope.$$phase) {
                                    $scope.$evalAsync(callback);
                                } else {
                                    $scope.$apply(callback);
                                }
                            }
                        });
                    });

                    // deregister ngDisabled watcher to prevent memory leaks
                    if (angular.isFunction(ngDisabledDeregisterFn)) {
                        ngDisabledDeregisterFn();
                        ngDisabledDeregisterFn = null;
                    }

                    ngDisabledDeregisterFn = $scope.$watch('ngDisabled', function (value) {
                        if (value) {
                            slider.disable();
                        }
                        else {
                            slider.enable();
                        }
                    });

                    // deregister ngModel watcher to prevent memory leaks
                    if (angular.isFunction(ngModelDeregisterFn)) ngModelDeregisterFn();
                    ngModelDeregisterFn = $scope.$watch('ngModel', function (value) {
                        if($scope.range){
                            slider.setValue(value);
                        }else{
                            slider.setValue(parseFloat(value));
                        }
                    }, true);
                }

                var watchers = ['min', 'max', 'step', 'range', 'scale'];
                angular.forEach(watchers, function (prop) {
                    $scope.$watch(prop, function () {
                        initSlider();
                    });
                });
            }
        };
    }])
;
<commit_msg>fix for #92<commit_after>angular.module('ui.bootstrap-slider', [])
    .directive('slider', ['$parse', '$timeout', '$rootScope', function ($parse, $timeout, $rootScope) {
        return {
            restrict: 'AE',
            replace: true,
            template: '
<input class="slider-input" type="text" style="width:100%" />
',
            require: 'ngModel',
            scope: {
                max: "=",
                min: "=",
                step: "=",
                value: "=",
                ngModel: '=',
                ngDisabled: '=',
                range: '=',
                sliderid: '=',
                ticks: '=',
                ticksLabels: '=',
                ticksSnapBounds: '=',
                ticksPositions: '=',
                scale: '=',
                formatter: '&',
                onStartSlide: '&',
                onStopSlide: '&',
                onSlide: '&'
            },
            link: function ($scope, element, attrs, ngModelCtrl, $compile) {
                var ngModelDeregisterFn, ngDisabledDeregisterFn;

                initSlider();

                function initSlider() {
                    var options = {};

                    function setOption(key, value, defaultValue) {
                        options[key] = value || defaultValue;
                    }

                    function setFloatOption(key, value, defaultValue) {
                        options[key] = value || value === 0 ? parseFloat(value) : defaultValue;
                    }

                    function setBooleanOption(key, value, defaultValue) {
                        options[key] = value ? value + '' === 'true' : defaultValue;
                    }

                    function getArrayOrValue(value) {
                        return (angular.isString(value) && value.indexOf("[") === 0) ? angular.fromJson(value) : value;
                    }

                    setOption('id', $scope.sliderid);
                    setOption('orientation', attrs.orientation, 'horizontal');
                    setOption('selection', attrs.selection, 'before');
                    setOption('handle', attrs.handle, 'round');
                    setOption('tooltip', attrs.sliderTooltip || attrs.tooltip, 'show');
                    setOption('tooltip_position', attrs.sliderTooltipPosition, 'top');
                    setOption('tooltipseparator', attrs.tooltipseparator, ':');
                    setOption('ticks', $scope.ticks);
                    setOption('ticks_labels', $scope.ticksLabels);
                    setOption('ticks_snap_bounds', $scope.ticksSnapBounds);
                    setOption('ticks_positions', $scope.ticksPositions);
                    setOption('scale', $scope.scale, 'linear');

                    setFloatOption('min', $scope.min, 0);
                    setFloatOption('max', $scope.max, 10);
                    setFloatOption('step', $scope.step, 1);
                    var strNbr = options.step + '';
                    var decimals = strNbr.substring(strNbr.lastIndexOf('.') + 1 || strNbr.length);
                    setFloatOption('precision', attrs.precision, decimals);

                    setBooleanOption('tooltip_split', attrs.tooltipsplit, false);
                    setBooleanOption('enabled', attrs.enabled, true);
                    setBooleanOption('naturalarrowkeys', attrs.naturalarrowkeys, false);
                    setBooleanOption('reversed', attrs.reversed, false);

                    setBooleanOption('range', $scope.range, false);
                    if (options.range) {
                        if (angular.isArray($scope.value)) {
                            options.value = $scope.value;
                        }
                        else if (angular.isString($scope.value)) {
                            options.value = getArrayOrValue($scope.value);
                            if (!angular.isArray(options.value)) {
                                var value = parseFloat($scope.value);
                                if (isNaN(value)) value = 5;

                                if (value < $scope.min) {
                                    value = $scope.min;
                                    options.value = [value, options.max];
                                }
                                else if (value > $scope.max) {
                                    value = $scope.max;
                                    options.value = [options.min, value];
                                }
                                else {
                                    options.value = [options.min, options.max];
                                }
                            }
                        }
                        else {
                            options.value = [options.min, options.max]; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
                        }
                        $scope.ngModel = options.value; // needed, otherwise turns value into [null, ##]
                    }
                    else {
                        setFloatOption('value', $scope.value, 5);
                    }

                    if ($scope.formatter) options.formatter = $scope.$eval($scope.formatter);

                    // check if slider jQuery plugin exists
                    if ('$' in window && $.fn.slider) {
                        // adding methods to jQuery slider plugin prototype
                        $.fn.slider.constructor.prototype.disable = function () {
                            this.picker.off();
                        };
                        $.fn.slider.constructor.prototype.enable = function () {
                            this.picker.on();
                        };
                    }

                    // destroy previous slider to reset all options
                    if (element[0].__slider)
                        element[0].__slider.destroy();

                    var slider = new Slider(element[0].getElementsByClassName('slider-input')[0], options);
                    element[0].__slider = slider;

                    // everything that needs slider element
                    var updateEvent = getArrayOrValue(attrs.updateevent);
                    if (angular.isString(updateEvent)) {
                        // if only single event name in string
                        updateEvent = [updateEvent];
                    }
                    else {
                        // default to slide event
                        updateEvent = ['slide'];
                    }
                    angular.forEach(updateEvent, function (sliderEvent) {
                        slider.on(sliderEvent, function (ev) {
                            ngModelCtrl.$setViewValue(ev);
                            $timeout(function () {
                                $scope.$apply();
                            });
                        });
                    });
                    slider.on('change', function (ev) {
                        ngModelCtrl.$setViewValue(ev.newValue);
                        $timeout(function () {
                            $scope.$apply();
                        });
                    });

                    // Event listeners
                    var sliderEvents = {
                        slideStart: 'onStartSlide',
                        slide: 'onSlide',
                        slideStop: 'onStopSlide'
                    };
                    angular.forEach(sliderEvents, function (sliderEventAttr, sliderEvent) {
                        var fn = $parse(attrs[sliderEventAttr]);
                        slider.on(sliderEvent, function (ev) {
                            if ($scope[sliderEventAttr]) {

                                var callback = function () {
                                    fn($scope.$parent, { $event: ev, value: ev });
                                }

                                if ($rootScope.$$phase) {
                                    $scope.$evalAsync(callback);
                                } else {
                                    $scope.$apply(callback);
                                }
                            }
                        });
                    });

                    // deregister ngDisabled watcher to prevent memory leaks
                    if (angular.isFunction(ngDisabledDeregisterFn)) {
                        ngDisabledDeregisterFn();
                        ngDisabledDeregisterFn = null;
                    }

                    ngDisabledDeregisterFn = $scope.$watch('ngDisabled', function (value) {
                        if (value) {
                            slider.disable();
                        }
                        else {
                            slider.enable();
                        }
                    });

                    // deregister ngModel watcher to prevent memory leaks
                    if (angular.isFunction(ngModelDeregisterFn)) ngModelDeregisterFn();
                    ngModelDeregisterFn = $scope.$watch('ngModel', function (value) {
                        if($scope.range){
                            slider.setValue(value);
                        }else{
                            slider.setValue(parseFloat(value));
                        }
                    }, true);
                }

                var watchers = ['min', 'max', 'step', 'range', 'scale'];
                angular.forEach(watchers, function (prop) {
                    $scope.$watch(prop, function () {
                        initSlider();
                    });
                });
            }
        };
    }])
;
<|endoftext|>


<commit_before>(function($){

	"use strict";

	$.fn.fullWidth = function(options) {

		var defaults = {
			maxHeight	:	450,
			minHeight	:	375,
			delay		:	5000,
			transition	:	1000,
			maxFont		:	36,
			minFont		:	20
		}, settings = $.extend(defaults, options);

		return this.each( function() {

			var full	=	$(this),
			inner		=	full.find('.inner'),
			slides		=	inner.find('.slide'),
			images		=	slides.find('img'),
			nav			=	full.find('.slide-nav'),
			controls	=	full.find('.controls a'),
			navCircles	=	'',
			smallest	=	9999,
			status		=	{current : 0, max : slides.length - 1},
			timers		=	{slides : '', resize : ''},
			move = function(direction, current){
				if(inner.is(':animated')) return;

				stop();

				if(direction === 'right'){
					status.current = status.current+1 > status.max ? 0 : status.current+1;
				}else if(direction === 'left'){
					status.current = status.current-1 < 0 ? status.max : status.current-1;
				}else{
					status.current = current || "0";
				}

				navCircles.removeClass('current').eq(status.current).addClass('current');
				inner.animate({'margin-left' : '-'+100*status.current+'%'}, settings.transition ,function(){ start(); });

			},
			start = function(){
				timers.slides = setTimeout(function(){ move('right'); }, settings.delay);
			},
			stop = function(){
				clearTimeout(timers.slides);
			},
			resize = function(){

				var wWidth	=	$(window).width(),
				newHeight	=	parseInt(wWidth/3, 10),
				imageCSS	=	wWidth <= smallest ? ['100%', 'auto', '9999'] : ['', '', ''],
				start		=	inner.height(),
				divCSS		=	wWidth <= 480 ? ['0', '100%', 'none'] : ['', '', ''],
				size		=	wWidth/41;
				/*
					size equals window width divided by 41 - 41 was chosen as it creates a nicely proportionate font size.
					However, you can experiment with this if you want a generally larger or smaller size to be set.
					For example: a width of 960px/41 = 23.4px, with 20 instead of 41 you'd get a font size of 48px.
					It really depends on what kind of content you're displaying and how much text you've got on each slide.
				*/

				size = size > settings.maxFont ? settings.maxFont :
							(size < settings.minFont ? settings.minFont : size);

				inner.css('height', function(){
					return newHeight > settings.maxHeight ? settings.maxHeight :
							(newHeight < settings.minHeight ? settings.minHeight : newHeight);
				});

				images.css({
					'margin-top' : function(){
						var curr = $(this).height();
						return '-'+(start > curr ? 0 : curr-start)/2+'px';
					},
					'height' : imageCSS[0], 'width' : imageCSS[1], 'maxWidth' : imageCSS[2]
				});

				slides.find('div').css({
					'font-size' : size,
					'top' : function(){
						var diff = start-$(this).height();
						return wWidth <= 480 ? diff : diff/2;
					},
					'padding' : divCSS[0], 'width' : divCSS[1]
				}).find('br').css('display', divCSS[2]);

			},
			attachEvents = function(){

				$(window).resize(function(){
					clearTimeout(timers.resize);
					timers.resize = setTimeout(function(){ resize(); }, 100);
				}).trigger('resize');

				controls.on('click', function(){
					move(this.className);
					return false;
				});

				full.on('mouseenter mouseleave', function(e){
					if(controls.is(':animated')) return;
					e.type === 'mouseenter' ? controls.fadeIn() : controls.fadeOut();
				});

				navCircles.on('click', function(){
					move('direct', $(this).index());
				});

				$(document).on('keydown', function(e){
					if(!(e.which === 37 || e.which === 39)) return;
					move(e.which === 37 ? 'left' : 'right');
				});

			};

			(function(){

				inner.css('height', settings.minHeight);

				images.each(function(){
					var w = $(this).attr('width');
					smallest = w < smallest ? w : smallest;
				});

				slides.each(function(i){
					$(this).addClass('slide-'+(i+1));
				});

				inner.css('width', (slides.length*100)+'%');

				slides.css('width',  parseFloat(100/slides.length, 10)+'%').each(function(){
					nav.append('•');
				});

				slides.find('div:first').wrapInner('
');
				// div:first just in case there's a div inside the caption div

				navCircles = nav.find('span');
				navCircles.first().addClass('current');
				nav.css('width', function(){
					return navCircles.length*26;
				});

				$(window).load(function() {
					attachEvents();
					inner.fadeTo(1000, 1, function(){
						start();
					});
				});
			}());

		});
	};

}(jQuery));
<commit_msg>no message<commit_after>(function($){

	"use strict";

	$.fn.fullWidth = function(options) {

		var defaults = {
			maxHeight	:	450,
			minHeight	:	375,
			delay		:	5000,
			transition	:	1000,
			maxFont		:	36,
			minFont		:	20
		}, settings = $.extend(defaults, options);

		return this.each( function() {

			var full	=	$(this),
			inner		=	full.find('.inner'),
			slides		=	inner.find('.slide'),
			images		=	slides.find('img'),
			nav		=	full.find('.slide-nav'),
			controls	=	full.find('.controls a'),
			navCircles	=	'',
			smallest	=	9999,
			status		=	{current : 0, max : slides.length - 1},
			timers		=	{slides : '', resize : ''},
			move = function(direction, current){
				if(inner.is(':animated')) return;

				stop();

				if(direction === 'right'){
					status.current = status.current+1 > status.max ? 0 : status.current+1;
				}else if(direction === 'left'){
					status.current = status.current-1 < 0 ? status.max : status.current-1;
				}else{
					status.current = current || "0";
				}

				navCircles.removeClass('current').eq(status.current).addClass('current');
				inner.animate({'margin-left' : '-'+100*status.current+'%'}, settings.transition ,function(){ start(); });

			},
			start = function(){
				timers.slides = setTimeout(function(){ move('right'); }, settings.delay);
			},
			stop = function(){
				clearTimeout(timers.slides);
			},
			resize = function(){

				var wWidth	=	$(window).width(),
				newHeight	=	parseInt(wWidth/3, 10),
				imageCSS	=	wWidth <= smallest ? ['100%', 'auto', '9999'] : ['', '', ''],
				start		=	inner.height(),
				divCSS		=	wWidth <= 480 ? ['0', '100%', 'none'] : ['', '', ''],
				size		=	wWidth/41;
				/*
					size equals window width divided by 41 - 41 was chosen as it creates a nicely proportionate font size.
					However, you can experiment with this if you want a generally larger or smaller size to be set.
					For example: a width of 960px/41 = 23.4px, with 20 instead of 41 you'd get a font size of 48px.
					It really depends on what kind of content you're displaying and how much text you've got on each slide.
				*/

				size = size > settings.maxFont ? settings.maxFont :
							(size < settings.minFont ? settings.minFont : size);

				inner.css('height', function(){
					return newHeight > settings.maxHeight ? settings.maxHeight :
							(newHeight < settings.minHeight ? settings.minHeight : newHeight);
				});

				images.css({
					'margin-top' : function(){
						var curr = $(this).height();
						return '-'+(start > curr ? 0 : curr-start)/2+'px';
					},
					'height' : imageCSS[0], 'width' : imageCSS[1], 'maxWidth' : imageCSS[2]
				});

				slides.find('div').css({
					'font-size' : size,
					'top' : function(){
						var diff = start-$(this).height();
						return wWidth <= 480 ? diff : diff/2;
					},
					'padding' : divCSS[0], 'width' : divCSS[1]
				}).find('br').css('display', divCSS[2]);

			},
			attachEvents = function(){

				$(window).resize(function(){
					clearTimeout(timers.resize);
					timers.resize = setTimeout(function(){ resize(); }, 100);
				}).trigger('resize');

				controls.on('click', function(){
					move(this.className);
					return false;
				});

				full.on('mouseenter mouseleave', function(e){
					if(controls.is(':animated')) return;
					e.type === 'mouseenter' ? controls.fadeIn() : controls.fadeOut();
				});

				navCircles.on('click', function(){
					move('direct', $(this).index());
				});

				$(document).on('keydown', function(e){
					if(!(e.which === 37 || e.which === 39)) return;
					move(e.which === 37 ? 'left' : 'right');
				});

			};

			(function(){

				inner.css('height', settings.minHeight);

				images.each(function(){
					var w = $(this).attr('width');
					smallest = w < smallest ? w : smallest;
				});

				slides.each(function(i){
					$(this).addClass('slide-'+(i+1));
				});

				inner.css('width', (slides.length*100)+'%');

				slides.css('width',  parseFloat(100/slides.length, 10)+'%').each(function(){
					nav.append('•');
				});

				slides.find('div:first').wrapInner('
');
				// div:first just in case there's a div inside the caption div

				navCircles = nav.find('span');
				navCircles.first().addClass('current');
				nav.css('width', function(){
					return navCircles.length*26;
				});

				$(window).load(function() {
					attachEvents();
					inner.fadeTo(1000, 1, function(){
						start();
					});
				});
			}());

		});
	};

}(jQuery));
<|endoftext|>